OpenVDB  11.0.0
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 
17 namespace openvdb {
19 namespace OPENVDB_VERSION_NAME {
20 namespace math {
21 
22 /// @brief Dummy class for tag dispatch of conversion constructors
23 struct Conversion {};
24 
25 
26 /// @class Tuple "Tuple.h"
27 /// A base class for homogenous tuple types
28 template<int SIZE, typename T>
29 class Tuple
30 {
31 public:
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 
163 protected:
164  T mm[SIZE];
165 };
166 
167 
168 ////////////////////////////////////////
169 
170 
171 /// @return true if t0 < t1, comparing components in order of significance.
172 template<int SIZE, typename T0, typename T1>
173 bool
174 operator<(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.
184 template<int SIZE, typename T0, typename T1>
185 bool
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.
199 template<int SIZE, typename 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.
209 template<int SIZE, typename T>
210 inline bool isNan(const Tuple<SIZE, T>& t) { return t.isNan(); }
211 
212 /// Return @c true if an Inf is present in the tuple.
213 template<int SIZE, typename T>
214 inline bool isInfinite(const Tuple<SIZE, T>& t) { return t.isInfinite(); }
215 
216 /// Return @c true if no Nan or Inf values are present.
217 template<int SIZE, typename T>
218 inline bool isFinite(const Tuple<SIZE, T>& t) { return t.isFinite(); }
219 
220 /// Return @c true if all elements are exactly equal to zero.
221 template<int SIZE, typename T>
222 inline bool isZero(const Tuple<SIZE, T>& t) { return t.isZero(); }
223 
224 ////////////////////////////////////////
225 
226 
227 /// Write a Tuple to an output stream
228 template <int SIZE, typename T>
229 std::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
bool isNan(const Tuple< SIZE, T > &t)
Return true if a Nan is present in the tuple.
Definition: Tuple.h:210
General-purpose arithmetic and comparison routines, most of which accept arbitrary value types (or at...
bool isExactlyEqual(const T0 &a, const T1 &b)
Return true if a is exactly equal to b.
Definition: Math.h:443
T & operator[](int i)
Definition: Tuple.h:83
bool isZero() const
True if all elements are exactly zero.
Definition: Tuple.h:156
std::string str() const
Definition: Tuple.h:108
void read(std::istream &is)
Definition: Tuple.h:127
value_type * asV()
Exposes the internal array. Be careful when using this function.
Definition: Tuple.h:98
bool isInfinite() const
True if an Inf is present in this tuple.
Definition: Tuple.h:140
bool isZero(const Tuple< SIZE, T > &t)
Return true if all elements are exactly equal to zero.
Definition: Tuple.h:222
Tuple< SIZE, T > Abs(const Tuple< SIZE, T > &t)
Definition: Tuple.h:201
T operator[](IdxT i) const
Definition: Tuple.h:64
value_type const * asV() const
Exposes the internal array. Be careful when using this function.
Definition: Tuple.h:102
Definition: Exceptions.h:13
Definition: Tuple.h:29
bool isFinite() const
True if no Nan or Inf values are present.
Definition: Tuple.h:148
bool isFinite(const Tuple< SIZE, T > &t)
Return true if no Nan or Inf values are present.
Definition: Tuple.h:218
void write(std::ostream &os) const
Definition: Tuple.h:124
T value_type
Definition: Tuple.h:32
bool isNan() const
True if a Nan is present in this tuple.
Definition: Tuple.h:132
bool operator>(const Tuple< SIZE, T0 > &t0, const Tuple< SIZE, T1 > &t1)
Definition: Tuple.h:186
T operator[](int i) const
Definition: Tuple.h:82
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
Tuple(Tuple< src_size, src_valtype > const &src)
Conversion constructor.
Definition: Tuple.h:49
bool isInfinite(const Tuple< SIZE, T > &t)
Return true if an Inf is present in the tuple.
Definition: Tuple.h:214
T & operator[](IdxT i)
Definition: Tuple.h:73
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition: version.h.in:121
void toV(S *v) const
Copies this tuple into an array of a compatible type.
Definition: Tuple.h:91
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h.in:212
T ValueType
Definition: Tuple.h:33
Dummy class for tag dispatch of conversion constructors.
Definition: Tuple.h:23