00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00049 #ifndef __vtkFastNumericConversion_h
00050 #define __vtkFastNumericConversion_h
00051
00052 #include "vtkObject.h"
00053
00054
00055
00056 #if defined(NDEBUG) && (defined i386 || defined _M_IX86)
00057 #define VTK_USE_TRICK
00058 #endif
00059
00060
00061
00062
00063
00064
00065
00066
00067 #if defined(__linux__)
00068 #define VTK_EXT_PREC
00069 #endif
00070
00071
00072 #ifdef VTK_TEST_HACK_TO_EMULATE_LINUX_UNDER_WINDOWS
00073 #define VTK_EXT_PREC
00074 #endif
00075
00076
00077 class VTK_COMMON_EXPORT vtkFastNumericConversion : public vtkObject
00078 {
00079 public:
00080 static vtkFastNumericConversion *New();
00081 vtkTypeRevisionMacro(vtkFastNumericConversion, vtkObject);
00082 void PrintSelf(ostream& os, vtkIndent indent);
00083
00086 int TestQuickFloor(double val);
00087
00090 int TestSafeFloor(double val);
00091
00094 int TestRound(double val);
00095
00098 int TestConvertFixedPointIntPart(double val);
00099
00102 int TestConvertFixedPointFracPart(double val);
00103
00104 protected:
00105
00111 static inline double BorrowBit() { return 1.5;};
00112
00114
00117 static inline double two30()
00118 {
00119 return static_cast<double>(static_cast<unsigned long>(1) << 30);
00120 }
00122
00124
00126 static inline double two52()
00127 {
00128 return (static_cast<unsigned long>(1) << (52-30)) * two30();
00129 }
00131
00133
00138 static inline double two51()
00139 {
00140 return (static_cast<unsigned long>(1) << (51-30)) * two30();
00141 }
00143
00145
00148 static inline double two63()
00149 {
00150 return (static_cast<unsigned long>(1) << (63-60)) * two30() * two30();
00151 }
00153
00155
00158 static inline double two62()
00159 {
00160 return (static_cast<unsigned long>(1) << (62-60)) * two30() * two30();
00161 }
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174 #define INT_BITS 30
00175 #define EXT_BITS 64
00176 #define DBL_BITS 53
00177
00206 public:
00207 #ifdef VTK_EXT_PREC
00208
00209 static inline double RoundingTieBreaker()
00210 {
00211 return 1.0 / (two30() * (static_cast<unsigned long>(1) << (EXT_BITS - INT_BITS - 30)));
00212 }
00213 #else
00214
00215 static inline double RoundingTieBreaker()
00216 {
00217 return 1.0 / (static_cast<unsigned long>(1) << (DBL_BITS - INT_BITS));
00218 }
00219 #endif
00220
00221 protected:
00223
00227 static inline double QuickFloorDenormalizer()
00228 {return two52() * BorrowBit(); };
00230
00232
00237 static inline double SafeFloorDenormalizer()
00238 { return two51() * BorrowBit(); };
00240
00242
00245 static inline double QuickExtPrecTempDenormalizer()
00246 {return two63() * BorrowBit(); };
00248
00250
00253 static inline double SafeExtPrecTempDenormalizer()
00254 {return two62() * BorrowBit(); };
00256
00257 static inline double QuickRoundAdjust() {return 0.5;};
00258 static inline double SafeRoundAdjust() {return 0.25;};
00259 static inline int SafeFinalShift() {return 1;};
00260
00261
00262 #ifdef VTK_WORDS_BIGENDIAN
00263 enum {exponent_pos = 0, mantissa_pos = 1};
00264 #else
00265 enum {exponent_pos = 1, mantissa_pos = 0};
00266 #endif
00267
00268
00269 public:
00270
00272
00283 void SetReservedFracBits(int bits)
00284 {
00285
00286
00287
00288 bits++;
00289 unsigned long mtime = this->GetMTime();
00290 this->SetinternalReservedFracBits(bits);
00291 if (mtime != this->GetMTime())
00292 {
00293 this->InternalRebuild();
00294 }
00295 };
00297
00301 void PerformanceTests(void);
00302
00303
00305
00322 inline static int QuickFloor(const double &val)
00323 {
00324 #ifdef VTK_USE_TRICK
00325 union { int i[2]; double d; } u;
00326 #ifdef VTK_EXT_PREC
00327 u.d = (((val - (QuickRoundAdjust() - RoundingTieBreaker()))
00328
00329 + QuickExtPrecTempDenormalizer())
00330
00331 - QuickExtPrecTempDenormalizer())
00332 + QuickFloorDenormalizer();
00333 #else // ! VTK_EXT_PREC
00334 u.d = (val - (QuickRoundAdjust() - RoundingTieBreaker()))
00335 + QuickFloorDenormalizer();
00336 #endif // VTK_EXT_PREC
00337 return u.i[mantissa_pos];
00338 #else // ! VTK_USE_TRICK
00339 return static_cast<int>(val);
00340 #endif // VTK_USE_TRICK
00341 }
00343
00345
00359 inline static int SafeFloor(const double &val)
00360 {
00361 #ifdef VTK_USE_TRICK
00362 union { int i[2]; double d; } u;
00363 #ifdef VTK_EXT_PREC
00364 u.d = (((val - SafeRoundAdjust())
00365 + SafeExtPrecTempDenormalizer())
00366 - SafeExtPrecTempDenormalizer())
00367 + SafeFloorDenormalizer();
00368 #else // ! VTK_EXT_PREC
00369 u.d = (val - SafeRoundAdjust())
00370 + SafeFloorDenormalizer();
00371 #endif // VTK_EXT_PREC
00372 return u.i[mantissa_pos] >> SafeFinalShift();
00373 #else // ! VTK_USE_TRICK
00374 return static_cast<int>(val);
00375 #endif // VTK_USE_TRICK
00376 }
00378
00380
00389 inline static int Round(const double &val)
00390 {
00391 #ifdef VTK_USE_TRICK
00392 union { int i[2]; double d; } u;
00393 #ifdef VTK_EXT_PREC
00394 u.d = ((val
00395 + QuickExtPrecTempDenormalizer())
00396 - QuickExtPrecTempDenormalizer())
00397 + QuickFloorDenormalizer();
00398 #else // ! VTK_EXT_PREC
00399 u.d = val
00400 + QuickFloorDenormalizer();
00401 #endif // VTK_EXT_PREC
00402 return u.i[mantissa_pos];
00403 #else // ! VTK_USE_TRICK
00404 if (val>=0)
00405 {
00406 return static_cast<int>(val + 0.5);
00407 }
00408 else
00409 {
00410 return static_cast<int>(val - 0.5);
00411 }
00412 #endif // VTK_USE_TRICK
00413 }
00415
00417
00420 inline int ConvertFixedPoint(const double &val, int &fracPart)
00421 {
00422 union { int i[2]; double d; } u;
00423 #ifdef VTK_EXT_PREC
00424 u.d = (((val - fixRound)
00425 + this->epTempDenormalizer)
00426 - this->epTempDenormalizer)
00427 + this->fpDenormalizer;
00428 #else // ! VTK_EXT_PREC
00429 u.d = (val - fixRound)
00430 + this->fpDenormalizer;
00431 #endif // VTK_EXT_PREC
00432 fracPart = (u.i[mantissa_pos] & fracMask) >> 1;
00433 return u.i[mantissa_pos] >> this->internalReservedFracBits;
00434 }
00435
00437
00438
00439 protected:
00440
00441 vtkFastNumericConversion()
00442 {
00443 #ifdef VTK_TEST_HACK_TO_EMULATE_LINUX_UNDER_WINDOWS
00444 _controlfp( _PC_64, MCW_PC );
00445 #endif
00446
00447 this->fixRound = 0;
00448 this->internalReservedFracBits = 0;
00449 this->fracMask = 0;
00450 this->fpDenormalizer = 0;
00451 this->bare_time = 0;
00452 this->cast_time = 0;
00453 this->convert_time = 0;
00454 this->quickfloor_time = 0;
00455 this->safefloor_time = 0;
00456 this->round_time = 0;
00457 this->InternalRebuild();
00458 };
00459 ~vtkFastNumericConversion() {};
00460 void InternalRebuild(void);
00461
00462 private:
00463 vtkSetMacro(internalReservedFracBits, int);
00464 vtkGetMacro(internalReservedFracBits, int);
00465 int internalReservedFracBits;
00466 int fracMask;
00467
00468
00469
00470
00471 double fpDenormalizer;
00472
00473
00474 double epTempDenormalizer;
00475
00476
00477
00478 double fixRound;
00479
00480 double bare_time;
00481 double cast_time;
00482 double convert_time;
00483 double quickfloor_time;
00484 double safefloor_time;
00485 double round_time;
00486
00487
00488 vtkFastNumericConversion(const vtkFastNumericConversion&);
00489 void operator=(const vtkFastNumericConversion&);
00490 };
00491
00492 #endif