VTK  9.7.1
vtkVariantInlineOperators.h
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
2 // SPDX-License-Identifier: BSD-3-Clause
3 
4 #ifndef vtkVariantInlineOperators_h
5 #define vtkVariantInlineOperators_h
6 
7 #include "vtkABINamespace.h"
8 
9 #include <climits>
10 
11 // ----------------------------------------------------------------------
12 
13 // First we have several helper functions that will determine what
14 // type we're actually dealing with. With any luck the compiler will
15 // inline these so they have very little overhead.
16 
17 VTK_ABI_NAMESPACE_BEGIN
18 inline bool IsSigned64Bit(int VariantType)
19 {
20 #if VTK_LONG_LONG == VTK_TYPE_INT64
21  return (VariantType == VTK_TYPE_INT64);
22 #else
23  return ((VariantType == VTK_LONG_LONG) || (VariantType == VTK_TYPE_INT64));
24 #endif
25 }
26 
27 inline bool IsSigned(int VariantType)
28 {
29 #if (CHAR_MIN == SCHAR_MIN && CHAR_MAX == SCHAR_MAX)
30  // the char type is signed on this compiler
31  return ((VariantType == VTK_CHAR) || (VariantType == VTK_SIGNED_CHAR) ||
32  (VariantType == VTK_SHORT) || (VariantType == VTK_INT) || (VariantType == VTK_LONG) ||
33  (VariantType == VTK_ID_TYPE) || IsSigned64Bit(VariantType));
34 #else
35  // char is unsigned
36  return ((VariantType == VTK_SIGNED_CHAR) || (VariantType == VTK_SHORT) ||
37  (VariantType == VTK_INT) || (VariantType == VTK_LONG) || (VariantType == VTK_ID_TYPE) ||
38  IsSigned64Bit(VariantType));
39 #endif
40 }
41 // Overload prevents warnings about enums stored as signed or unsigned.
42 inline bool IsSigned(unsigned int VariantType)
43 {
44  return IsSigned(static_cast<int>(VariantType));
45 }
46 
47 // ----------------------------------------------------------------------
48 
49 inline bool IsFloatingPoint(int VariantType)
50 {
51  return ((VariantType == VTK_FLOAT) || (VariantType == VTK_DOUBLE));
52 }
53 // Overload prevents warnings about enums stored as signed or unsigned.
54 inline bool IsFloatingPoint(unsigned int VariantType)
55 {
56  return IsFloatingPoint(static_cast<int>(VariantType));
57 }
58 
59 // ----------------------------------------------------------------------
60 
62  const vtkVariant& SignedVariant, const vtkVariant& UnsignedVariant)
63 {
64  // If the signed value is less than zero then they cannot possibly
65  // be equal.
66  vtkTypeInt64 A = SignedVariant.ToTypeInt64();
67  return (A >= 0) && (A == UnsignedVariant.ToTypeInt64());
68 }
69 
70 // ----------------------------------------------------------------------
71 
73  const vtkVariant& SignedVariant, const vtkVariant& UnsignedVariant)
74 {
75  vtkTypeInt64 A = SignedVariant.ToTypeInt64();
76  return ((A < 0) || (static_cast<vtkTypeUInt64>(A) < UnsignedVariant.ToTypeUInt64()));
77 }
78 
79 // ----------------------------------------------------------------------
80 
82  const vtkVariant& UnsignedVariant, const vtkVariant& SignedVariant)
83 {
84  vtkTypeInt64 B = SignedVariant.ToTypeInt64();
85  return ((B > 0) && (UnsignedVariant.ToTypeUInt64() < static_cast<vtkTypeUInt64>(B)));
86 }
87 
88 // ----------------------------------------------------------------------
89 
90 inline bool CompareSignedLessThan(const vtkVariant& A, const vtkVariant& B)
91 {
92  return (A.ToTypeInt64() < B.ToTypeInt64());
93 }
94 
95 // ----------------------------------------------------------------------
96 
97 inline bool CompareUnsignedLessThan(const vtkVariant& A, const vtkVariant& B)
98 {
99  return (A.ToTypeUInt64() < B.ToTypeUInt64());
100 }
101 
102 // ----------------------------------------------------------------------
103 
104 inline bool vtkVariant::operator==(const vtkVariant& other) const
105 {
106  // First test: nullptr values are always equal to one another and
107  // unequal to anything else.
108  if (!(this->Valid && other.Valid))
109  {
110  return (!(this->Valid || other.Valid));
111  }
112 
113  // Second test: VTK objects can only be compared with other VTK
114  // objects.
115  if ((this->Type == VTK_OBJECT) || (other.Type == VTK_OBJECT))
116  {
117  return ((this->Type == VTK_OBJECT) && (other.Type == VTK_OBJECT) &&
118  (this->Data.VTKObject == other.Data.VTKObject));
119  }
120 
121  // Third test: the STRING type dominates all else. If either item
122  // is a string then they must both be compared as strings.
123  if ((this->Type == VTK_STRING) || (other.Type == VTK_STRING))
124  {
125  return (this->ToString() == other.ToString());
126  }
127 
128  // Fifth: floating point dominates integer types.
129  // Demote to the lowest-floating-point precision for the comparison.
130  // This effectively makes the lower-precision number an interval
131  // corresponding to the range of double values that get rounded to
132  // that float. Otherwise, comparisons of numbers that cannot fit in
133  // the smaller mantissa exactly will never be equal to their
134  // corresponding higher-precision representations.
135  if (this->Type == VTK_FLOAT || other.Type == VTK_FLOAT)
136  {
137  return this->ToFloat() == other.ToFloat();
138  }
139  else if (this->Type == VTK_DOUBLE || other.Type == VTK_DOUBLE)
140  {
141  return (this->ToDouble() == other.ToDouble());
142  }
143 
144  // Sixth: we must be comparing integers.
145 
146  // 6A: catch signed/unsigned comparison. If the signed object is
147  // less than zero then they cannot be equal.
148  bool thisSigned = IsSigned(this->Type);
149  bool otherSigned = IsSigned(other.Type);
150 
151  if (thisSigned ^ otherSigned)
152  {
153  if (thisSigned)
154  {
155  return CompareSignedUnsignedEqual(*this, other);
156  }
157  else
158  {
159  return CompareSignedUnsignedEqual(other, *this);
160  }
161  }
162  else // 6B: both are signed or both are unsigned. In either event
163  // all we have to do is check whether the bit patterns are
164  // equal.
165  {
166  return (this->ToTypeInt64() == other.ToTypeInt64());
167  }
168 }
169 
170 // ----------------------------------------------------------------------
171 
172 inline bool vtkVariant::operator<(const vtkVariant& other) const
173 {
174  // First test: a nullptr value is less than anything except another
175  // nullptr value. unequal to anything else.
176  if (!(this->Valid && other.Valid))
177  {
178  return ((!this->Valid) && (other.Valid));
179  }
180 
181  // Second test: VTK objects can only be compared with other VTK
182  // objects.
183  if ((this->Type == VTK_OBJECT) || (other.Type == VTK_OBJECT))
184  {
185  return ((this->Type == VTK_OBJECT) && (other.Type == VTK_OBJECT) &&
186  (this->Data.VTKObject < other.Data.VTKObject));
187  }
188 
189  // Third test: the STRING type dominates all else. If either item
190  // is a string then they must both be compared as strings.
191  if ((this->Type == VTK_STRING) || (other.Type == VTK_STRING))
192  {
193  return (this->ToString() < other.ToString());
194  }
195 
196  // Fourth: floating point dominates integer types.
197  // Demote to the lowest-floating-point precision for the comparison.
198  // This effectively makes the lower-precision number an interval
199  // corresponding to the range of double values that get rounded to
200  // that float. Otherwise, comparisons of numbers that cannot fit in
201  // the smaller mantissa exactly will never be equal to their
202  // corresponding higher-precision representations.
203  if (this->Type == VTK_FLOAT || other.Type == VTK_FLOAT)
204  {
205  return this->ToFloat() < other.ToFloat();
206  }
207  else if (this->Type == VTK_DOUBLE || other.Type == VTK_DOUBLE)
208  {
209  return (this->ToDouble() < other.ToDouble());
210  }
211 
212  // Fifth: we must be comparing integers.
213 
214  // 5A: catch signed/unsigned comparison. If the signed object is
215  // less than zero then they cannot be equal.
216  bool thisSigned = IsSigned(this->Type);
217  bool otherSigned = IsSigned(other.Type);
218 
219  if (thisSigned ^ otherSigned)
220  {
221  if (thisSigned)
222  {
223  return CompareSignedUnsignedLessThan(*this, other);
224  }
225  else
226  {
227  return CompareUnsignedSignedLessThan(*this, other);
228  }
229  }
230  else if (thisSigned)
231  {
232  return CompareSignedLessThan(*this, other);
233  }
234  else
235  {
236  return CompareUnsignedLessThan(*this, other);
237  }
238 }
239 
240 // ----------------------------------------------------------------------
241 
242 // Below this point are operators defined in terms of other operators.
243 // Again, this may sacrifice some speed, but reduces the chance of
244 // inconsistent behavior.
245 
246 // ----------------------------------------------------------------------
247 
248 inline bool vtkVariant::operator!=(const vtkVariant& other) const
249 {
250  return !(this->operator==(other));
251 }
252 
253 inline bool vtkVariant::operator>(const vtkVariant& other) const
254 {
255  return (!(this->operator==(other) || this->operator<(other)));
256 }
257 
258 inline bool vtkVariant::operator<=(const vtkVariant& other) const
259 {
260  return (this->operator==(other) || this->operator<(other));
261 }
262 
263 inline bool vtkVariant::operator>=(const vtkVariant& other) const
264 {
265  return (!this->operator<(other));
266 }
267 
268 VTK_ABI_NAMESPACE_END
269 #endif
270 // VTK-HeaderTest-Exclude: vtkVariantInlineOperators.h
vtkTypeInt64 ToTypeInt64(bool *valid) const
Convert the variant to a numeric type: If it holds a numeric, cast to the appropriate type...
#define VTK_OBJECT
Definition: vtkType.h:57
vtkStdString ToString(int formatting=DEFAULT_FORMATTING, int precision=6) const
Convert the variant to a string.
bool operator!=(const vtkVariant &other) const
Compare two variants for equality, greater than, and less than.
bool IsSigned(int VariantType)
vtkTypeUInt64 ToTypeUInt64(bool *valid) const
Convert the variant to a numeric type: If it holds a numeric, cast to the appropriate type...
float ToFloat() const
Convert the variant to a numeric type: If it holds a numeric, cast to the appropriate type...
Definition: vtkVariant.h:310
double ToDouble() const
Convert the variant to a numeric type: If it holds a numeric, cast to the appropriate type...
Definition: vtkVariant.h:312
#define VTK_LONG_LONG
Definition: vtkType.h:52
A type representing the union of many types.
Definition: vtkVariant.h:52
vtkObjectBase * VTKObject
Definition: vtkVariant.h:424
#define VTK_STRING
Definition: vtkType.h:49
float ToFloat(bool *valid) const
Convert the variant to a numeric type: If it holds a numeric, cast to the appropriate type...
#define VTK_DOUBLE
Definition: vtkType.h:44
#define VTK_FLOAT
Definition: vtkType.h:43
bool CompareUnsignedSignedLessThan(const vtkVariant &UnsignedVariant, const vtkVariant &SignedVariant)
bool operator>(const vtkVariant &other) const
Compare two variants for equality, greater than, and less than.
bool IsFloatingPoint(int VariantType)
bool CompareSignedUnsignedLessThan(const vtkVariant &SignedVariant, const vtkVariant &UnsignedVariant)
#define VTK_SHORT
Definition: vtkType.h:37
#define VTK_CHAR
Definition: vtkType.h:34
#define VTK_LONG
Definition: vtkType.h:41
bool CompareUnsignedLessThan(const vtkVariant &A, const vtkVariant &B)
bool operator==(const vtkVariant &other) const
Compare two variants for equality, greater than, and less than.
bool CompareSignedLessThan(const vtkVariant &A, const vtkVariant &B)
vtkTypeInt64 ToTypeInt64() const
Convert the variant to a numeric type: If it holds a numeric, cast to the appropriate type...
Definition: vtkVariant.h:336
#define VTK_SIGNED_CHAR
Definition: vtkType.h:35
bool operator<(const vtkVariant &other) const
Compare two variants for equality, greater than, and less than.
bool CompareSignedUnsignedEqual(const vtkVariant &SignedVariant, const vtkVariant &UnsignedVariant)
bool IsSigned64Bit(int VariantType)
bool operator<=(const vtkVariant &other) const
Compare two variants for equality, greater than, and less than.
#define VTK_ID_TYPE
Definition: vtkType.h:45
bool operator>=(const vtkVariant &other) const
Compare two variants for equality, greater than, and less than.
#define VTK_INT
Definition: vtkType.h:39
double ToDouble(bool *valid) const
Convert the variant to a numeric type: If it holds a numeric, cast to the appropriate type...