diff options
| author | Yukihiro "Matz" Matsumoto <[email protected]> | 2012-05-16 08:24:22 -0700 |
|---|---|---|
| committer | Yukihiro "Matz" Matsumoto <[email protected]> | 2012-05-16 08:24:22 -0700 |
| commit | 357aac680e321890c6c9c641adaf3c87c1c4c76e (patch) | |
| tree | d259ca49b43047244cf1cc98243c77c673f47fbc /src | |
| parent | 7b4c28cef88b559110804c2cdc5e887a6c252b20 (diff) | |
| parent | 7bcfb67f3db76cee19f4d989090b27ed3acf8e5a (diff) | |
| download | mruby-357aac680e321890c6c9c641adaf3c87c1c4c76e.tar.gz mruby-357aac680e321890c6c9c641adaf3c87c1c4c76e.zip | |
Merge pull request #139 from pbosetti/master
Re-added Math functions missing under MSVC, with custom implementations
Diffstat (limited to 'src')
| -rw-r--r-- | src/math.c | 215 |
1 files changed, 215 insertions, 0 deletions
diff --git a/src/math.c b/src/math.c index adf02206c..cbe773c58 100644 --- a/src/math.c +++ b/src/math.c @@ -10,6 +10,79 @@ #define domain_error(msg) \ mrb_raise(mrb, E_RANGE_ERROR, "Numerical argument is out of domain - " #msg); +/* math functions not provided under Microsoft Visual C++ */ +#ifdef _MSC_VER +#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) + +/* Declaration of complementary Error function */ +double +erfc(double x); + +/* +** Implementations of error functions +** credits to http://www.digitalmars.com/archives/cplusplus/3634.html +*/ +#define REL_ERROR 1E-12 +/* Implementation of Error function */ +double +erf(double x) +{ + static const double two_sqrtpi = 1.128379167095512574; + double sum = x; + double term = x; + double xsqr = x*x; + int j= 1; + if (fabs(x) > 2.2) { + return 1.0 - erfc(x); + } + do { + term *= xsqr/j; + sum -= term/(2*j+1); + ++j; + term *= xsqr/j; + sum += term/(2*j+1); + ++j; + } while (fabs(term)/sum > REL_ERROR); + return two_sqrtpi*sum; +} + +/* Implementation of complementary Error function */ +double +erfc(double x) +{ + static const double one_sqrtpi= 0.564189583547756287; + double a = 1; + double b = x; + double c = x; + double d = x*x+0.5; + double q1, q2; + double n = 1.0; + double t; + if (fabs(x) < 2.2) { + return 1.0 - erf(x); + } + if (x < 0.0) { /*signbit(x)*/ + return 2.0 - erfc(-x); + } + do { + t = a*n+b*x; + a = b; + b = t; + t = c*n+d*x; + c = d; + d = t; + n += 0.5; + q1 = q2; + q2 = b/d; + } while (fabs(q1-q2)/q2 > REL_ERROR); + return one_sqrtpi*exp(-x*x)*q2; +} + +#endif + mrb_value mrb_assoc_new(mrb_state *mrb, mrb_value car, mrb_value cdr); @@ -216,6 +289,62 @@ math_tanh(mrb_state *mrb, mrb_value obj) /* + INVERSE HYPERBOLIC TRIG FUNCTIONS +*/ + +/* + * call-seq: + * Math.asinh(x) -> float + * + * Computes the inverse hyperbolic sine of <i>x</i>. + */ +static mrb_value +math_asinh(mrb_state *mrb, mrb_value obj) +{ + mrb_float x; + + mrb_get_args(mrb, "f", &x); + + x = asinh(x); + + return mrb_float_value(x); +} + +/* + * call-seq: + * Math.acosh(x) -> float + * + * Computes the inverse hyperbolic cosine of <i>x</i>. + */ +static mrb_value +math_acosh(mrb_state *mrb, mrb_value obj) +{ + mrb_float x; + + mrb_get_args(mrb, "f", &x); + x = acosh(x); + + return mrb_float_value(x); +} + +/* + * call-seq: + * Math.atanh(x) -> float + * + * Computes the inverse hyperbolic tangent of <i>x</i>. + */ +static mrb_value +math_atanh(mrb_state *mrb, mrb_value obj) +{ + mrb_float x; + + mrb_get_args(mrb, "f", &x); + x = atanh(x); + + return mrb_float_value(x); +} + +/* EXPONENTIALS AND LOGARITHMS */ #if defined __CYGWIN__ @@ -334,6 +463,49 @@ math_log10(mrb_state *mrb, mrb_value obj) /* * call-seq: + * Math.cbrt(numeric) -> float + * + * Returns the cube root of <i>numeric</i>. + * + * -9.upto(9) {|x| + * p [x, Math.cbrt(x), Math.cbrt(x)**3] + * } + * #=> + * [-9, -2.0800838230519, -9.0] + * [-8, -2.0, -8.0] + * [-7, -1.91293118277239, -7.0] + * [-6, -1.81712059283214, -6.0] + * [-5, -1.7099759466767, -5.0] + * [-4, -1.5874010519682, -4.0] + * [-3, -1.44224957030741, -3.0] + * [-2, -1.25992104989487, -2.0] + * [-1, -1.0, -1.0] + * [0, 0.0, 0.0] + * [1, 1.0, 1.0] + * [2, 1.25992104989487, 2.0] + * [3, 1.44224957030741, 3.0] + * [4, 1.5874010519682, 4.0] + * [5, 1.7099759466767, 5.0] + * [6, 1.81712059283214, 6.0] + * [7, 1.91293118277239, 7.0] + * [8, 2.0, 8.0] + * [9, 2.0800838230519, 9.0] + * + */ +static mrb_value +math_cbrt(mrb_state *mrb, mrb_value obj) +{ + mrb_float x; + + mrb_get_args(mrb, "f", &x); + x = cbrt(x); + + return mrb_float_value(x); +} + + +/* + * call-seq: * Math.frexp(numeric) -> [ fraction, exponent ] * * Returns a two-element array containing the normalized fraction (a @@ -396,6 +568,41 @@ math_hypot(mrb_state *mrb, mrb_value obj) return mrb_float_value(x); } +/* + * call-seq: + * Math.erf(x) -> float + * + * Calculates the error function of x. + */ +static mrb_value +math_erf(mrb_state *mrb, mrb_value obj) +{ + mrb_float x; + + mrb_get_args(mrb, "f", &x); + x = erf(x); + + return mrb_float_value(x); +} + + +/* + * call-seq: + * Math.erfc(x) -> float + * + * Calculates the complementary error function of x. + */ +static mrb_value +math_erfc(mrb_state *mrb, mrb_value obj) +{ + mrb_float x; + + mrb_get_args(mrb, "f", &x); + x = erfc(x); + + return mrb_float_value(x); +} + /* ------------------------------------------------------------------------*/ void mrb_init_math(mrb_state *mrb) @@ -428,13 +635,21 @@ mrb_init_math(mrb_state *mrb) mrb_define_class_method(mrb, mrb_math, "cosh", math_cosh, 1); mrb_define_class_method(mrb, mrb_math, "tanh", math_tanh, 1); + mrb_define_class_method(mrb, mrb_math, "asinh", math_asinh, 1); + mrb_define_class_method(mrb, mrb_math, "acosh", math_acosh, 1); + mrb_define_class_method(mrb, mrb_math, "atanh", math_atanh, 1); + mrb_define_class_method(mrb, mrb_math, "exp", math_exp, 1); mrb_define_class_method(mrb, mrb_math, "log", math_log, -1); mrb_define_class_method(mrb, mrb_math, "log2", math_log2, 1); mrb_define_class_method(mrb, mrb_math, "log10", math_log10, 1); + mrb_define_class_method(mrb, mrb_math, "cbrt", math_cbrt, 1); mrb_define_class_method(mrb, mrb_math, "frexp", math_frexp, 1); mrb_define_class_method(mrb, mrb_math, "ldexp", math_ldexp, 2); mrb_define_class_method(mrb, mrb_math, "hypot", math_hypot, 2); + + mrb_define_class_method(mrb, mrb_math, "erf", math_erf, 1); + mrb_define_class_method(mrb, mrb_math, "erfc", math_erfc, 1); } |
