1 /********************************************************************************
2 *                                                                               *
3 *                           M a t h   F u n c t i o n s                         *
4 *                                                                               *
5 *********************************************************************************
6 * Copyright (C) 2015,2020 by Jeroen van der Zijp.   All Rights Reserved.        *
7 *********************************************************************************
8 * This library is free software; you can redistribute it and/or modify          *
9 * it under the terms of the GNU Lesser General Public License as published by   *
10 * the Free Software Foundation; either version 3 of the License, or             *
11 * (at your option) any later version.                                           *
12 *                                                                               *
13 * This library is distributed in the hope that it will be useful,               *
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of                *
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the                 *
16 * GNU Lesser General Public License for more details.                           *
17 *                                                                               *
18 * You should have received a copy of the GNU Lesser General Public License      *
19 * along with this program.  If not, see <http://www.gnu.org/licenses/>          *
20 ********************************************************************************/
21 #ifndef FXMATH_H
22 #define FXMATH_H
23 
24 // Remove macros
25 #undef fabs
26 #undef fabsf
27 #undef fmod
28 #undef fmodf
29 
30 #undef ceil
31 #undef ceilf
32 #undef floor
33 #undef floorf
34 #undef round
35 #undef roundf
36 #undef trunc
37 #undef truncf
38 #undef nearbyint
39 #undef nearbyintf
40 #undef rint
41 #undef rintf
42 
43 #undef sin
44 #undef sinf
45 #undef cos
46 #undef cosf
47 #undef tan
48 #undef tanf
49 #undef asin
50 #undef asinf
51 #undef acos
52 #undef acosf
53 #undef atan
54 #undef atanf
55 #undef atan2
56 #undef atan2f
57 #undef sincos
58 #undef sincosf
59 #undef sinh
60 #undef sinhf
61 #undef cosh
62 #undef coshf
63 #undef tanh
64 #undef tanhf
65 #undef asinh
66 #undef asinhf
67 #undef acosh
68 #undef acoshf
69 #undef atanh
70 #undef atanhf
71 
72 #undef pow
73 #undef powf
74 #undef pow10
75 #undef pow10f
76 #undef exp
77 #undef expf
78 #undef expm1
79 #undef expm1f
80 #undef exp2
81 #undef exp2f
82 #undef exp10
83 #undef exp10f
84 #undef log
85 #undef logf
86 #undef log1p
87 #undef log1pf
88 #undef log2
89 #undef log2f
90 #undef log10
91 #undef log10f
92 
93 #undef sqrt
94 #undef sqrtf
95 #undef cbrt
96 #undef cbrtf
97 #undef sqr
98 #undef sqrf
99 #undef cub
100 #undef cubf
101 
102 #undef max
103 #undef min
104 #undef fmax
105 #undef fmaxf
106 #undef fmin
107 #undef fminf
108 #undef copysign
109 #undef copysignf
110 #undef hypot
111 #undef hypotf
112 
113 
114 // Switch on remedial math on Windows with VC++
115 #if defined(WIN32) && (defined(_MSC_VER) || defined(__MINGW32__))
116 #define NO_CEILF
117 #define NO_FLOORF
118 #define NO_ROUNDF
119 #define NO_ROUND
120 #define NO_TRUNCF
121 #define NO_TRUNC
122 #define NO_NEARBYINTF
123 #define NO_NEARBYINT
124 #define NO_RINTF
125 #define NO_RINT
126 #define NO_EXPM1F
127 #define NO_EXPM1
128 #define NO_EXP2F
129 #define NO_EXP2
130 #define NO_EXP10F
131 #define NO_EXP10
132 #define NO_POW10F
133 #define NO_POW10
134 #define NO_LOG1PF
135 #define NO_LOG1P
136 #define NO_LOG2F
137 #define NO_LOG2
138 #define NO_CBRTF
139 #define NO_CBRT
140 #define NO_SINHF
141 #define NO_SINH
142 #define NO_COSHF
143 #define NO_COSH
144 #define NO_TANHF
145 #define NO_TANH
146 #define NO_ASINHF
147 #define NO_ASINH
148 #define NO_ACOSHF
149 #define NO_ACOSH
150 #define NO_ATANHF
151 #define NO_ATANH
152 #define NO_FMAXF
153 #define NO_FMAX
154 #define NO_FMINF
155 #define NO_FMIN
156 #define NO_COPYSIGNF
157 #define NO_COPYSIGN
158 #define NO_HYPOTF
159 #define NO_HYPOT
160 #define NO_FDIMF
161 #define NO_FDIM
162 #define NO_SINCOS
163 #define NO_SINCOSF
164 #define NO_LRINT
165 #define NO_LRINTF
166 #endif
167 
168 // Systems below are missing these functions
169 #if defined(__sun__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__DragonFly__)
170 #define NO_EXP10F
171 #define NO_EXP10
172 #endif
173 
174 // Apple is missing sincos
175 #if defined(__APPLE__)
176 #define NO_SINCOS
177 #define NO_SINCOSF
178 #endif
179 
180 
181 namespace FX {
182 
183 /*********************************  Constants  *********************************/
184 
185 /// Pi
186 const FXdouble PI=3.1415926535897932384626433833;
187 
188 /// Euler constant
189 const FXdouble EULER=2.7182818284590452353602874713;
190 
191 /// Multiplier for degrees to radians
192 const FXdouble DTOR=0.0174532925199432957692369077;
193 
194 /// Multiplier for radians to degrees
195 const FXdouble RTOD=57.295779513082320876798154814;
196 
197 /// Feigenbaum constant
198 const FXdouble FEIGENBAUM=4.6692016091029906718532038215;
199 
200 /*********************************  Functions  *********************************/
201 
202 // FOX math functions live here
203 namespace Math {
204 
205 /// Sign of single precision float point number (0..1)
206 extern FXAPI FXint fpSign(FXfloat x);
207 
208 /// Sign of double precision float point number (0..1)
209 extern FXAPI FXlong fpSign(FXdouble x);
210 
211 /// Signed exponent of single precision float point number (-127..128)
212 extern FXAPI FXint fpExponent(FXfloat x);
213 
214 /// Signed exponent of double precision float point number (-1023..1023)
215 extern FXAPI FXlong fpExponent(FXdouble x);
216 
217 /// Mantissa of single precision float point number (including hidden bit)
218 extern FXAPI FXint fpMantissa(FXfloat x);
219 
220 /// Mantissa of double precision float point number (including hidden bit)
221 extern FXAPI FXlong fpMantissa(FXdouble x);
222 
223 /// Single precision floating point number is finite
224 extern FXAPI FXbool fpFinite(FXfloat x);
225 
226 /// Double precision floating point number is finite
227 extern FXAPI FXbool fpFinite(FXdouble x);
228 
229 /// Single precision floating point number is infinite
230 extern FXAPI FXbool fpInfinite(FXfloat x);
231 
232 /// Double precision floating point number is infinite
233 extern FXAPI FXbool fpInfinite(FXdouble x);
234 
235 /// Single precision floating point number is NaN
236 extern FXAPI FXbool fpNan(FXfloat x);
237 
238 /// Double precision floating point number is NaN
239 extern FXAPI FXbool fpNan(FXdouble x);
240 
241 /// Single precision floating point number is normalized
242 extern FXAPI FXbool fpNormal(FXfloat x);
243 
244 /// Double precision floating point number is normalized
245 extern FXAPI FXbool fpNormal(FXdouble x);
246 
247 /// All bits of single precision floating point number
248 extern FXAPI FXuint fpBits(FXfloat x);
249 
250 /// All bits of double precision floating point number
251 extern FXAPI FXulong fpBits(FXdouble x);
252 
253 
254 /// Evaluate integer (a < b) ? x : y
iblend(FXint a,FXint b,FXint x,FXint y)255 static inline FXint iblend(FXint a,FXint b,FXint x,FXint y){
256   return a<b ? x : y;
257   }
258 
259 /// Evaluate long integer (a < b) ? x : y
iblend(FXlong a,FXlong b,FXlong x,FXlong y)260 static inline FXlong iblend(FXlong a,FXlong b,FXlong x,FXlong y){
261   return a<b ? x : y;
262   }
263 
264 
265 /// Minimum if two integers
imin(FXint x,FXint y)266 static inline FXint imin(FXint x,FXint y){
267   return (x<y)?x:y;
268   }
269 
270 /// Minimum if two longs
imin(FXlong x,FXlong y)271 static inline FXlong imin(FXlong x,FXlong y){
272   return (x<y)?x:y;
273   }
274 
275 
276 /// Minimum of two integers
imax(FXint x,FXint y)277 static inline FXint imax(FXint x,FXint y){
278   return (x>y)?x:y;
279   }
280 
281 /// Minimum of two longs
imax(FXlong x,FXlong y)282 static inline FXlong imax(FXlong x,FXlong y){
283   return (x>y)?x:y;
284   }
285 
286 
287 /// Absolute value of integer
iabs(FXint x)288 static inline FXint iabs(FXint x){
289   return 0<x?x:-x;
290   }
291 
292 /// Absolute value of long
iabs(FXlong x)293 static inline FXlong iabs(FXlong x){
294   return 0<x?x:-x;
295   }
296 
297 
298 /// Integer clamp of integer x to lie within range [lo..hi]
iclamp(FXint lo,FXint x,FXint hi)299 static inline FXint iclamp(FXint lo,FXint x,FXint hi){
300   return Math::imin(Math::imax(x,lo),hi);
301   }
302 
303 /// Long clamp of long x to lie within range [lo..hi]
iclamp(FXlong lo,FXlong x,FXlong hi)304 static inline FXlong iclamp(FXlong lo,FXlong x,FXlong hi){
305   return Math::imin(Math::imax(x,lo),hi);
306   }
307 
308 
309 /// Sign of integer, return -1 if x is <0, +1 if x>0, and zero otherwise
isign(FXint x)310 static inline FXint isign(FXint x){
311   return (x>0)-(x<0);
312   }
313 
314 /// Sign of integer, return -1 if x is <0, +1 if x>0, and zero otherwise
isign(FXlong x)315 static inline FXlong isign(FXlong x){
316   return (x>0)-(x<0);
317   }
318 
319 
320 /// Single precision minimum of two
fmin(FXfloat x,FXfloat y)321 static inline FXfloat fmin(FXfloat x,FXfloat y){
322 #if defined(NO_FMINF)
323   return (x<y)?x:y;
324 #else
325   return ::fminf(x,y);
326 #endif
327   }
328 
329 /// Double precision minimum of two
fmin(FXdouble x,FXdouble y)330 static inline FXdouble fmin(FXdouble x,FXdouble y){
331 #if defined(NO_FMIN)
332   return (x<y)?x:y;
333 #else
334   return ::fmin(x,y);
335 #endif
336   }
337 
338 
339 /// Single precision maximum of two
fmax(FXfloat x,FXfloat y)340 static inline FXfloat fmax(FXfloat x,FXfloat y){
341 #if defined(NO_FMAXF)
342   return (x>y)?x:y;
343 #else
344   return ::fmaxf(x,y);
345 #endif
346   }
347 
348 /// Double precision maximum of two
fmax(FXdouble x,FXdouble y)349 static inline FXdouble fmax(FXdouble x,FXdouble y){
350 #if defined(NO_FMAX)
351   return (x>y)?x:y;
352 #else
353   return ::fmax(x,y);
354 #endif
355   }
356 
357 
358 /// Single precision absolute value
fabs(FXfloat x)359 static inline FXfloat fabs(FXfloat x){
360 #if defined(NO_FABSF)
361   return (x<0.0f) ? -x : x;
362 #else
363   return ::fabsf(x);
364 #endif
365   }
366 
367 /// Double precision absolute value
fabs(FXdouble x)368 static inline FXdouble fabs(FXdouble x){
369   return ::fabs(x);
370   }
371 
372 
373 /// Single precision clamp of number x to lie within range [lo..hi]
fclamp(FXfloat lo,FXfloat x,FXfloat hi)374 static inline FXfloat fclamp(FXfloat lo,FXfloat x,FXfloat hi){
375   return Math::fmin(Math::fmax(x,lo),hi);
376   }
377 
378 /// Double precision clamp of number x to lie within range [lo..hi]
fclamp(FXdouble lo,FXdouble x,FXdouble hi)379 static inline FXdouble fclamp(FXdouble lo,FXdouble x,FXdouble hi){
380   return Math::fmin(Math::fmax(x,lo),hi);
381   }
382 
383 
384 /// Single precision positive difference
fdim(FXfloat x,FXfloat y)385 static inline FXfloat fdim(FXfloat x,FXfloat y){
386 #if defined(NO_FDIMF)
387   return Math::fmax(x-y,0.0f);
388 #else
389   return ::fdimf(x,y);
390 #endif
391   }
392 
393 /// Double precision positive difference
fdim(FXdouble x,FXdouble y)394 static inline FXdouble fdim(FXdouble x,FXdouble y){
395 #if defined(NO_FDIM)
396   return Math::fmax(x-y,0.0);
397 #else
398   return ::fdim(x,y);
399 #endif
400   }
401 
402 
403 /// Single precision floating point remainder
fmod(FXfloat x,FXfloat y)404 static inline FXfloat fmod(FXfloat x,FXfloat y){
405   return ::fmodf(x,y);
406   }
407 
408 /// Double precision floating point remainder
fmod(FXdouble x,FXdouble y)409 static inline FXdouble fmod(FXdouble x,FXdouble y){
410   return ::fmod(x,y);
411   }
412 
413 
414 /// Evaluate single-precision (a < b) ? x : y
fblend(FXfloat a,FXfloat b,FXfloat x,FXfloat y)415 static inline FXfloat fblend(FXfloat a,FXfloat b,FXfloat x,FXfloat y){
416   return a<b ? x : y;
417   }
418 
419 
420 /// Evaluate double-precision (a < b) ? x : y
fblend(FXdouble a,FXdouble b,FXdouble x,FXdouble y)421 static inline FXdouble fblend(FXdouble a,FXdouble b,FXdouble x,FXdouble y){
422   return a<b ? x : y;
423   }
424 
425 
426 /// Single precision copy sign of y and apply to magnitude of x
copysign(FXfloat x,FXfloat y)427 static inline FXfloat copysign(FXfloat x,FXfloat y){
428 #if defined(NO_COPYSIGNF)
429   union{ FXfloat f; FXuint u; } xx={x},yy={y};
430   xx.u&=0x7fffffff;
431   xx.u|=(yy.u&0x80000000);
432   return xx.f;
433 #else
434   return ::copysignf(x,y);
435 #endif
436   }
437 
438 /// Double precision copy sign of y and apply to magnitude of x
copysign(FXdouble x,FXdouble y)439 static inline FXdouble copysign(FXdouble x,FXdouble y){
440 #if defined(NO_COPYSIGN)
441   union{ FXdouble f; FXulong u; } xx={x},yy={y};
442   xx.u&=FXULONG(0x7fffffffffffffff);
443   xx.u|=(yy.u&FXULONG(0x8000000000000000));
444   return xx.f;
445 #else
446   return ::copysign(x,y);
447 #endif
448   }
449 
450 
451 /// Single precision ceiling (round upward to nearest integer)
452 #if defined(NO_CEILF)
453 extern FXAPI FXfloat ceil(FXfloat x);
454 #else
ceil(FXfloat x)455 static inline FXfloat ceil(FXfloat x){ return ::ceilf(x); }
456 #endif
457 
458 /// Double precision ceiling (round upward to nearest integer)
ceil(FXdouble x)459 static inline FXdouble ceil(FXdouble x){ return ::ceil(x); }
460 
461 
462 /// Single precision floor (round down to nearest integer)
463 #if defined(NO_FLOORF)
464 extern FXAPI FXfloat floor(FXfloat x);
465 #else
floor(FXfloat x)466 static inline FXfloat floor(FXfloat x){ return ::floorf(x); }
467 #endif
468 
469 /// Double precision floor (round down to nearest integer)
floor(FXdouble x)470 static inline FXdouble floor(FXdouble x){ return ::floor(x); }
471 
472 /// Single precision round to nearest integer (away from zero)
473 #if defined(NO_ROUNDF)
474 extern FXAPI FXfloat round(FXfloat x);
475 #else
round(FXfloat x)476 static inline FXfloat round(FXfloat x){ return ::roundf(x); }
477 #endif
478 
479 /// Double precision round to nearest integer (away from zero)
480 #if defined(NO_ROUND)
481 extern FXAPI FXdouble round(FXdouble x);
482 #else
round(FXdouble x)483 static inline FXdouble round(FXdouble x){ return ::round(x); }
484 #endif
485 
486 
487 /// Single precision truncate to nearest integer (toward zero)
488 #if defined(NO_TRUNCF)
489 extern FXAPI FXfloat trunc(FXfloat x);
490 #else
trunc(FXfloat x)491 static inline FXfloat trunc(FXfloat x){ return ::truncf(x); }
492 #endif
493 
494 /// Double precision truncate to nearest integer (toward zero)
495 #if defined(NO_TRUNC)
496 extern FXAPI FXdouble trunc(FXdouble x);
497 #else
trunc(FXdouble x)498 static inline FXdouble trunc(FXdouble x){ return ::trunc(x); }
499 #endif
500 
501 
502 /// Single precision round to nearest integer
503 #if defined(NO_NEARBYINTF)
504 extern FXAPI FXfloat nearbyint(FXfloat x);
505 #else
nearbyint(FXfloat x)506 static inline FXfloat nearbyint(FXfloat x){ return ::nearbyintf(x); }
507 #endif
508 
509 /// Double precision round to nearest integer
510 #if defined(NO_NEARBYINT)
511 extern FXAPI FXdouble nearbyint(FXdouble x);
512 #else
nearbyint(FXdouble x)513 static inline FXdouble nearbyint(FXdouble x){ return ::nearbyint(x); }
514 #endif
515 
516 /// Single precision round to nearest integer
517 #if defined(NO_RINTF)
518 extern FXAPI FXfloat rint(FXfloat x);
519 #else
rint(FXfloat x)520 static inline FXfloat rint(FXfloat x){ return ::rintf(x); }
521 #endif
522 
523 /// Double precision round to nearest integer
524 #if defined(NO_RINT)
525 extern FXAPI FXdouble rint(FXdouble x);
526 #else
rint(FXdouble x)527 static inline FXdouble rint(FXdouble x){ return ::rint(x); }
528 #endif
529 
530 
531 /// Single precision round to nearest integer
lrint(FXfloat x)532 static inline FXint lrint(FXfloat x){
533 #if defined(NO_LRINTF)
534   return (FXint)(x+Math::copysign(0.5f,x));
535 #else
536   return ::lrintf(x);
537 #endif
538  }
539 
540 /// Double precision round to nearest integer
lrint(FXdouble x)541 static inline FXlong lrint(FXdouble x){
542 #if defined(NO_LRINT)
543  return (FXlong)(x+Math::copysign(0.5,x));
544 #else
545  return ::lrint(x);
546 #endif
547  }
548 
549 
550 /// Wrap single precision phase argument x to -PI...PI range
wrap(FXfloat x)551 static inline FXfloat wrap(FXfloat x){
552 #if defined(__SSE4_1__)
553   return x-Math::nearbyint(x*0.159154943091895335768883763373f)*6.28318530717958647692528676656f;
554 #else
555   return x-Math::lrint(x*0.159154943091895335768883763373f)*6.28318530717958647692528676656f;
556 #endif
557   }
558 
559 /// Wrap double precision phase argument x to -PI...PI range
wrap(FXdouble x)560 static inline FXdouble wrap(FXdouble x){
561 #if defined(__SSE4_1__)
562   return x-Math::nearbyint(x*0.159154943091895335768883763373)*6.28318530717958647692528676656;
563 #else
564   return x-Math::lrint(x*0.159154943091895335768883763373)*6.28318530717958647692528676656;
565 #endif
566   }
567 
568 
569 /// Stepify single precision x into multiples of step s (where s>0)
stepify(FXfloat x,FXfloat s)570 static inline FXfloat stepify(FXfloat x,FXfloat s){
571   return Math::nearbyint(x/s)*s;
572   }
573 
574 /// Stepify double precision x into multiples of step s (where s>0)
stepify(FXdouble x,FXdouble s)575 static inline FXdouble stepify(FXdouble x,FXdouble s){
576   return Math::nearbyint(x/s)*s;
577   }
578 
579 
580 /// Single precision sine
sin(FXfloat x)581 static inline FXfloat sin(FXfloat x){
582   return ::sinf(x);
583   }
584 
585 /// Double precision sine
sin(FXdouble x)586 static inline FXdouble sin(FXdouble x){
587   return ::sin(x);
588   }
589 
590 
591 /// Single precision cosine
cos(FXfloat x)592 static inline FXfloat cos(FXfloat x){
593   return ::cosf(x);
594   }
595 
596 /// Double precision cosine
cos(FXdouble x)597 static inline FXdouble cos(FXdouble x){
598   return ::cos(x);
599   }
600 
601 
602 /// Single precision tangent
tan(FXfloat x)603 static inline FXfloat tan(FXfloat x){
604   return ::tanf(x);
605   }
606 
607 /// Double precision tangent
tan(FXdouble x)608 static inline FXdouble tan(FXdouble x){
609   return ::tan(x);
610   }
611 
612 
613 /// Single precision arc sine
asin(FXfloat x)614 static inline FXfloat asin(FXfloat x){
615   return ::asinf(x);
616   }
617 
618 /// Double precision arc sine
asin(FXdouble x)619 static inline FXdouble asin(FXdouble x){
620   return ::asin(x);
621   }
622 
623 
624 /// Single precision arc cosine
acos(FXfloat x)625 static inline FXfloat acos(FXfloat x){
626   return ::acosf(x);
627   }
628 
629 /// Double precision arc cosine
acos(FXdouble x)630 static inline FXdouble acos(FXdouble x){
631   return ::acos(x);
632   }
633 
634 
635 /// Single precision arc tangent
atan(FXfloat x)636 static inline FXfloat atan(FXfloat x){
637   return ::atanf(x);
638   }
639 
640 /// Double precision arc tangent
atan(FXdouble x)641 static inline FXdouble atan(FXdouble x){
642   return ::atan(x);
643   }
644 
645 
646 /// Single precision arc tangent
atan2(FXfloat y,FXfloat x)647 static inline FXfloat atan2(FXfloat y,FXfloat x){
648   return ::atan2f(y,x);
649   }
650 
651 /// Double precision arc tangent
atan2(FXdouble y,FXdouble x)652 static inline FXdouble atan2(FXdouble y,FXdouble x){
653   return ::atan2(y,x);
654   }
655 
656 
657 /// Single precision sincos
sincos(FXfloat x,FXfloat & s,FXfloat & c)658 static inline void sincos(FXfloat x,FXfloat& s,FXfloat& c){
659 #if defined(NO_SINCOSF)
660   s=Math::sin(x);
661   c=Math::cos(x);
662 #else
663   ::sincosf(x,&s,&c);
664 #endif
665   }
666 
667 
668 /// Double precision sincos
sincos(FXdouble x,FXdouble & s,FXdouble & c)669 static inline void sincos(FXdouble x,FXdouble& s,FXdouble& c){
670 #if defined(NO_SINCOS)
671   s=Math::sin(x);
672   c=Math::cos(x);
673 #else
674   ::sincos(x,&s,&c);
675 #endif
676   }
677 
678 
679 /// Single precision hyperbolic sine
680 #if defined(NO_SINHF)
681 extern FXAPI FXfloat sinh(FXfloat x);
682 #else
sinh(FXfloat x)683 static inline FXfloat sinh(FXfloat x){ return ::sinhf(x); }
684 #endif
685 
686 /// Double precision hyperbolic sine
687 #if defined(NO_SINH)
688 extern FXAPI FXdouble sinh(FXdouble x);
689 #else
sinh(FXdouble x)690 static inline FXdouble sinh(FXdouble x){ return ::sinh(x); }
691 #endif
692 
693 
694 /// Single precision hyperbolic cosine
695 #if defined(NO_COSHF)
696 extern FXAPI FXfloat cosh(FXfloat x);
697 #else
cosh(FXfloat x)698 static inline FXfloat cosh(FXfloat x){ return ::coshf(x); }
699 #endif
700 
701 /// Double precision hyperbolic cosine
702 #if defined(NO_COSH)
703 extern FXAPI FXdouble cosh(FXdouble x);
704 #else
cosh(FXdouble x)705 static inline FXdouble cosh(FXdouble x){ return ::cosh(x); }
706 #endif
707 
708 
709 /// Single precision hyperbolic tangent
710 #if defined(NO_TANHF)
711 extern FXAPI FXfloat tanh(FXfloat x);
712 #else
tanh(FXfloat x)713 static inline FXfloat tanh(FXfloat x){ return ::tanhf(x); }
714 #endif
715 
716 /// Double precision hyperbolic tangent
717 #if defined(NO_TANH)
718 extern FXAPI FXdouble tanh(FXdouble x);
719 #else
tanh(FXdouble x)720 static inline FXdouble tanh(FXdouble x){ return ::tanh(x); }
721 #endif
722 
723 
724 /// Single precision hyperbolic arc sine
725 #if defined(NO_ASINHF)
726 extern FXAPI FXfloat asinh(FXfloat x);
727 #else
asinh(FXfloat x)728 static inline FXfloat asinh(FXfloat x){ return ::asinhf(x); }
729 #endif
730 
731 /// Double precision hyperbolic arc sine
732 #if defined(NO_ASINH)
733 extern FXAPI FXdouble asinh(FXdouble x);
734 #else
asinh(FXdouble x)735 static inline FXdouble asinh(FXdouble x){ return ::asinh(x); }
736 #endif
737 
738 
739 /// Single precision hyperbolic arc cosine
740 #if defined(NO_ACOSHF)
741 extern FXAPI FXfloat acosh(FXfloat x);
742 #else
acosh(FXfloat x)743 static inline FXfloat acosh(FXfloat x){ return ::acoshf(x); }
744 #endif
745 
746 /// Double precision  hyperbolic arc cosine
747 #if defined(NO_ACOSH)
748 extern FXAPI FXdouble acosh(FXdouble x);
749 #else
acosh(FXdouble x)750 static inline FXdouble acosh(FXdouble x){ return ::acosh(x); }
751 #endif
752 
753 
754 /// Single precision hyperbolic arc tangent
755 #if defined(NO_ATANHF)
756 extern FXAPI FXfloat atanh(FXfloat x);
757 #else
atanh(FXfloat x)758 static inline FXfloat atanh(FXfloat x){ return ::atanhf(x); }
759 #endif
760 
761 /// Double precision hyperbolic arc tangent
762 #if defined(NO_ATANH)
763 extern FXAPI FXdouble atanh(FXdouble x);
764 #else
atanh(FXdouble x)765 static inline FXdouble atanh(FXdouble x){ return ::atanh(x); }
766 #endif
767 
768 
769 /// Single precision square root
sqrt(FXfloat x)770 static inline FXfloat sqrt(FXfloat x){
771   return ::sqrtf(x);
772   }
773 
774 /// Double precision square root
sqrt(FXdouble x)775 static inline FXdouble sqrt(FXdouble x){
776   return ::sqrt(x);
777   }
778 
779 
780 /// Safe single precision square root
safesqrt(FXfloat x)781 static inline FXfloat safesqrt(FXfloat x){
782   return Math::sqrt(Math::fmax(x,0.0f));
783   }
784 
785 /// Safe double precision square root
safesqrt(FXdouble x)786 static inline FXdouble safesqrt(FXdouble x){
787   return Math::sqrt(Math::fmax(x,0.0));
788   }
789 
790 
791 /// Single precision cube root
cbrt(FXfloat x)792 static inline FXfloat cbrt(FXfloat x){
793 #if defined(NO_CBRTF)
794   return ::powf(x,0.333333333333333333333333333333f);
795 #else
796   return ::cbrtf(x);
797 #endif
798   }
799 
800 /// Double precision cube root
cbrt(FXdouble x)801 static inline FXdouble cbrt(FXdouble x){
802 #if defined(NO_CBRT)
803   return ::pow(x,0.333333333333333333333333333333);
804 #else
805   return ::cbrt(x);
806 #endif
807   }
808 
809 
810 /// Single precision square
sqr(FXfloat x)811 static inline FXfloat sqr(FXfloat x){
812   return x*x;
813   }
814 
815 /// Double precision square
sqr(FXdouble x)816 static inline FXdouble sqr(FXdouble x){
817   return x*x;
818   }
819 
820 
821 /// Single precision cube
cub(FXfloat x)822 static inline FXfloat cub(FXfloat x){
823   return x*x*x;
824   }
825 
826 /// Double precision cube
cub(FXdouble x)827 static inline FXdouble cub(FXdouble x){
828   return x*x*x;
829   }
830 
831 
832 /// Single precision calculate hypothenuse sqrt(x^2+y^2)
hypot(FXfloat x,FXfloat y)833 static inline FXfloat hypot(FXfloat x,FXfloat y){
834 #if defined(NO_HYPOTF)
835   return Math::sqrt(Math::sqr(x)+Math::sqr(y));
836 #else
837   return ::hypotf(x,y);
838 #endif
839   }
840 
841 /// Double precision calculate hypothenuse sqrt(x^2+y^2)
hypot(FXdouble x,FXdouble y)842 static inline FXdouble hypot(FXdouble x,FXdouble y){
843 #if defined(NO_HYPOT)
844   return Math::sqrt(Math::sqr(x)+Math::sqr(y));
845 #else
846   return ::hypot(x,y);
847 #endif
848   }
849 
850 
851 /// Linearly interpolate between u and v as f goes from 0...1
lerp(FXfloat u,FXfloat v,FXfloat f)852 static inline FXfloat lerp(FXfloat u,FXfloat v,FXfloat f){
853   return (v-u)*f+u;
854   }
855 
856 
857 /// Linearly interpolate between u and v as f goes from 0...1
lerp(FXdouble u,FXdouble v,FXdouble f)858 static inline FXdouble lerp(FXdouble u,FXdouble v,FXdouble f){
859   return (v-u)*f+u;
860   }
861 
862 
863 /// Smooth transition from 0 to 1 as f goes from 0...1
smoothstep(FXfloat f)864 static inline FXfloat smoothstep(FXfloat f){
865   return (3.0f-2.0f*f)*f*f;
866   }
867 
868 /// Smooth transition from 0 to 1 as f goes from 0...1
smoothstep(FXdouble f)869 static inline FXdouble smoothstep(FXdouble f){
870   return (3.0-2.0*f)*f*f;
871   }
872 
873 
874 /// Single precision base E exponential
exp(FXfloat x)875 static inline FXfloat exp(FXfloat x){
876   return ::expf(x);
877   }
878 
879 /// Double precision base E exponential
exp(FXdouble x)880 static inline FXdouble exp(FXdouble x){
881   return ::exp(x);
882   }
883 
884 
885 /// Single precision base E exponential - 1
expm1(FXfloat x)886 static inline FXfloat expm1(FXfloat x){
887 #if defined(NO_EXPM1F)
888   return ::expf(x)-1.0f;
889 #else
890   return ::expm1f(x);
891 #endif
892   }
893 
894 /// Double precision base E exponential - 1
expm1(FXdouble x)895 static inline FXdouble expm1(FXdouble x){
896 #if defined(NO_EXPM1)
897   return ::exp(x)-1.0;
898 #else
899   return ::expm1(x);
900 #endif
901   }
902 
903 
904 /// Single precision power x^y
pow(FXfloat x,FXfloat y)905 static inline FXfloat pow(FXfloat x,FXfloat y){
906   return ::powf(x,y);
907   }
908 
909 /// Double precision power x^y
pow(FXdouble x,FXdouble y)910 static inline FXdouble pow(FXdouble x,FXdouble y){
911   return ::pow(x,y);
912   }
913 
914 
915 /// Single precision base 2 exponential
exp2(FXfloat x)916 static inline FXfloat exp2(FXfloat x){
917 #if defined(NO_EXP2F)
918   return Math::pow(2.0f,x);
919 #else
920   return ::exp2f(x);
921 #endif
922   }
923 
924 
925 /// Double precision base 2 exponential
exp2(FXdouble x)926 static inline FXdouble exp2(FXdouble x){
927 #if defined(NO_EXP2)
928   return Math::pow(2.0,x);
929 #else
930   return ::exp2(x);
931 #endif
932   }
933 
934 
935 /// Single precision base 10 exponential
exp10(FXfloat x)936 static inline FXfloat exp10(FXfloat x){
937 #if defined(NO_EXP10F)
938   return Math::pow(10.0f,x);
939 #else
940   return ::exp10f(x);
941 #endif
942   }
943 
944 
945 /// Double precision base 10 exponential
exp10(FXdouble x)946 static inline FXdouble exp10(FXdouble x){
947 #if defined(NO_EXP10)
948   return Math::pow(10.0,x);
949 #else
950   return ::exp10(x);
951 #endif
952   }
953 
954 
955 /// Single precision 10^x
pow10(FXfloat x)956 static inline FXfloat pow10(FXfloat x){
957   return Math::exp10(x);
958   }
959 
960 /// Double precision 10^x
pow10(FXdouble x)961 static inline FXdouble pow10(FXdouble x){
962   return Math::exp10(x);
963   }
964 
965 
966 /// Double precision integer power of 10
967 extern FXAPI FXdouble pow10i(FXint ex);
968 
969 
970 /// Single precision integer power
971 extern FXAPI FXfloat powi(FXfloat base,FXint ex);
972 
973 
974 /// Double precision integer power
975 extern FXAPI FXdouble powi(FXdouble base,FXint ex);
976 
977 
978 /// Single precision natural logarithm
log(FXfloat x)979 static inline FXfloat log(FXfloat x){
980   return ::logf(x);
981   }
982 
983 /// Double precision natural logarithm
log(FXdouble x)984 static inline FXdouble log(FXdouble x){
985   return ::log(x);
986   }
987 
988 
989 /// Single precision logarithm of 1+x
log1p(FXfloat x)990 static inline FXfloat log1p(FXfloat x){
991 #if defined(NO_LOG1PF)
992   return Math::log(1.0f+x);
993 #else
994   return ::log1pf(x);
995 #endif
996   }
997 
998 
999 /// Double precision logarithm of 1+x
log1p(FXdouble x)1000 static inline FXdouble log1p(FXdouble x){
1001 #if defined(NO_LOG1P)
1002   return Math::log(1.0+x);
1003 #else
1004   return ::log1p(x);
1005 #endif
1006   }
1007 
1008 
1009 /// Single precision base 2 logarithm
log2(FXfloat x)1010 static inline FXfloat log2(FXfloat x){
1011 #if defined(NO_LOG2F)
1012   return Math::log(x)*1.442695040888963407359924681001892137f;
1013 #else
1014   return ::log2f(x);
1015 #endif
1016   }
1017 
1018 
1019 /// Double precision base 2 logarithm
log2(FXdouble x)1020 static inline FXdouble log2(FXdouble x){
1021 #if defined(NO_LOG2)
1022   return Math::log(x)*1.442695040888963407359924681001892137;
1023 #else
1024   return ::log2(x);
1025 #endif
1026   }
1027 
1028 
1029 /// Single precision base 10 logarithm
log10(FXfloat x)1030 static inline FXfloat log10(FXfloat x){
1031   return ::log10f(x);
1032   }
1033 
1034 /// Double precision base 10 logarithm
log10(FXdouble x)1035 static inline FXdouble log10(FXdouble x){
1036   return ::log10(x);
1037   }
1038 
1039 }
1040 
1041 }
1042 
1043 #endif
1044