Skip to content

Commit c8ac057

Browse files
committed
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.
2 parents 706096b + ab8068c commit c8ac057

File tree

15 files changed

+671
-188
lines changed

15 files changed

+671
-188
lines changed

Diff for: src/libcore/core.rc

+1-1
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ pub use iter::{BaseIter, ExtendedIter, EqIter, CopyableIter};
105105
pub use iter::{CopyableOrderedIter, CopyableNonstrictIter, Times};
106106
pub use iter::{ExtendedMutableIter};
107107

108-
pub use num::{Num, NumCast};
108+
pub use num::{Num, Signed, Unsigned, Natural, NumCast};
109109
pub use ptr::Ptr;
110110
pub use to_str::ToStr;
111111
pub use clone::Clone;

Diff for: src/libcore/num/f32.rs

+74-40
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
//! Operations and constants for `f32`
1212
1313
use num::strconv;
14+
use num::Signed;
1415
use num;
1516
use option::Option;
1617
use from_str;
@@ -163,38 +164,6 @@ pub fn gt(x: f32, y: f32) -> bool { return x > y; }
163164
// FIXME (#1999): replace the predicates below with llvm intrinsics or
164165
// calls to the libmath macros in the rust runtime for performance.
165166

166-
/// Returns true if `x` is a positive number, including +0.0f320 and +Infinity
167-
#[inline(always)]
168-
pub fn is_positive(x: f32) -> bool {
169-
x > 0.0f32 || (1.0f32/x) == infinity
170-
}
171-
172-
/// Returns true if `x` is a negative number, including -0.0f320 and -Infinity
173-
#[inline(always)]
174-
pub fn is_negative(x: f32) -> bool {
175-
x < 0.0f32 || (1.0f32/x) == neg_infinity
176-
}
177-
178-
/**
179-
* Returns true if `x` is a negative number, including -0.0f320 and -Infinity
180-
*
181-
* This is the same as `f32::is_negative`.
182-
*/
183-
#[inline(always)]
184-
pub fn is_nonpositive(x: f32) -> bool {
185-
return x < 0.0f32 || (1.0f32/x) == neg_infinity;
186-
}
187-
188-
/**
189-
* Returns true if `x` is a positive number, including +0.0f320 and +Infinity
190-
*
191-
* This is the same as `f32::is_positive`.)
192-
*/
193-
#[inline(always)]
194-
pub fn is_nonnegative(x: f32) -> bool {
195-
return x > 0.0f32 || (1.0f32/x) == infinity;
196-
}
197-
198167
/// Returns true if `x` is a zero number (positive or negative zero)
199168
#[inline(always)]
200169
pub fn is_zero(x: f32) -> bool {
@@ -259,11 +228,6 @@ pub mod consts {
259228
pub static ln_10: f32 = 2.30258509299404568401799145468436421_f32;
260229
}
261230

262-
#[inline(always)]
263-
pub fn signbit(x: f32) -> int {
264-
if is_negative(x) { return 1; } else { return 0; }
265-
}
266-
267231
#[inline(always)]
268232
pub fn logarithm(n: f32, b: f32) -> f32 {
269233
return log2(n) / log2(b);
@@ -351,15 +315,41 @@ impl Neg<f32> for f32 {
351315
fn neg(&self) -> f32 { -*self }
352316
}
353317

318+
impl Signed for f32 {
319+
/// Computes the absolute value. Returns `NaN` if the number is `NaN`.
320+
#[inline(always)]
321+
fn abs(&self) -> f32 { abs(*self) }
322+
323+
/**
324+
* # Returns
325+
*
326+
* - `1.0` if the number is positive, `+0.0` or `infinity`
327+
* - `-1.0` if the number is negative, `-0.0` or `neg_infinity`
328+
* - `NaN` if the number is `NaN`
329+
*/
330+
#[inline(always)]
331+
fn signum(&self) -> f32 {
332+
if is_NaN(*self) { NaN } else { copysign(1.0, *self) }
333+
}
334+
335+
/// Returns `true` if the number is positive, including `+0.0` and `infinity`
336+
#[inline(always)]
337+
fn is_positive(&self) -> bool { *self > 0.0 || (1.0 / *self) == infinity }
338+
339+
/// Returns `true` if the number is negative, including `-0.0` and `neg_infinity`
340+
#[inline(always)]
341+
fn is_negative(&self) -> bool { *self < 0.0 || (1.0 / *self) == neg_infinity }
342+
}
343+
354344
impl num::Round for f32 {
355345
#[inline(always)]
356346
fn round(&self, mode: num::RoundMode) -> f32 {
357347
match mode {
358348
num::RoundDown => floor(*self),
359349
num::RoundUp => ceil(*self),
360-
num::RoundToZero if is_negative(*self) => ceil(*self),
350+
num::RoundToZero if self.is_negative() => ceil(*self),
361351
num::RoundToZero => floor(*self),
362-
num::RoundFromZero if is_negative(*self) => floor(*self),
352+
num::RoundFromZero if self.is_negative() => floor(*self),
363353
num::RoundFromZero => ceil(*self)
364354
}
365355
}
@@ -370,7 +360,7 @@ impl num::Round for f32 {
370360
fn ceil(&self) -> f32 { ceil(*self) }
371361
#[inline(always)]
372362
fn fract(&self) -> f32 {
373-
if is_negative(*self) {
363+
if self.is_negative() {
374364
(*self) - ceil(*self)
375365
} else {
376366
(*self) - floor(*self)
@@ -595,6 +585,50 @@ impl num::FromStrRadix for f32 {
595585
}
596586
}
597587

588+
#[cfg(test)]
589+
mod tests {
590+
use f32::*;
591+
592+
#[test]
593+
pub fn test_signed() {
594+
assert_eq!(infinity.abs(), infinity);
595+
assert_eq!(1f32.abs(), 1f32);
596+
assert_eq!(0f32.abs(), 0f32);
597+
assert_eq!((-0f32).abs(), 0f32);
598+
assert_eq!((-1f32).abs(), 1f32);
599+
assert_eq!(neg_infinity.abs(), infinity);
600+
assert_eq!((1f32/neg_infinity).abs(), 0f32);
601+
assert!(is_NaN(NaN.abs()));
602+
603+
assert_eq!(infinity.signum(), 1f32);
604+
assert_eq!(1f32.signum(), 1f32);
605+
assert_eq!(0f32.signum(), 1f32);
606+
assert_eq!((-0f32).signum(), -1f32);
607+
assert_eq!((-1f32).signum(), -1f32);
608+
assert_eq!(neg_infinity.signum(), -1f32);
609+
assert_eq!((1f32/neg_infinity).signum(), -1f32);
610+
assert!(is_NaN(NaN.signum()));
611+
612+
assert!(infinity.is_positive());
613+
assert!(1f32.is_positive());
614+
assert!(0f32.is_positive());
615+
assert!(!(-0f32).is_positive());
616+
assert!(!(-1f32).is_positive());
617+
assert!(!neg_infinity.is_positive());
618+
assert!(!(1f32/neg_infinity).is_positive());
619+
assert!(!NaN.is_positive());
620+
621+
assert!(!infinity.is_negative());
622+
assert!(!1f32.is_negative());
623+
assert!(!0f32.is_negative());
624+
assert!((-0f32).is_negative());
625+
assert!((-1f32).is_negative());
626+
assert!(neg_infinity.is_negative());
627+
assert!((1f32/neg_infinity).is_negative());
628+
assert!(!NaN.is_negative());
629+
}
630+
}
631+
598632
//
599633
// Local Variables:
600634
// mode: rust

Diff for: src/libcore/num/f64.rs

+74-38
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
//! Operations and constants for `f64`
1212
1313
use num::strconv;
14+
use num::Signed;
1415
use num;
1516
use option::Option;
1617
use to_str;
@@ -183,36 +184,6 @@ pub fn ge(x: f64, y: f64) -> bool { return x >= y; }
183184
#[inline(always)]
184185
pub fn gt(x: f64, y: f64) -> bool { return x > y; }
185186

186-
/// Returns true if `x` is a positive number, including +0.0f640 and +Infinity
187-
#[inline(always)]
188-
pub fn is_positive(x: f64) -> bool
189-
{ return x > 0.0f64 || (1.0f64/x) == infinity; }
190-
191-
/// Returns true if `x` is a negative number, including -0.0f640 and -Infinity
192-
#[inline(always)]
193-
pub fn is_negative(x: f64) -> bool
194-
{ return x < 0.0f64 || (1.0f64/x) == neg_infinity; }
195-
196-
/**
197-
* Returns true if `x` is a negative number, including -0.0f640 and -Infinity
198-
*
199-
* This is the same as `f64::is_negative`.
200-
*/
201-
#[inline(always)]
202-
pub fn is_nonpositive(x: f64) -> bool {
203-
return x < 0.0f64 || (1.0f64/x) == neg_infinity;
204-
}
205-
206-
/**
207-
* Returns true if `x` is a positive number, including +0.0f640 and +Infinity
208-
*
209-
* This is the same as `f64::positive`.
210-
*/
211-
#[inline(always)]
212-
pub fn is_nonnegative(x: f64) -> bool {
213-
return x > 0.0f64 || (1.0f64/x) == infinity;
214-
}
215-
216187
/// Returns true if `x` is a zero number (positive or negative zero)
217188
#[inline(always)]
218189
pub fn is_zero(x: f64) -> bool {
@@ -278,11 +249,6 @@ pub mod consts {
278249
pub static ln_10: f64 = 2.30258509299404568401799145468436421_f64;
279250
}
280251

281-
#[inline(always)]
282-
pub fn signbit(x: f64) -> int {
283-
if is_negative(x) { return 1; } else { return 0; }
284-
}
285-
286252
#[inline(always)]
287253
pub fn logarithm(n: f64, b: f64) -> f64 {
288254
return log2(n) / log2(b);
@@ -357,15 +323,41 @@ impl Neg<f64> for f64 {
357323
fn neg(&self) -> f64 { -*self }
358324
}
359325

326+
impl Signed for f64 {
327+
/// Computes the absolute value. Returns `NaN` if the number is `NaN`.
328+
#[inline(always)]
329+
fn abs(&self) -> f64 { abs(*self) }
330+
331+
/**
332+
* # Returns
333+
*
334+
* - `1.0` if the number is positive, `+0.0` or `infinity`
335+
* - `-1.0` if the number is negative, `-0.0` or `neg_infinity`
336+
* - `NaN` if the number is `NaN`
337+
*/
338+
#[inline(always)]
339+
fn signum(&self) -> f64 {
340+
if is_NaN(*self) { NaN } else { copysign(1.0, *self) }
341+
}
342+
343+
/// Returns `true` if the number is positive, including `+0.0` and `infinity`
344+
#[inline(always)]
345+
fn is_positive(&self) -> bool { *self > 0.0 || (1.0 / *self) == infinity }
346+
347+
/// Returns `true` if the number is negative, including `-0.0` and `neg_infinity`
348+
#[inline(always)]
349+
fn is_negative(&self) -> bool { *self < 0.0 || (1.0 / *self) == neg_infinity }
350+
}
351+
360352
impl num::Round for f64 {
361353
#[inline(always)]
362354
fn round(&self, mode: num::RoundMode) -> f64 {
363355
match mode {
364356
num::RoundDown => floor(*self),
365357
num::RoundUp => ceil(*self),
366-
num::RoundToZero if is_negative(*self) => ceil(*self),
358+
num::RoundToZero if self.is_negative() => ceil(*self),
367359
num::RoundToZero => floor(*self),
368-
num::RoundFromZero if is_negative(*self) => floor(*self),
360+
num::RoundFromZero if self.is_negative() => floor(*self),
369361
num::RoundFromZero => ceil(*self)
370362
}
371363
}
@@ -376,7 +368,7 @@ impl num::Round for f64 {
376368
fn ceil(&self) -> f64 { ceil(*self) }
377369
#[inline(always)]
378370
fn fract(&self) -> f64 {
379-
if is_negative(*self) {
371+
if self.is_negative() {
380372
(*self) - ceil(*self)
381373
} else {
382374
(*self) - floor(*self)
@@ -601,6 +593,50 @@ impl num::FromStrRadix for f64 {
601593
}
602594
}
603595

596+
#[cfg(test)]
597+
mod tests {
598+
use f64::*;
599+
600+
#[test]
601+
pub fn test_signed() {
602+
assert_eq!(infinity.abs(), infinity);
603+
assert_eq!(1f64.abs(), 1f64);
604+
assert_eq!(0f64.abs(), 0f64);
605+
assert_eq!((-0f64).abs(), 0f64);
606+
assert_eq!((-1f64).abs(), 1f64);
607+
assert_eq!(neg_infinity.abs(), infinity);
608+
assert_eq!((1f64/neg_infinity).abs(), 0f64);
609+
assert!(is_NaN(NaN.abs()));
610+
611+
assert_eq!(infinity.signum(), 1f64);
612+
assert_eq!(1f64.signum(), 1f64);
613+
assert_eq!(0f64.signum(), 1f64);
614+
assert_eq!((-0f64).signum(), -1f64);
615+
assert_eq!((-1f64).signum(), -1f64);
616+
assert_eq!(neg_infinity.signum(), -1f64);
617+
assert_eq!((1f64/neg_infinity).signum(), -1f64);
618+
assert!(is_NaN(NaN.signum()));
619+
620+
assert!(infinity.is_positive());
621+
assert!(1f64.is_positive());
622+
assert!(0f64.is_positive());
623+
assert!(!(-0f64).is_positive());
624+
assert!(!(-1f64).is_positive());
625+
assert!(!neg_infinity.is_positive());
626+
assert!(!(1f64/neg_infinity).is_positive());
627+
assert!(!NaN.is_positive());
628+
629+
assert!(!infinity.is_negative());
630+
assert!(!1f64.is_negative());
631+
assert!(!0f64.is_negative());
632+
assert!((-0f64).is_negative());
633+
assert!((-1f64).is_negative());
634+
assert!(neg_infinity.is_negative());
635+
assert!((1f64/neg_infinity).is_negative());
636+
assert!(!NaN.is_negative());
637+
}
638+
}
639+
604640
//
605641
// Local Variables:
606642
// mode: rust

0 commit comments

Comments
 (0)