VTK
dox/Common/Core/vtkVariantInlineOperators.h
Go to the documentation of this file.
00001 #include <climits>
00002 
00003 // ----------------------------------------------------------------------
00004 
00005 // First we have several helper functions that will determine what
00006 // type we're actually dealing with.  With any luck the compiler will
00007 // inline these so they have very little overhead.
00008 
00009 inline bool
00010 IsSigned64Bit(int VariantType)
00011 {
00012 #if defined(VTK_TYPE_USE_LONG_LONG) && defined(VTK_TYPE_USE___INT64)
00013   return ((VariantType == VTK_LONG_LONG) ||
00014           (VariantType == VTK___INT64) ||
00015           (VariantType == VTK_TYPE_INT64));
00016 #elif defined(VTK_TYPE_USE_LONG_LONG)
00017   return ((VariantType == VTK_LONG_LONG) ||
00018           (VariantType == VTK_TYPE_INT64));
00019 #elif defined(VTK_TYPE_USE___INT64)
00020   return ((VariantType == VTK___INT64) ||
00021           (VariantType == VTK_TYPE_INT64));
00022 #else
00023   return (VariantType == VTK_TYPE_INT64);
00024 #endif
00025 }
00026 
00027 inline bool
00028 IsSigned(int VariantType)
00029 {
00030 #if (CHAR_MIN == SCHAR_MIN && CHAR_MAX == SCHAR_MAX)
00031 // the char type is signed on this compiler
00032   return ((VariantType == VTK_CHAR) ||
00033           (VariantType == VTK_SIGNED_CHAR) ||
00034           (VariantType == VTK_SHORT) ||
00035           (VariantType == VTK_INT) ||
00036           (VariantType == VTK_LONG) ||
00037           (VariantType == VTK_ID_TYPE) ||
00038           IsSigned64Bit(VariantType));
00039 #else
00040   // char is unsigned
00041   return ((VariantType == VTK_SIGNED_CHAR) ||
00042           (VariantType == VTK_SHORT) ||
00043           (VariantType == VTK_INT) ||
00044           (VariantType == VTK_LONG) ||
00045           (VariantType == VTK_ID_TYPE) ||
00046           IsSigned64Bit(VariantType));
00047 #endif
00048 }
00049 
00050 // ----------------------------------------------------------------------
00051 
00052 inline bool
00053 IsFloatingPoint(int VariantType)
00054 {
00055   return ((VariantType == VTK_FLOAT) ||
00056           (VariantType == VTK_DOUBLE));
00057 }
00058 
00059 // ----------------------------------------------------------------------
00060 
00061 inline bool
00062 CompareSignedUnsignedEqual(const vtkVariant &SignedVariant,
00063                            const vtkVariant &UnsignedVariant)
00064 {
00065   // If the signed value is less than zero then they cannot possibly
00066   // be equal.
00067   vtkTypeInt64 A = SignedVariant.ToTypeInt64();
00068   return (A >= 0) && (A == UnsignedVariant.ToTypeInt64());
00069 }
00070 
00071 // ----------------------------------------------------------------------
00072 
00073 inline bool
00074 CompareSignedUnsignedLessThan(const vtkVariant &SignedVariant,
00075                               const vtkVariant &UnsignedVariant)
00076 {
00077   vtkTypeInt64 A = SignedVariant.ToTypeInt64();
00078   return ((A < 0) ||
00079           (static_cast<vtkTypeUInt64>(A) < UnsignedVariant.ToTypeUInt64()));
00080 }
00081 
00082 // ----------------------------------------------------------------------
00083 
00084 inline bool
00085 CompareUnsignedSignedLessThan(const vtkVariant &UnsignedVariant,
00086                               const vtkVariant &SignedVariant)
00087 {
00088   vtkTypeInt64 B = SignedVariant.ToTypeInt64();
00089   return ((B > 0) &&
00090           (UnsignedVariant.ToTypeUInt64() < static_cast<vtkTypeUInt64>(B)));
00091 }
00092 
00093 // ----------------------------------------------------------------------
00094 
00095 inline bool
00096 CompareSignedLessThan(const vtkVariant &A,
00097                       const vtkVariant &B)
00098 {
00099   return (A.ToTypeInt64() < B.ToTypeInt64());
00100 }
00101 
00102 // ----------------------------------------------------------------------
00103 
00104 inline bool
00105 CompareUnsignedLessThan(const vtkVariant &A,
00106                         const vtkVariant &B)
00107 {
00108   return (A.ToTypeUInt64() < B.ToTypeUInt64());
00109 }
00110 
00111 // ----------------------------------------------------------------------
00112 
00113 inline bool
00114 vtkVariant::operator==(const vtkVariant &other) const
00115 {
00116   // First test: NULL values are always equal to one another and
00117   // unequal to anything else.
00118   if (! (this->Valid && other.Valid))
00119     {
00120     return (!(this->Valid || other.Valid));
00121     }
00122 
00123   // Second test: VTK objects can only be compared with other VTK
00124   // objects.
00125   if ((this->Type == VTK_OBJECT) || (other.Type == VTK_OBJECT))
00126     {
00127     return ((this->Type == VTK_OBJECT) &&
00128             (other.Type == VTK_OBJECT) &&
00129             (this->Data.VTKObject == other.Data.VTKObject));
00130     }
00131 
00132   // Third test: the STRING type dominates all else.  If either item
00133   // is a string then they must both be compared as strings.
00134   if ((this->Type == VTK_STRING) ||
00135       (other.Type == VTK_STRING))
00136     {
00137     return (this->ToString() == other.ToString());
00138     }
00139 
00140   // Fourth test: the Unicode STRING type dominates all else.  If either item
00141   // is a unicode string then they must both be compared as strings.
00142   if ((this->Type == VTK_UNICODE_STRING) ||
00143       (other.Type == VTK_UNICODE_STRING))
00144     {
00145     return (this->ToUnicodeString() == other.ToUnicodeString());
00146     }
00147 
00148 
00149   // Fifth: floating point dominates integer types.
00150   // Demote to the lowest-floating-point precision for the comparison.
00151   // This effectively makes the lower-precision number an interval
00152   // corresponding to the range of double values that get rounded to
00153   // that float. Otherwise, comparisons of numbers that cannot fit in
00154   // the smaller mantissa exactly will never be equal to their
00155   // corresponding higher-precision representations.
00156   if (this->Type == VTK_FLOAT || other.Type == VTK_FLOAT)
00157     {
00158     return this->ToFloat() == other.ToFloat();
00159     }
00160   else if (this->Type == VTK_DOUBLE || other.Type == VTK_DOUBLE)
00161     {
00162     return (this->ToDouble() == other.ToDouble());
00163     }
00164 
00165   // Sixth: we must be comparing integers.
00166 
00167   // 6A: catch signed/unsigned comparison.  If the signed object is
00168   // less than zero then they cannot be equal.
00169   bool thisSigned = IsSigned(this->Type);
00170   bool otherSigned = IsSigned(other.Type);
00171 
00172   if (thisSigned ^ otherSigned)
00173     {
00174     if (thisSigned)
00175       {
00176       return CompareSignedUnsignedEqual(*this, other);
00177       }
00178     else
00179       {
00180       return CompareSignedUnsignedEqual(other, *this);
00181       }
00182     }
00183   else // 6B: both are signed or both are unsigned.  In either event
00184        // all we have to do is check whether the bit patterns are
00185        // equal.
00186     {
00187     return (this->ToTypeInt64() == other.ToTypeInt64());
00188     }
00189 }
00190 
00191 // ----------------------------------------------------------------------
00192 
00193 inline bool
00194 vtkVariant::operator<(const vtkVariant &other) const
00195 {
00196   // First test: a NULL value is less than anything except another
00197   // NULL value.  unequal to anything else.
00198   if (! (this->Valid && other.Valid))
00199     {
00200     return ((!this->Valid) && (other.Valid));
00201     }
00202 
00203   // Second test: VTK objects can only be compared with other VTK
00204   // objects.
00205   if ((this->Type == VTK_OBJECT) || (other.Type == VTK_OBJECT))
00206     {
00207     return ((this->Type == VTK_OBJECT) &&
00208             (other.Type == VTK_OBJECT) &&
00209             (this->Data.VTKObject < other.Data.VTKObject));
00210     }
00211 
00212   // Third test: the STRING type dominates all else.  If either item
00213   // is a string then they must both be compared as strings.
00214   if ((this->Type == VTK_STRING) ||
00215       (other.Type == VTK_STRING))
00216     {
00217     return (this->ToString() < other.ToString());
00218     }
00219 
00220   // Fourth test: the Unicode STRING type dominates all else.  If either item
00221   // is a unicode string then they must both be compared as strings.
00222   if ((this->Type == VTK_UNICODE_STRING) ||
00223       (other.Type == VTK_UNICODE_STRING))
00224     {
00225     return (this->ToUnicodeString() < other.ToUnicodeString());
00226     }
00227 
00228   // Fourth: floating point dominates integer types.
00229   // Demote to the lowest-floating-point precision for the comparison.
00230   // This effectively makes the lower-precision number an interval
00231   // corresponding to the range of double values that get rounded to
00232   // that float. Otherwise, comparisons of numbers that cannot fit in
00233   // the smaller mantissa exactly will never be equal to their
00234   // corresponding higher-precision representations.
00235   if (this->Type == VTK_FLOAT || other.Type == VTK_FLOAT)
00236     {
00237     return this->ToFloat() < other.ToFloat();
00238     }
00239   else if (this->Type == VTK_DOUBLE || other.Type == VTK_DOUBLE)
00240     {
00241     return (this->ToDouble() < other.ToDouble());
00242     }
00243 
00244   // Fifth: we must be comparing integers.
00245 
00246   // 5A: catch signed/unsigned comparison.  If the signed object is
00247   // less than zero then they cannot be equal.
00248   bool thisSigned = IsSigned(this->Type);
00249   bool otherSigned = IsSigned(other.Type);
00250 
00251   if (thisSigned ^ otherSigned)
00252     {
00253     if (thisSigned)
00254       {
00255       return CompareSignedUnsignedLessThan(*this, other);
00256       }
00257     else
00258       {
00259       return CompareUnsignedSignedLessThan(*this, other);
00260       }
00261     }
00262   else if (thisSigned)
00263     {
00264     return CompareSignedLessThan(*this, other);
00265     }
00266   else
00267     {
00268     return CompareUnsignedLessThan(*this, other);
00269     }
00270 }
00271 
00272 // ----------------------------------------------------------------------
00273 
00274 // Below this point are operators defined in terms of other operators.
00275 // Again, this may sacrifice some speed, but reduces the chance of
00276 // inconsistent behavior.
00277 
00278 
00279 // ----------------------------------------------------------------------
00280 
00281 inline bool
00282 vtkVariant::operator!=(const vtkVariant &other) const
00283 {
00284   return ! (this->operator==(other));
00285 }
00286 
00287 inline bool
00288 vtkVariant::operator>(const vtkVariant &other) const
00289 {
00290   return (!(this->operator==(other) ||
00291             this->operator<(other)));
00292 }
00293 
00294 inline bool
00295 vtkVariant::operator<=(const vtkVariant &other) const
00296 {
00297   return (this->operator==(other) ||
00298           this->operator<(other));
00299 }
00300 
00301 inline bool
00302 vtkVariant::operator>=(const vtkVariant &other) const
00303 {
00304   return (!this->operator<(other));
00305 }
00306 
00307 // VTK-HeaderTest-Exclude: vtkVariantInlineOperators.h