00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00052 #ifndef __vtkFastNumericConversion_h
00053 #define __vtkFastNumericConversion_h
00054
00055 #include "vtkObject.h"
00056
00057
00058
00059 #if defined(NDEBUG) && (defined i386 || defined _M_IX86)
00060 #define VTK_USE_TRICK
00061 #endif
00062
00063
00064
00065
00066
00067
00068
00069
00070 #if defined(__linux__)
00071 #define VTK_EXT_PREC
00072 #endif
00073
00074
00075 #ifdef VTK_TEST_HACK_TO_EMULATE_LINUX_UNDER_WINDOWS
00076 #define VTK_EXT_PREC
00077 #endif
00078
00079
00080 class VTK_COMMON_EXPORT vtkFastNumericConversion : public vtkObject
00081 {
00082 public:
00083 static vtkFastNumericConversion *New();
00084 vtkTypeMacro(vtkFastNumericConversion, vtkObject);
00085 void PrintSelf(ostream& os, vtkIndent indent);
00086
00087 int TestQuickFloor(double val)
00088 {
00089 return vtkFastNumericConversion::QuickFloor(val);
00090 }
00091
00092 int TestSafeFloor(double val)
00093 {
00094 return vtkFastNumericConversion::SafeFloor(val);
00095 }
00096
00097 int TestRound(double val)
00098 {
00099 return vtkFastNumericConversion::Round(val);
00100 }
00101
00102 int TestConvertFixedPointIntPart(double val)
00103 {
00104 int frac;
00105 return ConvertFixedPoint(val, frac);
00106 }
00107
00108 int TestConvertFixedPointFracPart(double val)
00109 {
00110 int frac;
00111 ConvertFixedPoint(val, frac);
00112 return frac;
00113 }
00114
00115 protected:
00116
00122 static inline double BorrowBit() { return 1.5;};
00123
00125
00128 static inline double two30()
00129 {
00130 return static_cast<double>(static_cast<unsigned long>(1) << 30);
00131 }
00133
00135
00137 static inline double two52()
00138 {
00139 return (static_cast<unsigned long>(1) << (52-30)) * two30();
00140 }
00142
00144
00149 static inline double two51()
00150 {
00151 return (static_cast<unsigned long>(1) << (51-30)) * two30();
00152 }
00154
00156
00159 static inline double two63()
00160 {
00161 return (static_cast<unsigned long>(1) << (63-60)) * two30() * two30();
00162 }
00164
00166
00169 static inline double two62()
00170 {
00171 return (static_cast<unsigned long>(1) << (62-60)) * two30() * two30();
00172 }
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185 #define INT_BITS 30
00186 #define EXT_BITS 64
00187 #define DBL_BITS 53
00188
00190
00218 public:
00219 #ifdef VTK_EXT_PREC
00220
00221 static inline double RoundingTieBreaker()
00222 {
00223 return 1.0 / (two30() * (static_cast<unsigned long>(1) << (EXT_BITS - INT_BITS - 30)));
00224 }
00225 #else
00226
00227 static inline double RoundingTieBreaker()
00228 {
00229 return 1.0 / (static_cast<unsigned long>(1) << (DBL_BITS - INT_BITS));
00230 }
00231 #endif
00232
00233
00234 protected:
00236
00240 static inline double QuickFloorDenormalizer()
00241 {return two52() * BorrowBit(); };
00243
00245
00250 static inline double SafeFloorDenormalizer()
00251 { return two51() * BorrowBit(); };
00253
00255
00258 static inline double QuickExtPrecTempDenormalizer()
00259 {return two63() * BorrowBit(); };
00261
00263
00266 static inline double SafeExtPrecTempDenormalizer()
00267 {return two62() * BorrowBit(); };
00269
00270 static inline double QuickRoundAdjust() {return 0.5;};
00271 static inline double SafeRoundAdjust() {return 0.25;};
00272 static inline int SafeFinalShift() {return 1;};
00273
00274
00275 #ifdef VTK_WORDS_BIGENDIAN
00276 enum {exponent_pos = 0, mantissa_pos = 1};
00277 #else
00278 enum {exponent_pos = 1, mantissa_pos = 0};
00279 #endif
00280
00281
00282 public:
00283
00285
00296 void SetReservedFracBits(int bits)
00297 {
00298
00299
00300
00301 bits++;
00302 unsigned long mtime = this->GetMTime();
00303 this->SetinternalReservedFracBits(bits);
00304 if (mtime != this->GetMTime())
00305 {
00306 this->InternalRebuild();
00307 }
00308 };
00310
00311
00313
00330 inline static int QuickFloor(const double &val)
00331 {
00332 #ifdef VTK_USE_TRICK
00333 union { int i[2]; double d; } u;
00334 #ifdef VTK_EXT_PREC
00335 u.d = (((val - (QuickRoundAdjust() - RoundingTieBreaker()))
00336
00337 + QuickExtPrecTempDenormalizer())
00338
00339 - QuickExtPrecTempDenormalizer())
00340 + QuickFloorDenormalizer();
00341 #else // ! VTK_EXT_PREC
00342 u.d = (val - (QuickRoundAdjust() - RoundingTieBreaker()))
00343 + QuickFloorDenormalizer();
00344 #endif // VTK_EXT_PREC
00345 return u.i[mantissa_pos];
00346 #else // ! VTK_USE_TRICK
00347 return static_cast<int>(val);
00348 #endif // VTK_USE_TRICK
00349 }
00351
00353
00367 inline static int SafeFloor(const double &val)
00368 {
00369 #ifdef VTK_USE_TRICK
00370 union { int i[2]; double d; } u;
00371 #ifdef VTK_EXT_PREC
00372 u.d = (((val - SafeRoundAdjust())
00373 + SafeExtPrecTempDenormalizer())
00374 - SafeExtPrecTempDenormalizer())
00375 + SafeFloorDenormalizer();
00376 #else // ! VTK_EXT_PREC
00377 u.d = (val - SafeRoundAdjust())
00378 + SafeFloorDenormalizer();
00379 #endif // VTK_EXT_PREC
00380 return u.i[mantissa_pos] >> SafeFinalShift();
00381 #else // ! VTK_USE_TRICK
00382 return static_cast<int>(val);
00383 #endif // VTK_USE_TRICK
00384 }
00386
00388
00397 inline static int Round(const double &val)
00398 {
00399 #ifdef VTK_USE_TRICK
00400 union { int i[2]; double d; } u;
00401 #ifdef VTK_EXT_PREC
00402 u.d = ((val
00403 + QuickExtPrecTempDenormalizer())
00404 - QuickExtPrecTempDenormalizer())
00405 + QuickFloorDenormalizer();
00406 #else // ! VTK_EXT_PREC
00407 u.d = val
00408 + QuickFloorDenormalizer();
00409 #endif // VTK_EXT_PREC
00410 return u.i[mantissa_pos];
00411 #else // ! VTK_USE_TRICK
00412 if (val>=0)
00413 {
00414 return static_cast<int>(val + 0.5);
00415 }
00416 else
00417 {
00418 return static_cast<int>(val - 0.5);
00419 }
00420 #endif // VTK_USE_TRICK
00421 }
00423
00425
00428 inline int ConvertFixedPoint(const double &val, int &fracPart)
00429 {
00430 union { int i[2]; double d; } u;
00431 #ifdef VTK_EXT_PREC
00432 u.d = (((val - fixRound)
00433 + this->epTempDenormalizer)
00434 - this->epTempDenormalizer)
00435 + this->fpDenormalizer;
00436 #else // ! VTK_EXT_PREC
00437 u.d = (val - fixRound)
00438 + this->fpDenormalizer;
00439 #endif // VTK_EXT_PREC
00440 fracPart = (u.i[mantissa_pos] & fracMask) >> 1;
00441 return u.i[mantissa_pos] >> this->internalReservedFracBits;
00442 }
00443
00445
00446
00447 protected:
00448
00449 vtkFastNumericConversion()
00450 {
00451 #ifdef VTK_TEST_HACK_TO_EMULATE_LINUX_UNDER_WINDOWS
00452 _controlfp( _PC_64, MCW_PC );
00453 #endif
00454
00455 this->fixRound = 0;
00456 this->internalReservedFracBits = 0;
00457 this->fracMask = 0;
00458 this->fpDenormalizer = 0;
00459 };
00460 ~vtkFastNumericConversion() {};
00461 void InternalRebuild(void);
00462
00463 private:
00464 vtkSetMacro(internalReservedFracBits, int);
00465 vtkGetMacro(internalReservedFracBits, int);
00466 int internalReservedFracBits;
00467 int fracMask;
00468
00469
00470
00471
00472 double fpDenormalizer;
00473
00474
00475 double epTempDenormalizer;
00476
00477
00478
00479 double fixRound;
00480
00481
00482 vtkFastNumericConversion(const vtkFastNumericConversion&);
00483 void operator=(const vtkFastNumericConversion&);
00484 };
00485
00486 #endif