OpenVDB 10.0.1
Loading...
Searching...
No Matches
Tuple.h
Go to the documentation of this file.
1// Copyright Contributors to the OpenVDB Project
2// SPDX-License-Identifier: MPL-2.0
3//
4/// @file Tuple.h
5/// @author Ben Kwa
6
7#ifndef OPENVDB_MATH_TUPLE_HAS_BEEN_INCLUDED
8#define OPENVDB_MATH_TUPLE_HAS_BEEN_INCLUDED
9
10#include "Math.h"
11#include <cmath>
12#include <sstream>
13#include <string>
14#include <type_traits>
15
16
17namespace openvdb {
19namespace OPENVDB_VERSION_NAME {
20namespace math {
21
22/// @brief Dummy class for tag dispatch of conversion constructors
23struct Conversion {};
24
25
26/// @class Tuple "Tuple.h"
27/// A base class for homogenous tuple types
28template<int SIZE, typename T>
29class Tuple
30{
31public:
32 using value_type = T;
33 using ValueType = T;
34
35 static const int size = SIZE;
36
37 /// Trivial constructor, the Tuple is NOT initialized
38 /// @note destructor, copy constructor, assignment operator and
39 /// move constructor are left to be defined by the compiler (default)
40 Tuple() = default;
41
42 /// @brief Conversion constructor.
43 /// @details Tuples with different value types and different sizes can be
44 /// interconverted using this member. Converting from a larger tuple
45 /// results in truncation; converting from a smaller tuple results in
46 /// the extra data members being zeroed out. This function assumes that
47 /// the integer 0 is convertible to the tuple's value type.
48 template <int src_size, typename src_valtype>
49 explicit Tuple(Tuple<src_size, src_valtype> const &src) {
50 enum { COPY_END = (SIZE < src_size ? SIZE : src_size) };
51
52 for (int i = 0; i < COPY_END; ++i) {
53 mm[i] = src[i];
54 }
55 for (int i = COPY_END; i < SIZE; ++i) {
56 mm[i] = 0;
57 }
58 }
59
60 // @brief const access to an element in the tuple. The offset idx must be
61 // an integral type. A copy of the tuple data is returned.
62 template <typename IdxT,
63 typename std::enable_if<std::is_integral<IdxT>::value, bool>::type = true>
64 T operator[](IdxT i) const {
65 assert(i >= IdxT(0) && i < IdxT(SIZE));
66 return mm[i];
67 }
68
69 // @brief non-const access to an element in the tuple. The offset idx must be
70 // an integral type. A reference to the tuple data is returned.
71 template <typename IdxT,
72 typename std::enable_if<std::is_integral<IdxT>::value, bool>::type = true>
73 T& operator[](IdxT i) {
74 assert(i >= IdxT(0) && i < IdxT(SIZE));
75 return mm[i];
76 }
77
78 // These exist solely to provide backwards compatibility with [] access of
79 // non-integer types that were castable to 'int' (such as floating point type).
80 // The above templates allow for any integer type to be used as an offset into
81 // the tuple data.
82 T operator[](int i) const { return this->template operator[]<int>(i); }
83 T& operator[](int i) { return this->template operator[]<int>(i); }
84
85 /// @name Compatibility
86 /// These are mostly for backwards compatibility with functions that take
87 /// old-style Vs (which are just arrays).
88 //@{
89 /// Copies this tuple into an array of a compatible type
90 template <typename S>
91 void toV(S *v) const {
92 for (int i = 0; i < SIZE; ++i) {
93 v[i] = mm[i];
94 }
95 }
96
97 /// Exposes the internal array. Be careful when using this function.
99 return mm;
100 }
101 /// Exposes the internal array. Be careful when using this function.
102 value_type const *asV() const {
103 return mm;
104 }
105 //@} Compatibility
106
107 /// @return string representation of Classname
108 std::string str() const {
109 std::ostringstream buffer;
110
111 buffer << "[";
112
113 // For each column
114 for (unsigned j(0); j < SIZE; j++) {
115 if (j) buffer << ", ";
116 buffer << PrintCast(mm[j]);
117 }
118
119 buffer << "]";
120
121 return buffer.str();
122 }
123
124 void write(std::ostream& os) const {
125 os.write(reinterpret_cast<const char*>(&mm), sizeof(T)*SIZE);
126 }
127 void read(std::istream& is) {
128 is.read(reinterpret_cast<char*>(&mm), sizeof(T)*SIZE);
129 }
130
131 /// True if a Nan is present in this tuple
132 bool isNan() const {
133 for (int i = 0; i < SIZE; ++i) {
134 if (math::isNan(mm[i])) return true;
135 }
136 return false;
137 }
138
139 /// True if an Inf is present in this tuple
140 bool isInfinite() const {
141 for (int i = 0; i < SIZE; ++i) {
142 if (math::isInfinite(mm[i])) return true;
143 }
144 return false;
145 }
146
147 /// True if no Nan or Inf values are present
148 bool isFinite() const {
149 for (int i = 0; i < SIZE; ++i) {
150 if (!math::isFinite(mm[i])) return false;
151 }
152 return true;
153 }
154
155 /// True if all elements are exactly zero
156 bool isZero() const {
157 for (int i = 0; i < SIZE; ++i) {
158 if (!math::isZero(mm[i])) return false;
159 }
160 return true;
161 }
162
163protected:
164 T mm[SIZE];
165};
166
167
168////////////////////////////////////////
169
170
171/// @return true if t0 < t1, comparing components in order of significance.
172template<int SIZE, typename T0, typename T1>
173bool
174operator<(const Tuple<SIZE, T0>& t0, const Tuple<SIZE, T1>& t1)
175{
176 for (int i = 0; i < SIZE-1; ++i) {
177 if (!isExactlyEqual(t0[i], t1[i])) return t0[i] < t1[i];
178 }
179 return t0[SIZE-1] < t1[SIZE-1];
180}
181
182
183/// @return true if t0 > t1, comparing components in order of significance.
184template<int SIZE, typename T0, typename T1>
185bool
187{
188 for (int i = 0; i < SIZE-1; ++i) {
189 if (!isExactlyEqual(t0[i], t1[i])) return t0[i] > t1[i];
190 }
191 return t0[SIZE-1] > t1[SIZE-1];
192}
193
194
195////////////////////////////////////////
196
197
198/// @return the absolute value of the given Tuple.
199template<int SIZE, typename T>
200Tuple<SIZE, T>
202{
203 Tuple<SIZE, T> result;
204 for (int i = 0; i < SIZE; ++i) result[i] = math::Abs(t[i]);
205 return result;
206}
207
208/// Return @c true if a Nan is present in the tuple.
209template<int SIZE, typename T>
210inline bool isNan(const Tuple<SIZE, T>& t) { return t.isNan(); }
211
212/// Return @c true if an Inf is present in the tuple.
213template<int SIZE, typename T>
214inline bool isInfinite(const Tuple<SIZE, T>& t) { return t.isInfinite(); }
215
216/// Return @c true if no Nan or Inf values are present.
217template<int SIZE, typename T>
218inline bool isFinite(const Tuple<SIZE, T>& t) { return t.isFinite(); }
219
220/// Return @c true if all elements are exactly equal to zero.
221template<int SIZE, typename T>
222inline bool isZero(const Tuple<SIZE, T>& t) { return t.isZero(); }
223
224////////////////////////////////////////
225
226
227/// Write a Tuple to an output stream
228template <int SIZE, typename T>
229std::ostream& operator<<(std::ostream& ostr, const Tuple<SIZE, T>& classname)
230{
231 ostr << classname.str();
232 return ostr;
233}
234
235} // namespace math
236} // namespace OPENVDB_VERSION_NAME
237} // namespace openvdb
238
239#endif // OPENVDB_MATH_TUPLE_HAS_BEEN_INCLUDED
General-purpose arithmetic and comparison routines, most of which accept arbitrary value types (or at...
Definition: Tuple.h:30
T operator[](IdxT i) const
Definition: Tuple.h:64
bool isZero() const
True if all elements are exactly zero.
Definition: Tuple.h:156
void write(std::ostream &os) const
Copies this tuple into an array of a compatible type.
Definition: Tuple.h:124
bool isInfinite() const
True if an Inf is present in this tuple.
Definition: Tuple.h:140
T & operator[](IdxT i)
Definition: Tuple.h:73
value_type const * asV() const
Exposes the internal array. Be careful when using this function.
Definition: Tuple.h:102
value_type * asV()
Exposes the internal array. Be careful when using this function.
Definition: Tuple.h:98
T operator[](int i) const
Definition: Tuple.h:82
Tuple(Tuple< src_size, src_valtype > const &src)
Conversion constructor.
Definition: Tuple.h:49
void toV(S *v) const
Copies this tuple into an array of a compatible type.
Definition: Tuple.h:91
T & operator[](int i)
Definition: Tuple.h:83
std::string str() const
Definition: Tuple.h:108
T ValueType
Definition: Tuple.h:33
bool isNan() const
True if a Nan is present in this tuple.
Definition: Tuple.h:132
T value_type
Definition: Tuple.h:32
void read(std::istream &is)
Copies this tuple into an array of a compatible type.
Definition: Tuple.h:127
bool isFinite() const
True if no Nan or Inf values are present.
Definition: Tuple.h:148
bool isInfinite(const float x)
Return true if x is an infinity value (either positive infinity or negative infinity).
Definition: Math.h:385
bool operator<(const Tuple< SIZE, T0 > &t0, const Tuple< SIZE, T1 > &t1)
Definition: Tuple.h:174
bool operator>(const Tuple< SIZE, T0 > &t0, const Tuple< SIZE, T1 > &t1)
Definition: Tuple.h:186
bool isFinite(const float x)
Return true if x is finite.
Definition: Math.h:375
auto PrintCast(const T &val) -> typename std::enable_if<!std::is_same< T, int8_t >::value &&!std::is_same< T, uint8_t >::value, const T & >::type
8-bit integer values print to std::ostreams as characters. Cast them so that they print as integers i...
Definition: Math.h:882
bool isNan(const float x)
Return true if x is a NaN (Not-A-Number) value.
Definition: Math.h:395
Coord Abs(const Coord &xyz)
Definition: Coord.h:515
bool isExactlyEqual(const T0 &a, const T1 &b)
Return true if a is exactly equal to b.
Definition: Math.h:443
bool isZero(const Type &x)
Return true if x is exactly equal to zero.
Definition: Math.h:337
std::ostream & operator<<(std::ostream &ostr, const Metadata &metadata)
Write a Metadata to an output stream.
Definition: Metadata.h:351
Definition: Exceptions.h:13
Dummy class for tag dispatch of conversion constructors.
Definition: Tuple.h:23
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition: version.h.in:121
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h.in:212