2013-02-14 20:29:36 -06:00
|
|
|
// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
|
2012-12-03 18:48:01 -06: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.
|
|
|
|
|
2012-09-19 18:52:32 -05:00
|
|
|
//! An interface for numeric types
|
2013-05-28 16:35:52 -05:00
|
|
|
|
|
|
|
#[allow(missing_doc)];
|
|
|
|
|
2013-05-06 01:10:26 -05:00
|
|
|
use cmp::{Eq, ApproxEq, Ord};
|
2013-05-01 00:40:05 -05:00
|
|
|
use ops::{Add, Sub, Mul, Div, Rem, Neg};
|
2013-04-25 19:02:00 -05:00
|
|
|
use ops::{Not, BitAnd, BitOr, BitXor, Shl, Shr};
|
2013-03-26 15:38:07 -05:00
|
|
|
use option::Option;
|
2012-06-07 19:25:54 -05:00
|
|
|
|
2013-02-14 20:29:36 -06:00
|
|
|
pub mod strconv;
|
|
|
|
|
2013-04-26 10:01:53 -05:00
|
|
|
///
|
|
|
|
/// The base trait for numeric types
|
|
|
|
///
|
2013-04-13 11:19:35 -05:00
|
|
|
pub trait Num: Eq + Zero + One
|
|
|
|
+ Neg<Self>
|
|
|
|
+ Add<Self,Self>
|
|
|
|
+ Sub<Self,Self>
|
|
|
|
+ Mul<Self,Self>
|
2013-05-01 00:40:05 -05:00
|
|
|
+ Div<Self,Self>
|
2013-04-21 10:58:53 -05:00
|
|
|
+ Rem<Self,Self> {}
|
2013-04-13 11:19:35 -05:00
|
|
|
|
2013-01-25 18:57:39 -06:00
|
|
|
pub trait IntConvertible {
|
2013-03-21 23:20:48 -05:00
|
|
|
fn to_int(&self) -> int;
|
|
|
|
fn from_int(n: int) -> Self;
|
2013-01-25 18:57:39 -06:00
|
|
|
}
|
|
|
|
|
2013-04-26 10:01:53 -05: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;
|
|
|
|
}
|
|
|
|
|
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 11:05:17 -05:00
|
|
|
#[inline(always)] pub fn min<T: Orderable>(a: T, b: T) -> T { a.min(&b) }
|
|
|
|
#[inline(always)] pub fn max<T: Orderable>(a: T, b: T) -> T { a.max(&b) }
|
|
|
|
|
2012-12-20 09:14:38 -06:00
|
|
|
pub trait Zero {
|
2013-04-25 00:30:56 -05:00
|
|
|
fn zero() -> Self; // FIXME (#5527): This should be an associated constant
|
|
|
|
fn is_zero(&self) -> bool;
|
2012-12-20 09:14:38 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
pub trait One {
|
2013-04-25 00:30:56 -05:00
|
|
|
fn one() -> Self; // FIXME (#5527): This should be an associated constant
|
2012-12-20 09:14:38 -06:00
|
|
|
}
|
2013-01-26 20:05:20 -06:00
|
|
|
|
2013-04-23 02:59:49 -05:00
|
|
|
pub trait Signed: Num
|
|
|
|
+ Neg<Self> {
|
|
|
|
fn abs(&self) -> Self;
|
2013-05-06 23:36:32 -05:00
|
|
|
fn abs_sub(&self, other: &Self) -> Self;
|
2013-04-23 02:59:49 -05:00
|
|
|
fn signum(&self) -> Self;
|
2013-05-06 23:36:32 -05:00
|
|
|
|
2013-04-23 02:59:49 -05:00
|
|
|
fn is_positive(&self) -> bool;
|
|
|
|
fn is_negative(&self) -> bool;
|
|
|
|
}
|
|
|
|
|
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 11:05:17 -05:00
|
|
|
#[inline(always)] pub fn abs<T: Signed>(value: T) -> T { value.abs() }
|
|
|
|
#[inline(always)] pub fn signum<T: Signed>(value: T) -> T { value.signum() }
|
2013-04-23 02:59:49 -05: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 11:05:17 -05:00
|
|
|
pub trait Unsigned: Num {}
|
2013-01-15 19:30:16 -06:00
|
|
|
|
2013-04-24 07:45:57 -05:00
|
|
|
pub trait Integer: Num
|
2013-04-26 10:01:53 -05:00
|
|
|
+ Orderable
|
2013-05-01 00:40:05 -05:00
|
|
|
+ Div<Self,Self>
|
2013-04-23 21:54:11 -05:00
|
|
|
+ Rem<Self,Self> {
|
2013-05-01 00:40:05 -05: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-23 21:54:11 -05:00
|
|
|
|
2013-04-24 07:50:56 -05:00
|
|
|
fn gcd(&self, other: &Self) -> Self;
|
|
|
|
fn lcm(&self, other: &Self) -> Self;
|
2013-04-29 01:02:43 -05:00
|
|
|
|
|
|
|
fn is_multiple_of(&self, other: &Self) -> bool;
|
2013-04-23 21:54:11 -05:00
|
|
|
fn is_even(&self) -> bool;
|
|
|
|
fn is_odd(&self) -> bool;
|
|
|
|
}
|
|
|
|
|
2013-04-24 20:53:04 -05:00
|
|
|
pub trait Round {
|
|
|
|
fn floor(&self) -> Self;
|
|
|
|
fn ceil(&self) -> Self;
|
|
|
|
fn round(&self) -> Self;
|
|
|
|
fn trunc(&self) -> Self;
|
|
|
|
fn fract(&self) -> Self;
|
|
|
|
}
|
|
|
|
|
2013-04-24 17:12:26 -05:00
|
|
|
pub trait Fractional: Num
|
2013-04-26 10:01:53 -05:00
|
|
|
+ Orderable
|
2013-04-24 20:53:04 -05:00
|
|
|
+ Round
|
2013-05-01 00:40:05 -05:00
|
|
|
+ Div<Self,Self> {
|
2013-04-24 17:12:26 -05:00
|
|
|
fn recip(&self) -> Self;
|
|
|
|
}
|
|
|
|
|
2013-04-29 00:33:55 -05:00
|
|
|
pub trait Algebraic {
|
2013-06-10 20:03:02 -05:00
|
|
|
fn pow(&self, n: &Self) -> Self;
|
2013-04-29 00:33:55 -05:00
|
|
|
fn sqrt(&self) -> Self;
|
|
|
|
fn rsqrt(&self) -> Self;
|
|
|
|
fn cbrt(&self) -> Self;
|
2013-06-10 20:03:02 -05:00
|
|
|
fn hypot(&self, other: &Self) -> Self;
|
2013-04-29 00:33:55 -05: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 11:05:17 -05:00
|
|
|
#[inline(always)] pub fn sqrt<T: Algebraic>(value: T) -> T { value.sqrt() }
|
|
|
|
|
2013-04-29 00:33:55 -05:00
|
|
|
pub trait Trigonometric {
|
|
|
|
fn sin(&self) -> Self;
|
|
|
|
fn cos(&self) -> Self;
|
|
|
|
fn tan(&self) -> Self;
|
|
|
|
fn asin(&self) -> Self;
|
|
|
|
fn acos(&self) -> Self;
|
|
|
|
fn atan(&self) -> Self;
|
2013-06-10 20:03:02 -05:00
|
|
|
fn atan2(&self, other: &Self) -> Self;
|
2013-05-16 21:30:02 -05:00
|
|
|
fn sin_cos(&self) -> (Self, Self);
|
2013-04-29 00:33:55 -05: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 11:05:17 -05:00
|
|
|
#[inline(always)] pub fn sin<T: Trigonometric>(value: T) -> T { value.sin() }
|
|
|
|
#[inline(always)] pub fn cos<T: Trigonometric>(value: T) -> T { value.cos() }
|
|
|
|
#[inline(always)] pub fn tan<T: Trigonometric>(value: T) -> T { value.tan() }
|
|
|
|
|
|
|
|
#[inline(always)] pub fn asin<T: Trigonometric>(value: T) -> T { value.asin() }
|
|
|
|
#[inline(always)] pub fn acos<T: Trigonometric>(value: T) -> T { value.acos() }
|
|
|
|
#[inline(always)] pub fn atan<T: Trigonometric>(value: T) -> T { value.atan() }
|
|
|
|
|
|
|
|
#[inline(always)] pub fn atan2<T: Trigonometric>(x: T, y: T) -> T { x.atan2(&y) }
|
|
|
|
|
2013-04-29 00:33:55 -05:00
|
|
|
pub trait Exponential {
|
|
|
|
fn exp(&self) -> Self;
|
|
|
|
fn exp2(&self) -> Self;
|
2013-05-06 12:09:09 -05:00
|
|
|
fn ln(&self) -> Self;
|
2013-06-10 20:03:02 -05:00
|
|
|
fn log(&self, base: &Self) -> Self;
|
2013-04-29 00:33:55 -05:00
|
|
|
fn log2(&self) -> Self;
|
|
|
|
fn log10(&self) -> Self;
|
2013-04-29 08:38:58 -05:00
|
|
|
}
|
2013-04-29 00:33:55 -05: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 11:05:17 -05:00
|
|
|
#[inline(always)] pub fn exp<T: Exponential>(value: T) -> T { value.exp() }
|
|
|
|
#[inline(always)] pub fn exp2<T: Exponential>(value: T) -> T { value.exp2() }
|
|
|
|
|
|
|
|
#[inline(always)] pub fn ln<T: Exponential>(value: T) -> T { value.ln() }
|
|
|
|
#[inline(always)] pub fn log<T: Exponential>(value: T, base: T) -> T { value.log(&base) }
|
|
|
|
#[inline(always)] pub fn log2<T: Exponential>(value: T) -> T { value.log2() }
|
|
|
|
#[inline(always)] pub fn log10<T: Exponential>(value: T) -> T { value.log10() }
|
|
|
|
|
2013-04-29 08:38:58 -05:00
|
|
|
pub trait Hyperbolic: Exponential {
|
2013-04-29 00:33:55 -05:00
|
|
|
fn sinh(&self) -> Self;
|
|
|
|
fn cosh(&self) -> Self;
|
|
|
|
fn tanh(&self) -> Self;
|
2013-05-13 09:11:35 -05:00
|
|
|
fn asinh(&self) -> Self;
|
|
|
|
fn acosh(&self) -> Self;
|
|
|
|
fn atanh(&self) -> Self;
|
2013-04-29 00:33:55 -05: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 11:05:17 -05:00
|
|
|
#[inline(always)] pub fn sinh<T: Hyperbolic>(value: T) -> T { value.sinh() }
|
|
|
|
#[inline(always)] pub fn cosh<T: Hyperbolic>(value: T) -> T { value.cosh() }
|
|
|
|
#[inline(always)] pub fn tanh<T: Hyperbolic>(value: T) -> T { value.tanh() }
|
|
|
|
|
|
|
|
#[inline(always)] pub fn asinh<T: Hyperbolic>(value: T) -> T { value.asinh() }
|
|
|
|
#[inline(always)] pub fn acosh<T: Hyperbolic>(value: T) -> T { value.acosh() }
|
|
|
|
#[inline(always)] pub fn atanh<T: Hyperbolic>(value: T) -> T { value.atanh() }
|
|
|
|
|
2013-04-26 10:02:30 -05:00
|
|
|
///
|
|
|
|
/// Defines constants and methods common to real numbers
|
|
|
|
///
|
2013-04-24 17:12:26 -05:00
|
|
|
pub trait Real: Signed
|
2013-04-29 00:33:55 -05:00
|
|
|
+ Fractional
|
|
|
|
+ Algebraic
|
|
|
|
+ Trigonometric
|
2013-04-29 08:38:58 -05:00
|
|
|
+ Hyperbolic {
|
2013-04-24 17:12:26 -05: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-06 12:09:09 -05:00
|
|
|
fn ln_2() -> Self;
|
|
|
|
fn ln_10() -> Self;
|
2013-01-26 20:05:20 -06:00
|
|
|
|
2013-04-24 17:12:26 -05:00
|
|
|
// Angular conversions
|
|
|
|
fn to_degrees(&self) -> Self;
|
|
|
|
fn to_radians(&self) -> Self;
|
2013-01-26 20:05:20 -06:00
|
|
|
}
|
|
|
|
|
2013-04-25 18:55:49 -05:00
|
|
|
///
|
2013-04-24 17:12:26 -05:00
|
|
|
/// Methods that are harder to implement and not commonly used.
|
2013-04-25 18:55:49 -05:00
|
|
|
///
|
2013-04-24 17:12:26 -05:00
|
|
|
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-14 22:46:07 -06:00
|
|
|
}
|
|
|
|
|
2013-04-25 19:02:00 -05: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-04-26 01:27:51 -05:00
|
|
|
pub trait BitCount {
|
|
|
|
fn population_count(&self) -> Self;
|
|
|
|
fn leading_zeros(&self) -> Self;
|
|
|
|
fn trailing_zeros(&self) -> Self;
|
|
|
|
}
|
|
|
|
|
2013-04-25 19:02:00 -05: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.
|
|
|
|
///
|
|
|
|
pub trait Primitive: Num
|
|
|
|
+ NumCast
|
2013-04-26 18:07:40 -05:00
|
|
|
+ Bounded
|
2013-04-25 19:02:00 -05:00
|
|
|
+ Neg<Self>
|
|
|
|
+ Add<Self,Self>
|
|
|
|
+ Sub<Self,Self>
|
|
|
|
+ Mul<Self,Self>
|
2013-05-01 00:40:05 -05:00
|
|
|
+ Div<Self,Self>
|
2013-04-25 19:02:00 -05:00
|
|
|
+ Rem<Self,Self> {
|
|
|
|
// FIXME (#5527): These should be associated constants
|
|
|
|
fn bits() -> uint;
|
|
|
|
fn bytes() -> uint;
|
|
|
|
}
|
|
|
|
|
|
|
|
///
|
|
|
|
/// A collection of traits relevant to primitive signed and unsigned integers
|
|
|
|
///
|
2013-04-26 04:56:11 -05:00
|
|
|
pub trait Int: Integer
|
|
|
|
+ Primitive
|
|
|
|
+ Bitwise
|
|
|
|
+ BitCount {}
|
2013-04-25 19:02:00 -05:00
|
|
|
|
2013-05-07 05:30:51 -05: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-25 19:22:08 -05:00
|
|
|
///
|
2013-04-26 10:02:30 -05:00
|
|
|
/// Primitive floating point numbers
|
2013-04-25 19:22:08 -05:00
|
|
|
///
|
|
|
|
pub trait Float: Real
|
|
|
|
+ Signed
|
2013-05-06 01:10:26 -05:00
|
|
|
+ Primitive
|
|
|
|
+ ApproxEq<Self> {
|
2013-04-25 19:22:08 -05:00
|
|
|
// FIXME (#5527): These should be associated constants
|
|
|
|
fn NaN() -> Self;
|
|
|
|
fn infinity() -> Self;
|
|
|
|
fn neg_infinity() -> Self;
|
|
|
|
fn neg_zero() -> Self;
|
|
|
|
|
|
|
|
fn is_NaN(&self) -> bool;
|
|
|
|
fn is_infinite(&self) -> bool;
|
|
|
|
fn is_finite(&self) -> bool;
|
2013-05-07 05:30:51 -05:00
|
|
|
fn is_normal(&self) -> bool;
|
|
|
|
fn classify(&self) -> FPCategory;
|
2013-04-26 10:02:30 -05:00
|
|
|
|
2013-04-26 18:07:40 -05:00
|
|
|
fn mantissa_digits() -> uint;
|
|
|
|
fn digits() -> uint;
|
|
|
|
fn epsilon() -> Self;
|
|
|
|
fn min_exp() -> int;
|
|
|
|
fn max_exp() -> int;
|
|
|
|
fn min_10_exp() -> int;
|
|
|
|
fn max_10_exp() -> int;
|
|
|
|
|
2013-05-13 20:24:55 -05:00
|
|
|
fn ldexp(x: Self, exp: int) -> Self;
|
|
|
|
fn frexp(&self) -> (Self, int);
|
|
|
|
|
2013-05-06 13:47:46 -05:00
|
|
|
fn exp_m1(&self) -> Self;
|
|
|
|
fn ln_1p(&self) -> Self;
|
2013-04-26 10:02:30 -05:00
|
|
|
fn mul_add(&self, a: Self, b: Self) -> Self;
|
|
|
|
fn next_after(&self, other: Self) -> Self;
|
2013-04-25 19:22:08 -05:00
|
|
|
}
|
|
|
|
|
2013-04-25 18:55:49 -05:00
|
|
|
///
|
|
|
|
/// Cast from one machine scalar to another
|
|
|
|
///
|
|
|
|
/// # Example
|
|
|
|
///
|
|
|
|
/// ~~~
|
|
|
|
/// let twenty: f32 = num::cast(0x14);
|
|
|
|
/// assert_eq!(twenty, 20f32);
|
|
|
|
/// ~~~
|
|
|
|
///
|
2013-06-18 16:45:18 -05:00
|
|
|
#[inline]
|
2013-03-21 23:20:48 -05:00
|
|
|
pub fn cast<T:NumCast,U:NumCast>(n: T) -> U {
|
2013-02-10 19:33:05 -06:00
|
|
|
NumCast::from(n)
|
|
|
|
}
|
|
|
|
|
2013-04-25 18:55:49 -05:00
|
|
|
///
|
|
|
|
/// An interface for casting between machine scalars
|
|
|
|
///
|
2013-02-10 19:33:05 -06:00
|
|
|
pub trait NumCast {
|
2013-03-21 23:20:48 -05:00
|
|
|
fn from<T:NumCast>(n: T) -> Self;
|
|
|
|
|
|
|
|
fn to_u8(&self) -> u8;
|
|
|
|
fn to_u16(&self) -> u16;
|
|
|
|
fn to_u32(&self) -> u32;
|
|
|
|
fn to_u64(&self) -> u64;
|
|
|
|
fn to_uint(&self) -> uint;
|
|
|
|
|
|
|
|
fn to_i8(&self) -> i8;
|
|
|
|
fn to_i16(&self) -> i16;
|
|
|
|
fn to_i32(&self) -> i32;
|
|
|
|
fn to_i64(&self) -> i64;
|
|
|
|
fn to_int(&self) -> int;
|
|
|
|
|
|
|
|
fn to_f32(&self) -> f32;
|
|
|
|
fn to_f64(&self) -> f64;
|
|
|
|
fn to_float(&self) -> float;
|
2013-02-10 19:33:05 -06:00
|
|
|
}
|
|
|
|
|
2013-04-13 08:44:35 -05:00
|
|
|
macro_rules! impl_num_cast(
|
|
|
|
($T:ty, $conv:ident) => (
|
2013-04-13 14:27:32 -05:00
|
|
|
impl NumCast for $T {
|
2013-06-18 16:45:18 -05:00
|
|
|
#[inline]
|
2013-04-13 14:27:32 -05:00
|
|
|
fn from<N:NumCast>(n: N) -> $T {
|
|
|
|
// `$conv` could be generated using `concat_idents!`, but that
|
|
|
|
// macro seems to be broken at the moment
|
|
|
|
n.$conv()
|
2013-04-13 08:44:35 -05:00
|
|
|
}
|
2013-04-13 14:27:32 -05:00
|
|
|
|
2013-06-18 16:45:18 -05:00
|
|
|
#[inline] fn to_u8(&self) -> u8 { *self as u8 }
|
|
|
|
#[inline] fn to_u16(&self) -> u16 { *self as u16 }
|
|
|
|
#[inline] fn to_u32(&self) -> u32 { *self as u32 }
|
|
|
|
#[inline] fn to_u64(&self) -> u64 { *self as u64 }
|
|
|
|
#[inline] fn to_uint(&self) -> uint { *self as uint }
|
|
|
|
|
|
|
|
#[inline] fn to_i8(&self) -> i8 { *self as i8 }
|
|
|
|
#[inline] fn to_i16(&self) -> i16 { *self as i16 }
|
|
|
|
#[inline] fn to_i32(&self) -> i32 { *self as i32 }
|
|
|
|
#[inline] fn to_i64(&self) -> i64 { *self as i64 }
|
|
|
|
#[inline] fn to_int(&self) -> int { *self as int }
|
|
|
|
|
|
|
|
#[inline] fn to_f32(&self) -> f32 { *self as f32 }
|
|
|
|
#[inline] fn to_f64(&self) -> f64 { *self as f64 }
|
|
|
|
#[inline] fn to_float(&self) -> float { *self as float }
|
2013-04-13 08:44:35 -05: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)
|
|
|
|
impl_num_cast!(float, to_float)
|
|
|
|
|
2013-01-24 14:09:58 -06:00
|
|
|
pub trait ToStrRadix {
|
2013-03-21 23:20:48 -05:00
|
|
|
pub fn to_str_radix(&self, radix: uint) -> ~str;
|
2013-01-24 14:09:58 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
pub trait FromStrRadix {
|
2013-03-21 23:20:48 -05:00
|
|
|
pub fn from_str_radix(str: &str, radix: uint) -> Option<Self>;
|
2013-01-20 17:40:02 -06:00
|
|
|
}
|
|
|
|
|
2013-04-25 18:55:49 -05: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 16:43:25 -05:00
|
|
|
pub fn pow_with_uint<T:NumCast+One+Zero+Div<T,T>+Mul<T,T>>(radix: uint, pow: uint) -> T {
|
2013-01-20 17:40:02 -06: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-05-17 11:07:16 -05:00
|
|
|
let mut multiplier = cast(radix);
|
2013-01-20 17:40:02 -06:00
|
|
|
while (my_pow > 0u) {
|
|
|
|
if my_pow % 2u == 1u {
|
2013-06-15 19:26:59 -05:00
|
|
|
total = total * multiplier;
|
2013-01-20 17:40:02 -06:00
|
|
|
}
|
2013-06-11 21:13:42 -05:00
|
|
|
my_pow = my_pow / 2u;
|
2013-06-15 19:26:59 -05:00
|
|
|
multiplier = multiplier * multiplier;
|
2013-01-20 17:40:02 -06:00
|
|
|
}
|
|
|
|
total
|
2013-01-26 20:13:33 -06:00
|
|
|
}
|
|
|
|
|
2013-07-18 19:12:46 -05:00
|
|
|
impl<T: Zero + 'static> Zero for @mut T {
|
2013-06-14 20:27:52 -05:00
|
|
|
fn zero() -> @mut T { @mut Zero::zero() }
|
|
|
|
fn is_zero(&self) -> bool { (**self).is_zero() }
|
|
|
|
}
|
|
|
|
|
2013-07-18 19:12:46 -05:00
|
|
|
impl<T: Zero + 'static> Zero for @T {
|
2013-06-14 20:27:52 -05: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-04-24 05:08:08 -05:00
|
|
|
/// Helper function for testing numeric operations
|
2013-05-04 16:25:41 -05:00
|
|
|
#[cfg(test)]
|
2013-04-24 05:08:08 -05:00
|
|
|
pub fn test_num<T:Num + NumCast>(ten: T, two: T) {
|
2013-04-21 10:58:53 -05:00
|
|
|
assert_eq!(ten.add(&two), cast(12));
|
|
|
|
assert_eq!(ten.sub(&two), cast(8));
|
|
|
|
assert_eq!(ten.mul(&two), cast(20));
|
2013-05-17 11:07:16 -05:00
|
|
|
assert_eq!(ten.div(&two), cast(5));
|
2013-04-21 10:58:53 -05:00
|
|
|
assert_eq!(ten.rem(&two), cast(0));
|
|
|
|
|
|
|
|
assert_eq!(ten.add(&two), ten + two);
|
|
|
|
assert_eq!(ten.sub(&two), ten - two);
|
|
|
|
assert_eq!(ten.mul(&two), ten * two);
|
2013-05-17 11:07:16 -05:00
|
|
|
assert_eq!(ten.div(&two), ten / two);
|
2013-04-21 10:58:53 -05:00
|
|
|
assert_eq!(ten.rem(&two), ten % two);
|
|
|
|
}
|
2013-04-13 11:53:00 -05:00
|
|
|
|
2013-04-13 08:44:35 -05:00
|
|
|
macro_rules! test_cast_20(
|
|
|
|
($_20:expr) => ({
|
|
|
|
let _20 = $_20;
|
2013-04-13 10:25:56 -05:00
|
|
|
|
2013-04-18 10:37:21 -05:00
|
|
|
assert_eq!(20u, _20.to_uint());
|
|
|
|
assert_eq!(20u8, _20.to_u8());
|
|
|
|
assert_eq!(20u16, _20.to_u16());
|
|
|
|
assert_eq!(20u32, _20.to_u32());
|
|
|
|
assert_eq!(20u64, _20.to_u64());
|
|
|
|
assert_eq!(20i, _20.to_int());
|
|
|
|
assert_eq!(20i8, _20.to_i8());
|
|
|
|
assert_eq!(20i16, _20.to_i16());
|
|
|
|
assert_eq!(20i32, _20.to_i32());
|
|
|
|
assert_eq!(20i64, _20.to_i64());
|
|
|
|
assert_eq!(20f, _20.to_float());
|
|
|
|
assert_eq!(20f32, _20.to_f32());
|
|
|
|
assert_eq!(20f64, _20.to_f64());
|
|
|
|
|
|
|
|
assert_eq!(_20, NumCast::from(20u));
|
|
|
|
assert_eq!(_20, NumCast::from(20u8));
|
|
|
|
assert_eq!(_20, NumCast::from(20u16));
|
|
|
|
assert_eq!(_20, NumCast::from(20u32));
|
|
|
|
assert_eq!(_20, NumCast::from(20u64));
|
|
|
|
assert_eq!(_20, NumCast::from(20i));
|
|
|
|
assert_eq!(_20, NumCast::from(20i8));
|
|
|
|
assert_eq!(_20, NumCast::from(20i16));
|
|
|
|
assert_eq!(_20, NumCast::from(20i32));
|
|
|
|
assert_eq!(_20, NumCast::from(20i64));
|
|
|
|
assert_eq!(_20, NumCast::from(20f));
|
|
|
|
assert_eq!(_20, NumCast::from(20f32));
|
|
|
|
assert_eq!(_20, NumCast::from(20f64));
|
|
|
|
|
|
|
|
assert_eq!(_20, cast(20u));
|
|
|
|
assert_eq!(_20, cast(20u8));
|
|
|
|
assert_eq!(_20, cast(20u16));
|
|
|
|
assert_eq!(_20, cast(20u32));
|
|
|
|
assert_eq!(_20, cast(20u64));
|
|
|
|
assert_eq!(_20, cast(20i));
|
|
|
|
assert_eq!(_20, cast(20i8));
|
|
|
|
assert_eq!(_20, cast(20i16));
|
|
|
|
assert_eq!(_20, cast(20i32));
|
|
|
|
assert_eq!(_20, cast(20i64));
|
|
|
|
assert_eq!(_20, cast(20f));
|
|
|
|
assert_eq!(_20, cast(20f32));
|
|
|
|
assert_eq!(_20, cast(20f64));
|
2013-04-13 08:44:35 -05: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-04-13 08:59:52 -05:00
|
|
|
#[test] fn test_float_cast() { test_cast_20!(20f) }
|