auto merge of #6071 : bjz/rust/numeric-traits, r=graydon
As part of the numeric trait reform (see issue #4819), I have added the following traits to `core::num` and implemented them for Rust's primitive numeric types: ~~~rust pub trait Bitwise: Not<Self> + BitAnd<Self,Self> + BitOr<Self,Self> + BitXor<Self,Self> + Shl<Self,Self> + Shr<Self,Self> {} pub trait BitCount { fn population_count(&self) -> Self; fn leading_zeros(&self) -> Self; fn trailing_zeros(&self) -> Self; } pub trait Bounded { fn min_value() -> Self; fn max_value() -> Self; } pub trait Primitive: Num + NumCast + Bounded + Neg<Self> + Add<Self,Self> + Sub<Self,Self> + Mul<Self,Self> + Quot<Self,Self> + Rem<Self,Self> { fn bits() -> uint; fn bytes() -> uint; } pub trait Int: Integer + Primitive + Bitwise + BitCount {} pub trait Float: Real + Signed + Primitive { fn NaN() -> Self; fn infinity() -> Self; fn neg_infinity() -> Self; fn neg_zero() -> Self; fn is_NaN(&self) -> bool; fn is_infinite(&self) -> bool; fn is_finite(&self) -> bool; fn mantissa_digits() -> uint; fn digits() -> uint; fn epsilon() -> Self; fn min_exp() -> int; fn max_exp() -> int; fn min_10_exp() -> int; fn max_10_exp() -> int; fn mul_add(&self, a: Self, b: Self) -> Self; fn next_after(&self, other: Self) -> Self; } ~~~ Note: I'm not sure my implementation for `BitCount::trailing_zeros` and `BitCount::leading_zeros` is correct for uints. I also need some assistance creating appropriate unit tests for them. More work needs to be done in implementing specialized primitive floating-point and integer methods, but I'm beginning to reach the limits of my knowledge. Please leave your suggestions/critiques/ideas on #4819 if you have them – I'd very much appreciate hearing them. I have also added an `Orderable` trait: ~~~rust pub trait Orderable: Ord { fn min(&self, other: &Self) -> Self; fn max(&self, other: &Self) -> Self; fn clamp(&self, mn: &Self, mx: &Self) -> Self; } ~~~ This is a temporary trait until we have default methods. We don't want to encumber all implementors of Ord by requiring them to implement these functions, but at the same time we want to be able to take advantage of the speed of the specific numeric functions (like the `fmin` and `fmax` intrinsics).
This commit is contained in:
commit
aa38867e4e
@ -104,8 +104,11 @@ pub use iter::{CopyableOrderedIter, CopyableNonstrictIter, Times};
|
||||
pub use iter::{ExtendedMutableIter};
|
||||
|
||||
pub use num::{Num, NumCast};
|
||||
pub use num::{Signed, Unsigned, Integer};
|
||||
pub use num::{Orderable, Signed, Unsigned, Integer};
|
||||
pub use num::{Round, Fractional, Real, RealExt};
|
||||
pub use num::{Bitwise, BitCount, Bounded};
|
||||
pub use num::{Primitive, Int, Float};
|
||||
|
||||
pub use ptr::Ptr;
|
||||
pub use to_str::ToStr;
|
||||
pub use clone::Clone;
|
||||
|
@ -47,7 +47,8 @@ pub mod c_double_utils {
|
||||
unsafe fn fmax(a: c_double, b: c_double) -> c_double;
|
||||
#[link_name="fmin"]
|
||||
unsafe fn fmin(a: c_double, b: c_double) -> c_double;
|
||||
unsafe fn nextafter(x: c_double, y: c_double) -> c_double;
|
||||
#[link_name="nextafter"]
|
||||
unsafe fn next_after(x: c_double, y: c_double) -> c_double;
|
||||
unsafe fn frexp(n: c_double, value: &mut c_int) -> c_double;
|
||||
unsafe fn hypot(x: c_double, y: c_double) -> c_double;
|
||||
unsafe fn ldexp(x: c_double, n: c_int) -> c_double;
|
||||
@ -131,7 +132,7 @@ pub mod c_float_utils {
|
||||
#[link_name="fminf"]
|
||||
unsafe fn fmin(a: c_float, b: c_float) -> c_float;
|
||||
#[link_name="nextafterf"]
|
||||
unsafe fn nextafter(x: c_float, y: c_float) -> c_float;
|
||||
unsafe fn next_after(x: c_float, y: c_float) -> c_float;
|
||||
#[link_name="hypotf"]
|
||||
unsafe fn hypot(x: c_float, y: c_float) -> c_float;
|
||||
#[link_name="ldexpf"]
|
||||
|
@ -12,7 +12,7 @@
|
||||
|
||||
use from_str;
|
||||
use libc::c_int;
|
||||
use num::strconv;
|
||||
use num::{Zero, One, strconv};
|
||||
use prelude::*;
|
||||
|
||||
pub use cmath::c_float_targ_consts::*;
|
||||
@ -88,7 +88,7 @@ delegate!(
|
||||
fn abs_sub(a: c_float, b: c_float) -> c_float = c_float_utils::abs_sub,
|
||||
fn fmax(a: c_float, b: c_float) -> c_float = c_float_utils::fmax,
|
||||
fn fmin(a: c_float, b: c_float) -> c_float = c_float_utils::fmin,
|
||||
fn nextafter(x: c_float, y: c_float) -> c_float = c_float_utils::nextafter,
|
||||
fn next_after(x: c_float, y: c_float) -> c_float = c_float_utils::next_after,
|
||||
fn frexp(n: c_float, value: &mut c_int) -> c_float = c_float_utils::frexp,
|
||||
fn hypot(x: c_float, y: c_float) -> c_float = c_float_utils::hypot,
|
||||
fn ldexp(x: c_float, n: c_int) -> c_float = c_float_utils::ldexp,
|
||||
@ -114,9 +114,6 @@ pub static infinity: f32 = 1.0_f32/0.0_f32;
|
||||
|
||||
pub static neg_infinity: f32 = -1.0_f32/0.0_f32;
|
||||
|
||||
#[inline(always)]
|
||||
pub fn is_NaN(f: f32) -> bool { f != f }
|
||||
|
||||
#[inline(always)]
|
||||
pub fn add(x: f32, y: f32) -> f32 { return x + y; }
|
||||
|
||||
@ -154,24 +151,6 @@ pub fn gt(x: f32, y: f32) -> bool { return x > y; }
|
||||
// FIXME (#1999): replace the predicates below with llvm intrinsics or
|
||||
// calls to the libmath macros in the rust runtime for performance.
|
||||
|
||||
/// Returns true if `x` is a zero number (positive or negative zero)
|
||||
#[inline(always)]
|
||||
pub fn is_zero(x: f32) -> bool {
|
||||
return x == 0.0f32 || x == -0.0f32;
|
||||
}
|
||||
|
||||
/// Returns true if `x`is an infinite number
|
||||
#[inline(always)]
|
||||
pub fn is_infinite(x: f32) -> bool {
|
||||
return x == infinity || x == neg_infinity;
|
||||
}
|
||||
|
||||
/// Returns true if `x`is a finite number
|
||||
#[inline(always)]
|
||||
pub fn is_finite(x: f32) -> bool {
|
||||
return !(is_NaN(x) || is_infinite(x));
|
||||
}
|
||||
|
||||
// FIXME (#1999): add is_normal, is_subnormal, and fpclassify.
|
||||
|
||||
/* Module: consts */
|
||||
@ -245,12 +224,40 @@ impl Ord for f32 {
|
||||
fn gt(&self, other: &f32) -> bool { (*self) > (*other) }
|
||||
}
|
||||
|
||||
impl num::Zero for f32 {
|
||||
impl Orderable for f32 {
|
||||
/// Returns `NaN` if either of the numbers are `NaN`.
|
||||
#[inline(always)]
|
||||
fn zero() -> f32 { 0.0 }
|
||||
fn min(&self, other: &f32) -> f32 {
|
||||
if self.is_NaN() || other.is_NaN() { Float::NaN() } else { fmin(*self, *other) }
|
||||
}
|
||||
|
||||
/// Returns `NaN` if either of the numbers are `NaN`.
|
||||
#[inline(always)]
|
||||
fn max(&self, other: &f32) -> f32 {
|
||||
if self.is_NaN() || other.is_NaN() { Float::NaN() } else { fmax(*self, *other) }
|
||||
}
|
||||
|
||||
/// Returns the number constrained within the range `mn <= self <= mx`.
|
||||
/// If any of the numbers are `NaN` then `NaN` is returned.
|
||||
#[inline(always)]
|
||||
fn clamp(&self, mn: &f32, mx: &f32) -> f32 {
|
||||
if self.is_NaN() { *self }
|
||||
else if !(*self <= *mx) { *mx }
|
||||
else if !(*self >= *mn) { *mn }
|
||||
else { *self }
|
||||
}
|
||||
}
|
||||
|
||||
impl num::One for f32 {
|
||||
impl Zero for f32 {
|
||||
#[inline(always)]
|
||||
fn zero() -> f32 { 0.0 }
|
||||
|
||||
/// Returns true if the number is equal to either `0.0` or `-0.0`
|
||||
#[inline(always)]
|
||||
fn is_zero(&self) -> bool { *self == 0.0 || *self == -0.0 }
|
||||
}
|
||||
|
||||
impl One for f32 {
|
||||
#[inline(always)]
|
||||
fn one() -> f32 { 1.0 }
|
||||
}
|
||||
@ -306,16 +313,16 @@ impl Signed for f32 {
|
||||
#[inline(always)]
|
||||
fn abs(&self) -> f32 { abs(*self) }
|
||||
|
||||
/**
|
||||
* # Returns
|
||||
*
|
||||
* - `1.0` if the number is positive, `+0.0` or `infinity`
|
||||
* - `-1.0` if the number is negative, `-0.0` or `neg_infinity`
|
||||
* - `NaN` if the number is `NaN`
|
||||
*/
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
/// - `1.0` if the number is positive, `+0.0` or `infinity`
|
||||
/// - `-1.0` if the number is negative, `-0.0` or `neg_infinity`
|
||||
/// - `NaN` if the number is NaN
|
||||
///
|
||||
#[inline(always)]
|
||||
fn signum(&self) -> f32 {
|
||||
if is_NaN(*self) { NaN } else { copysign(1.0, *self) }
|
||||
if self.is_NaN() { NaN } else { copysign(1.0, *self) }
|
||||
}
|
||||
|
||||
/// Returns `true` if the number is positive, including `+0.0` and `infinity`
|
||||
@ -511,17 +518,99 @@ impl Real for f32 {
|
||||
fn tanh(&self) -> f32 { tanh(*self) }
|
||||
}
|
||||
|
||||
/**
|
||||
* Section: String Conversions
|
||||
*/
|
||||
impl Bounded for f32 {
|
||||
#[inline(always)]
|
||||
fn min_value() -> f32 { 1.17549435e-38 }
|
||||
|
||||
/**
|
||||
* Converts a float to a string
|
||||
*
|
||||
* # Arguments
|
||||
*
|
||||
* * num - The float value
|
||||
*/
|
||||
#[inline(always)]
|
||||
fn max_value() -> f32 { 3.40282347e+38 }
|
||||
}
|
||||
|
||||
impl Primitive for f32 {
|
||||
#[inline(always)]
|
||||
fn bits() -> uint { 32 }
|
||||
|
||||
#[inline(always)]
|
||||
fn bytes() -> uint { Primitive::bits::<f32>() / 8 }
|
||||
}
|
||||
|
||||
impl Float for f32 {
|
||||
#[inline(always)]
|
||||
fn NaN() -> f32 { 0.0 / 0.0 }
|
||||
|
||||
#[inline(always)]
|
||||
fn infinity() -> f32 { 1.0 / 0.0 }
|
||||
|
||||
#[inline(always)]
|
||||
fn neg_infinity() -> f32 { -1.0 / 0.0 }
|
||||
|
||||
#[inline(always)]
|
||||
fn neg_zero() -> f32 { -0.0 }
|
||||
|
||||
#[inline(always)]
|
||||
fn is_NaN(&self) -> bool { *self != *self }
|
||||
|
||||
#[inline(always)]
|
||||
fn mantissa_digits() -> uint { 24 }
|
||||
|
||||
#[inline(always)]
|
||||
fn digits() -> uint { 6 }
|
||||
|
||||
#[inline(always)]
|
||||
fn epsilon() -> f32 { 1.19209290e-07 }
|
||||
|
||||
#[inline(always)]
|
||||
fn min_exp() -> int { -125 }
|
||||
|
||||
#[inline(always)]
|
||||
fn max_exp() -> int { 128 }
|
||||
|
||||
#[inline(always)]
|
||||
fn min_10_exp() -> int { -37 }
|
||||
|
||||
#[inline(always)]
|
||||
fn max_10_exp() -> int { 38 }
|
||||
|
||||
/// Returns `true` if the number is infinite
|
||||
#[inline(always)]
|
||||
fn is_infinite(&self) -> bool {
|
||||
*self == Float::infinity() || *self == Float::neg_infinity()
|
||||
}
|
||||
|
||||
/// Returns `true` if the number is finite
|
||||
#[inline(always)]
|
||||
fn is_finite(&self) -> bool {
|
||||
!(self.is_NaN() || self.is_infinite())
|
||||
}
|
||||
|
||||
///
|
||||
/// Fused multiply-add. Computes `(self * a) + b` with only one rounding error. This
|
||||
/// produces a more accurate result with better performance than a separate multiplication
|
||||
/// operation followed by an add.
|
||||
///
|
||||
#[inline(always)]
|
||||
fn mul_add(&self, a: f32, b: f32) -> f32 {
|
||||
mul_add(*self, a, b)
|
||||
}
|
||||
|
||||
/// Returns the next representable floating-point value in the direction of `other`
|
||||
#[inline(always)]
|
||||
fn next_after(&self, other: f32) -> f32 {
|
||||
next_after(*self, other)
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Section: String Conversions
|
||||
//
|
||||
|
||||
///
|
||||
/// Converts a float to a string
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * num - The float value
|
||||
///
|
||||
#[inline(always)]
|
||||
pub fn to_str(num: f32) -> ~str {
|
||||
let (r, _) = strconv::to_str_common(
|
||||
@ -529,13 +618,13 @@ pub fn to_str(num: f32) -> ~str {
|
||||
r
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a float to a string in hexadecimal format
|
||||
*
|
||||
* # Arguments
|
||||
*
|
||||
* * num - The float value
|
||||
*/
|
||||
///
|
||||
/// Converts a float to a string in hexadecimal format
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * num - The float value
|
||||
///
|
||||
#[inline(always)]
|
||||
pub fn to_str_hex(num: f32) -> ~str {
|
||||
let (r, _) = strconv::to_str_common(
|
||||
@ -543,20 +632,20 @@ pub fn to_str_hex(num: f32) -> ~str {
|
||||
r
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a float to a string in a given radix
|
||||
*
|
||||
* # Arguments
|
||||
*
|
||||
* * num - The float value
|
||||
* * radix - The base to use
|
||||
*
|
||||
* # Failure
|
||||
*
|
||||
* Fails if called on a special value like `inf`, `-inf` or `NaN` due to
|
||||
* possible misinterpretation of the result at higher bases. If those values
|
||||
* are expected, use `to_str_radix_special()` instead.
|
||||
*/
|
||||
///
|
||||
/// Converts a float to a string in a given radix
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * num - The float value
|
||||
/// * radix - The base to use
|
||||
///
|
||||
/// # Failure
|
||||
///
|
||||
/// Fails if called on a special value like `inf`, `-inf` or `NaN` due to
|
||||
/// possible misinterpretation of the result at higher bases. If those values
|
||||
/// are expected, use `to_str_radix_special()` instead.
|
||||
///
|
||||
#[inline(always)]
|
||||
pub fn to_str_radix(num: f32, rdx: uint) -> ~str {
|
||||
let (r, special) = strconv::to_str_common(
|
||||
@ -566,30 +655,30 @@ pub fn to_str_radix(num: f32, rdx: uint) -> ~str {
|
||||
r
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a float to a string in a given radix, and a flag indicating
|
||||
* whether it's a special value
|
||||
*
|
||||
* # Arguments
|
||||
*
|
||||
* * num - The float value
|
||||
* * radix - The base to use
|
||||
*/
|
||||
///
|
||||
/// Converts a float to a string in a given radix, and a flag indicating
|
||||
/// whether it's a special value
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * num - The float value
|
||||
/// * radix - The base to use
|
||||
///
|
||||
#[inline(always)]
|
||||
pub fn to_str_radix_special(num: f32, rdx: uint) -> (~str, bool) {
|
||||
strconv::to_str_common(&num, rdx, true,
|
||||
strconv::SignNeg, strconv::DigAll)
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a float to a string with exactly the number of
|
||||
* provided significant digits
|
||||
*
|
||||
* # Arguments
|
||||
*
|
||||
* * num - The float value
|
||||
* * digits - The number of significant digits
|
||||
*/
|
||||
///
|
||||
/// Converts a float to a string with exactly the number of
|
||||
/// provided significant digits
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * num - The float value
|
||||
/// * digits - The number of significant digits
|
||||
///
|
||||
#[inline(always)]
|
||||
pub fn to_str_exact(num: f32, dig: uint) -> ~str {
|
||||
let (r, _) = strconv::to_str_common(
|
||||
@ -597,15 +686,15 @@ pub fn to_str_exact(num: f32, dig: uint) -> ~str {
|
||||
r
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a float to a string with a maximum number of
|
||||
* significant digits
|
||||
*
|
||||
* # Arguments
|
||||
*
|
||||
* * num - The float value
|
||||
* * digits - The number of significant digits
|
||||
*/
|
||||
///
|
||||
/// Converts a float to a string with a maximum number of
|
||||
/// significant digits
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * num - The float value
|
||||
/// * digits - The number of significant digits
|
||||
///
|
||||
#[inline(always)]
|
||||
pub fn to_str_digits(num: f32, dig: uint) -> ~str {
|
||||
let (r, _) = strconv::to_str_common(
|
||||
@ -625,91 +714,91 @@ impl num::ToStrRadix for f32 {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a string in base 10 to a float.
|
||||
* Accepts a optional decimal exponent.
|
||||
*
|
||||
* This function accepts strings such as
|
||||
*
|
||||
* * '3.14'
|
||||
* * '+3.14', equivalent to '3.14'
|
||||
* * '-3.14'
|
||||
* * '2.5E10', or equivalently, '2.5e10'
|
||||
* * '2.5E-10'
|
||||
* * '.' (understood as 0)
|
||||
* * '5.'
|
||||
* * '.5', or, equivalently, '0.5'
|
||||
* * '+inf', 'inf', '-inf', 'NaN'
|
||||
*
|
||||
* Leading and trailing whitespace represent an error.
|
||||
*
|
||||
* # Arguments
|
||||
*
|
||||
* * num - A string
|
||||
*
|
||||
* # Return value
|
||||
*
|
||||
* `none` if the string did not represent a valid number. Otherwise,
|
||||
* `Some(n)` where `n` is the floating-point number represented by `num`.
|
||||
*/
|
||||
///
|
||||
/// Convert a string in base 10 to a float.
|
||||
/// Accepts a optional decimal exponent.
|
||||
///
|
||||
/// This function accepts strings such as
|
||||
///
|
||||
/// * '3.14'
|
||||
/// * '+3.14', equivalent to '3.14'
|
||||
/// * '-3.14'
|
||||
/// * '2.5E10', or equivalently, '2.5e10'
|
||||
/// * '2.5E-10'
|
||||
/// * '.' (understood as 0)
|
||||
/// * '5.'
|
||||
/// * '.5', or, equivalently, '0.5'
|
||||
/// * '+inf', 'inf', '-inf', 'NaN'
|
||||
///
|
||||
/// Leading and trailing whitespace represent an error.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * num - A string
|
||||
///
|
||||
/// # Return value
|
||||
///
|
||||
/// `none` if the string did not represent a valid number. Otherwise,
|
||||
/// `Some(n)` where `n` is the floating-point number represented by `num`.
|
||||
///
|
||||
#[inline(always)]
|
||||
pub fn from_str(num: &str) -> Option<f32> {
|
||||
strconv::from_str_common(num, 10u, true, true, true,
|
||||
strconv::ExpDec, false, false)
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a string in base 16 to a float.
|
||||
* Accepts a optional binary exponent.
|
||||
*
|
||||
* This function accepts strings such as
|
||||
*
|
||||
* * 'a4.fe'
|
||||
* * '+a4.fe', equivalent to 'a4.fe'
|
||||
* * '-a4.fe'
|
||||
* * '2b.aP128', or equivalently, '2b.ap128'
|
||||
* * '2b.aP-128'
|
||||
* * '.' (understood as 0)
|
||||
* * 'c.'
|
||||
* * '.c', or, equivalently, '0.c'
|
||||
* * '+inf', 'inf', '-inf', 'NaN'
|
||||
*
|
||||
* Leading and trailing whitespace represent an error.
|
||||
*
|
||||
* # Arguments
|
||||
*
|
||||
* * num - A string
|
||||
*
|
||||
* # Return value
|
||||
*
|
||||
* `none` if the string did not represent a valid number. Otherwise,
|
||||
* `Some(n)` where `n` is the floating-point number represented by `[num]`.
|
||||
*/
|
||||
///
|
||||
/// Convert a string in base 16 to a float.
|
||||
/// Accepts a optional binary exponent.
|
||||
///
|
||||
/// This function accepts strings such as
|
||||
///
|
||||
/// * 'a4.fe'
|
||||
/// * '+a4.fe', equivalent to 'a4.fe'
|
||||
/// * '-a4.fe'
|
||||
/// * '2b.aP128', or equivalently, '2b.ap128'
|
||||
/// * '2b.aP-128'
|
||||
/// * '.' (understood as 0)
|
||||
/// * 'c.'
|
||||
/// * '.c', or, equivalently, '0.c'
|
||||
/// * '+inf', 'inf', '-inf', 'NaN'
|
||||
///
|
||||
/// Leading and trailing whitespace represent an error.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * num - A string
|
||||
///
|
||||
/// # Return value
|
||||
///
|
||||
/// `none` if the string did not represent a valid number. Otherwise,
|
||||
/// `Some(n)` where `n` is the floating-point number represented by `[num]`.
|
||||
///
|
||||
#[inline(always)]
|
||||
pub fn from_str_hex(num: &str) -> Option<f32> {
|
||||
strconv::from_str_common(num, 16u, true, true, true,
|
||||
strconv::ExpBin, false, false)
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a string in an given base to a float.
|
||||
*
|
||||
* Due to possible conflicts, this function does **not** accept
|
||||
* the special values `inf`, `-inf`, `+inf` and `NaN`, **nor**
|
||||
* does it recognize exponents of any kind.
|
||||
*
|
||||
* Leading and trailing whitespace represent an error.
|
||||
*
|
||||
* # Arguments
|
||||
*
|
||||
* * num - A string
|
||||
* * radix - The base to use. Must lie in the range [2 .. 36]
|
||||
*
|
||||
* # Return value
|
||||
*
|
||||
* `none` if the string did not represent a valid number. Otherwise,
|
||||
* `Some(n)` where `n` is the floating-point number represented by `num`.
|
||||
*/
|
||||
///
|
||||
/// Convert a string in an given base to a float.
|
||||
///
|
||||
/// Due to possible conflicts, this function does **not** accept
|
||||
/// the special values `inf`, `-inf`, `+inf` and `NaN`, **nor**
|
||||
/// does it recognize exponents of any kind.
|
||||
///
|
||||
/// Leading and trailing whitespace represent an error.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * num - A string
|
||||
/// * radix - The base to use. Must lie in the range [2 .. 36]
|
||||
///
|
||||
/// # Return value
|
||||
///
|
||||
/// `none` if the string did not represent a valid number. Otherwise,
|
||||
/// `Some(n)` where `n` is the floating-point number represented by `num`.
|
||||
///
|
||||
#[inline(always)]
|
||||
pub fn from_str_radix(num: &str, rdx: uint) -> Option<f32> {
|
||||
strconv::from_str_common(num, rdx, true, true, false,
|
||||
@ -748,6 +837,28 @@ mod tests {
|
||||
num::test_num(10f32, 2f32);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_min() {
|
||||
assert_eq!(1f32.min(&2f32), 1f32);
|
||||
assert_eq!(2f32.min(&1f32), 1f32);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_max() {
|
||||
assert_eq!(1f32.max(&2f32), 2f32);
|
||||
assert_eq!(2f32.max(&1f32), 2f32);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_clamp() {
|
||||
assert_eq!(1f32.clamp(&2f32, &4f32), 2f32);
|
||||
assert_eq!(8f32.clamp(&2f32, &4f32), 4f32);
|
||||
assert_eq!(3f32.clamp(&2f32, &4f32), 3f32);
|
||||
assert!(3f32.clamp(&Float::NaN::<f32>(), &4f32).is_NaN());
|
||||
assert!(3f32.clamp(&2f32, &Float::NaN::<f32>()).is_NaN());
|
||||
assert!(Float::NaN::<f32>().clamp(&2f32, &4f32).is_NaN());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_floor() {
|
||||
assert_fuzzy_eq!(1.0f32.floor(), 1.0f32);
|
||||
@ -846,7 +957,7 @@ mod tests {
|
||||
assert_eq!((-1f32).abs(), 1f32);
|
||||
assert_eq!(neg_infinity.abs(), infinity);
|
||||
assert_eq!((1f32/neg_infinity).abs(), 0f32);
|
||||
assert!(is_NaN(NaN.abs()));
|
||||
assert!(NaN.abs().is_NaN());
|
||||
|
||||
assert_eq!(infinity.signum(), 1f32);
|
||||
assert_eq!(1f32.signum(), 1f32);
|
||||
@ -855,7 +966,7 @@ mod tests {
|
||||
assert_eq!((-1f32).signum(), -1f32);
|
||||
assert_eq!(neg_infinity.signum(), -1f32);
|
||||
assert_eq!((1f32/neg_infinity).signum(), -1f32);
|
||||
assert!(is_NaN(NaN.signum()));
|
||||
assert!(NaN.signum().is_NaN());
|
||||
|
||||
assert!(infinity.is_positive());
|
||||
assert!(1f32.is_positive());
|
||||
@ -875,6 +986,12 @@ mod tests {
|
||||
assert!((1f32/neg_infinity).is_negative());
|
||||
assert!(!NaN.is_negative());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_primitive() {
|
||||
assert_eq!(Primitive::bits::<f32>(), sys::size_of::<f32>() * 8);
|
||||
assert_eq!(Primitive::bytes::<f32>(), sys::size_of::<f32>());
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -12,7 +12,7 @@
|
||||
|
||||
use from_str;
|
||||
use libc::c_int;
|
||||
use num::strconv;
|
||||
use num::{Zero, One, strconv};
|
||||
use prelude::*;
|
||||
|
||||
pub use cmath::c_double_targ_consts::*;
|
||||
@ -89,7 +89,7 @@ delegate!(
|
||||
fn abs_sub(a: c_double, b: c_double) -> c_double = c_double_utils::abs_sub,
|
||||
fn fmax(a: c_double, b: c_double) -> c_double = c_double_utils::fmax,
|
||||
fn fmin(a: c_double, b: c_double) -> c_double = c_double_utils::fmin,
|
||||
fn nextafter(x: c_double, y: c_double) -> c_double = c_double_utils::nextafter,
|
||||
fn next_after(x: c_double, y: c_double) -> c_double = c_double_utils::next_after,
|
||||
fn frexp(n: c_double, value: &mut c_int) -> c_double = c_double_utils::frexp,
|
||||
fn hypot(x: c_double, y: c_double) -> c_double = c_double_utils::hypot,
|
||||
fn ldexp(x: c_double, n: c_int) -> c_double = c_double_utils::ldexp,
|
||||
@ -138,9 +138,6 @@ pub static infinity: f64 = 1.0_f64/0.0_f64;
|
||||
|
||||
pub static neg_infinity: f64 = -1.0_f64/0.0_f64;
|
||||
|
||||
#[inline(always)]
|
||||
pub fn is_NaN(f: f64) -> bool { f != f }
|
||||
|
||||
#[inline(always)]
|
||||
pub fn add(x: f64, y: f64) -> f64 { return x + y; }
|
||||
|
||||
@ -174,24 +171,6 @@ pub fn ge(x: f64, y: f64) -> bool { return x >= y; }
|
||||
#[inline(always)]
|
||||
pub fn gt(x: f64, y: f64) -> bool { return x > y; }
|
||||
|
||||
/// Returns true if `x` is a zero number (positive or negative zero)
|
||||
#[inline(always)]
|
||||
pub fn is_zero(x: f64) -> bool {
|
||||
return x == 0.0f64 || x == -0.0f64;
|
||||
}
|
||||
|
||||
/// Returns true if `x`is an infinite number
|
||||
#[inline(always)]
|
||||
pub fn is_infinite(x: f64) -> bool {
|
||||
return x == infinity || x == neg_infinity;
|
||||
}
|
||||
|
||||
/// Returns true if `x` is a finite number
|
||||
#[inline(always)]
|
||||
pub fn is_finite(x: f64) -> bool {
|
||||
return !(is_NaN(x) || is_infinite(x));
|
||||
}
|
||||
|
||||
|
||||
// FIXME (#1999): add is_normal, is_subnormal, and fpclassify
|
||||
|
||||
@ -266,12 +245,40 @@ impl Ord for f64 {
|
||||
fn gt(&self, other: &f64) -> bool { (*self) > (*other) }
|
||||
}
|
||||
|
||||
impl num::Zero for f64 {
|
||||
impl Orderable for f64 {
|
||||
/// Returns `NaN` if either of the numbers are `NaN`.
|
||||
#[inline(always)]
|
||||
fn zero() -> f64 { 0.0 }
|
||||
fn min(&self, other: &f64) -> f64 {
|
||||
if self.is_NaN() || other.is_NaN() { Float::NaN() } else { fmin(*self, *other) }
|
||||
}
|
||||
|
||||
/// Returns `NaN` if either of the numbers are `NaN`.
|
||||
#[inline(always)]
|
||||
fn max(&self, other: &f64) -> f64 {
|
||||
if self.is_NaN() || other.is_NaN() { Float::NaN() } else { fmax(*self, *other) }
|
||||
}
|
||||
|
||||
/// Returns the number constrained within the range `mn <= self <= mx`.
|
||||
/// If any of the numbers are `NaN` then `NaN` is returned.
|
||||
#[inline(always)]
|
||||
fn clamp(&self, mn: &f64, mx: &f64) -> f64 {
|
||||
if self.is_NaN() { *self }
|
||||
else if !(*self <= *mx) { *mx }
|
||||
else if !(*self >= *mn) { *mn }
|
||||
else { *self }
|
||||
}
|
||||
}
|
||||
|
||||
impl num::One for f64 {
|
||||
impl Zero for f64 {
|
||||
#[inline(always)]
|
||||
fn zero() -> f64 { 0.0 }
|
||||
|
||||
/// Returns true if the number is equal to either `0.0` or `-0.0`
|
||||
#[inline(always)]
|
||||
fn is_zero(&self) -> bool { *self == 0.0 || *self == -0.0 }
|
||||
}
|
||||
|
||||
impl One for f64 {
|
||||
#[inline(always)]
|
||||
fn one() -> f64 { 1.0 }
|
||||
}
|
||||
@ -316,16 +323,16 @@ impl Signed for f64 {
|
||||
#[inline(always)]
|
||||
fn abs(&self) -> f64 { abs(*self) }
|
||||
|
||||
/**
|
||||
* # Returns
|
||||
*
|
||||
* - `1.0` if the number is positive, `+0.0` or `infinity`
|
||||
* - `-1.0` if the number is negative, `-0.0` or `neg_infinity`
|
||||
* - `NaN` if the number is `NaN`
|
||||
*/
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
/// - `1.0` if the number is positive, `+0.0` or `infinity`
|
||||
/// - `-1.0` if the number is negative, `-0.0` or `neg_infinity`
|
||||
/// - `NaN` if the number is NaN
|
||||
///
|
||||
#[inline(always)]
|
||||
fn signum(&self) -> f64 {
|
||||
if is_NaN(*self) { NaN } else { copysign(1.0, *self) }
|
||||
if self.is_NaN() { NaN } else { copysign(1.0, *self) }
|
||||
}
|
||||
|
||||
/// Returns `true` if the number is positive, including `+0.0` and `infinity`
|
||||
@ -551,17 +558,99 @@ impl RealExt for f64 {
|
||||
fn yn(&self, n: int) -> f64 { yn(n as c_int, *self) }
|
||||
}
|
||||
|
||||
/**
|
||||
* Section: String Conversions
|
||||
*/
|
||||
impl Bounded for f64 {
|
||||
#[inline(always)]
|
||||
fn min_value() -> f64 { 2.2250738585072014e-308 }
|
||||
|
||||
/**
|
||||
* Converts a float to a string
|
||||
*
|
||||
* # Arguments
|
||||
*
|
||||
* * num - The float value
|
||||
*/
|
||||
#[inline(always)]
|
||||
fn max_value() -> f64 { 1.7976931348623157e+308 }
|
||||
}
|
||||
|
||||
impl Primitive for f64 {
|
||||
#[inline(always)]
|
||||
fn bits() -> uint { 64 }
|
||||
|
||||
#[inline(always)]
|
||||
fn bytes() -> uint { Primitive::bits::<f64>() / 8 }
|
||||
}
|
||||
|
||||
impl Float for f64 {
|
||||
#[inline(always)]
|
||||
fn NaN() -> f64 { 0.0 / 0.0 }
|
||||
|
||||
#[inline(always)]
|
||||
fn infinity() -> f64 { 1.0 / 0.0 }
|
||||
|
||||
#[inline(always)]
|
||||
fn neg_infinity() -> f64 { -1.0 / 0.0 }
|
||||
|
||||
#[inline(always)]
|
||||
fn neg_zero() -> f64 { -0.0 }
|
||||
|
||||
#[inline(always)]
|
||||
fn is_NaN(&self) -> bool { *self != *self }
|
||||
|
||||
/// Returns `true` if the number is infinite
|
||||
#[inline(always)]
|
||||
fn is_infinite(&self) -> bool {
|
||||
*self == Float::infinity() || *self == Float::neg_infinity()
|
||||
}
|
||||
|
||||
/// Returns `true` if the number is finite
|
||||
#[inline(always)]
|
||||
fn is_finite(&self) -> bool {
|
||||
!(self.is_NaN() || self.is_infinite())
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn mantissa_digits() -> uint { 53 }
|
||||
|
||||
#[inline(always)]
|
||||
fn digits() -> uint { 15 }
|
||||
|
||||
#[inline(always)]
|
||||
fn epsilon() -> f64 { 2.2204460492503131e-16 }
|
||||
|
||||
#[inline(always)]
|
||||
fn min_exp() -> int { -1021 }
|
||||
|
||||
#[inline(always)]
|
||||
fn max_exp() -> int { 1024 }
|
||||
|
||||
#[inline(always)]
|
||||
fn min_10_exp() -> int { -307 }
|
||||
|
||||
#[inline(always)]
|
||||
fn max_10_exp() -> int { 308 }
|
||||
|
||||
///
|
||||
/// Fused multiply-add. Computes `(self * a) + b` with only one rounding error. This
|
||||
/// produces a more accurate result with better performance than a separate multiplication
|
||||
/// operation followed by an add.
|
||||
///
|
||||
#[inline(always)]
|
||||
fn mul_add(&self, a: f64, b: f64) -> f64 {
|
||||
mul_add(*self, a, b)
|
||||
}
|
||||
|
||||
/// Returns the next representable floating-point value in the direction of `other`
|
||||
#[inline(always)]
|
||||
fn next_after(&self, other: f64) -> f64 {
|
||||
next_after(*self, other)
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Section: String Conversions
|
||||
//
|
||||
|
||||
///
|
||||
/// Converts a float to a string
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * num - The float value
|
||||
///
|
||||
#[inline(always)]
|
||||
pub fn to_str(num: f64) -> ~str {
|
||||
let (r, _) = strconv::to_str_common(
|
||||
@ -569,13 +658,13 @@ pub fn to_str(num: f64) -> ~str {
|
||||
r
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a float to a string in hexadecimal format
|
||||
*
|
||||
* # Arguments
|
||||
*
|
||||
* * num - The float value
|
||||
*/
|
||||
///
|
||||
/// Converts a float to a string in hexadecimal format
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * num - The float value
|
||||
///
|
||||
#[inline(always)]
|
||||
pub fn to_str_hex(num: f64) -> ~str {
|
||||
let (r, _) = strconv::to_str_common(
|
||||
@ -583,20 +672,20 @@ pub fn to_str_hex(num: f64) -> ~str {
|
||||
r
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a float to a string in a given radix
|
||||
*
|
||||
* # Arguments
|
||||
*
|
||||
* * num - The float value
|
||||
* * radix - The base to use
|
||||
*
|
||||
* # Failure
|
||||
*
|
||||
* Fails if called on a special value like `inf`, `-inf` or `NaN` due to
|
||||
* possible misinterpretation of the result at higher bases. If those values
|
||||
* are expected, use `to_str_radix_special()` instead.
|
||||
*/
|
||||
///
|
||||
/// Converts a float to a string in a given radix
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * num - The float value
|
||||
/// * radix - The base to use
|
||||
///
|
||||
/// # Failure
|
||||
///
|
||||
/// Fails if called on a special value like `inf`, `-inf` or `NaN` due to
|
||||
/// possible misinterpretation of the result at higher bases. If those values
|
||||
/// are expected, use `to_str_radix_special()` instead.
|
||||
///
|
||||
#[inline(always)]
|
||||
pub fn to_str_radix(num: f64, rdx: uint) -> ~str {
|
||||
let (r, special) = strconv::to_str_common(
|
||||
@ -606,30 +695,30 @@ pub fn to_str_radix(num: f64, rdx: uint) -> ~str {
|
||||
r
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a float to a string in a given radix, and a flag indicating
|
||||
* whether it's a special value
|
||||
*
|
||||
* # Arguments
|
||||
*
|
||||
* * num - The float value
|
||||
* * radix - The base to use
|
||||
*/
|
||||
///
|
||||
/// Converts a float to a string in a given radix, and a flag indicating
|
||||
/// whether it's a special value
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * num - The float value
|
||||
/// * radix - The base to use
|
||||
///
|
||||
#[inline(always)]
|
||||
pub fn to_str_radix_special(num: f64, rdx: uint) -> (~str, bool) {
|
||||
strconv::to_str_common(&num, rdx, true,
|
||||
strconv::SignNeg, strconv::DigAll)
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a float to a string with exactly the number of
|
||||
* provided significant digits
|
||||
*
|
||||
* # Arguments
|
||||
*
|
||||
* * num - The float value
|
||||
* * digits - The number of significant digits
|
||||
*/
|
||||
///
|
||||
/// Converts a float to a string with exactly the number of
|
||||
/// provided significant digits
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * num - The float value
|
||||
/// * digits - The number of significant digits
|
||||
///
|
||||
#[inline(always)]
|
||||
pub fn to_str_exact(num: f64, dig: uint) -> ~str {
|
||||
let (r, _) = strconv::to_str_common(
|
||||
@ -637,15 +726,15 @@ pub fn to_str_exact(num: f64, dig: uint) -> ~str {
|
||||
r
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a float to a string with a maximum number of
|
||||
* significant digits
|
||||
*
|
||||
* # Arguments
|
||||
*
|
||||
* * num - The float value
|
||||
* * digits - The number of significant digits
|
||||
*/
|
||||
///
|
||||
/// Converts a float to a string with a maximum number of
|
||||
/// significant digits
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * num - The float value
|
||||
/// * digits - The number of significant digits
|
||||
///
|
||||
#[inline(always)]
|
||||
pub fn to_str_digits(num: f64, dig: uint) -> ~str {
|
||||
let (r, _) = strconv::to_str_common(
|
||||
@ -665,91 +754,91 @@ impl num::ToStrRadix for f64 {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a string in base 10 to a float.
|
||||
* Accepts a optional decimal exponent.
|
||||
*
|
||||
* This function accepts strings such as
|
||||
*
|
||||
* * '3.14'
|
||||
* * '+3.14', equivalent to '3.14'
|
||||
* * '-3.14'
|
||||
* * '2.5E10', or equivalently, '2.5e10'
|
||||
* * '2.5E-10'
|
||||
* * '.' (understood as 0)
|
||||
* * '5.'
|
||||
* * '.5', or, equivalently, '0.5'
|
||||
* * '+inf', 'inf', '-inf', 'NaN'
|
||||
*
|
||||
* Leading and trailing whitespace represent an error.
|
||||
*
|
||||
* # Arguments
|
||||
*
|
||||
* * num - A string
|
||||
*
|
||||
* # Return value
|
||||
*
|
||||
* `none` if the string did not represent a valid number. Otherwise,
|
||||
* `Some(n)` where `n` is the floating-point number represented by `num`.
|
||||
*/
|
||||
///
|
||||
/// Convert a string in base 10 to a float.
|
||||
/// Accepts a optional decimal exponent.
|
||||
///
|
||||
/// This function accepts strings such as
|
||||
///
|
||||
/// * '3.14'
|
||||
/// * '+3.14', equivalent to '3.14'
|
||||
/// * '-3.14'
|
||||
/// * '2.5E10', or equivalently, '2.5e10'
|
||||
/// * '2.5E-10'
|
||||
/// * '.' (understood as 0)
|
||||
/// * '5.'
|
||||
/// * '.5', or, equivalently, '0.5'
|
||||
/// * '+inf', 'inf', '-inf', 'NaN'
|
||||
///
|
||||
/// Leading and trailing whitespace represent an error.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * num - A string
|
||||
///
|
||||
/// # Return value
|
||||
///
|
||||
/// `none` if the string did not represent a valid number. Otherwise,
|
||||
/// `Some(n)` where `n` is the floating-point number represented by `num`.
|
||||
///
|
||||
#[inline(always)]
|
||||
pub fn from_str(num: &str) -> Option<f64> {
|
||||
strconv::from_str_common(num, 10u, true, true, true,
|
||||
strconv::ExpDec, false, false)
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a string in base 16 to a float.
|
||||
* Accepts a optional binary exponent.
|
||||
*
|
||||
* This function accepts strings such as
|
||||
*
|
||||
* * 'a4.fe'
|
||||
* * '+a4.fe', equivalent to 'a4.fe'
|
||||
* * '-a4.fe'
|
||||
* * '2b.aP128', or equivalently, '2b.ap128'
|
||||
* * '2b.aP-128'
|
||||
* * '.' (understood as 0)
|
||||
* * 'c.'
|
||||
* * '.c', or, equivalently, '0.c'
|
||||
* * '+inf', 'inf', '-inf', 'NaN'
|
||||
*
|
||||
* Leading and trailing whitespace represent an error.
|
||||
*
|
||||
* # Arguments
|
||||
*
|
||||
* * num - A string
|
||||
*
|
||||
* # Return value
|
||||
*
|
||||
* `none` if the string did not represent a valid number. Otherwise,
|
||||
* `Some(n)` where `n` is the floating-point number represented by `[num]`.
|
||||
*/
|
||||
///
|
||||
/// Convert a string in base 16 to a float.
|
||||
/// Accepts a optional binary exponent.
|
||||
///
|
||||
/// This function accepts strings such as
|
||||
///
|
||||
/// * 'a4.fe'
|
||||
/// * '+a4.fe', equivalent to 'a4.fe'
|
||||
/// * '-a4.fe'
|
||||
/// * '2b.aP128', or equivalently, '2b.ap128'
|
||||
/// * '2b.aP-128'
|
||||
/// * '.' (understood as 0)
|
||||
/// * 'c.'
|
||||
/// * '.c', or, equivalently, '0.c'
|
||||
/// * '+inf', 'inf', '-inf', 'NaN'
|
||||
///
|
||||
/// Leading and trailing whitespace represent an error.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * num - A string
|
||||
///
|
||||
/// # Return value
|
||||
///
|
||||
/// `none` if the string did not represent a valid number. Otherwise,
|
||||
/// `Some(n)` where `n` is the floating-point number represented by `[num]`.
|
||||
///
|
||||
#[inline(always)]
|
||||
pub fn from_str_hex(num: &str) -> Option<f64> {
|
||||
strconv::from_str_common(num, 16u, true, true, true,
|
||||
strconv::ExpBin, false, false)
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a string in an given base to a float.
|
||||
*
|
||||
* Due to possible conflicts, this function does **not** accept
|
||||
* the special values `inf`, `-inf`, `+inf` and `NaN`, **nor**
|
||||
* does it recognize exponents of any kind.
|
||||
*
|
||||
* Leading and trailing whitespace represent an error.
|
||||
*
|
||||
* # Arguments
|
||||
*
|
||||
* * num - A string
|
||||
* * radix - The base to use. Must lie in the range [2 .. 36]
|
||||
*
|
||||
* # Return value
|
||||
*
|
||||
* `none` if the string did not represent a valid number. Otherwise,
|
||||
* `Some(n)` where `n` is the floating-point number represented by `num`.
|
||||
*/
|
||||
///
|
||||
/// Convert a string in an given base to a float.
|
||||
///
|
||||
/// Due to possible conflicts, this function does **not** accept
|
||||
/// the special values `inf`, `-inf`, `+inf` and `NaN`, **nor**
|
||||
/// does it recognize exponents of any kind.
|
||||
///
|
||||
/// Leading and trailing whitespace represent an error.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * num - A string
|
||||
/// * radix - The base to use. Must lie in the range [2 .. 36]
|
||||
///
|
||||
/// # Return value
|
||||
///
|
||||
/// `none` if the string did not represent a valid number. Otherwise,
|
||||
/// `Some(n)` where `n` is the floating-point number represented by `num`.
|
||||
///
|
||||
#[inline(always)]
|
||||
pub fn from_str_radix(num: &str, rdx: uint) -> Option<f64> {
|
||||
strconv::from_str_common(num, rdx, true, true, false,
|
||||
@ -789,6 +878,32 @@ mod tests {
|
||||
num::test_num(10f64, 2f64);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_min() {
|
||||
assert_eq!(1f64.min(&2f64), 1f64);
|
||||
assert_eq!(2f64.min(&1f64), 1f64);
|
||||
assert!(1f64.min(&Float::NaN::<f64>()).is_NaN());
|
||||
assert!(Float::NaN::<f64>().min(&1f64).is_NaN());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_max() {
|
||||
assert_eq!(1f64.max(&2f64), 2f64);
|
||||
assert_eq!(2f64.max(&1f64), 2f64);
|
||||
assert!(1f64.max(&Float::NaN::<f64>()).is_NaN());
|
||||
assert!(Float::NaN::<f64>().max(&1f64).is_NaN());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_clamp() {
|
||||
assert_eq!(1f64.clamp(&2f64, &4f64), 2f64);
|
||||
assert_eq!(8f64.clamp(&2f64, &4f64), 4f64);
|
||||
assert_eq!(3f64.clamp(&2f64, &4f64), 3f64);
|
||||
assert!(3f64.clamp(&Float::NaN::<f64>(), &4f64).is_NaN());
|
||||
assert!(3f64.clamp(&2f64, &Float::NaN::<f64>()).is_NaN());
|
||||
assert!(Float::NaN::<f64>().clamp(&2f64, &4f64).is_NaN());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_floor() {
|
||||
assert_fuzzy_eq!(1.0f64.floor(), 1.0f64);
|
||||
@ -887,7 +1002,7 @@ mod tests {
|
||||
assert_eq!((-1f64).abs(), 1f64);
|
||||
assert_eq!(neg_infinity.abs(), infinity);
|
||||
assert_eq!((1f64/neg_infinity).abs(), 0f64);
|
||||
assert!(is_NaN(NaN.abs()));
|
||||
assert!(NaN.abs().is_NaN());
|
||||
|
||||
assert_eq!(infinity.signum(), 1f64);
|
||||
assert_eq!(1f64.signum(), 1f64);
|
||||
@ -896,7 +1011,7 @@ mod tests {
|
||||
assert_eq!((-1f64).signum(), -1f64);
|
||||
assert_eq!(neg_infinity.signum(), -1f64);
|
||||
assert_eq!((1f64/neg_infinity).signum(), -1f64);
|
||||
assert!(is_NaN(NaN.signum()));
|
||||
assert!(NaN.signum().is_NaN());
|
||||
|
||||
assert!(infinity.is_positive());
|
||||
assert!(1f64.is_positive());
|
||||
@ -916,6 +1031,12 @@ mod tests {
|
||||
assert!((1f64/neg_infinity).is_negative());
|
||||
assert!(!NaN.is_negative());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_primitive() {
|
||||
assert_eq!(Primitive::bits::<f64>(), sys::size_of::<f64>() * 8);
|
||||
assert_eq!(Primitive::bytes::<f64>(), sys::size_of::<f64>());
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -22,14 +22,14 @@
|
||||
|
||||
use from_str;
|
||||
use libc::c_int;
|
||||
use num::strconv;
|
||||
use num::{Zero, One, strconv};
|
||||
use prelude::*;
|
||||
|
||||
pub use f64::{add, sub, mul, quot, rem, lt, le, eq, ne, ge, gt};
|
||||
pub use f64::logarithm;
|
||||
pub use f64::{acos, asin, atan2, cbrt, ceil, copysign, cosh, floor};
|
||||
pub use f64::{erf, erfc, exp, expm1, exp2, abs_sub};
|
||||
pub use f64::{mul_add, fmax, fmin, nextafter, frexp, hypot, ldexp};
|
||||
pub use f64::{mul_add, fmax, fmin, next_after, frexp, hypot, ldexp};
|
||||
pub use f64::{lgamma, ln, log_radix, ln1p, log10, log2, ilog_radix};
|
||||
pub use f64::{modf, pow, powi, round, sinh, tanh, tgamma, trunc};
|
||||
pub use f64::{j0, j1, jn, y0, y1, yn};
|
||||
@ -84,17 +84,17 @@ pub mod consts {
|
||||
pub static ln_10: float = 2.30258509299404568401799145468436421;
|
||||
}
|
||||
|
||||
/*
|
||||
* Section: String Conversions
|
||||
*/
|
||||
//
|
||||
// Section: String Conversions
|
||||
//
|
||||
|
||||
/**
|
||||
* Converts a float to a string
|
||||
*
|
||||
* # Arguments
|
||||
*
|
||||
* * num - The float value
|
||||
*/
|
||||
///
|
||||
/// Converts a float to a string
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * num - The float value
|
||||
///
|
||||
#[inline(always)]
|
||||
pub fn to_str(num: float) -> ~str {
|
||||
let (r, _) = strconv::to_str_common(
|
||||
@ -102,13 +102,13 @@ pub fn to_str(num: float) -> ~str {
|
||||
r
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a float to a string in hexadecimal format
|
||||
*
|
||||
* # Arguments
|
||||
*
|
||||
* * num - The float value
|
||||
*/
|
||||
///
|
||||
/// Converts a float to a string in hexadecimal format
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * num - The float value
|
||||
///
|
||||
#[inline(always)]
|
||||
pub fn to_str_hex(num: float) -> ~str {
|
||||
let (r, _) = strconv::to_str_common(
|
||||
@ -116,20 +116,20 @@ pub fn to_str_hex(num: float) -> ~str {
|
||||
r
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a float to a string in a given radix
|
||||
*
|
||||
* # Arguments
|
||||
*
|
||||
* * num - The float value
|
||||
* * radix - The base to use
|
||||
*
|
||||
* # Failure
|
||||
*
|
||||
* Fails if called on a special value like `inf`, `-inf` or `NaN` due to
|
||||
* possible misinterpretation of the result at higher bases. If those values
|
||||
* are expected, use `to_str_radix_special()` instead.
|
||||
*/
|
||||
///
|
||||
/// Converts a float to a string in a given radix
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * num - The float value
|
||||
/// * radix - The base to use
|
||||
///
|
||||
/// # Failure
|
||||
///
|
||||
/// Fails if called on a special value like `inf`, `-inf` or `NaN` due to
|
||||
/// possible misinterpretation of the result at higher bases. If those values
|
||||
/// are expected, use `to_str_radix_special()` instead.
|
||||
///
|
||||
#[inline(always)]
|
||||
pub fn to_str_radix(num: float, radix: uint) -> ~str {
|
||||
let (r, special) = strconv::to_str_common(
|
||||
@ -139,30 +139,30 @@ pub fn to_str_radix(num: float, radix: uint) -> ~str {
|
||||
r
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a float to a string in a given radix, and a flag indicating
|
||||
* whether it's a special value
|
||||
*
|
||||
* # Arguments
|
||||
*
|
||||
* * num - The float value
|
||||
* * radix - The base to use
|
||||
*/
|
||||
///
|
||||
/// Converts a float to a string in a given radix, and a flag indicating
|
||||
/// whether it's a special value
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * num - The float value
|
||||
/// * radix - The base to use
|
||||
///
|
||||
#[inline(always)]
|
||||
pub fn to_str_radix_special(num: float, radix: uint) -> (~str, bool) {
|
||||
strconv::to_str_common(&num, radix, true,
|
||||
strconv::SignNeg, strconv::DigAll)
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a float to a string with exactly the number of
|
||||
* provided significant digits
|
||||
*
|
||||
* # Arguments
|
||||
*
|
||||
* * num - The float value
|
||||
* * digits - The number of significant digits
|
||||
*/
|
||||
///
|
||||
/// Converts a float to a string with exactly the number of
|
||||
/// provided significant digits
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * num - The float value
|
||||
/// * digits - The number of significant digits
|
||||
///
|
||||
#[inline(always)]
|
||||
pub fn to_str_exact(num: float, digits: uint) -> ~str {
|
||||
let (r, _) = strconv::to_str_common(
|
||||
@ -170,15 +170,15 @@ pub fn to_str_exact(num: float, digits: uint) -> ~str {
|
||||
r
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a float to a string with a maximum number of
|
||||
* significant digits
|
||||
*
|
||||
* # Arguments
|
||||
*
|
||||
* * num - The float value
|
||||
* * digits - The number of significant digits
|
||||
*/
|
||||
///
|
||||
/// Converts a float to a string with a maximum number of
|
||||
/// significant digits
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * num - The float value
|
||||
/// * digits - The number of significant digits
|
||||
///
|
||||
#[inline(always)]
|
||||
pub fn to_str_digits(num: float, digits: uint) -> ~str {
|
||||
let (r, _) = strconv::to_str_common(
|
||||
@ -198,91 +198,91 @@ impl num::ToStrRadix for float {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a string in base 10 to a float.
|
||||
* Accepts a optional decimal exponent.
|
||||
*
|
||||
* This function accepts strings such as
|
||||
*
|
||||
* * '3.14'
|
||||
* * '+3.14', equivalent to '3.14'
|
||||
* * '-3.14'
|
||||
* * '2.5E10', or equivalently, '2.5e10'
|
||||
* * '2.5E-10'
|
||||
* * '.' (understood as 0)
|
||||
* * '5.'
|
||||
* * '.5', or, equivalently, '0.5'
|
||||
* * '+inf', 'inf', '-inf', 'NaN'
|
||||
*
|
||||
* Leading and trailing whitespace represent an error.
|
||||
*
|
||||
* # Arguments
|
||||
*
|
||||
* * num - A string
|
||||
*
|
||||
* # Return value
|
||||
*
|
||||
* `none` if the string did not represent a valid number. Otherwise,
|
||||
* `Some(n)` where `n` is the floating-point number represented by `num`.
|
||||
*/
|
||||
///
|
||||
/// Convert a string in base 10 to a float.
|
||||
/// Accepts a optional decimal exponent.
|
||||
///
|
||||
/// This function accepts strings such as
|
||||
///
|
||||
/// * '3.14'
|
||||
/// * '+3.14', equivalent to '3.14'
|
||||
/// * '-3.14'
|
||||
/// * '2.5E10', or equivalently, '2.5e10'
|
||||
/// * '2.5E-10'
|
||||
/// * '.' (understood as 0)
|
||||
/// * '5.'
|
||||
/// * '.5', or, equivalently, '0.5'
|
||||
/// * '+inf', 'inf', '-inf', 'NaN'
|
||||
///
|
||||
/// Leading and trailing whitespace represent an error.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * num - A string
|
||||
///
|
||||
/// # Return value
|
||||
///
|
||||
/// `none` if the string did not represent a valid number. Otherwise,
|
||||
/// `Some(n)` where `n` is the floating-point number represented by `num`.
|
||||
///
|
||||
#[inline(always)]
|
||||
pub fn from_str(num: &str) -> Option<float> {
|
||||
strconv::from_str_common(num, 10u, true, true, true,
|
||||
strconv::ExpDec, false, false)
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a string in base 16 to a float.
|
||||
* Accepts a optional binary exponent.
|
||||
*
|
||||
* This function accepts strings such as
|
||||
*
|
||||
* * 'a4.fe'
|
||||
* * '+a4.fe', equivalent to 'a4.fe'
|
||||
* * '-a4.fe'
|
||||
* * '2b.aP128', or equivalently, '2b.ap128'
|
||||
* * '2b.aP-128'
|
||||
* * '.' (understood as 0)
|
||||
* * 'c.'
|
||||
* * '.c', or, equivalently, '0.c'
|
||||
* * '+inf', 'inf', '-inf', 'NaN'
|
||||
*
|
||||
* Leading and trailing whitespace represent an error.
|
||||
*
|
||||
* # Arguments
|
||||
*
|
||||
* * num - A string
|
||||
*
|
||||
* # Return value
|
||||
*
|
||||
* `none` if the string did not represent a valid number. Otherwise,
|
||||
* `Some(n)` where `n` is the floating-point number represented by `[num]`.
|
||||
*/
|
||||
///
|
||||
/// Convert a string in base 16 to a float.
|
||||
/// Accepts a optional binary exponent.
|
||||
///
|
||||
/// This function accepts strings such as
|
||||
///
|
||||
/// * 'a4.fe'
|
||||
/// * '+a4.fe', equivalent to 'a4.fe'
|
||||
/// * '-a4.fe'
|
||||
/// * '2b.aP128', or equivalently, '2b.ap128'
|
||||
/// * '2b.aP-128'
|
||||
/// * '.' (understood as 0)
|
||||
/// * 'c.'
|
||||
/// * '.c', or, equivalently, '0.c'
|
||||
/// * '+inf', 'inf', '-inf', 'NaN'
|
||||
///
|
||||
/// Leading and trailing whitespace represent an error.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * num - A string
|
||||
///
|
||||
/// # Return value
|
||||
///
|
||||
/// `none` if the string did not represent a valid number. Otherwise,
|
||||
/// `Some(n)` where `n` is the floating-point number represented by `[num]`.
|
||||
///
|
||||
#[inline(always)]
|
||||
pub fn from_str_hex(num: &str) -> Option<float> {
|
||||
strconv::from_str_common(num, 16u, true, true, true,
|
||||
strconv::ExpBin, false, false)
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a string in an given base to a float.
|
||||
*
|
||||
* Due to possible conflicts, this function does **not** accept
|
||||
* the special values `inf`, `-inf`, `+inf` and `NaN`, **nor**
|
||||
* does it recognize exponents of any kind.
|
||||
*
|
||||
* Leading and trailing whitespace represent an error.
|
||||
*
|
||||
* # Arguments
|
||||
*
|
||||
* * num - A string
|
||||
* * radix - The base to use. Must lie in the range [2 .. 36]
|
||||
*
|
||||
* # Return value
|
||||
*
|
||||
* `none` if the string did not represent a valid number. Otherwise,
|
||||
* `Some(n)` where `n` is the floating-point number represented by `num`.
|
||||
*/
|
||||
///
|
||||
/// Convert a string in an given base to a float.
|
||||
///
|
||||
/// Due to possible conflicts, this function does **not** accept
|
||||
/// the special values `inf`, `-inf`, `+inf` and `NaN`, **nor**
|
||||
/// does it recognize exponents of any kind.
|
||||
///
|
||||
/// Leading and trailing whitespace represent an error.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * num - A string
|
||||
/// * radix - The base to use. Must lie in the range [2 .. 36]
|
||||
///
|
||||
/// # Return value
|
||||
///
|
||||
/// `none` if the string did not represent a valid number. Otherwise,
|
||||
/// `Some(n)` where `n` is the floating-point number represented by `num`.
|
||||
///
|
||||
#[inline(always)]
|
||||
pub fn from_str_radix(num: &str, radix: uint) -> Option<float> {
|
||||
strconv::from_str_common(num, radix, true, true, false,
|
||||
@ -301,22 +301,22 @@ impl num::FromStrRadix for float {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Section: Arithmetics
|
||||
*/
|
||||
//
|
||||
// Section: Arithmetics
|
||||
//
|
||||
|
||||
/**
|
||||
* Compute the exponentiation of an integer by another integer as a float
|
||||
*
|
||||
* # Arguments
|
||||
*
|
||||
* * x - The base
|
||||
* * pow - The exponent
|
||||
*
|
||||
* # Return value
|
||||
*
|
||||
* `NaN` if both `x` and `pow` are `0u`, otherwise `x^pow`
|
||||
*/
|
||||
///
|
||||
/// Compute the exponentiation of an integer by another integer as a float
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * x - The base
|
||||
/// * pow - The exponent
|
||||
///
|
||||
/// # Return value
|
||||
///
|
||||
/// `NaN` if both `x` and `pow` are `0u`, otherwise `x^pow`
|
||||
///
|
||||
pub fn pow_with_uint(base: uint, pow: uint) -> float {
|
||||
if base == 0u {
|
||||
if pow == 0u {
|
||||
@ -337,15 +337,6 @@ pub fn pow_with_uint(base: uint, pow: uint) -> float {
|
||||
return total;
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn is_zero(x: float) -> bool { f64::is_zero(x as f64) }
|
||||
#[inline(always)]
|
||||
pub fn is_infinite(x: float) -> bool { f64::is_infinite(x as f64) }
|
||||
#[inline(always)]
|
||||
pub fn is_finite(x: float) -> bool { f64::is_finite(x as f64) }
|
||||
#[inline(always)]
|
||||
pub fn is_NaN(x: float) -> bool { f64::is_NaN(x as f64) }
|
||||
|
||||
#[inline(always)]
|
||||
pub fn abs(x: float) -> float {
|
||||
f64::abs(x as f64) as float
|
||||
@ -393,12 +384,37 @@ impl Ord for float {
|
||||
fn gt(&self, other: &float) -> bool { (*self) > (*other) }
|
||||
}
|
||||
|
||||
impl num::Zero for float {
|
||||
impl Orderable for float {
|
||||
/// Returns `NaN` if either of the numbers are `NaN`.
|
||||
#[inline(always)]
|
||||
fn zero() -> float { 0.0 }
|
||||
fn min(&self, other: &float) -> float {
|
||||
(*self as f64).min(&(*other as f64)) as float
|
||||
}
|
||||
|
||||
/// Returns `NaN` if either of the numbers are `NaN`.
|
||||
#[inline(always)]
|
||||
fn max(&self, other: &float) -> float {
|
||||
(*self as f64).max(&(*other as f64)) as float
|
||||
}
|
||||
|
||||
/// Returns the number constrained within the range `mn <= self <= mx`.
|
||||
/// If any of the numbers are `NaN` then `NaN` is returned.
|
||||
#[inline(always)]
|
||||
fn clamp(&self, mn: &float, mx: &float) -> float {
|
||||
(*self as f64).clamp(&(*mn as f64), &(*mx as f64)) as float
|
||||
}
|
||||
}
|
||||
|
||||
impl num::One for float {
|
||||
impl Zero for float {
|
||||
#[inline(always)]
|
||||
fn zero() -> float { 0.0 }
|
||||
|
||||
/// Returns true if the number is equal to either `0.0` or `-0.0`
|
||||
#[inline(always)]
|
||||
fn is_zero(&self) -> bool { *self == 0.0 || *self == -0.0 }
|
||||
}
|
||||
|
||||
impl One for float {
|
||||
#[inline(always)]
|
||||
fn one() -> float { 1.0 }
|
||||
}
|
||||
@ -666,16 +682,16 @@ impl Signed for float {
|
||||
#[inline(always)]
|
||||
fn abs(&self) -> float { abs(*self) }
|
||||
|
||||
/**
|
||||
* # Returns
|
||||
*
|
||||
* - `1.0` if the number is positive, `+0.0` or `infinity`
|
||||
* - `-1.0` if the number is negative, `-0.0` or `neg_infinity`
|
||||
* - `NaN` if the number is NaN
|
||||
*/
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
/// - `1.0` if the number is positive, `+0.0` or `infinity`
|
||||
/// - `-1.0` if the number is negative, `-0.0` or `neg_infinity`
|
||||
/// - `NaN` if the number is NaN
|
||||
///
|
||||
#[inline(always)]
|
||||
fn signum(&self) -> float {
|
||||
if is_NaN(*self) { NaN } else { f64::copysign(1.0, *self as f64) as float }
|
||||
if self.is_NaN() { NaN } else { f64::copysign(1.0, *self as f64) as float }
|
||||
}
|
||||
|
||||
/// Returns `true` if the number is positive, including `+0.0` and `infinity`
|
||||
@ -687,6 +703,88 @@ impl Signed for float {
|
||||
fn is_negative(&self) -> bool { *self < 0.0 || (1.0 / *self) == neg_infinity }
|
||||
}
|
||||
|
||||
impl Bounded for float {
|
||||
#[inline(always)]
|
||||
fn min_value() -> float { Bounded::min_value::<f64>() as float }
|
||||
|
||||
#[inline(always)]
|
||||
fn max_value() -> float { Bounded::max_value::<f64>() as float }
|
||||
}
|
||||
|
||||
impl Primitive for float {
|
||||
#[inline(always)]
|
||||
fn bits() -> uint { Primitive::bits::<f64>() }
|
||||
|
||||
#[inline(always)]
|
||||
fn bytes() -> uint { Primitive::bytes::<f64>() }
|
||||
}
|
||||
|
||||
impl Float for float {
|
||||
#[inline(always)]
|
||||
fn NaN() -> float { 0.0 / 0.0 }
|
||||
|
||||
#[inline(always)]
|
||||
fn infinity() -> float { 1.0 / 0.0 }
|
||||
|
||||
#[inline(always)]
|
||||
fn neg_infinity() -> float { -1.0 / 0.0 }
|
||||
|
||||
#[inline(always)]
|
||||
fn neg_zero() -> float { -0.0 }
|
||||
|
||||
#[inline(always)]
|
||||
fn is_NaN(&self) -> bool { *self != *self }
|
||||
|
||||
#[inline(always)]
|
||||
fn mantissa_digits() -> uint { Float::mantissa_digits::<f64>() }
|
||||
|
||||
#[inline(always)]
|
||||
fn digits() -> uint { Float::digits::<f64>() }
|
||||
|
||||
#[inline(always)]
|
||||
fn epsilon() -> float { Float::epsilon::<f64>() as float }
|
||||
|
||||
#[inline(always)]
|
||||
fn min_exp() -> int { Float::min_exp::<f64>() }
|
||||
|
||||
#[inline(always)]
|
||||
fn max_exp() -> int { Float::max_exp::<f64>() }
|
||||
|
||||
#[inline(always)]
|
||||
fn min_10_exp() -> int { Float::min_10_exp::<f64>() }
|
||||
|
||||
#[inline(always)]
|
||||
fn max_10_exp() -> int { Float::max_10_exp::<f64>() }
|
||||
|
||||
/// Returns `true` if the number is infinite
|
||||
#[inline(always)]
|
||||
fn is_infinite(&self) -> bool {
|
||||
*self == Float::infinity() || *self == Float::neg_infinity()
|
||||
}
|
||||
|
||||
/// Returns `true` if the number is finite
|
||||
#[inline(always)]
|
||||
fn is_finite(&self) -> bool {
|
||||
!(self.is_NaN() || self.is_infinite())
|
||||
}
|
||||
|
||||
///
|
||||
/// Fused multiply-add. Computes `(self * a) + b` with only one rounding error. This
|
||||
/// produces a more accurate result with better performance than a separate multiplication
|
||||
/// operation followed by an add.
|
||||
///
|
||||
#[inline(always)]
|
||||
fn mul_add(&self, a: float, b: float) -> float {
|
||||
mul_add(*self as f64, a as f64, b as f64) as float
|
||||
}
|
||||
|
||||
/// Returns the next representable floating-point value in the direction of `other`
|
||||
#[inline(always)]
|
||||
fn next_after(&self, other: float) -> float {
|
||||
next_after(*self as f64, other as f64) as float
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
@ -706,6 +804,28 @@ mod tests {
|
||||
num::test_num(10f, 2f);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_min() {
|
||||
assert_eq!(1f.min(&2f), 1f);
|
||||
assert_eq!(2f.min(&1f), 1f);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_max() {
|
||||
assert_eq!(1f.max(&2f), 2f);
|
||||
assert_eq!(2f.max(&1f), 2f);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_clamp() {
|
||||
assert_eq!(1f.clamp(&2f, &4f), 2f);
|
||||
assert_eq!(8f.clamp(&2f, &4f), 4f);
|
||||
assert_eq!(3f.clamp(&2f, &4f), 3f);
|
||||
assert!(3f.clamp(&Float::NaN::<float>(), &4f).is_NaN());
|
||||
assert!(3f.clamp(&2f, &Float::NaN::<float>()).is_NaN());
|
||||
assert!(Float::NaN::<float>().clamp(&2f, &4f).is_NaN());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_floor() {
|
||||
assert_fuzzy_eq!(1.0f.floor(), 1.0f);
|
||||
@ -796,7 +916,7 @@ mod tests {
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn test_signed() {
|
||||
fn test_signed() {
|
||||
assert_eq!(infinity.abs(), infinity);
|
||||
assert_eq!(1f.abs(), 1f);
|
||||
assert_eq!(0f.abs(), 0f);
|
||||
@ -804,7 +924,7 @@ mod tests {
|
||||
assert_eq!((-1f).abs(), 1f);
|
||||
assert_eq!(neg_infinity.abs(), infinity);
|
||||
assert_eq!((1f/neg_infinity).abs(), 0f);
|
||||
assert!(is_NaN(NaN.abs()));
|
||||
assert!(NaN.abs().is_NaN());
|
||||
|
||||
assert_eq!(infinity.signum(), 1f);
|
||||
assert_eq!(1f.signum(), 1f);
|
||||
@ -813,7 +933,7 @@ mod tests {
|
||||
assert_eq!((-1f).signum(), -1f);
|
||||
assert_eq!(neg_infinity.signum(), -1f);
|
||||
assert_eq!((1f/neg_infinity).signum(), -1f);
|
||||
assert!(is_NaN(NaN.signum()));
|
||||
assert!(NaN.signum().is_NaN());
|
||||
|
||||
assert!(infinity.is_positive());
|
||||
assert!(1f.is_positive());
|
||||
@ -834,6 +954,12 @@ mod tests {
|
||||
assert!(!NaN.is_negative());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_primitive() {
|
||||
assert_eq!(Primitive::bits::<float>(), sys::size_of::<float>() * 8);
|
||||
assert_eq!(Primitive::bytes::<float>(), sys::size_of::<float>());
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn test_to_str_exact_do_decimal() {
|
||||
let s = to_str_exact(5.0, 4u);
|
||||
@ -862,16 +988,16 @@ mod tests {
|
||||
assert_eq!(from_str(~"-inf"), Some(neg_infinity));
|
||||
// note: NaN != NaN, hence this slightly complex test
|
||||
match from_str(~"NaN") {
|
||||
Some(f) => assert!(is_NaN(f)),
|
||||
Some(f) => assert!(f.is_NaN()),
|
||||
None => fail!()
|
||||
}
|
||||
// note: -0 == 0, hence these slightly more complex tests
|
||||
match from_str(~"-0") {
|
||||
Some(v) if is_zero(v) => assert!(v.is_negative()),
|
||||
Some(v) if v.is_zero() => assert!(v.is_negative()),
|
||||
_ => fail!()
|
||||
}
|
||||
match from_str(~"0") {
|
||||
Some(v) if is_zero(v) => assert!(v.is_positive()),
|
||||
Some(v) if v.is_zero() => assert!(v.is_positive()),
|
||||
_ => fail!()
|
||||
}
|
||||
|
||||
@ -909,16 +1035,16 @@ mod tests {
|
||||
assert_eq!(from_str_hex(~"-inf"), Some(neg_infinity));
|
||||
// note: NaN != NaN, hence this slightly complex test
|
||||
match from_str_hex(~"NaN") {
|
||||
Some(f) => assert!(is_NaN(f)),
|
||||
Some(f) => assert!(f.is_NaN()),
|
||||
None => fail!()
|
||||
}
|
||||
// note: -0 == 0, hence these slightly more complex tests
|
||||
match from_str_hex(~"-0") {
|
||||
Some(v) if is_zero(v) => assert!(v.is_negative()),
|
||||
Some(v) if v.is_zero() => assert!(v.is_negative()),
|
||||
_ => fail!()
|
||||
}
|
||||
match from_str_hex(~"0") {
|
||||
Some(v) if is_zero(v) => assert!(v.is_positive()),
|
||||
Some(v) if v.is_zero() => assert!(v.is_positive()),
|
||||
_ => fail!()
|
||||
}
|
||||
assert_eq!(from_str_hex(~"e"), Some(14.));
|
||||
|
@ -12,7 +12,7 @@ use T = self::inst::T;
|
||||
|
||||
use from_str::FromStr;
|
||||
use num::{ToStrRadix, FromStrRadix};
|
||||
use num::strconv;
|
||||
use num::{Zero, One, strconv};
|
||||
use prelude::*;
|
||||
|
||||
pub use cmp::{min, max};
|
||||
@ -32,26 +32,26 @@ pub fn mul(x: T, y: T) -> T { x * y }
|
||||
#[inline(always)]
|
||||
pub fn quot(x: T, y: T) -> T { x / y }
|
||||
|
||||
/**
|
||||
* Returns the remainder of y / x.
|
||||
*
|
||||
* # Examples
|
||||
* ~~~
|
||||
* assert!(int::rem(5 / 2) == 1);
|
||||
* ~~~
|
||||
*
|
||||
* When faced with negative numbers, the result copies the sign of the
|
||||
* dividend.
|
||||
*
|
||||
* ~~~
|
||||
* assert!(int::rem(2 / -3) == 2);
|
||||
* ~~~
|
||||
*
|
||||
* ~~~
|
||||
* assert!(int::rem(-2 / 3) == -2);
|
||||
* ~~~
|
||||
*
|
||||
*/
|
||||
///
|
||||
/// Returns the remainder of y / x.
|
||||
///
|
||||
/// # Examples
|
||||
/// ~~~
|
||||
/// assert!(int::rem(5 / 2) == 1);
|
||||
/// ~~~
|
||||
///
|
||||
/// When faced with negative numbers, the result copies the sign of the
|
||||
/// dividend.
|
||||
///
|
||||
/// ~~~
|
||||
/// assert!(int::rem(2 / -3) == 2);
|
||||
/// ~~~
|
||||
///
|
||||
/// ~~~
|
||||
/// assert!(int::rem(-2 / 3) == -2);
|
||||
/// ~~~
|
||||
///
|
||||
///
|
||||
#[inline(always)]
|
||||
pub fn rem(x: T, y: T) -> T { x % y }
|
||||
|
||||
@ -68,23 +68,23 @@ pub fn ge(x: T, y: T) -> bool { x >= y }
|
||||
#[inline(always)]
|
||||
pub fn gt(x: T, y: T) -> bool { x > y }
|
||||
|
||||
/**
|
||||
* Iterate over the range [`lo`..`hi`)
|
||||
*
|
||||
* # Arguments
|
||||
*
|
||||
* * `lo` - lower bound, inclusive
|
||||
* * `hi` - higher bound, exclusive
|
||||
*
|
||||
* # Examples
|
||||
* ~~~
|
||||
* let mut sum = 0;
|
||||
* for int::range(1, 5) |i| {
|
||||
* sum += i;
|
||||
* }
|
||||
* assert!(sum == 10);
|
||||
* ~~~
|
||||
*/
|
||||
///
|
||||
/// Iterate over the range [`lo`..`hi`)
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `lo` - lower bound, inclusive
|
||||
/// * `hi` - higher bound, exclusive
|
||||
///
|
||||
/// # Examples
|
||||
/// ~~~
|
||||
/// let mut sum = 0;
|
||||
/// for int::range(1, 5) |i| {
|
||||
/// sum += i;
|
||||
/// }
|
||||
/// assert!(sum == 10);
|
||||
/// ~~~
|
||||
///
|
||||
#[inline(always)]
|
||||
/// Iterate over the range [`start`,`start`+`step`..`stop`)
|
||||
pub fn range_step(start: T, stop: T, step: T, it: &fn(T) -> bool) {
|
||||
@ -152,12 +152,33 @@ impl Eq for T {
|
||||
fn ne(&self, other: &T) -> bool { return (*self) != (*other); }
|
||||
}
|
||||
|
||||
impl num::Zero for T {
|
||||
impl Orderable for T {
|
||||
#[inline(always)]
|
||||
fn zero() -> T { 0 }
|
||||
fn min(&self, other: &T) -> T {
|
||||
if *self < *other { *self } else { *other }
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn max(&self, other: &T) -> T {
|
||||
if *self > *other { *self } else { *other }
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn clamp(&self, mn: &T, mx: &T) -> T {
|
||||
if *self > *mx { *mx } else
|
||||
if *self < *mn { *mn } else { *self }
|
||||
}
|
||||
}
|
||||
|
||||
impl num::One for T {
|
||||
impl Zero for T {
|
||||
#[inline(always)]
|
||||
fn zero() -> T { 0 }
|
||||
|
||||
#[inline(always)]
|
||||
fn is_zero(&self) -> bool { *self == 0 }
|
||||
}
|
||||
|
||||
impl One for T {
|
||||
#[inline(always)]
|
||||
fn one() -> T { 1 }
|
||||
}
|
||||
@ -187,24 +208,24 @@ impl Div<T,T> for T {
|
||||
}
|
||||
#[cfg(not(stage0),notest)]
|
||||
impl Quot<T,T> for T {
|
||||
/**
|
||||
* Returns the integer quotient, truncated towards 0. As this behaviour reflects
|
||||
* the underlying machine implementation it is more efficient than `Natural::div`.
|
||||
*
|
||||
* # Examples
|
||||
*
|
||||
* ~~~
|
||||
* assert!( 8 / 3 == 2);
|
||||
* assert!( 8 / -3 == -2);
|
||||
* assert!(-8 / 3 == -2);
|
||||
* assert!(-8 / -3 == 2);
|
||||
///
|
||||
/// Returns the integer quotient, truncated towards 0. As this behaviour reflects
|
||||
/// the underlying machine implementation it is more efficient than `Natural::div`.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ~~~
|
||||
/// assert!( 8 / 3 == 2);
|
||||
/// assert!( 8 / -3 == -2);
|
||||
/// assert!(-8 / 3 == -2);
|
||||
/// assert!(-8 / -3 == 2);
|
||||
|
||||
* assert!( 1 / 2 == 0);
|
||||
* assert!( 1 / -2 == 0);
|
||||
* assert!(-1 / 2 == 0);
|
||||
* assert!(-1 / -2 == 0);
|
||||
* ~~~
|
||||
*/
|
||||
/// assert!( 1 / 2 == 0);
|
||||
/// assert!( 1 / -2 == 0);
|
||||
/// assert!(-1 / 2 == 0);
|
||||
/// assert!(-1 / -2 == 0);
|
||||
/// ~~~
|
||||
///
|
||||
#[inline(always)]
|
||||
fn quot(&self, other: &T) -> T { *self / *other }
|
||||
}
|
||||
@ -216,27 +237,27 @@ impl Modulo<T,T> for T {
|
||||
}
|
||||
#[cfg(not(stage0),notest)]
|
||||
impl Rem<T,T> for T {
|
||||
/**
|
||||
* Returns the integer remainder after division, satisfying:
|
||||
*
|
||||
* ~~~
|
||||
* assert!((n / d) * d + (n % d) == n)
|
||||
* ~~~
|
||||
*
|
||||
* # Examples
|
||||
*
|
||||
* ~~~
|
||||
* assert!( 8 % 3 == 2);
|
||||
* assert!( 8 % -3 == 2);
|
||||
* assert!(-8 % 3 == -2);
|
||||
* assert!(-8 % -3 == -2);
|
||||
///
|
||||
/// Returns the integer remainder after division, satisfying:
|
||||
///
|
||||
/// ~~~
|
||||
/// assert!((n / d) * d + (n % d) == n)
|
||||
/// ~~~
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ~~~
|
||||
/// assert!( 8 % 3 == 2);
|
||||
/// assert!( 8 % -3 == 2);
|
||||
/// assert!(-8 % 3 == -2);
|
||||
/// assert!(-8 % -3 == -2);
|
||||
|
||||
* assert!( 1 % 2 == 1);
|
||||
* assert!( 1 % -2 == 1);
|
||||
* assert!(-1 % 2 == -1);
|
||||
* assert!(-1 % -2 == -1);
|
||||
* ~~~
|
||||
*/
|
||||
/// assert!( 1 % 2 == 1);
|
||||
/// assert!( 1 % -2 == 1);
|
||||
/// assert!(-1 % 2 == -1);
|
||||
/// assert!(-1 % -2 == -1);
|
||||
/// ~~~
|
||||
///
|
||||
#[inline(always)]
|
||||
fn rem(&self, other: &T) -> T { *self % *other }
|
||||
}
|
||||
@ -254,13 +275,13 @@ impl Signed for T {
|
||||
if self.is_negative() { -*self } else { *self }
|
||||
}
|
||||
|
||||
/**
|
||||
* # Returns
|
||||
*
|
||||
* - `0` if the number is zero
|
||||
* - `1` if the number is positive
|
||||
* - `-1` if the number is negative
|
||||
*/
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
/// - `0` if the number is zero
|
||||
/// - `1` if the number is positive
|
||||
/// - `-1` if the number is negative
|
||||
///
|
||||
#[inline(always)]
|
||||
fn signum(&self) -> T {
|
||||
match *self {
|
||||
@ -280,23 +301,23 @@ impl Signed for T {
|
||||
}
|
||||
|
||||
impl Integer for T {
|
||||
/**
|
||||
* Floored integer division
|
||||
*
|
||||
* # Examples
|
||||
*
|
||||
* ~~~
|
||||
* assert!(( 8).div( 3) == 2);
|
||||
* assert!(( 8).div(-3) == -3);
|
||||
* assert!((-8).div( 3) == -3);
|
||||
* assert!((-8).div(-3) == 2);
|
||||
*
|
||||
* assert!(( 1).div( 2) == 0);
|
||||
* assert!(( 1).div(-2) == -1);
|
||||
* assert!((-1).div( 2) == -1);
|
||||
* assert!((-1).div(-2) == 0);
|
||||
* ~~~
|
||||
*/
|
||||
///
|
||||
/// Floored integer division
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ~~~
|
||||
/// assert!(( 8).div( 3) == 2);
|
||||
/// assert!(( 8).div(-3) == -3);
|
||||
/// assert!((-8).div( 3) == -3);
|
||||
/// assert!((-8).div(-3) == 2);
|
||||
///
|
||||
/// assert!(( 1).div( 2) == 0);
|
||||
/// assert!(( 1).div(-2) == -1);
|
||||
/// assert!((-1).div( 2) == -1);
|
||||
/// assert!((-1).div(-2) == 0);
|
||||
/// ~~~
|
||||
///
|
||||
#[inline(always)]
|
||||
fn div(&self, other: &T) -> T {
|
||||
// Algorithm from [Daan Leijen. _Division and Modulus for Computer Scientists_,
|
||||
@ -308,27 +329,27 @@ impl Integer for T {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Integer modulo, satisfying:
|
||||
*
|
||||
* ~~~
|
||||
* assert!(n.div(d) * d + n.modulo(d) == n)
|
||||
* ~~~
|
||||
*
|
||||
* # Examples
|
||||
*
|
||||
* ~~~
|
||||
* assert!(( 8).modulo( 3) == 2);
|
||||
* assert!(( 8).modulo(-3) == -1);
|
||||
* assert!((-8).modulo( 3) == 1);
|
||||
* assert!((-8).modulo(-3) == -2);
|
||||
*
|
||||
* assert!(( 1).modulo( 2) == 1);
|
||||
* assert!(( 1).modulo(-2) == -1);
|
||||
* assert!((-1).modulo( 2) == 1);
|
||||
* assert!((-1).modulo(-2) == -1);
|
||||
* ~~~
|
||||
*/
|
||||
///
|
||||
/// Integer modulo, satisfying:
|
||||
///
|
||||
/// ~~~
|
||||
/// assert!(n.div(d) * d + n.modulo(d) == n)
|
||||
/// ~~~
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ~~~
|
||||
/// assert!(( 8).modulo( 3) == 2);
|
||||
/// assert!(( 8).modulo(-3) == -1);
|
||||
/// assert!((-8).modulo( 3) == 1);
|
||||
/// assert!((-8).modulo(-3) == -2);
|
||||
///
|
||||
/// assert!(( 1).modulo( 2) == 1);
|
||||
/// assert!(( 1).modulo(-2) == -1);
|
||||
/// assert!((-1).modulo( 2) == 1);
|
||||
/// assert!((-1).modulo(-2) == -1);
|
||||
/// ~~~
|
||||
///
|
||||
#[inline(always)]
|
||||
fn modulo(&self, other: &T) -> T {
|
||||
// Algorithm from [Daan Leijen. _Division and Modulus for Computer Scientists_,
|
||||
@ -358,11 +379,11 @@ impl Integer for T {
|
||||
(*self / *other, *self % *other)
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the Greatest Common Divisor (GCD) of the number and `other`
|
||||
*
|
||||
* The result is always positive
|
||||
*/
|
||||
///
|
||||
/// Calculates the Greatest Common Divisor (GCD) of the number and `other`
|
||||
///
|
||||
/// The result is always positive
|
||||
///
|
||||
#[inline(always)]
|
||||
fn gcd(&self, other: &T) -> T {
|
||||
// Use Euclid's algorithm
|
||||
@ -375,9 +396,9 @@ impl Integer for T {
|
||||
n.abs()
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the Lowest Common Multiple (LCM) of the number and `other`
|
||||
*/
|
||||
///
|
||||
/// Calculates the Lowest Common Multiple (LCM) of the number and `other`
|
||||
///
|
||||
#[inline(always)]
|
||||
fn lcm(&self, other: &T) -> T {
|
||||
((*self * *other) / self.gcd(other)).abs() // should not have to recaluculate abs
|
||||
@ -396,6 +417,8 @@ impl Integer for T {
|
||||
fn is_odd(&self) -> bool { !self.is_even() }
|
||||
}
|
||||
|
||||
impl Bitwise for T {}
|
||||
|
||||
#[cfg(notest)]
|
||||
impl BitOr<T,T> for T {
|
||||
#[inline(always)]
|
||||
@ -432,6 +455,16 @@ impl Not<T> for T {
|
||||
fn not(&self) -> T { !*self }
|
||||
}
|
||||
|
||||
impl Bounded for T {
|
||||
#[inline(always)]
|
||||
fn min_value() -> T { min_value }
|
||||
|
||||
#[inline(always)]
|
||||
fn max_value() -> T { max_value }
|
||||
}
|
||||
|
||||
impl Int for T {}
|
||||
|
||||
// String conversion functions and impl str -> num
|
||||
|
||||
/// Parse a string as a number in base 10.
|
||||
@ -520,6 +553,17 @@ mod tests {
|
||||
num::test_num(10 as T, 2 as T);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_orderable() {
|
||||
assert_eq!((1 as T).min(&(2 as T)), 1 as T);
|
||||
assert_eq!((2 as T).min(&(1 as T)), 1 as T);
|
||||
assert_eq!((1 as T).max(&(2 as T)), 2 as T);
|
||||
assert_eq!((2 as T).max(&(1 as T)), 2 as T);
|
||||
assert_eq!((1 as T).clamp(&(2 as T), &(4 as T)), 2 as T);
|
||||
assert_eq!((8 as T).clamp(&(2 as T), &(4 as T)), 4 as T);
|
||||
assert_eq!((3 as T).clamp(&(2 as T), &(4 as T)), 3 as T);
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn test_signed() {
|
||||
assert_eq!((1 as T).abs(), 1 as T);
|
||||
@ -542,18 +586,15 @@ mod tests {
|
||||
assert!((-1 as T).is_negative());
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that the division rule holds for:
|
||||
*
|
||||
* - `n`: numerator (dividend)
|
||||
* - `d`: denominator (divisor)
|
||||
* - `qr`: quotient and remainder
|
||||
*/
|
||||
///
|
||||
/// Checks that the division rule holds for:
|
||||
///
|
||||
/// - `n`: numerator (dividend)
|
||||
/// - `d`: denominator (divisor)
|
||||
/// - `qr`: quotient and remainder
|
||||
///
|
||||
#[cfg(test)]
|
||||
fn test_division_rule(nd: (T,T), qr: (T,T)) {
|
||||
let (n,d) = nd,
|
||||
(q,r) = qr;
|
||||
|
||||
fn test_division_rule((n,d): (T,T), (q,r): (T,T)) {
|
||||
assert_eq!(d * q + r, n);
|
||||
}
|
||||
|
||||
@ -632,7 +673,7 @@ mod tests {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_bitwise_ops() {
|
||||
fn test_bitwise() {
|
||||
assert_eq!(0b1110 as T, (0b1100 as T).bitor(&(0b1010 as T)));
|
||||
assert_eq!(0b1000 as T, (0b1100 as T).bitand(&(0b1010 as T)));
|
||||
assert_eq!(0b0110 as T, (0b1100 as T).bitxor(&(0b1010 as T)));
|
||||
@ -641,6 +682,17 @@ mod tests {
|
||||
assert_eq!(-(0b11 as T) - (1 as T), (0b11 as T).not());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_bitcount() {
|
||||
assert_eq!((0b010101 as T).population_count(), 3);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_primitive() {
|
||||
assert_eq!(Primitive::bits::<T>(), sys::size_of::<T>() * 8);
|
||||
assert_eq!(Primitive::bytes::<T>(), sys::size_of::<T>());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_from_str() {
|
||||
assert_eq!(from_str(~"0"), Some(0 as T));
|
||||
|
@ -11,6 +11,31 @@
|
||||
//! Operations and constants for `i16`
|
||||
|
||||
mod inst {
|
||||
use num::{Primitive, BitCount};
|
||||
use unstable::intrinsics;
|
||||
|
||||
pub type T = i16;
|
||||
pub static bits: uint = ::u16::bits;
|
||||
|
||||
impl Primitive for i16 {
|
||||
#[inline(always)]
|
||||
fn bits() -> uint { 16 }
|
||||
|
||||
#[inline(always)]
|
||||
fn bytes() -> uint { Primitive::bits::<i16>() / 8 }
|
||||
}
|
||||
|
||||
impl BitCount for i16 {
|
||||
/// Counts the number of bits set. Wraps LLVM's `ctpop` intrinsic.
|
||||
#[inline(always)]
|
||||
fn population_count(&self) -> i16 { unsafe { intrinsics::ctpop16(*self) } }
|
||||
|
||||
/// Counts the number of leading zeros. Wraps LLVM's `ctlz` intrinsic.
|
||||
#[inline(always)]
|
||||
fn leading_zeros(&self) -> i16 { unsafe { intrinsics::ctlz16(*self) } }
|
||||
|
||||
/// Counts the number of trailing zeros. Wraps LLVM's `cttz` intrinsic.
|
||||
#[inline(always)]
|
||||
fn trailing_zeros(&self) -> i16 { unsafe { intrinsics::cttz16(*self) } }
|
||||
}
|
||||
}
|
||||
|
@ -11,6 +11,31 @@
|
||||
//! Operations and constants for `i32`
|
||||
|
||||
mod inst {
|
||||
use num::{Primitive, BitCount};
|
||||
use unstable::intrinsics;
|
||||
|
||||
pub type T = i32;
|
||||
pub static bits: uint = ::u32::bits;
|
||||
|
||||
impl Primitive for i32 {
|
||||
#[inline(always)]
|
||||
fn bits() -> uint { 32 }
|
||||
|
||||
#[inline(always)]
|
||||
fn bytes() -> uint { Primitive::bits::<i32>() / 8 }
|
||||
}
|
||||
|
||||
impl BitCount for i32 {
|
||||
/// Counts the number of bits set. Wraps LLVM's `ctpop` intrinsic.
|
||||
#[inline(always)]
|
||||
fn population_count(&self) -> i32 { unsafe { intrinsics::ctpop32(*self) } }
|
||||
|
||||
/// Counts the number of leading zeros. Wraps LLVM's `ctlz` intrinsic.
|
||||
#[inline(always)]
|
||||
fn leading_zeros(&self) -> i32 { unsafe { intrinsics::ctlz32(*self) } }
|
||||
|
||||
/// Counts the number of trailing zeros. Wraps LLVM's `cttz` intrinsic.
|
||||
#[inline(always)]
|
||||
fn trailing_zeros(&self) -> i32 { unsafe { intrinsics::cttz32(*self) } }
|
||||
}
|
||||
}
|
||||
|
@ -11,6 +11,31 @@
|
||||
//! Operations and constants for `i64`
|
||||
|
||||
mod inst {
|
||||
use num::{Primitive, BitCount};
|
||||
use unstable::intrinsics;
|
||||
|
||||
pub type T = i64;
|
||||
pub static bits: uint = ::u64::bits;
|
||||
|
||||
impl Primitive for i64 {
|
||||
#[inline(always)]
|
||||
fn bits() -> uint { 64 }
|
||||
|
||||
#[inline(always)]
|
||||
fn bytes() -> uint { Primitive::bits::<i64>() / 8 }
|
||||
}
|
||||
|
||||
impl BitCount for i64 {
|
||||
/// Counts the number of bits set. Wraps LLVM's `ctpop` intrinsic.
|
||||
#[inline(always)]
|
||||
fn population_count(&self) -> i64 { unsafe { intrinsics::ctpop64(*self) } }
|
||||
|
||||
/// Counts the number of leading zeros. Wraps LLVM's `ctlz` intrinsic.
|
||||
#[inline(always)]
|
||||
fn leading_zeros(&self) -> i64 { unsafe { intrinsics::ctlz64(*self) } }
|
||||
|
||||
/// Counts the number of trailing zeros. Wraps LLVM's `cttz` intrinsic.
|
||||
#[inline(always)]
|
||||
fn trailing_zeros(&self) -> i64 { unsafe { intrinsics::cttz64(*self) } }
|
||||
}
|
||||
}
|
||||
|
@ -11,6 +11,31 @@
|
||||
//! Operations and constants for `i8`
|
||||
|
||||
mod inst {
|
||||
use num::{Primitive, BitCount};
|
||||
use unstable::intrinsics;
|
||||
|
||||
pub type T = i8;
|
||||
pub static bits: uint = ::u8::bits;
|
||||
|
||||
impl Primitive for i8 {
|
||||
#[inline(always)]
|
||||
fn bits() -> uint { 8 }
|
||||
|
||||
#[inline(always)]
|
||||
fn bytes() -> uint { Primitive::bits::<i8>() / 8 }
|
||||
}
|
||||
|
||||
impl BitCount for i8 {
|
||||
/// Counts the number of bits set. Wraps LLVM's `ctpop` intrinsic.
|
||||
#[inline(always)]
|
||||
fn population_count(&self) -> i8 { unsafe { intrinsics::ctpop8(*self) } }
|
||||
|
||||
/// Counts the number of leading zeros. Wraps LLVM's `ctlz` intrinsic.
|
||||
#[inline(always)]
|
||||
fn leading_zeros(&self) -> i8 { unsafe { intrinsics::ctlz8(*self) } }
|
||||
|
||||
/// Counts the number of trailing zeros. Wraps LLVM's `cttz` intrinsic.
|
||||
#[inline(always)]
|
||||
fn trailing_zeros(&self) -> i8 { unsafe { intrinsics::cttz8(*self) } }
|
||||
}
|
||||
}
|
||||
|
@ -13,9 +13,56 @@
|
||||
pub use self::inst::pow;
|
||||
|
||||
mod inst {
|
||||
use num::{Primitive, BitCount};
|
||||
|
||||
pub type T = int;
|
||||
pub static bits: uint = ::uint::bits;
|
||||
|
||||
impl Primitive for int {
|
||||
#[cfg(target_word_size = "32")]
|
||||
#[inline(always)]
|
||||
fn bits() -> uint { 32 }
|
||||
|
||||
#[cfg(target_word_size = "64")]
|
||||
#[inline(always)]
|
||||
fn bits() -> uint { 64 }
|
||||
|
||||
#[inline(always)]
|
||||
fn bytes() -> uint { Primitive::bits::<int>() / 8 }
|
||||
}
|
||||
|
||||
#[cfg(target_word_size = "32")]
|
||||
#[inline(always)]
|
||||
impl BitCount for int {
|
||||
/// Counts the number of bits set. Wraps LLVM's `ctpop` intrinsic.
|
||||
#[inline(always)]
|
||||
fn population_count(&self) -> int { (*self as i32).population_count() as int }
|
||||
|
||||
/// Counts the number of leading zeros. Wraps LLVM's `ctlz` intrinsic.
|
||||
#[inline(always)]
|
||||
fn leading_zeros(&self) -> int { (*self as i32).leading_zeros() as int }
|
||||
|
||||
/// Counts the number of trailing zeros. Wraps LLVM's `cttz` intrinsic.
|
||||
#[inline(always)]
|
||||
fn trailing_zeros(&self) -> int { (*self as i32).trailing_zeros() as int }
|
||||
}
|
||||
|
||||
#[cfg(target_word_size = "64")]
|
||||
#[inline(always)]
|
||||
impl BitCount for int {
|
||||
/// Counts the number of bits set. Wraps LLVM's `ctpop` intrinsic.
|
||||
#[inline(always)]
|
||||
fn population_count(&self) -> int { (*self as i64).population_count() as int }
|
||||
|
||||
/// Counts the number of leading zeros. Wraps LLVM's `ctlz` intrinsic.
|
||||
#[inline(always)]
|
||||
fn leading_zeros(&self) -> int { (*self as i64).leading_zeros() as int }
|
||||
|
||||
/// Counts the number of trailing zeros. Wraps LLVM's `cttz` intrinsic.
|
||||
#[inline(always)]
|
||||
fn trailing_zeros(&self) -> int { (*self as i64).trailing_zeros() as int }
|
||||
}
|
||||
|
||||
/// Returns `base` raised to the power of `exponent`
|
||||
pub fn pow(base: int, exponent: uint) -> int {
|
||||
if exponent == 0u {
|
||||
|
@ -18,11 +18,15 @@ use Quot = ops::Div;
|
||||
use Rem = ops::Modulo;
|
||||
#[cfg(not(stage0))]
|
||||
use ops::{Add, Sub, Mul, Quot, Rem, Neg};
|
||||
use ops::{Not, BitAnd, BitOr, BitXor, Shl, Shr};
|
||||
use option::Option;
|
||||
use kinds::Copy;
|
||||
|
||||
pub mod strconv;
|
||||
|
||||
///
|
||||
/// The base trait for numeric types
|
||||
///
|
||||
pub trait Num: Eq + Zero + One
|
||||
+ Neg<Self>
|
||||
+ Add<Self,Self>
|
||||
@ -36,14 +40,23 @@ pub trait IntConvertible {
|
||||
fn from_int(n: int) -> Self;
|
||||
}
|
||||
|
||||
pub trait Orderable: Ord {
|
||||
// These should be methods on `Ord`, with overridable default implementations. We don't want
|
||||
// to encumber all implementors of Ord by requiring them to implement these functions, but at
|
||||
// the same time we want to be able to take advantage of the speed of the specific numeric
|
||||
// functions (like the `fmin` and `fmax` intrinsics).
|
||||
fn min(&self, other: &Self) -> Self;
|
||||
fn max(&self, other: &Self) -> Self;
|
||||
fn clamp(&self, mn: &Self, mx: &Self) -> Self;
|
||||
}
|
||||
|
||||
pub trait Zero {
|
||||
// FIXME (#5527): These should be associated constants
|
||||
fn zero() -> Self;
|
||||
fn zero() -> Self; // FIXME (#5527): This should be an associated constant
|
||||
fn is_zero(&self) -> bool;
|
||||
}
|
||||
|
||||
pub trait One {
|
||||
// FIXME (#5527): These should be associated constants
|
||||
fn one() -> Self;
|
||||
fn one() -> Self; // FIXME (#5527): This should be an associated constant
|
||||
}
|
||||
|
||||
pub trait Signed: Num
|
||||
@ -62,7 +75,7 @@ pub fn abs<T:Ord + Zero + Neg<T>>(v: T) -> T {
|
||||
}
|
||||
|
||||
pub trait Integer: Num
|
||||
+ Ord
|
||||
+ Orderable
|
||||
+ Quot<Self,Self>
|
||||
+ Rem<Self,Self> {
|
||||
fn div(&self, other: &Self) -> Self;
|
||||
@ -86,12 +99,15 @@ pub trait Round {
|
||||
}
|
||||
|
||||
pub trait Fractional: Num
|
||||
+ Ord
|
||||
+ Orderable
|
||||
+ Round
|
||||
+ Quot<Self,Self> {
|
||||
fn recip(&self) -> Self;
|
||||
}
|
||||
|
||||
///
|
||||
/// Defines constants and methods common to real numbers
|
||||
///
|
||||
pub trait Real: Signed
|
||||
+ Fractional {
|
||||
// FIXME (#5527): usages of `int` should be replaced with an associated
|
||||
@ -154,7 +170,9 @@ pub trait Real: Signed
|
||||
fn tanh(&self) -> Self;
|
||||
}
|
||||
|
||||
///
|
||||
/// Methods that are harder to implement and not commonly used.
|
||||
///
|
||||
pub trait RealExt: Real {
|
||||
// FIXME (#5527): usages of `int` should be replaced with an associated
|
||||
// integer type once these are implemented
|
||||
@ -172,24 +190,101 @@ pub trait RealExt: Real {
|
||||
fn yn(&self, n: int) -> Self;
|
||||
}
|
||||
|
||||
/**
|
||||
* Cast from one machine scalar to another
|
||||
*
|
||||
* # Example
|
||||
*
|
||||
* ~~~
|
||||
* let twenty: f32 = num::cast(0x14);
|
||||
* assert_eq!(twenty, 20f32);
|
||||
* ~~~
|
||||
*/
|
||||
///
|
||||
/// Collects the bitwise operators under one trait.
|
||||
///
|
||||
pub trait Bitwise: Not<Self>
|
||||
+ BitAnd<Self,Self>
|
||||
+ BitOr<Self,Self>
|
||||
+ BitXor<Self,Self>
|
||||
+ Shl<Self,Self>
|
||||
+ Shr<Self,Self> {}
|
||||
|
||||
pub trait BitCount {
|
||||
fn population_count(&self) -> Self;
|
||||
fn leading_zeros(&self) -> Self;
|
||||
fn trailing_zeros(&self) -> Self;
|
||||
}
|
||||
|
||||
pub trait Bounded {
|
||||
// FIXME (#5527): These should be associated constants
|
||||
fn min_value() -> Self;
|
||||
fn max_value() -> Self;
|
||||
}
|
||||
|
||||
///
|
||||
/// Specifies the available operations common to all of Rust's core numeric primitives.
|
||||
/// These may not always make sense from a purely mathematical point of view, but
|
||||
/// may be useful for systems programming.
|
||||
///
|
||||
pub trait Primitive: Num
|
||||
+ NumCast
|
||||
+ Bounded
|
||||
+ Neg<Self>
|
||||
+ Add<Self,Self>
|
||||
+ Sub<Self,Self>
|
||||
+ Mul<Self,Self>
|
||||
+ Quot<Self,Self>
|
||||
+ Rem<Self,Self> {
|
||||
// FIXME (#5527): These should be associated constants
|
||||
fn bits() -> uint;
|
||||
fn bytes() -> uint;
|
||||
}
|
||||
|
||||
///
|
||||
/// A collection of traits relevant to primitive signed and unsigned integers
|
||||
///
|
||||
pub trait Int: Integer
|
||||
+ Primitive
|
||||
+ Bitwise
|
||||
+ BitCount {}
|
||||
|
||||
///
|
||||
/// Primitive floating point numbers
|
||||
///
|
||||
pub trait Float: Real
|
||||
+ Signed
|
||||
+ Primitive {
|
||||
// FIXME (#5527): These should be associated constants
|
||||
fn NaN() -> Self;
|
||||
fn infinity() -> Self;
|
||||
fn neg_infinity() -> Self;
|
||||
fn neg_zero() -> Self;
|
||||
|
||||
fn is_NaN(&self) -> bool;
|
||||
fn is_infinite(&self) -> bool;
|
||||
fn is_finite(&self) -> bool;
|
||||
|
||||
fn mantissa_digits() -> uint;
|
||||
fn digits() -> uint;
|
||||
fn epsilon() -> Self;
|
||||
fn min_exp() -> int;
|
||||
fn max_exp() -> int;
|
||||
fn min_10_exp() -> int;
|
||||
fn max_10_exp() -> int;
|
||||
|
||||
fn mul_add(&self, a: Self, b: Self) -> Self;
|
||||
fn next_after(&self, other: Self) -> Self;
|
||||
}
|
||||
|
||||
///
|
||||
/// Cast from one machine scalar to another
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ~~~
|
||||
/// let twenty: f32 = num::cast(0x14);
|
||||
/// assert_eq!(twenty, 20f32);
|
||||
/// ~~~
|
||||
///
|
||||
#[inline(always)]
|
||||
pub fn cast<T:NumCast,U:NumCast>(n: T) -> U {
|
||||
NumCast::from(n)
|
||||
}
|
||||
|
||||
/**
|
||||
* An interface for casting between machine scalars
|
||||
*/
|
||||
///
|
||||
/// An interface for casting between machine scalars
|
||||
///
|
||||
pub trait NumCast {
|
||||
fn from<T:NumCast>(n: T) -> Self;
|
||||
|
||||
@ -261,21 +356,19 @@ pub trait FromStrRadix {
|
||||
pub fn from_str_radix(str: &str, radix: uint) -> Option<Self>;
|
||||
}
|
||||
|
||||
// Generic math functions:
|
||||
|
||||
/**
|
||||
* Calculates a power to a given radix, optimized for uint `pow` and `radix`.
|
||||
*
|
||||
* Returns `radix^pow` as `T`.
|
||||
*
|
||||
* Note:
|
||||
* Also returns `1` for `0^0`, despite that technically being an
|
||||
* undefined number. The reason for this is twofold:
|
||||
* - If code written to use this function cares about that special case, it's
|
||||
* probably going to catch it before making the call.
|
||||
* - If code written to use this function doesn't care about it, it's
|
||||
* probably assuming that `x^0` always equals `1`.
|
||||
*/
|
||||
///
|
||||
/// Calculates a power to a given radix, optimized for uint `pow` and `radix`.
|
||||
///
|
||||
/// Returns `radix^pow` as `T`.
|
||||
///
|
||||
/// Note:
|
||||
/// Also returns `1` for `0^0`, despite that technically being an
|
||||
/// undefined number. The reason for this is twofold:
|
||||
/// - If code written to use this function cares about that special case, it's
|
||||
/// probably going to catch it before making the call.
|
||||
/// - If code written to use this function doesn't care about it, it's
|
||||
/// probably assuming that `x^0` always equals `1`.
|
||||
///
|
||||
pub fn pow_with_uint<T:NumCast+One+Zero+Copy+Quot<T,T>+Mul<T,T>>(
|
||||
radix: uint, pow: uint) -> T {
|
||||
let _0: T = Zero::zero();
|
||||
|
@ -13,7 +13,7 @@ use T_SIGNED = self::inst::T_SIGNED;
|
||||
|
||||
use from_str::FromStr;
|
||||
use num::{ToStrRadix, FromStrRadix};
|
||||
use num::strconv;
|
||||
use num::{Zero, One, strconv};
|
||||
use prelude::*;
|
||||
|
||||
pub use cmp::{min, max};
|
||||
@ -49,10 +49,9 @@ pub fn ge(x: T, y: T) -> bool { x >= y }
|
||||
pub fn gt(x: T, y: T) -> bool { x > y }
|
||||
|
||||
#[inline(always)]
|
||||
/**
|
||||
* Iterate over the range [`start`,`start`+`step`..`stop`)
|
||||
*
|
||||
*/
|
||||
///
|
||||
/// Iterate over the range [`start`,`start`+`step`..`stop`)
|
||||
///
|
||||
pub fn range_step(start: T,
|
||||
stop: T,
|
||||
step: T_SIGNED,
|
||||
@ -118,12 +117,33 @@ impl Eq for T {
|
||||
fn ne(&self, other: &T) -> bool { return (*self) != (*other); }
|
||||
}
|
||||
|
||||
impl num::Zero for T {
|
||||
impl Orderable for T {
|
||||
#[inline(always)]
|
||||
fn zero() -> T { 0 }
|
||||
fn min(&self, other: &T) -> T {
|
||||
if *self < *other { *self } else { *other }
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn max(&self, other: &T) -> T {
|
||||
if *self > *other { *self } else { *other }
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn clamp(&self, mn: &T, mx: &T) -> T {
|
||||
if *self > *mx { *mx } else
|
||||
if *self < *mn { *mn } else { *self }
|
||||
}
|
||||
}
|
||||
|
||||
impl num::One for T {
|
||||
impl Zero for T {
|
||||
#[inline(always)]
|
||||
fn zero() -> T { 0 }
|
||||
|
||||
#[inline(always)]
|
||||
fn is_zero(&self) -> bool { *self == 0 }
|
||||
}
|
||||
|
||||
impl One for T {
|
||||
#[inline(always)]
|
||||
fn one() -> T { 1 }
|
||||
}
|
||||
@ -229,6 +249,8 @@ impl Integer for T {
|
||||
fn is_odd(&self) -> bool { !self.is_even() }
|
||||
}
|
||||
|
||||
impl Bitwise for T {}
|
||||
|
||||
#[cfg(notest)]
|
||||
impl BitOr<T,T> for T {
|
||||
#[inline(always)]
|
||||
@ -265,6 +287,16 @@ impl Not<T> for T {
|
||||
fn not(&self) -> T { !*self }
|
||||
}
|
||||
|
||||
impl Bounded for T {
|
||||
#[inline(always)]
|
||||
fn min_value() -> T { min_value }
|
||||
|
||||
#[inline(always)]
|
||||
fn max_value() -> T { max_value }
|
||||
}
|
||||
|
||||
impl Int for T {}
|
||||
|
||||
// String conversion functions and impl str -> num
|
||||
|
||||
/// Parse a string as a number in base 10.
|
||||
@ -353,6 +385,17 @@ mod tests {
|
||||
num::test_num(10 as T, 2 as T);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_orderable() {
|
||||
assert_eq!((1 as T).min(&(2 as T)), 1 as T);
|
||||
assert_eq!((2 as T).min(&(1 as T)), 1 as T);
|
||||
assert_eq!((1 as T).max(&(2 as T)), 2 as T);
|
||||
assert_eq!((2 as T).max(&(1 as T)), 2 as T);
|
||||
assert_eq!((1 as T).clamp(&(2 as T), &(4 as T)), 2 as T);
|
||||
assert_eq!((8 as T).clamp(&(2 as T), &(4 as T)), 4 as T);
|
||||
assert_eq!((3 as T).clamp(&(2 as T), &(4 as T)), 3 as T);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_gcd() {
|
||||
assert_eq!((10 as T).gcd(&2), 2 as T);
|
||||
@ -373,7 +416,7 @@ mod tests {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_bitwise_ops() {
|
||||
fn test_bitwise() {
|
||||
assert_eq!(0b1110 as T, (0b1100 as T).bitor(&(0b1010 as T)));
|
||||
assert_eq!(0b1000 as T, (0b1100 as T).bitand(&(0b1010 as T)));
|
||||
assert_eq!(0b0110 as T, (0b1100 as T).bitxor(&(0b1010 as T)));
|
||||
@ -382,6 +425,17 @@ mod tests {
|
||||
assert_eq!(max_value - (0b1011 as T), (0b1011 as T).not());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_bitcount() {
|
||||
assert_eq!((0b010101 as T).population_count(), 3);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_primitive() {
|
||||
assert_eq!(Primitive::bits::<T>(), sys::size_of::<T>() * 8);
|
||||
assert_eq!(Primitive::bytes::<T>(), sys::size_of::<T>());
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn test_to_str() {
|
||||
assert_eq!(to_str_radix(0 as T, 10u), ~"0");
|
||||
|
@ -11,8 +11,33 @@
|
||||
//! Operations and constants for `u16`
|
||||
|
||||
mod inst {
|
||||
use num::{Primitive, BitCount};
|
||||
use unstable::intrinsics;
|
||||
|
||||
pub type T = u16;
|
||||
#[allow(non_camel_case_types)]
|
||||
pub type T_SIGNED = i16;
|
||||
pub static bits: uint = 16;
|
||||
|
||||
impl Primitive for u16 {
|
||||
#[inline(always)]
|
||||
fn bits() -> uint { 16 }
|
||||
|
||||
#[inline(always)]
|
||||
fn bytes() -> uint { Primitive::bits::<u16>() / 8 }
|
||||
}
|
||||
|
||||
impl BitCount for u16 {
|
||||
/// Counts the number of bits set. Wraps LLVM's `ctpop` intrinsic.
|
||||
#[inline(always)]
|
||||
fn population_count(&self) -> u16 { unsafe { intrinsics::ctpop16(*self as i16) as u16 } }
|
||||
|
||||
/// Counts the number of leading zeros. Wraps LLVM's `ctlz` intrinsic.
|
||||
#[inline(always)]
|
||||
fn leading_zeros(&self) -> u16 { unsafe { intrinsics::ctlz16(*self as i16) as u16 } }
|
||||
|
||||
/// Counts the number of trailing zeros. Wraps LLVM's `cttz` intrinsic.
|
||||
#[inline(always)]
|
||||
fn trailing_zeros(&self) -> u16 { unsafe { intrinsics::cttz16(*self as i16) as u16 } }
|
||||
}
|
||||
}
|
||||
|
@ -11,8 +11,33 @@
|
||||
//! Operations and constants for `u32`
|
||||
|
||||
mod inst {
|
||||
use num::{Primitive, BitCount};
|
||||
use unstable::intrinsics;
|
||||
|
||||
pub type T = u32;
|
||||
#[allow(non_camel_case_types)]
|
||||
pub type T_SIGNED = i32;
|
||||
pub static bits: uint = 32;
|
||||
|
||||
impl Primitive for u32 {
|
||||
#[inline(always)]
|
||||
fn bits() -> uint { 32 }
|
||||
|
||||
#[inline(always)]
|
||||
fn bytes() -> uint { Primitive::bits::<u32>() / 8 }
|
||||
}
|
||||
|
||||
impl BitCount for u32 {
|
||||
/// Counts the number of bits set. Wraps LLVM's `ctpop` intrinsic.
|
||||
#[inline(always)]
|
||||
fn population_count(&self) -> u32 { unsafe { intrinsics::ctpop32(*self as i32) as u32 } }
|
||||
|
||||
/// Counts the number of leading zeros. Wraps LLVM's `ctlp` intrinsic.
|
||||
#[inline(always)]
|
||||
fn leading_zeros(&self) -> u32 { unsafe { intrinsics::ctlz32(*self as i32) as u32 } }
|
||||
|
||||
/// Counts the number of trailing zeros. Wraps LLVM's `cttp` intrinsic.
|
||||
#[inline(always)]
|
||||
fn trailing_zeros(&self) -> u32 { unsafe { intrinsics::cttz32(*self as i32) as u32 } }
|
||||
}
|
||||
}
|
||||
|
@ -11,8 +11,33 @@
|
||||
//! Operations and constants for `u64`
|
||||
|
||||
mod inst {
|
||||
use num::{Primitive, BitCount};
|
||||
use unstable::intrinsics;
|
||||
|
||||
pub type T = u64;
|
||||
#[allow(non_camel_case_types)]
|
||||
pub type T_SIGNED = i64;
|
||||
pub static bits: uint = 64;
|
||||
|
||||
impl Primitive for u64 {
|
||||
#[inline(always)]
|
||||
fn bits() -> uint { 64 }
|
||||
|
||||
#[inline(always)]
|
||||
fn bytes() -> uint { Primitive::bits::<u64>() / 8 }
|
||||
}
|
||||
|
||||
impl BitCount for u64 {
|
||||
/// Counts the number of bits set. Wraps LLVM's `ctpop` intrinsic.
|
||||
#[inline(always)]
|
||||
fn population_count(&self) -> u64 { unsafe { intrinsics::ctpop64(*self as i64) as u64 } }
|
||||
|
||||
/// Counts the number of leading zeros. Wraps LLVM's `ctlz` intrinsic.
|
||||
#[inline(always)]
|
||||
fn leading_zeros(&self) -> u64 { unsafe { intrinsics::ctlz64(*self as i64) as u64 } }
|
||||
|
||||
/// Counts the number of trailing zeros. Wraps LLVM's `cttz` intrinsic.
|
||||
#[inline(always)]
|
||||
fn trailing_zeros(&self) -> u64 { unsafe { intrinsics::cttz64(*self as i64) as u64 } }
|
||||
}
|
||||
}
|
||||
|
@ -11,8 +11,33 @@
|
||||
//! Operations and constants for `u8`
|
||||
|
||||
mod inst {
|
||||
use num::{Primitive, BitCount};
|
||||
use unstable::intrinsics;
|
||||
|
||||
pub type T = u8;
|
||||
#[allow(non_camel_case_types)]
|
||||
pub type T_SIGNED = i8;
|
||||
pub static bits: uint = 8;
|
||||
|
||||
impl Primitive for u8 {
|
||||
#[inline(always)]
|
||||
fn bits() -> uint { 8 }
|
||||
|
||||
#[inline(always)]
|
||||
fn bytes() -> uint { Primitive::bits::<u8>() / 8 }
|
||||
}
|
||||
|
||||
impl BitCount for u8 {
|
||||
/// Counts the number of bits set. Wraps LLVM's `ctpop` intrinsic.
|
||||
#[inline(always)]
|
||||
fn population_count(&self) -> u8 { unsafe { intrinsics::ctpop8(*self as i8) as u8 } }
|
||||
|
||||
/// Counts the number of leading zeros. Wraps LLVM's `ctlz` intrinsic.
|
||||
#[inline(always)]
|
||||
fn leading_zeros(&self) -> u8 { unsafe { intrinsics::ctlz8(*self as i8) as u8 } }
|
||||
|
||||
/// Counts the number of trailing zeros. Wraps LLVM's `cttz` intrinsic.
|
||||
#[inline(always)]
|
||||
fn trailing_zeros(&self) -> u8 { unsafe { intrinsics::cttz8(*self as i8) as u8 } }
|
||||
}
|
||||
}
|
||||
|
@ -18,6 +18,7 @@ pub use self::inst::{
|
||||
pub mod inst {
|
||||
use sys;
|
||||
use iter;
|
||||
use num::{Primitive, BitCount};
|
||||
|
||||
pub type T = uint;
|
||||
#[allow(non_camel_case_types)]
|
||||
@ -31,74 +32,119 @@ pub mod inst {
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
pub static bits: uint = 64;
|
||||
|
||||
/**
|
||||
* Divide two numbers, return the result, rounded up.
|
||||
*
|
||||
* # Arguments
|
||||
*
|
||||
* * x - an integer
|
||||
* * y - an integer distinct from 0u
|
||||
*
|
||||
* # Return value
|
||||
*
|
||||
* The smallest integer `q` such that `x/y <= q`.
|
||||
*/
|
||||
impl Primitive for uint {
|
||||
#[cfg(target_word_size = "32")]
|
||||
#[inline(always)]
|
||||
fn bits() -> uint { 32 }
|
||||
|
||||
#[cfg(target_word_size = "64")]
|
||||
#[inline(always)]
|
||||
fn bits() -> uint { 64 }
|
||||
|
||||
#[inline(always)]
|
||||
fn bytes() -> uint { Primitive::bits::<uint>() / 8 }
|
||||
}
|
||||
|
||||
#[cfg(target_word_size = "32")]
|
||||
#[inline(always)]
|
||||
impl BitCount for uint {
|
||||
/// Counts the number of bits set. Wraps LLVM's `ctpop` intrinsic.
|
||||
#[inline(always)]
|
||||
fn population_count(&self) -> uint { (*self as i32).population_count() as uint }
|
||||
|
||||
/// Counts the number of leading zeros. Wraps LLVM's `ctlz` intrinsic.
|
||||
#[inline(always)]
|
||||
fn leading_zeros(&self) -> uint { (*self as i32).leading_zeros() as uint }
|
||||
|
||||
/// Counts the number of trailing zeros. Wraps LLVM's `cttz` intrinsic.
|
||||
#[inline(always)]
|
||||
fn trailing_zeros(&self) -> uint { (*self as i32).trailing_zeros() as uint }
|
||||
}
|
||||
|
||||
#[cfg(target_word_size = "64")]
|
||||
#[inline(always)]
|
||||
impl BitCount for uint {
|
||||
/// Counts the number of bits set. Wraps LLVM's `ctpop` intrinsic.
|
||||
#[inline(always)]
|
||||
fn population_count(&self) -> uint { (*self as i64).population_count() as uint }
|
||||
|
||||
/// Counts the number of leading zeros. Wraps LLVM's `ctlz` intrinsic.
|
||||
#[inline(always)]
|
||||
fn leading_zeros(&self) -> uint { (*self as i64).leading_zeros() as uint }
|
||||
|
||||
/// Counts the number of trailing zeros. Wraps LLVM's `cttz` intrinsic.
|
||||
#[inline(always)]
|
||||
fn trailing_zeros(&self) -> uint { (*self as i64).trailing_zeros() as uint }
|
||||
}
|
||||
|
||||
///
|
||||
/// Divide two numbers, return the result, rounded up.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * x - an integer
|
||||
/// * y - an integer distinct from 0u
|
||||
///
|
||||
/// # Return value
|
||||
///
|
||||
/// The smallest integer `q` such that `x/y <= q`.
|
||||
///
|
||||
pub fn div_ceil(x: uint, y: uint) -> uint {
|
||||
let div = x / y;
|
||||
if x % y == 0u { div }
|
||||
else { div + 1u }
|
||||
}
|
||||
|
||||
/**
|
||||
* Divide two numbers, return the result, rounded to the closest integer.
|
||||
*
|
||||
* # Arguments
|
||||
*
|
||||
* * x - an integer
|
||||
* * y - an integer distinct from 0u
|
||||
*
|
||||
* # Return value
|
||||
*
|
||||
* The integer `q` closest to `x/y`.
|
||||
*/
|
||||
///
|
||||
/// Divide two numbers, return the result, rounded to the closest integer.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * x - an integer
|
||||
/// * y - an integer distinct from 0u
|
||||
///
|
||||
/// # Return value
|
||||
///
|
||||
/// The integer `q` closest to `x/y`.
|
||||
///
|
||||
pub fn div_round(x: uint, y: uint) -> uint {
|
||||
let div = x / y;
|
||||
if x % y * 2u < y { div }
|
||||
else { div + 1u }
|
||||
}
|
||||
|
||||
/**
|
||||
* Divide two numbers, return the result, rounded down.
|
||||
*
|
||||
* Note: This is the same function as `div`.
|
||||
*
|
||||
* # Arguments
|
||||
*
|
||||
* * x - an integer
|
||||
* * y - an integer distinct from 0u
|
||||
*
|
||||
* # Return value
|
||||
*
|
||||
* The smallest integer `q` such that `x/y <= q`. This
|
||||
* is either `x/y` or `x/y + 1`.
|
||||
*/
|
||||
///
|
||||
/// Divide two numbers, return the result, rounded down.
|
||||
///
|
||||
/// Note: This is the same function as `div`.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * x - an integer
|
||||
/// * y - an integer distinct from 0u
|
||||
///
|
||||
/// # Return value
|
||||
///
|
||||
/// The smallest integer `q` such that `x/y <= q`. This
|
||||
/// is either `x/y` or `x/y + 1`.
|
||||
///
|
||||
pub fn div_floor(x: uint, y: uint) -> uint { return x / y; }
|
||||
|
||||
/**
|
||||
* Iterate over the range [`lo`..`hi`), or stop when requested
|
||||
*
|
||||
* # Arguments
|
||||
*
|
||||
* * lo - The integer at which to start the loop (included)
|
||||
* * hi - The integer at which to stop the loop (excluded)
|
||||
* * it - A block to execute with each consecutive integer of the range.
|
||||
* Return `true` to continue, `false` to stop.
|
||||
*
|
||||
* # Return value
|
||||
*
|
||||
* `true` If execution proceeded correctly, `false` if it was interrupted,
|
||||
* that is if `it` returned `false` at any point.
|
||||
*/
|
||||
///
|
||||
/// Iterate over the range [`lo`..`hi`), or stop when requested
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * lo - The integer at which to start the loop (included)
|
||||
/// * hi - The integer at which to stop the loop (excluded)
|
||||
/// * it - A block to execute with each consecutive integer of the range.
|
||||
/// Return `true` to continue, `false` to stop.
|
||||
///
|
||||
/// # Return value
|
||||
///
|
||||
/// `true` If execution proceeded correctly, `false` if it was interrupted,
|
||||
/// that is if `it` returned `false` at any point.
|
||||
///
|
||||
pub fn iterate(lo: uint, hi: uint, it: &fn(uint) -> bool) -> bool {
|
||||
let mut i = lo;
|
||||
while i < hi {
|
||||
@ -110,16 +156,16 @@ pub mod inst {
|
||||
|
||||
impl iter::Times for uint {
|
||||
#[inline(always)]
|
||||
/**
|
||||
* A convenience form for basic iteration. Given a uint `x`,
|
||||
* `for x.times { ... }` executes the given block x times.
|
||||
*
|
||||
* Equivalent to `for uint::range(0, x) |_| { ... }`.
|
||||
*
|
||||
* Not defined on all integer types to permit unambiguous
|
||||
* use with integer literals of inferred integer-type as
|
||||
* the self-value (eg. `for 100.times { ... }`).
|
||||
*/
|
||||
///
|
||||
/// A convenience form for basic iteration. Given a uint `x`,
|
||||
/// `for x.times { ... }` executes the given block x times.
|
||||
///
|
||||
/// Equivalent to `for uint::range(0, x) |_| { ... }`.
|
||||
///
|
||||
/// Not defined on all integer types to permit unambiguous
|
||||
/// use with integer literals of inferred integer-type as
|
||||
/// the self-value (eg. `for 100.times { ... }`).
|
||||
///
|
||||
fn times(&self, it: &fn() -> bool) {
|
||||
let mut i = *self;
|
||||
while i > 0 {
|
||||
|
@ -38,8 +38,10 @@ pub use iter::{BaseIter, ReverseIter, MutableIter, ExtendedIter, EqIter};
|
||||
pub use iter::{CopyableIter, CopyableOrderedIter, CopyableNonstrictIter};
|
||||
pub use iter::{Times, ExtendedMutableIter};
|
||||
pub use num::{Num, NumCast};
|
||||
pub use num::{Signed, Unsigned, Integer};
|
||||
pub use num::{Orderable, Signed, Unsigned, Integer};
|
||||
pub use num::{Round, Fractional, Real, RealExt};
|
||||
pub use num::{Bitwise, BitCount, Bounded};
|
||||
pub use num::{Primitive, Int, Float};
|
||||
pub use path::GenericPath;
|
||||
pub use path::Path;
|
||||
pub use path::PosixPath;
|
||||
|
@ -148,10 +148,12 @@ impl Shr<uint, BigUint> for BigUint {
|
||||
|
||||
impl Zero for BigUint {
|
||||
fn zero() -> BigUint { BigUint::new(~[]) }
|
||||
|
||||
fn is_zero(&self) -> bool { self.data.is_empty() }
|
||||
}
|
||||
|
||||
impl One for BigUint {
|
||||
pub fn one() -> BigUint { BigUint::new(~[1]) }
|
||||
fn one() -> BigUint { BigUint::new(~[1]) }
|
||||
}
|
||||
|
||||
impl Unsigned for BigUint {}
|
||||
@ -310,7 +312,7 @@ impl ToStrRadix for BigUint {
|
||||
result += [m0.to_uint() as BigDigit];
|
||||
m = d;
|
||||
}
|
||||
if m.is_not_zero() {
|
||||
if !m.is_zero() {
|
||||
result += [m.to_uint() as BigDigit];
|
||||
}
|
||||
return result;
|
||||
@ -470,10 +472,6 @@ pub impl BigUint {
|
||||
self.div_mod(other)
|
||||
}
|
||||
|
||||
fn is_zero(&self) -> bool { self.data.is_empty() }
|
||||
|
||||
fn is_not_zero(&self) -> bool { !self.data.is_empty() }
|
||||
|
||||
fn to_uint(&self) -> uint {
|
||||
match self.data.len() {
|
||||
0 => 0,
|
||||
@ -684,6 +682,8 @@ impl Zero for BigInt {
|
||||
pub fn zero() -> BigInt {
|
||||
BigInt::from_biguint(Zero, Zero::zero())
|
||||
}
|
||||
|
||||
fn is_zero(&self) -> bool { self.sign == Zero }
|
||||
}
|
||||
|
||||
impl One for BigInt {
|
||||
@ -909,8 +909,6 @@ pub impl BigInt {
|
||||
|
||||
fn is_zero(&self) -> bool { self.sign == Zero }
|
||||
|
||||
fn is_not_zero(&self) -> bool { self.sign != Zero }
|
||||
|
||||
fn to_uint(&self) -> uint {
|
||||
match self.sign {
|
||||
Plus => self.data.to_uint(),
|
||||
@ -1212,10 +1210,10 @@ mod biguint_tests {
|
||||
let b = BigUint::from_slice(bVec);
|
||||
let c = BigUint::from_slice(cVec);
|
||||
|
||||
if a.is_not_zero() {
|
||||
if !a.is_zero() {
|
||||
assert!(c.quot_rem(&a) == (b, Zero::zero()));
|
||||
}
|
||||
if b.is_not_zero() {
|
||||
if !b.is_zero() {
|
||||
assert!(c.quot_rem(&b) == (a, Zero::zero()));
|
||||
}
|
||||
}
|
||||
@ -1227,7 +1225,7 @@ mod biguint_tests {
|
||||
let c = BigUint::from_slice(cVec);
|
||||
let d = BigUint::from_slice(dVec);
|
||||
|
||||
if b.is_not_zero() { assert!(a.quot_rem(&b) == (c, d)); }
|
||||
if !b.is_zero() { assert!(a.quot_rem(&b) == (c, d)); }
|
||||
}
|
||||
}
|
||||
|
||||
@ -1577,7 +1575,7 @@ mod bigint_tests {
|
||||
fn test_div_mod() {
|
||||
fn check_sub(a: &BigInt, b: &BigInt, ans_d: &BigInt, ans_m: &BigInt) {
|
||||
let (d, m) = a.div_mod(b);
|
||||
if m.is_not_zero() {
|
||||
if !m.is_zero() {
|
||||
assert!(m.sign == b.sign);
|
||||
}
|
||||
assert!(m.abs() <= b.abs());
|
||||
@ -1606,8 +1604,8 @@ mod bigint_tests {
|
||||
let b = BigInt::from_slice(Plus, bVec);
|
||||
let c = BigInt::from_slice(Plus, cVec);
|
||||
|
||||
if a.is_not_zero() { check(&c, &a, &b, &Zero::zero()); }
|
||||
if b.is_not_zero() { check(&c, &b, &a, &Zero::zero()); }
|
||||
if !a.is_zero() { check(&c, &a, &b, &Zero::zero()); }
|
||||
if !b.is_zero() { check(&c, &b, &a, &Zero::zero()); }
|
||||
}
|
||||
|
||||
for quot_rem_quadruples.each |elm| {
|
||||
@ -1617,7 +1615,7 @@ mod bigint_tests {
|
||||
let c = BigInt::from_slice(Plus, cVec);
|
||||
let d = BigInt::from_slice(Plus, dVec);
|
||||
|
||||
if b.is_not_zero() {
|
||||
if !b.is_zero() {
|
||||
check(&a, &b, &c, &d);
|
||||
}
|
||||
}
|
||||
@ -1628,7 +1626,7 @@ mod bigint_tests {
|
||||
fn test_quot_rem() {
|
||||
fn check_sub(a: &BigInt, b: &BigInt, ans_q: &BigInt, ans_r: &BigInt) {
|
||||
let (q, r) = a.quot_rem(b);
|
||||
if r.is_not_zero() {
|
||||
if !r.is_zero() {
|
||||
assert!(r.sign == a.sign);
|
||||
}
|
||||
assert!(r.abs() <= b.abs());
|
||||
@ -1649,8 +1647,8 @@ mod bigint_tests {
|
||||
let b = BigInt::from_slice(Plus, bVec);
|
||||
let c = BigInt::from_slice(Plus, cVec);
|
||||
|
||||
if a.is_not_zero() { check(&c, &a, &b, &Zero::zero()); }
|
||||
if b.is_not_zero() { check(&c, &b, &a, &Zero::zero()); }
|
||||
if !a.is_zero() { check(&c, &a, &b, &Zero::zero()); }
|
||||
if !b.is_zero() { check(&c, &b, &a, &Zero::zero()); }
|
||||
}
|
||||
|
||||
for quot_rem_quadruples.each |elm| {
|
||||
@ -1660,7 +1658,7 @@ mod bigint_tests {
|
||||
let c = BigInt::from_slice(Plus, cVec);
|
||||
let d = BigInt::from_slice(Plus, dVec);
|
||||
|
||||
if b.is_not_zero() {
|
||||
if !b.is_zero() {
|
||||
check(&a, &b, &c, &d);
|
||||
}
|
||||
}
|
||||
|
@ -125,6 +125,11 @@ impl<T: Copy + Num> Zero for Cmplx<T> {
|
||||
fn zero() -> Cmplx<T> {
|
||||
Cmplx::new(Zero::zero(), Zero::zero())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn is_zero(&self) -> bool {
|
||||
*self == Zero::zero()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Copy + Num> One for Cmplx<T> {
|
||||
|
@ -191,6 +191,11 @@ impl<T: Copy + Num + Ord>
|
||||
fn zero() -> Ratio<T> {
|
||||
Ratio::new_raw(Zero::zero(), One::one())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn is_zero(&self) -> bool {
|
||||
*self == Zero::zero()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Copy + Num + Ord>
|
||||
|
@ -10,82 +10,86 @@
|
||||
|
||||
extern mod std;
|
||||
|
||||
use core::num::Float::{
|
||||
NaN, infinity, neg_infinity
|
||||
};
|
||||
|
||||
pub fn main() {
|
||||
let nan = float::NaN;
|
||||
assert!((float::is_NaN(nan)));
|
||||
let nan = NaN::<float>();
|
||||
assert!((nan).is_NaN());
|
||||
|
||||
let inf = float::infinity;
|
||||
assert!((-inf == float::neg_infinity));
|
||||
let inf = infinity::<float>();
|
||||
assert!(-inf == neg_infinity::<float>());
|
||||
|
||||
assert!(( nan != nan));
|
||||
assert!(( nan != -nan));
|
||||
assert!((-nan != -nan));
|
||||
assert!((-nan != nan));
|
||||
assert!( nan != nan);
|
||||
assert!( nan != -nan);
|
||||
assert!(-nan != -nan);
|
||||
assert!(-nan != nan);
|
||||
|
||||
assert!(( nan != 1.));
|
||||
assert!(( nan != 0.));
|
||||
assert!(( nan != inf));
|
||||
assert!(( nan != -inf));
|
||||
assert!( nan != 1.);
|
||||
assert!( nan != 0.);
|
||||
assert!( nan != inf);
|
||||
assert!( nan != -inf);
|
||||
|
||||
assert!(( 1. != nan));
|
||||
assert!(( 0. != nan));
|
||||
assert!(( inf != nan));
|
||||
assert!((-inf != nan));
|
||||
assert!( 1. != nan);
|
||||
assert!( 0. != nan);
|
||||
assert!( inf != nan);
|
||||
assert!(-inf != nan);
|
||||
|
||||
assert!((!( nan == nan)));
|
||||
assert!((!( nan == -nan)));
|
||||
assert!((!( nan == 1.)));
|
||||
assert!((!( nan == 0.)));
|
||||
assert!((!( nan == inf)));
|
||||
assert!((!( nan == -inf)));
|
||||
assert!((!( 1. == nan)));
|
||||
assert!((!( 0. == nan)));
|
||||
assert!((!( inf == nan)));
|
||||
assert!((!(-inf == nan)));
|
||||
assert!((!(-nan == nan)));
|
||||
assert!((!(-nan == -nan)));
|
||||
assert!(!( nan == nan));
|
||||
assert!(!( nan == -nan));
|
||||
assert!(!( nan == 1.));
|
||||
assert!(!( nan == 0.));
|
||||
assert!(!( nan == inf));
|
||||
assert!(!( nan == -inf));
|
||||
assert!(!( 1. == nan));
|
||||
assert!(!( 0. == nan));
|
||||
assert!(!( inf == nan));
|
||||
assert!(!(-inf == nan));
|
||||
assert!(!(-nan == nan));
|
||||
assert!(!(-nan == -nan));
|
||||
|
||||
assert!((!( nan > nan)));
|
||||
assert!((!( nan > -nan)));
|
||||
assert!((!( nan > 0.)));
|
||||
assert!((!( nan > inf)));
|
||||
assert!((!( nan > -inf)));
|
||||
assert!((!( 0. > nan)));
|
||||
assert!((!( inf > nan)));
|
||||
assert!((!(-inf > nan)));
|
||||
assert!((!(-nan > nan)));
|
||||
assert!(!( nan > nan));
|
||||
assert!(!( nan > -nan));
|
||||
assert!(!( nan > 0.));
|
||||
assert!(!( nan > inf));
|
||||
assert!(!( nan > -inf));
|
||||
assert!(!( 0. > nan));
|
||||
assert!(!( inf > nan));
|
||||
assert!(!(-inf > nan));
|
||||
assert!(!(-nan > nan));
|
||||
|
||||
assert!((!(nan < 0.)));
|
||||
assert!((!(nan < 1.)));
|
||||
assert!((!(nan < -1.)));
|
||||
assert!((!(nan < inf)));
|
||||
assert!((!(nan < -inf)));
|
||||
assert!((!(nan < nan)));
|
||||
assert!((!(nan < -nan)));
|
||||
assert!(!(nan < 0.));
|
||||
assert!(!(nan < 1.));
|
||||
assert!(!(nan < -1.));
|
||||
assert!(!(nan < inf));
|
||||
assert!(!(nan < -inf));
|
||||
assert!(!(nan < nan));
|
||||
assert!(!(nan < -nan));
|
||||
|
||||
assert!((!( 0. < nan)));
|
||||
assert!((!( 1. < nan)));
|
||||
assert!((!( -1. < nan)));
|
||||
assert!((!( inf < nan)));
|
||||
assert!((!(-inf < nan)));
|
||||
assert!((!(-nan < nan)));
|
||||
assert!(!( 0. < nan));
|
||||
assert!(!( 1. < nan));
|
||||
assert!(!( -1. < nan));
|
||||
assert!(!( inf < nan));
|
||||
assert!(!(-inf < nan));
|
||||
assert!(!(-nan < nan));
|
||||
|
||||
assert!((float::is_NaN(nan + inf)));
|
||||
assert!((float::is_NaN(nan + -inf)));
|
||||
assert!((float::is_NaN(nan + 0.)));
|
||||
assert!((float::is_NaN(nan + 1.)));
|
||||
assert!((float::is_NaN(nan * 1.)));
|
||||
assert!((float::is_NaN(nan / 1.)));
|
||||
assert!((float::is_NaN(nan / 0.)));
|
||||
assert!((float::is_NaN(0. / 0.)));
|
||||
assert!((float::is_NaN(-inf + inf)));
|
||||
assert!((float::is_NaN(inf - inf)));
|
||||
assert!((nan + inf).is_NaN());
|
||||
assert!((nan + -inf).is_NaN());
|
||||
assert!((nan + 0.).is_NaN());
|
||||
assert!((nan + 1.).is_NaN());
|
||||
assert!((nan * 1.).is_NaN());
|
||||
assert!((nan / 1.).is_NaN());
|
||||
assert!((nan / 0.).is_NaN());
|
||||
assert!((0f/0f).is_NaN());
|
||||
assert!((-inf + inf).is_NaN());
|
||||
assert!((inf - inf).is_NaN());
|
||||
|
||||
assert!((!float::is_NaN(-1.)));
|
||||
assert!((!float::is_NaN(0.)));
|
||||
assert!((!float::is_NaN(0.1)));
|
||||
assert!((!float::is_NaN(1.)));
|
||||
assert!((!float::is_NaN(inf)));
|
||||
assert!((!float::is_NaN(-inf)));
|
||||
assert!((!float::is_NaN(1./-inf)));
|
||||
assert!(!(-1f).is_NaN());
|
||||
assert!(!(0f).is_NaN());
|
||||
assert!(!(0.1f).is_NaN());
|
||||
assert!(!(1f).is_NaN());
|
||||
assert!(!(inf).is_NaN());
|
||||
assert!(!(-inf).is_NaN());
|
||||
assert!(!(1./-inf).is_NaN());
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user