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