auto merge of #6041 : bjz/rust/numeric-traits, r=brson
As part of the numeric trait reform (see issue #4819), I have added the following traits to `core::num` and implemented them for the appropriate types: ~~~rust pub trait Signed: Num + Neg<Self> { fn abs(&self) -> Self; fn signum(&self) -> Self; fn is_positive(&self) -> bool; fn is_negative(&self) -> bool; } pub trait Unsigned: Num {} pub trait Natural: Num + Ord + Quot<Self,Self> + Rem<Self,Self> { fn div(&self, other: Self) -> Self; fn modulo(&self, other: Self) -> Self; fn div_mod(&self, other: Self) -> (Self,Self); fn quot_rem(&self, other: Self) -> (Self,Self); fn gcd(&self, other: Self) -> Self; fn lcm(&self, other: Self) -> Self; fn divisible_by(&self, other: Self) -> bool; fn is_even(&self) -> bool; fn is_odd(&self) -> bool; } ~~~ I have not implemented `Natural` for `BigInt` and `BigUInt` because they're a little over my head. Help with this would be most appreciated.
This commit is contained in:
commit
c8ac057545
@ -105,7 +105,7 @@ pub use iter::{BaseIter, ExtendedIter, EqIter, CopyableIter};
|
||||
pub use iter::{CopyableOrderedIter, CopyableNonstrictIter, Times};
|
||||
pub use iter::{ExtendedMutableIter};
|
||||
|
||||
pub use num::{Num, NumCast};
|
||||
pub use num::{Num, Signed, Unsigned, Natural, NumCast};
|
||||
pub use ptr::Ptr;
|
||||
pub use to_str::ToStr;
|
||||
pub use clone::Clone;
|
||||
|
@ -11,6 +11,7 @@
|
||||
//! Operations and constants for `f32`
|
||||
|
||||
use num::strconv;
|
||||
use num::Signed;
|
||||
use num;
|
||||
use option::Option;
|
||||
use from_str;
|
||||
@ -163,38 +164,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 positive number, including +0.0f320 and +Infinity
|
||||
#[inline(always)]
|
||||
pub fn is_positive(x: f32) -> bool {
|
||||
x > 0.0f32 || (1.0f32/x) == infinity
|
||||
}
|
||||
|
||||
/// Returns true if `x` is a negative number, including -0.0f320 and -Infinity
|
||||
#[inline(always)]
|
||||
pub fn is_negative(x: f32) -> bool {
|
||||
x < 0.0f32 || (1.0f32/x) == neg_infinity
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if `x` is a negative number, including -0.0f320 and -Infinity
|
||||
*
|
||||
* This is the same as `f32::is_negative`.
|
||||
*/
|
||||
#[inline(always)]
|
||||
pub fn is_nonpositive(x: f32) -> bool {
|
||||
return x < 0.0f32 || (1.0f32/x) == neg_infinity;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if `x` is a positive number, including +0.0f320 and +Infinity
|
||||
*
|
||||
* This is the same as `f32::is_positive`.)
|
||||
*/
|
||||
#[inline(always)]
|
||||
pub fn is_nonnegative(x: f32) -> bool {
|
||||
return x > 0.0f32 || (1.0f32/x) == infinity;
|
||||
}
|
||||
|
||||
/// Returns true if `x` is a zero number (positive or negative zero)
|
||||
#[inline(always)]
|
||||
pub fn is_zero(x: f32) -> bool {
|
||||
@ -259,11 +228,6 @@ pub mod consts {
|
||||
pub static ln_10: f32 = 2.30258509299404568401799145468436421_f32;
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn signbit(x: f32) -> int {
|
||||
if is_negative(x) { return 1; } else { return 0; }
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn logarithm(n: f32, b: f32) -> f32 {
|
||||
return log2(n) / log2(b);
|
||||
@ -351,15 +315,41 @@ impl Neg<f32> for f32 {
|
||||
fn neg(&self) -> f32 { -*self }
|
||||
}
|
||||
|
||||
impl Signed for f32 {
|
||||
/// Computes the absolute value. Returns `NaN` if the number is `NaN`.
|
||||
#[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`
|
||||
*/
|
||||
#[inline(always)]
|
||||
fn signum(&self) -> f32 {
|
||||
if is_NaN(*self) { NaN } else { copysign(1.0, *self) }
|
||||
}
|
||||
|
||||
/// Returns `true` if the number is positive, including `+0.0` and `infinity`
|
||||
#[inline(always)]
|
||||
fn is_positive(&self) -> bool { *self > 0.0 || (1.0 / *self) == infinity }
|
||||
|
||||
/// Returns `true` if the number is negative, including `-0.0` and `neg_infinity`
|
||||
#[inline(always)]
|
||||
fn is_negative(&self) -> bool { *self < 0.0 || (1.0 / *self) == neg_infinity }
|
||||
}
|
||||
|
||||
impl num::Round for f32 {
|
||||
#[inline(always)]
|
||||
fn round(&self, mode: num::RoundMode) -> f32 {
|
||||
match mode {
|
||||
num::RoundDown => floor(*self),
|
||||
num::RoundUp => ceil(*self),
|
||||
num::RoundToZero if is_negative(*self) => ceil(*self),
|
||||
num::RoundToZero if self.is_negative() => ceil(*self),
|
||||
num::RoundToZero => floor(*self),
|
||||
num::RoundFromZero if is_negative(*self) => floor(*self),
|
||||
num::RoundFromZero if self.is_negative() => floor(*self),
|
||||
num::RoundFromZero => ceil(*self)
|
||||
}
|
||||
}
|
||||
@ -370,7 +360,7 @@ impl num::Round for f32 {
|
||||
fn ceil(&self) -> f32 { ceil(*self) }
|
||||
#[inline(always)]
|
||||
fn fract(&self) -> f32 {
|
||||
if is_negative(*self) {
|
||||
if self.is_negative() {
|
||||
(*self) - ceil(*self)
|
||||
} else {
|
||||
(*self) - floor(*self)
|
||||
@ -595,6 +585,50 @@ impl num::FromStrRadix for f32 {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use f32::*;
|
||||
|
||||
#[test]
|
||||
pub fn test_signed() {
|
||||
assert_eq!(infinity.abs(), infinity);
|
||||
assert_eq!(1f32.abs(), 1f32);
|
||||
assert_eq!(0f32.abs(), 0f32);
|
||||
assert_eq!((-0f32).abs(), 0f32);
|
||||
assert_eq!((-1f32).abs(), 1f32);
|
||||
assert_eq!(neg_infinity.abs(), infinity);
|
||||
assert_eq!((1f32/neg_infinity).abs(), 0f32);
|
||||
assert!(is_NaN(NaN.abs()));
|
||||
|
||||
assert_eq!(infinity.signum(), 1f32);
|
||||
assert_eq!(1f32.signum(), 1f32);
|
||||
assert_eq!(0f32.signum(), 1f32);
|
||||
assert_eq!((-0f32).signum(), -1f32);
|
||||
assert_eq!((-1f32).signum(), -1f32);
|
||||
assert_eq!(neg_infinity.signum(), -1f32);
|
||||
assert_eq!((1f32/neg_infinity).signum(), -1f32);
|
||||
assert!(is_NaN(NaN.signum()));
|
||||
|
||||
assert!(infinity.is_positive());
|
||||
assert!(1f32.is_positive());
|
||||
assert!(0f32.is_positive());
|
||||
assert!(!(-0f32).is_positive());
|
||||
assert!(!(-1f32).is_positive());
|
||||
assert!(!neg_infinity.is_positive());
|
||||
assert!(!(1f32/neg_infinity).is_positive());
|
||||
assert!(!NaN.is_positive());
|
||||
|
||||
assert!(!infinity.is_negative());
|
||||
assert!(!1f32.is_negative());
|
||||
assert!(!0f32.is_negative());
|
||||
assert!((-0f32).is_negative());
|
||||
assert!((-1f32).is_negative());
|
||||
assert!(neg_infinity.is_negative());
|
||||
assert!((1f32/neg_infinity).is_negative());
|
||||
assert!(!NaN.is_negative());
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Local Variables:
|
||||
// mode: rust
|
||||
|
@ -11,6 +11,7 @@
|
||||
//! Operations and constants for `f64`
|
||||
|
||||
use num::strconv;
|
||||
use num::Signed;
|
||||
use num;
|
||||
use option::Option;
|
||||
use to_str;
|
||||
@ -183,36 +184,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 positive number, including +0.0f640 and +Infinity
|
||||
#[inline(always)]
|
||||
pub fn is_positive(x: f64) -> bool
|
||||
{ return x > 0.0f64 || (1.0f64/x) == infinity; }
|
||||
|
||||
/// Returns true if `x` is a negative number, including -0.0f640 and -Infinity
|
||||
#[inline(always)]
|
||||
pub fn is_negative(x: f64) -> bool
|
||||
{ return x < 0.0f64 || (1.0f64/x) == neg_infinity; }
|
||||
|
||||
/**
|
||||
* Returns true if `x` is a negative number, including -0.0f640 and -Infinity
|
||||
*
|
||||
* This is the same as `f64::is_negative`.
|
||||
*/
|
||||
#[inline(always)]
|
||||
pub fn is_nonpositive(x: f64) -> bool {
|
||||
return x < 0.0f64 || (1.0f64/x) == neg_infinity;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if `x` is a positive number, including +0.0f640 and +Infinity
|
||||
*
|
||||
* This is the same as `f64::positive`.
|
||||
*/
|
||||
#[inline(always)]
|
||||
pub fn is_nonnegative(x: f64) -> bool {
|
||||
return x > 0.0f64 || (1.0f64/x) == infinity;
|
||||
}
|
||||
|
||||
/// Returns true if `x` is a zero number (positive or negative zero)
|
||||
#[inline(always)]
|
||||
pub fn is_zero(x: f64) -> bool {
|
||||
@ -278,11 +249,6 @@ pub mod consts {
|
||||
pub static ln_10: f64 = 2.30258509299404568401799145468436421_f64;
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn signbit(x: f64) -> int {
|
||||
if is_negative(x) { return 1; } else { return 0; }
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn logarithm(n: f64, b: f64) -> f64 {
|
||||
return log2(n) / log2(b);
|
||||
@ -357,15 +323,41 @@ impl Neg<f64> for f64 {
|
||||
fn neg(&self) -> f64 { -*self }
|
||||
}
|
||||
|
||||
impl Signed for f64 {
|
||||
/// Computes the absolute value. Returns `NaN` if the number is `NaN`.
|
||||
#[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`
|
||||
*/
|
||||
#[inline(always)]
|
||||
fn signum(&self) -> f64 {
|
||||
if is_NaN(*self) { NaN } else { copysign(1.0, *self) }
|
||||
}
|
||||
|
||||
/// Returns `true` if the number is positive, including `+0.0` and `infinity`
|
||||
#[inline(always)]
|
||||
fn is_positive(&self) -> bool { *self > 0.0 || (1.0 / *self) == infinity }
|
||||
|
||||
/// Returns `true` if the number is negative, including `-0.0` and `neg_infinity`
|
||||
#[inline(always)]
|
||||
fn is_negative(&self) -> bool { *self < 0.0 || (1.0 / *self) == neg_infinity }
|
||||
}
|
||||
|
||||
impl num::Round for f64 {
|
||||
#[inline(always)]
|
||||
fn round(&self, mode: num::RoundMode) -> f64 {
|
||||
match mode {
|
||||
num::RoundDown => floor(*self),
|
||||
num::RoundUp => ceil(*self),
|
||||
num::RoundToZero if is_negative(*self) => ceil(*self),
|
||||
num::RoundToZero if self.is_negative() => ceil(*self),
|
||||
num::RoundToZero => floor(*self),
|
||||
num::RoundFromZero if is_negative(*self) => floor(*self),
|
||||
num::RoundFromZero if self.is_negative() => floor(*self),
|
||||
num::RoundFromZero => ceil(*self)
|
||||
}
|
||||
}
|
||||
@ -376,7 +368,7 @@ impl num::Round for f64 {
|
||||
fn ceil(&self) -> f64 { ceil(*self) }
|
||||
#[inline(always)]
|
||||
fn fract(&self) -> f64 {
|
||||
if is_negative(*self) {
|
||||
if self.is_negative() {
|
||||
(*self) - ceil(*self)
|
||||
} else {
|
||||
(*self) - floor(*self)
|
||||
@ -601,6 +593,50 @@ impl num::FromStrRadix for f64 {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use f64::*;
|
||||
|
||||
#[test]
|
||||
pub fn test_signed() {
|
||||
assert_eq!(infinity.abs(), infinity);
|
||||
assert_eq!(1f64.abs(), 1f64);
|
||||
assert_eq!(0f64.abs(), 0f64);
|
||||
assert_eq!((-0f64).abs(), 0f64);
|
||||
assert_eq!((-1f64).abs(), 1f64);
|
||||
assert_eq!(neg_infinity.abs(), infinity);
|
||||
assert_eq!((1f64/neg_infinity).abs(), 0f64);
|
||||
assert!(is_NaN(NaN.abs()));
|
||||
|
||||
assert_eq!(infinity.signum(), 1f64);
|
||||
assert_eq!(1f64.signum(), 1f64);
|
||||
assert_eq!(0f64.signum(), 1f64);
|
||||
assert_eq!((-0f64).signum(), -1f64);
|
||||
assert_eq!((-1f64).signum(), -1f64);
|
||||
assert_eq!(neg_infinity.signum(), -1f64);
|
||||
assert_eq!((1f64/neg_infinity).signum(), -1f64);
|
||||
assert!(is_NaN(NaN.signum()));
|
||||
|
||||
assert!(infinity.is_positive());
|
||||
assert!(1f64.is_positive());
|
||||
assert!(0f64.is_positive());
|
||||
assert!(!(-0f64).is_positive());
|
||||
assert!(!(-1f64).is_positive());
|
||||
assert!(!neg_infinity.is_positive());
|
||||
assert!(!(1f64/neg_infinity).is_positive());
|
||||
assert!(!NaN.is_positive());
|
||||
|
||||
assert!(!infinity.is_negative());
|
||||
assert!(!1f64.is_negative());
|
||||
assert!(!0f64.is_negative());
|
||||
assert!((-0f64).is_negative());
|
||||
assert!((-1f64).is_negative());
|
||||
assert!(neg_infinity.is_negative());
|
||||
assert!((1f64/neg_infinity).is_negative());
|
||||
assert!(!NaN.is_negative());
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Local Variables:
|
||||
// mode: rust
|
||||
|
@ -22,6 +22,7 @@
|
||||
|
||||
use f64;
|
||||
use num::strconv;
|
||||
use num::Signed;
|
||||
use num;
|
||||
use option::Option;
|
||||
use to_str;
|
||||
@ -42,7 +43,6 @@ pub use f64::{erf, erfc, exp, expm1, exp2, abs_sub};
|
||||
pub use f64::{mul_add, fmax, fmin, nextafter, 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::signbit;
|
||||
pub use f64::{j0, j1, jn, y0, y1, yn};
|
||||
|
||||
pub static NaN: float = 0.0/0.0;
|
||||
@ -348,14 +348,6 @@ pub fn pow_with_uint(base: uint, pow: uint) -> float {
|
||||
return total;
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn is_positive(x: float) -> bool { f64::is_positive(x as f64) }
|
||||
#[inline(always)]
|
||||
pub fn is_negative(x: float) -> bool { f64::is_negative(x as f64) }
|
||||
#[inline(always)]
|
||||
pub fn is_nonpositive(x: float) -> bool { f64::is_nonpositive(x as f64) }
|
||||
#[inline(always)]
|
||||
pub fn is_nonnegative(x: float) -> bool { f64::is_nonnegative(x as f64) }
|
||||
#[inline(always)]
|
||||
pub fn is_zero(x: float) -> bool { f64::is_zero(x as f64) }
|
||||
#[inline(always)]
|
||||
@ -428,11 +420,11 @@ impl num::Round for float {
|
||||
=> f64::floor(*self as f64) as float,
|
||||
num::RoundUp
|
||||
=> f64::ceil(*self as f64) as float,
|
||||
num::RoundToZero if is_negative(*self)
|
||||
num::RoundToZero if self.is_negative()
|
||||
=> f64::ceil(*self as f64) as float,
|
||||
num::RoundToZero
|
||||
=> f64::floor(*self as f64) as float,
|
||||
num::RoundFromZero if is_negative(*self)
|
||||
num::RoundFromZero if self.is_negative()
|
||||
=> f64::floor(*self as f64) as float,
|
||||
num::RoundFromZero
|
||||
=> f64::ceil(*self as f64) as float
|
||||
@ -445,7 +437,7 @@ impl num::Round for float {
|
||||
fn ceil(&self) -> float { f64::ceil(*self as f64) as float}
|
||||
#[inline(always)]
|
||||
fn fract(&self) -> float {
|
||||
if is_negative(*self) {
|
||||
if self.is_negative() {
|
||||
(*self) - (f64::ceil(*self as f64) as float)
|
||||
} else {
|
||||
(*self) - (f64::floor(*self as f64) as float)
|
||||
@ -501,10 +493,76 @@ impl Neg<float> for float {
|
||||
fn neg(&self) -> float { -*self }
|
||||
}
|
||||
|
||||
impl Signed for float {
|
||||
/// Computes the absolute value. Returns `NaN` if the number is `NaN`.
|
||||
#[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
|
||||
*/
|
||||
#[inline(always)]
|
||||
fn signum(&self) -> float {
|
||||
if is_NaN(*self) { NaN } else { f64::copysign(1.0, *self as f64) as float }
|
||||
}
|
||||
|
||||
/// Returns `true` if the number is positive, including `+0.0` and `infinity`
|
||||
#[inline(always)]
|
||||
fn is_positive(&self) -> bool { *self > 0.0 || (1.0 / *self) == infinity }
|
||||
|
||||
/// Returns `true` if the number is negative, including `-0.0` and `neg_infinity`
|
||||
#[inline(always)]
|
||||
fn is_negative(&self) -> bool { *self < 0.0 || (1.0 / *self) == neg_infinity }
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use prelude::*;
|
||||
|
||||
#[test]
|
||||
pub fn test_signed() {
|
||||
assert_eq!(infinity.abs(), infinity);
|
||||
assert_eq!(1f.abs(), 1f);
|
||||
assert_eq!(0f.abs(), 0f);
|
||||
assert_eq!((-0f).abs(), 0f);
|
||||
assert_eq!((-1f).abs(), 1f);
|
||||
assert_eq!(neg_infinity.abs(), infinity);
|
||||
assert_eq!((1f/neg_infinity).abs(), 0f);
|
||||
assert!(is_NaN(NaN.abs()));
|
||||
|
||||
assert_eq!(infinity.signum(), 1f);
|
||||
assert_eq!(1f.signum(), 1f);
|
||||
assert_eq!(0f.signum(), 1f);
|
||||
assert_eq!((-0f).signum(), -1f);
|
||||
assert_eq!((-1f).signum(), -1f);
|
||||
assert_eq!(neg_infinity.signum(), -1f);
|
||||
assert_eq!((1f/neg_infinity).signum(), -1f);
|
||||
assert!(is_NaN(NaN.signum()));
|
||||
|
||||
assert!(infinity.is_positive());
|
||||
assert!(1f.is_positive());
|
||||
assert!(0f.is_positive());
|
||||
assert!(!(-0f).is_positive());
|
||||
assert!(!(-1f).is_positive());
|
||||
assert!(!neg_infinity.is_positive());
|
||||
assert!(!(1f/neg_infinity).is_positive());
|
||||
assert!(!NaN.is_positive());
|
||||
|
||||
assert!(!infinity.is_negative());
|
||||
assert!(!1f.is_negative());
|
||||
assert!(!0f.is_negative());
|
||||
assert!((-0f).is_negative());
|
||||
assert!((-1f).is_negative());
|
||||
assert!(neg_infinity.is_negative());
|
||||
assert!((1f/neg_infinity).is_negative());
|
||||
assert!(!NaN.is_negative());
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn test_to_str_exact_do_decimal() {
|
||||
let s = to_str_exact(5.0, 4u);
|
||||
@ -538,11 +596,11 @@ mod tests {
|
||||
}
|
||||
// note: -0 == 0, hence these slightly more complex tests
|
||||
match from_str(~"-0") {
|
||||
Some(v) if is_zero(v) => assert!(is_negative(v)),
|
||||
Some(v) if is_zero(v) => assert!(v.is_negative()),
|
||||
_ => fail!()
|
||||
}
|
||||
match from_str(~"0") {
|
||||
Some(v) if is_zero(v) => assert!(is_positive(v)),
|
||||
Some(v) if is_zero(v) => assert!(v.is_positive()),
|
||||
_ => fail!()
|
||||
}
|
||||
|
||||
@ -585,11 +643,11 @@ mod tests {
|
||||
}
|
||||
// note: -0 == 0, hence these slightly more complex tests
|
||||
match from_str_hex(~"-0") {
|
||||
Some(v) if is_zero(v) => assert!(is_negative(v)),
|
||||
Some(v) if is_zero(v) => assert!(v.is_negative()),
|
||||
_ => fail!()
|
||||
}
|
||||
match from_str_hex(~"0") {
|
||||
Some(v) if is_zero(v) => assert!(is_positive(v)),
|
||||
Some(v) if is_zero(v) => assert!(v.is_positive()),
|
||||
_ => fail!()
|
||||
}
|
||||
assert_eq!(from_str_hex(~"e"), Some(14.));
|
||||
@ -641,50 +699,6 @@ mod tests {
|
||||
assert_eq!(from_str_radix(~"1000.001", 2u), Some(8.125));
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn test_positive() {
|
||||
assert!(is_positive(infinity));
|
||||
assert!(is_positive(1.));
|
||||
assert!(is_positive(0.));
|
||||
assert!(!is_positive(-1.));
|
||||
assert!(!is_positive(neg_infinity));
|
||||
assert!(!is_positive(1./neg_infinity));
|
||||
assert!(!is_positive(NaN));
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn test_negative() {
|
||||
assert!(!is_negative(infinity));
|
||||
assert!(!is_negative(1.));
|
||||
assert!(!is_negative(0.));
|
||||
assert!(is_negative(-1.));
|
||||
assert!(is_negative(neg_infinity));
|
||||
assert!(is_negative(1./neg_infinity));
|
||||
assert!(!is_negative(NaN));
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn test_nonpositive() {
|
||||
assert!(!is_nonpositive(infinity));
|
||||
assert!(!is_nonpositive(1.));
|
||||
assert!(!is_nonpositive(0.));
|
||||
assert!(is_nonpositive(-1.));
|
||||
assert!(is_nonpositive(neg_infinity));
|
||||
assert!(is_nonpositive(1./neg_infinity));
|
||||
assert!(!is_nonpositive(NaN));
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn test_nonnegative() {
|
||||
assert!(is_nonnegative(infinity));
|
||||
assert!(is_nonnegative(1.));
|
||||
assert!(is_nonnegative(0.));
|
||||
assert!(!is_nonnegative(-1.));
|
||||
assert!(!is_nonnegative(neg_infinity));
|
||||
assert!(!is_nonnegative(1./neg_infinity));
|
||||
assert!(!is_nonnegative(NaN));
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn test_to_str_inf() {
|
||||
assert_eq!(to_str_digits(infinity, 10u), ~"inf");
|
||||
|
@ -14,6 +14,7 @@ use to_str::ToStr;
|
||||
use from_str::FromStr;
|
||||
use num::{ToStrRadix, FromStrRadix};
|
||||
use num::strconv;
|
||||
use num::Signed;
|
||||
use num;
|
||||
use prelude::*;
|
||||
|
||||
@ -70,15 +71,6 @@ pub fn ge(x: T, y: T) -> bool { x >= y }
|
||||
#[inline(always)]
|
||||
pub fn gt(x: T, y: T) -> bool { x > y }
|
||||
|
||||
#[inline(always)]
|
||||
pub fn is_positive(x: T) -> bool { x > 0 as T }
|
||||
#[inline(always)]
|
||||
pub fn is_negative(x: T) -> bool { x < 0 as T }
|
||||
#[inline(always)]
|
||||
pub fn is_nonpositive(x: T) -> bool { x <= 0 as T }
|
||||
#[inline(always)]
|
||||
pub fn is_nonnegative(x: T) -> bool { x >= 0 as T }
|
||||
|
||||
/**
|
||||
* Iterate over the range [`lo`..`hi`)
|
||||
*
|
||||
@ -139,9 +131,7 @@ pub fn compl(i: T) -> T {
|
||||
|
||||
/// Computes the absolute value
|
||||
#[inline(always)]
|
||||
pub fn abs(i: T) -> T {
|
||||
if is_negative(i) { -i } else { i }
|
||||
}
|
||||
pub fn abs(i: T) -> T { i.abs() }
|
||||
|
||||
#[cfg(notest)]
|
||||
impl Ord for T {
|
||||
@ -201,6 +191,24 @@ impl Div<T,T> for T {
|
||||
#[cfg(stage2,notest)]
|
||||
#[cfg(stage3,notest)]
|
||||
impl Quot<T,T> for T {
|
||||
/**
|
||||
* Returns the integer quotient, truncated towards 0. As this behaviour reflects
|
||||
* the underlying machine implementation it is more efficient than `Natural::div`.
|
||||
*
|
||||
* # Examples
|
||||
*
|
||||
* ~~~
|
||||
* assert!( 8 / 3 == 2);
|
||||
* assert!( 8 / -3 == -2);
|
||||
* assert!(-8 / 3 == -2);
|
||||
* assert!(-8 / -3 == 2);
|
||||
|
||||
* 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 }
|
||||
}
|
||||
@ -215,6 +223,27 @@ impl Modulo<T,T> for T {
|
||||
#[cfg(stage2,notest)]
|
||||
#[cfg(stage3,notest)]
|
||||
impl Rem<T,T> for T {
|
||||
/**
|
||||
* Returns the integer remainder after division, satisfying:
|
||||
*
|
||||
* ~~~
|
||||
* assert!((n / d) * d + (n % d) == n)
|
||||
* ~~~
|
||||
*
|
||||
* # Examples
|
||||
*
|
||||
* ~~~
|
||||
* assert!( 8 % 3 == 2);
|
||||
* assert!( 8 % -3 == 2);
|
||||
* assert!(-8 % 3 == -2);
|
||||
* assert!(-8 % -3 == -2);
|
||||
|
||||
* 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 }
|
||||
}
|
||||
@ -225,6 +254,155 @@ impl Neg<T> for T {
|
||||
fn neg(&self) -> T { -*self }
|
||||
}
|
||||
|
||||
impl Signed for T {
|
||||
/// Computes the absolute value
|
||||
#[inline(always)]
|
||||
fn abs(&self) -> 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
|
||||
*/
|
||||
#[inline(always)]
|
||||
fn signum(&self) -> T {
|
||||
match *self {
|
||||
n if n > 0 => 1,
|
||||
0 => 0,
|
||||
_ => -1,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns true if the number is positive
|
||||
#[inline(always)]
|
||||
fn is_positive(&self) -> bool { *self > 0 }
|
||||
|
||||
/// Returns true if the number is negative
|
||||
#[inline(always)]
|
||||
fn is_negative(&self) -> bool { *self < 0 }
|
||||
}
|
||||
|
||||
impl Natural 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);
|
||||
* ~~~
|
||||
*/
|
||||
#[inline(always)]
|
||||
fn div(&self, other: T) -> T {
|
||||
// Algorithm from [Daan Leijen. _Division and Modulus for Computer Scientists_,
|
||||
// December 2001](http://research.microsoft.com/pubs/151917/divmodnote-letter.pdf)
|
||||
match self.quot_rem(other) {
|
||||
(q, r) if (r > 0 && other < 0)
|
||||
|| (r < 0 && other > 0) => q - 1,
|
||||
(q, _) => q,
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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_,
|
||||
// December 2001](http://research.microsoft.com/pubs/151917/divmodnote-letter.pdf)
|
||||
match *self % other {
|
||||
r if (r > 0 && other < 0)
|
||||
|| (r < 0 && other > 0) => r + other,
|
||||
r => r,
|
||||
}
|
||||
}
|
||||
|
||||
/// Calculates `div` and `modulo` simultaneously
|
||||
#[inline(always)]
|
||||
fn div_mod(&self, other: T) -> (T,T) {
|
||||
// Algorithm from [Daan Leijen. _Division and Modulus for Computer Scientists_,
|
||||
// December 2001](http://research.microsoft.com/pubs/151917/divmodnote-letter.pdf)
|
||||
match self.quot_rem(other) {
|
||||
(q, r) if (r > 0 && other < 0)
|
||||
|| (r < 0 && other > 0) => (q - 1, r + other),
|
||||
(q, r) => (q, r),
|
||||
}
|
||||
}
|
||||
|
||||
/// Calculates `quot` (`\`) and `rem` (`%`) simultaneously
|
||||
#[inline(always)]
|
||||
fn quot_rem(&self, other: T) -> (T,T) {
|
||||
(*self / other, *self % other)
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
let mut m = *self, n = other;
|
||||
while m != 0 {
|
||||
let temp = m;
|
||||
m = n % temp;
|
||||
n = temp;
|
||||
}
|
||||
n.abs()
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
}
|
||||
|
||||
/// Returns `true` if the number can be divided by `other` without leaving a remainder
|
||||
#[inline(always)]
|
||||
fn divisible_by(&self, other: T) -> bool { *self % other == 0 }
|
||||
|
||||
/// Returns `true` if the number is divisible by `2`
|
||||
#[inline(always)]
|
||||
fn is_even(&self) -> bool { self.divisible_by(2) }
|
||||
|
||||
/// Returns `true` if the number is not divisible by `2`
|
||||
#[inline(always)]
|
||||
fn is_odd(&self) -> bool { !self.is_even() }
|
||||
}
|
||||
|
||||
#[cfg(notest)]
|
||||
impl BitOr<T,T> for T {
|
||||
#[inline(always)]
|
||||
@ -344,6 +522,117 @@ mod tests {
|
||||
use super::inst::T;
|
||||
use prelude::*;
|
||||
|
||||
#[test]
|
||||
pub fn test_signed() {
|
||||
assert_eq!((1 as T).abs(), 1 as T);
|
||||
assert_eq!((0 as T).abs(), 0 as T);
|
||||
assert_eq!((-1 as T).abs(), 1 as T);
|
||||
|
||||
assert_eq!((1 as T).signum(), 1 as T);
|
||||
assert_eq!((0 as T).signum(), 0 as T);
|
||||
assert_eq!((-0 as T).signum(), 0 as T);
|
||||
assert_eq!((-1 as T).signum(), -1 as T);
|
||||
|
||||
assert!((1 as T).is_positive());
|
||||
assert!(!(0 as T).is_positive());
|
||||
assert!(!(-0 as T).is_positive());
|
||||
assert!(!(-1 as T).is_positive());
|
||||
|
||||
assert!(!(1 as T).is_negative());
|
||||
assert!(!(0 as T).is_negative());
|
||||
assert!(!(-0 as T).is_negative());
|
||||
assert!((-1 as T).is_negative());
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that the division rule holds for:
|
||||
*
|
||||
* - `n`: numerator (dividend)
|
||||
* - `d`: denominator (divisor)
|
||||
* - `qr`: quotient and remainder
|
||||
*/
|
||||
#[cfg(test)]
|
||||
fn test_division_rule(nd: (T,T), qr: (T,T)) {
|
||||
let (n,d) = nd,
|
||||
(q,r) = qr;
|
||||
|
||||
assert_eq!(d * q + r, n);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_quot_rem() {
|
||||
fn test_nd_qr(nd: (T,T), qr: (T,T)) {
|
||||
let (n,d) = nd;
|
||||
let separate_quot_rem = (n / d, n % d);
|
||||
let combined_quot_rem = n.quot_rem(d);
|
||||
|
||||
assert_eq!(separate_quot_rem, qr);
|
||||
assert_eq!(combined_quot_rem, qr);
|
||||
|
||||
test_division_rule(nd, separate_quot_rem);
|
||||
test_division_rule(nd, combined_quot_rem);
|
||||
}
|
||||
|
||||
test_nd_qr(( 8, 3), ( 2, 2));
|
||||
test_nd_qr(( 8, -3), (-2, 2));
|
||||
test_nd_qr((-8, 3), (-2, -2));
|
||||
test_nd_qr((-8, -3), ( 2, -2));
|
||||
|
||||
test_nd_qr(( 1, 2), ( 0, 1));
|
||||
test_nd_qr(( 1, -2), ( 0, 1));
|
||||
test_nd_qr((-1, 2), ( 0, -1));
|
||||
test_nd_qr((-1, -2), ( 0, -1));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_div_mod() {
|
||||
fn test_nd_dm(nd: (T,T), dm: (T,T)) {
|
||||
let (n,d) = nd;
|
||||
let separate_div_mod = (n.div(d), n.modulo(d));
|
||||
let combined_div_mod = n.div_mod(d);
|
||||
|
||||
assert_eq!(separate_div_mod, dm);
|
||||
assert_eq!(combined_div_mod, dm);
|
||||
|
||||
test_division_rule(nd, separate_div_mod);
|
||||
test_division_rule(nd, combined_div_mod);
|
||||
}
|
||||
|
||||
test_nd_dm(( 8, 3), ( 2, 2));
|
||||
test_nd_dm(( 8, -3), (-3, -1));
|
||||
test_nd_dm((-8, 3), (-3, 1));
|
||||
test_nd_dm((-8, -3), ( 2, -2));
|
||||
|
||||
test_nd_dm(( 1, 2), ( 0, 1));
|
||||
test_nd_dm(( 1, -2), (-1, -1));
|
||||
test_nd_dm((-1, 2), (-1, 1));
|
||||
test_nd_dm((-1, -2), ( 0, -1));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_gcd() {
|
||||
assert_eq!((10 as T).gcd(2), 2 as T);
|
||||
assert_eq!((10 as T).gcd(3), 1 as T);
|
||||
assert_eq!((0 as T).gcd(3), 3 as T);
|
||||
assert_eq!((3 as T).gcd(3), 3 as T);
|
||||
assert_eq!((56 as T).gcd(42), 14 as T);
|
||||
assert_eq!((3 as T).gcd(-3), 3 as T);
|
||||
assert_eq!((-6 as T).gcd(3), 3 as T);
|
||||
assert_eq!((-4 as T).gcd(-2), 2 as T);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_lcm() {
|
||||
assert_eq!((1 as T).lcm(0), 0 as T);
|
||||
assert_eq!((0 as T).lcm(1), 0 as T);
|
||||
assert_eq!((1 as T).lcm(1), 1 as T);
|
||||
assert_eq!((-1 as T).lcm(1), 1 as T);
|
||||
assert_eq!((1 as T).lcm(-1), 1 as T);
|
||||
assert_eq!((-1 as T).lcm(-1), 1 as T);
|
||||
assert_eq!((8 as T).lcm(9), 72 as T);
|
||||
assert_eq!((11 as T).lcm(5), 55 as T);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_bitwise_ops() {
|
||||
assert_eq!(0b1110 as T, (0b1100 as T).bitor(&(0b1010 as T)));
|
||||
|
@ -60,10 +60,37 @@ pub trait One {
|
||||
fn one() -> Self;
|
||||
}
|
||||
|
||||
pub trait Signed: Num
|
||||
+ Neg<Self> {
|
||||
fn abs(&self) -> Self;
|
||||
fn signum(&self) -> Self;
|
||||
fn is_positive(&self) -> bool;
|
||||
fn is_negative(&self) -> bool;
|
||||
}
|
||||
|
||||
pub trait Unsigned: Num {}
|
||||
|
||||
// This should be moved into the default implementation for Signed::abs
|
||||
pub fn abs<T:Ord + Zero + Neg<T>>(v: T) -> T {
|
||||
if v < Zero::zero() { v.neg() } else { v }
|
||||
}
|
||||
|
||||
pub trait Natural: Num
|
||||
+ Ord
|
||||
+ Quot<Self,Self>
|
||||
+ Rem<Self,Self> {
|
||||
fn div(&self, other: Self) -> Self;
|
||||
fn modulo(&self, other: Self) -> Self;
|
||||
fn div_mod(&self, other: Self) -> (Self,Self);
|
||||
fn quot_rem(&self, other: Self) -> (Self,Self);
|
||||
|
||||
fn gcd(&self, other: Self) -> Self;
|
||||
fn lcm(&self, other: Self) -> Self;
|
||||
fn divisible_by(&self, other: Self) -> bool;
|
||||
fn is_even(&self) -> bool;
|
||||
fn is_odd(&self) -> bool;
|
||||
}
|
||||
|
||||
pub trait Round {
|
||||
fn round(&self, mode: RoundMode) -> Self;
|
||||
|
||||
|
@ -15,6 +15,7 @@ use to_str::ToStr;
|
||||
use from_str::FromStr;
|
||||
use num::{ToStrRadix, FromStrRadix};
|
||||
use num::strconv;
|
||||
use num::Unsigned;
|
||||
use num;
|
||||
use option::Option;
|
||||
use prelude::*;
|
||||
@ -51,15 +52,6 @@ pub fn ge(x: T, y: T) -> bool { x >= y }
|
||||
#[inline(always)]
|
||||
pub fn gt(x: T, y: T) -> bool { x > y }
|
||||
|
||||
#[inline(always)]
|
||||
pub fn is_positive(x: T) -> bool { x > 0 as T }
|
||||
#[inline(always)]
|
||||
pub fn is_negative(x: T) -> bool { x < 0 as T }
|
||||
#[inline(always)]
|
||||
pub fn is_nonpositive(x: T) -> bool { x <= 0 as T }
|
||||
#[inline(always)]
|
||||
pub fn is_nonnegative(x: T) -> bool { x >= 0 as T }
|
||||
|
||||
#[inline(always)]
|
||||
/**
|
||||
* Iterate over the range [`start`,`start`+`step`..`stop`)
|
||||
@ -190,6 +182,61 @@ impl Neg<T> for T {
|
||||
fn neg(&self) -> T { -*self }
|
||||
}
|
||||
|
||||
impl Unsigned for T {}
|
||||
|
||||
impl Natural for T {
|
||||
/// Unsigned integer division. Returns the same result as `quot` (`/`).
|
||||
#[inline(always)]
|
||||
fn div(&self, other: T) -> T { *self / other }
|
||||
|
||||
/// Unsigned integer modulo operation. Returns the same result as `rem` (`%`).
|
||||
#[inline(always)]
|
||||
fn modulo(&self, other: T) -> T { *self / other }
|
||||
|
||||
/// Calculates `div` and `modulo` simultaneously
|
||||
#[inline(always)]
|
||||
fn div_mod(&self, other: T) -> (T,T) {
|
||||
(*self / other, *self % other)
|
||||
}
|
||||
|
||||
/// Calculates `quot` (`\`) and `rem` (`%`) simultaneously
|
||||
#[inline(always)]
|
||||
fn quot_rem(&self, other: T) -> (T,T) {
|
||||
(*self / other, *self % other)
|
||||
}
|
||||
|
||||
/// Calculates the Greatest Common Divisor (GCD) of the number and `other`
|
||||
#[inline(always)]
|
||||
fn gcd(&self, other: T) -> T {
|
||||
// Use Euclid's algorithm
|
||||
let mut m = *self, n = other;
|
||||
while m != 0 {
|
||||
let temp = m;
|
||||
m = n % temp;
|
||||
n = temp;
|
||||
}
|
||||
n
|
||||
}
|
||||
|
||||
/// Calculates the Lowest Common Multiple (LCM) of the number and `other`
|
||||
#[inline(always)]
|
||||
fn lcm(&self, other: T) -> T {
|
||||
(*self * other) / self.gcd(other)
|
||||
}
|
||||
|
||||
/// Returns `true` if the number can be divided by `other` without leaving a remainder
|
||||
#[inline(always)]
|
||||
fn divisible_by(&self, other: T) -> bool { *self % other == 0 }
|
||||
|
||||
/// Returns `true` if the number is divisible by `2`
|
||||
#[inline(always)]
|
||||
fn is_even(&self) -> bool { self.divisible_by(2) }
|
||||
|
||||
/// Returns `true` if the number is not divisible by `2`
|
||||
#[inline(always)]
|
||||
fn is_odd(&self) -> bool { !self.is_even() }
|
||||
}
|
||||
|
||||
#[cfg(notest)]
|
||||
impl BitOr<T,T> for T {
|
||||
#[inline(always)]
|
||||
@ -309,6 +356,25 @@ mod tests {
|
||||
use super::inst::T;
|
||||
use prelude::*;
|
||||
|
||||
#[test]
|
||||
fn test_gcd() {
|
||||
assert_eq!((10 as T).gcd(2), 2 as T);
|
||||
assert_eq!((10 as T).gcd(3), 1 as T);
|
||||
assert_eq!((0 as T).gcd(3), 3 as T);
|
||||
assert_eq!((3 as T).gcd(3), 3 as T);
|
||||
assert_eq!((56 as T).gcd(42), 14 as T);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_lcm() {
|
||||
assert_eq!((1 as T).lcm(0), 0 as T);
|
||||
assert_eq!((0 as T).lcm(1), 0 as T);
|
||||
assert_eq!((1 as T).lcm(1), 1 as T);
|
||||
assert_eq!((8 as T).lcm(9), 72 as T);
|
||||
assert_eq!((11 as T).lcm(5), 55 as T);
|
||||
assert_eq!((99 as T).lcm(17), 1683 as T);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_bitwise_ops() {
|
||||
assert_eq!(0b1110 as T, (0b1100 as T).bitor(&(0b1010 as T)));
|
||||
|
@ -39,7 +39,7 @@ pub use hash::Hash;
|
||||
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::{Num, Signed, Unsigned, Natural, NumCast};
|
||||
pub use path::GenericPath;
|
||||
pub use path::Path;
|
||||
pub use path::PosixPath;
|
||||
|
@ -299,9 +299,9 @@ pub fn eval_const_expr_partial(tcx: middle::ty::ctxt, e: @expr)
|
||||
add => Ok(const_int(a + b)),
|
||||
subtract => Ok(const_int(a - b)),
|
||||
mul => Ok(const_int(a * b)),
|
||||
quot if b == 0 => Err(~"quotient zero"),
|
||||
quot if b == 0 => Err(~"attempted quotient with a divisor of zero"),
|
||||
quot => Ok(const_int(a / b)),
|
||||
rem if b == 0 => Err(~"remainder zero"),
|
||||
rem if b == 0 => Err(~"attempted remainder with a divisor of zero"),
|
||||
rem => Ok(const_int(a % b)),
|
||||
and | bitand => Ok(const_int(a & b)),
|
||||
or | bitor => Ok(const_int(a | b)),
|
||||
@ -321,9 +321,9 @@ pub fn eval_const_expr_partial(tcx: middle::ty::ctxt, e: @expr)
|
||||
add => Ok(const_uint(a + b)),
|
||||
subtract => Ok(const_uint(a - b)),
|
||||
mul => Ok(const_uint(a * b)),
|
||||
quot if b == 0 => Err(~"quotient zero"),
|
||||
quot if b == 0 => Err(~"attempted quotient with a divisor of zero"),
|
||||
quot => Ok(const_uint(a / b)),
|
||||
rem if b == 0 => Err(~"remainder zero"),
|
||||
rem if b == 0 => Err(~"attempted remainder with a divisor of zero"),
|
||||
rem => Ok(const_uint(a % b)),
|
||||
and | bitand => Ok(const_uint(a & b)),
|
||||
or | bitor => Ok(const_uint(a | b)),
|
||||
|
@ -785,9 +785,9 @@ pub fn cast_shift_rhs(op: ast::binop,
|
||||
pub fn fail_if_zero(cx: block, span: span, quotrem: ast::binop,
|
||||
rhs: ValueRef, rhs_t: ty::t) -> block {
|
||||
let text = if quotrem == ast::quot {
|
||||
@~"quotient zero"
|
||||
@~"attempted quotient with a divisor of zero"
|
||||
} else {
|
||||
@~"remainder zero"
|
||||
@~"attempted remainder with a divisor of zero"
|
||||
};
|
||||
let is_zero = match ty::get(rhs_t).sty {
|
||||
ty::ty_int(t) => {
|
||||
|
@ -154,6 +154,8 @@ impl One for BigUint {
|
||||
pub fn one() -> BigUint { BigUint::new(~[1]) }
|
||||
}
|
||||
|
||||
impl Unsigned for BigUint {}
|
||||
|
||||
impl Add<BigUint, BigUint> for BigUint {
|
||||
fn add(&self, other: &BigUint) -> BigUint {
|
||||
let new_len = uint::max(self.data.len(), other.data.len());
|
||||
@ -469,11 +471,8 @@ pub impl BigUint {
|
||||
}
|
||||
|
||||
fn is_zero(&self) -> bool { self.data.is_empty() }
|
||||
|
||||
fn is_not_zero(&self) -> bool { !self.data.is_empty() }
|
||||
fn is_positive(&self) -> bool { self.is_not_zero() }
|
||||
fn is_negative(&self) -> bool { false }
|
||||
fn is_nonpositive(&self) -> bool { self.is_zero() }
|
||||
fn is_nonnegative(&self) -> bool { true }
|
||||
|
||||
fn to_uint(&self) -> uint {
|
||||
match self.data.len() {
|
||||
@ -693,6 +692,27 @@ impl One for BigInt {
|
||||
}
|
||||
}
|
||||
|
||||
impl Signed for BigInt {
|
||||
fn abs(&self) -> BigInt {
|
||||
match self.sign {
|
||||
Plus | Zero => copy *self,
|
||||
Minus => BigInt::from_biguint(Plus, copy self.data)
|
||||
}
|
||||
}
|
||||
|
||||
fn signum(&self) -> BigInt {
|
||||
match self.sign {
|
||||
Plus => BigInt::from_biguint(Plus, One::one()),
|
||||
Minus => BigInt::from_biguint(Minus, One::one()),
|
||||
Zero => Zero::zero(),
|
||||
}
|
||||
}
|
||||
|
||||
fn is_positive(&self) -> bool { self.sign == Plus }
|
||||
|
||||
fn is_negative(&self) -> bool { self.sign == Minus }
|
||||
}
|
||||
|
||||
impl Add<BigInt, BigInt> for BigInt {
|
||||
fn add(&self, other: &BigInt) -> BigInt {
|
||||
match (self.sign, other.sign) {
|
||||
@ -888,11 +908,8 @@ pub impl BigInt {
|
||||
}
|
||||
|
||||
fn is_zero(&self) -> bool { self.sign == Zero }
|
||||
|
||||
fn is_not_zero(&self) -> bool { self.sign != Zero }
|
||||
fn is_positive(&self) -> bool { self.sign == Plus }
|
||||
fn is_negative(&self) -> bool { self.sign == Minus }
|
||||
fn is_nonpositive(&self) -> bool { self.sign != Plus }
|
||||
fn is_nonnegative(&self) -> bool { self.sign != Minus }
|
||||
|
||||
fn to_uint(&self) -> uint {
|
||||
match self.sign {
|
||||
|
@ -1,6 +1,6 @@
|
||||
enum test {
|
||||
quot_zero = 1/0, //~ERROR expected constant: quotient zero
|
||||
rem_zero = 1%0 //~ERROR expected constant: remainder zero
|
||||
quot_zero = 1/0, //~ERROR expected constant: attempted quotient with a divisor of zero
|
||||
rem_zero = 1%0 //~ERROR expected constant: attempted remainder with a divisor of zero
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
@ -8,7 +8,7 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// error-pattern:quotient zero
|
||||
// error-pattern:attempted quotient with a divisor of zero
|
||||
fn main() {
|
||||
let y = 0;
|
||||
let z = 1 / y;
|
||||
|
@ -8,7 +8,7 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// error-pattern:remainder zero
|
||||
// error-pattern:attempted remainder with a divisor of zero
|
||||
fn main() {
|
||||
let y = 0;
|
||||
let z = 1 % y;
|
||||
|
@ -18,28 +18,28 @@ pub fn main() {
|
||||
}
|
||||
|
||||
// Usable at all:
|
||||
let mut any_negative = do vec::any(v) |e| { float::is_negative(*e) };
|
||||
let mut any_negative = do vec::any(v) |e| { e.is_negative() };
|
||||
assert!(any_negative);
|
||||
|
||||
// Higher precedence than assignments:
|
||||
any_negative = do vec::any(v) |e| { float::is_negative(*e) };
|
||||
any_negative = do vec::any(v) |e| { e.is_negative() };
|
||||
assert!(any_negative);
|
||||
|
||||
// Higher precedence than unary operations:
|
||||
let abs_v = do vec::map(v) |e| { float::abs(*e) };
|
||||
assert!(do vec::all(abs_v) |e| { float::is_nonnegative(*e) });
|
||||
assert!(!do vec::any(abs_v) |e| { float::is_negative(*e) });
|
||||
let abs_v = do vec::map(v) |e| { e.abs() };
|
||||
assert!(do vec::all(abs_v) |e| { e.is_positive() });
|
||||
assert!(!do vec::any(abs_v) |e| { e.is_negative() });
|
||||
|
||||
// Usable in funny statement-like forms:
|
||||
if !do vec::any(v) |e| { float::is_positive(*e) } {
|
||||
if !do vec::any(v) |e| { e.is_positive() } {
|
||||
assert!(false);
|
||||
}
|
||||
match do vec::all(v) |e| { float::is_negative(*e) } {
|
||||
match do vec::all(v) |e| { e.is_negative() } {
|
||||
true => { fail!(~"incorrect answer."); }
|
||||
false => { }
|
||||
}
|
||||
match 3 {
|
||||
_ if do vec::any(v) |e| { float::is_negative(*e) } => {
|
||||
_ if do vec::any(v) |e| { e.is_negative() } => {
|
||||
}
|
||||
_ => {
|
||||
fail!(~"wrong answer.");
|
||||
@ -56,7 +56,7 @@ pub fn main() {
|
||||
|
||||
// In the tail of a block
|
||||
let w =
|
||||
if true { do vec::any(abs_v) |e| { float::is_nonnegative(*e) } }
|
||||
if true { do vec::any(abs_v) |e| { e.is_positive() } }
|
||||
else { false };
|
||||
assert!(w);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user