rust/src/libstd/num/mod.rs

1837 lines
60 KiB
Rust
Raw Normal View History

// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
//! Numeric traits and functions for generic mathematics
//!
//! These are implemented for the primitive numeric types in `std::{u8, u16,
2015-02-20 06:18:12 +00:00
//! u32, u64, usize, i8, i16, i32, i64, isize, f32, f64}`.
2015-01-24 05:48:20 +00:00
#![stable(feature = "rust1", since = "1.0.0")]
2014-10-27 22:37:07 +00:00
#![allow(missing_docs)]
std: Rename Show/String to Debug/Display This commit is an implementation of [RFC 565][rfc] which is a stabilization of the `std::fmt` module and the implementations of various formatting traits. Specifically, the following changes were performed: [rfc]: https://github.com/rust-lang/rfcs/blob/master/text/0565-show-string-guidelines.md * The `Show` trait is now deprecated, it was renamed to `Debug` * The `String` trait is now deprecated, it was renamed to `Display` * Many `Debug` and `Display` implementations were audited in accordance with the RFC and audited implementations now have the `#[stable]` attribute * Integers and floats no longer print a suffix * Smart pointers no longer print details that they are a smart pointer * Paths with `Debug` are now quoted and escape characters * The `unwrap` methods on `Result` now require `Display` instead of `Debug` * The `Error` trait no longer has a `detail` method and now requires that `Display` must be implemented. With the loss of `String`, this has moved into libcore. * `impl<E: Error> FromError<E> for Box<Error>` now exists * `derive(Show)` has been renamed to `derive(Debug)`. This is not currently warned about due to warnings being emitted on stage1+ While backwards compatibility is attempted to be maintained with a blanket implementation of `Display` for the old `String` trait (and the same for `Show`/`Debug`) this is still a breaking change due to primitives no longer implementing `String` as well as modifications such as `unwrap` and the `Error` trait. Most code is fairly straightforward to update with a rename or tweaks of method calls. [breaking-change] Closes #21436
2015-01-20 23:45:07 +00:00
#[cfg(test)] use fmt::Debug;
use ops::{Add, Sub, Mul, Div, Rem, Neg};
2015-01-06 22:33:42 +00:00
use marker::Copy;
use clone::Clone;
use cmp::{PartialOrd, PartialEq};
2015-03-11 04:13:40 +00:00
pub use core::num::{Int, SignedInt};
pub use core::num::{cast, FromPrimitive, NumCast, ToPrimitive};
pub use core::num::{from_int, from_i8, from_i16, from_i32, from_i64};
pub use core::num::{from_uint, from_u8, from_u16, from_u32, from_u64};
pub use core::num::{from_f32, from_f64};
2014-11-15 04:52:00 +00:00
pub use core::num::{FromStrRadix, from_str_radix};
pub use core::num::{FpCategory, ParseIntError, ParseFloatError};
Add `core::num::wrapping` and fix overflow errors. Many of the core rust libraries have places that rely on integer wrapping behaviour. These places have been altered to use the wrapping_* methods: * core::hash::sip - A number of macros * core::str - The `maximal_suffix` method in `TwoWaySearcher` * rustc::util::nodemap - Implementation of FnvHash * rustc_back::sha2 - A number of macros and other places * rand::isaac - Isaac64Rng, changed to use the Wrapping helper type Some places had "benign" underflow. This is when underflow or overflow occurs, but the unspecified value is not used due to other conditions. * collections::bit::Bitv - underflow when `self.nbits` is zero. * collections::hash::{map,table} - Underflow when searching an empty table. Did cause undefined behaviour in this case due to an out-of-bounds ptr::offset based on the underflowed index. However the resulting pointers would never be read from. * syntax::ext::deriving::encodable - Underflow when calculating the index of the last field in a variant with no fields. These cases were altered to avoid the underflow, often by moving the underflowing operation to a place where underflow could not happen. There was one case that relied on the fact that unsigned arithmetic and two's complement arithmetic are identical with wrapping semantics. This was changed to use the wrapping_* methods. Finally, the calculation of variant discriminants could overflow if the preceeding discriminant was `U64_MAX`. The logic in `rustc::middle::ty` for this was altered to avoid the overflow completely, while the remaining places were changed to use wrapping methods. This is because `rustc::middle::ty::enum_variants` now throws an error when the calculated discriminant value overflows a `u64`. This behaviour can be triggered by the following code: ``` enum Foo { A = U64_MAX, B } ``` This commit also implements the remaining integer operators for Wrapped<T>.
2015-01-09 03:10:57 +00:00
pub use core::num::wrapping;
use option::Option;
2012-06-08 00:25:54 +00:00
#[unstable(feature = "std_misc", reason = "may be removed or relocated")]
pub mod strconv;
/// Mathematical operations on primitive floating point numbers.
2015-01-24 05:48:20 +00:00
#[stable(feature = "rust1", since = "1.0.0")]
pub trait Float
: Copy + Clone
+ NumCast
+ PartialOrd
+ PartialEq
+ Neg<Output=Self>
+ Add<Output=Self>
+ Sub<Output=Self>
+ Mul<Output=Self>
+ Div<Output=Self>
+ Rem<Output=Self>
{
// inlined methods from `num::Float`
2015-02-14 01:41:49 +00:00
/// Returns the `NaN` value.
///
/// ```
/// use std::num::Float;
///
/// let nan: f32 = Float::nan();
///
/// assert!(nan.is_nan());
/// ```
#[unstable(feature = "std_misc",
reason = "unsure about its place in the world")]
fn nan() -> Self;
/// Returns the infinite value.
2015-02-14 01:41:49 +00:00
///
/// ```
/// use std::num::Float;
/// use std::f32;
///
/// let infinity: f32 = Float::infinity();
///
/// assert!(infinity.is_infinite());
/// assert!(!infinity.is_finite());
/// assert!(infinity > f32::MAX);
/// ```
#[unstable(feature = "std_misc",
reason = "unsure about its place in the world")]
fn infinity() -> Self;
/// Returns the negative infinite value.
2015-02-14 01:41:49 +00:00
///
/// ```
/// use std::num::Float;
/// use std::f32;
///
/// let neg_infinity: f32 = Float::neg_infinity();
///
/// assert!(neg_infinity.is_infinite());
/// assert!(!neg_infinity.is_finite());
/// assert!(neg_infinity < f32::MIN);
/// ```
#[unstable(feature = "std_misc",
reason = "unsure about its place in the world")]
fn neg_infinity() -> Self;
2015-02-14 01:41:49 +00:00
/// Returns `0.0`.
///
/// ```
/// use std::num::Float;
///
/// let inf: f32 = Float::infinity();
/// let zero: f32 = Float::zero();
/// let neg_zero: f32 = Float::neg_zero();
///
/// assert_eq!(zero, neg_zero);
/// assert_eq!(7.0f32/inf, zero);
/// assert_eq!(zero * 10.0, zero);
/// ```
#[unstable(feature = "std_misc",
reason = "unsure about its place in the world")]
fn zero() -> Self;
2015-02-14 01:41:49 +00:00
/// Returns `-0.0`.
///
/// ```
/// use std::num::Float;
///
/// let inf: f32 = Float::infinity();
/// let zero: f32 = Float::zero();
/// let neg_zero: f32 = Float::neg_zero();
///
/// assert_eq!(zero, neg_zero);
/// assert_eq!(7.0f32/inf, zero);
/// assert_eq!(zero * 10.0, zero);
/// ```
#[unstable(feature = "std_misc",
reason = "unsure about its place in the world")]
fn neg_zero() -> Self;
2015-02-14 01:41:49 +00:00
/// Returns `1.0`.
///
/// ```
/// use std::num::Float;
///
/// let one: f32 = Float::one();
///
/// assert_eq!(one, 1.0f32);
/// ```
#[unstable(feature = "std_misc",
reason = "unsure about its place in the world")]
fn one() -> Self;
// FIXME (#5527): These should be associated constants
2015-02-14 01:41:49 +00:00
/// Deprecated: use `std::f32::MANTISSA_DIGITS` or `std::f64::MANTISSA_DIGITS`
/// instead.
#[unstable(feature = "std_misc")]
#[deprecated(since = "1.0.0",
reason = "use `std::f32::MANTISSA_DIGITS` or \
`std::f64::MANTISSA_DIGITS` as appropriate")]
2015-02-20 06:18:12 +00:00
fn mantissa_digits(unused_self: Option<Self>) -> usize;
2015-02-14 01:41:49 +00:00
/// Deprecated: use `std::f32::DIGITS` or `std::f64::DIGITS` instead.
#[unstable(feature = "std_misc")]
#[deprecated(since = "1.0.0",
reason = "use `std::f32::DIGITS` or `std::f64::DIGITS` as appropriate")]
2015-02-20 06:18:12 +00:00
fn digits(unused_self: Option<Self>) -> usize;
2015-02-14 01:41:49 +00:00
/// Deprecated: use `std::f32::EPSILON` or `std::f64::EPSILON` instead.
#[unstable(feature = "std_misc")]
#[deprecated(since = "1.0.0",
reason = "use `std::f32::EPSILON` or `std::f64::EPSILON` as appropriate")]
fn epsilon() -> Self;
2015-02-14 01:41:49 +00:00
/// Deprecated: use `std::f32::MIN_EXP` or `std::f64::MIN_EXP` instead.
#[unstable(feature = "std_misc")]
#[deprecated(since = "1.0.0",
reason = "use `std::f32::MIN_EXP` or `std::f64::MIN_EXP` as appropriate")]
2015-02-20 06:18:12 +00:00
fn min_exp(unused_self: Option<Self>) -> isize;
2015-02-14 01:41:49 +00:00
/// Deprecated: use `std::f32::MAX_EXP` or `std::f64::MAX_EXP` instead.
#[unstable(feature = "std_misc")]
#[deprecated(since = "1.0.0",
reason = "use `std::f32::MAX_EXP` or `std::f64::MAX_EXP` as appropriate")]
2015-02-20 06:18:12 +00:00
fn max_exp(unused_self: Option<Self>) -> isize;
2015-02-14 01:41:49 +00:00
/// Deprecated: use `std::f32::MIN_10_EXP` or `std::f64::MIN_10_EXP` instead.
#[unstable(feature = "std_misc")]
#[deprecated(since = "1.0.0",
reason = "use `std::f32::MIN_10_EXP` or `std::f64::MIN_10_EXP` as appropriate")]
2015-02-20 06:18:12 +00:00
fn min_10_exp(unused_self: Option<Self>) -> isize;
2015-02-14 01:41:49 +00:00
/// Deprecated: use `std::f32::MAX_10_EXP` or `std::f64::MAX_10_EXP` instead.
#[unstable(feature = "std_misc")]
#[deprecated(since = "1.0.0",
reason = "use `std::f32::MAX_10_EXP` or `std::f64::MAX_10_EXP` as appropriate")]
2015-02-20 06:18:12 +00:00
fn max_10_exp(unused_self: Option<Self>) -> isize;
/// Returns the smallest finite value that this type can represent.
2015-02-14 01:41:49 +00:00
///
/// ```
/// use std::num::Float;
/// use std::f64;
///
/// let x: f64 = Float::min_value();
///
/// assert_eq!(x, f64::MIN);
/// ```
#[unstable(feature = "std_misc",
reason = "unsure about its place in the world")]
fn min_value() -> Self;
/// Returns the smallest normalized positive number that this type can represent.
#[unstable(feature = "std_misc",
reason = "unsure about its place in the world")]
fn min_pos_value(unused_self: Option<Self>) -> Self;
/// Returns the largest finite value that this type can represent.
2015-02-14 01:41:49 +00:00
///
/// ```
/// use std::num::Float;
/// use std::f64;
///
/// let x: f64 = Float::max_value();
/// assert_eq!(x, f64::MAX);
/// ```
#[unstable(feature = "std_misc",
reason = "unsure about its place in the world")]
fn max_value() -> Self;
2015-02-14 01:41:49 +00:00
/// Returns `true` if this value is `NaN` and false otherwise.
///
/// ```
/// use std::num::Float;
/// use std::f64;
///
/// let nan = f64::NAN;
/// let f = 7.0;
///
/// assert!(nan.is_nan());
/// assert!(!f.is_nan());
/// ```
#[unstable(feature = "std_misc", reason = "position is undecided")]
fn is_nan(self) -> bool;
2015-02-14 01:41:49 +00:00
/// Returns `true` if this value is positive infinity or negative infinity and
/// false otherwise.
2015-02-14 01:41:49 +00:00
///
/// ```
/// use std::num::Float;
/// use std::f32;
///
/// let f = 7.0f32;
/// let inf: f32 = Float::infinity();
/// let neg_inf: f32 = Float::neg_infinity();
/// let nan: f32 = f32::NAN;
///
/// assert!(!f.is_infinite());
/// assert!(!nan.is_infinite());
///
/// assert!(inf.is_infinite());
/// assert!(neg_inf.is_infinite());
/// ```
#[unstable(feature = "std_misc", reason = "position is undecided")]
fn is_infinite(self) -> bool;
2015-02-14 01:41:49 +00:00
/// Returns `true` if this number is neither infinite nor `NaN`.
///
/// ```
/// use std::num::Float;
/// use std::f32;
///
/// let f = 7.0f32;
/// let inf: f32 = Float::infinity();
/// let neg_inf: f32 = Float::neg_infinity();
/// let nan: f32 = f32::NAN;
///
/// assert!(f.is_finite());
///
/// assert!(!nan.is_finite());
/// assert!(!inf.is_finite());
/// assert!(!neg_inf.is_finite());
/// ```
#[unstable(feature = "std_misc", reason = "position is undecided")]
fn is_finite(self) -> bool;
2015-02-14 01:41:49 +00:00
/// Returns `true` if the number is neither zero, infinite,
/// [subnormal][subnormal], or `NaN`.
///
/// ```
/// use std::num::Float;
/// use std::f32;
///
/// let min = f32::MIN_POSITIVE; // 1.17549435e-38f32
/// let max = f32::MAX;
/// let lower_than_min = 1.0e-40_f32;
/// let zero = 0.0f32;
///
/// assert!(min.is_normal());
/// assert!(max.is_normal());
///
/// assert!(!zero.is_normal());
/// assert!(!f32::NAN.is_normal());
/// assert!(!f32::INFINITY.is_normal());
/// // Values between `0` and `min` are Subnormal.
/// assert!(!lower_than_min.is_normal());
/// ```
/// [subnormal]: http://en.wikipedia.org/wiki/Denormal_number
#[unstable(feature = "std_misc", reason = "position is undecided")]
fn is_normal(self) -> bool;
2015-02-14 01:41:49 +00:00
/// Returns the floating point category of the number. If only one property
/// is going to be tested, it is generally faster to use the specific
/// predicate instead.
///
/// ```
/// use std::num::{Float, FpCategory};
/// use std::f32;
///
/// let num = 12.4f32;
/// let inf = f32::INFINITY;
///
/// assert_eq!(num.classify(), FpCategory::Normal);
/// assert_eq!(inf.classify(), FpCategory::Infinite);
/// ```
2015-01-24 05:48:20 +00:00
#[stable(feature = "rust1", since = "1.0.0")]
fn classify(self) -> FpCategory;
2015-02-14 01:41:49 +00:00
/// Returns the mantissa, base 2 exponent, and sign as integers, respectively.
/// The original number can be recovered by `sign * mantissa * 2 ^ exponent`.
/// The floating point encoding is documented in the [Reference][floating-point].
///
/// ```
/// use std::num::Float;
///
/// let num = 2.0f32;
///
/// // (8388608, -22, 1)
2015-02-14 01:41:49 +00:00
/// let (mantissa, exponent, sign) = num.integer_decode();
/// let sign_f = sign as f32;
/// let mantissa_f = mantissa as f32;
/// let exponent_f = num.powf(exponent as f32);
///
/// // 1 * 8388608 * 2^(-22) == 2
/// let abs_difference = (sign_f * mantissa_f * exponent_f - num).abs();
///
/// assert!(abs_difference < 1e-10);
/// ```
/// [floating-point]: ../../../../../reference.html#machine-types
#[unstable(feature = "std_misc", reason = "signature is undecided")]
fn integer_decode(self) -> (u64, i16, i8);
2015-02-14 01:41:49 +00:00
/// Returns the largest integer less than or equal to a number.
///
/// ```
/// use std::num::Float;
///
/// let f = 3.99;
/// let g = 3.0;
///
/// assert_eq!(f.floor(), 3.0);
/// assert_eq!(g.floor(), 3.0);
/// ```
2015-01-24 05:48:20 +00:00
#[stable(feature = "rust1", since = "1.0.0")]
fn floor(self) -> Self;
2015-02-14 01:41:49 +00:00
/// Returns the smallest integer greater than or equal to a number.
///
/// ```
/// use std::num::Float;
///
/// let f = 3.01;
/// let g = 4.0;
///
/// assert_eq!(f.ceil(), 4.0);
/// assert_eq!(g.ceil(), 4.0);
/// ```
2015-01-24 05:48:20 +00:00
#[stable(feature = "rust1", since = "1.0.0")]
fn ceil(self) -> Self;
2015-02-14 01:41:49 +00:00
/// Returns the nearest integer to a number. Round half-way cases away from
/// `0.0`.
2015-02-14 01:41:49 +00:00
///
/// ```
/// use std::num::Float;
///
/// let f = 3.3;
/// let g = -3.3;
///
/// assert_eq!(f.round(), 3.0);
/// assert_eq!(g.round(), -3.0);
/// ```
2015-01-24 05:48:20 +00:00
#[stable(feature = "rust1", since = "1.0.0")]
fn round(self) -> Self;
/// Return the integer part of a number.
2015-02-14 01:41:49 +00:00
///
/// ```
/// use std::num::Float;
///
/// let f = 3.3;
/// let g = -3.7;
///
/// assert_eq!(f.trunc(), 3.0);
/// assert_eq!(g.trunc(), -3.0);
/// ```
2015-01-24 05:48:20 +00:00
#[stable(feature = "rust1", since = "1.0.0")]
fn trunc(self) -> Self;
2015-02-14 01:41:49 +00:00
/// Returns the fractional part of a number.
///
/// ```
/// use std::num::Float;
///
/// let x = 3.5;
/// let y = -3.5;
/// let abs_difference_x = (x.fract() - 0.5).abs();
/// let abs_difference_y = (y.fract() - (-0.5)).abs();
///
/// assert!(abs_difference_x < 1e-10);
/// assert!(abs_difference_y < 1e-10);
/// ```
2015-01-24 05:48:20 +00:00
#[stable(feature = "rust1", since = "1.0.0")]
fn fract(self) -> Self;
/// Computes the absolute value of `self`. Returns `Float::nan()` if the
/// number is `Float::nan()`.
2015-02-14 01:41:49 +00:00
///
/// ```
/// use std::num::Float;
/// use std::f64;
///
/// let x = 3.5;
/// let y = -3.5;
///
/// let abs_difference_x = (x.abs() - x).abs();
/// let abs_difference_y = (y.abs() - (-y)).abs();
///
/// assert!(abs_difference_x < 1e-10);
/// assert!(abs_difference_y < 1e-10);
///
/// assert!(f64::NAN.abs().is_nan());
/// ```
2015-01-24 05:48:20 +00:00
#[stable(feature = "rust1", since = "1.0.0")]
fn abs(self) -> Self;
/// Returns a number that represents the sign of `self`.
///
/// - `1.0` if the number is positive, `+0.0` or `Float::infinity()`
/// - `-1.0` if the number is negative, `-0.0` or `Float::neg_infinity()`
/// - `Float::nan()` if the number is `Float::nan()`
2015-02-14 01:41:49 +00:00
///
/// ```
/// use std::num::Float;
/// use std::f64;
///
/// let f = 3.5;
///
/// assert_eq!(f.signum(), 1.0);
/// assert_eq!(f64::NEG_INFINITY.signum(), -1.0);
///
/// assert!(f64::NAN.signum().is_nan());
/// ```
2015-01-24 05:48:20 +00:00
#[stable(feature = "rust1", since = "1.0.0")]
fn signum(self) -> Self;
/// Returns `true` if `self` is positive, including `+0.0` and
/// `Float::infinity()`.
2015-02-14 01:41:49 +00:00
///
/// ```
/// use std::num::Float;
/// use std::f64;
///
/// let nan: f64 = f64::NAN;
///
/// let f = 7.0;
/// let g = -7.0;
///
/// assert!(f.is_positive());
/// assert!(!g.is_positive());
/// // Requires both tests to determine if is `NaN`
/// assert!(!nan.is_positive() && !nan.is_negative());
/// ```
2015-01-24 05:48:20 +00:00
#[stable(feature = "rust1", since = "1.0.0")]
fn is_positive(self) -> bool;
/// Returns `true` if `self` is negative, including `-0.0` and
/// `Float::neg_infinity()`.
2015-02-14 01:41:49 +00:00
///
/// ```
/// use std::num::Float;
/// use std::f64;
///
/// let nan = f64::NAN;
///
/// let f = 7.0;
/// let g = -7.0;
///
/// assert!(!f.is_negative());
/// assert!(g.is_negative());
/// // Requires both tests to determine if is `NaN`.
/// assert!(!nan.is_positive() && !nan.is_negative());
/// ```
2015-01-24 05:48:20 +00:00
#[stable(feature = "rust1", since = "1.0.0")]
fn is_negative(self) -> bool;
/// 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.
2015-02-14 01:41:49 +00:00
///
/// ```
/// use std::num::Float;
///
/// let m = 10.0;
/// let x = 4.0;
/// let b = 60.0;
///
/// // 100.0
/// let abs_difference = (m.mul_add(x, b) - (m*x + b)).abs();
///
/// assert!(abs_difference < 1e-10);
/// ```
#[unstable(feature = "std_misc",
reason = "unsure about its place in the world")]
fn mul_add(self, a: Self, b: Self) -> Self;
/// Take the reciprocal (inverse) of a number, `1/x`.
2015-02-14 01:41:49 +00:00
///
/// ```
/// use std::num::Float;
///
/// let x = 2.0;
/// let abs_difference = (x.recip() - (1.0/x)).abs();
///
/// assert!(abs_difference < 1e-10);
/// ```
#[unstable(feature = "std_misc",
reason = "unsure about its place in the world")]
fn recip(self) -> Self;
/// Raise a number to an integer power.
///
/// Using this function is generally faster than using `powf`
2015-02-14 01:41:49 +00:00
///
/// ```
/// use std::num::Float;
///
/// let x = 2.0;
/// let abs_difference = (x.powi(2) - x*x).abs();
///
/// assert!(abs_difference < 1e-10);
/// ```
2015-01-24 05:48:20 +00:00
#[stable(feature = "rust1", since = "1.0.0")]
fn powi(self, n: i32) -> Self;
/// Raise a number to a floating point power.
2015-02-14 01:41:49 +00:00
///
/// ```
/// use std::num::Float;
///
/// let x = 2.0;
/// let abs_difference = (x.powf(2.0) - x*x).abs();
///
/// assert!(abs_difference < 1e-10);
/// ```
2015-01-24 05:48:20 +00:00
#[stable(feature = "rust1", since = "1.0.0")]
fn powf(self, n: Self) -> Self;
/// Take the square root of a number.
///
/// Returns NaN if `self` is a negative number.
2015-02-14 01:41:49 +00:00
///
/// ```
/// use std::num::Float;
///
/// let positive = 4.0;
/// let negative = -4.0;
///
/// let abs_difference = (positive.sqrt() - 2.0).abs();
///
/// assert!(abs_difference < 1e-10);
/// assert!(negative.sqrt().is_nan());
/// ```
2015-01-24 05:48:20 +00:00
#[stable(feature = "rust1", since = "1.0.0")]
fn sqrt(self) -> Self;
2015-02-14 01:41:49 +00:00
/// Take the reciprocal (inverse) square root of a number, `1/sqrt(x)`.
2015-02-14 01:41:49 +00:00
///
/// ```
/// use std::num::Float;
///
/// let f = 4.0;
///
/// let abs_difference = (f.rsqrt() - 0.5).abs();
///
/// assert!(abs_difference < 1e-10);
/// ```
#[unstable(feature = "std_misc",
reason = "unsure about its place in the world")]
fn rsqrt(self) -> Self;
/// Returns `e^(self)`, (the exponential function).
2015-02-14 01:41:49 +00:00
///
/// ```
/// use std::num::Float;
///
/// let one = 1.0;
/// // e^1
/// let e = one.exp();
///
/// // ln(e) - 1 == 0
/// let abs_difference = (e.ln() - 1.0).abs();
///
/// assert!(abs_difference < 1e-10);
/// ```
2015-01-24 05:48:20 +00:00
#[stable(feature = "rust1", since = "1.0.0")]
fn exp(self) -> Self;
2015-02-14 01:41:49 +00:00
/// Returns `2^(self)`.
///
/// ```
/// use std::num::Float;
///
/// let f = 2.0;
///
/// // 2^2 - 4 == 0
/// let abs_difference = (f.exp2() - 4.0).abs();
///
/// assert!(abs_difference < 1e-10);
/// ```
2015-01-24 05:48:20 +00:00
#[stable(feature = "rust1", since = "1.0.0")]
fn exp2(self) -> Self;
/// Returns the natural logarithm of the number.
2015-02-14 01:41:49 +00:00
///
/// ```
/// use std::num::Float;
///
/// let one = 1.0;
/// // e^1
/// let e = one.exp();
///
/// // ln(e) - 1 == 0
/// let abs_difference = (e.ln() - 1.0).abs();
///
/// assert!(abs_difference < 1e-10);
/// ```
2015-01-24 05:48:20 +00:00
#[stable(feature = "rust1", since = "1.0.0")]
fn ln(self) -> Self;
/// Returns the logarithm of the number with respect to an arbitrary base.
2015-02-14 01:41:49 +00:00
///
/// ```
/// use std::num::Float;
///
/// let ten = 10.0;
/// let two = 2.0;
///
/// // log10(10) - 1 == 0
/// let abs_difference_10 = (ten.log(10.0) - 1.0).abs();
///
/// // log2(2) - 1 == 0
/// let abs_difference_2 = (two.log(2.0) - 1.0).abs();
///
/// assert!(abs_difference_10 < 1e-10);
/// assert!(abs_difference_2 < 1e-10);
/// ```
2015-01-24 05:48:20 +00:00
#[stable(feature = "rust1", since = "1.0.0")]
fn log(self, base: Self) -> Self;
/// Returns the base 2 logarithm of the number.
2015-02-14 01:41:49 +00:00
///
/// ```
/// use std::num::Float;
///
/// let two = 2.0;
///
/// // log2(2) - 1 == 0
/// let abs_difference = (two.log2() - 1.0).abs();
///
/// assert!(abs_difference < 1e-10);
/// ```
2015-01-24 05:48:20 +00:00
#[stable(feature = "rust1", since = "1.0.0")]
fn log2(self) -> Self;
/// Returns the base 10 logarithm of the number.
2015-02-14 01:41:49 +00:00
///
/// ```
/// use std::num::Float;
///
/// let ten = 10.0;
///
/// // log10(10) - 1 == 0
/// let abs_difference = (ten.log10() - 1.0).abs();
///
/// assert!(abs_difference < 1e-10);
/// ```
2015-01-24 05:48:20 +00:00
#[stable(feature = "rust1", since = "1.0.0")]
fn log10(self) -> Self;
/// Convert radians to degrees.
2015-02-14 01:41:49 +00:00
///
/// ```
/// use std::num::Float;
/// use std::f64::consts;
///
/// let angle = consts::PI;
///
/// let abs_difference = (angle.to_degrees() - 180.0).abs();
///
/// assert!(abs_difference < 1e-10);
/// ```
#[unstable(feature = "std_misc", reason = "desirability is unclear")]
fn to_degrees(self) -> Self;
/// Convert degrees to radians.
2015-02-14 01:41:49 +00:00
///
/// ```
/// use std::num::Float;
/// use std::f64::consts;
///
/// let angle = 180.0;
///
/// let abs_difference = (angle.to_radians() - consts::PI).abs();
///
/// assert!(abs_difference < 1e-10);
/// ```
#[unstable(feature = "std_misc", reason = "desirability is unclear")]
fn to_radians(self) -> Self;
2015-02-14 01:41:49 +00:00
/// Constructs a floating point number of `x*2^exp`.
///
/// ```
/// use std::num::Float;
///
/// // 3*2^2 - 12 == 0
/// let abs_difference = (Float::ldexp(3.0, 2) - 12.0).abs();
///
/// assert!(abs_difference < 1e-10);
/// ```
#[unstable(feature = "std_misc",
reason = "pending integer conventions")]
fn ldexp(self, exp: isize) -> Self;
/// Breaks the number into a normalized fraction and a base-2 exponent,
/// satisfying:
///
2015-02-14 01:41:49 +00:00
/// * `self = x * 2^exp`
/// * `0.5 <= abs(x) < 1.0`
2015-02-14 01:41:49 +00:00
///
/// ```
/// use std::num::Float;
///
/// let x = 4.0;
///
/// // (1/2)*2^3 -> 1 * 8/2 -> 4.0
/// let f = x.frexp();
/// let abs_difference_0 = (f.0 - 0.5).abs();
/// let abs_difference_1 = (f.1 as f64 - 3.0).abs();
///
/// assert!(abs_difference_0 < 1e-10);
/// assert!(abs_difference_1 < 1e-10);
/// ```
#[unstable(feature = "std_misc",
reason = "pending integer conventions")]
2015-02-20 06:18:12 +00:00
fn frexp(self) -> (Self, isize);
/// Returns the next representable floating-point value in the direction of
/// `other`.
2015-02-14 01:41:49 +00:00
///
/// ```
/// use std::num::Float;
///
/// let x = 1.0f32;
///
/// let abs_diff = (x.next_after(2.0) - 1.00000011920928955078125_f32).abs();
///
/// assert!(abs_diff < 1e-10);
/// ```
#[unstable(feature = "std_misc",
reason = "unsure about its place in the world")]
fn next_after(self, other: Self) -> Self;
/// Returns the maximum of the two numbers.
2015-02-14 01:41:49 +00:00
///
/// ```
/// use std::num::Float;
///
/// let x = 1.0;
/// let y = 2.0;
///
/// assert_eq!(x.max(y), y);
/// ```
2015-01-24 05:48:20 +00:00
#[stable(feature = "rust1", since = "1.0.0")]
fn max(self, other: Self) -> Self;
/// Returns the minimum of the two numbers.
2015-02-14 01:41:49 +00:00
///
/// ```
/// use std::num::Float;
///
/// let x = 1.0;
/// let y = 2.0;
///
/// assert_eq!(x.min(y), x);
/// ```
2015-01-24 05:48:20 +00:00
#[stable(feature = "rust1", since = "1.0.0")]
fn min(self, other: Self) -> Self;
2015-02-14 01:41:49 +00:00
/// The positive difference of two numbers.
///
/// * If `self <= other`: `0:0`
/// * Else: `self - other`
///
/// ```
/// use std::num::Float;
///
/// let x = 3.0;
/// let y = -3.0;
///
/// let abs_difference_x = (x.abs_sub(1.0) - 2.0).abs();
/// let abs_difference_y = (y.abs_sub(1.0) - 0.0).abs();
///
/// assert!(abs_difference_x < 1e-10);
/// assert!(abs_difference_y < 1e-10);
/// ```
#[unstable(feature = "std_misc", reason = "may be renamed")]
fn abs_sub(self, other: Self) -> Self;
/// Take the cubic root of a number.
2015-02-14 01:41:49 +00:00
///
/// ```
/// use std::num::Float;
///
/// let x = 8.0;
///
/// // x^(1/3) - 2 == 0
/// let abs_difference = (x.cbrt() - 2.0).abs();
///
/// assert!(abs_difference < 1e-10);
/// ```
#[unstable(feature = "std_misc", reason = "may be renamed")]
fn cbrt(self) -> Self;
/// Calculate the length of the hypotenuse of a right-angle triangle given
/// legs of length `x` and `y`.
2015-02-14 01:41:49 +00:00
///
/// ```
/// use std::num::Float;
///
/// let x = 2.0;
/// let y = 3.0;
///
/// // sqrt(x^2 + y^2)
/// let abs_difference = (x.hypot(y) - (x.powi(2) + y.powi(2)).sqrt()).abs();
///
/// assert!(abs_difference < 1e-10);
/// ```
#[unstable(feature = "std_misc",
reason = "unsure about its place in the world")]
fn hypot(self, other: Self) -> Self;
/// Computes the sine of a number (in radians).
2015-02-14 01:41:49 +00:00
///
/// ```
/// use std::num::Float;
/// use std::f64;
///
/// let x = f64::consts::PI/2.0;
///
/// let abs_difference = (x.sin() - 1.0).abs();
///
/// assert!(abs_difference < 1e-10);
/// ```
2015-01-24 05:48:20 +00:00
#[stable(feature = "rust1", since = "1.0.0")]
fn sin(self) -> Self;
/// Computes the cosine of a number (in radians).
2015-02-14 01:41:49 +00:00
///
/// ```
/// use std::num::Float;
/// use std::f64;
///
/// let x = 2.0*f64::consts::PI;
///
/// let abs_difference = (x.cos() - 1.0).abs();
///
/// assert!(abs_difference < 1e-10);
/// ```
2015-01-24 05:48:20 +00:00
#[stable(feature = "rust1", since = "1.0.0")]
fn cos(self) -> Self;
/// Computes the tangent of a number (in radians).
2015-02-14 01:41:49 +00:00
///
/// ```
/// use std::num::Float;
/// use std::f64;
///
/// let x = f64::consts::PI/4.0;
/// let abs_difference = (x.tan() - 1.0).abs();
///
/// assert!(abs_difference < 1e-14);
/// ```
2015-01-24 05:48:20 +00:00
#[stable(feature = "rust1", since = "1.0.0")]
fn tan(self) -> Self;
/// 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].
2015-02-14 01:41:49 +00:00
///
/// ```
/// use std::num::Float;
/// use std::f64;
///
/// let f = f64::consts::PI / 2.0;
///
/// // asin(sin(pi/2))
/// let abs_difference = (f.sin().asin() - f64::consts::PI / 2.0).abs();
///
/// assert!(abs_difference < 1e-10);
/// ```
2015-01-24 05:48:20 +00:00
#[stable(feature = "rust1", since = "1.0.0")]
fn asin(self) -> Self;
/// 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].
2015-02-14 01:41:49 +00:00
///
/// ```
/// use std::num::Float;
/// use std::f64;
///
/// let f = f64::consts::PI / 4.0;
///
/// // acos(cos(pi/4))
/// let abs_difference = (f.cos().acos() - f64::consts::PI / 4.0).abs();
///
/// assert!(abs_difference < 1e-10);
/// ```
2015-01-24 05:48:20 +00:00
#[stable(feature = "rust1", since = "1.0.0")]
fn acos(self) -> Self;
/// Computes the arctangent of a number. Return value is in radians in the
/// range [-pi/2, pi/2];
2015-02-14 01:41:49 +00:00
///
/// ```
/// use std::num::Float;
///
/// let f = 1.0;
///
/// // atan(tan(1))
/// let abs_difference = (f.tan().atan() - 1.0).abs();
///
/// assert!(abs_difference < 1e-10);
/// ```
2015-01-24 05:48:20 +00:00
#[stable(feature = "rust1", since = "1.0.0")]
fn atan(self) -> Self;
2015-02-14 01:41:49 +00:00
/// Computes the four quadrant arctangent of `self` (`y`) and `other` (`x`).
///
/// * `x = 0`, `y = 0`: `0`
/// * `x >= 0`: `arctan(y/x)` -> `[-pi/2, pi/2]`
/// * `y >= 0`: `arctan(y/x) + pi` -> `(pi/2, pi]`
/// * `y < 0`: `arctan(y/x) - pi` -> `(-pi, -pi/2)`
///
/// ```
/// use std::num::Float;
/// use std::f64;
///
/// let pi = f64::consts::PI;
/// // All angles from horizontal right (+x)
/// // 45 deg counter-clockwise
/// let x1 = 3.0;
/// let y1 = -3.0;
///
/// // 135 deg clockwise
/// let x2 = -3.0;
/// let y2 = 3.0;
///
/// let abs_difference_1 = (y1.atan2(x1) - (-pi/4.0)).abs();
/// let abs_difference_2 = (y2.atan2(x2) - 3.0*pi/4.0).abs();
///
/// assert!(abs_difference_1 < 1e-10);
/// assert!(abs_difference_2 < 1e-10);
/// ```
2015-01-24 05:48:20 +00:00
#[stable(feature = "rust1", since = "1.0.0")]
fn atan2(self, other: Self) -> Self;
/// Simultaneously computes the sine and cosine of the number, `x`. Returns
/// `(sin(x), cos(x))`.
2015-02-14 01:41:49 +00:00
///
/// ```
/// use std::num::Float;
/// use std::f64;
///
/// let x = f64::consts::PI/4.0;
/// let f = x.sin_cos();
///
/// let abs_difference_0 = (f.0 - x.sin()).abs();
/// let abs_difference_1 = (f.1 - x.cos()).abs();
///
/// assert!(abs_difference_0 < 1e-10);
/// assert!(abs_difference_0 < 1e-10);
/// ```
2015-01-24 05:48:20 +00:00
#[stable(feature = "rust1", since = "1.0.0")]
fn sin_cos(self) -> (Self, Self);
2015-02-14 01:41:49 +00:00
/// Returns `e^(self) - 1` in a way that is accurate even if the
/// number is close to zero.
///
/// ```
/// use std::num::Float;
///
/// let x = 7.0;
///
/// // e^(ln(7)) - 1
/// let abs_difference = (x.ln().exp_m1() - 6.0).abs();
///
/// assert!(abs_difference < 1e-10);
/// ```
#[unstable(feature = "std_misc", reason = "may be renamed")]
fn exp_m1(self) -> Self;
2015-02-14 01:41:49 +00:00
/// Returns `ln(1+n)` (natural logarithm) more accurately than if
/// the operations were performed separately.
///
/// ```
/// use std::num::Float;
/// use std::f64;
///
/// let x = f64::consts::E - 1.0;
///
/// // ln(1 + (e - 1)) == ln(e) == 1
/// let abs_difference = (x.ln_1p() - 1.0).abs();
///
/// assert!(abs_difference < 1e-10);
/// ```
#[unstable(feature = "std_misc", reason = "may be renamed")]
fn ln_1p(self) -> Self;
/// Hyperbolic sine function.
2015-02-14 01:41:49 +00:00
///
/// ```
/// use std::num::Float;
/// use std::f64;
///
/// let e = f64::consts::E;
/// let x = 1.0;
///
/// let f = x.sinh();
/// // Solving sinh() at 1 gives `(e^2-1)/(2e)`
/// let g = (e*e - 1.0)/(2.0*e);
/// let abs_difference = (f - g).abs();
///
/// assert!(abs_difference < 1e-10);
/// ```
2015-01-24 05:48:20 +00:00
#[stable(feature = "rust1", since = "1.0.0")]
fn sinh(self) -> Self;
/// Hyperbolic cosine function.
2015-02-14 01:41:49 +00:00
///
/// ```
/// use std::num::Float;
/// use std::f64;
///
/// let e = f64::consts::E;
/// let x = 1.0;
/// let f = x.cosh();
/// // Solving cosh() at 1 gives this result
/// let g = (e*e + 1.0)/(2.0*e);
/// let abs_difference = (f - g).abs();
///
/// // Same result
/// assert!(abs_difference < 1.0e-10);
/// ```
2015-01-24 05:48:20 +00:00
#[stable(feature = "rust1", since = "1.0.0")]
fn cosh(self) -> Self;
/// Hyperbolic tangent function.
2015-02-14 01:41:49 +00:00
///
/// ```
/// use std::num::Float;
/// use std::f64;
///
/// let e = f64::consts::E;
/// let x = 1.0;
///
/// let f = x.tanh();
/// // Solving tanh() at 1 gives `(1 - e^(-2))/(1 + e^(-2))`
/// let g = (1.0 - e.powi(-2))/(1.0 + e.powi(-2));
/// let abs_difference = (f - g).abs();
///
/// assert!(abs_difference < 1.0e-10);
/// ```
2015-01-24 05:48:20 +00:00
#[stable(feature = "rust1", since = "1.0.0")]
fn tanh(self) -> Self;
/// Inverse hyperbolic sine function.
2015-02-14 01:41:49 +00:00
///
/// ```
/// use std::num::Float;
///
/// let x = 1.0;
/// let f = x.sinh().asinh();
///
/// let abs_difference = (f - x).abs();
///
/// assert!(abs_difference < 1.0e-10);
/// ```
2015-01-24 05:48:20 +00:00
#[stable(feature = "rust1", since = "1.0.0")]
fn asinh(self) -> Self;
/// Inverse hyperbolic cosine function.
2015-02-14 01:41:49 +00:00
///
/// ```
/// use std::num::Float;
///
/// let x = 1.0;
/// let f = x.cosh().acosh();
///
/// let abs_difference = (f - x).abs();
///
/// assert!(abs_difference < 1.0e-10);
/// ```
2015-01-24 05:48:20 +00:00
#[stable(feature = "rust1", since = "1.0.0")]
fn acosh(self) -> Self;
/// Inverse hyperbolic tangent function.
2015-02-14 01:41:49 +00:00
///
/// ```
/// use std::num::Float;
/// use std::f64;
///
/// let e = f64::consts::E;
/// let f = e.tanh().atanh();
///
/// let abs_difference = (f - e).abs();
///
/// assert!(abs_difference < 1.0e-10);
/// ```
2015-01-24 05:48:20 +00:00
#[stable(feature = "rust1", since = "1.0.0")]
fn atanh(self) -> Self;
}
/// Helper function for testing numeric operations
2013-05-04 21:25:41 +00:00
#[cfg(test)]
pub fn test_num<T>(ten: T, two: T) where
T: PartialEq + NumCast
2014-12-31 20:45:13 +00:00
+ Add<Output=T> + Sub<Output=T>
+ Mul<Output=T> + Div<Output=T>
std: Rename Show/String to Debug/Display This commit is an implementation of [RFC 565][rfc] which is a stabilization of the `std::fmt` module and the implementations of various formatting traits. Specifically, the following changes were performed: [rfc]: https://github.com/rust-lang/rfcs/blob/master/text/0565-show-string-guidelines.md * The `Show` trait is now deprecated, it was renamed to `Debug` * The `String` trait is now deprecated, it was renamed to `Display` * Many `Debug` and `Display` implementations were audited in accordance with the RFC and audited implementations now have the `#[stable]` attribute * Integers and floats no longer print a suffix * Smart pointers no longer print details that they are a smart pointer * Paths with `Debug` are now quoted and escape characters * The `unwrap` methods on `Result` now require `Display` instead of `Debug` * The `Error` trait no longer has a `detail` method and now requires that `Display` must be implemented. With the loss of `String`, this has moved into libcore. * `impl<E: Error> FromError<E> for Box<Error>` now exists * `derive(Show)` has been renamed to `derive(Debug)`. This is not currently warned about due to warnings being emitted on stage1+ While backwards compatibility is attempted to be maintained with a blanket implementation of `Display` for the old `String` trait (and the same for `Show`/`Debug`) this is still a breaking change due to primitives no longer implementing `String` as well as modifications such as `unwrap` and the `Error` trait. Most code is fairly straightforward to update with a rename or tweaks of method calls. [breaking-change] Closes #21436
2015-01-20 23:45:07 +00:00
+ Rem<Output=T> + Debug
2014-12-01 22:55:28 +00:00
+ Copy
{
2015-01-25 21:05:03 +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());
2014-12-01 22:55:28 +00:00
assert_eq!(ten.add(two), ten + two);
assert_eq!(ten.sub(two), ten - two);
assert_eq!(ten.mul(two), ten * two);
assert_eq!(ten.div(two), ten / two);
assert_eq!(ten.rem(two), ten % two);
}
#[cfg(test)]
mod tests {
use prelude::v1::*;
use super::*;
use i8;
use i16;
use i32;
use i64;
2015-02-20 06:18:12 +00:00
use isize;
use u8;
use u16;
use u32;
use u64;
2015-02-20 06:18:12 +00:00
use usize;
macro_rules! test_cast_20 {
($_20:expr) => ({
let _20 = $_20;
assert_eq!(20usize, _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!(20, _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(20usize).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());
2015-01-25 21:05:03 +00:00
assert_eq!(_20, NumCast::from(20).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(20usize).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());
2015-01-25 21:05:03 +00:00
assert_eq!(_20, cast(20).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());
})
}
#[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!(20usize) }
#[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!(20) }
#[test] fn test_f32_cast() { test_cast_20!(20f32) }
#[test] fn test_f64_cast() { test_cast_20!(20f64) }
#[test]
fn test_cast_range_int_min() {
2015-02-20 06:18:12 +00:00
assert_eq!(isize::MIN.to_int(), Some(isize::MIN as isize));
assert_eq!(isize::MIN.to_i8(), None);
assert_eq!(isize::MIN.to_i16(), None);
// isize::MIN.to_i32() is word-size specific
assert_eq!(isize::MIN.to_i64(), Some(isize::MIN as i64));
assert_eq!(isize::MIN.to_uint(), None);
assert_eq!(isize::MIN.to_u8(), None);
assert_eq!(isize::MIN.to_u16(), None);
assert_eq!(isize::MIN.to_u32(), None);
assert_eq!(isize::MIN.to_u64(), None);
2015-01-16 15:01:02 +00:00
#[cfg(target_pointer_width = "32")]
fn check_word_size() {
2015-02-20 06:18:12 +00:00
assert_eq!(isize::MIN.to_i32(), Some(isize::MIN as i32));
}
2015-01-16 15:01:02 +00:00
#[cfg(target_pointer_width = "64")]
fn check_word_size() {
2015-02-20 06:18:12 +00:00
assert_eq!(isize::MIN.to_i32(), None);
}
check_word_size();
}
#[test]
fn test_cast_range_i8_min() {
2015-02-20 06:18:12 +00:00
assert_eq!(i8::MIN.to_int(), Some(i8::MIN as isize));
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);
}
#[test]
fn test_cast_range_i16_min() {
2015-02-20 06:18:12 +00:00
assert_eq!(i16::MIN.to_int(), Some(i16::MIN as isize));
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);
}
#[test]
fn test_cast_range_i32_min() {
2015-02-20 06:18:12 +00:00
assert_eq!(i32::MIN.to_int(), Some(i32::MIN as isize));
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);
}
#[test]
fn test_cast_range_i64_min() {
// 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);
2015-01-16 15:01:02 +00:00
#[cfg(target_pointer_width = "32")]
fn check_word_size() {
assert_eq!(i64::MIN.to_int(), None);
}
2015-01-16 15:01:02 +00:00
#[cfg(target_pointer_width = "64")]
fn check_word_size() {
2015-02-20 06:18:12 +00:00
assert_eq!(i64::MIN.to_int(), Some(i64::MIN as isize));
}
check_word_size();
}
#[test]
fn test_cast_range_int_max() {
2015-02-20 06:18:12 +00:00
assert_eq!(isize::MAX.to_int(), Some(isize::MAX as isize));
assert_eq!(isize::MAX.to_i8(), None);
assert_eq!(isize::MAX.to_i16(), None);
// isize::MAX.to_i32() is word-size specific
assert_eq!(isize::MAX.to_i64(), Some(isize::MAX as i64));
assert_eq!(isize::MAX.to_u8(), None);
assert_eq!(isize::MAX.to_u16(), None);
// isize::MAX.to_u32() is word-size specific
assert_eq!(isize::MAX.to_u64(), Some(isize::MAX as u64));
2015-01-16 15:01:02 +00:00
#[cfg(target_pointer_width = "32")]
fn check_word_size() {
2015-02-20 06:18:12 +00:00
assert_eq!(isize::MAX.to_i32(), Some(isize::MAX as i32));
assert_eq!(isize::MAX.to_u32(), Some(isize::MAX as u32));
}
2015-01-16 15:01:02 +00:00
#[cfg(target_pointer_width = "64")]
fn check_word_size() {
2015-02-20 06:18:12 +00:00
assert_eq!(isize::MAX.to_i32(), None);
assert_eq!(isize::MAX.to_u32(), None);
}
check_word_size();
}
#[test]
fn test_cast_range_i8_max() {
2015-02-20 06:18:12 +00:00
assert_eq!(i8::MAX.to_int(), Some(i8::MAX as isize));
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));
2015-02-20 06:18:12 +00:00
assert_eq!(i8::MAX.to_uint(), Some(i8::MAX as usize));
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));
}
#[test]
fn test_cast_range_i16_max() {
2015-02-20 06:18:12 +00:00
assert_eq!(i16::MAX.to_int(), Some(i16::MAX as isize));
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));
2015-02-20 06:18:12 +00:00
assert_eq!(i16::MAX.to_uint(), Some(i16::MAX as usize));
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));
}
#[test]
fn test_cast_range_i32_max() {
2015-02-20 06:18:12 +00:00
assert_eq!(i32::MAX.to_int(), Some(i32::MAX as isize));
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));
2015-02-20 06:18:12 +00:00
assert_eq!(i32::MAX.to_uint(), Some(i32::MAX as usize));
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));
}
#[test]
fn test_cast_range_i64_max() {
// 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));
2015-01-16 15:01:02 +00:00
#[cfg(target_pointer_width = "32")]
fn check_word_size() {
assert_eq!(i64::MAX.to_int(), None);
assert_eq!(i64::MAX.to_uint(), None);
}
2015-01-16 15:01:02 +00:00
#[cfg(target_pointer_width = "64")]
fn check_word_size() {
2015-02-20 06:18:12 +00:00
assert_eq!(i64::MAX.to_int(), Some(i64::MAX as isize));
assert_eq!(i64::MAX.to_uint(), Some(i64::MAX as usize));
}
check_word_size();
}
#[test]
fn test_cast_range_uint_min() {
2015-02-20 06:18:12 +00:00
assert_eq!(usize::MIN.to_int(), Some(usize::MIN as isize));
assert_eq!(usize::MIN.to_i8(), Some(usize::MIN as i8));
assert_eq!(usize::MIN.to_i16(), Some(usize::MIN as i16));
assert_eq!(usize::MIN.to_i32(), Some(usize::MIN as i32));
assert_eq!(usize::MIN.to_i64(), Some(usize::MIN as i64));
assert_eq!(usize::MIN.to_uint(), Some(usize::MIN as usize));
assert_eq!(usize::MIN.to_u8(), Some(usize::MIN as u8));
assert_eq!(usize::MIN.to_u16(), Some(usize::MIN as u16));
assert_eq!(usize::MIN.to_u32(), Some(usize::MIN as u32));
assert_eq!(usize::MIN.to_u64(), Some(usize::MIN as u64));
}
#[test]
fn test_cast_range_u8_min() {
2015-02-20 06:18:12 +00:00
assert_eq!(u8::MIN.to_int(), Some(u8::MIN as isize));
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));
2015-02-20 06:18:12 +00:00
assert_eq!(u8::MIN.to_uint(), Some(u8::MIN as usize));
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));
}
#[test]
fn test_cast_range_u16_min() {
2015-02-20 06:18:12 +00:00
assert_eq!(u16::MIN.to_int(), Some(u16::MIN as isize));
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));
2015-02-20 06:18:12 +00:00
assert_eq!(u16::MIN.to_uint(), Some(u16::MIN as usize));
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));
}
#[test]
fn test_cast_range_u32_min() {
2015-02-20 06:18:12 +00:00
assert_eq!(u32::MIN.to_int(), Some(u32::MIN as isize));
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));
2015-02-20 06:18:12 +00:00
assert_eq!(u32::MIN.to_uint(), Some(u32::MIN as usize));
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));
}
#[test]
fn test_cast_range_u64_min() {
2015-02-20 06:18:12 +00:00
assert_eq!(u64::MIN.to_int(), Some(u64::MIN as isize));
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));
2015-02-20 06:18:12 +00:00
assert_eq!(u64::MIN.to_uint(), Some(u64::MIN as usize));
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));
}
#[test]
fn test_cast_range_uint_max() {
2015-02-20 06:18:12 +00:00
assert_eq!(usize::MAX.to_int(), None);
assert_eq!(usize::MAX.to_i8(), None);
assert_eq!(usize::MAX.to_i16(), None);
assert_eq!(usize::MAX.to_i32(), None);
// usize::MAX.to_i64() is word-size specific
assert_eq!(usize::MAX.to_u8(), None);
assert_eq!(usize::MAX.to_u16(), None);
// usize::MAX.to_u32() is word-size specific
assert_eq!(usize::MAX.to_u64(), Some(usize::MAX as u64));
2015-01-16 15:01:02 +00:00
#[cfg(target_pointer_width = "32")]
fn check_word_size() {
2015-02-20 06:18:12 +00:00
assert_eq!(usize::MAX.to_u32(), Some(usize::MAX as u32));
assert_eq!(usize::MAX.to_i64(), Some(usize::MAX as i64));
}
2015-01-16 15:01:02 +00:00
#[cfg(target_pointer_width = "64")]
fn check_word_size() {
2015-02-20 06:18:12 +00:00
assert_eq!(usize::MAX.to_u32(), None);
assert_eq!(usize::MAX.to_i64(), None);
}
check_word_size();
}
#[test]
fn test_cast_range_u8_max() {
2015-02-20 06:18:12 +00:00
assert_eq!(u8::MAX.to_int(), Some(u8::MAX as isize));
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));
2015-02-20 06:18:12 +00:00
assert_eq!(u8::MAX.to_uint(), Some(u8::MAX as usize));
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));
}
#[test]
fn test_cast_range_u16_max() {
2015-02-20 06:18:12 +00:00
assert_eq!(u16::MAX.to_int(), Some(u16::MAX as isize));
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));
2015-02-20 06:18:12 +00:00
assert_eq!(u16::MAX.to_uint(), Some(u16::MAX as usize));
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));
}
#[test]
fn test_cast_range_u32_max() {
// 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));
2015-02-20 06:18:12 +00:00
assert_eq!(u32::MAX.to_uint(), Some(u32::MAX as usize));
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));
2015-01-16 15:01:02 +00:00
#[cfg(target_pointer_width = "32")]
fn check_word_size() {
assert_eq!(u32::MAX.to_int(), None);
}
2015-01-16 15:01:02 +00:00
#[cfg(target_pointer_width = "64")]
fn check_word_size() {
2015-02-20 06:18:12 +00:00
assert_eq!(u32::MAX.to_int(), Some(u32::MAX as isize));
}
check_word_size();
}
#[test]
fn test_cast_range_u64_max() {
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));
2015-01-16 15:01:02 +00:00
#[cfg(target_pointer_width = "32")]
fn check_word_size() {
assert_eq!(u64::MAX.to_uint(), None);
}
2015-01-16 15:01:02 +00:00
#[cfg(target_pointer_width = "64")]
fn check_word_size() {
2015-02-20 06:18:12 +00:00
assert_eq!(u64::MAX.to_uint(), Some(u64::MAX as usize));
}
check_word_size();
}
#[test]
fn test_saturating_add_uint() {
2015-02-20 06:18:12 +00:00
use usize::MAX;
assert_eq!(3_usize.saturating_add(5_usize), 8_usize);
assert_eq!(3_usize.saturating_add(MAX-1), MAX);
assert_eq!(MAX.saturating_add(MAX), MAX);
assert_eq!((MAX-2).saturating_add(1), MAX-1);
}
#[test]
fn test_saturating_sub_uint() {
2015-02-20 06:18:12 +00:00
use usize::MAX;
assert_eq!(5_usize.saturating_sub(3_usize), 2_usize);
assert_eq!(3_usize.saturating_sub(5_usize), 0_usize);
assert_eq!(0_usize.saturating_sub(1_usize), 0_usize);
assert_eq!((MAX-1).saturating_sub(MAX), 0);
}
#[test]
fn test_saturating_add_int() {
2015-02-20 06:18:12 +00:00
use isize::{MIN,MAX};
2015-01-25 21:05:03 +00:00
assert_eq!(3.saturating_add(5), 8);
assert_eq!(3.saturating_add(MAX-1), MAX);
assert_eq!(MAX.saturating_add(MAX), MAX);
assert_eq!((MAX-2).saturating_add(1), MAX-1);
2015-01-25 21:05:03 +00:00
assert_eq!(3.saturating_add(-5), -2);
assert_eq!(MIN.saturating_add(-1), MIN);
assert_eq!((-2).saturating_add(-MAX), MIN);
}
#[test]
fn test_saturating_sub_int() {
2015-02-20 06:18:12 +00:00
use isize::{MIN,MAX};
2015-01-25 21:05:03 +00:00
assert_eq!(3.saturating_sub(5), -2);
assert_eq!(MIN.saturating_sub(1), MIN);
assert_eq!((-2).saturating_sub(MAX), MIN);
assert_eq!(3.saturating_sub(-5), 8);
assert_eq!(3.saturating_sub(-(MAX-1)), MAX);
assert_eq!(MAX.saturating_sub(-MAX), MAX);
assert_eq!((MAX-2).saturating_sub(-1), MAX-1);
}
#[test]
fn test_checked_add() {
2015-02-20 06:18:12 +00:00
let five_less = usize::MAX - 5;
assert_eq!(five_less.checked_add(0), Some(usize::MAX - 5));
assert_eq!(five_less.checked_add(1), Some(usize::MAX - 4));
assert_eq!(five_less.checked_add(2), Some(usize::MAX - 3));
assert_eq!(five_less.checked_add(3), Some(usize::MAX - 2));
assert_eq!(five_less.checked_add(4), Some(usize::MAX - 1));
assert_eq!(five_less.checked_add(5), Some(usize::MAX));
assert_eq!(five_less.checked_add(6), None);
assert_eq!(five_less.checked_add(7), None);
}
#[test]
fn test_checked_sub() {
assert_eq!(5_usize.checked_sub(0), Some(5));
assert_eq!(5_usize.checked_sub(1), Some(4));
assert_eq!(5_usize.checked_sub(2), Some(3));
assert_eq!(5_usize.checked_sub(3), Some(2));
assert_eq!(5_usize.checked_sub(4), Some(1));
assert_eq!(5_usize.checked_sub(5), Some(0));
assert_eq!(5_usize.checked_sub(6), None);
assert_eq!(5_usize.checked_sub(7), None);
}
#[test]
fn test_checked_mul() {
2015-02-20 06:18:12 +00:00
let third = usize::MAX / 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);
}
macro_rules! test_is_power_of_two {
($test_name:ident, $T:ident) => (
fn $test_name() {
#![test]
assert_eq!((0 as $T).is_power_of_two(), false);
assert_eq!((1 as $T).is_power_of_two(), true);
assert_eq!((2 as $T).is_power_of_two(), true);
assert_eq!((3 as $T).is_power_of_two(), false);
assert_eq!((4 as $T).is_power_of_two(), true);
assert_eq!((5 as $T).is_power_of_two(), false);
assert_eq!(($T::MAX / 2 + 1).is_power_of_two(), true);
}
)
}
test_is_power_of_two!{ test_is_power_of_two_u8, u8 }
test_is_power_of_two!{ test_is_power_of_two_u16, u16 }
test_is_power_of_two!{ test_is_power_of_two_u32, u32 }
test_is_power_of_two!{ test_is_power_of_two_u64, u64 }
2015-02-20 06:18:12 +00:00
test_is_power_of_two!{ test_is_power_of_two_uint, usize }
macro_rules! test_next_power_of_two {
($test_name:ident, $T:ident) => (
fn $test_name() {
2014-04-02 03:39:26 +00:00
#![test]
assert_eq!((0 as $T).next_power_of_two(), 1);
let mut next_power = 1;
for i in range::<$T>(1, 40) {
assert_eq!(i.next_power_of_two(), 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 }
2015-02-20 06:18:12 +00:00
test_next_power_of_two! { test_next_power_of_two_uint, usize }
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]
assert_eq!((0 as $T).checked_next_power_of_two(), Some(1));
assert!(($T::MAX / 2).checked_next_power_of_two().is_some());
assert_eq!(($T::MAX - 1).checked_next_power_of_two(), None);
assert_eq!($T::MAX.checked_next_power_of_two(), None);
let mut next_power = 1;
for i in range::<$T>(1, 40) {
assert_eq!(i.checked_next_power_of_two(), Some(next_power));
if i == next_power { next_power *= 2 }
}
}
)
}
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 }
2015-02-20 06:18:12 +00:00
test_checked_next_power_of_two! { test_checked_next_power_of_two_uint, usize }
2015-01-28 13:34:18 +00:00
#[derive(PartialEq, Debug)]
2015-02-20 06:18:12 +00:00
struct Value { x: isize }
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 {
2015-02-20 06:18:12 +00:00
fn from_i64(n: i64) -> Option<Value> { Some(Value { x: n as isize }) }
fn from_u64(n: u64) -> Option<Value> { Some(Value { x: n as isize }) }
}
#[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 }));
}
#[test]
fn test_pow() {
2015-02-20 06:18:12 +00:00
fn naive_pow<T: Int>(base: T, exp: usize) -> T {
2014-11-15 08:44:22 +00:00
let one: T = Int::one();
(0..exp).fold(one, |acc, _| acc * base)
}
macro_rules! assert_pow {
(($num:expr, $exp:expr) => $expected:expr) => {{
let result = $num.pow($exp);
assert_eq!(result, $expected);
assert_eq!(result, naive_pow($num, $exp));
}}
}
2015-01-25 21:05:03 +00:00
assert_pow!((3, 0 ) => 1);
assert_pow!((5, 1 ) => 5);
assert_pow!((-4, 2 ) => 16);
assert_pow!((8, 3 ) => 512);
assert_pow!((2u64, 50) => 1125899906842624);
}
#[test]
fn test_uint_to_str_overflow() {
let mut u8_val: u8 = 255;
assert_eq!(u8_val.to_string(), "255");
u8_val = u8_val.wrapping_add(1);
assert_eq!(u8_val.to_string(), "0");
let mut u16_val: u16 = 65_535;
assert_eq!(u16_val.to_string(), "65535");
u16_val = u16_val.wrapping_add(1);
assert_eq!(u16_val.to_string(), "0");
let mut u32_val: u32 = 4_294_967_295;
assert_eq!(u32_val.to_string(), "4294967295");
u32_val = u32_val.wrapping_add(1);
assert_eq!(u32_val.to_string(), "0");
let mut u64_val: u64 = 18_446_744_073_709_551_615;
assert_eq!(u64_val.to_string(), "18446744073709551615");
u64_val = u64_val.wrapping_add(1);
assert_eq!(u64_val.to_string(), "0");
}
fn from_str<T: ::str::FromStr>(t: &str) -> Option<T> {
::str::FromStr::from_str(t).ok()
}
#[test]
fn test_uint_from_str_overflow() {
let mut u8_val: u8 = 255;
assert_eq!(from_str::<u8>("255"), Some(u8_val));
assert_eq!(from_str::<u8>("256"), None);
u8_val = u8_val.wrapping_add(1);
assert_eq!(from_str::<u8>("0"), Some(u8_val));
assert_eq!(from_str::<u8>("-1"), None);
let mut u16_val: u16 = 65_535;
assert_eq!(from_str::<u16>("65535"), Some(u16_val));
assert_eq!(from_str::<u16>("65536"), None);
u16_val = u16_val.wrapping_add(1);
assert_eq!(from_str::<u16>("0"), Some(u16_val));
assert_eq!(from_str::<u16>("-1"), None);
let mut u32_val: u32 = 4_294_967_295;
assert_eq!(from_str::<u32>("4294967295"), Some(u32_val));
assert_eq!(from_str::<u32>("4294967296"), None);
u32_val = u32_val.wrapping_add(1);
assert_eq!(from_str::<u32>("0"), Some(u32_val));
assert_eq!(from_str::<u32>("-1"), None);
let mut u64_val: u64 = 18_446_744_073_709_551_615;
assert_eq!(from_str::<u64>("18446744073709551615"), Some(u64_val));
assert_eq!(from_str::<u64>("18446744073709551616"), None);
u64_val = u64_val.wrapping_add(1);
assert_eq!(from_str::<u64>("0"), Some(u64_val));
assert_eq!(from_str::<u64>("-1"), None);
}
}
#[cfg(test)]
mod bench {
2014-02-14 01:49:11 +00:00
extern crate test;
use self::test::Bencher;
use num::Int;
use prelude::v1::*;
#[bench]
fn bench_pow_function(b: &mut Bencher) {
let v = (0..1024).collect::<Vec<_>>();
b.iter(|| {v.iter().fold(0, |old, new| old.pow(*new as u32));});
}
}