Commit 631ab353 authored by Yukihiro "Matz" Matsumoto's avatar Yukihiro "Matz" Matsumoto

Merge pull request #158 from pbosetti/tests

Minor edits to test suite and Math module
parents 2728f302 d1f6f504
...@@ -10,6 +10,8 @@ ...@@ -10,6 +10,8 @@
#define domain_error(msg) \ #define domain_error(msg) \
mrb_raise(mrb, E_RANGE_ERROR, "Numerical argument is out of domain - " #msg); mrb_raise(mrb, E_RANGE_ERROR, "Numerical argument is out of domain - " #msg);
#define MATH_TOLERANCE 1E-12
/* math functions not provided under Microsoft Visual C++ */ /* math functions not provided under Microsoft Visual C++ */
#ifdef _MSC_VER #ifdef _MSC_VER
#define asinh(x) log(x + sqrt(pow(x,2.0) + 1)) #define asinh(x) log(x + sqrt(pow(x,2.0) + 1))
...@@ -25,7 +27,7 @@ erfc(double x); ...@@ -25,7 +27,7 @@ erfc(double x);
** Implementations of error functions ** Implementations of error functions
** credits to http://www.digitalmars.com/archives/cplusplus/3634.html ** credits to http://www.digitalmars.com/archives/cplusplus/3634.html
*/ */
#define REL_ERROR 1E-12
/* Implementation of Error function */ /* Implementation of Error function */
double double
erf(double x) erf(double x)
...@@ -45,7 +47,7 @@ erf(double x) ...@@ -45,7 +47,7 @@ erf(double x)
term *= xsqr/j; term *= xsqr/j;
sum += term/(2*j+1); sum += term/(2*j+1);
++j; ++j;
} while (fabs(term)/sum > REL_ERROR); } while (fabs(term)/sum > MATH_TOLERANCE);
return two_sqrtpi*sum; return two_sqrtpi*sum;
} }
...@@ -77,7 +79,7 @@ erfc(double x) ...@@ -77,7 +79,7 @@ erfc(double x)
n += 0.5; n += 0.5;
q1 = q2; q1 = q2;
q2 = b/d; q2 = b/d;
} while (fabs(q1-q2)/q2 > REL_ERROR); } while (fabs(q1-q2)/q2 > MATH_TOLERANCE);
return one_sqrtpi*exp(-x*x)*q2; return one_sqrtpi*exp(-x*x)*q2;
} }
...@@ -610,6 +612,7 @@ mrb_init_math(mrb_state *mrb) ...@@ -610,6 +612,7 @@ mrb_init_math(mrb_state *mrb)
struct RClass *mrb_math; struct RClass *mrb_math;
mrb_math = mrb_define_module(mrb, "Math"); mrb_math = mrb_define_module(mrb, "Math");
mrb_define_const(mrb, mrb_math, "TOLERANCE", mrb_float_value(MATH_TOLERANCE));
#ifdef M_PI #ifdef M_PI
mrb_define_const(mrb, mrb_math, "PI", mrb_float_value(M_PI)); mrb_define_const(mrb, mrb_math, "PI", mrb_float_value(M_PI));
#else #else
......
...@@ -22,7 +22,7 @@ end ...@@ -22,7 +22,7 @@ end
# iso : The ISO reference code of the feature # iso : The ISO reference code of the feature
# which will be tested by this # which will be tested by this
# assertion # assertion
def assert(str = 'Assertion failed', iso = '') def assert(str = 'Assertion failed', iso = 'No ISO')
begin begin
if(!yield) if(!yield)
$asserts.push([str, iso]) $asserts.push([str, iso])
......
## ##
# Math Test # Math Test
MATH_TOLERANCE = 1E-12 ##
# Performs fuzzy check for equality on methods returning floats
# on the basis of the Math::TOLERANCE constant.
def check(a,b) def check(a,b)
a = a.to_f a = a.to_f
b = b.to_f b = b.to_f
if a.finite? and b.finite? if a.finite? and b.finite?
(a-b).abs < MATH_TOLERANCE (a-b).abs < Math::TOLERANCE
else else
true true
end end
end end
assert('Math.sin 0') do assert('Math.sin 0') do
check(Math.sin(0), 0) check(Math.sin(0), 0)
end end
...@@ -26,12 +27,13 @@ assert('Fundamental trig identities') do ...@@ -26,12 +27,13 @@ assert('Fundamental trig identities') do
result = true result = true
N = 15 N = 15
N.times do |i| N.times do |i|
a = Math::PI / N * i a = Math::PI / N * i
s = Math.sin(a) ca = Math::PI / 2 - a
c = Math.cos(a) s = Math.sin(a)
t = Math.tan(a) c = Math.cos(a)
result &= check(s, Math.cos(Math::PI / 2 - a)) t = Math.tan(a)
result &= check(t, 1 / Math.tan(Math::PI / 2 - a)) result &= check(s, Math.cos(ca))
result &= check(t, 1 / Math.tan(ca))
result &= check(s ** 2 + c ** 2, 1) result &= check(s ** 2 + c ** 2, 1)
result &= check(t ** 2 + 1, (1/c) ** 2) result &= check(t ** 2 + 1, (1/c) ** 2)
result &= check((1/t) ** 2 + 1, (1/s) ** 2) result &= check((1/t) ** 2 + 1, (1/s) ** 2)
...@@ -101,3 +103,16 @@ assert('Math.hypot') do ...@@ -101,3 +103,16 @@ assert('Math.hypot') do
check(Math.hypot(3, 4), 5.0) check(Math.hypot(3, 4), 5.0)
end end
assert('Math.frexp 1234') do
n = 1234
fraction, exponent = Math.frexp(n)
check(Math.ldexp(fraction, exponent), n)
end
assert('Math.erf 1') do
check(Math.erf(1), 0.842700792949715)
end
assert('Math.erfc 1') do
check(Math.erfc(1), 0.157299207050285)
end
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment