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 7d5807ba546..c03761c2322 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 3b6198bfc47..ca6416be739 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 9c0412b422f..248bc2a4d56 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 f9edf1cefc8..b53bf876f77 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 e19afdc69c3..19d5340527d 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 96019ddd564..803d034c919 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 5f0fd76640a..214bb0be0ed 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 ef7fa397d7f..fc17cbc678e 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 8af1d99fa47..93b63593a5e 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 | 306 +++++++++++++------------- src/libcore/num/int-template.rs | 268 +++++++++++----------- src/libcore/num/num.rs | 56 ++--- src/libcore/num/uint-template.rs | 7 +- src/libcore/num/uint-template/uint.rs | 128 +++++------ 7 files changed, 658 insertions(+), 659 deletions(-) diff --git a/src/libcore/num/f32.rs b/src/libcore/num/f32.rs index c03761c2322..63e52fab7c9 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 ca6416be739..e6013eec243 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 248bc2a4d56..d5f22e6b056 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 - */ +// +// Section: String Conversions +// -/** - * Converts a float to a string - * - * # Arguments - * - * * num - The float value - */ +/// +/// Converts a float to a string +/// +/// # Arguments +/// +/// * num - The float value +/// #[inline(always)] pub fn to_str(num: float) -> ~str { let (r, _) = strconv::to_str_common( @@ -102,13 +102,13 @@ pub fn to_str(num: float) -> ~str { r } -/** - * Converts a float to a string in hexadecimal format - * - * # Arguments - * - * * num - The float value - */ +/// +/// Converts a float to a string in hexadecimal format +/// +/// # Arguments +/// +/// * num - The float value +/// #[inline(always)] pub fn to_str_hex(num: float) -> ~str { let (r, _) = strconv::to_str_common( @@ -116,20 +116,20 @@ pub fn to_str_hex(num: float) -> ~str { r } -/** - * Converts a float to a string in a given radix - * - * # Arguments - * - * * num - The float value - * * radix - The base to use - * - * # Failure - * - * Fails if called on a special value like `inf`, `-inf` or `NaN` due to - * possible misinterpretation of the result at higher bases. If those values - * are expected, use `to_str_radix_special()` instead. - */ +/// +/// Converts a float to a string in a given radix +/// +/// # Arguments +/// +/// * num - The float value +/// * radix - The base to use +/// +/// # Failure +/// +/// Fails if called on a special value like `inf`, `-inf` or `NaN` due to +/// possible misinterpretation of the result at higher bases. If those values +/// are expected, use `to_str_radix_special()` instead. +/// #[inline(always)] pub fn to_str_radix(num: float, radix: uint) -> ~str { let (r, special) = strconv::to_str_common( @@ -139,30 +139,30 @@ pub fn to_str_radix(num: float, radix: uint) -> ~str { r } -/** - * Converts a float to a string in a given radix, and a flag indicating - * whether it's a special value - * - * # Arguments - * - * * num - The float value - * * radix - The base to use - */ +/// +/// Converts a float to a string in a given radix, and a flag indicating +/// whether it's a special value +/// +/// # Arguments +/// +/// * num - The float value +/// * radix - The base to use +/// #[inline(always)] pub fn to_str_radix_special(num: float, radix: uint) -> (~str, bool) { strconv::to_str_common(&num, radix, true, strconv::SignNeg, strconv::DigAll) } -/** - * Converts a float to a string with exactly the number of - * provided significant digits - * - * # Arguments - * - * * num - The float value - * * digits - The number of significant digits - */ +/// +/// Converts a float to a string with exactly the number of +/// provided significant digits +/// +/// # Arguments +/// +/// * num - The float value +/// * digits - The number of significant digits +/// #[inline(always)] pub fn to_str_exact(num: float, digits: uint) -> ~str { let (r, _) = strconv::to_str_common( @@ -170,15 +170,15 @@ pub fn to_str_exact(num: float, digits: uint) -> ~str { r } -/** - * Converts a float to a string with a maximum number of - * significant digits - * - * # Arguments - * - * * num - The float value - * * digits - The number of significant digits - */ +/// +/// Converts a float to a string with a maximum number of +/// significant digits +/// +/// # Arguments +/// +/// * num - The float value +/// * digits - The number of significant digits +/// #[inline(always)] pub fn to_str_digits(num: float, digits: uint) -> ~str { let (r, _) = strconv::to_str_common( @@ -198,91 +198,91 @@ impl num::ToStrRadix for float { } } -/** - * Convert a string in base 10 to a float. - * Accepts a optional decimal exponent. - * - * This function accepts strings such as - * - * * '3.14' - * * '+3.14', equivalent to '3.14' - * * '-3.14' - * * '2.5E10', or equivalently, '2.5e10' - * * '2.5E-10' - * * '.' (understood as 0) - * * '5.' - * * '.5', or, equivalently, '0.5' - * * '+inf', 'inf', '-inf', 'NaN' - * - * Leading and trailing whitespace represent an error. - * - * # Arguments - * - * * num - A string - * - * # Return value - * - * `none` if the string did not represent a valid number. Otherwise, - * `Some(n)` where `n` is the floating-point number represented by `num`. - */ +/// +/// Convert a string in base 10 to a float. +/// Accepts a optional decimal exponent. +/// +/// This function accepts strings such as +/// +/// * '3.14' +/// * '+3.14', equivalent to '3.14' +/// * '-3.14' +/// * '2.5E10', or equivalently, '2.5e10' +/// * '2.5E-10' +/// * '.' (understood as 0) +/// * '5.' +/// * '.5', or, equivalently, '0.5' +/// * '+inf', 'inf', '-inf', 'NaN' +/// +/// Leading and trailing whitespace represent an error. +/// +/// # Arguments +/// +/// * num - A string +/// +/// # Return value +/// +/// `none` if the string did not represent a valid number. Otherwise, +/// `Some(n)` where `n` is the floating-point number represented by `num`. +/// #[inline(always)] pub fn from_str(num: &str) -> Option { 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 - */ +// +// Section: Arithmetics +// -/** - * Compute the exponentiation of an integer by another integer as a float - * - * # Arguments - * - * * x - The base - * * pow - The exponent - * - * # Return value - * - * `NaN` if both `x` and `pow` are `0u`, otherwise `x^pow` - */ +/// +/// Compute the exponentiation of an integer by another integer as a float +/// +/// # Arguments +/// +/// * x - The base +/// * pow - The exponent +/// +/// # Return value +/// +/// `NaN` if both `x` and `pow` are `0u`, otherwise `x^pow` +/// pub fn pow_with_uint(base: uint, pow: uint) -> float { if base == 0u { if pow == 0u { @@ -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 b53bf876f77..75d170118e6 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); + /// + /// Returns the integer quotient, truncated towards 0. As this behaviour reflects + /// the underlying machine implementation it is more efficient than `Natural::div`. + /// + /// # Examples + /// + /// ~~~ + /// assert!( 8 / 3 == 2); + /// assert!( 8 / -3 == -2); + /// assert!(-8 / 3 == -2); + /// assert!(-8 / -3 == 2); - * assert!( 1 / 2 == 0); - * assert!( 1 / -2 == 0); - * assert!(-1 / 2 == 0); - * assert!(-1 / -2 == 0); - * ~~~ - */ + /// assert!( 1 / 2 == 0); + /// assert!( 1 / -2 == 0); + /// assert!(-1 / 2 == 0); + /// assert!(-1 / -2 == 0); + /// ~~~ + /// #[inline(always)] fn quot(&self, other: &T) -> T { *self / *other } } @@ -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); + /// + /// Returns the integer remainder after division, satisfying: + /// + /// ~~~ + /// assert!((n / d) * d + (n % d) == n) + /// ~~~ + /// + /// # Examples + /// + /// ~~~ + /// assert!( 8 % 3 == 2); + /// assert!( 8 % -3 == 2); + /// assert!(-8 % 3 == -2); + /// assert!(-8 % -3 == -2); - * assert!( 1 % 2 == 1); - * assert!( 1 % -2 == 1); - * assert!(-1 % 2 == -1); - * assert!(-1 % -2 == -1); - * ~~~ - */ + /// assert!( 1 % 2 == 1); + /// assert!( 1 % -2 == 1); + /// assert!(-1 % 2 == -1); + /// assert!(-1 % -2 == -1); + /// ~~~ + /// #[inline(always)] fn rem(&self, other: &T) -> T { *self % *other } } @@ -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 19d5340527d..5797d86e6ec 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 803d034c919..ed0a5aa3876 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 efcf68aba31..5eaa27fb7a0 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 d5f22e6b056..92decce325a 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 75d170118e6..56b7616c255 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 71bbaf557ce..8b9ba22f330 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 63e52fab7c9..d1369b929f6 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 e6013eec243..4e0030b5421 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 92decce325a..a409639f9e6 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 56b7616c255..32ae19bec41 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 34dcd508397..d67017ec62d 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 91eea0e8d47..fe2014bd3e0 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 3834a1e2a03..0b39b421dab 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 9486ed748d7..0babd3779f1 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 6649b364015..3c179c554a8 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 5797d86e6ec..5b524a42c25 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 ed0a5aa3876..a89a6faec28 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 63144162fc5..fda731b7a18 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 4d9958fe38a..2ebf86a749f 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 af198dd6942..d34c6ced36f 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 5c548d72093..857a3f90caa 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 5eaa27fb7a0..df7d45f6201 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 553bb826810..2ab1347f578 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 8b9ba22f330..55cabad7412 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 d1369b929f6..f6330df9f9e 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 4e0030b5421..d40c402b464 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 a409639f9e6..9852e05c0b8 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 32ae19bec41..877767b5cbf 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 5b524a42c25..8e6128ceb97 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 a89a6faec28..67a930c72a4 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 2ab1347f578..fdae5298d7c 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 55cabad7412..b7d657669fe 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 877767b5cbf..11dacdd4493 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 d67017ec62d..28263378555 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 fe2014bd3e0..959cf8f7d77 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 0b39b421dab..3b51c70be12 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 0babd3779f1..896fb4dbf50 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 3c179c554a8..bfe8bd0bfe6 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 8e6128ceb97..cec5fe8cd28 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 67a930c72a4..2e6c7e28b18 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 fda731b7a18..cc262f6b4de 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 2ebf86a749f..7d7c8e3be30 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 d34c6ced36f..756c29950c3 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 857a3f90caa..5ac860c0359 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 df7d45f6201..9e10ed63968 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 fdae5298d7c..1ab6f8d4441 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 918d45ad492..08523de3ccd 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 b7d657669fe..47f83103b79 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 11dacdd4493..0c126bd1de5 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 cec5fe8cd28..f1a77a4ed59 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 2e6c7e28b18..d84f4a99d53 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 1ab6f8d4441..2711399c483 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 47f83103b79..158da9a12fc 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 f6330df9f9e..1e08979d796 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 d40c402b464..a42084336bf 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 9852e05c0b8..8661e7f0574 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 0c126bd1de5..08df820a73d 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 f1a77a4ed59..759f3e9872f 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 d84f4a99d53..af64660ad0c 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 2711399c483..7e41f1b5b34 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 1e08979d796..cae26349af1 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 a42084336bf..d5b423edb29 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 8661e7f0574..4ba5b005490 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 759f3e9872f..7da6107a0fb 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 cae26349af1..bc067369bdb 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 d5b423edb29..2a9f1cb3350 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 4ba5b005490..55f12817026 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 7da6107a0fb..0e2669a26b6 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 378ebfa53a0..30b0c54dc2d 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 bc067369bdb..97ad23696bd 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 2a9f1cb3350..92ce4969f47 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 55f12817026..d784aeb2397 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 bfe8bd0bfe6..c04e2a2e70d 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 9e10ed63968..d333b0b58e1 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 c04e2a2e70d..7a44bfdf160 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 d333b0b58e1..6a8567451e6 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 97ad23696bd..ada47fb597e 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 92ce4969f47..07a29652e94 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 d784aeb2397..ef0adee884b 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]