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 union { int i[2]; double d; } u;
00307 #ifdef VTK_EXT_PREC
00308 u.d = (((val - (QuickRoundAdjust() - RoundingTieBreaker()))
00309
00310 + QuickExtPrecTempDenormalizer())
00311
00312 - QuickExtPrecTempDenormalizer())
00313 + QuickFloorDenormalizer();
00314 #else // ! VTK_EXT_PREC
00315 u.d = (val - (QuickRoundAdjust() - RoundingTieBreaker()))
00316 + QuickFloorDenormalizer();
00317 #endif // VTK_EXT_PREC
00318 return u.i[mantissa_pos];
00319 #else // ! VTK_USE_TRICK
00320 return (int) val;
00321 #endif // VTK_USE_TRICK
00322 }
00324
00326
00340 inline static int SafeFloor(const double &val)
00341 {
00342 #ifdef VTK_USE_TRICK
00343 union { int i[2]; double d; } u;
00344 #ifdef VTK_EXT_PREC
00345 u.d = (((val - SafeRoundAdjust())
00346 + SafeExtPrecTempDenormalizer())
00347 - SafeExtPrecTempDenormalizer())
00348 + SafeFloorDenormalizer();
00349 #else // ! VTK_EXT_PREC
00350 u.d = (val - SafeRoundAdjust())
00351 + SafeFloorDenormalizer();
00352 #endif // VTK_EXT_PREC
00353 return u.i[mantissa_pos] >> SafeFinalShift();
00354 #else // ! VTK_USE_TRICK
00355 return (int) val;
00356 #endif // VTK_USE_TRICK
00357 }
00359
00361
00370 inline static int Round(const double &val)
00371 {
00372 #ifdef VTK_USE_TRICK
00373 union { int i[2]; double d; } u;
00374 #ifdef VTK_EXT_PREC
00375 u.d = ((val
00376 + QuickExtPrecTempDenormalizer())
00377 - QuickExtPrecTempDenormalizer())
00378 + QuickFloorDenormalizer();
00379 #else // ! VTK_EXT_PREC
00380 u.d = val
00381 + QuickFloorDenormalizer();
00382 #endif // VTK_EXT_PREC
00383 return u.i[mantissa_pos];
00384 #else // ! VTK_USE_TRICK
00385 if (val>=0)
00386 {
00387 return (int) (val + 0.5);
00388 }
00389 else
00390 {
00391 return (int) (val - 0.5);
00392 }
00393 #endif // VTK_USE_TRICK
00394 }
00396
00398
00401 inline int ConvertFixedPoint(const double &val, int &fracPart)
00402 {
00403 union { int i[2]; double d; } u;
00404 #ifdef VTK_EXT_PREC
00405 u.d = (((val - fixRound)
00406 + this->epTempDenormalizer)
00407 - this->epTempDenormalizer)
00408 + this->fpDenormalizer;
00409 #else // ! VTK_EXT_PREC
00410 u.d = (val - fixRound)
00411 + this->fpDenormalizer;
00412 #endif // VTK_EXT_PREC
00413 fracPart = (u.i[mantissa_pos] & fracMask) >> 1;
00414 return u.i[mantissa_pos] >> this->internalReservedFracBits;
00415 }
00416
00418
00419
00420 protected:
00421
00422 vtkFastNumericConversion()
00423 {
00424 #ifdef VTK_TEST_HACK_TO_EMULATE_LINUX_UNDER_WINDOWS
00425 _controlfp( _PC_64, MCW_PC );
00426 #endif
00427
00428 this->fixRound = 0;
00429 this->internalReservedFracBits = 0;
00430 this->fracMask = 0;
00431 this->fpDenormalizer = 0;
00432 this->bare_time = 0;
00433 this->cast_time = 0;
00434 this->convert_time = 0;
00435 this->quickfloor_time = 0;
00436 this->safefloor_time = 0;
00437 this->round_time = 0;
00438 this->InternalRebuild();
00439 };
00440 ~vtkFastNumericConversion() {};
00441 void InternalRebuild(void);
00442
00443 private:
00444 vtkSetMacro(internalReservedFracBits, int);
00445 vtkGetMacro(internalReservedFracBits, int);
00446 int internalReservedFracBits;
00447 int fracMask;
00448
00449
00450
00451
00452 double fpDenormalizer;
00453
00454
00455 double epTempDenormalizer;
00456
00457
00458
00459 double fixRound;
00460
00461 double bare_time;
00462 double cast_time;
00463 double convert_time;
00464 double quickfloor_time;
00465 double safefloor_time;
00466 double round_time;
00467
00468
00469 vtkFastNumericConversion(const vtkFastNumericConversion&);
00470 void operator=(const vtkFastNumericConversion&);
00471 };
00472
00473 #endif