Panda3D
cmath.I
Go to the documentation of this file.
1 /**
2  * PANDA 3D SOFTWARE
3  * Copyright (c) Carnegie Mellon University. All rights reserved.
4  *
5  * All use of this software is subject to the terms of the revised BSD
6  * license. You should have received a copy of this license along
7  * with this source code in a file named "LICENSE."
8  *
9  * @file cmath.I
10  * @author drose
11  * @date 2000-05-19
12  */
13 
14 #ifdef __INTEL_COMPILER
15 // see float.h
16 #define FPU_CONTROLWORD_WRITEMASK 0xFFFFF // if you look at defn of _CW_DEFAULT, all settings fall within 0xFFFFF
17 #define FPU_CONTROLWORD_NEW_SETTING _CW_DEFAULT
18 #endif
19 
20 /**
21  *
22  */
23 INLINE float
24 csqrt(float v) {
25  return sqrtf(v);
26 }
27 
28 /**
29  *
30  */
31 INLINE float
32 csin(float v) {
33  return sinf(v);
34 }
35 
36 /**
37  *
38  */
39 INLINE float
40 ccos(float v) {
41  return cosf(v);
42 }
43 
44 /**
45  *
46  */
47 INLINE float ctan(float v) {
48  return tanf(v);
49 }
50 
51 /**
52  *
53  */
54 INLINE void
55 csincos(float v, float *sin_result, float *cos_result) {
56  // MS VC defines _M_IX86 for x86. gcc should define _X86_
57 #if defined(_M_IX86) || defined(_X86_)
58  // #define fsincos_opcode __asm _emit 0xd9 __asm _emit 0xfb
59  __asm {
60  mov eax, sin_result
61  mov edx, cos_result
62  fld v
63  fsincos
64  fstp DWORD ptr [edx]
65  fstp DWORD ptr [eax]
66  }
67 #else //!_X86_
68  *sin_result = sinf(v);
69  *cos_result = cosf(v);
70 #endif //!_X86_
71 }
72 
73 /**
74  * Computes sin(x) / x, well-behaved as x approaches 0.
75  */
76 INLINE float
77 csin_over_x(float v) {
78  if (1.0f + v * v == 1.0f) {
79  return 1.0f;
80  } else {
81  return csin(v) / v;
82  }
83 }
84 
85 /**
86  *
87  */
88 INLINE float
89 cabs(float v) {
90  return fabs(v);
91 }
92 
93 /**
94  *
95  */
96 INLINE float
97 catan(float v) {
98  return atanf(v);
99 }
100 
101 /**
102  *
103  */
104 INLINE float
105 catan2(float y, float x) {
106  return atan2f(y, x);
107 }
108 
109 /**
110  *
111  */
112 INLINE float
113 casin(float v) {
114  return asinf(v);
115 }
116 
117 /**
118  *
119  */
120 INLINE float
121 cacos(float v) {
122  return acosf(v);
123 }
124 
125 /**
126  * This is similar to fmod(), but it behaves properly when x is negative: that
127  * is, it always returns a value in the range [0, y), assuming y is positive.
128  */
129 INLINE float
130 cmod(float x, float y) {
131  return x - floor(x / y) * y;
132 }
133 
134 /**
135  *
136  */
137 INLINE float
138 cpow(float x, float y) {
139  return powf(x, y);
140 }
141 
142 
143 /**
144  *
145  */
146 INLINE double
147 cfloor(double f) {
148  #ifdef __INTEL_COMPILER
149  // intel floor doesnt work right if fpu mode is not double, so make
150  // double-prec mode is on
151  unsigned int saved_fpu_control_word=_controlfp(0x0,0x0);
152  _controlfp(FPU_CONTROLWORD_NEW_SETTING,FPU_CONTROLWORD_WRITEMASK);
153  double retval=floor(f);
154  _controlfp(saved_fpu_control_word,FPU_CONTROLWORD_WRITEMASK);
155  return retval;
156  #else
157  return floor(f);
158  #endif
159 }
160 
161 /**
162  *
163  */
164 INLINE double
165 cceil(double f) {
166  #ifdef __INTEL_COMPILER
167  // intel ceil doesnt work right if fpu mode is not double, so make double-
168  // prec mode is on
169  unsigned int saved_fpu_control_word=_controlfp(0x0,0x0);
170  _controlfp(FPU_CONTROLWORD_NEW_SETTING,FPU_CONTROLWORD_WRITEMASK);
171  double retval=ceil(f);
172  _controlfp(saved_fpu_control_word,FPU_CONTROLWORD_WRITEMASK);
173  return retval;
174  #else
175  return ceil(f);
176  #endif
177 }
178 
179 /**
180  * Returns the fractional component of f: f - cfloor(f).
181  */
182 INLINE double
183 cfrac(double f) {
184  return f - cfloor(f);
185 }
186 
187 /**
188  *
189  */
190 INLINE double
191 csqrt(double v) {
192  return sqrt(v);
193 }
194 
195 /**
196  *
197  */
198 INLINE double
199 csin(double v) {
200  return sin(v);
201 }
202 
203 /**
204  *
205  */
206 INLINE double
207 ccos(double v) {
208  return cos(v);
209 }
210 
211 /**
212  *
213  */
214 INLINE double
215 ctan(double v) {
216  return tan(v);
217 }
218 
219 /**
220  *
221  */
222 INLINE void
223 csincos(double v, double *sin_result, double *cos_result) {
224 #if defined(_M_IX86) || defined(_X86_)
225  // #define fsincos_opcode __asm _emit 0xd9 __asm _emit 0xfb
226  __asm {
227  mov eax, sin_result
228  mov edx, cos_result
229  fld v
230  fsincos
231  fstp QWORD ptr [edx]
232  fstp QWORD ptr [eax]
233  }
234 #else //!_X86_
235  *sin_result = sin(v);
236  *cos_result = cos(v);
237 #endif //!_X86_
238 }
239 
240 /**
241  * Computes sin(x) / x, well-behaved as x approaches 0.
242  */
243 INLINE double
244 csin_over_x(double v) {
245  if (1.0 + v * v == 1.0) {
246  return 1.0;
247  } else {
248  return csin(v) / v;
249  }
250 }
251 
252 /**
253  *
254  */
255 INLINE double
256 cabs(double v) {
257  return fabs(v);
258 }
259 
260 /**
261  *
262  */
263 INLINE double
264 catan(double v) {
265  return atan(v);
266 }
267 
268 /**
269  *
270  */
271 INLINE double
272 catan2(double y, double x) {
273  return atan2(y, x);
274 }
275 
276 /**
277  *
278  */
279 INLINE double
280 casin(double v) {
281  return asin(v);
282 }
283 
284 /**
285  *
286  */
287 INLINE double
288 cacos(double v) {
289  return acos(v);
290 }
291 
292 /**
293  * This is similar to fmod(), but it behaves properly when x is negative: that
294  * is, it always returns a value in the range [0, y), assuming y is positive.
295  */
296 INLINE double
297 cmod(double x, double y) {
298  return x - cfloor(x / y) * y;
299 }
300 
301 /**
302  *
303  */
304 INLINE double
305 cpow(double x, double y) {
306  return pow(x, y);
307 }
308 
309 /**
310  *
311  */
312 INLINE int
313 cpow(int x, int y) {
314  int result = 1;
315 
316  if (y >= 0) {
317  for(; y > 0; --y) {
318  result *= x;
319  }
320  return result;
321 
322  } else {
323  for(; y < 0; ++y) {
324  result *= x;
325  }
326  return 1 / result;
327  }
328 }
329 
330 /**
331  *
332  */
333 INLINE bool
334 cnan(float v) {
335 #if __FINITE_MATH_ONLY__
336  // GCC's isnan breaks when using -ffast-math.
337  union { float f; uint32_t x; } u = { v };
338  return ((u.x << 1) > 0xff000000u);
339 #elif !defined(_WIN32)
340  return std::isnan(v);
341 #else
342  return (_isnan(v) != 0);
343 #endif
344 }
345 
346 /**
347  *
348  */
349 INLINE bool
350 cnan(double v) {
351 #if __FINITE_MATH_ONLY__
352  // GCC's isnan breaks when using -ffast-math.
353  union { double d; uint64_t x; } u = { v };
354  return ((u.x << 1) > 0xff70000000000000ull);
355 #elif !defined(_WIN32)
356  return std::isnan(v);
357 #else
358  return (_isnan(v) != 0);
359 #endif
360 }
361 
362 /**
363  *
364  */
365 INLINE bool
366 cinf(float v) {
367 #if __FINITE_MATH_ONLY__
368  // GCC's isinf breaks when using -ffast-math.
369  union { float f; uint32_t x; } u = { v };
370  return ((u.x << 1) == 0xff000000u);
371 #elif !defined(_WIN32)
372  return std::isinf(v);
373 #else
374  return (_isnan(v) == 0 && _finite(v) == 0);
375 #endif
376 }
377 
378 /**
379  *
380  */
381 INLINE bool
382 cinf(double v) {
383 #if __FINITE_MATH_ONLY__
384  // GCC's isinf breaks when using -ffast-math.
385  union { double d; uint64_t x; } u = { v };
386  return ((u.x << 1) == 0xff70000000000000ull);
387 #elif !defined(_WIN32)
388  return std::isinf(v);
389 #else
390  return (_isnan(v) == 0 && _finite(v) == 0);
391 #endif
392 }
393 
394 /**
395  *
396  */
397 INLINE float
398 make_nan(float) {
399  return std::numeric_limits<float>::quiet_NaN();
400 }
401 
402 /**
403  *
404  */
405 INLINE double
406 make_nan(double) {
407  return std::numeric_limits<double>::quiet_NaN();
408 }
409 
410 /**
411  *
412  */
413 INLINE float
414 make_inf(float) {
415  return std::numeric_limits<float>::infinity();
416 }
417 
418 /**
419  *
420  */
421 INLINE double
422 make_inf(double) {
423  return std::numeric_limits<double>::infinity();
424 }
425 
426 /**
427  * This is similar to fmod(), but it behaves properly when x is negative: that
428  * is, it always returns a value in the range [0, y), assuming y is positive.
429  *
430  * This integer-valued function is provided since the built-in modulo operator
431  * % does not work properly for negative x.
432  */
433 INLINE int
434 cmod(int x, int y) {
435  if (x < 0) {
436  return y - 1 - ((-x - 1) % y);
437  } else {
438  return x % y;
439  }
440 }
float cmod(float x, float y)
This is similar to fmod(), but it behaves properly when x is negative: that is, it always returns a v...
Definition: cmath.I:130
double cfrac(double f)
Returns the fractional component of f: f - cfloor(f).
Definition: cmath.I:183
float csin_over_x(float v)
Computes sin(x) / x, well-behaved as x approaches 0.
Definition: cmath.I:77