2013-02-15 03:29:36 +01:00
|
|
|
// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
|
2012-12-03 16:48:01 -08: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 17:08:28 +01:00
|
|
|
//! Numeric traits and functions for generic mathematics
|
2013-07-30 08:59:43 +10: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 16:35:52 -05:00
|
|
|
|
|
|
|
#[allow(missing_doc)];
|
|
|
|
|
2013-09-07 17:16:56 +10:00
|
|
|
use clone::{Clone, DeepClone};
|
2013-05-06 16:10:26 +10:00
|
|
|
use cmp::{Eq, ApproxEq, Ord};
|
2013-05-01 15:40:05 +10:00
|
|
|
use ops::{Add, Sub, Mul, Div, Rem, Neg};
|
2013-04-26 10:02:00 +10:00
|
|
|
use ops::{Not, BitAnd, BitOr, BitXor, Shl, Shr};
|
2013-08-07 15:40:09 -04:00
|
|
|
use option::{Option, Some, None};
|
2012-06-07 17:25:54 -07:00
|
|
|
|
2013-02-15 03:29:36 +01:00
|
|
|
pub mod strconv;
|
|
|
|
|
2013-04-27 01:01:53 +10:00
|
|
|
/// The base trait for numeric types
|
2013-04-14 02:19:35 +10:00
|
|
|
pub trait Num: Eq + Zero + One
|
|
|
|
+ Neg<Self>
|
|
|
|
+ Add<Self,Self>
|
|
|
|
+ Sub<Self,Self>
|
|
|
|
+ Mul<Self,Self>
|
2013-05-01 15:40:05 +10:00
|
|
|
+ Div<Self,Self>
|
2013-04-22 01:58:53 +10:00
|
|
|
+ Rem<Self,Self> {}
|
2013-04-14 02:19:35 +10:00
|
|
|
|
2013-04-27 01:01:53 +10:00
|
|
|
pub trait Orderable: Ord {
|
|
|
|
// These should be methods on `Ord`, with overridable default implementations. We don't want
|
|
|
|
// to encumber all implementors of Ord by requiring them to implement these functions, but at
|
|
|
|
// the same time we want to be able to take advantage of the speed of the specific numeric
|
|
|
|
// functions (like the `fmin` and `fmax` intrinsics).
|
|
|
|
fn min(&self, other: &Self) -> Self;
|
|
|
|
fn max(&self, other: &Self) -> Self;
|
|
|
|
fn clamp(&self, mn: &Self, mx: &Self) -> Self;
|
|
|
|
}
|
|
|
|
|
2013-09-24 10:25:45 -07:00
|
|
|
/// Return the smaller number.
|
2013-07-30 08:58:46 +10:00
|
|
|
#[inline(always)] pub fn min<T: Orderable>(x: T, y: T) -> T { x.min(&y) }
|
2013-09-24 10:25:45 -07:00
|
|
|
/// Return the larger number.
|
2013-07-30 08:58:46 +10:00
|
|
|
#[inline(always)] pub fn max<T: Orderable>(x: T, y: T) -> T { x.max(&y) }
|
2013-09-24 10:25:45 -07:00
|
|
|
/// Returns the number constrained within the range `mn <= self <= mx`.
|
2013-07-30 08:58:46 +10:00
|
|
|
#[inline(always)] pub fn clamp<T: Orderable>(value: T, mn: T, mx: T) -> T { value.clamp(&mn, &mx) }
|
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 18:05:17 +02:00
|
|
|
|
2012-12-20 07:14:38 -08:00
|
|
|
pub trait Zero {
|
2013-04-25 15:30:56 +10:00
|
|
|
fn zero() -> Self; // FIXME (#5527): This should be an associated constant
|
|
|
|
fn is_zero(&self) -> bool;
|
2012-12-20 07:14:38 -08:00
|
|
|
}
|
|
|
|
|
2013-09-24 10:25:45 -07:00
|
|
|
/// Returns `0` of appropriate type.
|
2013-07-30 08:58:46 +10:00
|
|
|
#[inline(always)] pub fn zero<T: Zero>() -> T { Zero::zero() }
|
|
|
|
|
2012-12-20 07:14:38 -08:00
|
|
|
pub trait One {
|
2013-04-25 15:30:56 +10:00
|
|
|
fn one() -> Self; // FIXME (#5527): This should be an associated constant
|
2012-12-20 07:14:38 -08:00
|
|
|
}
|
2013-01-27 03:05:20 +01:00
|
|
|
|
2013-09-24 10:25:45 -07:00
|
|
|
/// Returns `1` of appropriate type.
|
2013-07-30 08:58:46 +10:00
|
|
|
#[inline(always)] pub fn one<T: One>() -> T { One::one() }
|
|
|
|
|
2013-04-23 17:59:49 +10:00
|
|
|
pub trait Signed: Num
|
|
|
|
+ Neg<Self> {
|
|
|
|
fn abs(&self) -> Self;
|
2013-05-07 14:36:32 +10:00
|
|
|
fn abs_sub(&self, other: &Self) -> Self;
|
2013-04-23 17:59:49 +10:00
|
|
|
fn signum(&self) -> Self;
|
2013-05-07 14:36:32 +10:00
|
|
|
|
2013-04-23 17:59:49 +10:00
|
|
|
fn is_positive(&self) -> bool;
|
|
|
|
fn is_negative(&self) -> bool;
|
|
|
|
}
|
|
|
|
|
2013-09-24 10:25:45 -07:00
|
|
|
/// Computes the absolute value.
|
|
|
|
///
|
|
|
|
/// For float, f32, and f64, `NaN` will be returned if the number is `NaN`
|
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 18:05:17 +02:00
|
|
|
#[inline(always)] pub fn abs<T: Signed>(value: T) -> T { value.abs() }
|
2013-09-24 10:25:45 -07: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-07-30 08:58:46 +10:00
|
|
|
#[inline(always)] pub fn abs_sub<T: Signed>(x: T, y: T) -> T { x.abs_sub(&y) }
|
2013-09-24 10:25:45 -07:00
|
|
|
/// Returns the sign of the number.
|
|
|
|
///
|
|
|
|
/// For float, f32, f64:
|
2013-10-28 17:34:33 -07: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 10:25:45 -07: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 18:05:17 +02:00
|
|
|
#[inline(always)] pub fn signum<T: Signed>(value: T) -> T { value.signum() }
|
2013-04-23 17:59:49 +10:00
|
|
|
|
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 18:05:17 +02:00
|
|
|
pub trait Unsigned: Num {}
|
2013-01-15 17:30:16 -08:00
|
|
|
|
2013-08-29 01:27:24 -04:00
|
|
|
/// Times trait
|
|
|
|
///
|
2013-09-23 17:20:36 -07:00
|
|
|
/// ```rust
|
2013-12-22 13:31:23 -08:00
|
|
|
/// let ten = 10u;
|
2013-08-29 01:27:24 -04:00
|
|
|
/// let mut accum = 0;
|
2013-11-22 14:15:32 -08:00
|
|
|
/// ten.times(|| { accum += 1; })
|
2013-09-23 17:20:36 -07:00
|
|
|
/// ```
|
2013-08-29 01:27:24 -04:00
|
|
|
///
|
|
|
|
pub trait Times {
|
2013-11-18 21:15:42 -08:00
|
|
|
fn times(&self, it: ||);
|
2013-08-29 01:27:24 -04:00
|
|
|
}
|
|
|
|
|
2013-04-24 22:45:57 +10:00
|
|
|
pub trait Integer: Num
|
2013-04-27 01:01:53 +10:00
|
|
|
+ Orderable
|
2013-05-01 15:40:05 +10:00
|
|
|
+ Div<Self,Self>
|
2013-04-24 12:54:11 +10:00
|
|
|
+ Rem<Self,Self> {
|
2013-05-01 15:40:05 +10:00
|
|
|
fn div_rem(&self, other: &Self) -> (Self,Self);
|
|
|
|
|
|
|
|
fn div_floor(&self, other: &Self) -> Self;
|
|
|
|
fn mod_floor(&self, other: &Self) -> Self;
|
|
|
|
fn div_mod_floor(&self, other: &Self) -> (Self,Self);
|
2013-04-24 12:54:11 +10:00
|
|
|
|
2013-04-24 22:50:56 +10:00
|
|
|
fn gcd(&self, other: &Self) -> Self;
|
|
|
|
fn lcm(&self, other: &Self) -> Self;
|
2013-04-29 16:02:43 +10:00
|
|
|
|
|
|
|
fn is_multiple_of(&self, other: &Self) -> bool;
|
2013-04-24 12:54:11 +10:00
|
|
|
fn is_even(&self) -> bool;
|
|
|
|
fn is_odd(&self) -> bool;
|
|
|
|
}
|
|
|
|
|
2013-09-24 10:25:45 -07:00
|
|
|
/// Calculates the Greatest Common Divisor (GCD) of the number and `other`.
|
|
|
|
///
|
|
|
|
/// The result is always positive.
|
2013-07-30 08:58:46 +10:00
|
|
|
#[inline(always)] pub fn gcd<T: Integer>(x: T, y: T) -> T { x.gcd(&y) }
|
2013-09-24 10:25:45 -07:00
|
|
|
/// Calculates the Lowest Common Multiple (LCM) of the number and `other`.
|
2013-07-30 08:58:46 +10:00
|
|
|
#[inline(always)] pub fn lcm<T: Integer>(x: T, y: T) -> T { x.lcm(&y) }
|
|
|
|
|
2013-11-09 23:11:39 -07:00
|
|
|
/// A collection of rounding operations.
|
2013-04-25 11:53:04 +10:00
|
|
|
pub trait Round {
|
2013-11-09 23:11:39 -07:00
|
|
|
/// Return the largest integer less than or equal to a number.
|
|
|
|
///
|
|
|
|
/// # Example
|
|
|
|
///
|
|
|
|
/// ```rust
|
|
|
|
/// assert_approx_eq!(1.3f32.floor(), 1.0);
|
|
|
|
/// assert_approx_eq!((-1.3f32).floor(), -2.0);
|
|
|
|
/// ```
|
2013-04-25 11:53:04 +10:00
|
|
|
fn floor(&self) -> Self;
|
2013-11-09 23:11:39 -07:00
|
|
|
|
|
|
|
/// Return the smallest integer greater than or equal to a number.
|
|
|
|
///
|
|
|
|
/// # Example
|
|
|
|
///
|
|
|
|
/// ```rust
|
|
|
|
/// assert_approx_eq!(1.3f32.ceil(), 2.0);
|
|
|
|
/// assert_approx_eq!((-1.3f32).ceil(), -1.0);
|
|
|
|
/// ```
|
2013-04-25 11:53:04 +10:00
|
|
|
fn ceil(&self) -> Self;
|
2013-11-09 23:11:39 -07:00
|
|
|
|
|
|
|
/// Return the nearest integer to a number. Round half-way cases away from
|
|
|
|
/// `0.0`.
|
|
|
|
///
|
|
|
|
/// # Example
|
|
|
|
///
|
|
|
|
/// ```rust
|
|
|
|
/// assert_approx_eq!(1.3f32.round(), 1.0);
|
|
|
|
/// assert_approx_eq!((-1.3f32).round(), -1.0);
|
|
|
|
/// assert_approx_eq!(1.5f32.round(), 2.0);
|
|
|
|
/// assert_approx_eq!((-1.5f32).round(), -2.0);
|
|
|
|
/// ```
|
2013-04-25 11:53:04 +10:00
|
|
|
fn round(&self) -> Self;
|
2013-11-09 23:11:39 -07:00
|
|
|
|
|
|
|
/// Return the integer part of a number.
|
|
|
|
///
|
|
|
|
/// # Example
|
|
|
|
///
|
|
|
|
/// ```rust
|
2013-12-22 13:31:23 -08:00
|
|
|
/// assert_approx_eq!(1.3f32.trunc(), 1.0);
|
|
|
|
/// assert_approx_eq!((-1.3f32).trunc(), -1.0);
|
|
|
|
/// assert_approx_eq!(1.5f32.trunc(), 1.0);
|
|
|
|
/// assert_approx_eq!((-1.5f32).trunc(), -1.0);
|
2013-11-09 23:11:39 -07:00
|
|
|
/// ```
|
2013-04-25 11:53:04 +10:00
|
|
|
fn trunc(&self) -> Self;
|
2013-11-09 23:11:39 -07:00
|
|
|
|
|
|
|
/// Return the fractional part of a number.
|
|
|
|
///
|
|
|
|
/// # Example
|
|
|
|
///
|
|
|
|
/// ```rust
|
2013-12-22 13:31:23 -08:00
|
|
|
/// assert_approx_eq!(1.3f32.fract(), 0.3);
|
|
|
|
/// assert_approx_eq!((-1.3f32).fract(), -0.3);
|
|
|
|
/// assert_approx_eq!(1.5f32.fract(), 0.5);
|
|
|
|
/// assert_approx_eq!((-1.5f32).fract(), -0.5);
|
2013-11-09 23:11:39 -07:00
|
|
|
/// ```
|
2013-04-25 11:53:04 +10:00
|
|
|
fn fract(&self) -> Self;
|
|
|
|
}
|
|
|
|
|
2013-11-09 23:11:39 -07:00
|
|
|
/// Trait for common fractional operations.
|
2013-04-25 08:12:26 +10:00
|
|
|
pub trait Fractional: Num
|
2013-04-27 01:01:53 +10:00
|
|
|
+ Orderable
|
2013-04-25 11:53:04 +10:00
|
|
|
+ Round
|
2013-05-01 15:40:05 +10:00
|
|
|
+ Div<Self,Self> {
|
2013-11-09 23:11:39 -07:00
|
|
|
/// Take the reciprocal (inverse) of a number, `1/x`.
|
2013-04-25 08:12:26 +10:00
|
|
|
fn recip(&self) -> Self;
|
|
|
|
}
|
|
|
|
|
2013-11-09 23:11:39 -07:00
|
|
|
/// A collection of algebraic operations.
|
2013-04-29 15:33:55 +10:00
|
|
|
pub trait Algebraic {
|
2013-11-09 23:11:39 -07:00
|
|
|
/// Raise a number to a power.
|
2013-06-11 11:03:02 +10:00
|
|
|
fn pow(&self, n: &Self) -> Self;
|
2013-12-15 16:26:09 +11:00
|
|
|
/// Take the square root of a number.
|
2013-04-29 15:33:55 +10:00
|
|
|
fn sqrt(&self) -> Self;
|
2013-11-09 23:11:39 -07:00
|
|
|
/// Take the reciprocal (inverse) square root of a number, `1/sqrt(x)`.
|
2013-04-29 15:33:55 +10:00
|
|
|
fn rsqrt(&self) -> Self;
|
2013-11-09 23:11:39 -07:00
|
|
|
/// Take the cubic root of a number.
|
2013-04-29 15:33:55 +10:00
|
|
|
fn cbrt(&self) -> Self;
|
2013-11-09 23:11:39 -07:00
|
|
|
/// Calculate the length of the hypotenuse of a right-angle triangle given
|
|
|
|
/// legs of length `x` and `y`.
|
2013-06-11 11:03:02 +10:00
|
|
|
fn hypot(&self, other: &Self) -> Self;
|
2013-04-29 15:33:55 +10:00
|
|
|
}
|
|
|
|
|
2013-09-24 10:25:45 -07:00
|
|
|
/// Raise a number to a power.
|
|
|
|
///
|
|
|
|
/// # Example
|
|
|
|
///
|
|
|
|
/// ```rust
|
2013-12-22 13:31:23 -08:00
|
|
|
/// use std::num;
|
|
|
|
///
|
|
|
|
/// let sixteen: f64 = num::pow(2.0, 4.0);
|
2013-09-24 10:25:45 -07:00
|
|
|
/// assert_eq!(sixteen, 16.0);
|
|
|
|
/// ```
|
2013-07-30 08:58:46 +10:00
|
|
|
#[inline(always)] pub fn pow<T: Algebraic>(value: T, n: T) -> T { value.pow(&n) }
|
2013-12-15 16:26:09 +11:00
|
|
|
/// Take the square root of a number.
|
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 18:05:17 +02:00
|
|
|
#[inline(always)] pub fn sqrt<T: Algebraic>(value: T) -> T { value.sqrt() }
|
2013-09-24 10:25:45 -07:00
|
|
|
/// Take the reciprocal (inverse) square root of a number, `1/sqrt(x)`.
|
2013-07-30 08:58:46 +10:00
|
|
|
#[inline(always)] pub fn rsqrt<T: Algebraic>(value: T) -> T { value.rsqrt() }
|
2013-09-24 10:25:45 -07:00
|
|
|
/// Take the cubic root of a number.
|
2013-07-30 08:58:46 +10:00
|
|
|
#[inline(always)] pub fn cbrt<T: Algebraic>(value: T) -> T { value.cbrt() }
|
2013-09-24 10:25:45 -07:00
|
|
|
/// Calculate the length of the hypotenuse of a right-angle triangle given legs of length `x` and
|
|
|
|
/// `y`.
|
2013-07-30 08:58:46 +10:00
|
|
|
#[inline(always)] pub fn hypot<T: Algebraic>(x: T, y: T) -> T { x.hypot(&y) }
|
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 18:05:17 +02:00
|
|
|
|
2013-11-09 23:11:39 -07:00
|
|
|
/// A trait for trigonometric functions.
|
2013-04-29 15:33:55 +10:00
|
|
|
pub trait Trigonometric {
|
2013-11-09 23:11:39 -07:00
|
|
|
/// Computes the sine of a number (in radians).
|
2013-04-29 15:33:55 +10:00
|
|
|
fn sin(&self) -> Self;
|
2013-11-09 23:11:39 -07:00
|
|
|
/// Computes the cosine of a number (in radians).
|
2013-04-29 15:33:55 +10:00
|
|
|
fn cos(&self) -> Self;
|
2013-11-09 23:11:39 -07:00
|
|
|
/// Computes the tangent of a number (in radians).
|
2013-04-29 15:33:55 +10:00
|
|
|
fn tan(&self) -> Self;
|
2013-07-30 08:58:46 +10:00
|
|
|
|
2013-11-09 23:11:39 -07: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].
|
2013-04-29 15:33:55 +10:00
|
|
|
fn asin(&self) -> Self;
|
2013-11-09 23:11:39 -07: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].
|
2013-04-29 15:33:55 +10:00
|
|
|
fn acos(&self) -> Self;
|
2013-11-09 23:11:39 -07:00
|
|
|
/// Computes the arctangent of a number. Return value is in radians in the
|
|
|
|
/// range [-pi/2, pi/2];
|
2013-04-29 15:33:55 +10:00
|
|
|
fn atan(&self) -> Self;
|
2013-07-30 08:58:46 +10:00
|
|
|
|
2013-11-09 23:11:39 -07:00
|
|
|
/// Computes the four quadrant arctangent of a number, `y`, and another
|
|
|
|
/// number `x`. Return value is in radians in the range [-pi, pi];
|
|
|
|
///
|
|
|
|
/// # Example
|
|
|
|
///
|
|
|
|
/// ```rust
|
2013-12-22 13:31:23 -08:00
|
|
|
/// use std::f32;
|
|
|
|
///
|
2013-11-09 23:11:39 -07:00
|
|
|
/// let y = 3f32.sqrt();
|
|
|
|
/// let x = 1f32;
|
2013-11-11 20:52:42 -07:00
|
|
|
/// assert_approx_eq!(y.atan2(&x), f32::consts::PI / 3f32);
|
|
|
|
/// assert_approx_eq!((-y).atan2(&(-x)), - 2f32 * f32::consts::PI / 3f32);
|
2013-11-09 23:11:39 -07:00
|
|
|
/// ```
|
2013-06-11 11:03:02 +10:00
|
|
|
fn atan2(&self, other: &Self) -> Self;
|
2013-11-09 23:11:39 -07:00
|
|
|
|
|
|
|
/// Simultaneously computes the sine and cosine of the number, `x`. Returns
|
|
|
|
/// `(sin(x), cos(x))`.
|
2013-05-17 12:30:02 +10:00
|
|
|
fn sin_cos(&self) -> (Self, Self);
|
2013-04-29 15:33:55 +10:00
|
|
|
}
|
|
|
|
|
2013-09-24 10:25:45 -07:00
|
|
|
/// Sine function.
|
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 18:05:17 +02:00
|
|
|
#[inline(always)] pub fn sin<T: Trigonometric>(value: T) -> T { value.sin() }
|
2013-09-24 10:25:45 -07:00
|
|
|
/// Cosine function.
|
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 18:05:17 +02:00
|
|
|
#[inline(always)] pub fn cos<T: Trigonometric>(value: T) -> T { value.cos() }
|
2013-09-24 10:25:45 -07:00
|
|
|
/// Tangent function.
|
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 18:05:17 +02:00
|
|
|
#[inline(always)] pub fn tan<T: Trigonometric>(value: T) -> T { value.tan() }
|
|
|
|
|
2013-09-24 10:25:45 -07:00
|
|
|
/// Compute the arcsine of the number.
|
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 18:05:17 +02:00
|
|
|
#[inline(always)] pub fn asin<T: Trigonometric>(value: T) -> T { value.asin() }
|
2013-09-24 10:25:45 -07:00
|
|
|
/// Compute the arccosine of the number.
|
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 18:05:17 +02:00
|
|
|
#[inline(always)] pub fn acos<T: Trigonometric>(value: T) -> T { value.acos() }
|
2013-09-24 10:25:45 -07:00
|
|
|
/// Compute the arctangent of the number.
|
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 18:05:17 +02:00
|
|
|
#[inline(always)] pub fn atan<T: Trigonometric>(value: T) -> T { value.atan() }
|
|
|
|
|
2013-09-24 10:25:45 -07:00
|
|
|
/// Compute the arctangent with 2 arguments.
|
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 18:05:17 +02:00
|
|
|
#[inline(always)] pub fn atan2<T: Trigonometric>(x: T, y: T) -> T { x.atan2(&y) }
|
2013-09-24 10:25:45 -07:00
|
|
|
/// Simultaneously computes the sine and cosine of the number.
|
2013-07-30 08:58:46 +10:00
|
|
|
#[inline(always)] pub fn sin_cos<T: Trigonometric>(value: T) -> (T, T) { value.sin_cos() }
|
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 18:05:17 +02:00
|
|
|
|
2013-11-10 21:39:16 -07:00
|
|
|
/// A trait exponential functions.
|
2013-04-29 15:33:55 +10:00
|
|
|
pub trait Exponential {
|
2013-11-10 21:39:16 -07:00
|
|
|
/// Returns `e^(self)`, (the exponential function).
|
2013-04-29 15:33:55 +10:00
|
|
|
fn exp(&self) -> Self;
|
2013-11-10 21:39:16 -07:00
|
|
|
/// Returns 2 raised to the power of the number, `2^(self)`.
|
2013-04-29 15:33:55 +10:00
|
|
|
fn exp2(&self) -> Self;
|
2013-07-30 08:58:46 +10:00
|
|
|
|
2013-11-10 21:39:16 -07:00
|
|
|
/// Returns the natural logarithm of the number.
|
2013-05-07 03:09:09 +10:00
|
|
|
fn ln(&self) -> Self;
|
2013-11-10 21:39:16 -07:00
|
|
|
/// Returns the logarithm of the number with respect to an arbitrary base.
|
2013-06-11 11:03:02 +10:00
|
|
|
fn log(&self, base: &Self) -> Self;
|
2013-11-10 21:39:16 -07:00
|
|
|
/// Returns the base 2 logarithm of the number.
|
2013-04-29 15:33:55 +10:00
|
|
|
fn log2(&self) -> Self;
|
2013-11-10 21:39:16 -07:00
|
|
|
/// Returns the base 10 logarithm of the number.
|
2013-04-29 15:33:55 +10:00
|
|
|
fn log10(&self) -> Self;
|
2013-04-29 23:38:58 +10:00
|
|
|
}
|
2013-04-29 15:33:55 +10:00
|
|
|
|
2013-09-24 10:25:45 -07:00
|
|
|
/// Returns `e^(value)`, (the exponential function).
|
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 18:05:17 +02:00
|
|
|
#[inline(always)] pub fn exp<T: Exponential>(value: T) -> T { value.exp() }
|
2013-09-24 10:25:45 -07:00
|
|
|
/// Returns 2 raised to the power of the number, `2^(value)`.
|
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 18:05:17 +02:00
|
|
|
#[inline(always)] pub fn exp2<T: Exponential>(value: T) -> T { value.exp2() }
|
|
|
|
|
2013-09-24 10:25:45 -07:00
|
|
|
/// Returns the natural logarithm of the number.
|
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 18:05:17 +02:00
|
|
|
#[inline(always)] pub fn ln<T: Exponential>(value: T) -> T { value.ln() }
|
2013-09-24 10:25:45 -07:00
|
|
|
/// Returns the logarithm of the number with respect to an arbitrary base.
|
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 18:05:17 +02:00
|
|
|
#[inline(always)] pub fn log<T: Exponential>(value: T, base: T) -> T { value.log(&base) }
|
2013-09-24 10:25:45 -07:00
|
|
|
/// Returns the base 2 logarithm of the number.
|
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 18:05:17 +02:00
|
|
|
#[inline(always)] pub fn log2<T: Exponential>(value: T) -> T { value.log2() }
|
2013-09-24 10:25:45 -07:00
|
|
|
/// Returns the base 10 logarithm of the number.
|
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 18:05:17 +02:00
|
|
|
#[inline(always)] pub fn log10<T: Exponential>(value: T) -> T { value.log10() }
|
|
|
|
|
2013-11-10 21:39:16 -07:00
|
|
|
/// A trait hyperbolic functions.
|
2013-04-29 23:38:58 +10:00
|
|
|
pub trait Hyperbolic: Exponential {
|
2013-11-10 21:39:16 -07:00
|
|
|
/// Hyperbolic sine function.
|
2013-04-29 15:33:55 +10:00
|
|
|
fn sinh(&self) -> Self;
|
2013-11-10 21:39:16 -07:00
|
|
|
/// Hyperbolic cosine function.
|
2013-04-29 15:33:55 +10:00
|
|
|
fn cosh(&self) -> Self;
|
2013-11-10 21:39:16 -07:00
|
|
|
/// Hyperbolic tangent function.
|
2013-04-29 15:33:55 +10:00
|
|
|
fn tanh(&self) -> Self;
|
2013-07-30 08:58:46 +10:00
|
|
|
|
2013-11-10 21:39:16 -07:00
|
|
|
/// Inverse hyperbolic sine function.
|
2013-05-14 00:11:35 +10:00
|
|
|
fn asinh(&self) -> Self;
|
2013-11-10 21:39:16 -07:00
|
|
|
/// Inverse hyperbolic cosine function.
|
2013-05-14 00:11:35 +10:00
|
|
|
fn acosh(&self) -> Self;
|
2013-11-10 21:39:16 -07:00
|
|
|
/// Inverse hyperbolic tangent function.
|
2013-05-14 00:11:35 +10:00
|
|
|
fn atanh(&self) -> Self;
|
2013-04-29 15:33:55 +10:00
|
|
|
}
|
|
|
|
|
2013-09-24 10:25:45 -07:00
|
|
|
/// Hyperbolic sine function.
|
2013-11-10 21:39:16 -07:00
|
|
|
#[inline(always)] pub fn sinh<T: Hyperbolic>(value: T) -> T { value.sinh() }
|
|
|
|
/// Hyperbolic cosine function.
|
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 18:05:17 +02:00
|
|
|
#[inline(always)] pub fn cosh<T: Hyperbolic>(value: T) -> T { value.cosh() }
|
2013-09-24 10:25:45 -07:00
|
|
|
/// Hyperbolic tangent function.
|
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 18:05:17 +02:00
|
|
|
#[inline(always)] pub fn tanh<T: Hyperbolic>(value: T) -> T { value.tanh() }
|
|
|
|
|
2013-09-24 10:25:45 -07:00
|
|
|
/// Inverse hyperbolic sine function.
|
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 18:05:17 +02:00
|
|
|
#[inline(always)] pub fn asinh<T: Hyperbolic>(value: T) -> T { value.asinh() }
|
2013-09-24 10:25:45 -07:00
|
|
|
/// Inverse hyperbolic cosine function.
|
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 18:05:17 +02:00
|
|
|
#[inline(always)] pub fn acosh<T: Hyperbolic>(value: T) -> T { value.acosh() }
|
2013-09-24 10:25:45 -07:00
|
|
|
/// Inverse hyperbolic tangent function.
|
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 18:05:17 +02:00
|
|
|
#[inline(always)] pub fn atanh<T: Hyperbolic>(value: T) -> T { value.atanh() }
|
|
|
|
|
2013-04-27 01:02:30 +10:00
|
|
|
/// Defines constants and methods common to real numbers
|
2013-04-25 08:12:26 +10:00
|
|
|
pub trait Real: Signed
|
2013-04-29 15:33:55 +10:00
|
|
|
+ Fractional
|
|
|
|
+ Algebraic
|
|
|
|
+ Trigonometric
|
2013-04-29 23:38:58 +10:00
|
|
|
+ Hyperbolic {
|
2013-04-25 08:12:26 +10:00
|
|
|
// Common Constants
|
|
|
|
// FIXME (#5527): These should be associated constants
|
|
|
|
fn pi() -> Self;
|
|
|
|
fn two_pi() -> Self;
|
|
|
|
fn frac_pi_2() -> Self;
|
|
|
|
fn frac_pi_3() -> Self;
|
|
|
|
fn frac_pi_4() -> Self;
|
|
|
|
fn frac_pi_6() -> Self;
|
|
|
|
fn frac_pi_8() -> Self;
|
|
|
|
fn frac_1_pi() -> Self;
|
|
|
|
fn frac_2_pi() -> Self;
|
|
|
|
fn frac_2_sqrtpi() -> Self;
|
|
|
|
fn sqrt2() -> Self;
|
|
|
|
fn frac_1_sqrt2() -> Self;
|
|
|
|
fn e() -> Self;
|
|
|
|
fn log2_e() -> Self;
|
|
|
|
fn log10_e() -> Self;
|
2013-05-07 03:09:09 +10:00
|
|
|
fn ln_2() -> Self;
|
|
|
|
fn ln_10() -> Self;
|
2013-01-27 03:05:20 +01:00
|
|
|
|
2013-04-25 08:12:26 +10:00
|
|
|
// Angular conversions
|
2013-11-10 21:39:16 -07:00
|
|
|
|
|
|
|
/// Convert radians to degrees.
|
2013-11-11 18:56:48 -07:00
|
|
|
fn to_degrees(&self) -> Self;
|
|
|
|
/// Convert degrees to radians.
|
2013-04-25 08:12:26 +10:00
|
|
|
fn to_radians(&self) -> Self;
|
2013-01-27 03:05:20 +01:00
|
|
|
}
|
|
|
|
|
2013-04-25 08:12:26 +10:00
|
|
|
/// Methods that are harder to implement and not commonly used.
|
|
|
|
pub trait RealExt: Real {
|
|
|
|
// FIXME (#5527): usages of `int` should be replaced with an associated
|
|
|
|
// integer type once these are implemented
|
|
|
|
|
|
|
|
// Gamma functions
|
|
|
|
fn lgamma(&self) -> (int, Self);
|
|
|
|
fn tgamma(&self) -> Self;
|
|
|
|
|
|
|
|
// Bessel functions
|
|
|
|
fn j0(&self) -> Self;
|
|
|
|
fn j1(&self) -> Self;
|
|
|
|
fn jn(&self, n: int) -> Self;
|
|
|
|
fn y0(&self) -> Self;
|
|
|
|
fn y1(&self) -> Self;
|
|
|
|
fn yn(&self, n: int) -> Self;
|
2013-02-15 05:46:07 +01:00
|
|
|
}
|
|
|
|
|
2013-04-26 10:02:00 +10:00
|
|
|
/// Collects the bitwise operators under one trait.
|
|
|
|
pub trait Bitwise: Not<Self>
|
|
|
|
+ BitAnd<Self,Self>
|
|
|
|
+ BitOr<Self,Self>
|
|
|
|
+ BitXor<Self,Self>
|
|
|
|
+ Shl<Self,Self>
|
|
|
|
+ Shr<Self,Self> {}
|
|
|
|
|
2013-11-10 21:39:16 -07:00
|
|
|
/// A trait for common counting operations on bits.
|
2013-04-26 16:27:51 +10:00
|
|
|
pub trait BitCount {
|
2013-11-10 21:39:16 -07:00
|
|
|
/// Returns the number of bits set in the number.
|
|
|
|
///
|
|
|
|
/// # Example
|
|
|
|
///
|
|
|
|
/// ```rust
|
|
|
|
/// let n = 0b0101000u16;
|
|
|
|
/// assert_eq!(n.population_count(), 2);
|
|
|
|
/// ```
|
2013-04-26 16:27:51 +10:00
|
|
|
fn population_count(&self) -> Self;
|
2013-11-10 21:39:16 -07:00
|
|
|
/// Returns the number of leading zeros in the number.
|
|
|
|
///
|
|
|
|
/// # Example
|
|
|
|
///
|
|
|
|
/// ```rust
|
|
|
|
/// let n = 0b0101000u16;
|
|
|
|
/// assert_eq!(n.leading_zeros(), 10);
|
|
|
|
/// ```
|
2013-04-26 16:27:51 +10:00
|
|
|
fn leading_zeros(&self) -> Self;
|
2013-11-10 21:39:16 -07:00
|
|
|
/// Returns the number of trailing zeros in the number.
|
|
|
|
///
|
|
|
|
/// # Example
|
|
|
|
///
|
|
|
|
/// ```rust
|
|
|
|
/// let n = 0b0101000u16;
|
|
|
|
/// assert_eq!(n.trailing_zeros(), 3);
|
|
|
|
/// ```
|
2013-04-26 16:27:51 +10:00
|
|
|
fn trailing_zeros(&self) -> Self;
|
|
|
|
}
|
|
|
|
|
2013-04-26 10:02:00 +10:00
|
|
|
pub trait Bounded {
|
|
|
|
// FIXME (#5527): These should be associated constants
|
|
|
|
fn min_value() -> Self;
|
|
|
|
fn max_value() -> Self;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// 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.
|
2013-09-07 17:16:56 +10:00
|
|
|
pub trait Primitive: Clone
|
|
|
|
+ DeepClone
|
|
|
|
+ Num
|
2013-04-26 10:02:00 +10:00
|
|
|
+ NumCast
|
2013-09-14 12:01:29 +10:00
|
|
|
+ Orderable
|
2013-04-27 09:07:40 +10:00
|
|
|
+ Bounded
|
2013-04-26 10:02:00 +10:00
|
|
|
+ Neg<Self>
|
|
|
|
+ Add<Self,Self>
|
|
|
|
+ Sub<Self,Self>
|
|
|
|
+ Mul<Self,Self>
|
2013-05-01 15:40:05 +10:00
|
|
|
+ Div<Self,Self>
|
2013-04-26 10:02:00 +10:00
|
|
|
+ Rem<Self,Self> {
|
|
|
|
// FIXME (#5527): These should be associated constants
|
2013-08-30 15:04:20 -07:00
|
|
|
// FIXME (#8888): Removing `unused_self` requires #8888 to be fixed.
|
2013-08-08 11:38:10 -07:00
|
|
|
fn bits(unused_self: Option<Self>) -> uint;
|
|
|
|
fn bytes(unused_self: Option<Self>) -> uint;
|
2013-09-27 20:41:49 -07:00
|
|
|
fn is_signed(unused_self: Option<Self>) -> bool;
|
2013-04-26 10:02:00 +10:00
|
|
|
}
|
|
|
|
|
|
|
|
/// A collection of traits relevant to primitive signed and unsigned integers
|
2013-04-26 19:56:11 +10:00
|
|
|
pub trait Int: Integer
|
|
|
|
+ Primitive
|
|
|
|
+ Bitwise
|
|
|
|
+ BitCount {}
|
2013-04-26 10:02:00 +10:00
|
|
|
|
2013-05-07 20:30:51 +10:00
|
|
|
/// Used for representing the classification of floating point numbers
|
|
|
|
#[deriving(Eq)]
|
|
|
|
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,
|
|
|
|
}
|
|
|
|
|
2013-04-27 01:02:30 +10:00
|
|
|
/// Primitive floating point numbers
|
2013-04-26 10:22:08 +10:00
|
|
|
pub trait Float: Real
|
|
|
|
+ Signed
|
2013-05-06 16:10:26 +10:00
|
|
|
+ Primitive
|
|
|
|
+ ApproxEq<Self> {
|
2013-04-26 10:22:08 +10:00
|
|
|
// FIXME (#5527): These should be associated constants
|
2013-09-19 15:37:34 +10:00
|
|
|
fn nan() -> Self;
|
2013-04-26 10:22:08 +10:00
|
|
|
fn infinity() -> Self;
|
|
|
|
fn neg_infinity() -> Self;
|
|
|
|
fn neg_zero() -> Self;
|
|
|
|
|
2013-09-19 15:37:34 +10:00
|
|
|
fn is_nan(&self) -> bool;
|
2013-04-26 10:22:08 +10:00
|
|
|
fn is_infinite(&self) -> bool;
|
|
|
|
fn is_finite(&self) -> bool;
|
2013-05-07 20:30:51 +10:00
|
|
|
fn is_normal(&self) -> bool;
|
|
|
|
fn classify(&self) -> FPCategory;
|
2013-04-27 01:02:30 +10:00
|
|
|
|
2013-08-30 15:04:20 -07:00
|
|
|
// FIXME (#8888): Removing `unused_self` requires #8888 to be fixed.
|
2013-08-08 11:38:10 -07:00
|
|
|
fn mantissa_digits(unused_self: Option<Self>) -> uint;
|
|
|
|
fn digits(unused_self: Option<Self>) -> uint;
|
2013-04-27 09:07:40 +10:00
|
|
|
fn epsilon() -> Self;
|
2013-08-08 11:38:10 -07:00
|
|
|
fn min_exp(unused_self: Option<Self>) -> int;
|
|
|
|
fn max_exp(unused_self: Option<Self>) -> int;
|
|
|
|
fn min_10_exp(unused_self: Option<Self>) -> int;
|
|
|
|
fn max_10_exp(unused_self: Option<Self>) -> int;
|
2013-04-27 09:07:40 +10:00
|
|
|
|
2013-05-14 11:24:55 +10:00
|
|
|
fn ldexp(x: Self, exp: int) -> Self;
|
|
|
|
fn frexp(&self) -> (Self, int);
|
|
|
|
|
2013-05-07 04:47:46 +10:00
|
|
|
fn exp_m1(&self) -> Self;
|
|
|
|
fn ln_1p(&self) -> Self;
|
2013-04-27 01:02:30 +10:00
|
|
|
fn mul_add(&self, a: Self, b: Self) -> Self;
|
|
|
|
fn next_after(&self, other: Self) -> Self;
|
2013-12-02 00:47:19 +01:00
|
|
|
|
|
|
|
fn integer_decode(&self) -> (u64, i16, i8);
|
2013-04-26 10:22:08 +10:00
|
|
|
}
|
|
|
|
|
2013-09-24 10:25:45 -07:00
|
|
|
/// Returns the exponential of the number, minus `1`, `exp(n) - 1`, in a way
|
|
|
|
/// that is accurate even if the number is close to zero.
|
2013-07-30 08:58:46 +10:00
|
|
|
#[inline(always)] pub fn exp_m1<T: Float>(value: T) -> T { value.exp_m1() }
|
2013-09-24 10:25:45 -07:00
|
|
|
/// Returns the natural logarithm of the number plus `1`, `ln(n + 1)`, more
|
|
|
|
/// accurately than if the operations were performed separately.
|
2013-07-30 08:58:46 +10:00
|
|
|
#[inline(always)] pub fn ln_1p<T: Float>(value: T) -> T { value.ln_1p() }
|
2013-09-24 10:25:45 -07:00
|
|
|
/// Fused multiply-add. Computes `(a * b) + c` with only one rounding error.
|
|
|
|
///
|
|
|
|
/// This produces a more accurate result with better performance (on some
|
|
|
|
/// architectures) than a separate multiplication operation followed by an add.
|
2013-07-30 08:58:46 +10:00
|
|
|
#[inline(always)] pub fn mul_add<T: Float>(a: T, b: T, c: T) -> T { a.mul_add(b, c) }
|
|
|
|
|
2013-09-15 09:50:17 -07:00
|
|
|
/// A generic trait for converting a value to a number.
|
|
|
|
pub trait ToPrimitive {
|
|
|
|
/// Converts the value of `self` to an `int`.
|
2013-09-17 19:28:35 -07:00
|
|
|
#[inline]
|
|
|
|
fn to_int(&self) -> Option<int> {
|
2013-09-27 17:09:18 -07:00
|
|
|
self.to_i64().and_then(|x| x.to_int())
|
2013-09-17 19:28:35 -07:00
|
|
|
}
|
2013-09-15 09:50:17 -07:00
|
|
|
|
|
|
|
/// Converts the value of `self` to an `i8`.
|
|
|
|
#[inline]
|
|
|
|
fn to_i8(&self) -> Option<i8> {
|
2013-09-27 17:09:18 -07:00
|
|
|
self.to_i64().and_then(|x| x.to_i8())
|
2013-09-15 09:50:17 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Converts the value of `self` to an `i16`.
|
|
|
|
#[inline]
|
|
|
|
fn to_i16(&self) -> Option<i16> {
|
2013-09-27 17:09:18 -07:00
|
|
|
self.to_i64().and_then(|x| x.to_i16())
|
2013-09-15 09:50:17 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Converts the value of `self` to an `i32`.
|
|
|
|
#[inline]
|
|
|
|
fn to_i32(&self) -> Option<i32> {
|
2013-09-27 17:09:18 -07:00
|
|
|
self.to_i64().and_then(|x| x.to_i32())
|
2013-09-15 09:50:17 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Converts the value of `self` to an `i64`.
|
2013-09-17 19:28:35 -07:00
|
|
|
fn to_i64(&self) -> Option<i64>;
|
|
|
|
|
|
|
|
/// Converts the value of `self` to an `uint`.
|
2013-09-15 09:50:17 -07:00
|
|
|
#[inline]
|
2013-09-17 19:28:35 -07:00
|
|
|
fn to_uint(&self) -> Option<uint> {
|
2013-09-27 17:09:18 -07:00
|
|
|
self.to_u64().and_then(|x| x.to_uint())
|
2013-09-15 09:50:17 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Converts the value of `self` to an `u8`.
|
|
|
|
#[inline]
|
|
|
|
fn to_u8(&self) -> Option<u8> {
|
2013-09-27 17:09:18 -07:00
|
|
|
self.to_u64().and_then(|x| x.to_u8())
|
2013-09-15 09:50:17 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Converts the value of `self` to an `u16`.
|
|
|
|
#[inline]
|
|
|
|
fn to_u16(&self) -> Option<u16> {
|
2013-09-27 17:09:18 -07:00
|
|
|
self.to_u64().and_then(|x| x.to_u16())
|
2013-09-15 09:50:17 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Converts the value of `self` to an `u32`.
|
|
|
|
#[inline]
|
|
|
|
fn to_u32(&self) -> Option<u32> {
|
2013-09-27 17:09:18 -07:00
|
|
|
self.to_u64().and_then(|x| x.to_u32())
|
2013-09-15 09:50:17 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Converts the value of `self` to an `u64`.
|
|
|
|
#[inline]
|
2013-10-07 19:56:30 -07:00
|
|
|
fn to_u64(&self) -> Option<u64>;
|
2013-09-15 09:50:17 -07:00
|
|
|
|
|
|
|
/// Converts the value of `self` to an `f32`.
|
|
|
|
#[inline]
|
|
|
|
fn to_f32(&self) -> Option<f32> {
|
2013-09-27 17:09:18 -07:00
|
|
|
self.to_f64().and_then(|x| x.to_f32())
|
2013-09-15 09:50:17 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Converts the value of `self` to an `f64`.
|
|
|
|
#[inline]
|
|
|
|
fn to_f64(&self) -> Option<f64> {
|
2013-09-27 17:09:18 -07:00
|
|
|
self.to_i64().and_then(|x| x.to_f64())
|
2013-09-15 09:50:17 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-09-25 20:22:46 -07:00
|
|
|
macro_rules! impl_to_primitive_int_to_int(
|
|
|
|
($SrcT:ty, $DstT:ty) => (
|
|
|
|
{
|
|
|
|
if Primitive::bits(None::<$SrcT>) <= Primitive::bits(None::<$DstT>) {
|
|
|
|
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) => (
|
|
|
|
{
|
|
|
|
if Primitive::bits(None::<$SrcT>) <= Primitive::bits(None::<$DstT>) {
|
|
|
|
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 09:50:17 -07:00
|
|
|
($T:ty) => (
|
|
|
|
impl ToPrimitive for $T {
|
2013-09-25 20:22:46 -07: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) => (
|
|
|
|
if Primitive::bits(None::<$SrcT>) <= Primitive::bits(None::<$DstT>) {
|
|
|
|
Some(*self as $DstT)
|
|
|
|
} else {
|
|
|
|
let n = *self as f64;
|
|
|
|
let max_value: $SrcT = Bounded::max_value();
|
2013-10-08 20:57:17 +02:00
|
|
|
if -max_value as f64 <= n && n <= max_value as f64 {
|
2013-09-25 20:22:46 -07: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 09:50:17 -07:00
|
|
|
}
|
|
|
|
)
|
|
|
|
)
|
|
|
|
|
2013-09-25 20:22:46 -07:00
|
|
|
impl_to_primitive_float!(f32)
|
|
|
|
impl_to_primitive_float!(f64)
|
2013-09-15 09:50:17 -07: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-17 19:28:35 -07:00
|
|
|
#[inline]
|
|
|
|
fn from_int(n: int) -> Option<Self> {
|
|
|
|
FromPrimitive::from_i64(n as i64)
|
|
|
|
}
|
2013-09-15 09:50:17 -07: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-17 19:28:35 -07:00
|
|
|
FromPrimitive::from_i64(n as i64)
|
2013-09-15 09:50:17 -07: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-17 19:28:35 -07:00
|
|
|
FromPrimitive::from_i64(n as i64)
|
2013-09-15 09:50:17 -07: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-17 19:28:35 -07:00
|
|
|
FromPrimitive::from_i64(n as i64)
|
2013-09-15 09:50:17 -07: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-17 19:28:35 -07:00
|
|
|
fn from_i64(n: i64) -> Option<Self>;
|
2013-09-15 09:50:17 -07: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-17 19:28:35 -07:00
|
|
|
#[inline]
|
|
|
|
fn from_uint(n: uint) -> Option<Self> {
|
|
|
|
FromPrimitive::from_u64(n as u64)
|
|
|
|
}
|
2013-09-15 09:50:17 -07: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-17 19:28:35 -07:00
|
|
|
FromPrimitive::from_u64(n as u64)
|
2013-09-15 09:50:17 -07: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-17 19:28:35 -07:00
|
|
|
FromPrimitive::from_u64(n as u64)
|
2013-09-15 09:50:17 -07: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-17 19:28:35 -07:00
|
|
|
FromPrimitive::from_u64(n as u64)
|
2013-09-15 09:50:17 -07: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-17 19:28:35 -07:00
|
|
|
fn from_u64(n: u64) -> Option<Self>;
|
2013-09-15 09:50:17 -07: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-17 19:28:35 -07:00
|
|
|
FromPrimitive::from_f64(n as f64)
|
2013-09-15 09:50:17 -07: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-17 19:28:35 -07:00
|
|
|
FromPrimitive::from_i64(n as i64)
|
2013-09-15 09:50:17 -07: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-25 20:22:46 -07:00
|
|
|
($T:ty, $to_ty:expr) => (
|
2013-09-15 09:50:17 -07:00
|
|
|
impl FromPrimitive for $T {
|
2013-09-25 20:22:46 -07: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 09:50:17 -07:00
|
|
|
}
|
|
|
|
)
|
|
|
|
)
|
|
|
|
|
2013-09-25 20:22:46 -07: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 09:50:17 -07:00
|
|
|
|
2013-09-24 10:25:45 -07:00
|
|
|
/// Cast from one machine scalar to another.
|
2013-04-26 09:55:49 +10:00
|
|
|
///
|
|
|
|
/// # Example
|
|
|
|
///
|
2013-09-23 17:20:36 -07:00
|
|
|
/// ```
|
2013-10-16 22:33:31 -07:00
|
|
|
/// let twenty: f32 = num::cast(0x14).unwrap();
|
2013-04-26 09:55:49 +10:00
|
|
|
/// assert_eq!(twenty, 20f32);
|
2013-09-23 17:20:36 -07:00
|
|
|
/// ```
|
2013-04-26 09:55:49 +10:00
|
|
|
///
|
2013-06-18 14:45:18 -07:00
|
|
|
#[inline]
|
2013-09-15 09:50:17 -07:00
|
|
|
pub fn cast<T: NumCast,U: NumCast>(n: T) -> Option<U> {
|
2013-02-11 12:33:05 +11:00
|
|
|
NumCast::from(n)
|
|
|
|
}
|
|
|
|
|
2013-04-26 09:55:49 +10:00
|
|
|
/// An interface for casting between machine scalars
|
2013-09-15 09:50:17 -07:00
|
|
|
pub trait NumCast: ToPrimitive {
|
|
|
|
fn from<T: ToPrimitive>(n: T) -> Option<Self>;
|
2013-02-11 12:33:05 +11:00
|
|
|
}
|
|
|
|
|
2013-04-13 23:44:35 +10:00
|
|
|
macro_rules! impl_num_cast(
|
|
|
|
($T:ty, $conv:ident) => (
|
2013-04-14 05:27:32 +10:00
|
|
|
impl NumCast for $T {
|
2013-06-18 14:45:18 -07:00
|
|
|
#[inline]
|
2013-09-15 09:50:17 -07:00
|
|
|
fn from<N: ToPrimitive>(n: N) -> Option<$T> {
|
2013-04-14 05:27:32 +10:00
|
|
|
// `$conv` could be generated using `concat_idents!`, but that
|
|
|
|
// macro seems to be broken at the moment
|
|
|
|
n.$conv()
|
2013-04-13 23:44:35 +10: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)
|
|
|
|
|
2013-01-24 21:09:58 +01:00
|
|
|
pub trait ToStrRadix {
|
2013-08-09 01:25:24 -07:00
|
|
|
fn to_str_radix(&self, radix: uint) -> ~str;
|
2013-01-24 21:09:58 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
pub trait FromStrRadix {
|
2013-08-09 01:25:24 -07:00
|
|
|
fn from_str_radix(str: &str, radix: uint) -> Option<Self>;
|
2013-01-21 00:40:02 +01:00
|
|
|
}
|
|
|
|
|
2013-09-24 10:25:45 -07:00
|
|
|
/// A utility function that just calls FromStrRadix::from_str_radix.
|
2013-09-15 07:27:32 +02:00
|
|
|
pub fn from_str_radix<T: FromStrRadix>(str: &str, radix: uint) -> Option<T> {
|
|
|
|
FromStrRadix::from_str_radix(str, radix)
|
|
|
|
}
|
|
|
|
|
2013-04-26 09:55:49 +10:00
|
|
|
/// Calculates a power to a given radix, optimized for uint `pow` and `radix`.
|
|
|
|
///
|
|
|
|
/// Returns `radix^pow` as `T`.
|
|
|
|
///
|
|
|
|
/// Note:
|
|
|
|
/// Also returns `1` for `0^0`, despite that technically being an
|
|
|
|
/// undefined number. The reason for this is twofold:
|
|
|
|
/// - If code written to use this function cares about that special case, it's
|
|
|
|
/// probably going to catch it before making the call.
|
|
|
|
/// - If code written to use this function doesn't care about it, it's
|
|
|
|
/// probably assuming that `x^0` always equals `1`.
|
|
|
|
///
|
2013-07-10 14:43:25 -07:00
|
|
|
pub fn pow_with_uint<T:NumCast+One+Zero+Div<T,T>+Mul<T,T>>(radix: uint, pow: uint) -> T {
|
2013-01-21 00:40:02 +01:00
|
|
|
let _0: T = Zero::zero();
|
|
|
|
let _1: T = One::one();
|
|
|
|
|
|
|
|
if pow == 0u { return _1; }
|
|
|
|
if radix == 0u { return _0; }
|
|
|
|
let mut my_pow = pow;
|
|
|
|
let mut total = _1;
|
2013-09-15 09:50:17 -07:00
|
|
|
let mut multiplier = cast(radix).unwrap();
|
2013-01-21 00:40:02 +01:00
|
|
|
while (my_pow > 0u) {
|
|
|
|
if my_pow % 2u == 1u {
|
2013-06-15 20:26:59 -04:00
|
|
|
total = total * multiplier;
|
2013-01-21 00:40:02 +01:00
|
|
|
}
|
2013-06-11 19:13:42 -07:00
|
|
|
my_pow = my_pow / 2u;
|
2013-06-15 20:26:59 -04:00
|
|
|
multiplier = multiplier * multiplier;
|
2013-01-21 00:40:02 +01:00
|
|
|
}
|
|
|
|
total
|
2013-01-27 03:13:33 +01:00
|
|
|
}
|
|
|
|
|
2013-07-18 17:12:46 -07:00
|
|
|
impl<T: Zero + 'static> Zero for @T {
|
2013-06-14 18:27:52 -07:00
|
|
|
fn zero() -> @T { @Zero::zero() }
|
|
|
|
fn is_zero(&self) -> bool { (**self).is_zero() }
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<T: Zero> Zero for ~T {
|
|
|
|
fn zero() -> ~T { ~Zero::zero() }
|
|
|
|
fn is_zero(&self) -> bool { (**self).is_zero() }
|
|
|
|
}
|
|
|
|
|
2013-08-05 19:28:20 -07:00
|
|
|
/// Saturating math operations
|
2013-08-14 13:02:20 -07:00
|
|
|
pub trait Saturating {
|
2013-08-05 19:28:20 -07:00
|
|
|
/// Saturating addition operator.
|
|
|
|
/// Returns a+b, saturating at the numeric bounds instead of overflowing.
|
2013-08-14 13:02:20 -07: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 17:15:35 +10:00
|
|
|
impl<T: CheckedAdd + CheckedSub + Zero + Ord + Bounded> Saturating for T {
|
2013-08-05 19:28:20 -07:00
|
|
|
#[inline]
|
2013-08-14 13:02:20 -07:00
|
|
|
fn saturating_add(self, v: T) -> T {
|
|
|
|
match self.checked_add(&v) {
|
|
|
|
Some(x) => x,
|
|
|
|
None => if v >= Zero::zero() {
|
2013-08-08 11:38:10 -07:00
|
|
|
Bounded::max_value()
|
2013-08-14 13:02:20 -07:00
|
|
|
} else {
|
2013-08-08 11:38:10 -07:00
|
|
|
Bounded::min_value()
|
2013-08-14 13:02:20 -07:00
|
|
|
}
|
2013-08-05 19:28:20 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
2013-08-14 13:02:20 -07:00
|
|
|
fn saturating_sub(self, v: T) -> T {
|
|
|
|
match self.checked_sub(&v) {
|
|
|
|
Some(x) => x,
|
|
|
|
None => if v >= Zero::zero() {
|
2013-08-08 11:38:10 -07:00
|
|
|
Bounded::min_value()
|
2013-08-14 13:02:20 -07:00
|
|
|
} else {
|
2013-08-08 11:38:10 -07:00
|
|
|
Bounded::max_value()
|
2013-08-14 13:02:20 -07:00
|
|
|
}
|
2013-08-05 19:28:20 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-08-07 15:40:09 -04:00
|
|
|
pub trait CheckedAdd: Add<Self, Self> {
|
|
|
|
fn checked_add(&self, v: &Self) -> Option<Self>;
|
|
|
|
}
|
|
|
|
|
|
|
|
pub trait CheckedSub: Sub<Self, Self> {
|
|
|
|
fn checked_sub(&self, v: &Self) -> Option<Self>;
|
|
|
|
}
|
|
|
|
|
|
|
|
pub trait CheckedMul: Mul<Self, Self> {
|
|
|
|
fn checked_mul(&self, v: &Self) -> Option<Self>;
|
|
|
|
}
|
|
|
|
|
2013-08-11 18:32:07 -04:00
|
|
|
pub trait CheckedDiv: Div<Self, Self> {
|
|
|
|
fn checked_div(&self, v: &Self) -> Option<Self>;
|
|
|
|
}
|
|
|
|
|
2013-04-24 20:08:08 +10:00
|
|
|
/// Helper function for testing numeric operations
|
2013-05-04 14:25:41 -07:00
|
|
|
#[cfg(test)]
|
2013-04-24 20:08:08 +10:00
|
|
|
pub fn test_num<T:Num + NumCast>(ten: T, two: T) {
|
2013-09-15 09:50:17 -07: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-22 01:58:53 +10: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 18:07:16 +02:00
|
|
|
assert_eq!(ten.div(&two), ten / two);
|
2013-04-22 01:58:53 +10:00
|
|
|
assert_eq!(ten.rem(&two), ten % two);
|
|
|
|
}
|
2013-04-14 02:53:00 +10:00
|
|
|
|
2013-08-05 19:28:20 -07:00
|
|
|
#[cfg(test)]
|
|
|
|
mod tests {
|
2013-08-07 15:40:09 -04:00
|
|
|
use prelude::*;
|
2013-08-05 19:28:20 -07:00
|
|
|
use super::*;
|
2013-09-25 20:22:46 -07:00
|
|
|
use i8;
|
|
|
|
use i16;
|
|
|
|
use i32;
|
|
|
|
use i64;
|
|
|
|
use int;
|
|
|
|
use u8;
|
|
|
|
use u16;
|
|
|
|
use u32;
|
|
|
|
use u64;
|
|
|
|
use uint;
|
2013-08-05 19:28:20 -07:00
|
|
|
|
|
|
|
macro_rules! test_cast_20(
|
|
|
|
($_20:expr) => ({
|
|
|
|
let _20 = $_20;
|
|
|
|
|
2013-09-15 09:50:17 -07: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-05 19:28:20 -07: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-25 20:22:46 -07:00
|
|
|
#[test]
|
|
|
|
fn test_cast_range_int_min() {
|
|
|
|
assert_eq!(int::min_value.to_int(), Some(int::min_value as int));
|
|
|
|
assert_eq!(int::min_value.to_i8(), None);
|
|
|
|
assert_eq!(int::min_value.to_i16(), None);
|
|
|
|
// int::min_value.to_i32() is word-size specific
|
|
|
|
assert_eq!(int::min_value.to_i64(), Some(int::min_value as i64));
|
|
|
|
assert_eq!(int::min_value.to_uint(), None);
|
|
|
|
assert_eq!(int::min_value.to_u8(), None);
|
|
|
|
assert_eq!(int::min_value.to_u16(), None);
|
|
|
|
assert_eq!(int::min_value.to_u32(), None);
|
|
|
|
assert_eq!(int::min_value.to_u64(), None);
|
|
|
|
|
|
|
|
#[cfg(target_word_size = "32")]
|
|
|
|
fn check_word_size() {
|
|
|
|
assert_eq!(int::min_value.to_i32(), Some(int::min_value as i32));
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(target_word_size = "64")]
|
|
|
|
fn check_word_size() {
|
|
|
|
assert_eq!(int::min_value.to_i32(), None);
|
|
|
|
}
|
|
|
|
|
|
|
|
check_word_size();
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_cast_range_i8_min() {
|
|
|
|
assert_eq!(i8::min_value.to_int(), Some(i8::min_value as int));
|
|
|
|
assert_eq!(i8::min_value.to_i8(), Some(i8::min_value as i8));
|
|
|
|
assert_eq!(i8::min_value.to_i16(), Some(i8::min_value as i16));
|
|
|
|
assert_eq!(i8::min_value.to_i32(), Some(i8::min_value as i32));
|
|
|
|
assert_eq!(i8::min_value.to_i64(), Some(i8::min_value as i64));
|
|
|
|
assert_eq!(i8::min_value.to_uint(), None);
|
|
|
|
assert_eq!(i8::min_value.to_u8(), None);
|
|
|
|
assert_eq!(i8::min_value.to_u16(), None);
|
|
|
|
assert_eq!(i8::min_value.to_u32(), None);
|
|
|
|
assert_eq!(i8::min_value.to_u64(), None);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_cast_range_i16_min() {
|
|
|
|
assert_eq!(i16::min_value.to_int(), Some(i16::min_value as int));
|
|
|
|
assert_eq!(i16::min_value.to_i8(), None);
|
|
|
|
assert_eq!(i16::min_value.to_i16(), Some(i16::min_value as i16));
|
|
|
|
assert_eq!(i16::min_value.to_i32(), Some(i16::min_value as i32));
|
|
|
|
assert_eq!(i16::min_value.to_i64(), Some(i16::min_value as i64));
|
|
|
|
assert_eq!(i16::min_value.to_uint(), None);
|
|
|
|
assert_eq!(i16::min_value.to_u8(), None);
|
|
|
|
assert_eq!(i16::min_value.to_u16(), None);
|
|
|
|
assert_eq!(i16::min_value.to_u32(), None);
|
|
|
|
assert_eq!(i16::min_value.to_u64(), None);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_cast_range_i32_min() {
|
|
|
|
assert_eq!(i32::min_value.to_int(), Some(i32::min_value as int));
|
|
|
|
assert_eq!(i32::min_value.to_i8(), None);
|
|
|
|
assert_eq!(i32::min_value.to_i16(), None);
|
|
|
|
assert_eq!(i32::min_value.to_i32(), Some(i32::min_value as i32));
|
|
|
|
assert_eq!(i32::min_value.to_i64(), Some(i32::min_value as i64));
|
|
|
|
assert_eq!(i32::min_value.to_uint(), None);
|
|
|
|
assert_eq!(i32::min_value.to_u8(), None);
|
|
|
|
assert_eq!(i32::min_value.to_u16(), None);
|
|
|
|
assert_eq!(i32::min_value.to_u32(), None);
|
|
|
|
assert_eq!(i32::min_value.to_u64(), None);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_cast_range_i64_min() {
|
|
|
|
// i64::min_value.to_int() is word-size specific
|
|
|
|
assert_eq!(i64::min_value.to_i8(), None);
|
|
|
|
assert_eq!(i64::min_value.to_i16(), None);
|
|
|
|
assert_eq!(i64::min_value.to_i32(), None);
|
|
|
|
assert_eq!(i64::min_value.to_i64(), Some(i64::min_value as i64));
|
|
|
|
assert_eq!(i64::min_value.to_uint(), None);
|
|
|
|
assert_eq!(i64::min_value.to_u8(), None);
|
|
|
|
assert_eq!(i64::min_value.to_u16(), None);
|
|
|
|
assert_eq!(i64::min_value.to_u32(), None);
|
|
|
|
assert_eq!(i64::min_value.to_u64(), None);
|
|
|
|
|
|
|
|
#[cfg(target_word_size = "32")]
|
|
|
|
fn check_word_size() {
|
|
|
|
assert_eq!(i64::min_value.to_int(), None);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(target_word_size = "64")]
|
|
|
|
fn check_word_size() {
|
|
|
|
assert_eq!(i64::min_value.to_int(), Some(i64::min_value as int));
|
|
|
|
}
|
|
|
|
|
|
|
|
check_word_size();
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_cast_range_int_max() {
|
|
|
|
assert_eq!(int::max_value.to_int(), Some(int::max_value as int));
|
|
|
|
assert_eq!(int::max_value.to_i8(), None);
|
|
|
|
assert_eq!(int::max_value.to_i16(), None);
|
|
|
|
// int::max_value.to_i32() is word-size specific
|
|
|
|
assert_eq!(int::max_value.to_i64(), Some(int::max_value as i64));
|
|
|
|
assert_eq!(int::max_value.to_u8(), None);
|
|
|
|
assert_eq!(int::max_value.to_u16(), None);
|
|
|
|
// int::max_value.to_u32() is word-size specific
|
|
|
|
assert_eq!(int::max_value.to_u64(), Some(int::max_value as u64));
|
|
|
|
|
|
|
|
#[cfg(target_word_size = "32")]
|
|
|
|
fn check_word_size() {
|
|
|
|
assert_eq!(int::max_value.to_i32(), Some(int::max_value as i32));
|
|
|
|
assert_eq!(int::max_value.to_u32(), Some(int::max_value as u32));
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(target_word_size = "64")]
|
|
|
|
fn check_word_size() {
|
|
|
|
assert_eq!(int::max_value.to_i32(), None);
|
|
|
|
assert_eq!(int::max_value.to_u32(), None);
|
|
|
|
}
|
|
|
|
|
|
|
|
check_word_size();
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_cast_range_i8_max() {
|
|
|
|
assert_eq!(i8::max_value.to_int(), Some(i8::max_value as int));
|
|
|
|
assert_eq!(i8::max_value.to_i8(), Some(i8::max_value as i8));
|
|
|
|
assert_eq!(i8::max_value.to_i16(), Some(i8::max_value as i16));
|
|
|
|
assert_eq!(i8::max_value.to_i32(), Some(i8::max_value as i32));
|
|
|
|
assert_eq!(i8::max_value.to_i64(), Some(i8::max_value as i64));
|
|
|
|
assert_eq!(i8::max_value.to_uint(), Some(i8::max_value as uint));
|
|
|
|
assert_eq!(i8::max_value.to_u8(), Some(i8::max_value as u8));
|
|
|
|
assert_eq!(i8::max_value.to_u16(), Some(i8::max_value as u16));
|
|
|
|
assert_eq!(i8::max_value.to_u32(), Some(i8::max_value as u32));
|
|
|
|
assert_eq!(i8::max_value.to_u64(), Some(i8::max_value as u64));
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_cast_range_i16_max() {
|
|
|
|
assert_eq!(i16::max_value.to_int(), Some(i16::max_value as int));
|
|
|
|
assert_eq!(i16::max_value.to_i8(), None);
|
|
|
|
assert_eq!(i16::max_value.to_i16(), Some(i16::max_value as i16));
|
|
|
|
assert_eq!(i16::max_value.to_i32(), Some(i16::max_value as i32));
|
|
|
|
assert_eq!(i16::max_value.to_i64(), Some(i16::max_value as i64));
|
|
|
|
assert_eq!(i16::max_value.to_uint(), Some(i16::max_value as uint));
|
|
|
|
assert_eq!(i16::max_value.to_u8(), None);
|
|
|
|
assert_eq!(i16::max_value.to_u16(), Some(i16::max_value as u16));
|
|
|
|
assert_eq!(i16::max_value.to_u32(), Some(i16::max_value as u32));
|
|
|
|
assert_eq!(i16::max_value.to_u64(), Some(i16::max_value as u64));
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_cast_range_i32_max() {
|
|
|
|
assert_eq!(i32::max_value.to_int(), Some(i32::max_value as int));
|
|
|
|
assert_eq!(i32::max_value.to_i8(), None);
|
|
|
|
assert_eq!(i32::max_value.to_i16(), None);
|
|
|
|
assert_eq!(i32::max_value.to_i32(), Some(i32::max_value as i32));
|
|
|
|
assert_eq!(i32::max_value.to_i64(), Some(i32::max_value as i64));
|
|
|
|
assert_eq!(i32::max_value.to_uint(), Some(i32::max_value as uint));
|
|
|
|
assert_eq!(i32::max_value.to_u8(), None);
|
|
|
|
assert_eq!(i32::max_value.to_u16(), None);
|
|
|
|
assert_eq!(i32::max_value.to_u32(), Some(i32::max_value as u32));
|
|
|
|
assert_eq!(i32::max_value.to_u64(), Some(i32::max_value as u64));
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_cast_range_i64_max() {
|
|
|
|
// i64::max_value.to_int() is word-size specific
|
|
|
|
assert_eq!(i64::max_value.to_i8(), None);
|
|
|
|
assert_eq!(i64::max_value.to_i16(), None);
|
|
|
|
assert_eq!(i64::max_value.to_i32(), None);
|
|
|
|
assert_eq!(i64::max_value.to_i64(), Some(i64::max_value as i64));
|
|
|
|
// i64::max_value.to_uint() is word-size specific
|
|
|
|
assert_eq!(i64::max_value.to_u8(), None);
|
|
|
|
assert_eq!(i64::max_value.to_u16(), None);
|
|
|
|
assert_eq!(i64::max_value.to_u32(), None);
|
|
|
|
assert_eq!(i64::max_value.to_u64(), Some(i64::max_value as u64));
|
|
|
|
|
|
|
|
#[cfg(target_word_size = "32")]
|
|
|
|
fn check_word_size() {
|
|
|
|
assert_eq!(i64::max_value.to_int(), None);
|
|
|
|
assert_eq!(i64::max_value.to_uint(), None);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(target_word_size = "64")]
|
|
|
|
fn check_word_size() {
|
|
|
|
assert_eq!(i64::max_value.to_int(), Some(i64::max_value as int));
|
|
|
|
assert_eq!(i64::max_value.to_uint(), Some(i64::max_value as uint));
|
|
|
|
}
|
|
|
|
|
|
|
|
check_word_size();
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_cast_range_uint_min() {
|
|
|
|
assert_eq!(uint::min_value.to_int(), Some(uint::min_value as int));
|
|
|
|
assert_eq!(uint::min_value.to_i8(), Some(uint::min_value as i8));
|
|
|
|
assert_eq!(uint::min_value.to_i16(), Some(uint::min_value as i16));
|
|
|
|
assert_eq!(uint::min_value.to_i32(), Some(uint::min_value as i32));
|
|
|
|
assert_eq!(uint::min_value.to_i64(), Some(uint::min_value as i64));
|
|
|
|
assert_eq!(uint::min_value.to_uint(), Some(uint::min_value as uint));
|
|
|
|
assert_eq!(uint::min_value.to_u8(), Some(uint::min_value as u8));
|
|
|
|
assert_eq!(uint::min_value.to_u16(), Some(uint::min_value as u16));
|
|
|
|
assert_eq!(uint::min_value.to_u32(), Some(uint::min_value as u32));
|
|
|
|
assert_eq!(uint::min_value.to_u64(), Some(uint::min_value as u64));
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_cast_range_u8_min() {
|
|
|
|
assert_eq!(u8::min_value.to_int(), Some(u8::min_value as int));
|
|
|
|
assert_eq!(u8::min_value.to_i8(), Some(u8::min_value as i8));
|
|
|
|
assert_eq!(u8::min_value.to_i16(), Some(u8::min_value as i16));
|
|
|
|
assert_eq!(u8::min_value.to_i32(), Some(u8::min_value as i32));
|
|
|
|
assert_eq!(u8::min_value.to_i64(), Some(u8::min_value as i64));
|
|
|
|
assert_eq!(u8::min_value.to_uint(), Some(u8::min_value as uint));
|
|
|
|
assert_eq!(u8::min_value.to_u8(), Some(u8::min_value as u8));
|
|
|
|
assert_eq!(u8::min_value.to_u16(), Some(u8::min_value as u16));
|
|
|
|
assert_eq!(u8::min_value.to_u32(), Some(u8::min_value as u32));
|
|
|
|
assert_eq!(u8::min_value.to_u64(), Some(u8::min_value as u64));
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_cast_range_u16_min() {
|
|
|
|
assert_eq!(u16::min_value.to_int(), Some(u16::min_value as int));
|
|
|
|
assert_eq!(u16::min_value.to_i8(), Some(u16::min_value as i8));
|
|
|
|
assert_eq!(u16::min_value.to_i16(), Some(u16::min_value as i16));
|
|
|
|
assert_eq!(u16::min_value.to_i32(), Some(u16::min_value as i32));
|
|
|
|
assert_eq!(u16::min_value.to_i64(), Some(u16::min_value as i64));
|
|
|
|
assert_eq!(u16::min_value.to_uint(), Some(u16::min_value as uint));
|
|
|
|
assert_eq!(u16::min_value.to_u8(), Some(u16::min_value as u8));
|
|
|
|
assert_eq!(u16::min_value.to_u16(), Some(u16::min_value as u16));
|
|
|
|
assert_eq!(u16::min_value.to_u32(), Some(u16::min_value as u32));
|
|
|
|
assert_eq!(u16::min_value.to_u64(), Some(u16::min_value as u64));
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_cast_range_u32_min() {
|
|
|
|
assert_eq!(u32::min_value.to_int(), Some(u32::min_value as int));
|
|
|
|
assert_eq!(u32::min_value.to_i8(), Some(u32::min_value as i8));
|
|
|
|
assert_eq!(u32::min_value.to_i16(), Some(u32::min_value as i16));
|
|
|
|
assert_eq!(u32::min_value.to_i32(), Some(u32::min_value as i32));
|
|
|
|
assert_eq!(u32::min_value.to_i64(), Some(u32::min_value as i64));
|
|
|
|
assert_eq!(u32::min_value.to_uint(), Some(u32::min_value as uint));
|
|
|
|
assert_eq!(u32::min_value.to_u8(), Some(u32::min_value as u8));
|
|
|
|
assert_eq!(u32::min_value.to_u16(), Some(u32::min_value as u16));
|
|
|
|
assert_eq!(u32::min_value.to_u32(), Some(u32::min_value as u32));
|
|
|
|
assert_eq!(u32::min_value.to_u64(), Some(u32::min_value as u64));
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_cast_range_u64_min() {
|
|
|
|
assert_eq!(u64::min_value.to_int(), Some(u64::min_value as int));
|
|
|
|
assert_eq!(u64::min_value.to_i8(), Some(u64::min_value as i8));
|
|
|
|
assert_eq!(u64::min_value.to_i16(), Some(u64::min_value as i16));
|
|
|
|
assert_eq!(u64::min_value.to_i32(), Some(u64::min_value as i32));
|
|
|
|
assert_eq!(u64::min_value.to_i64(), Some(u64::min_value as i64));
|
|
|
|
assert_eq!(u64::min_value.to_uint(), Some(u64::min_value as uint));
|
|
|
|
assert_eq!(u64::min_value.to_u8(), Some(u64::min_value as u8));
|
|
|
|
assert_eq!(u64::min_value.to_u16(), Some(u64::min_value as u16));
|
|
|
|
assert_eq!(u64::min_value.to_u32(), Some(u64::min_value as u32));
|
|
|
|
assert_eq!(u64::min_value.to_u64(), Some(u64::min_value as u64));
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_cast_range_uint_max() {
|
|
|
|
assert_eq!(uint::max_value.to_int(), None);
|
|
|
|
assert_eq!(uint::max_value.to_i8(), None);
|
|
|
|
assert_eq!(uint::max_value.to_i16(), None);
|
|
|
|
assert_eq!(uint::max_value.to_i32(), None);
|
|
|
|
// uint::max_value.to_i64() is word-size specific
|
|
|
|
assert_eq!(uint::max_value.to_u8(), None);
|
|
|
|
assert_eq!(uint::max_value.to_u16(), None);
|
|
|
|
// uint::max_value.to_u32() is word-size specific
|
|
|
|
assert_eq!(uint::max_value.to_u64(), Some(uint::max_value as u64));
|
|
|
|
|
|
|
|
#[cfg(target_word_size = "32")]
|
|
|
|
fn check_word_size() {
|
|
|
|
assert_eq!(uint::max_value.to_u32(), Some(uint::max_value as u32));
|
|
|
|
assert_eq!(uint::max_value.to_i64(), Some(uint::max_value as i64));
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(target_word_size = "64")]
|
|
|
|
fn check_word_size() {
|
|
|
|
assert_eq!(uint::max_value.to_u32(), None);
|
|
|
|
assert_eq!(uint::max_value.to_i64(), None);
|
|
|
|
}
|
|
|
|
|
|
|
|
check_word_size();
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_cast_range_u8_max() {
|
|
|
|
assert_eq!(u8::max_value.to_int(), Some(u8::max_value as int));
|
|
|
|
assert_eq!(u8::max_value.to_i8(), None);
|
|
|
|
assert_eq!(u8::max_value.to_i16(), Some(u8::max_value as i16));
|
|
|
|
assert_eq!(u8::max_value.to_i32(), Some(u8::max_value as i32));
|
|
|
|
assert_eq!(u8::max_value.to_i64(), Some(u8::max_value as i64));
|
|
|
|
assert_eq!(u8::max_value.to_uint(), Some(u8::max_value as uint));
|
|
|
|
assert_eq!(u8::max_value.to_u8(), Some(u8::max_value as u8));
|
|
|
|
assert_eq!(u8::max_value.to_u16(), Some(u8::max_value as u16));
|
|
|
|
assert_eq!(u8::max_value.to_u32(), Some(u8::max_value as u32));
|
|
|
|
assert_eq!(u8::max_value.to_u64(), Some(u8::max_value as u64));
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_cast_range_u16_max() {
|
|
|
|
assert_eq!(u16::max_value.to_int(), Some(u16::max_value as int));
|
|
|
|
assert_eq!(u16::max_value.to_i8(), None);
|
|
|
|
assert_eq!(u16::max_value.to_i16(), None);
|
|
|
|
assert_eq!(u16::max_value.to_i32(), Some(u16::max_value as i32));
|
|
|
|
assert_eq!(u16::max_value.to_i64(), Some(u16::max_value as i64));
|
|
|
|
assert_eq!(u16::max_value.to_uint(), Some(u16::max_value as uint));
|
|
|
|
assert_eq!(u16::max_value.to_u8(), None);
|
|
|
|
assert_eq!(u16::max_value.to_u16(), Some(u16::max_value as u16));
|
|
|
|
assert_eq!(u16::max_value.to_u32(), Some(u16::max_value as u32));
|
|
|
|
assert_eq!(u16::max_value.to_u64(), Some(u16::max_value as u64));
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_cast_range_u32_max() {
|
|
|
|
// u32::max_value.to_int() is word-size specific
|
|
|
|
assert_eq!(u32::max_value.to_i8(), None);
|
|
|
|
assert_eq!(u32::max_value.to_i16(), None);
|
|
|
|
assert_eq!(u32::max_value.to_i32(), None);
|
|
|
|
assert_eq!(u32::max_value.to_i64(), Some(u32::max_value as i64));
|
|
|
|
assert_eq!(u32::max_value.to_uint(), Some(u32::max_value as uint));
|
|
|
|
assert_eq!(u32::max_value.to_u8(), None);
|
|
|
|
assert_eq!(u32::max_value.to_u16(), None);
|
|
|
|
assert_eq!(u32::max_value.to_u32(), Some(u32::max_value as u32));
|
|
|
|
assert_eq!(u32::max_value.to_u64(), Some(u32::max_value as u64));
|
|
|
|
|
|
|
|
#[cfg(target_word_size = "32")]
|
|
|
|
fn check_word_size() {
|
|
|
|
assert_eq!(u32::max_value.to_int(), None);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(target_word_size = "64")]
|
|
|
|
fn check_word_size() {
|
|
|
|
assert_eq!(u32::max_value.to_int(), Some(u32::max_value as int));
|
|
|
|
}
|
|
|
|
|
|
|
|
check_word_size();
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_cast_range_u64_max() {
|
|
|
|
assert_eq!(u64::max_value.to_int(), None);
|
|
|
|
assert_eq!(u64::max_value.to_i8(), None);
|
|
|
|
assert_eq!(u64::max_value.to_i16(), None);
|
|
|
|
assert_eq!(u64::max_value.to_i32(), None);
|
|
|
|
assert_eq!(u64::max_value.to_i64(), None);
|
|
|
|
// u64::max_value.to_uint() is word-size specific
|
|
|
|
assert_eq!(u64::max_value.to_u8(), None);
|
|
|
|
assert_eq!(u64::max_value.to_u16(), None);
|
|
|
|
assert_eq!(u64::max_value.to_u32(), None);
|
|
|
|
assert_eq!(u64::max_value.to_u64(), Some(u64::max_value as u64));
|
|
|
|
|
|
|
|
#[cfg(target_word_size = "32")]
|
|
|
|
fn check_word_size() {
|
|
|
|
assert_eq!(u64::max_value.to_uint(), None);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(target_word_size = "64")]
|
|
|
|
fn check_word_size() {
|
|
|
|
assert_eq!(u64::max_value.to_uint(), Some(u64::max_value as uint));
|
|
|
|
}
|
|
|
|
|
|
|
|
check_word_size();
|
|
|
|
}
|
|
|
|
|
2013-08-05 19:28:20 -07:00
|
|
|
#[test]
|
|
|
|
fn test_saturating_add_uint() {
|
|
|
|
use uint::max_value;
|
|
|
|
assert_eq!(3u.saturating_add(5u), 8u);
|
|
|
|
assert_eq!(3u.saturating_add(max_value-1), max_value);
|
|
|
|
assert_eq!(max_value.saturating_add(max_value), max_value);
|
|
|
|
assert_eq!((max_value-2).saturating_add(1), max_value-1);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_saturating_sub_uint() {
|
|
|
|
use uint::max_value;
|
|
|
|
assert_eq!(5u.saturating_sub(3u), 2u);
|
|
|
|
assert_eq!(3u.saturating_sub(5u), 0u);
|
|
|
|
assert_eq!(0u.saturating_sub(1u), 0u);
|
|
|
|
assert_eq!((max_value-1).saturating_sub(max_value), 0);
|
|
|
|
}
|
2013-04-13 23:44:35 +10:00
|
|
|
|
2013-08-05 19:28:20 -07:00
|
|
|
#[test]
|
|
|
|
fn test_saturating_add_int() {
|
|
|
|
use int::{min_value,max_value};
|
|
|
|
assert_eq!(3i.saturating_add(5i), 8i);
|
|
|
|
assert_eq!(3i.saturating_add(max_value-1), max_value);
|
|
|
|
assert_eq!(max_value.saturating_add(max_value), max_value);
|
|
|
|
assert_eq!((max_value-2).saturating_add(1), max_value-1);
|
|
|
|
assert_eq!(3i.saturating_add(-5i), -2i);
|
|
|
|
assert_eq!(min_value.saturating_add(-1i), min_value);
|
|
|
|
assert_eq!((-2i).saturating_add(-max_value), min_value);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_saturating_sub_int() {
|
|
|
|
use int::{min_value,max_value};
|
|
|
|
assert_eq!(3i.saturating_sub(5i), -2i);
|
|
|
|
assert_eq!(min_value.saturating_sub(1i), min_value);
|
|
|
|
assert_eq!((-2i).saturating_sub(max_value), min_value);
|
|
|
|
assert_eq!(3i.saturating_sub(-5i), 8i);
|
|
|
|
assert_eq!(3i.saturating_sub(-(max_value-1)), max_value);
|
|
|
|
assert_eq!(max_value.saturating_sub(-max_value), max_value);
|
|
|
|
assert_eq!((max_value-2).saturating_sub(-1), max_value-1);
|
|
|
|
}
|
2013-08-07 15:40:09 -04:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_checked_add() {
|
|
|
|
let five_less = uint::max_value - 5;
|
|
|
|
assert_eq!(five_less.checked_add(&0), Some(uint::max_value - 5));
|
|
|
|
assert_eq!(five_less.checked_add(&1), Some(uint::max_value - 4));
|
|
|
|
assert_eq!(five_less.checked_add(&2), Some(uint::max_value - 3));
|
|
|
|
assert_eq!(five_less.checked_add(&3), Some(uint::max_value - 2));
|
|
|
|
assert_eq!(five_less.checked_add(&4), Some(uint::max_value - 1));
|
|
|
|
assert_eq!(five_less.checked_add(&5), Some(uint::max_value));
|
|
|
|
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() {
|
|
|
|
let third = uint::max_value / 3;
|
|
|
|
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-07 19:56:30 -07:00
|
|
|
|
|
|
|
|
|
|
|
#[deriving(Eq)]
|
|
|
|
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 }));
|
|
|
|
}
|
2013-08-05 19:28:20 -07:00
|
|
|
}
|