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