From ad0b337036f2f9076852d5d6701ec302e3cce101 Mon Sep 17 00:00:00 2001 From: Brendan Zabarauskas Date: Thu, 25 Apr 2013 15:30:56 +1000 Subject: [PATCH 01/15] Add is_zero method to Zero --- src/libcore/num/f32.rs | 16 +++++++------- src/libcore/num/f64.rs | 16 +++++++------- src/libcore/num/float.rs | 20 ++++++++++-------- src/libcore/num/int-template.rs | 9 +++++--- src/libcore/num/num.rs | 7 +++---- src/libcore/num/uint-template.rs | 9 +++++--- src/libstd/num/bigint.rs | 36 +++++++++++++++----------------- src/libstd/num/complex.rs | 5 +++++ src/libstd/num/rational.rs | 5 +++++ 9 files changed, 67 insertions(+), 56 deletions(-) diff --git a/src/libcore/num/f32.rs b/src/libcore/num/f32.rs index 7d5807ba5462c..c03761c2322ed 100644 --- a/src/libcore/num/f32.rs +++ b/src/libcore/num/f32.rs @@ -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::*; @@ -154,12 +154,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 { @@ -245,12 +239,16 @@ impl Ord for f32 { fn gt(&self, other: &f32) -> bool { (*self) > (*other) } } -impl num::Zero 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 num::One for f32 { +impl One for f32 { #[inline(always)] fn one() -> f32 { 1.0 } } diff --git a/src/libcore/num/f64.rs b/src/libcore/num/f64.rs index 3b6198bfc472e..ca6416be7396c 100644 --- a/src/libcore/num/f64.rs +++ b/src/libcore/num/f64.rs @@ -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::*; @@ -174,12 +174,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 { @@ -266,12 +260,16 @@ impl Ord for f64 { fn gt(&self, other: &f64) -> bool { (*self) > (*other) } } -impl num::Zero 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 num::One for f64 { +impl One for f64 { #[inline(always)] fn one() -> f64 { 1.0 } } diff --git a/src/libcore/num/float.rs b/src/libcore/num/float.rs index 9c0412b422f52..248bc2a4d563c 100644 --- a/src/libcore/num/float.rs +++ b/src/libcore/num/float.rs @@ -22,7 +22,7 @@ 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}; @@ -337,8 +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)] @@ -393,12 +391,16 @@ impl Ord for float { fn gt(&self, other: &float) -> bool { (*self) > (*other) } } -impl num::Zero 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 num::One for float { +impl One for float { #[inline(always)] fn one() -> float { 1.0 } } @@ -867,11 +869,11 @@ mod tests { } // 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!() } @@ -914,11 +916,11 @@ mod tests { } // 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.)); diff --git a/src/libcore/num/int-template.rs b/src/libcore/num/int-template.rs index f9edf1cefc873..b53bf876f777f 100644 --- a/src/libcore/num/int-template.rs +++ b/src/libcore/num/int-template.rs @@ -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}; @@ -152,12 +152,15 @@ impl Eq for T { fn ne(&self, other: &T) -> bool { return (*self) != (*other); } } -impl num::Zero for T { +impl Zero for T { #[inline(always)] fn zero() -> T { 0 } + + #[inline(always)] + fn is_zero(&self) -> bool { *self == 0 } } -impl num::One for T { +impl One for T { #[inline(always)] fn one() -> T { 1 } } diff --git a/src/libcore/num/num.rs b/src/libcore/num/num.rs index e19afdc69c32f..19d5340527df6 100644 --- a/src/libcore/num/num.rs +++ b/src/libcore/num/num.rs @@ -37,13 +37,12 @@ pub trait IntConvertible { } 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 diff --git a/src/libcore/num/uint-template.rs b/src/libcore/num/uint-template.rs index 96019ddd564d6..803d034c91921 100644 --- a/src/libcore/num/uint-template.rs +++ b/src/libcore/num/uint-template.rs @@ -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}; @@ -118,12 +118,15 @@ impl Eq for T { fn ne(&self, other: &T) -> bool { return (*self) != (*other); } } -impl num::Zero for T { +impl Zero for T { #[inline(always)] fn zero() -> T { 0 } + + #[inline(always)] + fn is_zero(&self) -> bool { *self == 0 } } -impl num::One for T { +impl One for T { #[inline(always)] fn one() -> T { 1 } } diff --git a/src/libstd/num/bigint.rs b/src/libstd/num/bigint.rs index 5f0fd76640a30..214bb0be0ed28 100644 --- a/src/libstd/num/bigint.rs +++ b/src/libstd/num/bigint.rs @@ -148,10 +148,12 @@ impl Shr 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); } } diff --git a/src/libstd/num/complex.rs b/src/libstd/num/complex.rs index ef7fa397d7f1b..fc17cbc678ea7 100644 --- a/src/libstd/num/complex.rs +++ b/src/libstd/num/complex.rs @@ -125,6 +125,11 @@ impl Zero for Cmplx { fn zero() -> Cmplx { Cmplx::new(Zero::zero(), Zero::zero()) } + + #[inline] + fn is_zero(&self) -> bool { + *self == Zero::zero() + } } impl One for Cmplx { diff --git a/src/libstd/num/rational.rs b/src/libstd/num/rational.rs index 8af1d99fa4719..93b63593a5eb0 100644 --- a/src/libstd/num/rational.rs +++ b/src/libstd/num/rational.rs @@ -191,6 +191,11 @@ impl fn zero() -> Ratio { Ratio::new_raw(Zero::zero(), One::one()) } + + #[inline] + fn is_zero(&self) -> bool { + *self == Zero::zero() + } } impl From dbc2e99693eb20da9b9823bc11953835b156802f Mon Sep 17 00:00:00 2001 From: Brendan Zabarauskas Date: Fri, 26 Apr 2013 09:55:49 +1000 Subject: [PATCH 02/15] Use `///` doc-comment form instead of `/** */` --- src/libcore/num/f32.rs | 276 +++++++++++------------ src/libcore/num/f64.rs | 276 +++++++++++------------ src/libcore/num/float.rs | 310 +++++++++++++------------- src/libcore/num/int-template.rs | 272 +++++++++++----------- src/libcore/num/num.rs | 56 ++--- src/libcore/num/uint-template.rs | 7 +- src/libcore/num/uint-template/uint.rs | 128 +++++------ 7 files changed, 662 insertions(+), 663 deletions(-) diff --git a/src/libcore/num/f32.rs b/src/libcore/num/f32.rs index c03761c2322ed..63e52fab7c96e 100644 --- a/src/libcore/num/f32.rs +++ b/src/libcore/num/f32.rs @@ -304,13 +304,13 @@ 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) } @@ -509,17 +509,17 @@ impl Real for f32 { fn tanh(&self) -> f32 { tanh(*self) } } -/** - * 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: f32) -> ~str { let (r, _) = strconv::to_str_common( @@ -527,13 +527,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( @@ -541,20 +541,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( @@ -564,30 +564,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( @@ -595,15 +595,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( @@ -623,91 +623,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 { 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 { 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 { strconv::from_str_common(num, rdx, true, true, false, diff --git a/src/libcore/num/f64.rs b/src/libcore/num/f64.rs index ca6416be7396c..e6013eec2435e 100644 --- a/src/libcore/num/f64.rs +++ b/src/libcore/num/f64.rs @@ -314,13 +314,13 @@ 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) } @@ -549,17 +549,17 @@ impl RealExt for f64 { fn yn(&self, n: int) -> f64 { yn(n as c_int, *self) } } -/** - * 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: f64) -> ~str { let (r, _) = strconv::to_str_common( @@ -567,13 +567,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( @@ -581,20 +581,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( @@ -604,30 +604,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( @@ -635,15 +635,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( @@ -663,91 +663,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 { 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 { 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 { strconv::from_str_common(num, rdx, true, true, false, diff --git a/src/libcore/num/float.rs b/src/libcore/num/float.rs index 248bc2a4d563c..d5f22e6b056c2 100644 --- a/src/libcore/num/float.rs +++ b/src/libcore/num/float.rs @@ -84,17 +84,17 @@ pub mod consts { pub static ln_10: float = 2.30258509299404568401799145468436421; } -/* - * Section: String Conversions - */ - -/** - * Converts a float to a string - * - * # Arguments - * - * * num - The float value - */ +// +// Section: String Conversions +// + +/// +/// 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 { 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 { 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 { strconv::from_str_common(num, radix, true, true, false, @@ -301,22 +301,22 @@ impl num::FromStrRadix for float { } } -/** - * 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` - */ +// +// 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` +/// pub fn pow_with_uint(base: uint, pow: uint) -> float { if base == 0u { if pow == 0u { @@ -668,13 +668,13 @@ 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 } diff --git a/src/libcore/num/int-template.rs b/src/libcore/num/int-template.rs index b53bf876f777f..75d170118e672 100644 --- a/src/libcore/num/int-template.rs +++ b/src/libcore/num/int-template.rs @@ -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) { @@ -190,24 +190,24 @@ impl Div for T { } #[cfg(not(stage0),notest)] impl Quot 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); - - * assert!( 1 / 2 == 0); - * assert!( 1 / -2 == 0); - * assert!(-1 / 2 == 0); - * assert!(-1 / -2 == 0); - * ~~~ - */ + /// + /// 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); + /// ~~~ + /// #[inline(always)] fn quot(&self, other: &T) -> T { *self / *other } } @@ -219,27 +219,27 @@ impl Modulo for T { } #[cfg(not(stage0),notest)] impl Rem 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); - - * assert!( 1 % 2 == 1); - * assert!( 1 % -2 == 1); - * assert!(-1 % 2 == -1); - * assert!(-1 % -2 == -1); - * ~~~ - */ + /// + /// 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); + /// ~~~ + /// #[inline(always)] fn rem(&self, other: &T) -> T { *self % *other } } @@ -257,13 +257,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 { @@ -283,23 +283,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_, @@ -311,27 +311,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_, @@ -361,11 +361,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 @@ -378,9 +378,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 @@ -545,13 +545,13 @@ 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, diff --git a/src/libcore/num/num.rs b/src/libcore/num/num.rs index 19d5340527df6..5797d86e6ec36 100644 --- a/src/libcore/num/num.rs +++ b/src/libcore/num/num.rs @@ -153,7 +153,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 @@ -171,24 +173,24 @@ 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); - * ~~~ - */ +/// +/// Cast from one machine scalar to another +/// +/// # Example +/// +/// ~~~ +/// let twenty: f32 = num::cast(0x14); +/// assert_eq!(twenty, 20f32); +/// ~~~ +/// #[inline(always)] pub fn cast(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(n: T) -> Self; @@ -260,21 +262,19 @@ pub trait FromStrRadix { pub fn from_str_radix(str: &str, radix: uint) -> Option; } -// 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+Mul>( radix: uint, pow: uint) -> T { let _0: T = Zero::zero(); diff --git a/src/libcore/num/uint-template.rs b/src/libcore/num/uint-template.rs index 803d034c91921..ed0a5aa387684 100644 --- a/src/libcore/num/uint-template.rs +++ b/src/libcore/num/uint-template.rs @@ -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, diff --git a/src/libcore/num/uint-template/uint.rs b/src/libcore/num/uint-template/uint.rs index efcf68aba3160..5eaa27fb7a05d 100644 --- a/src/libcore/num/uint-template/uint.rs +++ b/src/libcore/num/uint-template/uint.rs @@ -31,74 +31,74 @@ 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`. - */ + /// + /// 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 +110,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 { From f40be999cab20ee51758620d9ccf435c62fcb51f Mon Sep 17 00:00:00 2001 From: Brendan Zabarauskas Date: Fri, 26 Apr 2013 09:58:40 +1000 Subject: [PATCH 03/15] Minor style improvements for test functions Use argument pattern-matching for test_division_rule and remove visibility specifier for test_signed --- src/libcore/num/float.rs | 2 +- src/libcore/num/int-template.rs | 5 +---- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/src/libcore/num/float.rs b/src/libcore/num/float.rs index d5f22e6b056c2..92decce325a20 100644 --- a/src/libcore/num/float.rs +++ b/src/libcore/num/float.rs @@ -798,7 +798,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); diff --git a/src/libcore/num/int-template.rs b/src/libcore/num/int-template.rs index 75d170118e672..56b7616c25546 100644 --- a/src/libcore/num/int-template.rs +++ b/src/libcore/num/int-template.rs @@ -553,10 +553,7 @@ mod tests { /// - `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); } From b62421000c8e0e9b08590b81af03e05c6edd3c10 Mon Sep 17 00:00:00 2001 From: Brendan Zabarauskas Date: Fri, 26 Apr 2013 10:02:00 +1000 Subject: [PATCH 04/15] Add Bitwise, Bounded, Primitive, and PrimitiveInt traits --- src/libcore/core.rc | 2 + src/libcore/num/f32.rs | 14 +++++++ src/libcore/num/f64.rs | 14 +++++++ src/libcore/num/float.rs | 14 +++++++ src/libcore/num/int-template.rs | 18 +++++++++ src/libcore/num/int-template/i16.rs | 10 +++++ src/libcore/num/int-template/i32.rs | 10 +++++ src/libcore/num/int-template/i64.rs | 10 +++++ src/libcore/num/int-template/i8.rs | 10 +++++ src/libcore/num/int-template/int.rs | 21 ++++++++++ src/libcore/num/num.rs | 55 +++++++++++++++++++++++++++ src/libcore/num/uint-template.rs | 18 +++++++++ src/libcore/num/uint-template/u16.rs | 10 +++++ src/libcore/num/uint-template/u32.rs | 10 +++++ src/libcore/num/uint-template/u64.rs | 10 +++++ src/libcore/num/uint-template/u8.rs | 10 +++++ src/libcore/num/uint-template/uint.rs | 20 ++++++++++ src/libcore/prelude.rs | 2 + 18 files changed, 258 insertions(+) diff --git a/src/libcore/core.rc b/src/libcore/core.rc index 71bbaf557ce38..8b9ba22f33018 100644 --- a/src/libcore/core.rc +++ b/src/libcore/core.rc @@ -106,6 +106,8 @@ pub use iter::{ExtendedMutableIter}; pub use num::{Num, NumCast}; pub use num::{Signed, Unsigned, Integer}; pub use num::{Round, Fractional, Real, RealExt}; +pub use num::{Bitwise, Bounded}; +pub use num::{Primitive, PrimitiveInt}; pub use ptr::Ptr; pub use to_str::ToStr; pub use clone::Clone; diff --git a/src/libcore/num/f32.rs b/src/libcore/num/f32.rs index 63e52fab7c96e..d1369b929f66f 100644 --- a/src/libcore/num/f32.rs +++ b/src/libcore/num/f32.rs @@ -509,6 +509,14 @@ impl Real for f32 { fn tanh(&self) -> f32 { tanh(*self) } } +impl Primitive for f32 { + #[inline(always)] + fn bits() -> uint { 32 } + + #[inline(always)] + fn bytes() -> uint { Primitive::bits::() / 8 } +} + // // Section: String Conversions // @@ -873,6 +881,12 @@ mod tests { assert!((1f32/neg_infinity).is_negative()); assert!(!NaN.is_negative()); } + + #[test] + fn test_primitive() { + assert_eq!(Primitive::bits::(), sys::size_of::() * 8); + assert_eq!(Primitive::bytes::(), sys::size_of::()); + } } // diff --git a/src/libcore/num/f64.rs b/src/libcore/num/f64.rs index e6013eec2435e..4e0030b542148 100644 --- a/src/libcore/num/f64.rs +++ b/src/libcore/num/f64.rs @@ -549,6 +549,14 @@ impl RealExt for f64 { fn yn(&self, n: int) -> f64 { yn(n as c_int, *self) } } +impl Primitive for f64 { + #[inline(always)] + fn bits() -> uint { 64 } + + #[inline(always)] + fn bytes() -> uint { Primitive::bits::() / 8 } +} + // // Section: String Conversions // @@ -914,6 +922,12 @@ mod tests { assert!((1f64/neg_infinity).is_negative()); assert!(!NaN.is_negative()); } + + #[test] + fn test_primitive() { + assert_eq!(Primitive::bits::(), sys::size_of::() * 8); + assert_eq!(Primitive::bytes::(), sys::size_of::()); + } } // diff --git a/src/libcore/num/float.rs b/src/libcore/num/float.rs index 92decce325a20..a409639f9e640 100644 --- a/src/libcore/num/float.rs +++ b/src/libcore/num/float.rs @@ -689,6 +689,14 @@ impl Signed for float { fn is_negative(&self) -> bool { *self < 0.0 || (1.0 / *self) == neg_infinity } } +impl Primitive for float { + #[inline(always)] + fn bits() -> uint { Primitive::bits::() } + + #[inline(always)] + fn bytes() -> uint { Primitive::bytes::() } +} + #[cfg(test)] mod tests { use super::*; @@ -836,6 +844,12 @@ mod tests { assert!(!NaN.is_negative()); } + #[test] + fn test_primitive() { + assert_eq!(Primitive::bits::(), sys::size_of::() * 8); + assert_eq!(Primitive::bytes::(), sys::size_of::()); + } + #[test] pub fn test_to_str_exact_do_decimal() { let s = to_str_exact(5.0, 4u); diff --git a/src/libcore/num/int-template.rs b/src/libcore/num/int-template.rs index 56b7616c25546..32ae19bec4196 100644 --- a/src/libcore/num/int-template.rs +++ b/src/libcore/num/int-template.rs @@ -399,6 +399,8 @@ impl Integer for T { fn is_odd(&self) -> bool { !self.is_even() } } +impl Bitwise for T {} + #[cfg(notest)] impl BitOr for T { #[inline(always)] @@ -435,6 +437,16 @@ impl Not 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 PrimitiveInt for T {} + // String conversion functions and impl str -> num /// Parse a string as a number in base 10. @@ -641,6 +653,12 @@ mod tests { assert_eq!(-(0b11 as T) - (1 as T), (0b11 as T).not()); } + #[test] + fn test_primitive() { + assert_eq!(Primitive::bits::(), sys::size_of::() * 8); + assert_eq!(Primitive::bytes::(), sys::size_of::()); + } + #[test] fn test_from_str() { assert_eq!(from_str(~"0"), Some(0 as T)); diff --git a/src/libcore/num/int-template/i16.rs b/src/libcore/num/int-template/i16.rs index 34dcd50839785..d67017ec62dd2 100644 --- a/src/libcore/num/int-template/i16.rs +++ b/src/libcore/num/int-template/i16.rs @@ -11,6 +11,16 @@ //! Operations and constants for `i16` mod inst { + use num::Primitive; + 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::() / 8 } + } } diff --git a/src/libcore/num/int-template/i32.rs b/src/libcore/num/int-template/i32.rs index 91eea0e8d4709..fe2014bd3e01e 100644 --- a/src/libcore/num/int-template/i32.rs +++ b/src/libcore/num/int-template/i32.rs @@ -11,6 +11,16 @@ //! Operations and constants for `i32` mod inst { + use num::Primitive; + 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::() / 8 } + } } diff --git a/src/libcore/num/int-template/i64.rs b/src/libcore/num/int-template/i64.rs index 3834a1e2a0387..0b39b421dab1c 100644 --- a/src/libcore/num/int-template/i64.rs +++ b/src/libcore/num/int-template/i64.rs @@ -11,6 +11,16 @@ //! Operations and constants for `i64` mod inst { + use num::Primitive; + 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::() / 8 } + } } diff --git a/src/libcore/num/int-template/i8.rs b/src/libcore/num/int-template/i8.rs index 9486ed748d7d0..0babd3779f15c 100644 --- a/src/libcore/num/int-template/i8.rs +++ b/src/libcore/num/int-template/i8.rs @@ -11,6 +11,16 @@ //! Operations and constants for `i8` mod inst { + use num::Primitive; + 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::() / 8 } + } } diff --git a/src/libcore/num/int-template/int.rs b/src/libcore/num/int-template/int.rs index 6649b364015d3..3c179c554a8a2 100644 --- a/src/libcore/num/int-template/int.rs +++ b/src/libcore/num/int-template/int.rs @@ -13,9 +13,30 @@ pub use self::inst::pow; mod inst { + use num::Primitive; + 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 } + + // fallback if we don't have access to the current word size + #[cfg(not(target_word_size = "32"), + not(target_word_size = "64"))] + #[inline(always)] + fn bits() -> uint { sys::size_of::() * 8 } + + #[inline(always)] + fn bytes() -> uint { Primitive::bits::() / 8 } + } + /// Returns `base` raised to the power of `exponent` pub fn pow(base: int, exponent: uint) -> int { if exponent == 0u { diff --git a/src/libcore/num/num.rs b/src/libcore/num/num.rs index 5797d86e6ec36..5b524a42c2585 100644 --- a/src/libcore/num/num.rs +++ b/src/libcore/num/num.rs @@ -18,6 +18,7 @@ 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; @@ -173,6 +174,60 @@ pub trait RealExt: Real { fn yn(&self, n: int) -> Self; } +/// +/// Collects the bitwise operators under one trait. +/// +pub trait Bitwise: Not + + BitAnd + + BitOr + + BitXor + + Shl + + Shr {} + +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 + + Neg + + Add + + Sub + + Mul + + Quot + + Rem { + // 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 PrimitiveInt: Integer + + Primitive + + Bounded + + Bitwise {} + +/// +/// Specialisation of `PrimitiveInt` for unsigned integers +/// +pub trait Uint: PrimitiveInt + + Unsigned {} + +/// +/// Specialisation of `PrimitiveInt` for signed integers +/// +pub trait Int: PrimitiveInt + + Signed {} + /// /// Cast from one machine scalar to another /// diff --git a/src/libcore/num/uint-template.rs b/src/libcore/num/uint-template.rs index ed0a5aa387684..a89a6faec2829 100644 --- a/src/libcore/num/uint-template.rs +++ b/src/libcore/num/uint-template.rs @@ -231,6 +231,8 @@ impl Integer for T { fn is_odd(&self) -> bool { !self.is_even() } } +impl Bitwise for T {} + #[cfg(notest)] impl BitOr for T { #[inline(always)] @@ -267,6 +269,16 @@ impl Not 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 PrimitiveInt for T {} + // String conversion functions and impl str -> num /// Parse a string as a number in base 10. @@ -384,6 +396,12 @@ mod tests { assert_eq!(max_value - (0b1011 as T), (0b1011 as T).not()); } + #[test] + fn test_primitive() { + assert_eq!(Primitive::bits::(), sys::size_of::() * 8); + assert_eq!(Primitive::bytes::(), sys::size_of::()); + } + #[test] pub fn test_to_str() { assert_eq!(to_str_radix(0 as T, 10u), ~"0"); diff --git a/src/libcore/num/uint-template/u16.rs b/src/libcore/num/uint-template/u16.rs index 63144162fc50a..fda731b7a182d 100644 --- a/src/libcore/num/uint-template/u16.rs +++ b/src/libcore/num/uint-template/u16.rs @@ -11,8 +11,18 @@ //! Operations and constants for `u16` mod inst { + use num::Primitive; + 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::() / 8 } + } } diff --git a/src/libcore/num/uint-template/u32.rs b/src/libcore/num/uint-template/u32.rs index 4d9958fe38aaf..2ebf86a749f22 100644 --- a/src/libcore/num/uint-template/u32.rs +++ b/src/libcore/num/uint-template/u32.rs @@ -11,8 +11,18 @@ //! Operations and constants for `u32` mod inst { + use num::Primitive; + 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::() / 8 } + } } diff --git a/src/libcore/num/uint-template/u64.rs b/src/libcore/num/uint-template/u64.rs index af198dd69424b..d34c6ced36f8e 100644 --- a/src/libcore/num/uint-template/u64.rs +++ b/src/libcore/num/uint-template/u64.rs @@ -11,8 +11,18 @@ //! Operations and constants for `u64` mod inst { + use num::Primitive; + 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::() / 8 } + } } diff --git a/src/libcore/num/uint-template/u8.rs b/src/libcore/num/uint-template/u8.rs index 5c548d7209330..857a3f90caa84 100644 --- a/src/libcore/num/uint-template/u8.rs +++ b/src/libcore/num/uint-template/u8.rs @@ -11,8 +11,18 @@ //! Operations and constants for `u8` mod inst { + use num::Primitive; + 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::() / 8 } + } } diff --git a/src/libcore/num/uint-template/uint.rs b/src/libcore/num/uint-template/uint.rs index 5eaa27fb7a05d..df7d45f620184 100644 --- a/src/libcore/num/uint-template/uint.rs +++ b/src/libcore/num/uint-template/uint.rs @@ -18,6 +18,7 @@ pub use self::inst::{ pub mod inst { use sys; use iter; + use num::Primitive; pub type T = uint; #[allow(non_camel_case_types)] @@ -31,6 +32,25 @@ pub mod inst { #[cfg(target_arch = "x86_64")] pub static bits: uint = 64; + 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 } + + // fallback if we don't have access to the current word size + #[cfg(not(target_word_size = "32"), + not(target_word_size = "64"))] + #[inline(always)] + fn bits() -> uint { sys::size_of::() * 8 } + + #[inline(always)] + fn bytes() -> uint { Primitive::bits::() / 8 } + } + /// /// Divide two numbers, return the result, rounded up. /// diff --git a/src/libcore/prelude.rs b/src/libcore/prelude.rs index 553bb8268102b..2ab1347f578db 100644 --- a/src/libcore/prelude.rs +++ b/src/libcore/prelude.rs @@ -40,6 +40,8 @@ pub use iter::{Times, ExtendedMutableIter}; pub use num::{Num, NumCast}; pub use num::{Signed, Unsigned, Integer}; pub use num::{Round, Fractional, Real, RealExt}; +pub use num::{Bitwise, Bounded}; +pub use num::{Primitive, PrimitiveInt}; pub use path::GenericPath; pub use path::Path; pub use path::PosixPath; From 4c07f5e457102d52042735e277959f7e1a55491e Mon Sep 17 00:00:00 2001 From: Brendan Zabarauskas Date: Fri, 26 Apr 2013 10:22:08 +1000 Subject: [PATCH 05/15] Add Int, Uint and Float traits for primitive numbers --- src/libcore/core.rc | 1 + src/libcore/num/f32.rs | 50 ++++++++++++++++++++------------ src/libcore/num/f64.rs | 50 ++++++++++++++++++++------------ src/libcore/num/float.rs | 46 +++++++++++++++++++++-------- src/libcore/num/int-template.rs | 2 ++ src/libcore/num/num.rs | 18 ++++++++++++ src/libcore/num/uint-template.rs | 2 ++ src/libcore/prelude.rs | 1 + 8 files changed, 122 insertions(+), 48 deletions(-) diff --git a/src/libcore/core.rc b/src/libcore/core.rc index 8b9ba22f33018..55cabad7412c3 100644 --- a/src/libcore/core.rc +++ b/src/libcore/core.rc @@ -108,6 +108,7 @@ pub use num::{Signed, Unsigned, Integer}; pub use num::{Round, Fractional, Real, RealExt}; pub use num::{Bitwise, Bounded}; pub use num::{Primitive, PrimitiveInt}; +pub use num::{Int, Uint, Float}; pub use ptr::Ptr; pub use to_str::ToStr; pub use clone::Clone; diff --git a/src/libcore/num/f32.rs b/src/libcore/num/f32.rs index d1369b929f66f..f6330df9f9ea5 100644 --- a/src/libcore/num/f32.rs +++ b/src/libcore/num/f32.rs @@ -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,18 +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 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 */ @@ -313,7 +298,7 @@ impl Signed for f32 { /// #[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` @@ -517,6 +502,35 @@ impl Primitive for f32 { fn bytes() -> uint { Primitive::bits::() / 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 } + + /// 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()) + } +} + // // Section: String Conversions // @@ -852,7 +866,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); @@ -861,7 +875,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()); diff --git a/src/libcore/num/f64.rs b/src/libcore/num/f64.rs index 4e0030b542148..d40c402b464d9 100644 --- a/src/libcore/num/f64.rs +++ b/src/libcore/num/f64.rs @@ -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,18 +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 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 @@ -323,7 +308,7 @@ impl Signed for f64 { /// #[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` @@ -557,6 +542,35 @@ impl Primitive for f64 { fn bytes() -> uint { Primitive::bits::() / 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()) + } +} + // // Section: String Conversions // @@ -893,7 +907,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); @@ -902,7 +916,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()); diff --git a/src/libcore/num/float.rs b/src/libcore/num/float.rs index a409639f9e640..9852e05c0b829 100644 --- a/src/libcore/num/float.rs +++ b/src/libcore/num/float.rs @@ -337,13 +337,6 @@ pub fn pow_with_uint(base: uint, pow: uint) -> float { return total; } -#[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 @@ -677,7 +670,7 @@ impl Signed for float { /// #[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` @@ -697,6 +690,35 @@ impl Primitive for float { fn bytes() -> uint { Primitive::bytes::() } } +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 } + + /// 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()) + } +} + #[cfg(test)] mod tests { use super::*; @@ -814,7 +836,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); @@ -823,7 +845,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()); @@ -878,7 +900,7 @@ 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 @@ -925,7 +947,7 @@ 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 diff --git a/src/libcore/num/int-template.rs b/src/libcore/num/int-template.rs index 32ae19bec4196..877767b5cbf6a 100644 --- a/src/libcore/num/int-template.rs +++ b/src/libcore/num/int-template.rs @@ -447,6 +447,8 @@ impl Bounded for T { impl PrimitiveInt for T {} +impl Int for T {} + // String conversion functions and impl str -> num /// Parse a string as a number in base 10. diff --git a/src/libcore/num/num.rs b/src/libcore/num/num.rs index 5b524a42c2585..8e6128ceb9763 100644 --- a/src/libcore/num/num.rs +++ b/src/libcore/num/num.rs @@ -228,6 +228,24 @@ pub trait Uint: PrimitiveInt pub trait Int: PrimitiveInt + Signed {} +/// +/// Primitive floating point numbers. This trait should only be implemented +/// for the `f32`, `f64`, and `float` types. +/// +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; +} + /// /// Cast from one machine scalar to another /// diff --git a/src/libcore/num/uint-template.rs b/src/libcore/num/uint-template.rs index a89a6faec2829..67a930c72a467 100644 --- a/src/libcore/num/uint-template.rs +++ b/src/libcore/num/uint-template.rs @@ -279,6 +279,8 @@ impl Bounded for T { impl PrimitiveInt for T {} +impl Uint for T {} + // String conversion functions and impl str -> num /// Parse a string as a number in base 10. diff --git a/src/libcore/prelude.rs b/src/libcore/prelude.rs index 2ab1347f578db..fdae5298d7cc6 100644 --- a/src/libcore/prelude.rs +++ b/src/libcore/prelude.rs @@ -42,6 +42,7 @@ pub use num::{Signed, Unsigned, Integer}; pub use num::{Round, Fractional, Real, RealExt}; pub use num::{Bitwise, Bounded}; pub use num::{Primitive, PrimitiveInt}; +pub use num::{Int, Uint, Float}; pub use path::GenericPath; pub use path::Path; pub use path::PosixPath; From d0737451fcf342e763b3700e6a491928cc887633 Mon Sep 17 00:00:00 2001 From: Brendan Zabarauskas Date: Fri, 26 Apr 2013 16:27:51 +1000 Subject: [PATCH 06/15] Add BitCount trait --- src/libcore/core.rc | 2 +- src/libcore/num/int-template.rs | 7 ++- src/libcore/num/int-template/i16.rs | 17 ++++++- src/libcore/num/int-template/i32.rs | 17 ++++++- src/libcore/num/int-template/i64.rs | 17 ++++++- src/libcore/num/int-template/i8.rs | 17 ++++++- src/libcore/num/int-template/int.rs | 71 ++++++++++++++++++++++++++- src/libcore/num/num.rs | 9 +++- src/libcore/num/uint-template.rs | 7 ++- src/libcore/num/uint-template/u16.rs | 17 ++++++- src/libcore/num/uint-template/u32.rs | 17 ++++++- src/libcore/num/uint-template/u64.rs | 17 ++++++- src/libcore/num/uint-template/u8.rs | 17 ++++++- src/libcore/num/uint-template/uint.rs | 69 +++++++++++++++++++++++++- src/libcore/prelude.rs | 2 +- 15 files changed, 287 insertions(+), 16 deletions(-) diff --git a/src/libcore/core.rc b/src/libcore/core.rc index 55cabad7412c3..b7d657669fea7 100644 --- a/src/libcore/core.rc +++ b/src/libcore/core.rc @@ -106,7 +106,7 @@ pub use iter::{ExtendedMutableIter}; pub use num::{Num, NumCast}; pub use num::{Signed, Unsigned, Integer}; pub use num::{Round, Fractional, Real, RealExt}; -pub use num::{Bitwise, Bounded}; +pub use num::{Bitwise, BitCount, Bounded}; pub use num::{Primitive, PrimitiveInt}; pub use num::{Int, Uint, Float}; pub use ptr::Ptr; diff --git a/src/libcore/num/int-template.rs b/src/libcore/num/int-template.rs index 877767b5cbf6a..11dacdd44939a 100644 --- a/src/libcore/num/int-template.rs +++ b/src/libcore/num/int-template.rs @@ -646,7 +646,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))); @@ -655,6 +655,11 @@ 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::(), sys::size_of::() * 8); diff --git a/src/libcore/num/int-template/i16.rs b/src/libcore/num/int-template/i16.rs index d67017ec62dd2..282633785553b 100644 --- a/src/libcore/num/int-template/i16.rs +++ b/src/libcore/num/int-template/i16.rs @@ -11,7 +11,8 @@ //! Operations and constants for `i16` mod inst { - use num::Primitive; + use num::{Primitive, BitCount}; + use unstable::intrinsics; pub type T = i16; pub static bits: uint = ::u16::bits; @@ -23,4 +24,18 @@ mod inst { #[inline(always)] fn bytes() -> uint { Primitive::bits::() / 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) } } + } } diff --git a/src/libcore/num/int-template/i32.rs b/src/libcore/num/int-template/i32.rs index fe2014bd3e01e..959cf8f7d77ca 100644 --- a/src/libcore/num/int-template/i32.rs +++ b/src/libcore/num/int-template/i32.rs @@ -11,7 +11,8 @@ //! Operations and constants for `i32` mod inst { - use num::Primitive; + use num::{Primitive, BitCount}; + use unstable::intrinsics; pub type T = i32; pub static bits: uint = ::u32::bits; @@ -23,4 +24,18 @@ mod inst { #[inline(always)] fn bytes() -> uint { Primitive::bits::() / 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) } } + } } diff --git a/src/libcore/num/int-template/i64.rs b/src/libcore/num/int-template/i64.rs index 0b39b421dab1c..3b51c70be12e5 100644 --- a/src/libcore/num/int-template/i64.rs +++ b/src/libcore/num/int-template/i64.rs @@ -11,7 +11,8 @@ //! Operations and constants for `i64` mod inst { - use num::Primitive; + use num::{Primitive, BitCount}; + use unstable::intrinsics; pub type T = i64; pub static bits: uint = ::u64::bits; @@ -23,4 +24,18 @@ mod inst { #[inline(always)] fn bytes() -> uint { Primitive::bits::() / 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) } } + } } diff --git a/src/libcore/num/int-template/i8.rs b/src/libcore/num/int-template/i8.rs index 0babd3779f15c..896fb4dbf50f8 100644 --- a/src/libcore/num/int-template/i8.rs +++ b/src/libcore/num/int-template/i8.rs @@ -11,7 +11,8 @@ //! Operations and constants for `i8` mod inst { - use num::Primitive; + use num::{Primitive, BitCount}; + use unstable::intrinsics; pub type T = i8; pub static bits: uint = ::u8::bits; @@ -23,4 +24,18 @@ mod inst { #[inline(always)] fn bytes() -> uint { Primitive::bits::() / 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) } } + } } diff --git a/src/libcore/num/int-template/int.rs b/src/libcore/num/int-template/int.rs index 3c179c554a8a2..bfe8bd0bfe68b 100644 --- a/src/libcore/num/int-template/int.rs +++ b/src/libcore/num/int-template/int.rs @@ -13,7 +13,7 @@ pub use self::inst::pow; mod inst { - use num::Primitive; + use num::{Primitive, BitCount}; pub type T = int; pub static bits: uint = ::uint::bits; @@ -31,12 +31,79 @@ mod inst { #[cfg(not(target_word_size = "32"), not(target_word_size = "64"))] #[inline(always)] - fn bits() -> uint { sys::size_of::() * 8 } + fn bits() -> uint { ::sys::size_of::() * 8 } #[inline(always)] fn bytes() -> uint { Primitive::bits::() / 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 uint } + + /// Counts the number of leading zeros. Wraps LLVM's `ctlz` intrinsic. + #[inline(always)] + fn leading_zeros(&self) -> int { (*self as i32).leading_zeros() as uint } + + /// Counts the number of trailing zeros. Wraps LLVM's `cttz` intrinsic. + #[inline(always)] + fn trailing_zeros(&self) -> int { (*self as i32).trailing_zeros() as uint } + } + + #[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 i32).trailing_zeros() as int } + } + + // fallback if we don't have access to the current word size + #[cfg(not(target_word_size = "32"), + not(target_word_size = "64"))] + impl BitCount for int { + /// Counts the number of bits set. + #[inline(always)] + fn population_count(&self) -> int { + match ::sys::size_of::() { + 8 => (*self as i64).population_count() as int, + 4 => (*self as i32).population_count() as int, + s => fail!(fmt!("unsupported word size: %?", s)), + } + } + + /// Counts the number of leading zeros. + #[inline(always)] + fn leading_zeros(&self) -> int { + match ::sys::size_of::() { + 8 => (*self as i64).leading_zeros() as int, + 4 => (*self as i32).leading_zeros() as int, + s => fail!(fmt!("unsupported word size: %?", s)), + } + } + + /// Counts the number of trailing zeros. + #[inline(always)] + fn trailing_zeros(&self) -> int { + match ::sys::size_of::() { + 8 => (*self as i64).trailing_zeros() as int, + 4 => (*self as i32).trailing_zeros() as int, + s => fail!(fmt!("unsupported word size: %?", s)), + } + } + } + /// Returns `base` raised to the power of `exponent` pub fn pow(base: int, exponent: uint) -> int { if exponent == 0u { diff --git a/src/libcore/num/num.rs b/src/libcore/num/num.rs index 8e6128ceb9763..cec5fe8cd283b 100644 --- a/src/libcore/num/num.rs +++ b/src/libcore/num/num.rs @@ -184,6 +184,12 @@ pub trait Bitwise: Not + Shl + Shr {} +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; @@ -214,7 +220,8 @@ pub trait Primitive: Num pub trait PrimitiveInt: Integer + Primitive + Bounded - + Bitwise {} + + Bitwise + + BitCount {} /// /// Specialisation of `PrimitiveInt` for unsigned integers diff --git a/src/libcore/num/uint-template.rs b/src/libcore/num/uint-template.rs index 67a930c72a467..2e6c7e28b18dd 100644 --- a/src/libcore/num/uint-template.rs +++ b/src/libcore/num/uint-template.rs @@ -389,7 +389,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))); @@ -398,6 +398,11 @@ 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::(), sys::size_of::() * 8); diff --git a/src/libcore/num/uint-template/u16.rs b/src/libcore/num/uint-template/u16.rs index fda731b7a182d..cc262f6b4dee7 100644 --- a/src/libcore/num/uint-template/u16.rs +++ b/src/libcore/num/uint-template/u16.rs @@ -11,7 +11,8 @@ //! Operations and constants for `u16` mod inst { - use num::Primitive; + use num::{Primitive, BitCount}; + use unstable::intrinsics; pub type T = u16; #[allow(non_camel_case_types)] @@ -25,4 +26,18 @@ mod inst { #[inline(always)] fn bytes() -> uint { Primitive::bits::() / 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 } } + } } diff --git a/src/libcore/num/uint-template/u32.rs b/src/libcore/num/uint-template/u32.rs index 2ebf86a749f22..7d7c8e3be302e 100644 --- a/src/libcore/num/uint-template/u32.rs +++ b/src/libcore/num/uint-template/u32.rs @@ -11,7 +11,8 @@ //! Operations and constants for `u32` mod inst { - use num::Primitive; + use num::{Primitive, BitCount}; + use unstable::intrinsics; pub type T = u32; #[allow(non_camel_case_types)] @@ -25,4 +26,18 @@ mod inst { #[inline(always)] fn bytes() -> uint { Primitive::bits::() / 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 } } + } } diff --git a/src/libcore/num/uint-template/u64.rs b/src/libcore/num/uint-template/u64.rs index d34c6ced36f8e..756c29950c35b 100644 --- a/src/libcore/num/uint-template/u64.rs +++ b/src/libcore/num/uint-template/u64.rs @@ -11,7 +11,8 @@ //! Operations and constants for `u64` mod inst { - use num::Primitive; + use num::{Primitive, BitCount}; + use unstable::intrinsics; pub type T = u64; #[allow(non_camel_case_types)] @@ -25,4 +26,18 @@ mod inst { #[inline(always)] fn bytes() -> uint { Primitive::bits::() / 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 } } + } } diff --git a/src/libcore/num/uint-template/u8.rs b/src/libcore/num/uint-template/u8.rs index 857a3f90caa84..5ac860c0359c5 100644 --- a/src/libcore/num/uint-template/u8.rs +++ b/src/libcore/num/uint-template/u8.rs @@ -11,7 +11,8 @@ //! Operations and constants for `u8` mod inst { - use num::Primitive; + use num::{Primitive, BitCount}; + use unstable::intrinsics; pub type T = u8; #[allow(non_camel_case_types)] @@ -25,4 +26,18 @@ mod inst { #[inline(always)] fn bytes() -> uint { Primitive::bits::() / 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 } } + } } diff --git a/src/libcore/num/uint-template/uint.rs b/src/libcore/num/uint-template/uint.rs index df7d45f620184..9e10ed63968a1 100644 --- a/src/libcore/num/uint-template/uint.rs +++ b/src/libcore/num/uint-template/uint.rs @@ -18,7 +18,7 @@ pub use self::inst::{ pub mod inst { use sys; use iter; - use num::Primitive; + use num::{Primitive, BitCount}; pub type T = uint; #[allow(non_camel_case_types)] @@ -51,6 +51,73 @@ pub mod inst { fn bytes() -> uint { Primitive::bits::() / 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 i32).trailing_zeros() as uint } + } + + // fallback if we don't have access to the current word size + #[cfg(not(target_word_size = "32"), + not(target_word_size = "64"))] + impl BitCount for uint { + /// Counts the number of bits set. + #[inline(always)] + fn population_count(&self) -> uint { + match sys::size_of::() { + 8 => (*self as i64).population_count() as uint, + 4 => (*self as i32).population_count() as uint, + s => fail!(fmt!("unsupported word size: %?", s)), + } + } + + /// Counts the number of leading zeros. + #[inline(always)] + fn leading_zeros(&self) -> uint { + match sys::size_of::() { + 8 => (*self as i64).leading_zeros() as uint, + 4 => (*self as i32).leading_zeros() as uint, + s => fail!(fmt!("unsupported word size: %?", s)), + } + } + + /// Counts the number of trailing zeros. + #[inline(always)] + fn trailing_zeros(&self) -> uint { + match sys::size_of::() { + 8 => (*self as i64).trailing_zeros() as uint, + 4 => (*self as i32).trailing_zeros() as uint, + s => fail!(fmt!("unsupported word size: %?", s)), + } + } + } + /// /// Divide two numbers, return the result, rounded up. /// diff --git a/src/libcore/prelude.rs b/src/libcore/prelude.rs index fdae5298d7cc6..1ab6f8d444178 100644 --- a/src/libcore/prelude.rs +++ b/src/libcore/prelude.rs @@ -40,7 +40,7 @@ pub use iter::{Times, ExtendedMutableIter}; pub use num::{Num, NumCast}; pub use num::{Signed, Unsigned, Integer}; pub use num::{Round, Fractional, Real, RealExt}; -pub use num::{Bitwise, Bounded}; +pub use num::{Bitwise, BitCount, Bounded}; pub use num::{Primitive, PrimitiveInt}; pub use num::{Int, Uint, Float}; pub use path::GenericPath; From faaf3bf1495a8d76e822981544de2b346346d91d Mon Sep 17 00:00:00 2001 From: Brendan Zabarauskas Date: Fri, 26 Apr 2013 17:25:17 +1000 Subject: [PATCH 07/15] Fix failing test --- src/test/run-pass/float-nan.rs | 138 +++++++++++++++++---------------- 1 file changed, 71 insertions(+), 67 deletions(-) diff --git a/src/test/run-pass/float-nan.rs b/src/test/run-pass/float-nan.rs index 918d45ad49246..08523de3ccd81 100644 --- a/src/test/run-pass/float-nan.rs +++ b/src/test/run-pass/float-nan.rs @@ -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::(); + assert!((nan).is_NaN()); - let inf = float::infinity; - assert!((-inf == float::neg_infinity)); + let inf = infinity::(); + assert!(-inf == neg_infinity::()); - 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()); } From 6efbbf2e1481c3f42d7bd1cd7008fdc54939d9d3 Mon Sep 17 00:00:00 2001 From: Brendan Zabarauskas Date: Fri, 26 Apr 2013 19:56:11 +1000 Subject: [PATCH 08/15] Combine PrimitiveInt, Int, and Uint traits into one single trait MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Having three traits for primitive ints/uints seemed rather excessive. If users wish to specify between them they can simply combine Int with either the Signed and Unsigned traits. For example: fn foo() { … } --- src/libcore/core.rc | 3 +-- src/libcore/num/int-template.rs | 2 -- src/libcore/num/num.rs | 22 +++++----------------- src/libcore/num/uint-template.rs | 4 +--- src/libcore/prelude.rs | 3 +-- 5 files changed, 8 insertions(+), 26 deletions(-) diff --git a/src/libcore/core.rc b/src/libcore/core.rc index b7d657669fea7..47f83103b799c 100644 --- a/src/libcore/core.rc +++ b/src/libcore/core.rc @@ -107,8 +107,7 @@ pub use num::{Num, NumCast}; pub use num::{Signed, Unsigned, Integer}; pub use num::{Round, Fractional, Real, RealExt}; pub use num::{Bitwise, BitCount, Bounded}; -pub use num::{Primitive, PrimitiveInt}; -pub use num::{Int, Uint, Float}; +pub use num::{Primitive, Int, Float}; pub use ptr::Ptr; pub use to_str::ToStr; pub use clone::Clone; diff --git a/src/libcore/num/int-template.rs b/src/libcore/num/int-template.rs index 11dacdd44939a..0c126bd1de536 100644 --- a/src/libcore/num/int-template.rs +++ b/src/libcore/num/int-template.rs @@ -445,8 +445,6 @@ impl Bounded for T { fn max_value() -> T { max_value } } -impl PrimitiveInt for T {} - impl Int for T {} // String conversion functions and impl str -> num diff --git a/src/libcore/num/num.rs b/src/libcore/num/num.rs index cec5fe8cd283b..f1a77a4ed59e9 100644 --- a/src/libcore/num/num.rs +++ b/src/libcore/num/num.rs @@ -217,23 +217,11 @@ pub trait Primitive: Num /// /// A collection of traits relevant to primitive signed and unsigned integers /// -pub trait PrimitiveInt: Integer - + Primitive - + Bounded - + Bitwise - + BitCount {} - -/// -/// Specialisation of `PrimitiveInt` for unsigned integers -/// -pub trait Uint: PrimitiveInt - + Unsigned {} - -/// -/// Specialisation of `PrimitiveInt` for signed integers -/// -pub trait Int: PrimitiveInt - + Signed {} +pub trait Int: Integer + + Primitive + + Bounded + + Bitwise + + BitCount {} /// /// Primitive floating point numbers. This trait should only be implemented diff --git a/src/libcore/num/uint-template.rs b/src/libcore/num/uint-template.rs index 2e6c7e28b18dd..d84f4a99d53f3 100644 --- a/src/libcore/num/uint-template.rs +++ b/src/libcore/num/uint-template.rs @@ -277,9 +277,7 @@ impl Bounded for T { fn max_value() -> T { max_value } } -impl PrimitiveInt for T {} - -impl Uint for T {} +impl Int for T {} // String conversion functions and impl str -> num diff --git a/src/libcore/prelude.rs b/src/libcore/prelude.rs index 1ab6f8d444178..2711399c483fc 100644 --- a/src/libcore/prelude.rs +++ b/src/libcore/prelude.rs @@ -41,8 +41,7 @@ pub use num::{Num, NumCast}; pub use num::{Signed, Unsigned, Integer}; pub use num::{Round, Fractional, Real, RealExt}; pub use num::{Bitwise, BitCount, Bounded}; -pub use num::{Primitive, PrimitiveInt}; -pub use num::{Int, Uint, Float}; +pub use num::{Primitive, Int, Float}; pub use path::GenericPath; pub use path::Path; pub use path::PosixPath; From 6cc7107aa6ca78093cb81aed44170099b8fad68a Mon Sep 17 00:00:00 2001 From: Brendan Zabarauskas Date: Sat, 27 Apr 2013 01:01:53 +1000 Subject: [PATCH 09/15] Add Orderable trait 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). --- src/libcore/core.rc | 3 ++- src/libcore/num/f32.rs | 25 +++++++++++++++++++++++++ src/libcore/num/f64.rs | 25 +++++++++++++++++++++++++ src/libcore/num/float.rs | 29 +++++++++++++++++++++++++++++ src/libcore/num/int-template.rs | 29 +++++++++++++++++++++++++++++ src/libcore/num/num.rs | 17 +++++++++++++++-- src/libcore/num/uint-template.rs | 29 +++++++++++++++++++++++++++++ src/libcore/prelude.rs | 2 +- 8 files changed, 155 insertions(+), 4 deletions(-) diff --git a/src/libcore/core.rc b/src/libcore/core.rc index 47f83103b799c..158da9a12fca1 100644 --- a/src/libcore/core.rc +++ b/src/libcore/core.rc @@ -104,10 +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; diff --git a/src/libcore/num/f32.rs b/src/libcore/num/f32.rs index f6330df9f9ea5..1e08979d79690 100644 --- a/src/libcore/num/f32.rs +++ b/src/libcore/num/f32.rs @@ -224,6 +224,20 @@ impl Ord for f32 { fn gt(&self, other: &f32) -> bool { (*self) > (*other) } } +impl Orderable for f32 { + #[inline(always)] + fn min(&self, other: &f32) -> f32 { fmin(*self, *other) } + + #[inline(always)] + fn max(&self, other: &f32) -> f32 { fmax(*self, *other) } + + #[inline(always)] + fn clamp(&self, mn: &f32, mx: &f32) -> f32 { + if *self > *mx { *mx } else + if *self < *mn { *mn } else { *self } + } +} + impl Zero for f32 { #[inline(always)] fn zero() -> f32 { 0.0 } @@ -768,6 +782,17 @@ mod tests { num::test_num(10f32, 2f32); } + #[test] + fn test_orderable() { + assert_eq!(1f32.min(&2f32), 1f32); + assert_eq!(2f32.min(&1f32), 1f32); + assert_eq!(1f32.max(&2f32), 2f32); + assert_eq!(2f32.max(&1f32), 2f32); + assert_eq!(1f32.clamp(&2f32, &4f32), 2f32); + assert_eq!(8f32.clamp(&2f32, &4f32), 4f32); + assert_eq!(3f32.clamp(&2f32, &4f32), 3f32); + } + #[test] fn test_floor() { assert_fuzzy_eq!(1.0f32.floor(), 1.0f32); diff --git a/src/libcore/num/f64.rs b/src/libcore/num/f64.rs index d40c402b464d9..a42084336bfc1 100644 --- a/src/libcore/num/f64.rs +++ b/src/libcore/num/f64.rs @@ -245,6 +245,20 @@ impl Ord for f64 { fn gt(&self, other: &f64) -> bool { (*self) > (*other) } } +impl Orderable for f64 { + #[inline(always)] + fn min(&self, other: &f64) -> f64 { fmin(*self, *other) } + + #[inline(always)] + fn max(&self, other: &f64) -> f64 { fmax(*self, *other) } + + #[inline(always)] + fn clamp(&self, mn: &f64, mx: &f64) -> f64 { + if *self > *mx { *mx } else + if *self < *mn { *mn } else { *self } + } +} + impl Zero for f64 { #[inline(always)] fn zero() -> f64 { 0.0 } @@ -809,6 +823,17 @@ mod tests { num::test_num(10f64, 2f64); } + #[test] + fn test_orderable() { + assert_eq!(1f64.min(&2f64), 1f64); + assert_eq!(2f64.min(&1f64), 1f64); + assert_eq!(1f64.max(&2f64), 2f64); + assert_eq!(2f64.max(&1f64), 2f64); + assert_eq!(1f64.clamp(&2f64, &4f64), 2f64); + assert_eq!(8f64.clamp(&2f64, &4f64), 4f64); + assert_eq!(3f64.clamp(&2f64, &4f64), 3f64); + } + #[test] fn test_floor() { assert_fuzzy_eq!(1.0f64.floor(), 1.0f64); diff --git a/src/libcore/num/float.rs b/src/libcore/num/float.rs index 9852e05c0b829..8661e7f0574cb 100644 --- a/src/libcore/num/float.rs +++ b/src/libcore/num/float.rs @@ -384,6 +384,24 @@ impl Ord for float { fn gt(&self, other: &float) -> bool { (*self) > (*other) } } +impl Orderable for float { + #[inline(always)] + fn min(&self, other: &float) -> float { + fmin(*self as f64, *other as f64) as float + } + + #[inline(always)] + fn max(&self, other: &float) -> float { + fmax(*self as f64, *other as f64) as float + } + + #[inline(always)] + fn clamp(&self, mn: &float, mx: &float) -> float { + if *self > *mx { *mx } else + if *self < *mn { *mn } else { *self } + } +} + impl Zero for float { #[inline(always)] fn zero() -> float { 0.0 } @@ -738,6 +756,17 @@ mod tests { num::test_num(10f, 2f); } + #[test] + fn test_orderable() { + assert_eq!(1f.min(&2f), 1f); + assert_eq!(2f.min(&1f), 1f); + assert_eq!(1f.max(&2f), 2f); + assert_eq!(2f.max(&1f), 2f); + assert_eq!(1f.clamp(&2f, &4f), 2f); + assert_eq!(8f.clamp(&2f, &4f), 4f); + assert_eq!(3f.clamp(&2f, &4f), 3f); + } + #[test] fn test_floor() { assert_fuzzy_eq!(1.0f.floor(), 1.0f); diff --git a/src/libcore/num/int-template.rs b/src/libcore/num/int-template.rs index 0c126bd1de536..08df820a73db8 100644 --- a/src/libcore/num/int-template.rs +++ b/src/libcore/num/int-template.rs @@ -152,6 +152,24 @@ impl Eq for T { fn ne(&self, other: &T) -> bool { return (*self) != (*other); } } +impl Orderable for T { + #[inline(always)] + 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 Zero for T { #[inline(always)] fn zero() -> T { 0 } @@ -535,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); diff --git a/src/libcore/num/num.rs b/src/libcore/num/num.rs index f1a77a4ed59e9..759f3e9872f92 100644 --- a/src/libcore/num/num.rs +++ b/src/libcore/num/num.rs @@ -24,6 +24,9 @@ use kinds::Copy; pub mod strconv; +/// +/// The base trait for numeric types +/// pub trait Num: Eq + Zero + One + Neg + Add @@ -37,6 +40,16 @@ 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 { fn zero() -> Self; // FIXME (#5527): This should be an associated constant fn is_zero(&self) -> bool; @@ -62,7 +75,7 @@ pub fn abs>(v: T) -> T { } pub trait Integer: Num - + Ord + + Orderable + Quot + Rem { fn div(&self, other: &Self) -> Self; @@ -86,7 +99,7 @@ pub trait Round { } pub trait Fractional: Num - + Ord + + Orderable + Round + Quot { fn recip(&self) -> Self; diff --git a/src/libcore/num/uint-template.rs b/src/libcore/num/uint-template.rs index d84f4a99d53f3..af64660ad0c5c 100644 --- a/src/libcore/num/uint-template.rs +++ b/src/libcore/num/uint-template.rs @@ -117,6 +117,24 @@ impl Eq for T { fn ne(&self, other: &T) -> bool { return (*self) != (*other); } } +impl Orderable for T { + #[inline(always)] + 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 Zero for T { #[inline(always)] fn zero() -> T { 0 } @@ -367,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); diff --git a/src/libcore/prelude.rs b/src/libcore/prelude.rs index 2711399c483fc..7e41f1b5b34e2 100644 --- a/src/libcore/prelude.rs +++ b/src/libcore/prelude.rs @@ -38,7 +38,7 @@ 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}; From b7cf89f6e8c076cfd844b884474279687554597e Mon Sep 17 00:00:00 2001 From: Brendan Zabarauskas Date: Sat, 27 Apr 2013 01:02:30 +1000 Subject: [PATCH 10/15] Add mul_add and next_after methods to Float --- src/libcore/num/f32.rs | 16 ++++++++++++++++ src/libcore/num/f64.rs | 16 ++++++++++++++++ src/libcore/num/float.rs | 16 ++++++++++++++++ src/libcore/num/num.rs | 9 +++++++-- 4 files changed, 55 insertions(+), 2 deletions(-) diff --git a/src/libcore/num/f32.rs b/src/libcore/num/f32.rs index 1e08979d79690..cae26349af14e 100644 --- a/src/libcore/num/f32.rs +++ b/src/libcore/num/f32.rs @@ -543,6 +543,22 @@ impl Float for f32 { 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 { + nextafter(*self, other) + } } // diff --git a/src/libcore/num/f64.rs b/src/libcore/num/f64.rs index a42084336bfc1..d5b423edb2988 100644 --- a/src/libcore/num/f64.rs +++ b/src/libcore/num/f64.rs @@ -583,6 +583,22 @@ impl Float for f64 { 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: 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 { + nextafter(*self, other) + } } // diff --git a/src/libcore/num/float.rs b/src/libcore/num/float.rs index 8661e7f0574cb..4ba5b00549097 100644 --- a/src/libcore/num/float.rs +++ b/src/libcore/num/float.rs @@ -735,6 +735,22 @@ impl Float for float { 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 { + nextafter(*self as f64, other as f64) as float + } } #[cfg(test)] diff --git a/src/libcore/num/num.rs b/src/libcore/num/num.rs index 759f3e9872f92..7da6107a0fb67 100644 --- a/src/libcore/num/num.rs +++ b/src/libcore/num/num.rs @@ -105,6 +105,9 @@ pub trait Fractional: Num 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 @@ -237,8 +240,7 @@ pub trait Int: Integer + BitCount {} /// -/// Primitive floating point numbers. This trait should only be implemented -/// for the `f32`, `f64`, and `float` types. +/// Primitive floating point numbers /// pub trait Float: Real + Signed @@ -252,6 +254,9 @@ pub trait Float: Real fn is_NaN(&self) -> bool; fn is_infinite(&self) -> bool; fn is_finite(&self) -> bool; + + fn mul_add(&self, a: Self, b: Self) -> Self; + fn next_after(&self, other: Self) -> Self; } /// From 4cc9d0ba7e454730988f318aeed92ab5e5ff8269 Mon Sep 17 00:00:00 2001 From: Brendan Zabarauskas Date: Sat, 27 Apr 2013 09:07:40 +1000 Subject: [PATCH 11/15] Add additional constants to primitive floating point numbers These follow the values defined in the C99 standard --- src/libcore/num/f32.rs | 29 +++++++++++++++++++++++++++++ src/libcore/num/f64.rs | 29 +++++++++++++++++++++++++++++ src/libcore/num/float.rs | 29 +++++++++++++++++++++++++++++ src/libcore/num/num.rs | 10 +++++++++- 4 files changed, 96 insertions(+), 1 deletion(-) diff --git a/src/libcore/num/f32.rs b/src/libcore/num/f32.rs index cae26349af14e..bc067369bdbfa 100644 --- a/src/libcore/num/f32.rs +++ b/src/libcore/num/f32.rs @@ -508,6 +508,14 @@ impl Real for f32 { fn tanh(&self) -> f32 { tanh(*self) } } +impl Bounded for f32 { + #[inline(always)] + fn min_value() -> f32 { 1.17549435e-38 } + + #[inline(always)] + fn max_value() -> f32 { 3.40282347e+38 } +} + impl Primitive for f32 { #[inline(always)] fn bits() -> uint { 32 } @@ -532,6 +540,27 @@ impl Float for f32 { #[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 { diff --git a/src/libcore/num/f64.rs b/src/libcore/num/f64.rs index d5b423edb2988..2a9f1cb3350fe 100644 --- a/src/libcore/num/f64.rs +++ b/src/libcore/num/f64.rs @@ -548,6 +548,14 @@ impl RealExt for f64 { fn yn(&self, n: int) -> f64 { yn(n as c_int, *self) } } +impl Bounded for f64 { + #[inline(always)] + fn min_value() -> f64 { 2.2250738585072014e-308 } + + #[inline(always)] + fn max_value() -> f64 { 1.7976931348623157e+308 } +} + impl Primitive for f64 { #[inline(always)] fn bits() -> uint { 64 } @@ -584,6 +592,27 @@ impl Float for f64 { !(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 diff --git a/src/libcore/num/float.rs b/src/libcore/num/float.rs index 4ba5b00549097..55f1281702681 100644 --- a/src/libcore/num/float.rs +++ b/src/libcore/num/float.rs @@ -700,6 +700,14 @@ 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::() as float } + + #[inline(always)] + fn max_value() -> float { Bounded::max_value::() as float } +} + impl Primitive for float { #[inline(always)] fn bits() -> uint { Primitive::bits::() } @@ -724,6 +732,27 @@ impl Float for float { #[inline(always)] fn is_NaN(&self) -> bool { *self != *self } + #[inline(always)] + fn mantissa_digits() -> uint { Float::mantissa_digits::() } + + #[inline(always)] + fn digits() -> uint { Float::digits::() } + + #[inline(always)] + fn epsilon() -> float { Float::epsilon::() as float } + + #[inline(always)] + fn min_exp() -> int { Float::min_exp::() } + + #[inline(always)] + fn max_exp() -> int { Float::max_exp::() } + + #[inline(always)] + fn min_10_exp() -> int { Float::min_10_exp::() } + + #[inline(always)] + fn max_10_exp() -> int { Float::max_10_exp::() } + /// Returns `true` if the number is infinite #[inline(always)] fn is_infinite(&self) -> bool { diff --git a/src/libcore/num/num.rs b/src/libcore/num/num.rs index 7da6107a0fb67..0e2669a26b6b3 100644 --- a/src/libcore/num/num.rs +++ b/src/libcore/num/num.rs @@ -219,6 +219,7 @@ pub trait Bounded { /// pub trait Primitive: Num + NumCast + + Bounded + Neg + Add + Sub @@ -235,7 +236,6 @@ pub trait Primitive: Num /// pub trait Int: Integer + Primitive - + Bounded + Bitwise + BitCount {} @@ -255,6 +255,14 @@ pub trait Float: Real 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; } From 32df8ed877e6ec73eb787798384e114182caf08c Mon Sep 17 00:00:00 2001 From: Brendan Zabarauskas Date: Sat, 27 Apr 2013 10:16:09 +1000 Subject: [PATCH 12/15] Rename `nextafter` to `next_after` to match method name in Float --- src/libcore/num/cmath.rs | 5 +++-- src/libcore/num/f32.rs | 4 ++-- src/libcore/num/f64.rs | 4 ++-- src/libcore/num/float.rs | 4 ++-- 4 files changed, 9 insertions(+), 8 deletions(-) diff --git a/src/libcore/num/cmath.rs b/src/libcore/num/cmath.rs index 378ebfa53a0c2..30b0c54dc2dc2 100644 --- a/src/libcore/num/cmath.rs +++ b/src/libcore/num/cmath.rs @@ -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"] diff --git a/src/libcore/num/f32.rs b/src/libcore/num/f32.rs index bc067369bdbfa..97ad23696bdab 100644 --- a/src/libcore/num/f32.rs +++ b/src/libcore/num/f32.rs @@ -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, @@ -586,7 +586,7 @@ impl Float for f32 { /// Returns the next representable floating-point value in the direction of `other` #[inline(always)] fn next_after(&self, other: f32) -> f32 { - nextafter(*self, other) + next_after(*self, other) } } diff --git a/src/libcore/num/f64.rs b/src/libcore/num/f64.rs index 2a9f1cb3350fe..92ce4969f47b8 100644 --- a/src/libcore/num/f64.rs +++ b/src/libcore/num/f64.rs @@ -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, @@ -626,7 +626,7 @@ impl Float for f64 { /// Returns the next representable floating-point value in the direction of `other` #[inline(always)] fn next_after(&self, other: f64) -> f64 { - nextafter(*self, other) + next_after(*self, other) } } diff --git a/src/libcore/num/float.rs b/src/libcore/num/float.rs index 55f1281702681..d784aeb23971c 100644 --- a/src/libcore/num/float.rs +++ b/src/libcore/num/float.rs @@ -29,7 +29,7 @@ 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}; @@ -778,7 +778,7 @@ impl Float for float { /// Returns the next representable floating-point value in the direction of `other` #[inline(always)] fn next_after(&self, other: float) -> float { - nextafter(*self as f64, other as f64) as float + next_after(*self as f64, other as f64) as float } } From 35f33c17f7d242bce031a9e648e6c3f31dd59ef6 Mon Sep 17 00:00:00 2001 From: Brendan Zabarauskas Date: Sat, 27 Apr 2013 10:34:29 +1000 Subject: [PATCH 13/15] Remove unnecessary fallbacks The `target_word_size` attribute is always available at compile time, so there is no need for a fallback. --- src/libcore/num/int-template/int.rs | 41 --------------------------- src/libcore/num/uint-template/uint.rs | 41 --------------------------- 2 files changed, 82 deletions(-) diff --git a/src/libcore/num/int-template/int.rs b/src/libcore/num/int-template/int.rs index bfe8bd0bfe68b..c04e2a2e70d38 100644 --- a/src/libcore/num/int-template/int.rs +++ b/src/libcore/num/int-template/int.rs @@ -27,12 +27,6 @@ mod inst { #[inline(always)] fn bits() -> uint { 64 } - // fallback if we don't have access to the current word size - #[cfg(not(target_word_size = "32"), - not(target_word_size = "64"))] - #[inline(always)] - fn bits() -> uint { ::sys::size_of::() * 8 } - #[inline(always)] fn bytes() -> uint { Primitive::bits::() / 8 } } @@ -69,41 +63,6 @@ mod inst { fn trailing_zeros(&self) -> int { (*self as i32).trailing_zeros() as int } } - // fallback if we don't have access to the current word size - #[cfg(not(target_word_size = "32"), - not(target_word_size = "64"))] - impl BitCount for int { - /// Counts the number of bits set. - #[inline(always)] - fn population_count(&self) -> int { - match ::sys::size_of::() { - 8 => (*self as i64).population_count() as int, - 4 => (*self as i32).population_count() as int, - s => fail!(fmt!("unsupported word size: %?", s)), - } - } - - /// Counts the number of leading zeros. - #[inline(always)] - fn leading_zeros(&self) -> int { - match ::sys::size_of::() { - 8 => (*self as i64).leading_zeros() as int, - 4 => (*self as i32).leading_zeros() as int, - s => fail!(fmt!("unsupported word size: %?", s)), - } - } - - /// Counts the number of trailing zeros. - #[inline(always)] - fn trailing_zeros(&self) -> int { - match ::sys::size_of::() { - 8 => (*self as i64).trailing_zeros() as int, - 4 => (*self as i32).trailing_zeros() as int, - s => fail!(fmt!("unsupported word size: %?", s)), - } - } - } - /// Returns `base` raised to the power of `exponent` pub fn pow(base: int, exponent: uint) -> int { if exponent == 0u { diff --git a/src/libcore/num/uint-template/uint.rs b/src/libcore/num/uint-template/uint.rs index 9e10ed63968a1..d333b0b58e1df 100644 --- a/src/libcore/num/uint-template/uint.rs +++ b/src/libcore/num/uint-template/uint.rs @@ -41,12 +41,6 @@ pub mod inst { #[inline(always)] fn bits() -> uint { 64 } - // fallback if we don't have access to the current word size - #[cfg(not(target_word_size = "32"), - not(target_word_size = "64"))] - #[inline(always)] - fn bits() -> uint { sys::size_of::() * 8 } - #[inline(always)] fn bytes() -> uint { Primitive::bits::() / 8 } } @@ -83,41 +77,6 @@ pub mod inst { fn trailing_zeros(&self) -> uint { (*self as i32).trailing_zeros() as uint } } - // fallback if we don't have access to the current word size - #[cfg(not(target_word_size = "32"), - not(target_word_size = "64"))] - impl BitCount for uint { - /// Counts the number of bits set. - #[inline(always)] - fn population_count(&self) -> uint { - match sys::size_of::() { - 8 => (*self as i64).population_count() as uint, - 4 => (*self as i32).population_count() as uint, - s => fail!(fmt!("unsupported word size: %?", s)), - } - } - - /// Counts the number of leading zeros. - #[inline(always)] - fn leading_zeros(&self) -> uint { - match sys::size_of::() { - 8 => (*self as i64).leading_zeros() as uint, - 4 => (*self as i32).leading_zeros() as uint, - s => fail!(fmt!("unsupported word size: %?", s)), - } - } - - /// Counts the number of trailing zeros. - #[inline(always)] - fn trailing_zeros(&self) -> uint { - match sys::size_of::() { - 8 => (*self as i64).trailing_zeros() as uint, - 4 => (*self as i32).trailing_zeros() as uint, - s => fail!(fmt!("unsupported word size: %?", s)), - } - } - } - /// /// Divide two numbers, return the result, rounded up. /// From c9d099d60d8be7327fb90f2d1228436f0b403b20 Mon Sep 17 00:00:00 2001 From: Brendan Zabarauskas Date: Sat, 27 Apr 2013 12:42:34 +1000 Subject: [PATCH 14/15] Fix copy-paste mistakes --- src/libcore/num/int-template/int.rs | 8 ++++---- src/libcore/num/uint-template/uint.rs | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/libcore/num/int-template/int.rs b/src/libcore/num/int-template/int.rs index c04e2a2e70d38..7a44bfdf16038 100644 --- a/src/libcore/num/int-template/int.rs +++ b/src/libcore/num/int-template/int.rs @@ -36,15 +36,15 @@ mod inst { 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 uint } + 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 uint } + 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 uint } + fn trailing_zeros(&self) -> int { (*self as i32).trailing_zeros() as int } } #[cfg(target_word_size = "64")] @@ -60,7 +60,7 @@ mod inst { /// 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 } + fn trailing_zeros(&self) -> int { (*self as i64).trailing_zeros() as int } } /// Returns `base` raised to the power of `exponent` diff --git a/src/libcore/num/uint-template/uint.rs b/src/libcore/num/uint-template/uint.rs index d333b0b58e1df..6a8567451e6e0 100644 --- a/src/libcore/num/uint-template/uint.rs +++ b/src/libcore/num/uint-template/uint.rs @@ -74,7 +74,7 @@ pub mod inst { /// 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 } + fn trailing_zeros(&self) -> uint { (*self as i64).trailing_zeros() as uint } } /// From 9cdf402c80536c7e138d04433ee3f0a0855f08ce Mon Sep 17 00:00:00 2001 From: Brendan Zabarauskas Date: Sat, 27 Apr 2013 13:13:28 +1000 Subject: [PATCH 15/15] Propagate NaNs for Orderable methods impled on floating-point primitives --- src/libcore/num/f32.rs | 31 ++++++++++++++++++++++++++----- src/libcore/num/f64.rs | 35 ++++++++++++++++++++++++++++++----- src/libcore/num/float.rs | 24 +++++++++++++++++++----- 3 files changed, 75 insertions(+), 15 deletions(-) diff --git a/src/libcore/num/f32.rs b/src/libcore/num/f32.rs index 97ad23696bdab..ada47fb597e5d 100644 --- a/src/libcore/num/f32.rs +++ b/src/libcore/num/f32.rs @@ -225,16 +225,26 @@ impl Ord for f32 { } impl Orderable for f32 { + /// Returns `NaN` if either of the numbers are `NaN`. #[inline(always)] - fn min(&self, other: &f32) -> f32 { fmin(*self, *other) } + 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 { fmax(*self, *other) } + 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 > *mx { *mx } else - if *self < *mn { *mn } else { *self } + if self.is_NaN() { *self } + else if !(*self <= *mx) { *mx } + else if !(*self >= *mn) { *mn } + else { *self } } } @@ -828,14 +838,25 @@ mod tests { } #[test] - fn test_orderable() { + 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::(), &4f32).is_NaN()); + assert!(3f32.clamp(&2f32, &Float::NaN::()).is_NaN()); + assert!(Float::NaN::().clamp(&2f32, &4f32).is_NaN()); } #[test] diff --git a/src/libcore/num/f64.rs b/src/libcore/num/f64.rs index 92ce4969f47b8..07a29652e94aa 100644 --- a/src/libcore/num/f64.rs +++ b/src/libcore/num/f64.rs @@ -246,16 +246,26 @@ impl Ord for f64 { } impl Orderable for f64 { + /// Returns `NaN` if either of the numbers are `NaN`. #[inline(always)] - fn min(&self, other: &f64) -> f64 { fmin(*self, *other) } + 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 { fmax(*self, *other) } + 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 > *mx { *mx } else - if *self < *mn { *mn } else { *self } + if self.is_NaN() { *self } + else if !(*self <= *mx) { *mx } + else if !(*self >= *mn) { *mn } + else { *self } } } @@ -869,14 +879,29 @@ mod tests { } #[test] - fn test_orderable() { + fn test_min() { assert_eq!(1f64.min(&2f64), 1f64); assert_eq!(2f64.min(&1f64), 1f64); + assert!(1f64.min(&Float::NaN::()).is_NaN()); + assert!(Float::NaN::().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::()).is_NaN()); + assert!(Float::NaN::().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::(), &4f64).is_NaN()); + assert!(3f64.clamp(&2f64, &Float::NaN::()).is_NaN()); + assert!(Float::NaN::().clamp(&2f64, &4f64).is_NaN()); } #[test] diff --git a/src/libcore/num/float.rs b/src/libcore/num/float.rs index d784aeb23971c..ef0adee884b7c 100644 --- a/src/libcore/num/float.rs +++ b/src/libcore/num/float.rs @@ -385,20 +385,23 @@ impl Ord for float { } impl Orderable for float { + /// Returns `NaN` if either of the numbers are `NaN`. #[inline(always)] fn min(&self, other: &float) -> float { - fmin(*self as f64, *other as f64) as 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 { - fmax(*self as f64, *other as f64) as 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 { - if *self > *mx { *mx } else - if *self < *mn { *mn } else { *self } + (*self as f64).clamp(&(*mn as f64), &(*mx as f64)) as float } } @@ -802,14 +805,25 @@ mod tests { } #[test] - fn test_orderable() { + 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::(), &4f).is_NaN()); + assert!(3f.clamp(&2f, &Float::NaN::()).is_NaN()); + assert!(Float::NaN::().clamp(&2f, &4f).is_NaN()); } #[test]