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
00089 int TestQuickFloor(double val);
00090
00093 int TestSafeFloor(double val);
00094
00097 int TestRound(double val);
00098
00101 int TestConvertFixedPointIntPart(double val);
00102
00105 int TestConvertFixedPointFracPart(double val);
00106
00107 protected:
00108
00114 static inline double BorrowBit() { return 1.5;};
00115
00117
00120 static inline double two30()
00121 {
00122 return static_cast<double>(static_cast<unsigned long>(1) << 30);
00123 }
00125
00127
00129 static inline double two52()
00130 {
00131 return (static_cast<unsigned long>(1) << (52-30)) * two30();
00132 }
00134
00136
00141 static inline double two51()
00142 {
00143 return (static_cast<unsigned long>(1) << (51-30)) * two30();
00144 }
00146
00148
00151 static inline double two63()
00152 {
00153 return (static_cast<unsigned long>(1) << (63-60)) * two30() * two30();
00154 }
00156
00158
00161 static inline double two62()
00162 {
00163 return (static_cast<unsigned long>(1) << (62-60)) * two30() * two30();
00164 }
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177 #define INT_BITS 30
00178 #define EXT_BITS 64
00179 #define DBL_BITS 53
00180
00209 public:
00210 #ifdef VTK_EXT_PREC
00211
00212 static inline double RoundingTieBreaker()
00213 {
00214 return 1.0 / (two30() * (static_cast<unsigned long>(1) << (EXT_BITS - INT_BITS - 30)));
00215 }
00216 #else
00217
00218 static inline double RoundingTieBreaker()
00219 {
00220 return 1.0 / (static_cast<unsigned long>(1) << (DBL_BITS - INT_BITS));
00221 }
00222 #endif
00223
00224 protected:
00226
00230 static inline double QuickFloorDenormalizer()
00231 {return two52() * BorrowBit(); };
00233
00235
00240 static inline double SafeFloorDenormalizer()
00241 { return two51() * BorrowBit(); };
00243
00245
00248 static inline double QuickExtPrecTempDenormalizer()
00249 {return two63() * BorrowBit(); };
00251
00253
00256 static inline double SafeExtPrecTempDenormalizer()
00257 {return two62() * BorrowBit(); };
00259
00260 static inline double QuickRoundAdjust() {return 0.5;};
00261 static inline double SafeRoundAdjust() {return 0.25;};
00262 static inline int SafeFinalShift() {return 1;};
00263
00264
00265 #ifdef VTK_WORDS_BIGENDIAN
00266 enum {exponent_pos = 0, mantissa_pos = 1};
00267 #else
00268 enum {exponent_pos = 1, mantissa_pos = 0};
00269 #endif
00270
00271
00272 public:
00273
00275
00286 void SetReservedFracBits(int bits)
00287 {
00288
00289
00290
00291 bits++;
00292 unsigned long mtime = this->GetMTime();
00293 this->SetinternalReservedFracBits(bits);
00294 if (mtime != this->GetMTime())
00295 {
00296 this->InternalRebuild();
00297 }
00298 };
00300
00304 void PerformanceTests(void);
00305
00306
00308
00325 inline static int QuickFloor(const double &val)
00326 {
00327 #ifdef VTK_USE_TRICK
00328 union { int i[2]; double d; } u;
00329 #ifdef VTK_EXT_PREC
00330 u.d = (((val - (QuickRoundAdjust() - RoundingTieBreaker()))
00331
00332 + QuickExtPrecTempDenormalizer())
00333
00334 - QuickExtPrecTempDenormalizer())
00335 + QuickFloorDenormalizer();
00336 #else // ! VTK_EXT_PREC
00337 u.d = (val - (QuickRoundAdjust() - RoundingTieBreaker()))
00338 + QuickFloorDenormalizer();
00339 #endif // VTK_EXT_PREC
00340 return u.i[mantissa_pos];
00341 #else // ! VTK_USE_TRICK
00342 return static_cast<int>(val);
00343 #endif // VTK_USE_TRICK
00344 }
00346
00348
00362 inline static int SafeFloor(const double &val)
00363 {
00364 #ifdef VTK_USE_TRICK
00365 union { int i[2]; double d; } u;
00366 #ifdef VTK_EXT_PREC
00367 u.d = (((val - SafeRoundAdjust())
00368 + SafeExtPrecTempDenormalizer())
00369 - SafeExtPrecTempDenormalizer())
00370 + SafeFloorDenormalizer();
00371 #else // ! VTK_EXT_PREC
00372 u.d = (val - SafeRoundAdjust())
00373 + SafeFloorDenormalizer();
00374 #endif // VTK_EXT_PREC
00375 return u.i[mantissa_pos] >> SafeFinalShift();
00376 #else // ! VTK_USE_TRICK
00377 return static_cast<int>(val);
00378 #endif // VTK_USE_TRICK
00379 }
00381
00383
00392 inline static int Round(const double &val)
00393 {
00394 #ifdef VTK_USE_TRICK
00395 union { int i[2]; double d; } u;
00396 #ifdef VTK_EXT_PREC
00397 u.d = ((val
00398 + QuickExtPrecTempDenormalizer())
00399 - QuickExtPrecTempDenormalizer())
00400 + QuickFloorDenormalizer();
00401 #else // ! VTK_EXT_PREC
00402 u.d = val
00403 + QuickFloorDenormalizer();
00404 #endif // VTK_EXT_PREC
00405 return u.i[mantissa_pos];
00406 #else // ! VTK_USE_TRICK
00407 if (val>=0)
00408 {
00409 return static_cast<int>(val + 0.5);
00410 }
00411 else
00412 {
00413 return static_cast<int>(val - 0.5);
00414 }
00415 #endif // VTK_USE_TRICK
00416 }
00418
00420
00423 inline int ConvertFixedPoint(const double &val, int &fracPart)
00424 {
00425 union { int i[2]; double d; } u;
00426 #ifdef VTK_EXT_PREC
00427 u.d = (((val - fixRound)
00428 + this->epTempDenormalizer)
00429 - this->epTempDenormalizer)
00430 + this->fpDenormalizer;
00431 #else // ! VTK_EXT_PREC
00432 u.d = (val - fixRound)
00433 + this->fpDenormalizer;
00434 #endif // VTK_EXT_PREC
00435 fracPart = (u.i[mantissa_pos] & fracMask) >> 1;
00436 return u.i[mantissa_pos] >> this->internalReservedFracBits;
00437 }
00438
00440
00441
00442 protected:
00443
00444 vtkFastNumericConversion()
00445 {
00446 #ifdef VTK_TEST_HACK_TO_EMULATE_LINUX_UNDER_WINDOWS
00447 _controlfp( _PC_64, MCW_PC );
00448 #endif
00449
00450 this->fixRound = 0;
00451 this->internalReservedFracBits = 0;
00452 this->fracMask = 0;
00453 this->fpDenormalizer = 0;
00454 this->bare_time = 0;
00455 this->cast_time = 0;
00456 this->convert_time = 0;
00457 this->quickfloor_time = 0;
00458 this->safefloor_time = 0;
00459 this->round_time = 0;
00460 this->InternalRebuild();
00461 };
00462 ~vtkFastNumericConversion() {};
00463 void InternalRebuild(void);
00464
00465 private:
00466 vtkSetMacro(internalReservedFracBits, int);
00467 vtkGetMacro(internalReservedFracBits, int);
00468 int internalReservedFracBits;
00469 int fracMask;
00470
00471
00472
00473
00474 double fpDenormalizer;
00475
00476
00477 double epTempDenormalizer;
00478
00479
00480
00481 double fixRound;
00482
00483 double bare_time;
00484 double cast_time;
00485 double convert_time;
00486 double quickfloor_time;
00487 double safefloor_time;
00488 double round_time;
00489
00490
00491 vtkFastNumericConversion(const vtkFastNumericConversion&);
00492 void operator=(const vtkFastNumericConversion&);
00493 };
00494
00495 #endif