Merge pull request #30 from gifnksm/master
Add numeric functions and traits that provide numeric traits for generic mathematics.
This commit is contained in:
commit
c0df55e470
|
@ -41,15 +41,12 @@
|
|||
extern crate num;
|
||||
extern crate test;
|
||||
|
||||
use std::from_str::FromStr;
|
||||
use std::num::One;
|
||||
use std::num::Zero;
|
||||
use std::str::FromStr;
|
||||
use std::num::FromPrimitive;
|
||||
|
||||
use test::Bencher;
|
||||
|
||||
use num::Integer;
|
||||
use num::bigint::BigInt;
|
||||
use num::{BigInt, Integer, One, Zero};
|
||||
|
||||
struct Context {
|
||||
numer: BigInt,
|
||||
|
|
|
@ -19,8 +19,7 @@
|
|||
//! ## Example
|
||||
//!
|
||||
//! ```rust
|
||||
//! use num::bigint::BigUint;
|
||||
//! use std::num::{Zero, One};
|
||||
//! use num::{BigUint, Zero, One};
|
||||
//! use std::mem::replace;
|
||||
//!
|
||||
//! // Calculate large fibonacci numbers.
|
||||
|
@ -61,14 +60,14 @@ use rand::Rng;
|
|||
|
||||
use std::{cmp, fmt, hash};
|
||||
use std::default::Default;
|
||||
use std::from_str::FromStr;
|
||||
use std::num::CheckedDiv;
|
||||
use std::num::{ToPrimitive, FromPrimitive};
|
||||
use std::num::{Zero, One, FromStrRadix};
|
||||
use std::str;
|
||||
use std::string::String;
|
||||
use std::iter::{AdditiveIterator, MultiplicativeIterator};
|
||||
use std::num::{Int, ToPrimitive, FromPrimitive};
|
||||
use std::num::FromStrRadix;
|
||||
use std::str::{mod, FromStr};
|
||||
use std::{i64, u64};
|
||||
|
||||
use {Num, Unsigned, CheckedAdd, CheckedSub, CheckedMul, CheckedDiv, Signed, Zero, One};
|
||||
|
||||
/// A `BigDigit` is a `BigUint`'s composing element.
|
||||
pub type BigDigit = u32;
|
||||
|
||||
|
@ -739,6 +738,20 @@ impl FromStrRadix for BigUint {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T: Iterator<BigUint>> AdditiveIterator<BigUint> for T {
|
||||
fn sum(&mut self) -> BigUint {
|
||||
let init: BigUint = Zero::zero();
|
||||
self.fold(init, |acc, x| acc + x)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Iterator<BigUint>> MultiplicativeIterator<BigUint> for T {
|
||||
fn product(&mut self) -> BigUint {
|
||||
let init: BigUint = One::one();
|
||||
self.fold(init, |acc, x| acc * x)
|
||||
}
|
||||
}
|
||||
|
||||
impl BigUint {
|
||||
/// Creates and initializes a `BigUint`.
|
||||
///
|
||||
|
@ -1084,7 +1097,6 @@ impl CheckedDiv for BigInt {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
impl Integer for BigInt {
|
||||
#[inline]
|
||||
fn div_rem(&self, other: &BigInt) -> (BigInt, BigInt) {
|
||||
|
@ -1374,6 +1386,20 @@ impl<R: Rng> RandBigInt for R {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T: Iterator<BigInt>> AdditiveIterator<BigInt> for T {
|
||||
fn sum(&mut self) -> BigInt {
|
||||
let init: BigInt = Zero::zero();
|
||||
self.fold(init, |acc, x| acc + x)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Iterator<BigInt>> MultiplicativeIterator<BigInt> for T {
|
||||
fn product(&mut self) -> BigInt {
|
||||
let init: BigInt = One::one();
|
||||
self.fold(init, |acc, x| acc * x)
|
||||
}
|
||||
}
|
||||
|
||||
impl BigInt {
|
||||
/// Creates and initializes a BigInt.
|
||||
///
|
||||
|
@ -1416,6 +1442,29 @@ impl BigInt {
|
|||
Minus => None
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn checked_add(&self, v: &BigInt) -> Option<BigInt> {
|
||||
return Some(self.add(v));
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn checked_sub(&self, v: &BigInt) -> Option<BigInt> {
|
||||
return Some(self.sub(v));
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn checked_mul(&self, v: &BigInt) -> Option<BigInt> {
|
||||
return Some(self.mul(v));
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn checked_div(&self, v: &BigInt) -> Option<BigInt> {
|
||||
if v.is_zero() {
|
||||
return None;
|
||||
}
|
||||
return Some(self.div(v));
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
@ -1425,15 +1474,16 @@ mod biguint_tests {
|
|||
use super::{Plus, BigInt, RandBigInt, ToBigInt};
|
||||
|
||||
use std::cmp::{Less, Equal, Greater};
|
||||
use std::from_str::FromStr;
|
||||
use std::str::FromStr;
|
||||
use std::i64;
|
||||
use std::num::{Zero, One, FromStrRadix};
|
||||
use std::num::FromStrRadix;
|
||||
use std::num::{ToPrimitive, FromPrimitive};
|
||||
use std::num::CheckedDiv;
|
||||
use std::rand::task_rng;
|
||||
use std::u64;
|
||||
use std::hash::hash;
|
||||
|
||||
use {Zero, One, CheckedAdd, CheckedSub, CheckedMul, CheckedDiv};
|
||||
|
||||
#[test]
|
||||
fn test_from_slice() {
|
||||
fn check(slice: &[BigDigit], data: &[BigDigit]) {
|
||||
|
@ -2289,13 +2339,14 @@ mod bigint_tests {
|
|||
|
||||
use std::cmp::{Less, Equal, Greater};
|
||||
use std::i64;
|
||||
use std::num::CheckedDiv;
|
||||
use std::num::{Zero, One, FromStrRadix};
|
||||
use std::num::FromStrRadix;
|
||||
use std::num::{ToPrimitive, FromPrimitive};
|
||||
use std::rand::task_rng;
|
||||
use std::u64;
|
||||
use std::hash::hash;
|
||||
|
||||
use {Zero, One, Signed};
|
||||
|
||||
#[test]
|
||||
fn test_from_biguint() {
|
||||
fn check(inp_s: Sign, inp_n: uint, ans_s: Sign, ans_n: uint) {
|
||||
|
@ -2882,7 +2933,9 @@ mod bench {
|
|||
use super::BigUint;
|
||||
use std::iter;
|
||||
use std::mem::replace;
|
||||
use std::num::{FromPrimitive, Zero, One};
|
||||
use std::num::FromPrimitive;
|
||||
|
||||
use {Zero, One};
|
||||
|
||||
fn factorial(n: uint) -> BigUint {
|
||||
let mut f: BigUint = One::one();
|
||||
|
|
|
@ -12,7 +12,10 @@
|
|||
//! Complex numbers.
|
||||
|
||||
use std::fmt;
|
||||
use std::num::{Zero, One};
|
||||
use std::num::FloatMath;
|
||||
use std::iter::{AdditiveIterator, MultiplicativeIterator};
|
||||
|
||||
use {Zero, One, Num};
|
||||
|
||||
// FIXME #1284: handle complex NaN & infinity etc. This
|
||||
// probably doesn't map to C's _Complex correctly.
|
||||
|
@ -80,7 +83,7 @@ impl<T: Clone + FloatMath> Complex<T> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T: Clone + FloatMath> Complex<T> {
|
||||
impl<T: Clone + FloatMath + Num> Complex<T> {
|
||||
/// Calculate the principal Arg of self.
|
||||
#[inline]
|
||||
pub fn arg(&self) -> T {
|
||||
|
@ -172,14 +175,30 @@ impl<T: fmt::Show + Num + PartialOrd> fmt::Show for Complex<T> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<A: Clone + Num, T: Iterator<Complex<A>>> AdditiveIterator<Complex<A>> for T {
|
||||
fn sum(&mut self) -> Complex<A> {
|
||||
let init: Complex<A> = Zero::zero();
|
||||
self.fold(init, |acc, x| acc + x)
|
||||
}
|
||||
}
|
||||
|
||||
impl<A: Clone + Num, T: Iterator<Complex<A>>> MultiplicativeIterator<Complex<A>> for T {
|
||||
fn product(&mut self) -> Complex<A> {
|
||||
let init: Complex<A> = One::one();
|
||||
self.fold(init, |acc, x| acc * x)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
#![allow(non_upper_case_globals)]
|
||||
|
||||
use super::{Complex64, Complex};
|
||||
use std::num::{Zero, One, Float};
|
||||
use std::num::Float;
|
||||
use std::hash::hash;
|
||||
|
||||
use {Zero, One};
|
||||
|
||||
pub const _0_0i : Complex64 = Complex { re: 0.0, im: 0.0 };
|
||||
pub const _1_0i : Complex64 = Complex { re: 1.0, im: 0.0 };
|
||||
pub const _1_1i : Complex64 = Complex { re: 1.0, im: 1.0 };
|
||||
|
@ -280,7 +299,7 @@ mod test {
|
|||
|
||||
mod arith {
|
||||
use super::{_0_0i, _1_0i, _1_1i, _0_1i, _neg1_1i, _05_05i, all_consts};
|
||||
use std::num::Zero;
|
||||
use Zero;
|
||||
|
||||
#[test]
|
||||
fn test_add() {
|
||||
|
|
|
@ -10,6 +10,8 @@
|
|||
|
||||
//! Integer trait and functions.
|
||||
|
||||
use {Num, Signed};
|
||||
|
||||
pub trait Integer: Num + PartialOrd
|
||||
+ Div<Self, Self>
|
||||
+ Rem<Self, Self> {
|
||||
|
|
|
@ -0,0 +1,341 @@
|
|||
// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
//! External iterators for generic mathematics
|
||||
|
||||
use {Integer, Zero, One, CheckedAdd};
|
||||
use std::num::Int;
|
||||
|
||||
/// An iterator over the range [start, stop)
|
||||
#[deriving(Clone)]
|
||||
pub struct Range<A> {
|
||||
state: A,
|
||||
stop: A,
|
||||
one: A
|
||||
}
|
||||
|
||||
/// Returns an iterator over the given range [start, stop) (that is, starting
|
||||
/// at start (inclusive), and ending at stop (exclusive)).
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
/// let array = [0, 1, 2, 3, 4];
|
||||
///
|
||||
/// for i in range(0, 5u) {
|
||||
/// println!("{}", i);
|
||||
/// assert_eq!(i, array[i]);
|
||||
/// }
|
||||
/// ```
|
||||
#[inline]
|
||||
pub fn range<A: Add<A, A> + PartialOrd + Clone + One>(start: A, stop: A) -> Range<A> {
|
||||
Range{state: start, stop: stop, one: One::one()}
|
||||
}
|
||||
|
||||
// FIXME: rust-lang/rust#10414: Unfortunate type bound
|
||||
impl<A: Add<A, A> + PartialOrd + Clone + ToPrimitive> Iterator<A> for Range<A> {
|
||||
#[inline]
|
||||
fn next(&mut self) -> Option<A> {
|
||||
if self.state < self.stop {
|
||||
let result = self.state.clone();
|
||||
self.state = self.state + self.one;
|
||||
Some(result)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn size_hint(&self) -> (uint, Option<uint>) {
|
||||
// This first checks if the elements are representable as i64. If they aren't, try u64 (to
|
||||
// handle cases like range(huge, huger)). We don't use uint/int because the difference of
|
||||
// the i64/u64 might lie within their range.
|
||||
let bound = match self.state.to_i64() {
|
||||
Some(a) => {
|
||||
let sz = self.stop.to_i64().map(|b| b.checked_sub(a));
|
||||
match sz {
|
||||
Some(Some(bound)) => bound.to_uint(),
|
||||
_ => None,
|
||||
}
|
||||
},
|
||||
None => match self.state.to_u64() {
|
||||
Some(a) => {
|
||||
let sz = self.stop.to_u64().map(|b| b.checked_sub(a));
|
||||
match sz {
|
||||
Some(Some(bound)) => bound.to_uint(),
|
||||
_ => None
|
||||
}
|
||||
},
|
||||
None => None
|
||||
}
|
||||
};
|
||||
|
||||
match bound {
|
||||
Some(b) => (b, Some(b)),
|
||||
// Standard fallback for unbounded/unrepresentable bounds
|
||||
None => (0, None)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// `Integer` is required to ensure the range will be the same regardless of
|
||||
/// the direction it is consumed.
|
||||
impl<A: Integer + PartialOrd + Clone + ToPrimitive> DoubleEndedIterator<A> for Range<A> {
|
||||
#[inline]
|
||||
fn next_back(&mut self) -> Option<A> {
|
||||
if self.stop > self.state {
|
||||
self.stop = self.stop - self.one;
|
||||
Some(self.stop.clone())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// An iterator over the range [start, stop]
|
||||
#[deriving(Clone)]
|
||||
pub struct RangeInclusive<A> {
|
||||
range: Range<A>,
|
||||
done: bool,
|
||||
}
|
||||
|
||||
/// Return an iterator over the range [start, stop]
|
||||
#[inline]
|
||||
pub fn range_inclusive<A: Add<A, A> + PartialOrd + Clone + One>(start: A, stop: A)
|
||||
-> RangeInclusive<A> {
|
||||
RangeInclusive{range: range(start, stop), done: false}
|
||||
}
|
||||
|
||||
impl<A: Add<A, A> + PartialOrd + Clone + ToPrimitive> Iterator<A> for RangeInclusive<A> {
|
||||
#[inline]
|
||||
fn next(&mut self) -> Option<A> {
|
||||
match self.range.next() {
|
||||
Some(x) => Some(x),
|
||||
None => {
|
||||
if !self.done && self.range.state == self.range.stop {
|
||||
self.done = true;
|
||||
Some(self.range.stop.clone())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn size_hint(&self) -> (uint, Option<uint>) {
|
||||
let (lo, hi) = self.range.size_hint();
|
||||
if self.done {
|
||||
(lo, hi)
|
||||
} else {
|
||||
let lo = lo.saturating_add(1);
|
||||
let hi = match hi {
|
||||
Some(x) => x.checked_add(1),
|
||||
None => None
|
||||
};
|
||||
(lo, hi)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<A: Sub<A, A> + Integer + PartialOrd + Clone + ToPrimitive> DoubleEndedIterator<A>
|
||||
for RangeInclusive<A> {
|
||||
#[inline]
|
||||
fn next_back(&mut self) -> Option<A> {
|
||||
if self.range.stop > self.range.state {
|
||||
let result = self.range.stop.clone();
|
||||
self.range.stop = self.range.stop - self.range.one;
|
||||
Some(result)
|
||||
} else if !self.done && self.range.state == self.range.stop {
|
||||
self.done = true;
|
||||
Some(self.range.stop.clone())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// An iterator over the range [start, stop) by `step`. It handles overflow by stopping.
|
||||
#[deriving(Clone)]
|
||||
pub struct RangeStep<A> {
|
||||
state: A,
|
||||
stop: A,
|
||||
step: A,
|
||||
rev: bool,
|
||||
}
|
||||
|
||||
/// Return an iterator over the range [start, stop) by `step`. It handles overflow by stopping.
|
||||
#[inline]
|
||||
pub fn range_step<A: CheckedAdd + PartialOrd +
|
||||
Clone + Zero>(start: A, stop: A, step: A) -> RangeStep<A> {
|
||||
let rev = step < Zero::zero();
|
||||
RangeStep{state: start, stop: stop, step: step, rev: rev}
|
||||
}
|
||||
|
||||
impl<A: CheckedAdd + PartialOrd + Clone> Iterator<A> for RangeStep<A> {
|
||||
#[inline]
|
||||
fn next(&mut self) -> Option<A> {
|
||||
if (self.rev && self.state > self.stop) || (!self.rev && self.state < self.stop) {
|
||||
let result = self.state.clone();
|
||||
match self.state.checked_add(&self.step) {
|
||||
Some(x) => self.state = x,
|
||||
None => self.state = self.stop.clone()
|
||||
}
|
||||
Some(result)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// An iterator over the range [start, stop] by `step`. It handles overflow by stopping.
|
||||
#[deriving(Clone)]
|
||||
pub struct RangeStepInclusive<A> {
|
||||
state: A,
|
||||
stop: A,
|
||||
step: A,
|
||||
rev: bool,
|
||||
done: bool,
|
||||
}
|
||||
|
||||
/// Return an iterator over the range [start, stop] by `step`. It handles overflow by stopping.
|
||||
#[inline]
|
||||
pub fn range_step_inclusive<A: CheckedAdd + PartialOrd + Clone + Zero>(start: A, stop: A,
|
||||
step: A) -> RangeStepInclusive<A> {
|
||||
let rev = step < Zero::zero();
|
||||
RangeStepInclusive{state: start, stop: stop, step: step, rev: rev, done: false}
|
||||
}
|
||||
|
||||
impl<A: CheckedAdd + PartialOrd + Clone + PartialEq> Iterator<A> for RangeStepInclusive<A> {
|
||||
#[inline]
|
||||
fn next(&mut self) -> Option<A> {
|
||||
if !self.done && ((self.rev && self.state >= self.stop) ||
|
||||
(!self.rev && self.state <= self.stop)) {
|
||||
let result = self.state.clone();
|
||||
match self.state.checked_add(&self.step) {
|
||||
Some(x) => self.state = x,
|
||||
None => self.done = true
|
||||
}
|
||||
Some(result)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::uint;
|
||||
use One;
|
||||
|
||||
#[test]
|
||||
fn test_range() {
|
||||
/// A mock type to check Range when ToPrimitive returns None
|
||||
struct Foo;
|
||||
|
||||
impl ToPrimitive for Foo {
|
||||
fn to_i64(&self) -> Option<i64> { None }
|
||||
fn to_u64(&self) -> Option<u64> { None }
|
||||
}
|
||||
|
||||
impl Add<Foo, Foo> for Foo {
|
||||
fn add(&self, _: &Foo) -> Foo {
|
||||
Foo
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq for Foo {
|
||||
fn eq(&self, _: &Foo) -> bool {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialOrd for Foo {
|
||||
fn partial_cmp(&self, _: &Foo) -> Option<Ordering> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
impl Clone for Foo {
|
||||
fn clone(&self) -> Foo {
|
||||
Foo
|
||||
}
|
||||
}
|
||||
|
||||
impl Mul<Foo, Foo> for Foo {
|
||||
fn mul(&self, _: &Foo) -> Foo {
|
||||
Foo
|
||||
}
|
||||
}
|
||||
|
||||
impl One for Foo {
|
||||
fn one() -> Foo {
|
||||
Foo
|
||||
}
|
||||
}
|
||||
|
||||
assert!(super::range(0i, 5).collect::<Vec<int>>() == vec![0i, 1, 2, 3, 4]);
|
||||
assert!(super::range(-10i, -1).collect::<Vec<int>>() ==
|
||||
vec![-10, -9, -8, -7, -6, -5, -4, -3, -2]);
|
||||
assert!(super::range(0i, 5).rev().collect::<Vec<int>>() == vec![4, 3, 2, 1, 0]);
|
||||
assert_eq!(super::range(200i, -5).count(), 0);
|
||||
assert_eq!(super::range(200i, -5).rev().count(), 0);
|
||||
assert_eq!(super::range(200i, 200).count(), 0);
|
||||
assert_eq!(super::range(200i, 200).rev().count(), 0);
|
||||
|
||||
assert_eq!(super::range(0i, 100).size_hint(), (100, Some(100)));
|
||||
// this test is only meaningful when sizeof uint < sizeof u64
|
||||
assert_eq!(super::range(uint::MAX - 1, uint::MAX).size_hint(), (1, Some(1)));
|
||||
assert_eq!(super::range(-10i, -1).size_hint(), (9, Some(9)));
|
||||
assert_eq!(super::range(Foo, Foo).size_hint(), (0, None));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_range_inclusive() {
|
||||
assert!(super::range_inclusive(0i, 5).collect::<Vec<int>>() ==
|
||||
vec![0i, 1, 2, 3, 4, 5]);
|
||||
assert!(super::range_inclusive(0i, 5).rev().collect::<Vec<int>>() ==
|
||||
vec![5i, 4, 3, 2, 1, 0]);
|
||||
assert_eq!(super::range_inclusive(200i, -5).count(), 0);
|
||||
assert_eq!(super::range_inclusive(200i, -5).rev().count(), 0);
|
||||
assert!(super::range_inclusive(200i, 200).collect::<Vec<int>>() == vec![200]);
|
||||
assert!(super::range_inclusive(200i, 200).rev().collect::<Vec<int>>() == vec![200]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_range_step() {
|
||||
assert!(super::range_step(0i, 20, 5).collect::<Vec<int>>() ==
|
||||
vec![0, 5, 10, 15]);
|
||||
assert!(super::range_step(20i, 0, -5).collect::<Vec<int>>() ==
|
||||
vec![20, 15, 10, 5]);
|
||||
assert!(super::range_step(20i, 0, -6).collect::<Vec<int>>() ==
|
||||
vec![20, 14, 8, 2]);
|
||||
assert!(super::range_step(200u8, 255, 50).collect::<Vec<u8>>() ==
|
||||
vec![200u8, 250]);
|
||||
assert!(super::range_step(200i, -5, 1).collect::<Vec<int>>() == vec![]);
|
||||
assert!(super::range_step(200i, 200, 1).collect::<Vec<int>>() == vec![]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_range_step_inclusive() {
|
||||
assert!(super::range_step_inclusive(0i, 20, 5).collect::<Vec<int>>() ==
|
||||
vec![0, 5, 10, 15, 20]);
|
||||
assert!(super::range_step_inclusive(20i, 0, -5).collect::<Vec<int>>() ==
|
||||
vec![20, 15, 10, 5, 0]);
|
||||
assert!(super::range_step_inclusive(20i, 0, -6).collect::<Vec<int>>() ==
|
||||
vec![20, 14, 8, 2]);
|
||||
assert!(super::range_step_inclusive(200u8, 255, 50).collect::<Vec<u8>>() ==
|
||||
vec![200u8, 250]);
|
||||
assert!(super::range_step_inclusive(200i, -5, 1).collect::<Vec<int>>() ==
|
||||
vec![]);
|
||||
assert!(super::range_step_inclusive(200i, 200, 1).collect::<Vec<int>>() ==
|
||||
vec![200]);
|
||||
}
|
||||
}
|
70
src/lib.rs
70
src/lib.rs
|
@ -64,8 +64,78 @@ pub use bigint::{BigInt, BigUint};
|
|||
pub use rational::{Rational, BigRational};
|
||||
pub use complex::Complex;
|
||||
pub use integer::Integer;
|
||||
pub use iter::{range, range_inclusive, range_step, range_step_inclusive};
|
||||
pub use traits::{Num, Zero, One, Signed, Unsigned, Bounded,
|
||||
Saturating, CheckedAdd, CheckedSub, CheckedMul, CheckedDiv};
|
||||
|
||||
pub mod bigint;
|
||||
pub mod complex;
|
||||
pub mod integer;
|
||||
pub mod iter;
|
||||
pub mod traits;
|
||||
pub mod rational;
|
||||
|
||||
/// Returns the additive identity, `0`.
|
||||
#[inline(always)] pub fn zero<T: Zero>() -> T { Zero::zero() }
|
||||
|
||||
/// Returns the multiplicative identity, `1`.
|
||||
#[inline(always)] pub fn one<T: One>() -> T { One::one() }
|
||||
|
||||
/// Computes the absolute value.
|
||||
///
|
||||
/// For `f32` and `f64`, `NaN` will be returned if the number is `NaN`
|
||||
///
|
||||
/// For signed integers, `::MIN` will be returned if the number is `::MIN`.
|
||||
#[inline(always)]
|
||||
pub fn abs<T: Signed>(value: T) -> T {
|
||||
value.abs()
|
||||
}
|
||||
|
||||
/// The positive difference of two numbers.
|
||||
///
|
||||
/// Returns zero if `x` is less than or equal to `y`, otherwise the difference
|
||||
/// between `x` and `y` is returned.
|
||||
#[inline(always)]
|
||||
pub fn abs_sub<T: Signed>(x: T, y: T) -> T {
|
||||
x.abs_sub(&y)
|
||||
}
|
||||
|
||||
/// Returns the sign of the number.
|
||||
///
|
||||
/// For `f32` and `f64`:
|
||||
///
|
||||
/// * `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`
|
||||
///
|
||||
/// For signed integers:
|
||||
///
|
||||
/// * `0` if the number is zero
|
||||
/// * `1` if the number is positive
|
||||
/// * `-1` if the number is negative
|
||||
#[inline(always)] pub fn signum<T: Signed>(value: T) -> T { value.signum() }
|
||||
|
||||
/// Raises a value to the power of exp, using exponentiation by squaring.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
/// use num;
|
||||
///
|
||||
/// assert_eq!(num::pow(2i, 4), 16);
|
||||
/// ```
|
||||
#[inline]
|
||||
pub fn pow<T: One + Mul<T, T>>(mut base: T, mut exp: uint) -> T {
|
||||
if exp == 1 { base }
|
||||
else {
|
||||
let mut acc = one::<T>();
|
||||
while exp > 0 {
|
||||
if (exp & 1) == 1 {
|
||||
acc = acc * base;
|
||||
}
|
||||
base = base * base;
|
||||
exp = exp >> 1;
|
||||
}
|
||||
acc
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,11 +14,12 @@ use Integer;
|
|||
|
||||
use std::cmp;
|
||||
use std::fmt;
|
||||
use std::from_str::FromStr;
|
||||
use std::num;
|
||||
use std::num::{Zero, One, FromStrRadix};
|
||||
use std::str::FromStr;
|
||||
use std::num::{FromStrRadix, Float};
|
||||
use std::iter::{AdditiveIterator, MultiplicativeIterator};
|
||||
|
||||
use bigint::{BigInt, BigUint, Sign, Plus, Minus};
|
||||
use {Num, Signed, Zero, One};
|
||||
|
||||
/// Represents the ratio between 2 numbers.
|
||||
#[deriving(Clone, Hash, Encodable, Decodable)]
|
||||
|
@ -303,7 +304,7 @@ impl<T: Clone + Integer + PartialOrd>
|
|||
Num for Ratio<T> {}
|
||||
|
||||
impl<T: Clone + Integer + PartialOrd>
|
||||
num::Signed for Ratio<T> {
|
||||
Signed for Ratio<T> {
|
||||
#[inline]
|
||||
fn abs(&self) -> Ratio<T> {
|
||||
if self.is_negative() { -self.clone() } else { self.clone() }
|
||||
|
@ -317,11 +318,11 @@ impl<T: Clone + Integer + PartialOrd>
|
|||
#[inline]
|
||||
fn signum(&self) -> Ratio<T> {
|
||||
if *self > Zero::zero() {
|
||||
num::one()
|
||||
One::one()
|
||||
} else if self.is_zero() {
|
||||
num::zero()
|
||||
Zero::zero()
|
||||
} else {
|
||||
- num::one::<Ratio<T>>()
|
||||
- ::one::<Ratio<T>>()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -382,15 +383,30 @@ impl<T: FromStrRadix + Clone + Integer + PartialOrd>
|
|||
}
|
||||
}
|
||||
|
||||
impl<A: Clone + Integer + PartialOrd, T: Iterator<Ratio<A>>> AdditiveIterator<Ratio<A>> for T {
|
||||
fn sum(&mut self) -> Ratio<A> {
|
||||
let init: Ratio<A> = Zero::zero();
|
||||
self.fold(init, |acc, x| acc + x)
|
||||
}
|
||||
}
|
||||
|
||||
impl<A: Clone + Integer + PartialOrd, T: Iterator<Ratio<A>>> MultiplicativeIterator<Ratio<A>> for T {
|
||||
fn product(&mut self) -> Ratio<A> {
|
||||
let init: Ratio<A> = One::one();
|
||||
self.fold(init, |acc, x| acc * x)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
|
||||
use super::{Ratio, Rational, BigRational};
|
||||
use std::num::{Zero, One, FromPrimitive};
|
||||
use std::from_str::FromStr;
|
||||
use std::num::{FromPrimitive, Float};
|
||||
use std::str::FromStr;
|
||||
use std::hash::hash;
|
||||
use std::num;
|
||||
use std::i32;
|
||||
use {Zero, One, Signed};
|
||||
|
||||
pub const _0 : Rational = Ratio { numer: 0, denom: 1};
|
||||
pub const _1 : Rational = Ratio { numer: 1, denom: 1};
|
||||
|
@ -735,7 +751,7 @@ mod test {
|
|||
assert_eq!(_3_2.abs_sub(&_1_2), _1);
|
||||
assert_eq!(_1_2.abs_sub(&_3_2), Zero::zero());
|
||||
assert_eq!(_1_2.signum(), One::one());
|
||||
assert_eq!(_NEG1_2.signum(), - num::one::<Ratio<int>>());
|
||||
assert_eq!(_NEG1_2.signum(), - ::one::<Ratio<int>>());
|
||||
assert!(_NEG1_2.is_negative());
|
||||
assert!(! _NEG1_2.is_positive());
|
||||
assert!(! _1_2.is_negative());
|
||||
|
|
|
@ -0,0 +1,514 @@
|
|||
// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
//! Numeric traits for generic mathematics
|
||||
|
||||
use std::intrinsics;
|
||||
use std::{uint, u8, u16, u32, u64};
|
||||
use std::{int, i8, i16, i32, i64};
|
||||
use std::{f32, f64};
|
||||
|
||||
/// The base trait for numeric types
|
||||
pub trait Num: PartialEq + Zero + One
|
||||
+ Neg<Self>
|
||||
+ Add<Self,Self>
|
||||
+ Sub<Self,Self>
|
||||
+ Mul<Self,Self>
|
||||
+ Div<Self,Self>
|
||||
+ Rem<Self,Self> {}
|
||||
|
||||
macro_rules! trait_impl(
|
||||
($name:ident for $($t:ty)*) => ($(
|
||||
impl $name for $t {}
|
||||
)*)
|
||||
)
|
||||
|
||||
trait_impl!(Num for uint u8 u16 u32 u64 int i8 i16 i32 i64 f32 f64)
|
||||
|
||||
/// Defines an additive identity element for `Self`.
|
||||
///
|
||||
/// # Deriving
|
||||
///
|
||||
/// This trait can be automatically be derived using `#[deriving(Zero)]`
|
||||
/// attribute. If you choose to use this, make sure that the laws outlined in
|
||||
/// the documentation for `Zero::zero` still hold.
|
||||
pub trait Zero: Add<Self, Self> {
|
||||
/// Returns the additive identity element of `Self`, `0`.
|
||||
///
|
||||
/// # Laws
|
||||
///
|
||||
/// ```{.text}
|
||||
/// a + 0 = a ∀ a ∈ Self
|
||||
/// 0 + a = a ∀ a ∈ Self
|
||||
/// ```
|
||||
///
|
||||
/// # Purity
|
||||
///
|
||||
/// This function should return the same result at all times regardless of
|
||||
/// external mutable state, for example values stored in TLS or in
|
||||
/// `static mut`s.
|
||||
// FIXME (#5527): This should be an associated constant
|
||||
fn zero() -> Self;
|
||||
|
||||
/// Returns `true` if `self` is equal to the additive identity.
|
||||
#[inline]
|
||||
fn is_zero(&self) -> bool;
|
||||
}
|
||||
|
||||
macro_rules! zero_impl(
|
||||
($t:ty, $v:expr) => {
|
||||
impl Zero for $t {
|
||||
#[inline]
|
||||
fn zero() -> $t { $v }
|
||||
#[inline]
|
||||
fn is_zero(&self) -> bool { *self == $v }
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
zero_impl!(uint, 0u)
|
||||
zero_impl!(u8, 0u8)
|
||||
zero_impl!(u16, 0u16)
|
||||
zero_impl!(u32, 0u32)
|
||||
zero_impl!(u64, 0u64)
|
||||
|
||||
zero_impl!(int, 0i)
|
||||
zero_impl!(i8, 0i8)
|
||||
zero_impl!(i16, 0i16)
|
||||
zero_impl!(i32, 0i32)
|
||||
zero_impl!(i64, 0i64)
|
||||
|
||||
zero_impl!(f32, 0.0f32)
|
||||
zero_impl!(f64, 0.0f64)
|
||||
|
||||
/// Defines a multiplicative identity element for `Self`.
|
||||
pub trait One: Mul<Self, Self> {
|
||||
/// Returns the multiplicative identity element of `Self`, `1`.
|
||||
///
|
||||
/// # Laws
|
||||
///
|
||||
/// ```{.text}
|
||||
/// a * 1 = a ∀ a ∈ Self
|
||||
/// 1 * a = a ∀ a ∈ Self
|
||||
/// ```
|
||||
///
|
||||
/// # Purity
|
||||
///
|
||||
/// This function should return the same result at all times regardless of
|
||||
/// external mutable state, for example values stored in TLS or in
|
||||
/// `static mut`s.
|
||||
// FIXME (#5527): This should be an associated constant
|
||||
fn one() -> Self;
|
||||
}
|
||||
|
||||
macro_rules! one_impl(
|
||||
($t:ty, $v:expr) => {
|
||||
impl One for $t {
|
||||
#[inline]
|
||||
fn one() -> $t { $v }
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
one_impl!(uint, 1u)
|
||||
one_impl!(u8, 1u8)
|
||||
one_impl!(u16, 1u16)
|
||||
one_impl!(u32, 1u32)
|
||||
one_impl!(u64, 1u64)
|
||||
|
||||
one_impl!(int, 1i)
|
||||
one_impl!(i8, 1i8)
|
||||
one_impl!(i16, 1i16)
|
||||
one_impl!(i32, 1i32)
|
||||
one_impl!(i64, 1i64)
|
||||
|
||||
one_impl!(f32, 1.0f32)
|
||||
one_impl!(f64, 1.0f64)
|
||||
|
||||
/// Useful functions for signed numbers (i.e. numbers that can be negative).
|
||||
pub trait Signed: Num + Neg<Self> {
|
||||
/// Computes the absolute value.
|
||||
///
|
||||
/// For `f32` and `f64`, `NaN` will be returned if the number is `NaN`.
|
||||
///
|
||||
/// For signed integers, `::MIN` will be returned if the number is `::MIN`.
|
||||
fn abs(&self) -> Self;
|
||||
|
||||
/// The positive difference of two numbers.
|
||||
///
|
||||
/// Returns `zero` if the number is less than or equal to `other`, otherwise the difference
|
||||
/// between `self` and `other` is returned.
|
||||
fn abs_sub(&self, other: &Self) -> Self;
|
||||
|
||||
/// Returns the sign of the number.
|
||||
///
|
||||
/// For `f32` and `f64`:
|
||||
///
|
||||
/// * `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`
|
||||
///
|
||||
/// For signed integers:
|
||||
///
|
||||
/// * `0` if the number is zero
|
||||
/// * `1` if the number is positive
|
||||
/// * `-1` if the number is negative
|
||||
fn signum(&self) -> Self;
|
||||
|
||||
/// Returns true if the number is positive and false if the number is zero or negative.
|
||||
fn is_positive(&self) -> bool;
|
||||
|
||||
/// Returns true if the number is negative and false if the number is zero or positive.
|
||||
fn is_negative(&self) -> bool;
|
||||
}
|
||||
|
||||
macro_rules! signed_impl(
|
||||
($($t:ty)*) => ($(
|
||||
impl Signed for $t {
|
||||
#[inline]
|
||||
fn abs(&self) -> $t {
|
||||
if self.is_negative() { -*self } else { *self }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn abs_sub(&self, other: &$t) -> $t {
|
||||
if *self <= *other { 0 } else { *self - *other }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn signum(&self) -> $t {
|
||||
match *self {
|
||||
n if n > 0 => 1,
|
||||
0 => 0,
|
||||
_ => -1,
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn is_positive(&self) -> bool { *self > 0 }
|
||||
|
||||
#[inline]
|
||||
fn is_negative(&self) -> bool { *self < 0 }
|
||||
}
|
||||
)*)
|
||||
)
|
||||
|
||||
signed_impl!(int i8 i16 i32 i64)
|
||||
|
||||
macro_rules! signed_float_impl(
|
||||
($t:ty, $nan:expr, $inf:expr, $neg_inf:expr, $fabs:path, $fcopysign:path, $fdim:ident) => {
|
||||
impl Signed for $t {
|
||||
/// Computes the absolute value. Returns `NAN` if the number is `NAN`.
|
||||
#[inline]
|
||||
fn abs(&self) -> $t {
|
||||
unsafe { $fabs(*self) }
|
||||
}
|
||||
|
||||
/// The positive difference of two numbers. Returns `0.0` if the number is
|
||||
/// less than or equal to `other`, otherwise the difference between`self`
|
||||
/// and `other` is returned.
|
||||
#[inline]
|
||||
fn abs_sub(&self, other: &$t) -> $t {
|
||||
extern { fn $fdim(a: $t, b: $t) -> $t; }
|
||||
unsafe { $fdim(*self, *other) }
|
||||
}
|
||||
|
||||
/// # 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]
|
||||
fn signum(&self) -> $t {
|
||||
if self != self { $nan } else {
|
||||
unsafe { $fcopysign(1.0, *self) }
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns `true` if the number is positive, including `+0.0` and `INFINITY`
|
||||
#[inline]
|
||||
fn is_positive(&self) -> bool { *self > 0.0 || (1.0 / *self) == $inf }
|
||||
|
||||
/// Returns `true` if the number is negative, including `-0.0` and `NEG_INFINITY`
|
||||
#[inline]
|
||||
fn is_negative(&self) -> bool { *self < 0.0 || (1.0 / *self) == $neg_inf }
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
signed_float_impl!(f32, f32::NAN, f32::INFINITY, f32::NEG_INFINITY,
|
||||
intrinsics::fabsf32, intrinsics::copysignf32, fdimf)
|
||||
signed_float_impl!(f64, f64::NAN, f64::INFINITY, f64::NEG_INFINITY,
|
||||
intrinsics::fabsf64, intrinsics::copysignf64, fdim)
|
||||
|
||||
/// A trait for values which cannot be negative
|
||||
pub trait Unsigned: Num {}
|
||||
|
||||
trait_impl!(Unsigned for uint u8 u16 u32 u64)
|
||||
|
||||
/// Numbers which have upper and lower bounds
|
||||
pub trait Bounded {
|
||||
// FIXME (#5527): These should be associated constants
|
||||
/// returns the smallest finite number this type can represent
|
||||
fn min_value() -> Self;
|
||||
/// returns the largest finite number this type can represent
|
||||
fn max_value() -> Self;
|
||||
}
|
||||
|
||||
macro_rules! bounded_impl(
|
||||
($t:ty, $min:expr, $max:expr) => {
|
||||
impl Bounded for $t {
|
||||
#[inline]
|
||||
fn min_value() -> $t { $min }
|
||||
|
||||
#[inline]
|
||||
fn max_value() -> $t { $max }
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
bounded_impl!(uint, uint::MIN, uint::MAX)
|
||||
bounded_impl!(u8, u8::MIN, u8::MAX)
|
||||
bounded_impl!(u16, u16::MIN, u16::MAX)
|
||||
bounded_impl!(u32, u32::MIN, u32::MAX)
|
||||
bounded_impl!(u64, u64::MIN, u64::MAX)
|
||||
|
||||
bounded_impl!(int, int::MIN, int::MAX)
|
||||
bounded_impl!(i8, i8::MIN, i8::MAX)
|
||||
bounded_impl!(i16, i16::MIN, i16::MAX)
|
||||
bounded_impl!(i32, i32::MIN, i32::MAX)
|
||||
bounded_impl!(i64, i64::MIN, i64::MAX)
|
||||
|
||||
bounded_impl!(f32, f32::MIN_VALUE, f32::MAX_VALUE)
|
||||
bounded_impl!(f64, f64::MIN_VALUE, f64::MAX_VALUE)
|
||||
|
||||
/// Saturating math operations
|
||||
pub trait Saturating {
|
||||
/// Saturating addition operator.
|
||||
/// Returns a+b, saturating at the numeric bounds instead of overflowing.
|
||||
fn saturating_add(self, v: Self) -> Self;
|
||||
|
||||
/// Saturating subtraction operator.
|
||||
/// Returns a-b, saturating at the numeric bounds instead of overflowing.
|
||||
fn saturating_sub(self, v: Self) -> Self;
|
||||
}
|
||||
|
||||
impl<T: CheckedAdd + CheckedSub + Zero + PartialOrd + Bounded> Saturating for T {
|
||||
#[inline]
|
||||
fn saturating_add(self, v: T) -> T {
|
||||
match self.checked_add(&v) {
|
||||
Some(x) => x,
|
||||
None => if v >= Zero::zero() {
|
||||
Bounded::max_value()
|
||||
} else {
|
||||
Bounded::min_value()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn saturating_sub(self, v: T) -> T {
|
||||
match self.checked_sub(&v) {
|
||||
Some(x) => x,
|
||||
None => if v >= Zero::zero() {
|
||||
Bounded::min_value()
|
||||
} else {
|
||||
Bounded::max_value()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Performs addition that returns `None` instead of wrapping around on overflow.
|
||||
pub trait CheckedAdd: Add<Self, Self> {
|
||||
/// Adds two numbers, checking for overflow. If overflow happens, `None` is returned.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
/// use num::CheckedAdd;
|
||||
/// assert_eq!(5u16.checked_add(&65530), Some(65535));
|
||||
/// assert_eq!(6u16.checked_add(&65530), None);
|
||||
/// ```
|
||||
fn checked_add(&self, v: &Self) -> Option<Self>;
|
||||
}
|
||||
|
||||
macro_rules! checked_impl(
|
||||
($trait_name:ident, $method:ident, $t:ty, $op:path) => {
|
||||
impl $trait_name for $t {
|
||||
#[inline]
|
||||
fn $method(&self, v: &$t) -> Option<$t> {
|
||||
unsafe {
|
||||
let (x, y) = $op(*self, *v);
|
||||
if y { None } else { Some(x) }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
macro_rules! checked_cast_impl(
|
||||
($trait_name:ident, $method:ident, $t:ty, $cast:ty, $op:path) => {
|
||||
impl $trait_name for $t {
|
||||
#[inline]
|
||||
fn $method(&self, v: &$t) -> Option<$t> {
|
||||
unsafe {
|
||||
let (x, y) = $op(*self as $cast, *v as $cast);
|
||||
if y { None } else { Some(x as $t) }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
#[cfg(target_word_size = "32")]
|
||||
checked_cast_impl!(CheckedAdd, checked_add, uint, u32, intrinsics::u32_add_with_overflow)
|
||||
#[cfg(target_word_size = "64")]
|
||||
checked_cast_impl!(CheckedAdd, checked_add, uint, u64, intrinsics::u64_add_with_overflow)
|
||||
|
||||
checked_impl!(CheckedAdd, checked_add, u8, intrinsics::u8_add_with_overflow)
|
||||
checked_impl!(CheckedAdd, checked_add, u16, intrinsics::u16_add_with_overflow)
|
||||
checked_impl!(CheckedAdd, checked_add, u32, intrinsics::u32_add_with_overflow)
|
||||
checked_impl!(CheckedAdd, checked_add, u64, intrinsics::u64_add_with_overflow)
|
||||
|
||||
#[cfg(target_word_size = "32")]
|
||||
checked_cast_impl!(CheckedAdd, checked_add, int, i32, intrinsics::i32_add_with_overflow)
|
||||
#[cfg(target_word_size = "64")]
|
||||
checked_cast_impl!(CheckedAdd, checked_add, int, i64, intrinsics::i64_add_with_overflow)
|
||||
|
||||
checked_impl!(CheckedAdd, checked_add, i8, intrinsics::i8_add_with_overflow)
|
||||
checked_impl!(CheckedAdd, checked_add, i16, intrinsics::i16_add_with_overflow)
|
||||
checked_impl!(CheckedAdd, checked_add, i32, intrinsics::i32_add_with_overflow)
|
||||
checked_impl!(CheckedAdd, checked_add, i64, intrinsics::i64_add_with_overflow)
|
||||
|
||||
/// Performs subtraction that returns `None` instead of wrapping around on underflow.
|
||||
pub trait CheckedSub: Sub<Self, Self> {
|
||||
/// Subtracts two numbers, checking for underflow. If underflow happens, `None` is returned.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
/// use num::CheckedSub;
|
||||
/// assert_eq!((-127i8).checked_sub(&1), Some(-128));
|
||||
/// assert_eq!((-128i8).checked_sub(&1), None);
|
||||
/// ```
|
||||
fn checked_sub(&self, v: &Self) -> Option<Self>;
|
||||
}
|
||||
|
||||
#[cfg(target_word_size = "32")]
|
||||
checked_cast_impl!(CheckedSub, checked_sub, uint, u32, intrinsics::u32_sub_with_overflow)
|
||||
#[cfg(target_word_size = "64")]
|
||||
checked_cast_impl!(CheckedSub, checked_sub, uint, u64, intrinsics::u64_sub_with_overflow)
|
||||
|
||||
checked_impl!(CheckedSub, checked_sub, u8, intrinsics::u8_sub_with_overflow)
|
||||
checked_impl!(CheckedSub, checked_sub, u16, intrinsics::u16_sub_with_overflow)
|
||||
checked_impl!(CheckedSub, checked_sub, u32, intrinsics::u32_sub_with_overflow)
|
||||
checked_impl!(CheckedSub, checked_sub, u64, intrinsics::u64_sub_with_overflow)
|
||||
|
||||
#[cfg(target_word_size = "32")]
|
||||
checked_cast_impl!(CheckedSub, checked_sub, int, i32, intrinsics::i32_sub_with_overflow)
|
||||
#[cfg(target_word_size = "64")]
|
||||
checked_cast_impl!(CheckedSub, checked_sub, int, i64, intrinsics::i64_sub_with_overflow)
|
||||
|
||||
checked_impl!(CheckedSub, checked_sub, i8, intrinsics::i8_sub_with_overflow)
|
||||
checked_impl!(CheckedSub, checked_sub, i16, intrinsics::i16_sub_with_overflow)
|
||||
checked_impl!(CheckedSub, checked_sub, i32, intrinsics::i32_sub_with_overflow)
|
||||
checked_impl!(CheckedSub, checked_sub, i64, intrinsics::i64_sub_with_overflow)
|
||||
|
||||
/// Performs multiplication that returns `None` instead of wrapping around on underflow or
|
||||
/// overflow.
|
||||
pub trait CheckedMul: Mul<Self, Self> {
|
||||
/// Multiplies two numbers, checking for underflow or overflow. If underflow or overflow
|
||||
/// happens, `None` is returned.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
/// use num::CheckedMul;
|
||||
/// assert_eq!(5u8.checked_mul(&51), Some(255));
|
||||
/// assert_eq!(5u8.checked_mul(&52), None);
|
||||
/// ```
|
||||
fn checked_mul(&self, v: &Self) -> Option<Self>;
|
||||
}
|
||||
|
||||
#[cfg(target_word_size = "32")]
|
||||
checked_cast_impl!(CheckedMul, checked_mul, uint, u32, intrinsics::u32_mul_with_overflow)
|
||||
#[cfg(target_word_size = "64")]
|
||||
checked_cast_impl!(CheckedMul, checked_mul, uint, u64, intrinsics::u64_mul_with_overflow)
|
||||
|
||||
checked_impl!(CheckedMul, checked_mul, u8, intrinsics::u8_mul_with_overflow)
|
||||
checked_impl!(CheckedMul, checked_mul, u16, intrinsics::u16_mul_with_overflow)
|
||||
checked_impl!(CheckedMul, checked_mul, u32, intrinsics::u32_mul_with_overflow)
|
||||
checked_impl!(CheckedMul, checked_mul, u64, intrinsics::u64_mul_with_overflow)
|
||||
|
||||
#[cfg(target_word_size = "32")]
|
||||
checked_cast_impl!(CheckedMul, checked_mul, int, i32, intrinsics::i32_mul_with_overflow)
|
||||
#[cfg(target_word_size = "64")]
|
||||
checked_cast_impl!(CheckedMul, checked_mul, int, i64, intrinsics::i64_mul_with_overflow)
|
||||
|
||||
checked_impl!(CheckedMul, checked_mul, i8, intrinsics::i8_mul_with_overflow)
|
||||
checked_impl!(CheckedMul, checked_mul, i16, intrinsics::i16_mul_with_overflow)
|
||||
checked_impl!(CheckedMul, checked_mul, i32, intrinsics::i32_mul_with_overflow)
|
||||
checked_impl!(CheckedMul, checked_mul, i64, intrinsics::i64_mul_with_overflow)
|
||||
|
||||
/// Performs division that returns `None` instead of panicking on division by zero and instead of
|
||||
/// wrapping around on underflow and overflow.
|
||||
pub trait CheckedDiv: Div<Self, Self> {
|
||||
/// Divides two numbers, checking for underflow, overflow and division by zero. If any of that
|
||||
/// happens, `None` is returned.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
/// use num::CheckedDiv;
|
||||
/// assert_eq!((-127i8).checked_div(&-1), Some(127));
|
||||
/// assert_eq!((-128i8).checked_div(&-1), None);
|
||||
/// assert_eq!((1i8).checked_div(&0), None);
|
||||
/// ```
|
||||
fn checked_div(&self, v: &Self) -> Option<Self>;
|
||||
}
|
||||
|
||||
macro_rules! checkeddiv_int_impl(
|
||||
($t:ty, $min:expr) => {
|
||||
impl CheckedDiv for $t {
|
||||
#[inline]
|
||||
fn checked_div(&self, v: &$t) -> Option<$t> {
|
||||
if *v == 0 || (*self == $min && *v == -1) {
|
||||
None
|
||||
} else {
|
||||
Some(*self / *v)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
checkeddiv_int_impl!(int, int::MIN)
|
||||
checkeddiv_int_impl!(i8, i8::MIN)
|
||||
checkeddiv_int_impl!(i16, i16::MIN)
|
||||
checkeddiv_int_impl!(i32, i32::MIN)
|
||||
checkeddiv_int_impl!(i64, i64::MIN)
|
||||
|
||||
macro_rules! checkeddiv_uint_impl(
|
||||
($($t:ty)*) => ($(
|
||||
impl CheckedDiv for $t {
|
||||
#[inline]
|
||||
fn checked_div(&self, v: &$t) -> Option<$t> {
|
||||
if *v == 0 {
|
||||
None
|
||||
} else {
|
||||
Some(*self / *v)
|
||||
}
|
||||
}
|
||||
}
|
||||
)*)
|
||||
)
|
||||
|
||||
checkeddiv_uint_impl!(uint u8 u16 u32 u64)
|
||||
|
Loading…
Reference in New Issue