2014-01-25 07:37:51 +00:00
|
|
|
// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
|
2012-12-04 00:48:01 +00:00
|
|
|
// 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.
|
|
|
|
|
2013-12-24 16:08:28 +00:00
|
|
|
//! Numeric traits and functions for generic mathematics
|
2013-07-29 22:59:43 +00:00
|
|
|
//!
|
|
|
|
//! These are implemented for the primitive numeric types in `std::{u8, u16,
|
|
|
|
//! u32, u64, uint, i8, i16, i32, i64, int, f32, f64, float}`.
|
2013-05-28 21:35:52 +00:00
|
|
|
|
2014-03-22 01:05:05 +00:00
|
|
|
#![allow(missing_doc)]
|
2013-05-28 21:35:52 +00:00
|
|
|
|
2014-03-05 06:19:14 +00:00
|
|
|
use clone::Clone;
|
2014-01-08 11:57:31 +00:00
|
|
|
use cmp::{Eq, Ord};
|
2014-03-26 23:01:11 +00:00
|
|
|
use kinds::Copy;
|
2014-01-17 21:53:00 +00:00
|
|
|
use mem::size_of;
|
2013-05-01 05:40:05 +00:00
|
|
|
use ops::{Add, Sub, Mul, Div, Rem, Neg};
|
2013-04-26 00:02:00 +00:00
|
|
|
use ops::{Not, BitAnd, BitOr, BitXor, Shl, Shr};
|
2013-08-07 19:40:09 +00:00
|
|
|
use option::{Option, Some, None};
|
2014-02-21 16:52:32 +00:00
|
|
|
use fmt::{Show, Binary, Octal, LowerHex, UpperHex};
|
2012-06-08 00:25:54 +00:00
|
|
|
|
2013-02-15 02:29:36 +00:00
|
|
|
pub mod strconv;
|
|
|
|
|
2013-04-26 15:01:53 +00:00
|
|
|
/// The base trait for numeric types
|
2013-04-13 16:19:35 +00:00
|
|
|
pub trait Num: Eq + Zero + One
|
|
|
|
+ Neg<Self>
|
|
|
|
+ Add<Self,Self>
|
|
|
|
+ Sub<Self,Self>
|
|
|
|
+ Mul<Self,Self>
|
2013-05-01 05:40:05 +00:00
|
|
|
+ Div<Self,Self>
|
2013-04-21 15:58:53 +00:00
|
|
|
+ Rem<Self,Self> {}
|
2013-04-13 16:19:35 +00:00
|
|
|
|
2014-02-16 20:20:01 +00:00
|
|
|
/// Simultaneous division and remainder
|
|
|
|
#[inline]
|
|
|
|
pub fn div_rem<T: Div<T, T> + Rem<T, T>>(x: T, y: T) -> (T, T) {
|
|
|
|
(x / y, x % y)
|
|
|
|
}
|
|
|
|
|
2014-01-18 06:08:23 +00:00
|
|
|
/// 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
|
|
|
|
///
|
2014-02-20 09:14:51 +00:00
|
|
|
/// ~~~notrust
|
2014-01-18 06:08:23 +00:00
|
|
|
/// 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.
|
2013-04-25 05:30:56 +00:00
|
|
|
fn is_zero(&self) -> bool;
|
2012-12-20 15:14:38 +00:00
|
|
|
}
|
|
|
|
|
2014-01-18 06:08:23 +00:00
|
|
|
/// Returns the additive identity, `0`.
|
2013-07-29 22:58:46 +00:00
|
|
|
#[inline(always)] pub fn zero<T: Zero>() -> T { Zero::zero() }
|
|
|
|
|
2014-01-18 06:08:23 +00:00
|
|
|
/// Defines a multiplicative identity element for `Self`.
|
|
|
|
pub trait One: Mul<Self, Self> {
|
|
|
|
/// Returns the multiplicative identity element of `Self`, `1`.
|
|
|
|
///
|
|
|
|
/// # Laws
|
|
|
|
///
|
2014-02-20 09:14:51 +00:00
|
|
|
/// ~~~notrust
|
2014-01-18 06:08:23 +00:00
|
|
|
/// 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;
|
2012-12-20 15:14:38 +00:00
|
|
|
}
|
2013-01-27 02:05:20 +00:00
|
|
|
|
2014-01-18 06:08:23 +00:00
|
|
|
/// Returns the multiplicative identity, `1`.
|
2013-07-29 22:58:46 +00:00
|
|
|
#[inline(always)] pub fn one<T: One>() -> T { One::one() }
|
|
|
|
|
2014-03-16 22:59:04 +00:00
|
|
|
/// Useful functions for signed numbers (i.e. numbers that can be negative).
|
|
|
|
pub trait Signed: Num + Neg<Self> {
|
|
|
|
/// Computes the absolute value.
|
|
|
|
///
|
|
|
|
/// For float, f32, and f64, `NaN` will be returned if the number is `NaN`.
|
2013-04-23 07:59:49 +00:00
|
|
|
fn abs(&self) -> Self;
|
2014-03-16 22:59:04 +00:00
|
|
|
|
|
|
|
/// 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.
|
2013-05-07 04:36:32 +00:00
|
|
|
fn abs_sub(&self, other: &Self) -> Self;
|
2014-03-16 22:59:04 +00:00
|
|
|
|
|
|
|
/// Returns the sign of the number.
|
|
|
|
///
|
|
|
|
/// For `float`, `f32`, `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 `int`:
|
|
|
|
/// * `0` if the number is zero
|
|
|
|
/// * `1` if the number is positive
|
|
|
|
/// * `-1` if the number is negative
|
2013-04-23 07:59:49 +00:00
|
|
|
fn signum(&self) -> Self;
|
2013-05-07 04:36:32 +00:00
|
|
|
|
2014-03-16 22:59:04 +00:00
|
|
|
/// Returns true if the number is positive and false if the number is zero or negative.
|
2013-04-23 07:59:49 +00:00
|
|
|
fn is_positive(&self) -> bool;
|
2014-03-16 22:59:04 +00:00
|
|
|
|
|
|
|
/// Returns true if the number is negative and false if the number is zero or positive.
|
2013-04-23 07:59:49 +00:00
|
|
|
fn is_negative(&self) -> bool;
|
|
|
|
}
|
|
|
|
|
2013-09-24 17:25:45 +00:00
|
|
|
/// Computes the absolute value.
|
|
|
|
///
|
|
|
|
/// For float, f32, and f64, `NaN` will be returned if the number is `NaN`
|
2014-03-16 22:59:04 +00:00
|
|
|
#[inline(always)]
|
|
|
|
pub fn abs<T: Signed>(value: T) -> T {
|
|
|
|
value.abs()
|
|
|
|
}
|
|
|
|
|
2013-09-24 17:25:45 +00:00
|
|
|
/// 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.
|
2014-03-16 22:59:04 +00:00
|
|
|
#[inline(always)]
|
|
|
|
pub fn abs_sub<T: Signed>(x: T, y: T) -> T {
|
|
|
|
x.abs_sub(&y)
|
|
|
|
}
|
|
|
|
|
2013-09-24 17:25:45 +00:00
|
|
|
/// Returns the sign of the number.
|
|
|
|
///
|
|
|
|
/// For float, f32, f64:
|
2013-10-29 00:34:33 +00:00
|
|
|
/// - `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`
|
2013-09-24 17:25:45 +00:00
|
|
|
///
|
|
|
|
/// For int:
|
|
|
|
/// - `0` if the number is zero
|
|
|
|
/// - `1` if the number is positive
|
|
|
|
/// - `-1` if the number is negative
|
Replaces the free-standing functions in f32, &c.
The free-standing functions in f32, f64, i8, i16, i32, i64, u8, u16,
u32, u64, float, int, and uint are replaced with generic functions in
num instead.
If you were previously using any of those functions, just replace them
with the corresponding function with the same name in num.
Note: If you were using a function that corresponds to an operator, use
the operator instead.
2013-07-08 16:05:17 +00:00
|
|
|
#[inline(always)] pub fn signum<T: Signed>(value: T) -> T { value.signum() }
|
2013-04-23 07:59:49 +00:00
|
|
|
|
2014-04-11 23:07:45 +00:00
|
|
|
/// A trait for values which cannot be negative
|
Replaces the free-standing functions in f32, &c.
The free-standing functions in f32, f64, i8, i16, i32, i64, u8, u16,
u32, u64, float, int, and uint are replaced with generic functions in
num instead.
If you were previously using any of those functions, just replace them
with the corresponding function with the same name in num.
Note: If you were using a function that corresponds to an operator, use
the operator instead.
2013-07-08 16:05:17 +00:00
|
|
|
pub trait Unsigned: Num {}
|
2013-01-16 01:30:16 +00:00
|
|
|
|
2014-01-19 13:39:05 +00:00
|
|
|
/// Raises a value to the power of exp, using exponentiation by squaring.
|
2014-01-12 20:02:59 +00:00
|
|
|
///
|
|
|
|
/// # Example
|
|
|
|
///
|
|
|
|
/// ```rust
|
|
|
|
/// use std::num;
|
|
|
|
///
|
2014-01-19 13:39:05 +00:00
|
|
|
/// assert_eq!(num::pow(2, 4), 16);
|
2014-01-12 20:02:59 +00:00
|
|
|
/// ```
|
|
|
|
#[inline]
|
2014-01-19 13:39:05 +00:00
|
|
|
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;
|
2014-01-12 20:02:59 +00:00
|
|
|
}
|
2014-01-19 13:39:05 +00:00
|
|
|
acc
|
2014-01-12 20:02:59 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-04-11 23:07:45 +00:00
|
|
|
/// Numbers which have upper and lower bounds
|
2014-01-15 00:32:04 +00:00
|
|
|
pub trait Bounded {
|
|
|
|
// FIXME (#5527): These should be associated constants
|
2014-04-25 00:09:58 +00:00
|
|
|
/// returns the smallest finite number this type can represent
|
2014-01-15 00:32:04 +00:00
|
|
|
fn min_value() -> Self;
|
2014-04-25 00:09:58 +00:00
|
|
|
/// returns the largest finite number this type can represent
|
2014-01-15 00:32:04 +00:00
|
|
|
fn max_value() -> Self;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Numbers with a fixed binary representation.
|
|
|
|
pub trait Bitwise: Bounded
|
|
|
|
+ Not<Self>
|
2013-04-26 00:02:00 +00:00
|
|
|
+ BitAnd<Self,Self>
|
|
|
|
+ BitOr<Self,Self>
|
|
|
|
+ BitXor<Self,Self>
|
|
|
|
+ Shl<Self,Self>
|
2014-01-15 00:32:04 +00:00
|
|
|
+ Shr<Self,Self> {
|
2014-02-16 23:12:10 +00:00
|
|
|
/// Returns the number of ones in the binary representation of the number.
|
2013-11-11 04:39:16 +00:00
|
|
|
///
|
|
|
|
/// # Example
|
|
|
|
///
|
|
|
|
/// ```rust
|
2014-01-15 00:32:04 +00:00
|
|
|
/// use std::num::Bitwise;
|
|
|
|
///
|
2014-02-16 23:12:10 +00:00
|
|
|
/// let n = 0b01001100u8;
|
|
|
|
/// assert_eq!(n.count_ones(), 3);
|
|
|
|
/// ```
|
|
|
|
fn count_ones(&self) -> Self;
|
|
|
|
|
|
|
|
/// Returns the number of zeros in the binary representation of the number.
|
|
|
|
///
|
|
|
|
/// # Example
|
|
|
|
///
|
|
|
|
/// ```rust
|
|
|
|
/// use std::num::Bitwise;
|
|
|
|
///
|
|
|
|
/// let n = 0b01001100u8;
|
|
|
|
/// assert_eq!(n.count_zeros(), 5);
|
2013-11-11 04:39:16 +00:00
|
|
|
/// ```
|
2014-02-16 23:12:10 +00:00
|
|
|
#[inline]
|
|
|
|
fn count_zeros(&self) -> Self {
|
|
|
|
(!*self).count_ones()
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Returns the number of leading zeros in the in the binary representation
|
|
|
|
/// of the number.
|
2013-11-11 04:39:16 +00:00
|
|
|
///
|
|
|
|
/// # Example
|
|
|
|
///
|
|
|
|
/// ```rust
|
2014-01-15 00:32:04 +00:00
|
|
|
/// use std::num::Bitwise;
|
|
|
|
///
|
2013-11-11 04:39:16 +00:00
|
|
|
/// let n = 0b0101000u16;
|
|
|
|
/// assert_eq!(n.leading_zeros(), 10);
|
|
|
|
/// ```
|
2013-04-26 06:27:51 +00:00
|
|
|
fn leading_zeros(&self) -> Self;
|
2014-02-16 23:12:10 +00:00
|
|
|
|
|
|
|
/// Returns the number of trailing zeros in the in the binary representation
|
|
|
|
/// of the number.
|
2013-11-11 04:39:16 +00:00
|
|
|
///
|
|
|
|
/// # Example
|
|
|
|
///
|
|
|
|
/// ```rust
|
2014-01-15 00:32:04 +00:00
|
|
|
/// use std::num::Bitwise;
|
|
|
|
///
|
2013-11-11 04:39:16 +00:00
|
|
|
/// let n = 0b0101000u16;
|
|
|
|
/// assert_eq!(n.trailing_zeros(), 3);
|
|
|
|
/// ```
|
2013-04-26 06:27:51 +00:00
|
|
|
fn trailing_zeros(&self) -> Self;
|
|
|
|
}
|
|
|
|
|
2013-04-26 00:02:00 +00:00
|
|
|
/// Specifies the available operations common to all of Rust's core numeric primitives.
|
|
|
|
/// These may not always make sense from a purely mathematical point of view, but
|
|
|
|
/// may be useful for systems programming.
|
2014-03-26 23:01:11 +00:00
|
|
|
pub trait Primitive: Copy
|
2014-02-21 16:51:56 +00:00
|
|
|
+ Clone
|
2013-09-07 07:16:56 +00:00
|
|
|
+ Num
|
2013-04-26 00:02:00 +00:00
|
|
|
+ NumCast
|
2014-02-06 07:34:33 +00:00
|
|
|
+ Ord
|
2014-01-17 21:53:00 +00:00
|
|
|
+ Bounded {}
|
2013-04-26 00:02:00 +00:00
|
|
|
|
|
|
|
/// A collection of traits relevant to primitive signed and unsigned integers
|
2014-02-16 20:20:01 +00:00
|
|
|
pub trait Int: Primitive
|
2014-01-30 05:35:17 +00:00
|
|
|
+ Bitwise
|
|
|
|
+ CheckedAdd
|
|
|
|
+ CheckedSub
|
2014-02-14 20:54:15 +00:00
|
|
|
+ CheckedMul
|
2014-02-21 16:52:32 +00:00
|
|
|
+ CheckedDiv
|
|
|
|
+ Show
|
|
|
|
+ Binary
|
|
|
|
+ Octal
|
|
|
|
+ LowerHex
|
|
|
|
+ UpperHex {}
|
2014-01-30 05:35:17 +00:00
|
|
|
|
|
|
|
/// Returns the smallest power of 2 greater than or equal to `n`.
|
|
|
|
#[inline]
|
|
|
|
pub fn next_power_of_two<T: Unsigned + Int>(n: T) -> T {
|
|
|
|
let halfbits: T = cast(size_of::<T>() * 4).unwrap();
|
|
|
|
let mut tmp: T = n - one();
|
|
|
|
let mut shift: T = one();
|
|
|
|
while shift <= halfbits {
|
|
|
|
tmp = tmp | (tmp >> shift);
|
|
|
|
shift = shift << one();
|
|
|
|
}
|
|
|
|
tmp + one()
|
|
|
|
}
|
|
|
|
|
2014-03-27 01:58:08 +00:00
|
|
|
// Returns `true` iff `n == 2^k` for some k.
|
|
|
|
#[inline]
|
|
|
|
pub fn is_power_of_two<T: Unsigned + Int>(n: T) -> bool {
|
|
|
|
(n - one()) & n == zero()
|
|
|
|
}
|
|
|
|
|
2014-01-30 05:35:17 +00:00
|
|
|
/// Returns the smallest power of 2 greater than or equal to `n`. If the next
|
|
|
|
/// power of two is greater than the type's maximum value, `None` is returned,
|
|
|
|
/// otherwise the power of 2 is wrapped in `Some`.
|
|
|
|
#[inline]
|
|
|
|
pub fn checked_next_power_of_two<T: Unsigned + Int>(n: T) -> Option<T> {
|
|
|
|
let halfbits: T = cast(size_of::<T>() * 4).unwrap();
|
|
|
|
let mut tmp: T = n - one();
|
|
|
|
let mut shift: T = one();
|
|
|
|
while shift <= halfbits {
|
|
|
|
tmp = tmp | (tmp >> shift);
|
|
|
|
shift = shift << one();
|
|
|
|
}
|
|
|
|
tmp.checked_add(&one())
|
|
|
|
}
|
2013-04-26 00:02:00 +00:00
|
|
|
|
2013-05-07 10:30:51 +00:00
|
|
|
/// Used for representing the classification of floating point numbers
|
2014-02-28 09:23:06 +00:00
|
|
|
#[deriving(Eq, Show)]
|
2013-05-07 10:30:51 +00:00
|
|
|
pub enum FPCategory {
|
|
|
|
/// "Not a Number", often obtained by dividing by zero
|
|
|
|
FPNaN,
|
|
|
|
/// Positive or negative infinity
|
|
|
|
FPInfinite ,
|
|
|
|
/// Positive or negative zero
|
|
|
|
FPZero,
|
|
|
|
/// De-normalized floating point representation (less precise than `FPNormal`)
|
|
|
|
FPSubnormal,
|
|
|
|
/// A regular floating point number
|
|
|
|
FPNormal,
|
|
|
|
}
|
|
|
|
|
2014-03-16 22:59:04 +00:00
|
|
|
/// Operations on primitive floating point numbers.
|
2014-03-25 17:23:51 +00:00
|
|
|
// FIXME(#5527): In a future version of Rust, many of these functions will
|
|
|
|
// become constants.
|
|
|
|
//
|
|
|
|
// FIXME(#8888): Several of these functions have a parameter named
|
|
|
|
// `unused_self`. Removing it requires #8888 to be fixed.
|
2014-04-18 02:48:48 +00:00
|
|
|
pub trait Float: Signed + Primitive {
|
2014-03-16 22:59:04 +00:00
|
|
|
/// Returns the NaN value.
|
2013-09-19 05:37:34 +00:00
|
|
|
fn nan() -> Self;
|
2014-03-16 22:59:04 +00:00
|
|
|
/// Returns the infinite value.
|
2013-04-26 00:22:08 +00:00
|
|
|
fn infinity() -> Self;
|
2014-03-16 22:59:04 +00:00
|
|
|
/// Returns the negative infinite value.
|
2013-04-26 00:22:08 +00:00
|
|
|
fn neg_infinity() -> Self;
|
2014-03-16 22:59:04 +00:00
|
|
|
/// Returns -0.0.
|
2013-04-26 00:22:08 +00:00
|
|
|
fn neg_zero() -> Self;
|
|
|
|
|
2014-03-16 22:59:04 +00:00
|
|
|
/// Returns true if this value is NaN and false otherwise.
|
2014-04-18 03:49:37 +00:00
|
|
|
fn is_nan(self) -> bool;
|
2014-04-18 16:15:09 +00:00
|
|
|
/// Returns true if this value is positive infinity or negative infinity and
|
|
|
|
/// false otherwise.
|
2014-04-18 03:49:37 +00:00
|
|
|
fn is_infinite(self) -> bool;
|
2014-03-16 22:59:04 +00:00
|
|
|
/// Returns true if this number is neither infinite nor NaN.
|
2014-04-18 03:49:37 +00:00
|
|
|
fn is_finite(self) -> bool;
|
2014-03-16 22:59:04 +00:00
|
|
|
/// Returns true if this number is neither zero, infinite, denormal, or NaN.
|
2014-04-18 03:49:37 +00:00
|
|
|
fn is_normal(self) -> bool;
|
2014-03-16 22:59:04 +00:00
|
|
|
/// Returns the category that this number falls into.
|
2014-04-18 03:49:37 +00:00
|
|
|
fn classify(self) -> FPCategory;
|
2013-04-26 15:02:30 +00:00
|
|
|
|
2014-04-25 00:09:58 +00:00
|
|
|
// FIXME (#5527): These should be associated constants
|
|
|
|
|
2014-03-16 22:59:04 +00:00
|
|
|
/// Returns the number of binary digits of mantissa that this type supports.
|
2013-08-08 18:38:10 +00:00
|
|
|
fn mantissa_digits(unused_self: Option<Self>) -> uint;
|
2014-04-23 19:04:34 +00:00
|
|
|
/// Returns the number of base-10 digits of precision that this type supports.
|
2013-08-08 18:38:10 +00:00
|
|
|
fn digits(unused_self: Option<Self>) -> uint;
|
2014-04-23 19:04:34 +00:00
|
|
|
/// Returns the difference between 1.0 and the smallest representable number larger than 1.0.
|
2013-04-26 23:07:40 +00:00
|
|
|
fn epsilon() -> Self;
|
2014-03-16 22:59:04 +00:00
|
|
|
/// Returns the minimum binary exponent that this type can represent.
|
2013-08-08 18:38:10 +00:00
|
|
|
fn min_exp(unused_self: Option<Self>) -> int;
|
2014-03-16 22:59:04 +00:00
|
|
|
/// Returns the maximum binary exponent that this type can represent.
|
2013-08-08 18:38:10 +00:00
|
|
|
fn max_exp(unused_self: Option<Self>) -> int;
|
2014-03-16 22:59:04 +00:00
|
|
|
/// Returns the minimum base-10 exponent that this type can represent.
|
2013-08-08 18:38:10 +00:00
|
|
|
fn min_10_exp(unused_self: Option<Self>) -> int;
|
2014-03-16 22:59:04 +00:00
|
|
|
/// Returns the maximum base-10 exponent that this type can represent.
|
2013-08-08 18:38:10 +00:00
|
|
|
fn max_10_exp(unused_self: Option<Self>) -> int;
|
2014-04-25 00:09:58 +00:00
|
|
|
/// Returns the smallest normalized positive number that this type can represent.
|
|
|
|
fn min_pos_value(unused_self: Option<Self>) -> Self;
|
2013-04-26 23:07:40 +00:00
|
|
|
|
2014-04-18 16:15:09 +00:00
|
|
|
/// Constructs a floating point number created by multiplying `x` by 2
|
|
|
|
/// raised to the power of `exp`.
|
2013-05-14 01:24:55 +00:00
|
|
|
fn ldexp(x: Self, exp: int) -> Self;
|
2014-04-18 16:15:09 +00:00
|
|
|
/// Breaks the number into a normalized fraction and a base-2 exponent,
|
|
|
|
/// satisfying:
|
2014-03-16 22:59:04 +00:00
|
|
|
///
|
|
|
|
/// * `self = x * pow(2, exp)`
|
|
|
|
///
|
|
|
|
/// * `0.5 <= abs(x) < 1.0`
|
2014-04-18 03:49:37 +00:00
|
|
|
fn frexp(self) -> (Self, int);
|
2014-03-16 22:59:04 +00:00
|
|
|
/// Returns the mantissa, exponent and sign as integers, respectively.
|
2014-04-18 03:49:37 +00:00
|
|
|
fn integer_decode(self) -> (u64, i16, i8);
|
2014-02-16 15:23:33 +00:00
|
|
|
|
2014-04-18 16:15:09 +00:00
|
|
|
/// Returns the next representable floating-point value in the direction of
|
|
|
|
/// `other`.
|
|
|
|
fn next_after(self, other: Self) -> Self;
|
|
|
|
|
2014-04-18 02:48:48 +00:00
|
|
|
/// Return the largest integer less than or equal to a number.
|
2014-04-18 03:49:37 +00:00
|
|
|
fn floor(self) -> Self;
|
2014-04-18 02:48:48 +00:00
|
|
|
/// Return the smallest integer greater than or equal to a number.
|
2014-04-18 03:49:37 +00:00
|
|
|
fn ceil(self) -> Self;
|
2014-04-18 02:48:48 +00:00
|
|
|
/// Return the nearest integer to a number. Round half-way cases away from
|
|
|
|
/// `0.0`.
|
2014-04-18 03:49:37 +00:00
|
|
|
fn round(self) -> Self;
|
2014-04-18 02:48:48 +00:00
|
|
|
/// Return the integer part of a number.
|
2014-04-18 03:49:37 +00:00
|
|
|
fn trunc(self) -> Self;
|
2014-04-18 02:48:48 +00:00
|
|
|
/// Return the fractional part of a number.
|
2014-04-18 03:49:37 +00:00
|
|
|
fn fract(self) -> Self;
|
2013-05-14 01:24:55 +00:00
|
|
|
|
2014-04-18 16:15:09 +00:00
|
|
|
/// Returns the maximum of the two numbers.
|
|
|
|
fn max(self, other: Self) -> Self;
|
|
|
|
/// Returns the minimum of the two numbers.
|
|
|
|
fn min(self, other: Self) -> Self;
|
2014-03-16 22:59:04 +00:00
|
|
|
|
2014-04-18 16:15:09 +00:00
|
|
|
/// Fused multiply-add. Computes `(self * a) + b` with only one rounding
|
|
|
|
/// error. This produces a more accurate result with better performance than
|
|
|
|
/// a separate multiplication operation followed by an add.
|
|
|
|
fn mul_add(self, a: Self, b: Self) -> Self;
|
|
|
|
/// Take the reciprocal (inverse) of a number, `1/x`.
|
|
|
|
fn recip(self) -> Self;
|
2014-03-16 22:59:04 +00:00
|
|
|
|
2014-04-18 16:15:09 +00:00
|
|
|
/// Raise a number to an integer power.
|
|
|
|
///
|
|
|
|
/// Using this function is generally faster than using `powf`
|
|
|
|
fn powi(self, n: i32) -> Self;
|
|
|
|
/// Raise a number to a floating point power.
|
|
|
|
fn powf(self, n: Self) -> Self;
|
2014-03-16 22:59:04 +00:00
|
|
|
|
2014-04-18 16:15:09 +00:00
|
|
|
/// sqrt(2.0).
|
|
|
|
fn sqrt2() -> Self;
|
|
|
|
/// 1.0 / sqrt(2.0).
|
|
|
|
fn frac_1_sqrt2() -> Self;
|
2013-12-01 23:47:19 +00:00
|
|
|
|
2014-04-18 16:15:09 +00:00
|
|
|
/// Take the square root of a number.
|
|
|
|
fn sqrt(self) -> Self;
|
|
|
|
/// Take the reciprocal (inverse) square root of a number, `1/sqrt(x)`.
|
|
|
|
fn rsqrt(self) -> Self;
|
|
|
|
/// Take the cubic root of a number.
|
|
|
|
fn cbrt(self) -> Self;
|
|
|
|
/// Calculate the length of the hypotenuse of a right-angle triangle given
|
|
|
|
/// legs of length `x` and `y`.
|
|
|
|
fn hypot(self, other: Self) -> Self;
|
2014-02-16 15:23:33 +00:00
|
|
|
|
2014-04-25 00:09:58 +00:00
|
|
|
// FIXME (#5527): These should be associated constants
|
|
|
|
|
2014-03-16 22:59:04 +00:00
|
|
|
/// Archimedes' constant.
|
2014-02-16 15:23:33 +00:00
|
|
|
fn pi() -> Self;
|
2014-03-16 22:59:04 +00:00
|
|
|
/// 2.0 * pi.
|
2014-02-16 15:23:33 +00:00
|
|
|
fn two_pi() -> Self;
|
2014-03-16 22:59:04 +00:00
|
|
|
/// pi / 2.0.
|
2014-02-16 15:23:33 +00:00
|
|
|
fn frac_pi_2() -> Self;
|
2014-03-16 22:59:04 +00:00
|
|
|
/// pi / 3.0.
|
2014-02-16 15:23:33 +00:00
|
|
|
fn frac_pi_3() -> Self;
|
2014-03-16 22:59:04 +00:00
|
|
|
/// pi / 4.0.
|
2014-02-16 15:23:33 +00:00
|
|
|
fn frac_pi_4() -> Self;
|
2014-03-16 22:59:04 +00:00
|
|
|
/// pi / 6.0.
|
2014-02-16 15:23:33 +00:00
|
|
|
fn frac_pi_6() -> Self;
|
2014-03-16 22:59:04 +00:00
|
|
|
/// pi / 8.0.
|
2014-02-16 15:23:33 +00:00
|
|
|
fn frac_pi_8() -> Self;
|
2014-03-16 22:59:04 +00:00
|
|
|
/// 1.0 / pi.
|
2014-02-16 15:23:33 +00:00
|
|
|
fn frac_1_pi() -> Self;
|
2014-03-16 22:59:04 +00:00
|
|
|
/// 2.0 / pi.
|
2014-02-16 15:23:33 +00:00
|
|
|
fn frac_2_pi() -> Self;
|
2014-03-16 22:59:04 +00:00
|
|
|
/// 2.0 / sqrt(pi).
|
2014-02-16 15:23:33 +00:00
|
|
|
fn frac_2_sqrtpi() -> Self;
|
2014-03-16 22:59:04 +00:00
|
|
|
|
2014-02-16 15:23:33 +00:00
|
|
|
/// Computes the sine of a number (in radians).
|
2014-04-18 03:49:37 +00:00
|
|
|
fn sin(self) -> Self;
|
2014-02-16 15:23:33 +00:00
|
|
|
/// Computes the cosine of a number (in radians).
|
2014-04-18 03:49:37 +00:00
|
|
|
fn cos(self) -> Self;
|
2014-02-16 15:23:33 +00:00
|
|
|
/// Computes the tangent of a number (in radians).
|
2014-04-18 03:49:37 +00:00
|
|
|
fn tan(self) -> Self;
|
2014-02-16 15:23:33 +00:00
|
|
|
|
|
|
|
/// Computes the arcsine of a number. Return value is in radians in
|
|
|
|
/// the range [-pi/2, pi/2] or NaN if the number is outside the range
|
|
|
|
/// [-1, 1].
|
2014-04-18 03:49:37 +00:00
|
|
|
fn asin(self) -> Self;
|
2014-02-16 15:23:33 +00:00
|
|
|
/// Computes the arccosine of a number. Return value is in radians in
|
|
|
|
/// the range [0, pi] or NaN if the number is outside the range
|
|
|
|
/// [-1, 1].
|
2014-04-18 03:49:37 +00:00
|
|
|
fn acos(self) -> Self;
|
2014-02-16 15:23:33 +00:00
|
|
|
/// Computes the arctangent of a number. Return value is in radians in the
|
|
|
|
/// range [-pi/2, pi/2];
|
2014-04-18 03:49:37 +00:00
|
|
|
fn atan(self) -> Self;
|
2014-02-16 15:23:33 +00:00
|
|
|
/// Computes the four quadrant arctangent of a number, `y`, and another
|
|
|
|
/// number `x`. Return value is in radians in the range [-pi, pi].
|
2014-04-18 03:49:37 +00:00
|
|
|
fn atan2(self, other: Self) -> Self;
|
2014-02-16 15:23:33 +00:00
|
|
|
/// Simultaneously computes the sine and cosine of the number, `x`. Returns
|
|
|
|
/// `(sin(x), cos(x))`.
|
2014-04-18 03:49:37 +00:00
|
|
|
fn sin_cos(self) -> (Self, Self);
|
2014-02-16 15:23:33 +00:00
|
|
|
|
2014-04-18 16:15:09 +00:00
|
|
|
/// Euler's number.
|
|
|
|
fn e() -> Self;
|
|
|
|
/// log2(e).
|
|
|
|
fn log2_e() -> Self;
|
|
|
|
/// log10(e).
|
|
|
|
fn log10_e() -> Self;
|
|
|
|
/// ln(2.0).
|
|
|
|
fn ln_2() -> Self;
|
|
|
|
/// ln(10.0).
|
|
|
|
fn ln_10() -> Self;
|
2014-02-16 15:23:33 +00:00
|
|
|
|
|
|
|
/// Returns `e^(self)`, (the exponential function).
|
2014-04-18 03:49:37 +00:00
|
|
|
fn exp(self) -> Self;
|
2014-02-16 15:23:33 +00:00
|
|
|
/// Returns 2 raised to the power of the number, `2^(self)`.
|
2014-04-18 03:49:37 +00:00
|
|
|
fn exp2(self) -> Self;
|
2014-04-18 16:15:09 +00:00
|
|
|
/// Returns the exponential of the number, minus 1, in a way that is
|
|
|
|
/// accurate even if the number is close to zero.
|
|
|
|
fn exp_m1(self) -> Self;
|
2014-02-16 15:23:33 +00:00
|
|
|
/// Returns the natural logarithm of the number.
|
2014-04-18 03:49:37 +00:00
|
|
|
fn ln(self) -> Self;
|
2014-02-16 15:23:33 +00:00
|
|
|
/// Returns the logarithm of the number with respect to an arbitrary base.
|
2014-04-18 03:49:37 +00:00
|
|
|
fn log(self, base: Self) -> Self;
|
2014-02-16 15:23:33 +00:00
|
|
|
/// Returns the base 2 logarithm of the number.
|
2014-04-18 03:49:37 +00:00
|
|
|
fn log2(self) -> Self;
|
2014-02-16 15:23:33 +00:00
|
|
|
/// Returns the base 10 logarithm of the number.
|
2014-04-18 03:49:37 +00:00
|
|
|
fn log10(self) -> Self;
|
2014-04-18 16:15:09 +00:00
|
|
|
/// Returns the natural logarithm of the number plus 1 (`ln(1+n)`) more
|
|
|
|
/// accurately than if the operations were performed separately.
|
|
|
|
fn ln_1p(self) -> Self;
|
2014-02-16 15:23:33 +00:00
|
|
|
|
|
|
|
/// Hyperbolic sine function.
|
2014-04-18 03:49:37 +00:00
|
|
|
fn sinh(self) -> Self;
|
2014-02-16 15:23:33 +00:00
|
|
|
/// Hyperbolic cosine function.
|
2014-04-18 03:49:37 +00:00
|
|
|
fn cosh(self) -> Self;
|
2014-02-16 15:23:33 +00:00
|
|
|
/// Hyperbolic tangent function.
|
2014-04-18 03:49:37 +00:00
|
|
|
fn tanh(self) -> Self;
|
2014-02-16 15:23:33 +00:00
|
|
|
/// Inverse hyperbolic sine function.
|
2014-04-18 03:49:37 +00:00
|
|
|
fn asinh(self) -> Self;
|
2014-02-16 15:23:33 +00:00
|
|
|
/// Inverse hyperbolic cosine function.
|
2014-04-18 03:49:37 +00:00
|
|
|
fn acosh(self) -> Self;
|
2014-02-16 15:23:33 +00:00
|
|
|
/// Inverse hyperbolic tangent function.
|
2014-04-18 03:49:37 +00:00
|
|
|
fn atanh(self) -> Self;
|
2014-02-16 15:23:33 +00:00
|
|
|
|
|
|
|
/// Convert radians to degrees.
|
2014-04-18 03:49:37 +00:00
|
|
|
fn to_degrees(self) -> Self;
|
2014-02-16 15:23:33 +00:00
|
|
|
/// Convert degrees to radians.
|
2014-04-18 03:49:37 +00:00
|
|
|
fn to_radians(self) -> Self;
|
2013-04-26 00:22:08 +00:00
|
|
|
}
|
|
|
|
|
2013-09-15 16:50:17 +00:00
|
|
|
/// A generic trait for converting a value to a number.
|
|
|
|
pub trait ToPrimitive {
|
|
|
|
/// Converts the value of `self` to an `int`.
|
2013-09-18 02:28:35 +00:00
|
|
|
#[inline]
|
|
|
|
fn to_int(&self) -> Option<int> {
|
2013-09-28 00:09:18 +00:00
|
|
|
self.to_i64().and_then(|x| x.to_int())
|
2013-09-18 02:28:35 +00:00
|
|
|
}
|
2013-09-15 16:50:17 +00:00
|
|
|
|
|
|
|
/// Converts the value of `self` to an `i8`.
|
|
|
|
#[inline]
|
|
|
|
fn to_i8(&self) -> Option<i8> {
|
2013-09-28 00:09:18 +00:00
|
|
|
self.to_i64().and_then(|x| x.to_i8())
|
2013-09-15 16:50:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Converts the value of `self` to an `i16`.
|
|
|
|
#[inline]
|
|
|
|
fn to_i16(&self) -> Option<i16> {
|
2013-09-28 00:09:18 +00:00
|
|
|
self.to_i64().and_then(|x| x.to_i16())
|
2013-09-15 16:50:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Converts the value of `self` to an `i32`.
|
|
|
|
#[inline]
|
|
|
|
fn to_i32(&self) -> Option<i32> {
|
2013-09-28 00:09:18 +00:00
|
|
|
self.to_i64().and_then(|x| x.to_i32())
|
2013-09-15 16:50:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Converts the value of `self` to an `i64`.
|
2013-09-18 02:28:35 +00:00
|
|
|
fn to_i64(&self) -> Option<i64>;
|
|
|
|
|
|
|
|
/// Converts the value of `self` to an `uint`.
|
2013-09-15 16:50:17 +00:00
|
|
|
#[inline]
|
2013-09-18 02:28:35 +00:00
|
|
|
fn to_uint(&self) -> Option<uint> {
|
2013-09-28 00:09:18 +00:00
|
|
|
self.to_u64().and_then(|x| x.to_uint())
|
2013-09-15 16:50:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Converts the value of `self` to an `u8`.
|
|
|
|
#[inline]
|
|
|
|
fn to_u8(&self) -> Option<u8> {
|
2013-09-28 00:09:18 +00:00
|
|
|
self.to_u64().and_then(|x| x.to_u8())
|
2013-09-15 16:50:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Converts the value of `self` to an `u16`.
|
|
|
|
#[inline]
|
|
|
|
fn to_u16(&self) -> Option<u16> {
|
2013-09-28 00:09:18 +00:00
|
|
|
self.to_u64().and_then(|x| x.to_u16())
|
2013-09-15 16:50:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Converts the value of `self` to an `u32`.
|
|
|
|
#[inline]
|
|
|
|
fn to_u32(&self) -> Option<u32> {
|
2013-09-28 00:09:18 +00:00
|
|
|
self.to_u64().and_then(|x| x.to_u32())
|
2013-09-15 16:50:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Converts the value of `self` to an `u64`.
|
|
|
|
#[inline]
|
2013-10-08 02:56:30 +00:00
|
|
|
fn to_u64(&self) -> Option<u64>;
|
2013-09-15 16:50:17 +00:00
|
|
|
|
|
|
|
/// Converts the value of `self` to an `f32`.
|
|
|
|
#[inline]
|
|
|
|
fn to_f32(&self) -> Option<f32> {
|
2013-09-28 00:09:18 +00:00
|
|
|
self.to_f64().and_then(|x| x.to_f32())
|
2013-09-15 16:50:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Converts the value of `self` to an `f64`.
|
|
|
|
#[inline]
|
|
|
|
fn to_f64(&self) -> Option<f64> {
|
2013-09-28 00:09:18 +00:00
|
|
|
self.to_i64().and_then(|x| x.to_f64())
|
2013-09-15 16:50:17 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-09-26 03:22:46 +00:00
|
|
|
macro_rules! impl_to_primitive_int_to_int(
|
|
|
|
($SrcT:ty, $DstT:ty) => (
|
|
|
|
{
|
2014-01-17 21:53:00 +00:00
|
|
|
if size_of::<$SrcT>() <= size_of::<$DstT>() {
|
2013-09-26 03:22:46 +00:00
|
|
|
Some(*self as $DstT)
|
|
|
|
} else {
|
|
|
|
let n = *self as i64;
|
|
|
|
let min_value: $DstT = Bounded::min_value();
|
|
|
|
let max_value: $DstT = Bounded::max_value();
|
|
|
|
if min_value as i64 <= n && n <= max_value as i64 {
|
|
|
|
Some(*self as $DstT)
|
|
|
|
} else {
|
|
|
|
None
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
)
|
|
|
|
)
|
|
|
|
|
|
|
|
macro_rules! impl_to_primitive_int_to_uint(
|
|
|
|
($SrcT:ty, $DstT:ty) => (
|
|
|
|
{
|
|
|
|
let zero: $SrcT = Zero::zero();
|
|
|
|
let max_value: $DstT = Bounded::max_value();
|
|
|
|
if zero <= *self && *self as u64 <= max_value as u64 {
|
|
|
|
Some(*self as $DstT)
|
|
|
|
} else {
|
|
|
|
None
|
|
|
|
}
|
|
|
|
}
|
|
|
|
)
|
|
|
|
)
|
|
|
|
|
|
|
|
macro_rules! impl_to_primitive_int(
|
|
|
|
($T:ty) => (
|
|
|
|
impl ToPrimitive for $T {
|
|
|
|
#[inline]
|
|
|
|
fn to_int(&self) -> Option<int> { impl_to_primitive_int_to_int!($T, int) }
|
|
|
|
#[inline]
|
|
|
|
fn to_i8(&self) -> Option<i8> { impl_to_primitive_int_to_int!($T, i8) }
|
|
|
|
#[inline]
|
|
|
|
fn to_i16(&self) -> Option<i16> { impl_to_primitive_int_to_int!($T, i16) }
|
|
|
|
#[inline]
|
|
|
|
fn to_i32(&self) -> Option<i32> { impl_to_primitive_int_to_int!($T, i32) }
|
|
|
|
#[inline]
|
|
|
|
fn to_i64(&self) -> Option<i64> { impl_to_primitive_int_to_int!($T, i64) }
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
fn to_uint(&self) -> Option<uint> { impl_to_primitive_int_to_uint!($T, uint) }
|
|
|
|
#[inline]
|
|
|
|
fn to_u8(&self) -> Option<u8> { impl_to_primitive_int_to_uint!($T, u8) }
|
|
|
|
#[inline]
|
|
|
|
fn to_u16(&self) -> Option<u16> { impl_to_primitive_int_to_uint!($T, u16) }
|
|
|
|
#[inline]
|
|
|
|
fn to_u32(&self) -> Option<u32> { impl_to_primitive_int_to_uint!($T, u32) }
|
|
|
|
#[inline]
|
|
|
|
fn to_u64(&self) -> Option<u64> { impl_to_primitive_int_to_uint!($T, u64) }
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
fn to_f32(&self) -> Option<f32> { Some(*self as f32) }
|
|
|
|
#[inline]
|
|
|
|
fn to_f64(&self) -> Option<f64> { Some(*self as f64) }
|
|
|
|
}
|
|
|
|
)
|
|
|
|
)
|
|
|
|
|
|
|
|
impl_to_primitive_int!(int)
|
|
|
|
impl_to_primitive_int!(i8)
|
|
|
|
impl_to_primitive_int!(i16)
|
|
|
|
impl_to_primitive_int!(i32)
|
|
|
|
impl_to_primitive_int!(i64)
|
|
|
|
|
|
|
|
macro_rules! impl_to_primitive_uint_to_int(
|
|
|
|
($DstT:ty) => (
|
|
|
|
{
|
|
|
|
let max_value: $DstT = Bounded::max_value();
|
|
|
|
if *self as u64 <= max_value as u64 {
|
|
|
|
Some(*self as $DstT)
|
|
|
|
} else {
|
|
|
|
None
|
|
|
|
}
|
|
|
|
}
|
|
|
|
)
|
|
|
|
)
|
|
|
|
|
|
|
|
macro_rules! impl_to_primitive_uint_to_uint(
|
|
|
|
($SrcT:ty, $DstT:ty) => (
|
|
|
|
{
|
2014-01-17 21:53:00 +00:00
|
|
|
if size_of::<$SrcT>() <= size_of::<$DstT>() {
|
2013-09-26 03:22:46 +00:00
|
|
|
Some(*self as $DstT)
|
|
|
|
} else {
|
|
|
|
let zero: $SrcT = Zero::zero();
|
|
|
|
let max_value: $DstT = Bounded::max_value();
|
|
|
|
if zero <= *self && *self as u64 <= max_value as u64 {
|
|
|
|
Some(*self as $DstT)
|
|
|
|
} else {
|
|
|
|
None
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
)
|
|
|
|
)
|
|
|
|
|
|
|
|
macro_rules! impl_to_primitive_uint(
|
2013-09-15 16:50:17 +00:00
|
|
|
($T:ty) => (
|
|
|
|
impl ToPrimitive for $T {
|
2013-09-26 03:22:46 +00:00
|
|
|
#[inline]
|
|
|
|
fn to_int(&self) -> Option<int> { impl_to_primitive_uint_to_int!(int) }
|
|
|
|
#[inline]
|
|
|
|
fn to_i8(&self) -> Option<i8> { impl_to_primitive_uint_to_int!(i8) }
|
|
|
|
#[inline]
|
|
|
|
fn to_i16(&self) -> Option<i16> { impl_to_primitive_uint_to_int!(i16) }
|
|
|
|
#[inline]
|
|
|
|
fn to_i32(&self) -> Option<i32> { impl_to_primitive_uint_to_int!(i32) }
|
|
|
|
#[inline]
|
|
|
|
fn to_i64(&self) -> Option<i64> { impl_to_primitive_uint_to_int!(i64) }
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
fn to_uint(&self) -> Option<uint> { impl_to_primitive_uint_to_uint!($T, uint) }
|
|
|
|
#[inline]
|
|
|
|
fn to_u8(&self) -> Option<u8> { impl_to_primitive_uint_to_uint!($T, u8) }
|
|
|
|
#[inline]
|
|
|
|
fn to_u16(&self) -> Option<u16> { impl_to_primitive_uint_to_uint!($T, u16) }
|
|
|
|
#[inline]
|
|
|
|
fn to_u32(&self) -> Option<u32> { impl_to_primitive_uint_to_uint!($T, u32) }
|
|
|
|
#[inline]
|
|
|
|
fn to_u64(&self) -> Option<u64> { impl_to_primitive_uint_to_uint!($T, u64) }
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
fn to_f32(&self) -> Option<f32> { Some(*self as f32) }
|
|
|
|
#[inline]
|
|
|
|
fn to_f64(&self) -> Option<f64> { Some(*self as f64) }
|
|
|
|
}
|
|
|
|
)
|
|
|
|
)
|
|
|
|
|
|
|
|
impl_to_primitive_uint!(uint)
|
|
|
|
impl_to_primitive_uint!(u8)
|
|
|
|
impl_to_primitive_uint!(u16)
|
|
|
|
impl_to_primitive_uint!(u32)
|
|
|
|
impl_to_primitive_uint!(u64)
|
|
|
|
|
|
|
|
macro_rules! impl_to_primitive_float_to_float(
|
|
|
|
($SrcT:ty, $DstT:ty) => (
|
2014-01-17 21:53:00 +00:00
|
|
|
if size_of::<$SrcT>() <= size_of::<$DstT>() {
|
2013-09-26 03:22:46 +00:00
|
|
|
Some(*self as $DstT)
|
|
|
|
} else {
|
|
|
|
let n = *self as f64;
|
|
|
|
let max_value: $SrcT = Bounded::max_value();
|
2013-10-08 18:57:17 +00:00
|
|
|
if -max_value as f64 <= n && n <= max_value as f64 {
|
2013-09-26 03:22:46 +00:00
|
|
|
Some(*self as $DstT)
|
|
|
|
} else {
|
|
|
|
None
|
|
|
|
}
|
|
|
|
}
|
|
|
|
)
|
|
|
|
)
|
|
|
|
|
|
|
|
macro_rules! impl_to_primitive_float(
|
|
|
|
($T:ty) => (
|
|
|
|
impl ToPrimitive for $T {
|
|
|
|
#[inline]
|
|
|
|
fn to_int(&self) -> Option<int> { Some(*self as int) }
|
|
|
|
#[inline]
|
|
|
|
fn to_i8(&self) -> Option<i8> { Some(*self as i8) }
|
|
|
|
#[inline]
|
|
|
|
fn to_i16(&self) -> Option<i16> { Some(*self as i16) }
|
|
|
|
#[inline]
|
|
|
|
fn to_i32(&self) -> Option<i32> { Some(*self as i32) }
|
|
|
|
#[inline]
|
|
|
|
fn to_i64(&self) -> Option<i64> { Some(*self as i64) }
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
fn to_uint(&self) -> Option<uint> { Some(*self as uint) }
|
|
|
|
#[inline]
|
|
|
|
fn to_u8(&self) -> Option<u8> { Some(*self as u8) }
|
|
|
|
#[inline]
|
|
|
|
fn to_u16(&self) -> Option<u16> { Some(*self as u16) }
|
|
|
|
#[inline]
|
|
|
|
fn to_u32(&self) -> Option<u32> { Some(*self as u32) }
|
|
|
|
#[inline]
|
|
|
|
fn to_u64(&self) -> Option<u64> { Some(*self as u64) }
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
fn to_f32(&self) -> Option<f32> { impl_to_primitive_float_to_float!($T, f32) }
|
|
|
|
#[inline]
|
|
|
|
fn to_f64(&self) -> Option<f64> { impl_to_primitive_float_to_float!($T, f64) }
|
2013-09-15 16:50:17 +00:00
|
|
|
}
|
|
|
|
)
|
|
|
|
)
|
|
|
|
|
2013-09-26 03:22:46 +00:00
|
|
|
impl_to_primitive_float!(f32)
|
|
|
|
impl_to_primitive_float!(f64)
|
2013-09-15 16:50:17 +00:00
|
|
|
|
|
|
|
/// A generic trait for converting a number to a value.
|
|
|
|
pub trait FromPrimitive {
|
|
|
|
/// Convert an `int` to return an optional value of this type. If the
|
|
|
|
/// value cannot be represented by this value, the `None` is returned.
|
2013-09-18 02:28:35 +00:00
|
|
|
#[inline]
|
|
|
|
fn from_int(n: int) -> Option<Self> {
|
|
|
|
FromPrimitive::from_i64(n as i64)
|
|
|
|
}
|
2013-09-15 16:50:17 +00:00
|
|
|
|
|
|
|
/// Convert an `i8` to return an optional value of this type. If the
|
|
|
|
/// type cannot be represented by this value, the `None` is returned.
|
|
|
|
#[inline]
|
|
|
|
fn from_i8(n: i8) -> Option<Self> {
|
2013-09-18 02:28:35 +00:00
|
|
|
FromPrimitive::from_i64(n as i64)
|
2013-09-15 16:50:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Convert an `i16` to return an optional value of this type. If the
|
|
|
|
/// type cannot be represented by this value, the `None` is returned.
|
|
|
|
#[inline]
|
|
|
|
fn from_i16(n: i16) -> Option<Self> {
|
2013-09-18 02:28:35 +00:00
|
|
|
FromPrimitive::from_i64(n as i64)
|
2013-09-15 16:50:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Convert an `i32` to return an optional value of this type. If the
|
|
|
|
/// type cannot be represented by this value, the `None` is returned.
|
|
|
|
#[inline]
|
|
|
|
fn from_i32(n: i32) -> Option<Self> {
|
2013-09-18 02:28:35 +00:00
|
|
|
FromPrimitive::from_i64(n as i64)
|
2013-09-15 16:50:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Convert an `i64` to return an optional value of this type. If the
|
|
|
|
/// type cannot be represented by this value, the `None` is returned.
|
2013-09-18 02:28:35 +00:00
|
|
|
fn from_i64(n: i64) -> Option<Self>;
|
2013-09-15 16:50:17 +00:00
|
|
|
|
|
|
|
/// Convert an `uint` to return an optional value of this type. If the
|
|
|
|
/// type cannot be represented by this value, the `None` is returned.
|
2013-09-18 02:28:35 +00:00
|
|
|
#[inline]
|
|
|
|
fn from_uint(n: uint) -> Option<Self> {
|
|
|
|
FromPrimitive::from_u64(n as u64)
|
|
|
|
}
|
2013-09-15 16:50:17 +00:00
|
|
|
|
|
|
|
/// Convert an `u8` to return an optional value of this type. If the
|
|
|
|
/// type cannot be represented by this value, the `None` is returned.
|
|
|
|
#[inline]
|
|
|
|
fn from_u8(n: u8) -> Option<Self> {
|
2013-09-18 02:28:35 +00:00
|
|
|
FromPrimitive::from_u64(n as u64)
|
2013-09-15 16:50:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Convert an `u16` to return an optional value of this type. If the
|
|
|
|
/// type cannot be represented by this value, the `None` is returned.
|
|
|
|
#[inline]
|
|
|
|
fn from_u16(n: u16) -> Option<Self> {
|
2013-09-18 02:28:35 +00:00
|
|
|
FromPrimitive::from_u64(n as u64)
|
2013-09-15 16:50:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Convert an `u32` to return an optional value of this type. If the
|
|
|
|
/// type cannot be represented by this value, the `None` is returned.
|
|
|
|
#[inline]
|
|
|
|
fn from_u32(n: u32) -> Option<Self> {
|
2013-09-18 02:28:35 +00:00
|
|
|
FromPrimitive::from_u64(n as u64)
|
2013-09-15 16:50:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Convert an `u64` to return an optional value of this type. If the
|
|
|
|
/// type cannot be represented by this value, the `None` is returned.
|
2013-09-18 02:28:35 +00:00
|
|
|
fn from_u64(n: u64) -> Option<Self>;
|
2013-09-15 16:50:17 +00:00
|
|
|
|
|
|
|
/// Convert a `f32` to return an optional value of this type. If the
|
|
|
|
/// type cannot be represented by this value, the `None` is returned.
|
|
|
|
#[inline]
|
|
|
|
fn from_f32(n: f32) -> Option<Self> {
|
2013-09-18 02:28:35 +00:00
|
|
|
FromPrimitive::from_f64(n as f64)
|
2013-09-15 16:50:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Convert a `f64` to return an optional value of this type. If the
|
|
|
|
/// type cannot be represented by this value, the `None` is returned.
|
|
|
|
#[inline]
|
|
|
|
fn from_f64(n: f64) -> Option<Self> {
|
2013-09-18 02:28:35 +00:00
|
|
|
FromPrimitive::from_i64(n as i64)
|
2013-09-15 16:50:17 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// A utility function that just calls `FromPrimitive::from_int`.
|
|
|
|
pub fn from_int<A: FromPrimitive>(n: int) -> Option<A> {
|
|
|
|
FromPrimitive::from_int(n)
|
|
|
|
}
|
|
|
|
|
|
|
|
/// A utility function that just calls `FromPrimitive::from_i8`.
|
|
|
|
pub fn from_i8<A: FromPrimitive>(n: i8) -> Option<A> {
|
|
|
|
FromPrimitive::from_i8(n)
|
|
|
|
}
|
|
|
|
|
|
|
|
/// A utility function that just calls `FromPrimitive::from_i16`.
|
|
|
|
pub fn from_i16<A: FromPrimitive>(n: i16) -> Option<A> {
|
|
|
|
FromPrimitive::from_i16(n)
|
|
|
|
}
|
|
|
|
|
|
|
|
/// A utility function that just calls `FromPrimitive::from_i32`.
|
|
|
|
pub fn from_i32<A: FromPrimitive>(n: i32) -> Option<A> {
|
|
|
|
FromPrimitive::from_i32(n)
|
|
|
|
}
|
|
|
|
|
|
|
|
/// A utility function that just calls `FromPrimitive::from_i64`.
|
|
|
|
pub fn from_i64<A: FromPrimitive>(n: i64) -> Option<A> {
|
|
|
|
FromPrimitive::from_i64(n)
|
|
|
|
}
|
|
|
|
|
|
|
|
/// A utility function that just calls `FromPrimitive::from_uint`.
|
|
|
|
pub fn from_uint<A: FromPrimitive>(n: uint) -> Option<A> {
|
|
|
|
FromPrimitive::from_uint(n)
|
|
|
|
}
|
|
|
|
|
|
|
|
/// A utility function that just calls `FromPrimitive::from_u8`.
|
|
|
|
pub fn from_u8<A: FromPrimitive>(n: u8) -> Option<A> {
|
|
|
|
FromPrimitive::from_u8(n)
|
|
|
|
}
|
|
|
|
|
|
|
|
/// A utility function that just calls `FromPrimitive::from_u16`.
|
|
|
|
pub fn from_u16<A: FromPrimitive>(n: u16) -> Option<A> {
|
|
|
|
FromPrimitive::from_u16(n)
|
|
|
|
}
|
|
|
|
|
|
|
|
/// A utility function that just calls `FromPrimitive::from_u32`.
|
|
|
|
pub fn from_u32<A: FromPrimitive>(n: u32) -> Option<A> {
|
|
|
|
FromPrimitive::from_u32(n)
|
|
|
|
}
|
|
|
|
|
|
|
|
/// A utility function that just calls `FromPrimitive::from_u64`.
|
|
|
|
pub fn from_u64<A: FromPrimitive>(n: u64) -> Option<A> {
|
|
|
|
FromPrimitive::from_u64(n)
|
|
|
|
}
|
|
|
|
|
|
|
|
/// A utility function that just calls `FromPrimitive::from_f32`.
|
|
|
|
pub fn from_f32<A: FromPrimitive>(n: f32) -> Option<A> {
|
|
|
|
FromPrimitive::from_f32(n)
|
|
|
|
}
|
|
|
|
|
|
|
|
/// A utility function that just calls `FromPrimitive::from_f64`.
|
|
|
|
pub fn from_f64<A: FromPrimitive>(n: f64) -> Option<A> {
|
|
|
|
FromPrimitive::from_f64(n)
|
|
|
|
}
|
|
|
|
|
|
|
|
macro_rules! impl_from_primitive(
|
2013-09-26 03:22:46 +00:00
|
|
|
($T:ty, $to_ty:expr) => (
|
2013-09-15 16:50:17 +00:00
|
|
|
impl FromPrimitive for $T {
|
2013-09-26 03:22:46 +00:00
|
|
|
#[inline] fn from_int(n: int) -> Option<$T> { $to_ty }
|
|
|
|
#[inline] fn from_i8(n: i8) -> Option<$T> { $to_ty }
|
|
|
|
#[inline] fn from_i16(n: i16) -> Option<$T> { $to_ty }
|
|
|
|
#[inline] fn from_i32(n: i32) -> Option<$T> { $to_ty }
|
|
|
|
#[inline] fn from_i64(n: i64) -> Option<$T> { $to_ty }
|
|
|
|
|
|
|
|
#[inline] fn from_uint(n: uint) -> Option<$T> { $to_ty }
|
|
|
|
#[inline] fn from_u8(n: u8) -> Option<$T> { $to_ty }
|
|
|
|
#[inline] fn from_u16(n: u16) -> Option<$T> { $to_ty }
|
|
|
|
#[inline] fn from_u32(n: u32) -> Option<$T> { $to_ty }
|
|
|
|
#[inline] fn from_u64(n: u64) -> Option<$T> { $to_ty }
|
|
|
|
|
|
|
|
#[inline] fn from_f32(n: f32) -> Option<$T> { $to_ty }
|
|
|
|
#[inline] fn from_f64(n: f64) -> Option<$T> { $to_ty }
|
2013-09-15 16:50:17 +00:00
|
|
|
}
|
|
|
|
)
|
|
|
|
)
|
|
|
|
|
2013-09-26 03:22:46 +00:00
|
|
|
impl_from_primitive!(int, n.to_int())
|
|
|
|
impl_from_primitive!(i8, n.to_i8())
|
|
|
|
impl_from_primitive!(i16, n.to_i16())
|
|
|
|
impl_from_primitive!(i32, n.to_i32())
|
|
|
|
impl_from_primitive!(i64, n.to_i64())
|
|
|
|
impl_from_primitive!(uint, n.to_uint())
|
|
|
|
impl_from_primitive!(u8, n.to_u8())
|
|
|
|
impl_from_primitive!(u16, n.to_u16())
|
|
|
|
impl_from_primitive!(u32, n.to_u32())
|
|
|
|
impl_from_primitive!(u64, n.to_u64())
|
|
|
|
impl_from_primitive!(f32, n.to_f32())
|
|
|
|
impl_from_primitive!(f64, n.to_f64())
|
2013-09-15 16:50:17 +00:00
|
|
|
|
2013-09-24 17:25:45 +00:00
|
|
|
/// Cast from one machine scalar to another.
|
2013-04-25 23:55:49 +00:00
|
|
|
///
|
|
|
|
/// # Example
|
|
|
|
///
|
2013-09-24 00:20:36 +00:00
|
|
|
/// ```
|
2014-02-15 07:44:22 +00:00
|
|
|
/// use std::num;
|
|
|
|
///
|
2013-10-17 05:33:31 +00:00
|
|
|
/// let twenty: f32 = num::cast(0x14).unwrap();
|
2013-04-25 23:55:49 +00:00
|
|
|
/// assert_eq!(twenty, 20f32);
|
2013-09-24 00:20:36 +00:00
|
|
|
/// ```
|
2013-04-25 23:55:49 +00:00
|
|
|
///
|
2013-06-18 21:45:18 +00:00
|
|
|
#[inline]
|
2013-09-15 16:50:17 +00:00
|
|
|
pub fn cast<T: NumCast,U: NumCast>(n: T) -> Option<U> {
|
2013-02-11 01:33:05 +00:00
|
|
|
NumCast::from(n)
|
|
|
|
}
|
|
|
|
|
2014-03-16 22:59:04 +00:00
|
|
|
/// An interface for casting between machine scalars.
|
2013-09-15 16:50:17 +00:00
|
|
|
pub trait NumCast: ToPrimitive {
|
2014-03-16 22:59:04 +00:00
|
|
|
/// Creates a number from another value that can be converted into a primitive via the
|
|
|
|
/// `ToPrimitive` trait.
|
2013-09-15 16:50:17 +00:00
|
|
|
fn from<T: ToPrimitive>(n: T) -> Option<Self>;
|
2013-02-11 01:33:05 +00:00
|
|
|
}
|
|
|
|
|
2013-04-13 13:44:35 +00:00
|
|
|
macro_rules! impl_num_cast(
|
|
|
|
($T:ty, $conv:ident) => (
|
2013-04-13 19:27:32 +00:00
|
|
|
impl NumCast for $T {
|
2013-06-18 21:45:18 +00:00
|
|
|
#[inline]
|
2013-09-15 16:50:17 +00:00
|
|
|
fn from<N: ToPrimitive>(n: N) -> Option<$T> {
|
2013-04-13 19:27:32 +00:00
|
|
|
// `$conv` could be generated using `concat_idents!`, but that
|
|
|
|
// macro seems to be broken at the moment
|
|
|
|
n.$conv()
|
2013-04-13 13:44:35 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
)
|
|
|
|
)
|
|
|
|
|
|
|
|
impl_num_cast!(u8, to_u8)
|
|
|
|
impl_num_cast!(u16, to_u16)
|
|
|
|
impl_num_cast!(u32, to_u32)
|
|
|
|
impl_num_cast!(u64, to_u64)
|
|
|
|
impl_num_cast!(uint, to_uint)
|
|
|
|
impl_num_cast!(i8, to_i8)
|
|
|
|
impl_num_cast!(i16, to_i16)
|
|
|
|
impl_num_cast!(i32, to_i32)
|
|
|
|
impl_num_cast!(i64, to_i64)
|
|
|
|
impl_num_cast!(int, to_int)
|
|
|
|
impl_num_cast!(f32, to_f32)
|
|
|
|
impl_num_cast!(f64, to_f64)
|
|
|
|
|
2014-04-11 23:07:45 +00:00
|
|
|
/// A generic trait for converting a value to a string with a radix (base)
|
2013-01-24 20:09:58 +00:00
|
|
|
pub trait ToStrRadix {
|
2013-08-09 08:25:24 +00:00
|
|
|
fn to_str_radix(&self, radix: uint) -> ~str;
|
2013-01-24 20:09:58 +00:00
|
|
|
}
|
|
|
|
|
2014-04-11 23:07:45 +00:00
|
|
|
/// A generic trait for converting a string with a radix (base) to a value
|
2013-01-24 20:09:58 +00:00
|
|
|
pub trait FromStrRadix {
|
2013-08-09 08:25:24 +00:00
|
|
|
fn from_str_radix(str: &str, radix: uint) -> Option<Self>;
|
2013-01-20 23:40:02 +00:00
|
|
|
}
|
|
|
|
|
2013-09-24 17:25:45 +00:00
|
|
|
/// A utility function that just calls FromStrRadix::from_str_radix.
|
2013-09-15 05:27:32 +00:00
|
|
|
pub fn from_str_radix<T: FromStrRadix>(str: &str, radix: uint) -> Option<T> {
|
|
|
|
FromStrRadix::from_str_radix(str, radix)
|
|
|
|
}
|
|
|
|
|
2013-08-06 02:28:20 +00:00
|
|
|
/// Saturating math operations
|
2013-08-14 20:02:20 +00:00
|
|
|
pub trait Saturating {
|
2013-08-06 02:28:20 +00:00
|
|
|
/// Saturating addition operator.
|
|
|
|
/// Returns a+b, saturating at the numeric bounds instead of overflowing.
|
2013-08-14 20:02:20 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2013-09-07 07:15:35 +00:00
|
|
|
impl<T: CheckedAdd + CheckedSub + Zero + Ord + Bounded> Saturating for T {
|
2013-08-06 02:28:20 +00:00
|
|
|
#[inline]
|
2013-08-14 20:02:20 +00:00
|
|
|
fn saturating_add(self, v: T) -> T {
|
|
|
|
match self.checked_add(&v) {
|
|
|
|
Some(x) => x,
|
|
|
|
None => if v >= Zero::zero() {
|
2013-08-08 18:38:10 +00:00
|
|
|
Bounded::max_value()
|
2013-08-14 20:02:20 +00:00
|
|
|
} else {
|
2013-08-08 18:38:10 +00:00
|
|
|
Bounded::min_value()
|
2013-08-14 20:02:20 +00:00
|
|
|
}
|
2013-08-06 02:28:20 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
2013-08-14 20:02:20 +00:00
|
|
|
fn saturating_sub(self, v: T) -> T {
|
|
|
|
match self.checked_sub(&v) {
|
|
|
|
Some(x) => x,
|
|
|
|
None => if v >= Zero::zero() {
|
2013-08-08 18:38:10 +00:00
|
|
|
Bounded::min_value()
|
2013-08-14 20:02:20 +00:00
|
|
|
} else {
|
2013-08-08 18:38:10 +00:00
|
|
|
Bounded::max_value()
|
2013-08-14 20:02:20 +00:00
|
|
|
}
|
2013-08-06 02:28:20 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-03-16 22:59:04 +00:00
|
|
|
/// Performs addition that returns `None` instead of wrapping around on overflow.
|
2013-08-07 19:40:09 +00:00
|
|
|
pub trait CheckedAdd: Add<Self, Self> {
|
2014-03-16 22:59:04 +00:00
|
|
|
/// Adds two numbers, checking for overflow. If overflow happens, `None` is returned.
|
2013-08-07 19:40:09 +00:00
|
|
|
fn checked_add(&self, v: &Self) -> Option<Self>;
|
|
|
|
}
|
|
|
|
|
2014-03-16 22:59:04 +00:00
|
|
|
/// Performs subtraction that returns `None` instead of wrapping around on underflow.
|
2013-08-07 19:40:09 +00:00
|
|
|
pub trait CheckedSub: Sub<Self, Self> {
|
2014-03-16 22:59:04 +00:00
|
|
|
/// Subtracts two numbers, checking for underflow. If underflow happens, `None` is returned.
|
2013-08-07 19:40:09 +00:00
|
|
|
fn checked_sub(&self, v: &Self) -> Option<Self>;
|
|
|
|
}
|
|
|
|
|
2014-03-16 22:59:04 +00:00
|
|
|
/// Performs multiplication that returns `None` instead of wrapping around on underflow or
|
|
|
|
/// overflow.
|
2013-08-07 19:40:09 +00:00
|
|
|
pub trait CheckedMul: Mul<Self, Self> {
|
2014-03-16 22:59:04 +00:00
|
|
|
/// Multiplies two numbers, checking for underflow or overflow. If underflow or overflow
|
|
|
|
/// happens, `None` is returned.
|
2013-08-07 19:40:09 +00:00
|
|
|
fn checked_mul(&self, v: &Self) -> Option<Self>;
|
|
|
|
}
|
|
|
|
|
2014-03-16 22:59:04 +00:00
|
|
|
/// Performs division that returns `None` instead of wrapping around on underflow or overflow.
|
2013-08-11 22:32:07 +00:00
|
|
|
pub trait CheckedDiv: Div<Self, Self> {
|
2014-03-16 22:59:04 +00:00
|
|
|
/// Divides two numbers, checking for underflow or overflow. If underflow or overflow happens,
|
|
|
|
/// `None` is returned.
|
2013-08-11 22:32:07 +00:00
|
|
|
fn checked_div(&self, v: &Self) -> Option<Self>;
|
|
|
|
}
|
|
|
|
|
2013-04-24 10:08:08 +00:00
|
|
|
/// Helper function for testing numeric operations
|
2013-05-04 21:25:41 +00:00
|
|
|
#[cfg(test)]
|
2014-02-28 09:23:06 +00:00
|
|
|
pub fn test_num<T:Num + NumCast + Show>(ten: T, two: T) {
|
2013-09-15 16:50:17 +00:00
|
|
|
assert_eq!(ten.add(&two), cast(12).unwrap());
|
|
|
|
assert_eq!(ten.sub(&two), cast(8).unwrap());
|
|
|
|
assert_eq!(ten.mul(&two), cast(20).unwrap());
|
|
|
|
assert_eq!(ten.div(&two), cast(5).unwrap());
|
|
|
|
assert_eq!(ten.rem(&two), cast(0).unwrap());
|
2013-04-21 15:58:53 +00:00
|
|
|
|
|
|
|
assert_eq!(ten.add(&two), ten + two);
|
|
|
|
assert_eq!(ten.sub(&two), ten - two);
|
|
|
|
assert_eq!(ten.mul(&two), ten * two);
|
2013-05-17 16:07:16 +00:00
|
|
|
assert_eq!(ten.div(&two), ten / two);
|
2013-04-21 15:58:53 +00:00
|
|
|
assert_eq!(ten.rem(&two), ten % two);
|
|
|
|
}
|
2013-04-13 16:53:00 +00:00
|
|
|
|
2013-08-06 02:28:20 +00:00
|
|
|
#[cfg(test)]
|
|
|
|
mod tests {
|
2013-08-07 19:40:09 +00:00
|
|
|
use prelude::*;
|
2013-08-06 02:28:20 +00:00
|
|
|
use super::*;
|
2013-09-26 03:22:46 +00:00
|
|
|
use i8;
|
|
|
|
use i16;
|
|
|
|
use i32;
|
|
|
|
use i64;
|
|
|
|
use int;
|
|
|
|
use u8;
|
|
|
|
use u16;
|
|
|
|
use u32;
|
|
|
|
use u64;
|
|
|
|
use uint;
|
2013-08-06 02:28:20 +00:00
|
|
|
|
|
|
|
macro_rules! test_cast_20(
|
|
|
|
($_20:expr) => ({
|
|
|
|
let _20 = $_20;
|
|
|
|
|
2013-09-15 16:50:17 +00:00
|
|
|
assert_eq!(20u, _20.to_uint().unwrap());
|
|
|
|
assert_eq!(20u8, _20.to_u8().unwrap());
|
|
|
|
assert_eq!(20u16, _20.to_u16().unwrap());
|
|
|
|
assert_eq!(20u32, _20.to_u32().unwrap());
|
|
|
|
assert_eq!(20u64, _20.to_u64().unwrap());
|
|
|
|
assert_eq!(20i, _20.to_int().unwrap());
|
|
|
|
assert_eq!(20i8, _20.to_i8().unwrap());
|
|
|
|
assert_eq!(20i16, _20.to_i16().unwrap());
|
|
|
|
assert_eq!(20i32, _20.to_i32().unwrap());
|
|
|
|
assert_eq!(20i64, _20.to_i64().unwrap());
|
|
|
|
assert_eq!(20f32, _20.to_f32().unwrap());
|
|
|
|
assert_eq!(20f64, _20.to_f64().unwrap());
|
|
|
|
|
|
|
|
assert_eq!(_20, NumCast::from(20u).unwrap());
|
|
|
|
assert_eq!(_20, NumCast::from(20u8).unwrap());
|
|
|
|
assert_eq!(_20, NumCast::from(20u16).unwrap());
|
|
|
|
assert_eq!(_20, NumCast::from(20u32).unwrap());
|
|
|
|
assert_eq!(_20, NumCast::from(20u64).unwrap());
|
|
|
|
assert_eq!(_20, NumCast::from(20i).unwrap());
|
|
|
|
assert_eq!(_20, NumCast::from(20i8).unwrap());
|
|
|
|
assert_eq!(_20, NumCast::from(20i16).unwrap());
|
|
|
|
assert_eq!(_20, NumCast::from(20i32).unwrap());
|
|
|
|
assert_eq!(_20, NumCast::from(20i64).unwrap());
|
|
|
|
assert_eq!(_20, NumCast::from(20f32).unwrap());
|
|
|
|
assert_eq!(_20, NumCast::from(20f64).unwrap());
|
|
|
|
|
|
|
|
assert_eq!(_20, cast(20u).unwrap());
|
|
|
|
assert_eq!(_20, cast(20u8).unwrap());
|
|
|
|
assert_eq!(_20, cast(20u16).unwrap());
|
|
|
|
assert_eq!(_20, cast(20u32).unwrap());
|
|
|
|
assert_eq!(_20, cast(20u64).unwrap());
|
|
|
|
assert_eq!(_20, cast(20i).unwrap());
|
|
|
|
assert_eq!(_20, cast(20i8).unwrap());
|
|
|
|
assert_eq!(_20, cast(20i16).unwrap());
|
|
|
|
assert_eq!(_20, cast(20i32).unwrap());
|
|
|
|
assert_eq!(_20, cast(20i64).unwrap());
|
|
|
|
assert_eq!(_20, cast(20f32).unwrap());
|
|
|
|
assert_eq!(_20, cast(20f64).unwrap());
|
2013-08-06 02:28:20 +00:00
|
|
|
})
|
|
|
|
)
|
|
|
|
|
|
|
|
#[test] fn test_u8_cast() { test_cast_20!(20u8) }
|
|
|
|
#[test] fn test_u16_cast() { test_cast_20!(20u16) }
|
|
|
|
#[test] fn test_u32_cast() { test_cast_20!(20u32) }
|
|
|
|
#[test] fn test_u64_cast() { test_cast_20!(20u64) }
|
|
|
|
#[test] fn test_uint_cast() { test_cast_20!(20u) }
|
|
|
|
#[test] fn test_i8_cast() { test_cast_20!(20i8) }
|
|
|
|
#[test] fn test_i16_cast() { test_cast_20!(20i16) }
|
|
|
|
#[test] fn test_i32_cast() { test_cast_20!(20i32) }
|
|
|
|
#[test] fn test_i64_cast() { test_cast_20!(20i64) }
|
|
|
|
#[test] fn test_int_cast() { test_cast_20!(20i) }
|
|
|
|
#[test] fn test_f32_cast() { test_cast_20!(20f32) }
|
|
|
|
#[test] fn test_f64_cast() { test_cast_20!(20f64) }
|
|
|
|
|
2013-09-26 03:22:46 +00:00
|
|
|
#[test]
|
|
|
|
fn test_cast_range_int_min() {
|
2014-01-25 07:37:51 +00:00
|
|
|
assert_eq!(int::MIN.to_int(), Some(int::MIN as int));
|
|
|
|
assert_eq!(int::MIN.to_i8(), None);
|
|
|
|
assert_eq!(int::MIN.to_i16(), None);
|
|
|
|
// int::MIN.to_i32() is word-size specific
|
|
|
|
assert_eq!(int::MIN.to_i64(), Some(int::MIN as i64));
|
|
|
|
assert_eq!(int::MIN.to_uint(), None);
|
|
|
|
assert_eq!(int::MIN.to_u8(), None);
|
|
|
|
assert_eq!(int::MIN.to_u16(), None);
|
|
|
|
assert_eq!(int::MIN.to_u32(), None);
|
|
|
|
assert_eq!(int::MIN.to_u64(), None);
|
2013-09-26 03:22:46 +00:00
|
|
|
|
|
|
|
#[cfg(target_word_size = "32")]
|
|
|
|
fn check_word_size() {
|
2014-01-25 07:37:51 +00:00
|
|
|
assert_eq!(int::MIN.to_i32(), Some(int::MIN as i32));
|
2013-09-26 03:22:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(target_word_size = "64")]
|
|
|
|
fn check_word_size() {
|
2014-01-25 07:37:51 +00:00
|
|
|
assert_eq!(int::MIN.to_i32(), None);
|
2013-09-26 03:22:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
check_word_size();
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_cast_range_i8_min() {
|
2014-01-25 07:37:51 +00:00
|
|
|
assert_eq!(i8::MIN.to_int(), Some(i8::MIN as int));
|
|
|
|
assert_eq!(i8::MIN.to_i8(), Some(i8::MIN as i8));
|
|
|
|
assert_eq!(i8::MIN.to_i16(), Some(i8::MIN as i16));
|
|
|
|
assert_eq!(i8::MIN.to_i32(), Some(i8::MIN as i32));
|
|
|
|
assert_eq!(i8::MIN.to_i64(), Some(i8::MIN as i64));
|
|
|
|
assert_eq!(i8::MIN.to_uint(), None);
|
|
|
|
assert_eq!(i8::MIN.to_u8(), None);
|
|
|
|
assert_eq!(i8::MIN.to_u16(), None);
|
|
|
|
assert_eq!(i8::MIN.to_u32(), None);
|
|
|
|
assert_eq!(i8::MIN.to_u64(), None);
|
2013-09-26 03:22:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_cast_range_i16_min() {
|
2014-01-25 07:37:51 +00:00
|
|
|
assert_eq!(i16::MIN.to_int(), Some(i16::MIN as int));
|
|
|
|
assert_eq!(i16::MIN.to_i8(), None);
|
|
|
|
assert_eq!(i16::MIN.to_i16(), Some(i16::MIN as i16));
|
|
|
|
assert_eq!(i16::MIN.to_i32(), Some(i16::MIN as i32));
|
|
|
|
assert_eq!(i16::MIN.to_i64(), Some(i16::MIN as i64));
|
|
|
|
assert_eq!(i16::MIN.to_uint(), None);
|
|
|
|
assert_eq!(i16::MIN.to_u8(), None);
|
|
|
|
assert_eq!(i16::MIN.to_u16(), None);
|
|
|
|
assert_eq!(i16::MIN.to_u32(), None);
|
|
|
|
assert_eq!(i16::MIN.to_u64(), None);
|
2013-09-26 03:22:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_cast_range_i32_min() {
|
2014-01-25 07:37:51 +00:00
|
|
|
assert_eq!(i32::MIN.to_int(), Some(i32::MIN as int));
|
|
|
|
assert_eq!(i32::MIN.to_i8(), None);
|
|
|
|
assert_eq!(i32::MIN.to_i16(), None);
|
|
|
|
assert_eq!(i32::MIN.to_i32(), Some(i32::MIN as i32));
|
|
|
|
assert_eq!(i32::MIN.to_i64(), Some(i32::MIN as i64));
|
|
|
|
assert_eq!(i32::MIN.to_uint(), None);
|
|
|
|
assert_eq!(i32::MIN.to_u8(), None);
|
|
|
|
assert_eq!(i32::MIN.to_u16(), None);
|
|
|
|
assert_eq!(i32::MIN.to_u32(), None);
|
|
|
|
assert_eq!(i32::MIN.to_u64(), None);
|
2013-09-26 03:22:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_cast_range_i64_min() {
|
2014-01-25 07:37:51 +00:00
|
|
|
// i64::MIN.to_int() is word-size specific
|
|
|
|
assert_eq!(i64::MIN.to_i8(), None);
|
|
|
|
assert_eq!(i64::MIN.to_i16(), None);
|
|
|
|
assert_eq!(i64::MIN.to_i32(), None);
|
|
|
|
assert_eq!(i64::MIN.to_i64(), Some(i64::MIN as i64));
|
|
|
|
assert_eq!(i64::MIN.to_uint(), None);
|
|
|
|
assert_eq!(i64::MIN.to_u8(), None);
|
|
|
|
assert_eq!(i64::MIN.to_u16(), None);
|
|
|
|
assert_eq!(i64::MIN.to_u32(), None);
|
|
|
|
assert_eq!(i64::MIN.to_u64(), None);
|
2013-09-26 03:22:46 +00:00
|
|
|
|
|
|
|
#[cfg(target_word_size = "32")]
|
|
|
|
fn check_word_size() {
|
2014-01-25 07:37:51 +00:00
|
|
|
assert_eq!(i64::MIN.to_int(), None);
|
2013-09-26 03:22:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(target_word_size = "64")]
|
|
|
|
fn check_word_size() {
|
2014-01-25 07:37:51 +00:00
|
|
|
assert_eq!(i64::MIN.to_int(), Some(i64::MIN as int));
|
2013-09-26 03:22:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
check_word_size();
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_cast_range_int_max() {
|
2014-01-25 07:37:51 +00:00
|
|
|
assert_eq!(int::MAX.to_int(), Some(int::MAX as int));
|
|
|
|
assert_eq!(int::MAX.to_i8(), None);
|
|
|
|
assert_eq!(int::MAX.to_i16(), None);
|
|
|
|
// int::MAX.to_i32() is word-size specific
|
|
|
|
assert_eq!(int::MAX.to_i64(), Some(int::MAX as i64));
|
|
|
|
assert_eq!(int::MAX.to_u8(), None);
|
|
|
|
assert_eq!(int::MAX.to_u16(), None);
|
|
|
|
// int::MAX.to_u32() is word-size specific
|
|
|
|
assert_eq!(int::MAX.to_u64(), Some(int::MAX as u64));
|
2013-09-26 03:22:46 +00:00
|
|
|
|
|
|
|
#[cfg(target_word_size = "32")]
|
|
|
|
fn check_word_size() {
|
2014-01-25 07:37:51 +00:00
|
|
|
assert_eq!(int::MAX.to_i32(), Some(int::MAX as i32));
|
|
|
|
assert_eq!(int::MAX.to_u32(), Some(int::MAX as u32));
|
2013-09-26 03:22:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(target_word_size = "64")]
|
|
|
|
fn check_word_size() {
|
2014-01-25 07:37:51 +00:00
|
|
|
assert_eq!(int::MAX.to_i32(), None);
|
|
|
|
assert_eq!(int::MAX.to_u32(), None);
|
2013-09-26 03:22:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
check_word_size();
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_cast_range_i8_max() {
|
2014-01-25 07:37:51 +00:00
|
|
|
assert_eq!(i8::MAX.to_int(), Some(i8::MAX as int));
|
|
|
|
assert_eq!(i8::MAX.to_i8(), Some(i8::MAX as i8));
|
|
|
|
assert_eq!(i8::MAX.to_i16(), Some(i8::MAX as i16));
|
|
|
|
assert_eq!(i8::MAX.to_i32(), Some(i8::MAX as i32));
|
|
|
|
assert_eq!(i8::MAX.to_i64(), Some(i8::MAX as i64));
|
|
|
|
assert_eq!(i8::MAX.to_uint(), Some(i8::MAX as uint));
|
|
|
|
assert_eq!(i8::MAX.to_u8(), Some(i8::MAX as u8));
|
|
|
|
assert_eq!(i8::MAX.to_u16(), Some(i8::MAX as u16));
|
|
|
|
assert_eq!(i8::MAX.to_u32(), Some(i8::MAX as u32));
|
|
|
|
assert_eq!(i8::MAX.to_u64(), Some(i8::MAX as u64));
|
2013-09-26 03:22:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_cast_range_i16_max() {
|
2014-01-25 07:37:51 +00:00
|
|
|
assert_eq!(i16::MAX.to_int(), Some(i16::MAX as int));
|
|
|
|
assert_eq!(i16::MAX.to_i8(), None);
|
|
|
|
assert_eq!(i16::MAX.to_i16(), Some(i16::MAX as i16));
|
|
|
|
assert_eq!(i16::MAX.to_i32(), Some(i16::MAX as i32));
|
|
|
|
assert_eq!(i16::MAX.to_i64(), Some(i16::MAX as i64));
|
|
|
|
assert_eq!(i16::MAX.to_uint(), Some(i16::MAX as uint));
|
|
|
|
assert_eq!(i16::MAX.to_u8(), None);
|
|
|
|
assert_eq!(i16::MAX.to_u16(), Some(i16::MAX as u16));
|
|
|
|
assert_eq!(i16::MAX.to_u32(), Some(i16::MAX as u32));
|
|
|
|
assert_eq!(i16::MAX.to_u64(), Some(i16::MAX as u64));
|
2013-09-26 03:22:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_cast_range_i32_max() {
|
2014-01-25 07:37:51 +00:00
|
|
|
assert_eq!(i32::MAX.to_int(), Some(i32::MAX as int));
|
|
|
|
assert_eq!(i32::MAX.to_i8(), None);
|
|
|
|
assert_eq!(i32::MAX.to_i16(), None);
|
|
|
|
assert_eq!(i32::MAX.to_i32(), Some(i32::MAX as i32));
|
|
|
|
assert_eq!(i32::MAX.to_i64(), Some(i32::MAX as i64));
|
|
|
|
assert_eq!(i32::MAX.to_uint(), Some(i32::MAX as uint));
|
|
|
|
assert_eq!(i32::MAX.to_u8(), None);
|
|
|
|
assert_eq!(i32::MAX.to_u16(), None);
|
|
|
|
assert_eq!(i32::MAX.to_u32(), Some(i32::MAX as u32));
|
|
|
|
assert_eq!(i32::MAX.to_u64(), Some(i32::MAX as u64));
|
2013-09-26 03:22:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_cast_range_i64_max() {
|
2014-01-25 07:37:51 +00:00
|
|
|
// i64::MAX.to_int() is word-size specific
|
|
|
|
assert_eq!(i64::MAX.to_i8(), None);
|
|
|
|
assert_eq!(i64::MAX.to_i16(), None);
|
|
|
|
assert_eq!(i64::MAX.to_i32(), None);
|
|
|
|
assert_eq!(i64::MAX.to_i64(), Some(i64::MAX as i64));
|
|
|
|
// i64::MAX.to_uint() is word-size specific
|
|
|
|
assert_eq!(i64::MAX.to_u8(), None);
|
|
|
|
assert_eq!(i64::MAX.to_u16(), None);
|
|
|
|
assert_eq!(i64::MAX.to_u32(), None);
|
|
|
|
assert_eq!(i64::MAX.to_u64(), Some(i64::MAX as u64));
|
2013-09-26 03:22:46 +00:00
|
|
|
|
|
|
|
#[cfg(target_word_size = "32")]
|
|
|
|
fn check_word_size() {
|
2014-01-25 07:37:51 +00:00
|
|
|
assert_eq!(i64::MAX.to_int(), None);
|
|
|
|
assert_eq!(i64::MAX.to_uint(), None);
|
2013-09-26 03:22:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(target_word_size = "64")]
|
|
|
|
fn check_word_size() {
|
2014-01-25 07:37:51 +00:00
|
|
|
assert_eq!(i64::MAX.to_int(), Some(i64::MAX as int));
|
|
|
|
assert_eq!(i64::MAX.to_uint(), Some(i64::MAX as uint));
|
2013-09-26 03:22:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
check_word_size();
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_cast_range_uint_min() {
|
2014-01-25 07:37:51 +00:00
|
|
|
assert_eq!(uint::MIN.to_int(), Some(uint::MIN as int));
|
|
|
|
assert_eq!(uint::MIN.to_i8(), Some(uint::MIN as i8));
|
|
|
|
assert_eq!(uint::MIN.to_i16(), Some(uint::MIN as i16));
|
|
|
|
assert_eq!(uint::MIN.to_i32(), Some(uint::MIN as i32));
|
|
|
|
assert_eq!(uint::MIN.to_i64(), Some(uint::MIN as i64));
|
|
|
|
assert_eq!(uint::MIN.to_uint(), Some(uint::MIN as uint));
|
|
|
|
assert_eq!(uint::MIN.to_u8(), Some(uint::MIN as u8));
|
|
|
|
assert_eq!(uint::MIN.to_u16(), Some(uint::MIN as u16));
|
|
|
|
assert_eq!(uint::MIN.to_u32(), Some(uint::MIN as u32));
|
|
|
|
assert_eq!(uint::MIN.to_u64(), Some(uint::MIN as u64));
|
2013-09-26 03:22:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_cast_range_u8_min() {
|
2014-01-25 07:37:51 +00:00
|
|
|
assert_eq!(u8::MIN.to_int(), Some(u8::MIN as int));
|
|
|
|
assert_eq!(u8::MIN.to_i8(), Some(u8::MIN as i8));
|
|
|
|
assert_eq!(u8::MIN.to_i16(), Some(u8::MIN as i16));
|
|
|
|
assert_eq!(u8::MIN.to_i32(), Some(u8::MIN as i32));
|
|
|
|
assert_eq!(u8::MIN.to_i64(), Some(u8::MIN as i64));
|
|
|
|
assert_eq!(u8::MIN.to_uint(), Some(u8::MIN as uint));
|
|
|
|
assert_eq!(u8::MIN.to_u8(), Some(u8::MIN as u8));
|
|
|
|
assert_eq!(u8::MIN.to_u16(), Some(u8::MIN as u16));
|
|
|
|
assert_eq!(u8::MIN.to_u32(), Some(u8::MIN as u32));
|
|
|
|
assert_eq!(u8::MIN.to_u64(), Some(u8::MIN as u64));
|
2013-09-26 03:22:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_cast_range_u16_min() {
|
2014-01-25 07:37:51 +00:00
|
|
|
assert_eq!(u16::MIN.to_int(), Some(u16::MIN as int));
|
|
|
|
assert_eq!(u16::MIN.to_i8(), Some(u16::MIN as i8));
|
|
|
|
assert_eq!(u16::MIN.to_i16(), Some(u16::MIN as i16));
|
|
|
|
assert_eq!(u16::MIN.to_i32(), Some(u16::MIN as i32));
|
|
|
|
assert_eq!(u16::MIN.to_i64(), Some(u16::MIN as i64));
|
|
|
|
assert_eq!(u16::MIN.to_uint(), Some(u16::MIN as uint));
|
|
|
|
assert_eq!(u16::MIN.to_u8(), Some(u16::MIN as u8));
|
|
|
|
assert_eq!(u16::MIN.to_u16(), Some(u16::MIN as u16));
|
|
|
|
assert_eq!(u16::MIN.to_u32(), Some(u16::MIN as u32));
|
|
|
|
assert_eq!(u16::MIN.to_u64(), Some(u16::MIN as u64));
|
2013-09-26 03:22:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_cast_range_u32_min() {
|
2014-01-25 07:37:51 +00:00
|
|
|
assert_eq!(u32::MIN.to_int(), Some(u32::MIN as int));
|
|
|
|
assert_eq!(u32::MIN.to_i8(), Some(u32::MIN as i8));
|
|
|
|
assert_eq!(u32::MIN.to_i16(), Some(u32::MIN as i16));
|
|
|
|
assert_eq!(u32::MIN.to_i32(), Some(u32::MIN as i32));
|
|
|
|
assert_eq!(u32::MIN.to_i64(), Some(u32::MIN as i64));
|
|
|
|
assert_eq!(u32::MIN.to_uint(), Some(u32::MIN as uint));
|
|
|
|
assert_eq!(u32::MIN.to_u8(), Some(u32::MIN as u8));
|
|
|
|
assert_eq!(u32::MIN.to_u16(), Some(u32::MIN as u16));
|
|
|
|
assert_eq!(u32::MIN.to_u32(), Some(u32::MIN as u32));
|
|
|
|
assert_eq!(u32::MIN.to_u64(), Some(u32::MIN as u64));
|
2013-09-26 03:22:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_cast_range_u64_min() {
|
2014-01-25 07:37:51 +00:00
|
|
|
assert_eq!(u64::MIN.to_int(), Some(u64::MIN as int));
|
|
|
|
assert_eq!(u64::MIN.to_i8(), Some(u64::MIN as i8));
|
|
|
|
assert_eq!(u64::MIN.to_i16(), Some(u64::MIN as i16));
|
|
|
|
assert_eq!(u64::MIN.to_i32(), Some(u64::MIN as i32));
|
|
|
|
assert_eq!(u64::MIN.to_i64(), Some(u64::MIN as i64));
|
|
|
|
assert_eq!(u64::MIN.to_uint(), Some(u64::MIN as uint));
|
|
|
|
assert_eq!(u64::MIN.to_u8(), Some(u64::MIN as u8));
|
|
|
|
assert_eq!(u64::MIN.to_u16(), Some(u64::MIN as u16));
|
|
|
|
assert_eq!(u64::MIN.to_u32(), Some(u64::MIN as u32));
|
|
|
|
assert_eq!(u64::MIN.to_u64(), Some(u64::MIN as u64));
|
2013-09-26 03:22:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_cast_range_uint_max() {
|
2014-01-25 07:37:51 +00:00
|
|
|
assert_eq!(uint::MAX.to_int(), None);
|
|
|
|
assert_eq!(uint::MAX.to_i8(), None);
|
|
|
|
assert_eq!(uint::MAX.to_i16(), None);
|
|
|
|
assert_eq!(uint::MAX.to_i32(), None);
|
|
|
|
// uint::MAX.to_i64() is word-size specific
|
|
|
|
assert_eq!(uint::MAX.to_u8(), None);
|
|
|
|
assert_eq!(uint::MAX.to_u16(), None);
|
|
|
|
// uint::MAX.to_u32() is word-size specific
|
|
|
|
assert_eq!(uint::MAX.to_u64(), Some(uint::MAX as u64));
|
2013-09-26 03:22:46 +00:00
|
|
|
|
|
|
|
#[cfg(target_word_size = "32")]
|
|
|
|
fn check_word_size() {
|
2014-01-25 07:37:51 +00:00
|
|
|
assert_eq!(uint::MAX.to_u32(), Some(uint::MAX as u32));
|
|
|
|
assert_eq!(uint::MAX.to_i64(), Some(uint::MAX as i64));
|
2013-09-26 03:22:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(target_word_size = "64")]
|
|
|
|
fn check_word_size() {
|
2014-01-25 07:37:51 +00:00
|
|
|
assert_eq!(uint::MAX.to_u32(), None);
|
|
|
|
assert_eq!(uint::MAX.to_i64(), None);
|
2013-09-26 03:22:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
check_word_size();
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_cast_range_u8_max() {
|
2014-01-25 07:37:51 +00:00
|
|
|
assert_eq!(u8::MAX.to_int(), Some(u8::MAX as int));
|
|
|
|
assert_eq!(u8::MAX.to_i8(), None);
|
|
|
|
assert_eq!(u8::MAX.to_i16(), Some(u8::MAX as i16));
|
|
|
|
assert_eq!(u8::MAX.to_i32(), Some(u8::MAX as i32));
|
|
|
|
assert_eq!(u8::MAX.to_i64(), Some(u8::MAX as i64));
|
|
|
|
assert_eq!(u8::MAX.to_uint(), Some(u8::MAX as uint));
|
|
|
|
assert_eq!(u8::MAX.to_u8(), Some(u8::MAX as u8));
|
|
|
|
assert_eq!(u8::MAX.to_u16(), Some(u8::MAX as u16));
|
|
|
|
assert_eq!(u8::MAX.to_u32(), Some(u8::MAX as u32));
|
|
|
|
assert_eq!(u8::MAX.to_u64(), Some(u8::MAX as u64));
|
2013-09-26 03:22:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_cast_range_u16_max() {
|
2014-01-25 07:37:51 +00:00
|
|
|
assert_eq!(u16::MAX.to_int(), Some(u16::MAX as int));
|
|
|
|
assert_eq!(u16::MAX.to_i8(), None);
|
|
|
|
assert_eq!(u16::MAX.to_i16(), None);
|
|
|
|
assert_eq!(u16::MAX.to_i32(), Some(u16::MAX as i32));
|
|
|
|
assert_eq!(u16::MAX.to_i64(), Some(u16::MAX as i64));
|
|
|
|
assert_eq!(u16::MAX.to_uint(), Some(u16::MAX as uint));
|
|
|
|
assert_eq!(u16::MAX.to_u8(), None);
|
|
|
|
assert_eq!(u16::MAX.to_u16(), Some(u16::MAX as u16));
|
|
|
|
assert_eq!(u16::MAX.to_u32(), Some(u16::MAX as u32));
|
|
|
|
assert_eq!(u16::MAX.to_u64(), Some(u16::MAX as u64));
|
2013-09-26 03:22:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_cast_range_u32_max() {
|
2014-01-25 07:37:51 +00:00
|
|
|
// u32::MAX.to_int() is word-size specific
|
|
|
|
assert_eq!(u32::MAX.to_i8(), None);
|
|
|
|
assert_eq!(u32::MAX.to_i16(), None);
|
|
|
|
assert_eq!(u32::MAX.to_i32(), None);
|
|
|
|
assert_eq!(u32::MAX.to_i64(), Some(u32::MAX as i64));
|
|
|
|
assert_eq!(u32::MAX.to_uint(), Some(u32::MAX as uint));
|
|
|
|
assert_eq!(u32::MAX.to_u8(), None);
|
|
|
|
assert_eq!(u32::MAX.to_u16(), None);
|
|
|
|
assert_eq!(u32::MAX.to_u32(), Some(u32::MAX as u32));
|
|
|
|
assert_eq!(u32::MAX.to_u64(), Some(u32::MAX as u64));
|
2013-09-26 03:22:46 +00:00
|
|
|
|
|
|
|
#[cfg(target_word_size = "32")]
|
|
|
|
fn check_word_size() {
|
2014-01-25 07:37:51 +00:00
|
|
|
assert_eq!(u32::MAX.to_int(), None);
|
2013-09-26 03:22:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(target_word_size = "64")]
|
|
|
|
fn check_word_size() {
|
2014-01-25 07:37:51 +00:00
|
|
|
assert_eq!(u32::MAX.to_int(), Some(u32::MAX as int));
|
2013-09-26 03:22:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
check_word_size();
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_cast_range_u64_max() {
|
2014-01-25 07:37:51 +00:00
|
|
|
assert_eq!(u64::MAX.to_int(), None);
|
|
|
|
assert_eq!(u64::MAX.to_i8(), None);
|
|
|
|
assert_eq!(u64::MAX.to_i16(), None);
|
|
|
|
assert_eq!(u64::MAX.to_i32(), None);
|
|
|
|
assert_eq!(u64::MAX.to_i64(), None);
|
|
|
|
// u64::MAX.to_uint() is word-size specific
|
|
|
|
assert_eq!(u64::MAX.to_u8(), None);
|
|
|
|
assert_eq!(u64::MAX.to_u16(), None);
|
|
|
|
assert_eq!(u64::MAX.to_u32(), None);
|
|
|
|
assert_eq!(u64::MAX.to_u64(), Some(u64::MAX as u64));
|
2013-09-26 03:22:46 +00:00
|
|
|
|
|
|
|
#[cfg(target_word_size = "32")]
|
|
|
|
fn check_word_size() {
|
2014-01-25 07:37:51 +00:00
|
|
|
assert_eq!(u64::MAX.to_uint(), None);
|
2013-09-26 03:22:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(target_word_size = "64")]
|
|
|
|
fn check_word_size() {
|
2014-01-25 07:37:51 +00:00
|
|
|
assert_eq!(u64::MAX.to_uint(), Some(u64::MAX as uint));
|
2013-09-26 03:22:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
check_word_size();
|
|
|
|
}
|
|
|
|
|
2013-08-06 02:28:20 +00:00
|
|
|
#[test]
|
|
|
|
fn test_saturating_add_uint() {
|
2014-01-25 07:37:51 +00:00
|
|
|
use uint::MAX;
|
2013-08-06 02:28:20 +00:00
|
|
|
assert_eq!(3u.saturating_add(5u), 8u);
|
2014-01-25 07:37:51 +00:00
|
|
|
assert_eq!(3u.saturating_add(MAX-1), MAX);
|
|
|
|
assert_eq!(MAX.saturating_add(MAX), MAX);
|
|
|
|
assert_eq!((MAX-2).saturating_add(1), MAX-1);
|
2013-08-06 02:28:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_saturating_sub_uint() {
|
2014-01-25 07:37:51 +00:00
|
|
|
use uint::MAX;
|
2013-08-06 02:28:20 +00:00
|
|
|
assert_eq!(5u.saturating_sub(3u), 2u);
|
|
|
|
assert_eq!(3u.saturating_sub(5u), 0u);
|
|
|
|
assert_eq!(0u.saturating_sub(1u), 0u);
|
2014-01-25 07:37:51 +00:00
|
|
|
assert_eq!((MAX-1).saturating_sub(MAX), 0);
|
2013-08-06 02:28:20 +00:00
|
|
|
}
|
2013-04-13 13:44:35 +00:00
|
|
|
|
2013-08-06 02:28:20 +00:00
|
|
|
#[test]
|
|
|
|
fn test_saturating_add_int() {
|
2014-01-25 07:37:51 +00:00
|
|
|
use int::{MIN,MAX};
|
2013-08-06 02:28:20 +00:00
|
|
|
assert_eq!(3i.saturating_add(5i), 8i);
|
2014-01-25 07:37:51 +00:00
|
|
|
assert_eq!(3i.saturating_add(MAX-1), MAX);
|
|
|
|
assert_eq!(MAX.saturating_add(MAX), MAX);
|
|
|
|
assert_eq!((MAX-2).saturating_add(1), MAX-1);
|
2013-08-06 02:28:20 +00:00
|
|
|
assert_eq!(3i.saturating_add(-5i), -2i);
|
2014-01-25 07:37:51 +00:00
|
|
|
assert_eq!(MIN.saturating_add(-1i), MIN);
|
|
|
|
assert_eq!((-2i).saturating_add(-MAX), MIN);
|
2013-08-06 02:28:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_saturating_sub_int() {
|
2014-01-25 07:37:51 +00:00
|
|
|
use int::{MIN,MAX};
|
2013-08-06 02:28:20 +00:00
|
|
|
assert_eq!(3i.saturating_sub(5i), -2i);
|
2014-01-25 07:37:51 +00:00
|
|
|
assert_eq!(MIN.saturating_sub(1i), MIN);
|
|
|
|
assert_eq!((-2i).saturating_sub(MAX), MIN);
|
2013-08-06 02:28:20 +00:00
|
|
|
assert_eq!(3i.saturating_sub(-5i), 8i);
|
2014-01-25 07:37:51 +00:00
|
|
|
assert_eq!(3i.saturating_sub(-(MAX-1)), MAX);
|
|
|
|
assert_eq!(MAX.saturating_sub(-MAX), MAX);
|
|
|
|
assert_eq!((MAX-2).saturating_sub(-1), MAX-1);
|
2013-08-06 02:28:20 +00:00
|
|
|
}
|
2013-08-07 19:40:09 +00:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_checked_add() {
|
2014-01-25 07:37:51 +00:00
|
|
|
let five_less = uint::MAX - 5;
|
|
|
|
assert_eq!(five_less.checked_add(&0), Some(uint::MAX - 5));
|
|
|
|
assert_eq!(five_less.checked_add(&1), Some(uint::MAX - 4));
|
|
|
|
assert_eq!(five_less.checked_add(&2), Some(uint::MAX - 3));
|
|
|
|
assert_eq!(five_less.checked_add(&3), Some(uint::MAX - 2));
|
|
|
|
assert_eq!(five_less.checked_add(&4), Some(uint::MAX - 1));
|
|
|
|
assert_eq!(five_less.checked_add(&5), Some(uint::MAX));
|
2013-08-07 19:40:09 +00:00
|
|
|
assert_eq!(five_less.checked_add(&6), None);
|
|
|
|
assert_eq!(five_less.checked_add(&7), None);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_checked_sub() {
|
|
|
|
assert_eq!(5u.checked_sub(&0), Some(5));
|
|
|
|
assert_eq!(5u.checked_sub(&1), Some(4));
|
|
|
|
assert_eq!(5u.checked_sub(&2), Some(3));
|
|
|
|
assert_eq!(5u.checked_sub(&3), Some(2));
|
|
|
|
assert_eq!(5u.checked_sub(&4), Some(1));
|
|
|
|
assert_eq!(5u.checked_sub(&5), Some(0));
|
|
|
|
assert_eq!(5u.checked_sub(&6), None);
|
|
|
|
assert_eq!(5u.checked_sub(&7), None);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_checked_mul() {
|
2014-01-25 07:37:51 +00:00
|
|
|
let third = uint::MAX / 3;
|
2013-08-07 19:40:09 +00:00
|
|
|
assert_eq!(third.checked_mul(&0), Some(0));
|
|
|
|
assert_eq!(third.checked_mul(&1), Some(third));
|
|
|
|
assert_eq!(third.checked_mul(&2), Some(third * 2));
|
|
|
|
assert_eq!(third.checked_mul(&3), Some(third * 3));
|
|
|
|
assert_eq!(third.checked_mul(&4), None);
|
|
|
|
}
|
2013-10-08 02:56:30 +00:00
|
|
|
|
2014-01-30 05:35:17 +00:00
|
|
|
macro_rules! test_next_power_of_two(
|
|
|
|
($test_name:ident, $T:ident) => (
|
|
|
|
fn $test_name() {
|
2014-04-02 03:39:26 +00:00
|
|
|
#![test]
|
2014-01-30 05:35:17 +00:00
|
|
|
assert_eq!(next_power_of_two::<$T>(0), 0);
|
|
|
|
let mut next_power = 1;
|
|
|
|
for i in range::<$T>(1, 40) {
|
|
|
|
assert_eq!(next_power_of_two(i), next_power);
|
|
|
|
if i == next_power { next_power *= 2 }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
)
|
|
|
|
)
|
|
|
|
|
|
|
|
test_next_power_of_two!(test_next_power_of_two_u8, u8)
|
|
|
|
test_next_power_of_two!(test_next_power_of_two_u16, u16)
|
|
|
|
test_next_power_of_two!(test_next_power_of_two_u32, u32)
|
|
|
|
test_next_power_of_two!(test_next_power_of_two_u64, u64)
|
|
|
|
test_next_power_of_two!(test_next_power_of_two_uint, uint)
|
|
|
|
|
|
|
|
macro_rules! test_checked_next_power_of_two(
|
|
|
|
($test_name:ident, $T:ident) => (
|
|
|
|
fn $test_name() {
|
2014-04-02 03:39:26 +00:00
|
|
|
#![test]
|
2014-01-30 05:35:17 +00:00
|
|
|
assert_eq!(checked_next_power_of_two::<$T>(0), None);
|
|
|
|
let mut next_power = 1;
|
|
|
|
for i in range::<$T>(1, 40) {
|
|
|
|
assert_eq!(checked_next_power_of_two(i), Some(next_power));
|
|
|
|
if i == next_power { next_power *= 2 }
|
|
|
|
}
|
|
|
|
assert!(checked_next_power_of_two::<$T>($T::MAX / 2).is_some());
|
|
|
|
assert_eq!(checked_next_power_of_two::<$T>($T::MAX - 1), None);
|
|
|
|
assert_eq!(checked_next_power_of_two::<$T>($T::MAX), None);
|
|
|
|
}
|
|
|
|
)
|
|
|
|
)
|
|
|
|
|
|
|
|
test_checked_next_power_of_two!(test_checked_next_power_of_two_u8, u8)
|
|
|
|
test_checked_next_power_of_two!(test_checked_next_power_of_two_u16, u16)
|
|
|
|
test_checked_next_power_of_two!(test_checked_next_power_of_two_u32, u32)
|
|
|
|
test_checked_next_power_of_two!(test_checked_next_power_of_two_u64, u64)
|
|
|
|
test_checked_next_power_of_two!(test_checked_next_power_of_two_uint, uint)
|
2013-10-08 02:56:30 +00:00
|
|
|
|
2014-02-28 09:23:06 +00:00
|
|
|
#[deriving(Eq, Show)]
|
2013-10-08 02:56:30 +00:00
|
|
|
struct Value { x: int }
|
|
|
|
|
|
|
|
impl ToPrimitive for Value {
|
|
|
|
fn to_i64(&self) -> Option<i64> { self.x.to_i64() }
|
|
|
|
fn to_u64(&self) -> Option<u64> { self.x.to_u64() }
|
|
|
|
}
|
|
|
|
|
|
|
|
impl FromPrimitive for Value {
|
|
|
|
fn from_i64(n: i64) -> Option<Value> { Some(Value { x: n as int }) }
|
|
|
|
fn from_u64(n: u64) -> Option<Value> { Some(Value { x: n as int }) }
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_to_primitive() {
|
|
|
|
let value = Value { x: 5 };
|
|
|
|
assert_eq!(value.to_int(), Some(5));
|
|
|
|
assert_eq!(value.to_i8(), Some(5));
|
|
|
|
assert_eq!(value.to_i16(), Some(5));
|
|
|
|
assert_eq!(value.to_i32(), Some(5));
|
|
|
|
assert_eq!(value.to_i64(), Some(5));
|
|
|
|
assert_eq!(value.to_uint(), Some(5));
|
|
|
|
assert_eq!(value.to_u8(), Some(5));
|
|
|
|
assert_eq!(value.to_u16(), Some(5));
|
|
|
|
assert_eq!(value.to_u32(), Some(5));
|
|
|
|
assert_eq!(value.to_u64(), Some(5));
|
|
|
|
assert_eq!(value.to_f32(), Some(5f32));
|
|
|
|
assert_eq!(value.to_f64(), Some(5f64));
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_from_primitive() {
|
|
|
|
assert_eq!(from_int(5), Some(Value { x: 5 }));
|
|
|
|
assert_eq!(from_i8(5), Some(Value { x: 5 }));
|
|
|
|
assert_eq!(from_i16(5), Some(Value { x: 5 }));
|
|
|
|
assert_eq!(from_i32(5), Some(Value { x: 5 }));
|
|
|
|
assert_eq!(from_i64(5), Some(Value { x: 5 }));
|
|
|
|
assert_eq!(from_uint(5), Some(Value { x: 5 }));
|
|
|
|
assert_eq!(from_u8(5), Some(Value { x: 5 }));
|
|
|
|
assert_eq!(from_u16(5), Some(Value { x: 5 }));
|
|
|
|
assert_eq!(from_u32(5), Some(Value { x: 5 }));
|
|
|
|
assert_eq!(from_u64(5), Some(Value { x: 5 }));
|
|
|
|
assert_eq!(from_f32(5f32), Some(Value { x: 5 }));
|
|
|
|
assert_eq!(from_f64(5f64), Some(Value { x: 5 }));
|
|
|
|
}
|
2014-01-12 20:02:59 +00:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_pow() {
|
2014-01-19 13:39:05 +00:00
|
|
|
fn naive_pow<T: One + Mul<T, T>>(base: T, exp: uint) -> T {
|
|
|
|
range(0, exp).fold(one::<T>(), |acc, _| acc * base)
|
2014-01-12 20:02:59 +00:00
|
|
|
}
|
2014-01-19 13:39:05 +00:00
|
|
|
macro_rules! assert_pow(
|
|
|
|
(($num:expr, $exp:expr) => $expected:expr) => {{
|
|
|
|
let result = pow($num, $exp);
|
|
|
|
assert_eq!(result, $expected);
|
|
|
|
assert_eq!(result, naive_pow($num, $exp));
|
|
|
|
}}
|
|
|
|
)
|
|
|
|
assert_pow!((3, 0 ) => 1);
|
|
|
|
assert_pow!((5, 1 ) => 5);
|
|
|
|
assert_pow!((-4, 2 ) => 16);
|
|
|
|
assert_pow!((0.5, 5 ) => 0.03125);
|
|
|
|
assert_pow!((8, 3 ) => 512);
|
|
|
|
assert_pow!((8.0, 5 ) => 32768.0);
|
|
|
|
assert_pow!((8.5, 5 ) => 44370.53125);
|
|
|
|
assert_pow!((2u64, 50) => 1125899906842624);
|
2014-01-12 20:02:59 +00:00
|
|
|
}
|
2013-08-06 02:28:20 +00:00
|
|
|
}
|
2014-01-18 18:25:38 +00:00
|
|
|
|
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
mod bench {
|
2014-02-14 01:49:11 +00:00
|
|
|
extern crate test;
|
2014-04-01 01:16:35 +00:00
|
|
|
use self::test::Bencher;
|
2014-01-18 18:25:38 +00:00
|
|
|
use num;
|
|
|
|
use prelude::*;
|
|
|
|
|
|
|
|
#[bench]
|
2014-04-01 01:16:35 +00:00
|
|
|
fn bench_pow_function(b: &mut Bencher) {
|
2014-04-17 22:28:14 +00:00
|
|
|
let v = Vec::from_fn(1024, |n| n);
|
2014-01-18 18:25:38 +00:00
|
|
|
b.iter(|| {v.iter().fold(0, |old, new| num::pow(old, *new));});
|
|
|
|
}
|
|
|
|
}
|