diff options
| author | chasonr <[email protected]> | 2014-08-15 23:15:45 -0400 |
|---|---|---|
| committer | chasonr <[email protected]> | 2014-08-15 23:15:45 -0400 |
| commit | e23deaafc2733b2c387815ea39b534778fe00b68 (patch) | |
| tree | 827bbd118d1459f3ff4e394c4c05d0bafefd2949 /mrbgems/mruby-math | |
| parent | ea959d4436310d85e640ed092bbfb86bcb6aaf82 (diff) | |
| download | mruby-e23deaafc2733b2c387815ea39b534778fe00b68.tar.gz mruby-e23deaafc2733b2c387815ea39b534778fe00b68.zip | |
Improve replacement math functions for Visual C++.
Diffstat (limited to 'mrbgems/mruby-math')
| -rw-r--r-- | mrbgems/mruby-math/src/math.c | 72 |
1 files changed, 68 insertions, 4 deletions
diff --git a/mrbgems/mruby-math/src/math.c b/mrbgems/mruby-math/src/math.c index 871cba301..04bf2d357 100644 --- a/mrbgems/mruby-math/src/math.c +++ b/mrbgems/mruby-math/src/math.c @@ -23,10 +23,74 @@ domain_error(mrb_state *mrb, const char *func) #define MATH_TOLERANCE 1E-12 -#define asinh(x) log(x + sqrt(pow(x,2.0) + 1)) -#define acosh(x) log(x + sqrt(pow(x,2.0) - 1)) -#define atanh(x) (log(1+x) - log(1-x))/2.0 -#define cbrt(x) pow(x,1.0/3.0) +double +asinh(double x) +{ + double xa, ya, y; + + /* Basic formula loses precision for x < 0, but asinh is an odd function */ + xa = fabs(x); + if (xa > 3.16227E+18) { + /* Prevent x*x from overflowing; basic formula reduces to log(2*x) */ + ya = log(xa) + 0.69314718055994530942; + } + else { + /* Basic formula for asinh */ + ya = log(xa + sqrt(xa*xa + 1.0)); + } + + y = copysign(ya, x); + return y; +} + +double +acosh(double x) +{ + double y; + + if (x > 3.16227E+18) { + /* Prevent x*x from overflowing; basic formula reduces to log(2*x) */ + y = log(x) + 0.69314718055994530942; + } + else { + /* Basic formula for acosh */ + y = log(x + sqrt(x*x - 1.0)); + } + + return y; +} + +double +atanh(double x) +{ + double y; + + if (fabs(x) < 1E-2) { + /* The sums 1+x and 1-x lose precision for small x. Use the polynomial + instead. */ + double x2 = x * x; + y = x*(1.0 + x2*(1.0/3.0 + x2*(1.0/5.0 + x2*(1.0/7.0)))); + } + else { + /* Basic formula for atanh */ + y = 0.5 * (log(1.0+x) - log(1.0-x)); + } + + return y; +} + +double +cbrt(double x) +{ + double xa, ya, y; + + /* pow(x, y) is undefined for x < 0 and y not an integer, but cbrt is an + odd function */ + xa = fabs(x); + ya = pow(xa, 1.0/3.0); + y = copysign(ya, x); + return y; +} /* Declaration of complementary Error function */ double |
