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