提交 aef24905 编写于 作者: B Brendan Zabarauskas

Implement Signed and Unsigned traits and remove related predicate functions

上级 706096b3
......@@ -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, 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 is_NaN(f: f32) -> bool { f != f }
// 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 @@ fn floor(&self) -> f32 { floor(*self) }
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 @@ fn from_str_radix(val: &str, rdx: uint) -> Option<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 is_NaN(f: f64) -> bool { f != f }
#[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 @@ fn floor(&self) -> f64 { floor(*self) }
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 @@ fn from_str_radix(val: &str, rdx: uint) -> Option<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::{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 @@ fn round(&self, mode: num::RoundMode) -> 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 @@ fn floor(&self) -> float { f64::floor(*self as f64) as 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 @@ pub fn test_from_str() {
}
// 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 @@ pub fn test_from_str_hex() {
}
// 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 @@ pub fn test_from_str_radix() {
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 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 {
......@@ -225,6 +215,38 @@ 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 }
}
#[cfg(notest)]
impl BitOr<T,T> for T {
#[inline(always)]
......@@ -344,6 +366,28 @@ 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());
}
#[test]
fn test_bitwise_ops() {
assert_eq!(0b1110 as T, (0b1100 as T).bitor(&(0b1010 as T)));
......
......@@ -60,6 +60,17 @@ 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 }
}
......
......@@ -15,6 +15,7 @@
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,8 @@ impl Neg<T> for T {
fn neg(&self) -> T { -*self }
}
impl Unsigned for T {}
#[cfg(notest)]
impl BitOr<T,T> for T {
#[inline(always)]
......
......@@ -39,7 +39,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::{Num, Signed, Unsigned, NumCast};
pub use path::GenericPath;
pub use path::Path;
pub use path::PosixPath;
......
......@@ -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 @@ fn quot_rem(&self, other: &BigUint) -> (BigUint, 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 @@ pub fn one() -> 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 @@ fn quot_rem(&self, other: &BigInt) -> (BigInt, 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 {
......
......@@ -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);
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册