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
17VTK_ABI_NAMESPACE_BEGIN
18inline bool IsSigned64Bit(int VariantType)
19{
20 return ((VariantType == VTK_LONG_LONG) || (VariantType == VTK_TYPE_INT64));
21}
22
23inline 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
40inline 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
76inline bool CompareSignedLessThan(const vtkVariant& A, const vtkVariant& B)
77{
78 return (A.ToTypeInt64() < B.ToTypeInt64());
79}
80
81// ----------------------------------------------------------------------
82
83inline bool CompareUnsignedLessThan(const vtkVariant& A, const vtkVariant& B)
84{
85 return (A.ToTypeUInt64() < B.ToTypeUInt64());
86}
87
88// ----------------------------------------------------------------------
89
90inline 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
158inline 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
234inline bool vtkVariant::operator!=(const vtkVariant& other) const
235{
236 return !(this->operator==(other));
237}
238
239inline bool vtkVariant::operator>(const vtkVariant& other) const
240{
241 return (!(this->operator==(other) || this->operator<(other)));
242}
243
244inline bool vtkVariant::operator<=(const vtkVariant& other) const
245{
246 return (this->operator==(other) || this->operator<(other));
247}
248
249inline bool vtkVariant::operator>=(const vtkVariant& other) const
250{
251 return (!this->operator<(other));
252}
253
254VTK_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)