HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
SYS_Floor.h
Go to the documentation of this file.
1 /*
2  * PROPRIETARY INFORMATION. This software is proprietary to
3  * Side Effects Software Inc., and is not to be reproduced,
4  * transmitted, or disclosed in any way without written permission.
5  *
6  * NAME: SYS_Floor (C++)
7  *
8  * COMMENTS: Fast floating point floor function (faster than floorf)
9  * There are two versions, a fast inline and a slower (but
10  * still faster than floorf) out-lined function.
11  *
12  */
13 
14 #ifndef __SYS_Floor_H__
15 #define __SYS_Floor_H__
16 
17 #include "SYS_API.h"
18 #include <math.h>
19 #include "SYS_Types.h"
20 
25 
26 /// @{
27 /// SYSniceNumber() will limit the precision of decimal digits, but leave the
28 /// integer portion of a number at full precision. Thus: @code
29 /// SYSniceNumber(1234.56, 2) == 1235; // (note the rounding)
30 /// SYSniceNumber(0.0123456, 2) == 0.012;
31 /// SYSniceNumber(1.23456e-14,2) == 1.2e-14;
32 /// @endcode
33 /// Note that 6 digits is almost enough to represent a single precision float.
34 SYS_API extern fpreal64 SYSniceNumber(fpreal64 num, int digits = 6);
35 static inline fpreal32 SYSniceNumber(fpreal32 num, int digits = 6)
36  { return (fpreal32)SYSniceNumber((fpreal64)num, digits);}
37 /// @}
38 
39 static inline fpreal64 SYSfloor(fpreal64 a) { return floor(a); }
40 static inline fpreal64 SYSceil(fpreal64 a) { return ceil(a); }
41 
42 /// Floor function that is incorrect for negative integers
43 /// @{
44 static constexpr int32
45 SYSfastFloor(fpreal32 a) { return a < 0 ? (int32)a - 1 : (int32)a; }
46 static constexpr int64
47 SYSfastFloor(fpreal64 a) { return a < 0 ? (int64)a - 1 : (int64)a; }
48 /// @}
49 
50 /// Ceiling function that is incorrect for positive integers
51 /// @{
52 static constexpr int32
53 SYSfastCeil(fpreal32 a) { return a <= 0 ? (int32)a : (int32)a + 1; }
54 static constexpr int64
55 SYSfastCeil(fpreal64 a) { return a <= 0 ? (int64)a : (int64)a + 1; }
56 /// @}
57 
58 inline fpreal32
60 {
61  SYS_FPRealUnionF tmp;
62  unsigned int shift;
63 
64  tmp.fval = val;
65  shift = (tmp.uval >> 23) & 0xff;
66 
67  if (shift < 0x7f)
68  {
69  tmp.fval = (tmp.uval > 0x80000000) ? -1.0F : 0.0F;
70  }
71  else if (shift < 0x96)
72  {
73  unsigned mask = 0xffffffff << (0x96 - shift);
74  if (tmp.uval & 0x80000000)
75  {
76  if ((tmp.uval & ~mask) & 0x7fffff)
77  {
78  tmp.uval &= mask;
79  tmp.fval--;
80  }
81  }
82  else tmp.uval &= mask;
83  }
84  return tmp.fval;
85 }
86 
87 inline fpreal64 SYSfloorIL(fpreal64 val) { return SYSfloor(val); }
88 inline fpreal32 SYSceilIL(fpreal32 val) { return SYSceil(val); }
89 inline fpreal64 SYSceilIL(fpreal64 val) { return SYSceil(val); }
90 
91 template <typename T, typename S>
92 static inline void
93 SYSsplitFloatT(T &val, S &ival)
94 {
95  val += 1; // Deal with numbers between (-1, 1)
96  T fval = SYSfloorIL(val);
97  ival = ((S)fval) - 1;
98  val = val - fval;
99 }
100 
101 //
102 // The following function splits a floating point value into its fractional and
103 // integer components. The integer returned is the floor() of the fractional
104 // value, while the fractional component is guaranteed to always be in the
105 // range [0, 1). This is different from (val - floor(val)) which can cause
106 // problems if the value is very close to -0.
107 //
108 static inline void SYSsplitFloat(fpreal32 &val, int32 &ival)
109  { SYSsplitFloatT(val, ival); }
110 static inline void SYSsplitFloat(fpreal32 &val, int64 &ival)
111  { SYSsplitFloatT(val, ival); }
112 static inline void SYSsplitFloat(fpreal32 &val, fpreal32 &ival)
113  { SYSsplitFloatT(val, ival); }
114 static inline void SYSsplitFloat(fpreal32 &val, fpreal64 &ival)
115  { SYSsplitFloatT(val, ival); }
116 static inline void SYSsplitFloat(fpreal64 &val, int32 &ival)
117  { SYSsplitFloatT(val, ival); }
118 static inline void SYSsplitFloat(fpreal64 &val, int64 &ival)
119  { SYSsplitFloatT(val, ival); }
120 static inline void SYSsplitFloat(fpreal64 &val, fpreal32 &ival)
121  { SYSsplitFloatT(val, ival); }
122 static inline void SYSsplitFloat(fpreal64 &val, fpreal64 &ival)
123  { SYSsplitFloatT(val, ival); }
124 
125 // fastSplitFloat() is not as correct as the above code. Using the fast
126 // version, you can get somewhat unexpected results. However, in many cases,
127 // it's quite acceptable to get these results.
128 // a) Denormalization of -ve values close to zero (i.e. -1e-10) will result
129 // in the fractional value being 1.0 exactly and the integer value = -1
130 template <typename REAL_TYPE, typename INT_TYPE>
131 static inline void
132 SYSfastSplitFloat(REAL_TYPE &val, INT_TYPE &ival)
133 {
134  ival = SYSfastFloor(val);
135  val -= REAL_TYPE(ival);
136 }
137 
138 inline fpreal32
140 {
141  // On Intel chips, val may be a double precision register value. In this
142  // case, a small value less than zero will cause the fractional result to
143  // be outside the range [0-1), which is obviously invalid. Thus, we have
144  // to have special code to handle this case properly. On non-intel chips,
145  // which support floating point operations, we can simply de-normalize the
146  // value and return the fractional component properly.
147 #if defined(WIN32) || defined(LINUX)
148  val = val - SYSfloorIL(val);
149  return (val < 0 || val >= 1) ? 0 : val;
150 #else
151  val += 1; // Normalize fpreal32 first
152  return val - SYSfloorIL(val);
153 #endif
154 }
155 
156 inline fpreal64
158 {
159  return SYSfrac(val);
160 }
161 
162 inline fpreal32
164 {
165  return SYSfloorIL(val + 0.5F);
166 }
167 
168 inline fpreal64
170 {
171  return SYSfloor(val + 0.5);
172 }
173 
174 
175 #endif
int int32
Definition: SYS_Types.h:39
fpreal32 SYSfracIL(fpreal32 val)
Definition: SYS_Floor.h:139
IMATH_HOSTDEVICE constexpr int floor(T x) IMATH_NOEXCEPT
Definition: ImathFun.h:112
GLboolean GLboolean GLboolean GLboolean a
Definition: glcorearb.h:1222
SYS_API fpreal64 SYSniceNumber(fpreal64 num, int digits=6)
float fpreal32
Definition: SYS_Types.h:200
double fpreal64
Definition: SYS_Types.h:201
SYS_API fpreal32 SYSfrac(fpreal32 val)
fpreal32 SYSceilIL(fpreal32 val)
Definition: SYS_Floor.h:88
GLint GLuint mask
Definition: glcorearb.h:124
long long int64
Definition: SYS_Types.h:116
SYS_API fpreal32 SYSfloor(fpreal32 val)
fpreal32 SYSrint(fpreal32 val)
Definition: SYS_Floor.h:163
IMATH_HOSTDEVICE constexpr int ceil(T x) IMATH_NOEXCEPT
Definition: ImathFun.h:119
GLuint GLfloat * val
Definition: glcorearb.h:1608
#define SYS_API
Definition: SYS_API.h:11
fpreal32 SYSfloorIL(fpreal32 val)
Definition: SYS_Floor.h:59
SYS_API fpreal32 SYSceil(fpreal32 val)