VTK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
vtkFastNumericConversion.h
Go to the documentation of this file.
1 /*=========================================================================
2 
3  Program: Visualization Toolkit
4  Module: vtkFastNumericConversion.h
5 
6  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
7  All rights reserved.
8  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
9 
10  This software is distributed WITHOUT ANY WARRANTY; without even
11  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
12  PURPOSE. See the above copyright notice for more information.
13 
14 =========================================================================*/
52 #ifndef __vtkFastNumericConversion_h
53 #define __vtkFastNumericConversion_h
54 
55 #include "vtkCommonMathModule.h" // For export macro
56 #include "vtkObject.h"
57 
58 // Use the bit-representation trick only on X86, and only when producing
59 // optimized code
60 #if defined(NDEBUG) && (defined i386 || defined _M_IX86)
61 #define VTK_USE_TRICK
62 #endif
63 
64 // Linux puts the FPU in extended precision. Windows and FreeBSD keep it in
65 // double precision. If other operating systems for i386 (Solaris?) behave
66 // like Linux, add them below. Special care needs to be taken when dealing
67 // with extended precision mode because even though we are eventually writing
68 // out to a double-precision variable to capture the fixed-point or integer
69 // results, the extra bits maintained in the internal computations disrupt
70 // the bit-playing that we're doing here.
71 #if defined(__linux__)
72 #define VTK_EXT_PREC
73 #endif
74 
75 //#define VTK_TEST_HACK_TO_EMULATE_LINUX_UNDER_WINDOWS
76 #ifdef VTK_TEST_HACK_TO_EMULATE_LINUX_UNDER_WINDOWS
77 #define VTK_EXT_PREC
78 #endif
79 
80 
82 {
83 public:
84  static vtkFastNumericConversion *New();
86  void PrintSelf(ostream& os, vtkIndent indent);
87 
88  int TestQuickFloor(double val)
89  {
91  }
92 
93  int TestSafeFloor(double val)
94  {
96  }
97 
98  int TestRound(double val)
99  {
101  }
102 
104  {
105  int frac;
106  return ConvertFixedPoint(val, frac);
107  }
108 
110  {
111  int frac;
112  ConvertFixedPoint(val, frac);
113  return frac;
114  }
115 
116 protected:
117  //BTX
123  static inline double BorrowBit() { return 1.5;};
124 
126 
129  static inline double two30()
130  {
131  return static_cast<double>(static_cast<unsigned long>(1) << 30);
132  }
134 
136 
138  static inline double two52()
139  {
140  return (static_cast<unsigned long>(1) << (52-30)) * two30();
141  }
143 
145 
150  static inline double two51()
151  {
152  return (static_cast<unsigned long>(1) << (51-30)) * two30();
153  }
155 
157 
160  static inline double two63()
161  {
162  return (static_cast<unsigned long>(1) << (63-60)) * two30() * two30();
163  }
165 
167 
170  static inline double two62()
171  {
172  return (static_cast<unsigned long>(1) << (62-60)) * two30() * two30();
173  }
175 
176  // Define number of bits of precision for various data types.
177  // Note: INT_BITS is really 31, (rather than 32, since one of the bits is
178  // just used for the two's-complement sign), but we say 30 because we don't
179  // need to be able to handle 31-bit magnitudes correctly. I say that
180  // because this is used for the QuickFloor code, and the SafeFloor code
181  // retains an extra bit of fixed point precision which it shifts-out at the
182  // end, thus reducing the magnitude of integers that it can handle. That's
183  // an inherent limitation of using SafeFloor to prevent round-ups under any
184  // circumstances, and there's no need to make QuickFloor handle a wider
185  // range of numbers than SafeFloor.
186 #define INT_BITS 30
187 #define EXT_BITS 64
188 #define DBL_BITS 53
189 
191 
219 public:
220 #ifdef VTK_EXT_PREC
221  // Compute (0.5 ^ (EXT_BITS-INT_BITS)) as a compile-time constant
222  static inline double RoundingTieBreaker()
223  {
224  return 1.0 / (two30() * (static_cast<unsigned long>(1) << (EXT_BITS - INT_BITS - 30)));
225  }
226 #else
227  // Compute (0.5 ^ (DBL_BITS-INT_BITS)) as a compile-time constant
228  static inline double RoundingTieBreaker()
229  {
230  return 1.0 / (static_cast<unsigned long>(1) << (DBL_BITS - INT_BITS));
231  }
232 #endif
233 
234 
235 protected:
237 
241  static inline double QuickFloorDenormalizer()
242  {return two52() * BorrowBit(); };
244 
246 
251  static inline double SafeFloorDenormalizer()
252  { return two51() * BorrowBit(); };
254 
256 
259  static inline double QuickExtPrecTempDenormalizer()
260  {return two63() * BorrowBit(); };
262 
264 
267  static inline double SafeExtPrecTempDenormalizer()
268  {return two62() * BorrowBit(); };
270 
271  static inline double QuickRoundAdjust() {return 0.5;};
272  static inline double SafeRoundAdjust() {return 0.25;};
273  static inline int SafeFinalShift() {return 1;};
274 
275 
276 #ifdef VTK_WORDS_BIGENDIAN
277  enum {exponent_pos = 0, mantissa_pos = 1};
278 #else
279  enum {exponent_pos = 1, mantissa_pos = 0};
280 #endif
281  //ETX
282 
283 public:
284 
286 
298  {
299  // Add one to the requested number of fractional bits, to make
300  // the conversion safe with respect to rounding mode. This is the
301  // same as the difference between QuickFloor and SafeFloor.
302  bits++;
303  unsigned long mtime = this->GetMTime();
304  this->SetinternalReservedFracBits(bits);
305  if (mtime != this->GetMTime())
306  {
307  this->InternalRebuild();
308  }
309  };
311 
312  //BTX
330  static int QuickFloor(const double &val);
331 
346  static int SafeFloor(const double &val);
347 
357  static int Round(const double &val);
358 
360 
363  inline int ConvertFixedPoint(const double &val, int &fracPart)
364  {
365  union { int i[2]; double d; } u;
366 #ifdef VTK_EXT_PREC
367  u.d = (((val - fixRound)
368  + this->epTempDenormalizer)
369  - this->epTempDenormalizer)
370  + this->fpDenormalizer;
371 #else // ! VTK_EXT_PREC
372  u.d = (val - fixRound)
373  + this->fpDenormalizer;
374 #endif // VTK_EXT_PREC
375  fracPart = (u.i[mantissa_pos] & fracMask) >> 1;
376  return u.i[mantissa_pos] >> this->internalReservedFracBits;
377  }
378  //ETX
380 
381 
382 protected:
383  //BTX
386  void InternalRebuild(void);
387 
388 private:
389  vtkSetMacro(internalReservedFracBits, int);
390  vtkGetMacro(internalReservedFracBits, int);
391 
392 #ifndef VTK_LEGACY_SILENT
393  static int QuickFloorInline(const double &val);
394  static int SafeFloorInline(const double &val);
395  static int RoundInline(const double &val);
396 #endif
397 
398  int internalReservedFracBits;
399  int fracMask;
400 
401  // Used when doing fixed point conversions with a certain number of bits
402  // remaining for the fractional part, as opposed to the pure integer
403  // flooring
404  double fpDenormalizer;
405 
406  // Used when doing fixed point conversions in extended precision mode
407  double epTempDenormalizer;
408 
409  // Adjustment for rounding based on the number of bits reserved for
410  // fractional representation
411  double fixRound;
412  //ETX
413 
414  vtkFastNumericConversion(const vtkFastNumericConversion&); // Not implemented
415  void operator=(const vtkFastNumericConversion&); // Not implemented
416 };
417 
418 #ifndef VTK_LEGACY_SILENT
419 inline int vtkFastNumericConversion::QuickFloorInline(const double &val)
420 #else
421 inline int vtkFastNumericConversion::QuickFloor(const double &val)
422 #endif
423 {
424 #ifdef VTK_USE_TRICK
425  union { int i[2]; double d; } u;
426 #ifdef VTK_EXT_PREC
427  u.d = (((val - (QuickRoundAdjust() - RoundingTieBreaker()))
428  // Push off those extended precision bits
429  + QuickExtPrecTempDenormalizer())
430  // Pull back the wanted bits into double range
431  - QuickExtPrecTempDenormalizer())
432  + QuickFloorDenormalizer();
433 #else // ! VTK_EXT_PREC
434  u.d = (val - (QuickRoundAdjust() - RoundingTieBreaker()))
435  + QuickFloorDenormalizer();
436 #endif // VTK_EXT_PREC
437  return u.i[mantissa_pos];
438 #else // ! VTK_USE_TRICK
439  return static_cast<int>(val);
440 #endif // VTK_USE_TRICK
441 }
442 
443 #ifndef VTK_LEGACY_SILENT
444 inline int vtkFastNumericConversion::SafeFloorInline(const double &val)
445 #else
446 inline int vtkFastNumericConversion::SafeFloor(const double &val)
447 #endif
448 {
449 #ifdef VTK_USE_TRICK
450  union { int i[2]; double d; } u;
451 #ifdef VTK_EXT_PREC
452  u.d = (((val - SafeRoundAdjust())
453  + SafeExtPrecTempDenormalizer())
454  - SafeExtPrecTempDenormalizer())
455  + SafeFloorDenormalizer();
456 #else // ! VTK_EXT_PREC
457  u.d = (val - SafeRoundAdjust())
458  + SafeFloorDenormalizer();
459 #endif // VTK_EXT_PREC
460  return u.i[mantissa_pos] >> SafeFinalShift();
461 #else // ! VTK_USE_TRICK
462  return static_cast<int>(val);
463 #endif // VTK_USE_TRICK
464 }
465 
466 #ifndef VTK_LEGACY_SILENT
467 inline int vtkFastNumericConversion::RoundInline(const double &val)
468 #else
469 inline int vtkFastNumericConversion::Round(const double &val)
470 #endif
471 {
472 #ifdef VTK_USE_TRICK
473  union { int i[2]; double d; } u;
474 #ifdef VTK_EXT_PREC
475  u.d = ((val
476  + QuickExtPrecTempDenormalizer())
477  - QuickExtPrecTempDenormalizer())
478  + QuickFloorDenormalizer();
479 #else // ! VTK_EXT_PREC
480  u.d = val
481  + QuickFloorDenormalizer();
482 #endif // VTK_EXT_PREC
483 return u.i[mantissa_pos];
484 #else // ! VTK_USE_TRICK
485 if (val>=0)
486  {
487  return static_cast<int>(val + 0.5);
488  }
489 else
490  {
491  return static_cast<int>(val - 0.5);
492  }
493 #endif // VTK_USE_TRICK
494 }
495 
496 #endif
static int QuickFloor(const double &val)
int TestConvertFixedPointFracPart(double val)
abstract base class for most VTK objects
Definition: vtkObject.h:61
int TestConvertFixedPointIntPart(double val)
virtual void PrintSelf(ostream &os, vtkIndent indent)
virtual unsigned long GetMTime()
GLenum GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * bits
Definition: vtkgl.h:18250
a simple class to control print indentation
Definition: vtkIndent.h:38
#define INT_BITS
Enables fast conversion of floating point to fixed point.
#define DBL_BITS
static int SafeFloor(const double &val)
int ConvertFixedPoint(const double &val, int &fracPart)
static double QuickExtPrecTempDenormalizer()
#define EXT_BITS
static int Round(const double &val)
static vtkObject * New()
GLuint GLfloat * val
Definition: vtkgl.h:13789
#define VTKCOMMONMATH_EXPORT