]> git.lizzy.rs Git - rust.git/commitdiff
Merge branch 'master' into kmath
authorStefan Plantikow <stefan.plantikow@googlemail.com>
Wed, 4 Jan 2012 23:11:25 +0000 (00:11 +0100)
committerStefan Plantikow <stefan.plantikow@googlemail.com>
Thu, 5 Jan 2012 01:07:12 +0000 (02:07 +0100)
Conflicts:
src/libcore/cmath.rs

1  2 
src/libcore/cmath.rs
src/libcore/f32.rs
src/libcore/f64.rs

index dd922ddf1bcb61c37046779249a9493cf5d90d7c,d62476a632e29f5022cd7f9014407d423b9bf4be..4f3c5a8d68b881ee0eb477bcb09cc01a89c4ef6a
@@@ -1,71 -1,41 +1,85 @@@
 +export c_double;
 +export c_float;
 +
  import ctypes::c_int;
 +import ctypes::c_float;
 +import ctypes::c_double;
 +
++// function names are almost identical to C's libmath, a few have been
++// renamed, grep for "rename:"
  #[link_name = "m"]
  #[abi = "cdecl"]
 -native mod f64 {
 +native mod c_double {
  
      // Alpabetically sorted by link_name
  
 -    pure fn acos(n: f64) -> f64;
 -    pure fn asin(n: f64) -> f64;
 -    pure fn atan(n: f64) -> f64;
 -    pure fn atan2(a: f64, b: f64) -> f64;
 -    pure fn ceil(n: f64) -> f64;
 -    pure fn cos(n: f64) -> f64;
 -    pure fn cosh(n: f64) -> f64;
 -    pure fn exp(n: f64) -> f64;
 -    #[link_name="fabs"] pure fn abs(n: f64) -> f64;
 -    pure fn floor(n: f64) -> f64;
 -    pure fn fmod(x: f64, y: f64) -> f64;
 -    pure fn frexp(n: f64, &value: c_int) -> f64;
 -    pure fn ldexp(x: f64, n: c_int) -> f64;
 -    #[link_name="log"] pure fn ln(n: f64) -> f64;
 -    #[link_name="log1p"] pure fn ln1p(n: f64) -> f64;
 -    pure fn log10(n: f64) -> f64;
 +    pure fn acos(n: c_double) -> c_double;
 +    pure fn asin(n: c_double) -> c_double;
 +    pure fn atan(n: c_double) -> c_double;
 +    pure fn atan2(a: c_double, b: c_double) -> c_double;
 +    pure fn cbrt(n: c_double) -> c_double;
 +    pure fn ceil(n: c_double) -> c_double;
 +    pure fn copysign(x: c_double, y: c_double) -> c_double;
 +    pure fn cos(n: c_double) -> c_double;
 +    pure fn cosh(n: c_double) -> c_double;
 +    pure fn erf(n: c_double) -> c_double;
 +    pure fn erfc(n: c_double) -> c_double;
 +    pure fn exp(n: c_double) -> c_double;
 +    pure fn expm1(n: c_double) -> c_double;
 +    pure fn exp2(n: c_double) -> c_double;
 +    #[link_name="fabs"] pure fn abs(n: c_double) -> c_double;
-     #[link_name="fdim"] pure fn sub_pos(a: c_double, b: c_double) -> c_double;
++    // rename: for clarity and consistency with add/sub/mul/div
++    #[link_name="fdim"] pure fn abs_sub(a: c_double, b: c_double) -> c_double;
 +    pure fn floor(n: c_double) -> c_double;
++    // rename: for clarity and consistency with add/sub/mul/div
 +    #[link_name="fma"] pure fn mul_add(a: c_double, b: c_double,
 +                                       c: c_double) -> c_double;
 +    #[link_name="fmax"] pure fn fmax(a: c_double, b: c_double) -> c_double;
 +    #[link_name="fmin"] pure fn fmin(a: c_double, b: c_double) -> c_double;
 +    pure fn nextafter(x: c_double, y: c_double) -> c_double;
 +    pure fn frexp(n: c_double, &value: c_int) -> c_double;
 +    pure fn hypot(x: c_double, y: c_double) -> c_double;
 +    pure fn ldexp(x: c_double, n: c_int) -> c_double;
 +    #[link_name="lgamma_r"] pure fn lgamma(n: c_double,
 +                                           &sign: c_int) -> c_double;
++    // renamed: log is a reserved keyword; ln seems more natural, too
 +    #[link_name="log"] pure fn ln(n: c_double) -> c_double;
-     pure fn logb(n: c_double) -> c_double;
++    // renamed: "logb" /often/ is confused for log2 by beginners
++    #[link_name="logb"] pure fn log_radix(n: c_double) -> c_double;
++    // renamed: to be consitent with log as ln
 +    #[link_name="log1p"] pure fn ln1p(n: c_double) -> c_double;
 +    pure fn log10(n: c_double) -> c_double;
+     #[cfg(target_os="linux")]
+     #[cfg(target_os="macos")]
+     #[cfg(target_os="win32")]
 -    pure fn log2(n: f64) -> f64;
 -    pure fn modf(n: f64, iptr: *f64) -> f64;
 -    pure fn pow(n: f64, e: f64) -> f64;
 -    pure fn rint(n: f64) -> f64;
 -    pure fn round(n: f64) -> f64;
 -    pure fn sin(n: f64) -> f64;
 -    pure fn sinh(n: f64) -> f64;
 -    pure fn sqrt(n: f64) -> f64;
 -    pure fn tan(n: f64) -> f64;
 -    pure fn tanh(n: f64) -> f64;
 -    pure fn trunc(n: f64) -> f64;
 +    pure fn log2(n: c_double) -> c_double;
-     pure fn ilogb(n: c_double) -> c_int;
++    #[link_name="ilogb"] pure fn ilogradix(n: c_double) -> c_int;
 +    pure fn modf(n: c_double, &iptr: c_double) -> c_double;
 +    pure fn pow(n: c_double, e: c_double) -> c_double;
-     pure fn rint(n: c_double) -> c_double;
++// FIXME enable when rounding modes become available
++//    pure fn rint(n: c_double) -> c_double;
 +    pure fn round(n: c_double) -> c_double;
-     pure fn scalbn(n: c_double, i: c_int) -> c_double;
++    // rename: for consistency with logradix
++    #[link_name="scalbn"] pure fn ldexp_radix(n: c_double, i: c_int) ->
++        c_double;
 +    pure fn sin(n: c_double) -> c_double;
 +    pure fn sinh(n: c_double) -> c_double;
 +    pure fn sqrt(n: c_double) -> c_double;
 +    pure fn tan(n: c_double) -> c_double;
 +    pure fn tanh(n: c_double) -> c_double;
 +    pure fn tgamma(n: c_double) -> c_double;
 +    pure fn trunc(n: c_double) -> c_double;
 +
 +    // These are commonly only available for doubles
 +
 +    pure fn j0(n: c_double) -> c_double;
 +    pure fn j1(n: c_double) -> c_double;
 +    pure fn jn(i: c_int, n: c_double) -> c_double;
 +
 +    pure fn y0(n: c_double) -> c_double;
 +    pure fn y1(n: c_double) -> c_double;
 +    pure fn yn(i: c_int, n: c_double) -> c_double;
  }
  
  #[link_name = "m"]
@@@ -74,55 -44,36 +88,59 @@@ native mod c_float 
  
      // Alpabetically sorted by link_name
  
 -    #[link_name="acosf"] pure fn acos(n: f32) -> f32;
 -    #[link_name="asinf"] pure fn asin(n: f32) -> f32;
 -    #[link_name="atanf"] pure fn atan(n: f32) -> f32;
 -    #[link_name="atan2f"] pure fn atan2(a: f32, b: f32) -> f32;
 -    #[link_name="ceilf"] pure fn ceil(n: f32) -> f32;
 -    #[link_name="cosf"] pure fn cos(n: f32) -> f32;
 -    #[link_name="coshf"] pure fn cosh(n: f32) -> f32;
 -    #[link_name="expf"] pure fn exp(n: f32) -> f32;
 -    #[link_name="fabsf"] pure fn abs(n: f32) -> f32;
 -    #[link_name="floorf"] pure fn floor(n: f32) -> f32;
 -    #[link_name="frexpf"] pure fn frexp(n: f64, &value: c_int) -> f32;
 -    #[link_name="fmodf"] pure fn fmod(x: f32, y: f32) -> f32;
 -    #[link_name="ldexpf"] pure fn ldexp(x: f32, n: c_int) -> f32;
 -    #[link_name="logf"] pure fn ln(n: f32) -> f32;
 -    #[link_name="log1p"] pure fn ln1p(n: f64) -> f64;
 +    #[link_name="acosf"] pure fn acos(n: c_float) -> c_float;
 +    #[link_name="asinf"] pure fn asin(n: c_float) -> c_float;
 +    #[link_name="atanf"] pure fn atan(n: c_float) -> c_float;
 +    #[link_name="atan2f"] pure fn atan2(a: c_float, b: c_float) -> c_float;
 +    #[link_name="cbrtf"] pure fn cbrt(n: c_float) -> c_float;
 +    #[link_name="ceilf"] pure fn ceil(n: c_float) -> c_float;
 +    #[link_name="copysignf"] pure fn copysign(x: c_float,
 +                                              y: c_float) -> c_float;
 +    #[link_name="cosf"] pure fn cos(n: c_float) -> c_float;
 +    #[link_name="coshf"] pure fn cosh(n: c_float) -> c_float;
 +    #[link_name="erff"] pure fn erf(n: c_float) -> c_float;
 +    #[link_name="erfcf"] pure fn erfc(n: c_float) -> c_float;
 +    #[link_name="expf"] pure fn exp(n: c_float) -> c_float;
 +    #[link_name="expm1f"]pure fn expm1(n: c_float) -> c_float;
 +    #[link_name="exp2f"] pure fn exp2(n: c_float) -> c_float;
 +    #[link_name="fabsf"] pure fn abs(n: c_float) -> c_float;
-     #[link_name="fdimf"] pure fn sub_pos(a: c_float, b: c_float) -> c_float;
++    #[link_name="fdimf"] pure fn abs_sub(a: c_float, b: c_float) -> c_float;
 +    #[link_name="floorf"] pure fn floor(n: c_float) -> c_float;
 +    #[link_name="frexpf"] pure fn frexp(n: c_float,
 +                                        &value: c_int) -> c_float;
 +    #[link_name="fmaf"] pure fn mul_add(a: c_float,
 +                                        b: c_float, c: c_float) -> c_float;
 +    #[link_name="fmaxf"] pure fn fmax(a: c_float, b: c_float) -> c_float;
 +    #[link_name="fminf"] pure fn fmin(a: c_float, b: c_float) -> c_float;
 +    #[link_name="nextafterf"] pure fn nextafter(x: c_float,
 +                                                y: c_float) -> c_float;
 +    #[link_name="hypotf"] pure fn hypot(x: c_float, y: c_float) -> c_float;
 +    #[link_name="ldexpf"] pure fn ldexp(x: c_float, n: c_int) -> c_float;
 +    #[link_name="lgammaf_r"] pure fn lgamma(n: c_float,
 +                                            &sign: c_int) -> c_float;
 +    #[link_name="logf"] pure fn ln(n: c_float) -> c_float;
-     #[link_name="logbf"] pure fn logb(n: c_float) -> c_float;
++    #[link_name="logbf"] pure fn log_radix(n: c_float) -> c_float;
 +    #[link_name="log1pf"] pure fn ln1p(n: c_float) -> c_float;
+     #[cfg(target_os="linux")]
+     #[cfg(target_os="macos")]
+     #[cfg(target_os="win32")]
 -    #[link_name="log2f"] pure fn log2(n: f32) -> f32;
 -    #[link_name="log10f"] pure fn log10(n: f32) -> f32;
 -    #[link_name="modff"] pure fn modf(n: f32, iptr: *f32) -> f32;
 -    #[link_name="powf"] pure fn pow(n: f32, e: f32) -> f32;
 -    #[link_name="rintf"] pure fn rint(n: f32) -> f32;
 -    #[link_name="roundf"] pure fn round(n: f32) -> f32;
 -    #[link_name="sinf"] pure fn sin(n: f32) -> f32;
 -    #[link_name="sinhf"] pure fn sinh(n: f32) -> f32;
 -    #[link_name="sqrtf"] pure fn sqrt(n: f32) -> f32;
 -    #[link_name="tanf"] pure fn tan(n: f32) -> f32;
 -    #[link_name="tanhf"] pure fn tanh(n: f32) -> f32;
 -    #[link_name="truncf"] pure fn trunc(n: f32) -> f32;
 +    #[link_name="log2f"] pure fn log2(n: c_float) -> c_float;
 +    #[link_name="log10f"] pure fn log10(n: c_float) -> c_float;
-     #[link_name="ilogbf"] pure fn ilogb(n: c_float) -> c_int;
++    #[link_name="ilogbf"] pure fn ilog_radix(n: c_float) -> c_int;
 +    #[link_name="modff"] pure fn modf(n: c_float,
 +                                      &iptr: c_float) -> c_float;
 +    #[link_name="powf"] pure fn pow(n: c_float, e: c_float) -> c_float;
-     #[link_name="rintf"] pure fn rint(n: c_float) -> c_float;
++// FIXME enable when rounding modes become available
++//    #[link_name="rintf"] pure fn rint(n: c_float) -> c_float;
 +    #[link_name="roundf"] pure fn round(n: c_float) -> c_float;
-     #[link_name="scalbnf"] pure fn scalbn(n: c_float, i: c_int) -> c_float;
++    #[link_name="scalbnf"] pure fn ldexp_radix(n: c_float, i: c_int) -> c_float;
 +    #[link_name="sinf"] pure fn sin(n: c_float) -> c_float;
 +    #[link_name="sinhf"] pure fn sinh(n: c_float) -> c_float;
 +    #[link_name="sqrtf"] pure fn sqrt(n: c_float) -> c_float;
 +    #[link_name="tanf"] pure fn tan(n: c_float) -> c_float;
 +    #[link_name="tanhf"] pure fn tanh(n: c_float) -> c_float;
 +    #[link_name="tgammaf"] pure fn tgamma(n: c_float) -> c_float;
 +    #[link_name="truncf"] pure fn trunc(n: c_float) -> c_float;
  }
  
  //
index 26ec20a2ed9fa56e680091c111f6d0aa4a86fbae,a91708580c19f222716fcc09b041b5479c2e6ca8..7c7d45694e50bdc48c1f56cca4ff2057613c63ea
  Module: f32
  
  Floating point operations and constants for `f32`
- pure fn isNaN(f: f32) -> bool { f != f }
 +*/
 +
 +// PORT
 +
 +import cmath::c_float::*;
 +
 +type t = f32;
 +
 +
 +// These are not defined inside consts:: for consistency with
 +// the integer types
 +
 +// PORT check per architecture
 +
++// FIXME obtain these in a different way
++
 +const radix: uint = 2u;
 +
 +const mantissa_digits: uint = 24u;
 +const digits: uint = 6u;
 +
 +const epsilon: f32 = 1.19209290e-07_f32;
 +
 +const min_value: f32 = 1.17549435e-38_f32;
 +const max_value: f32 = 3.40282347e+38_f32;
 +
 +const min_exp: int = -125;
 +const max_exp: int = 128;
 +
 +const min_10_exp: int = -37;
 +const max_10_exp: int = 38;
 +
 +/* Const: NaN */
 +const NaN: f32 = 0.0_f32/0.0_f32;
 +
 +/* Const: infinity */
 +const infinity: f32 = 1.0_f32/0.0_f32;
 +
 +/* Const: neg_infinity */
 +const neg_infinity: f32 = -1.0_f32/0.0_f32;
 +
 +/* Predicate: isNaN */
++pure fn is_NaN(f: f32) -> bool { f != f }
 +
 +/* Function: add */
 +pure fn add(x: f32, y: f32) -> f32 { ret x + y; }
 +
 +/* Function: sub */
 +pure fn sub(x: f32, y: f32) -> f32 { ret x - y; }
 +
 +/* Function: mul */
 +pure fn mul(x: f32, y: f32) -> f32 { ret x * y; }
 +
 +/* Function: div */
 +pure fn div(x: f32, y: f32) -> f32 { ret x / y; }
 +
 +/* Function: rem */
 +pure fn rem(x: f32, y: f32) -> f32 { ret x % y; }
 +
 +/* Predicate: lt */
 +pure fn lt(x: f32, y: f32) -> bool { ret x < y; }
 +
 +/* Predicate: le */
 +pure fn le(x: f32, y: f32) -> bool { ret x <= y; }
 +
 +/* Predicate: eq */
 +pure fn eq(x: f32, y: f32) -> bool { ret x == y; }
 +
 +/* Predicate: ne */
 +pure fn ne(x: f32, y: f32) -> bool { ret x != y; }
 +
 +/* Predicate: ge */
 +pure fn ge(x: f32, y: f32) -> bool { ret x >= y; }
 +
 +/* Predicate: gt */
 +pure fn gt(x: f32, y: f32) -> bool { ret x > y; }
  
 -This exposes the same operations as `math`, just for `f32` even though
 -they do not show up in the docs right now!
++// FIXME replace the predicates below with llvm intrinsics or calls
++// to the libmath macros in the rust runtime for performance
++
 +/*
- Predicate: positive
++Predicate: is_positive
 +
 +Returns true if `x` is a positive number, including +0.0f320 and +Infinity.
 + */
- pure fn positive(x: f32) -> bool
++pure fn is_positive(x: f32) -> bool
 +    { ret x > 0.0f32 || (1.0f32/x) == infinity; }
 +
 +/*
- Predicate: negative
++Predicate: is_negative
 +
 +Returns true if `x` is a negative number, including -0.0f320 and -Infinity.
 + */
- pure fn negative(x: f32) -> bool
++pure fn is_negative(x: f32) -> bool
 +    { ret x < 0.0f32 || (1.0f32/x) == neg_infinity; }
 +
 +/*
- Predicate: nonpositive
++Predicate: is_nonpositive
 +
 +Returns true if `x` is a negative number, including -0.0f320 and -Infinity.
 +(This is the same as `f32::negative`.)
  */
- pure fn nonpositive(x: f32) -> bool {
++pure fn is_nonpositive(x: f32) -> bool {
 +  ret x < 0.0f32 || (1.0f32/x) == neg_infinity;
 +}
  
 -import cmath::f32::*;
 +/*
 +Predicate: nonnegative
  
 -export
 -    acos, asin, atan, atan2, ceil, cos, cosh, exp, abs, floor, fmod,
 -    frexp, ldexp, ln, ln1p, log10, log2, modf, rint, round, pow, sin,
 -    sinh, sqrt, tan, tanh, trunc, t;
 +Returns true if `x` is a positive number, including +0.0f320 and +Infinity.
 +(This is the same as `f32::positive`.)
 +*/
- pure fn nonnegative(x: f32) -> bool {
++pure fn is_nonnegative(x: f32) -> bool {
 +  ret x > 0.0f32 || (1.0f32/x) == infinity;
 +}
  
 -export consts;
++/*
++Predicate: is_zero
 -type t = f32;
++Returns true if `x` is a zero number (positive or negative zero)
++*/
++pure fn is_zero(x: f32) -> bool {
++    ret x == 0.0f32 || x == -0.0f32;
++}
++
++/*
++Predicate: is_infinite
++
++Returns true if `x`is an infinite numer
++*/
++pure fn is_infinite(x: f32) -> bool {
++    ret x == infinity || x == neg_infinity;
++}
++
++/*
++Predicate: is_finite
++
++Returns true if `x`is a finite numer
++*/
++pure fn is_finite(x: f32) -> bool {
++    ret !(is_nan(x) || is_infinite(x));
++}
++
++// FIXME add is_normal, is_subnormal, and fpclassify
  /* Module: consts */
  mod consts {
  
  
      ln(10.0)
      */
 -    const ln_10: f32 = 2.30258509299404568401799145468436421f32;
 +    const ln_10: f32 = 2.30258509299404568401799145468436421_f32;
 +}
 +
++pure fn logarithm(n: f32, b: f32) -> f32 {
++    ret ln(n) / ln(b);
+ }
+ #[cfg(target_os="freebsd")]
+ pure fn log2(n: f32) -> f32 {
 -    ret ln(n) / ln(2f32)
++    ret ln(n) / consts::ln_2;
+ }
  //
  // Local Variables:
  // mode: rust
index c7ee7e1a5dbfa94fa660c79e4849062b2e8f3835,73f807a4285cf7f57b33e4a3fcdb242c4177550d..058d662010604452b5a8e803853a3fd48c6b5276
  /*
  Module: f64
  
 -Floating point operations and constants for `f64`s
 +Floating point operations and constants for `f64`
 +*/
 +
 +// PORT
 +
 +import cmath::c_double::*;
 +
 +type t = f64;
 +
 +
 +// These are not defined inside consts:: for consistency with
 +// the integer types
 +
 +// PORT check per architecture
 +
++// FIXME obtain these in a different way
++
 +const radix: uint = 2u;
 +
 +const mantissa_digits: uint = 53u;
 +const digits: uint = 15u;
 +
 +const epsilon: f64 = 2.2204460492503131e-16_f64;
 +
 +const min_value: f64 = 2.2250738585072014e-308_f64;
 +const max_value: f64 = 1.7976931348623157e+308_f64;
 +
 +const min_exp: int = -1021;
 +const max_exp: int = 1024;
 +
 +const min_10_exp: int = -307;
 +const max_10_exp: int = 308;
 +
 +/* Const: NaN */
 +const NaN: f64 = 0.0_f64/0.0_f64;
 +
 +/* Const: infinity */
 +const infinity: f64 = 1.0_f64/0.0_f64;
 +
 +/* Const: neg_infinity */
 +const neg_infinity: f64 = -1.0_f64/0.0_f64;
 +
 +/* Predicate: isNaN */
- pure fn isNaN(f: f64) -> bool { f != f }
++pure fn is_NaN(f: f64) -> bool { f != f }
 +
 +/* Function: add */
 +pure fn add(x: f64, y: f64) -> f64 { ret x + y; }
 +
 +/* Function: sub */
 +pure fn sub(x: f64, y: f64) -> f64 { ret x - y; }
 +
 +/* Function: mul */
 +pure fn mul(x: f64, y: f64) -> f64 { ret x * y; }
 +
 +/* Function: div */
 +pure fn div(x: f64, y: f64) -> f64 { ret x / y; }
 +
 +/* Function: rem */
 +pure fn rem(x: f64, y: f64) -> f64 { ret x % y; }
 +
 +/* Predicate: lt */
 +pure fn lt(x: f64, y: f64) -> bool { ret x < y; }
 +
 +/* Predicate: le */
 +pure fn le(x: f64, y: f64) -> bool { ret x <= y; }
 +
 +/* Predicate: eq */
 +pure fn eq(x: f64, y: f64) -> bool { ret x == y; }
 +
 +/* Predicate: ne */
 +pure fn ne(x: f64, y: f64) -> bool { ret x != y; }
 +
 +/* Predicate: ge */
 +pure fn ge(x: f64, y: f64) -> bool { ret x >= y; }
  
 -This exposes the same operations as `math`, just for `f64` even though
 -they do not show up in the docs right now!
 +/* Predicate: gt */
 +pure fn gt(x: f64, y: f64) -> bool { ret x > y; }
 +
 +/*
- Predicate: positive
++Predicate: is_positive
 +
 +Returns true if `x` is a positive number, including +0.0f640 and +Infinity.
 + */
- pure fn positive(x: f64) -> bool
++pure fn is_positive(x: f64) -> bool
 +    { ret x > 0.0f64 || (1.0f64/x) == infinity; }
 +
 +/*
- Predicate: negative
++Predicate: is_negative
 +
 +Returns true if `x` is a negative number, including -0.0f640 and -Infinity.
 + */
- pure fn negative(x: f64) -> bool
++pure fn is_negative(x: f64) -> bool
 +    { ret x < 0.0f64 || (1.0f64/x) == neg_infinity; }
 +
 +/*
- Predicate: nonpositive
++Predicate: is_nonpositive
 +
 +Returns true if `x` is a negative number, including -0.0f640 and -Infinity.
 +(This is the same as `f64::negative`.)
  */
- pure fn nonpositive(x: f64) -> bool {
++pure fn is_nonpositive(x: f64) -> bool {
 +  ret x < 0.0f64 || (1.0f64/x) == neg_infinity;
 +}
  
 -import cmath::f64::*;
 +/*
- Predicate: nonnegative
++Predicate: is_nonnegative
  
 -export
 -    acos, asin, atan, atan2, ceil, cos, cosh, exp, abs, floor, fmod,
 -    frexp, ldexp, ln, ln1p, log10, log2, modf, rint, round, pow, sin,
 -    sinh, sqrt, tan, tanh, trunc, t;
 +Returns true if `x` is a positive number, including +0.0f640 and +Infinity.
 +(This is the same as `f64::positive`.)
 +*/
- pure fn nonnegative(x: f64) -> bool {
++pure fn is_nonnegative(x: f64) -> bool {
 +  ret x > 0.0f64 || (1.0f64/x) == infinity;
 +}
  
 -export consts;
++/*
++Predicate: is_zero
 -type t = f64;
++Returns true if `x` is a zero number (positive or negative zero)
++*/
++pure fn is_zero(x: f64) -> bool {
++    ret x == 0.0f64 || x == -0.0f64;
++}
++
++/*
++Predicate: is_infinite
++
++Returns true if `x`is an infinite numer
++*/
++pure fn is_infinite(x: f64) -> bool {
++    ret x == infinity || x == neg_infinity;
++}
++
++/*
++Predicate: is_finite
++
++Returns true if `x`is a finite numer
++*/
++pure fn is_finite(x: f64) -> bool {
++    ret !(is_nan(x) || is_infinite(x));
++}
++
++// FIXME add is_normal, is_subnormal, and fpclassify
  /* Module: consts */
  mod consts {
  
  
      ln(10.0)
      */
 -    const ln_10: f64 = 2.30258509299404568401799145468436421f64;
 +    const ln_10: f64 = 2.30258509299404568401799145468436421_f64;
 +}
 +
++pure fn logarithm(n: f64, b: f64) -> f64 {
++    ret ln(n) / ln(b);
+ }
+ #[cfg(target_os="freebsd")]
+ pure fn log2(n: f64) -> f64 {
 -    ret ln(n) / ln(2f64)
++    ret ln(n) / consts::ln_2;
+ }
  //
  // Local Variables:
  // mode: rust