From 9c9be62b02eccd177db2311c337c7b469cd19e62 Mon Sep 17 00:00:00 2001 From: Stefan Plantikow Date: Tue, 22 Nov 2011 18:08:26 +0100 Subject: [PATCH] std: rewrote math to support most C95 libmath calls on f32, f64 and float --- src/lib/ctypes.rs | 4 + src/lib/math.rs | 389 +++++++++++++++++++++++++++++++-------- src/test/stdtest/math.rs | 12 +- 3 files changed, 323 insertions(+), 82 deletions(-) diff --git a/src/lib/ctypes.rs b/src/lib/ctypes.rs index c48a2c8c073..890300ce781 100644 --- a/src/lib/ctypes.rs +++ b/src/lib/ctypes.rs @@ -5,6 +5,7 @@ Definitions useful for C interop */ type c_int = i32; + type long = int; type unsigned = u32; type ulong = uint; @@ -13,6 +14,9 @@ type intptr_t = uint; type uintptr_t = uint; type uint32_t = u32; +// This *must* match with "import c_float = fXX" in std::math per arch +type c_float = f64; + type size_t = uint; type ssize_t = int; type off_t = uint; diff --git a/src/lib/math.rs b/src/lib/math.rs index 5d826d5ce32..339e6308651 100644 --- a/src/lib/math.rs +++ b/src/lib/math.rs @@ -1,77 +1,173 @@ /* Module: math */ -#[link_name = ""] +export consts; +export min, max; + +export f32, f64; + +// Currently this module supports from -lmath +// C95 - frexp - ldexp - fmod - modf + log2 + log1p + +export + acos, asin, atan, atan2, ceil, cos, cosh, exp, abs, floor, + ln, ln1p, log10, log2, pow, sin, sinh, sqrt, tan, tanh; + +// These two must match in width according to architecture + +import ctypes::c_float; +import c_float = f64; + + +#[link_name = "m"] #[abi = "cdecl"] -native mod libc { - fn sqrt(n: float) -> float; - fn sin(n: float) -> float; - fn asin(n: float) -> float; - fn cos(n: float) -> float; - fn acos(n: float) -> float; - fn tan(n: float) -> float; - fn atan(n: float) -> float; - #[link_name="log"] - fn ln(n: float) -> float; - fn log2(n: float) -> float; - fn log10(n: float) -> float; - fn log1p(n: float) -> float; +native mod f64 { + + // Alpabetically sorted by link_name + + fn acos(n: f64) -> f64; + fn asin(n: f64) -> f64; + fn atan(n: f64) -> f64; + fn atan2(a: f64, b: f64) -> f64; + fn ceil(n: f64) -> f64; + fn cos(n: f64) -> f64; + fn cosh(n: f64) -> f64; + fn exp(n: f64) -> f64; + #[link_name="fabs"] fn abs(n: f64) -> f64; + fn floor(n: f64) -> f64; + #[link_name="log"] fn ln(n: f64) -> f64; + #[link_name="log1p"] fn ln1p(n: f64) -> f64; + fn log10(n: f64) -> f64; + fn log2(n: f64) -> f64; + fn pow(n: f64, e: f64) -> f64; + fn sin(n: f64) -> f64; + fn sinh(n: f64) -> f64; + fn sqrt(n: f64) -> f64; + fn tan(n: f64) -> f64; + fn tanh(n: f64) -> f64; } -/* -Function: sqrt +#[link_name = "m"] +#[abi = "cdecl"] +native mod f32 { -Returns the square root -*/ -pure fn sqrt(x: float) -> float { unsafe { libc::sqrt(x) } } + // Alpabetically sorted by link_name -/* -Function: sin + #[link_name="acosf"] fn acos(n: f32) -> f32; + #[link_name="asinf"] fn asin(n: f32) -> f32; + #[link_name="atanf"] fn atan(n: f32) -> f32; + #[link_name="atan2f"] fn atan2(a: f32, b: f32) -> f32; + #[link_name="ceilf"] fn ceil(n: f32) -> f32; + #[link_name="cosf"] fn cos(n: f32) -> f32; + #[link_name="coshf"] fn cosh(n: f32) -> f32; + #[link_name="expf"] fn exp(n: f32) -> f32; + #[link_name="fabsf"] fn abs(n: f32) -> f32; + #[link_name="floorf"] fn floor(n: f32) -> f32; + #[link_name="powf"] fn pow(n: f32, e: f32) -> f32; + #[link_name="sinf"] fn sin(n: f32) -> f32; + #[link_name="sinhf"] fn sinh(n: f32) -> f32; + #[link_name="sqrtf"] fn sqrt(n: f32) -> f32; + #[link_name="tanf"] fn tan(n: f32) -> f32; + #[link_name="tanhf"] fn tanh(n: f32) -> f32; + #[link_name="logf"] fn ln(n: f32) -> f32; + #[link_name="log1p"] fn ln1p(n: f64) -> f64; + #[link_name="log2f"] fn log2(n: f32) -> f32; + #[link_name="log10f"] fn log10(n: f32) -> f32; +} -Returns the sine of an angle -*/ -pure fn sin(x: float) -> float { unsafe { libc::sin(x) } } -/* -Function: cos +mod consts { + /* + Const: pi -Returns the cosine of an angle -*/ -pure fn cos(x: float) -> float { unsafe { libc::cos(x) } } + Archimedes' constant + */ + const pi: float = 3.14159265358979323846264338327950288; -/* -Function: tan + /* + Const: frac_pi_2 -Returns the tangent of an angle -*/ -pure fn tan(x: float) -> float { unsafe { libc::tan(x) } } + pi/2.0 + */ + const frac_pi_2: float = 1.57079632679489661923132169163975144; -/* -Function: asin + /* + Const: frac_pi_4 -Returns the arcsine of an angle -*/ -pure fn asin(x: float) -> float { unsafe { libc::asin(x) } } + pi/4.0 + */ + const frac_pi_4: float = 0.785398163397448309615660845819875721; -/* -Function: acos + /* + Const: frac_1_pi -Returns the arccosine of an angle -*/ -pure fn acos(x: float) -> float { unsafe { libc::acos(x) } } + 1.0/pi + */ + const frac_1_pi: float = 0.318309886183790671537767526745028724; -/* -Function: atan + /* + Const: frac_2_pi -Returns the arctangent of an angle -*/ -pure fn atan(x: float) -> float { unsafe { libc::atan(x) } } + 2.0/pi + */ + const frac_2_pi: float = 0.636619772367581343075535053490057448; -/* -Const: pi + /* + Const: frac_2_sqrtpi -Archimedes' constant -*/ -const pi: float = 3.141592653589793; + 2.0/sqrt(pi) + */ + const frac_2_sqrtpi: float = 1.12837916709551257389615890312154517; + + /* + Const: sqrt2 + + sqrt(2.0) + */ + const sqrt2: float = 1.41421356237309504880168872420969808; + + /* + Const: frac_1_sqrt2 + + 1.0/sqrt(2.0) + */ + const frac_1_sqrt2: float = 0.707106781186547524400844362104849039; + + /* + Const: e + + Euler's number + */ + const e: float = 2.71828182845904523536028747135266250; + + /* + Const: log2_e + + log2(e) + */ + const log2_e: float = 1.44269504088896340735992468100189214; + + /* + Const: log10_e + + log10(e) + */ + const log10_e: float = 0.434294481903251827651128918916605082; + + /* + Const: ln_2 + + ln(2.0) + */ + const ln_2: float = 0.693147180559945309417232121458176568; + + /* + Const: ln_10 + + ln(10.0) + */ + const ln_10: float = 2.30258509299404568401799145468436421; + +} /* Function: min @@ -88,38 +184,179 @@ Returns the maximum of two values pure fn max(x: T, y: T) -> T { x < y ? y : x } /* -Const: e +Function: acos -Euler's number +Returns the arccosine of an angle (measured in rad) */ -const e: float = 2.718281828459045235; +pure fn acos(x: float) -> float + { unsafe { c_float::acos(x as c_float) as float } } + +/* +Function: asin + +Returns the arcsine of an angle (measured in rad) +*/ +pure fn asin(x: float) -> float + { unsafe { c_float::asin(x as c_float) as float } } + +/* +Function: atan + +Returns the arctangents of an angle (measured in rad) +*/ +pure fn atan(x: float) -> float + { unsafe { c_float::atan(x as c_float) as float } } + + +/* +Function: atan2 + +Returns the arctangent of an angle (measured in rad) +*/ +pure fn atan2(y: float, x: float) -> float + { unsafe { c_float::atan2(y as c_float, x as c_float) as float } } + +/* +Function: ceil + +Returns: + +The smallest integral value less than or equal to `n` +*/ +pure fn ceil(n: float) -> float + { unsafe { c_float::ceil(n as c_float) as float } } + +/* +Function: cos + +Returns the cosine of an angle `x` (measured in rad) +*/ +pure fn cos(x: float) -> float + { unsafe { c_float::cos(x as c_float) as float } } + +/* +Function: cosh + +Returns the hyperbolic cosine of `x` + +*/ +pure fn cosh(x: float) -> float + { unsafe { c_float::cosh(x as c_float) as float } } + + +/* +Function: exp + +Returns: + +e to the power of `n* +*/ +pure fn exp(n: float) -> float + { unsafe { c_float::exp(n as c_float) as float } } + +/* +Function: abs + +Returns: + +The absolute value of `n` + +*/ +pure fn abs(n: float) -> float + { unsafe { c_float::abs(n as c_float) as float } } + +/* +Function: floor + +Returns: + +The largest integral value less than or equal to `n` +*/ +pure fn floor(n: float) -> float + { unsafe { c_float::floor(n as c_float) as float } } /* Function: ln -Returns the natural logaritm +Returns the natural logaritm of `n` */ -pure fn ln(n: float) -> float { unsafe { libc::ln(n) } } +pure fn ln(n: float) -> float + { unsafe { c_float::ln(n as c_float) as float } } /* -Function: log2 - -Returns the logarithm to base 2 -*/ -pure fn log2(n: float) -> float { unsafe { libc::log2(n) } } - -/* -Function: log2 - -Returns the logarithm to base 10 -*/ -pure fn log10(n: float) -> float { unsafe { libc::log10(n) } } - - -/* -Function: log1p +Function: ln1p Returns the natural logarithm of `1+n` accurately, even for very small values of `n` */ -pure fn ln1p(n: float) -> float { unsafe { libc::log1p(n) } } +pure fn ln1p(n: float) -> float + { unsafe { c_float::ln1p(n as c_float) as float } } + +/* +Function: log10 + +Returns the logarithm to base 10 of `n` +*/ +pure fn log10(n: float) -> float + { unsafe { c_float::log10(n as c_float) as float } } + +/* +Function: log2 + +Returns the logarithm to base 2 of `n` +*/ +pure fn log2(n: float) -> float + { unsafe { c_float::log2(n as c_float) as float } } + +/* +Function: pow +*/ +pure fn pow(v: float, e: float) -> float + { unsafe { c_float::pow(v as c_float, e as c_float) as float } } + + +/* +Function: sin + +Returns the sine of an angle `x` (measured in rad) +*/ +pure fn sin(x: float) -> float + { unsafe { c_float::sin(x as c_float) as float } } + +/* +Function: sinh + +Returns the hyperbolic sine of an angle `x` (measured in rad) +*/ +pure fn sinh(x: float) -> float + { unsafe { c_float::sinh(x as c_float) as float } } + +/* +Function: sqrt + +Returns the square root of `x` +*/ +pure fn sqrt(x: float) -> float + { unsafe { c_float::sqrt(x as c_float) as float } } + +/* +Function: tan + +Returns the tangent of an angle `x` (measured in rad) + +*/ +pure fn tan(x: float) -> float + { unsafe { c_float::tan(x as c_float) as float } } + +/* +Function: tanh + +Returns the hyperbolic tangent of an angle `x` (measured in rad) + +*/ +pure fn tanh(x: float) -> float + { unsafe { c_float::tanh(x as c_float) as float } } + + + + diff --git a/src/test/stdtest/math.rs b/src/test/stdtest/math.rs index 12bc31bb0e5..53d93ae3077 100644 --- a/src/test/stdtest/math.rs +++ b/src/test/stdtest/math.rs @@ -24,14 +24,14 @@ fn test_max_min() { fn test_angle() { fn angle(vec: (float, float)) -> float { alt vec { - (0f, y) when y < 0f { 1.5 * std::math::pi } - (0f, y) { 0.5 * std::math::pi } + (0f, y) when y < 0f { 1.5 * consts::pi } + (0f, y) { 0.5 * consts::pi } (x, y) { std::math::atan(y / x) } } } assert angle((1f, 0f)) == 0f; - assert angle((1f, 1f)) == 0.25 * pi; - assert angle((0f, 1f)) == 0.5 * pi; + assert angle((1f, 1f)) == 0.25 * consts::pi; + assert angle((0f, 1f)) == 0.5 * consts::pi; } @@ -42,11 +42,11 @@ fn test_log_functions() { assert log2(1.0) == 0.0; assert log10(1.0) == 0.0; - assert ln(e) == 1.0; + assert ln(consts::e) == 1.0; assert log2(2.0) == 1.0; assert log10(10.0) == 1.0; - assert ln(e*e*e*e) == 4.0; + assert ln(consts::e*consts::e*consts::e*consts::e) == 4.0; assert log2(256.0) == 8.0; assert log10(1000.0) == 3.0;