summaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorYukihiro "Matz" Matsumoto <[email protected]>2012-05-16 08:24:22 -0700
committerYukihiro "Matz" Matsumoto <[email protected]>2012-05-16 08:24:22 -0700
commit357aac680e321890c6c9c641adaf3c87c1c4c76e (patch)
treed259ca49b43047244cf1cc98243c77c673f47fbc /src
parent7b4c28cef88b559110804c2cdc5e887a6c252b20 (diff)
parent7bcfb67f3db76cee19f4d989090b27ed3acf8e5a (diff)
downloadmruby-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.c215
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);
}