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
00116 static inline double two30() { return (double)(((unsigned long)1) << 30); };
00117
00119
00121 static inline double two52()
00122 { return (((unsigned long)1) << (52-30)) * two30(); };
00124
00126
00131 static inline double two51()
00132 { return (((unsigned long)1) << (51-30)) * two30(); };
00134
00136
00139 static inline double two63()
00140 { return (((unsigned long)1) << (63-60)) * two30() * two30();};
00142
00144
00147 static inline double two62()
00148 { return (((unsigned long)1) << (62-60)) * two30() * two30();};
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161 #define INT_BITS 30
00162 #define EXT_BITS 64
00163 #define DBL_BITS 53
00164
00193 public:
00194 #ifdef VTK_EXT_PREC
00195
00196 static inline double RoundingTieBreaker() {return 1.0 / (two30() * (((unsigned long)1) << (EXT_BITS - INT_BITS - 30))); };
00197 #else
00198
00199 static inline double RoundingTieBreaker() { return 1.0 / (((unsigned long)1) << (DBL_BITS - INT_BITS)); };
00200 #endif
00201
00202 protected:
00204
00208 static inline double QuickFloorDenormalizer()
00209 {return two52() * BorrowBit(); };
00211
00213
00218 static inline double SafeFloorDenormalizer()
00219 { return two51() * BorrowBit(); };
00221
00223
00226 static inline double QuickExtPrecTempDenormalizer()
00227 {return two63() * BorrowBit(); };
00229
00231
00234 static inline double SafeExtPrecTempDenormalizer()
00235 {return two62() * BorrowBit(); };
00237
00238 static inline double QuickRoundAdjust() {return 0.5;};
00239 static inline double SafeRoundAdjust() {return 0.25;};
00240 static inline int SafeFinalShift() {return 1;};
00241
00242
00243 #ifdef VTK_WORDS_BIGENDIAN
00244 enum {exponent_pos = 0, mantissa_pos = 1};
00245 #else
00246 enum {exponent_pos = 1, mantissa_pos = 0};
00247 #endif
00248
00249
00250 public:
00251
00253
00264 void SetReservedFracBits(int bits)
00265 {
00266
00267
00268
00269 bits++;
00270 unsigned long mtime = this->GetMTime();
00271 this->SetinternalReservedFracBits(bits);
00272 if (mtime != this->GetMTime())
00273 {
00274 this->InternalRebuild();
00275 }
00276 };
00278
00282 void PerformanceTests(void);
00283
00284
00286
00303 inline static int QuickFloor(const double &val)
00304 {
00305 #ifdef VTK_USE_TRICK
00306 double tempval;
00307 #ifdef VTK_EXT_PREC
00308 tempval = (((val - (QuickRoundAdjust() - RoundingTieBreaker()))
00309 + QuickExtPrecTempDenormalizer())
00310 - QuickExtPrecTempDenormalizer())
00311 + QuickFloorDenormalizer();
00312 #else // ! VTK_EXT_PREC
00313 tempval = (val - (QuickRoundAdjust() - RoundingTieBreaker()))
00314 + QuickFloorDenormalizer();
00315 #endif // VTK_EXT_PREC
00316 return ((int*)&tempval)[mantissa_pos];
00317 #else // ! VTK_USE_TRICK
00318 return (int) val;
00319 #endif // VTK_USE_TRICK
00320 }
00322
00324
00338 inline static int SafeFloor(const double &val)
00339 {
00340 #ifdef VTK_USE_TRICK
00341 double tempval;
00342 #ifdef VTK_EXT_PREC
00343 tempval = (((val - SafeRoundAdjust())
00344 + SafeExtPrecTempDenormalizer())
00345 - SafeExtPrecTempDenormalizer())
00346 + SafeFloorDenormalizer();
00347 #else // ! VTK_EXT_PREC
00348 tempval = (val - SafeRoundAdjust())
00349 + SafeFloorDenormalizer();
00350 #endif // VTK_EXT_PREC
00351 return ((int*)&tempval)[mantissa_pos] >> SafeFinalShift();
00352 #else // ! VTK_USE_TRICK
00353 return (int) val;
00354 #endif // VTK_USE_TRICK
00355 }
00357
00359
00368 inline static int Round(const double &val)
00369 {
00370 #ifdef VTK_USE_TRICK
00371 double tempval;
00372 #ifdef VTK_EXT_PREC
00373 tempval = ((val
00374 + QuickExtPrecTempDenormalizer())
00375 - QuickExtPrecTempDenormalizer())
00376 + QuickFloorDenormalizer();
00377 #else // ! VTK_EXT_PREC
00378 tempval = val
00379 + QuickFloorDenormalizer();
00380 #endif // VTK_EXT_PREC
00381 return ((int*)&tempval)[mantissa_pos];
00382 #else // ! VTK_USE_TRICK
00383 if (val>=0)
00384 {
00385 return (int) (val + 0.5);
00386 }
00387 else
00388 {
00389 return (int) (val - 0.5);
00390 }
00391 #endif // VTK_USE_TRICK
00392 }
00394
00396
00399 inline int ConvertFixedPoint(const double &val, int &fracPart)
00400 {
00401 double tempval;
00402 #ifdef VTK_EXT_PREC
00403 tempval = (((val - fixRound)
00404 + this->epTempDenormalizer)
00405 - this->epTempDenormalizer)
00406 + this->fpDenormalizer;
00407 #else
00408 tempval = (val - fixRound)
00409 + this->fpDenormalizer;
00410 #endif // VTK_EXT_PREC
00411 fracPart = (((int*)&tempval)[mantissa_pos] & fracMask) >> 1;
00412 return ((int*)&tempval)[mantissa_pos] >> this->internalReservedFracBits;
00413 }
00414
00416
00417
00418 protected:
00419
00420 vtkFastNumericConversion()
00421 {
00422 #ifdef VTK_TEST_HACK_TO_EMULATE_LINUX_UNDER_WINDOWS
00423 _controlfp( _PC_64, MCW_PC );
00424 #endif
00425
00426 this->fixRound = 0;
00427 this->internalReservedFracBits = 0;
00428 this->fracMask = 0;
00429 this->fpDenormalizer = 0;
00430 this->bare_time = 0;
00431 this->cast_time = 0;
00432 this->convert_time = 0;
00433 this->quickfloor_time = 0;
00434 this->safefloor_time = 0;
00435 this->round_time = 0;
00436 this->InternalRebuild();
00437 };
00438 ~vtkFastNumericConversion() {};
00439 void InternalRebuild(void);
00440
00441 private:
00442 vtkSetMacro(internalReservedFracBits, int);
00443 vtkGetMacro(internalReservedFracBits, int);
00444 int internalReservedFracBits;
00445 int fracMask;
00446
00447
00448
00449
00450 double fpDenormalizer;
00451
00452
00453 double epTempDenormalizer;
00454
00455
00456
00457 double fixRound;
00458
00459 double bare_time;
00460 double cast_time;
00461 double convert_time;
00462 double quickfloor_time;
00463 double safefloor_time;
00464 double round_time;
00465
00466
00467 vtkFastNumericConversion(const vtkFastNumericConversion&);
00468 void operator=(const vtkFastNumericConversion&);
00469 };
00470
00471 #endif