1 // Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
11 //! An interface for numeric types
14 use ops::{Add, Sub, Mul, Neg};
18 use Rem = ops::Modulo;
20 use ops::{Add, Sub, Mul, Quot, Rem, Neg};
21 use ops::{Not, BitAnd, BitOr, BitXor, Shl, Shr};
28 /// The base trait for numeric types
30 pub trait Num: Eq + Zero + One
38 pub trait IntConvertible {
39 fn to_int(&self) -> int;
40 fn from_int(n: int) -> Self;
43 pub trait Orderable: Ord {
44 // These should be methods on `Ord`, with overridable default implementations. We don't want
45 // to encumber all implementors of Ord by requiring them to implement these functions, but at
46 // the same time we want to be able to take advantage of the speed of the specific numeric
47 // functions (like the `fmin` and `fmax` intrinsics).
48 fn min(&self, other: &Self) -> Self;
49 fn max(&self, other: &Self) -> Self;
50 fn clamp(&self, mn: &Self, mx: &Self) -> Self;
54 fn zero() -> Self; // FIXME (#5527): This should be an associated constant
55 fn is_zero(&self) -> bool;
59 fn one() -> Self; // FIXME (#5527): This should be an associated constant
64 fn abs(&self) -> Self;
65 fn signum(&self) -> Self;
66 fn is_positive(&self) -> bool;
67 fn is_negative(&self) -> bool;
70 pub trait Unsigned: Num {}
72 // This should be moved into the default implementation for Signed::abs
73 pub fn abs<T:Ord + Zero + Neg<T>>(v: T) -> T {
74 if v < Zero::zero() { v.neg() } else { v }
77 pub trait Integer: Num
81 fn div(&self, other: &Self) -> Self;
82 fn modulo(&self, other: &Self) -> Self;
83 fn div_mod(&self, other: &Self) -> (Self,Self);
84 fn quot_rem(&self, other: &Self) -> (Self,Self);
86 fn gcd(&self, other: &Self) -> Self;
87 fn lcm(&self, other: &Self) -> Self;
89 fn is_multiple_of(&self, other: &Self) -> bool;
90 fn is_even(&self) -> bool;
91 fn is_odd(&self) -> bool;
95 fn floor(&self) -> Self;
96 fn ceil(&self) -> Self;
97 fn round(&self) -> Self;
98 fn trunc(&self) -> Self;
99 fn fract(&self) -> Self;
102 pub trait Fractional: Num
106 fn recip(&self) -> Self;
109 pub trait Algebraic {
110 fn pow(&self, n: Self) -> Self;
111 fn sqrt(&self) -> Self;
112 fn rsqrt(&self) -> Self;
113 fn cbrt(&self) -> Self;
114 fn hypot(&self, other: Self) -> Self;
117 pub trait Trigonometric {
118 fn sin(&self) -> Self;
119 fn cos(&self) -> Self;
120 fn tan(&self) -> Self;
121 fn asin(&self) -> Self;
122 fn acos(&self) -> Self;
123 fn atan(&self) -> Self;
124 fn atan2(&self, other: Self) -> Self;
127 pub trait Exponential {
128 fn exp(&self) -> Self;
129 fn exp2(&self) -> Self;
130 fn expm1(&self) -> Self;
131 fn log(&self) -> Self;
132 fn log2(&self) -> Self;
133 fn log10(&self) -> Self;
136 pub trait Hyperbolic: Exponential {
137 fn sinh(&self) -> Self;
138 fn cosh(&self) -> Self;
139 fn tanh(&self) -> Self;
143 /// Defines constants and methods common to real numbers
145 pub trait Real: Signed
151 // FIXME (#5527): These should be associated constants
154 fn frac_pi_2() -> Self;
155 fn frac_pi_3() -> Self;
156 fn frac_pi_4() -> Self;
157 fn frac_pi_6() -> Self;
158 fn frac_pi_8() -> Self;
159 fn frac_1_pi() -> Self;
160 fn frac_2_pi() -> Self;
161 fn frac_2_sqrtpi() -> Self;
163 fn frac_1_sqrt2() -> Self;
166 fn log10_e() -> Self;
170 // Angular conversions
171 fn to_degrees(&self) -> Self;
172 fn to_radians(&self) -> Self;
176 /// Methods that are harder to implement and not commonly used.
178 pub trait RealExt: Real {
179 // FIXME (#5527): usages of `int` should be replaced with an associated
180 // integer type once these are implemented
183 fn lgamma(&self) -> (int, Self);
184 fn tgamma(&self) -> Self;
187 fn j0(&self) -> Self;
188 fn j1(&self) -> Self;
189 fn jn(&self, n: int) -> Self;
190 fn y0(&self) -> Self;
191 fn y1(&self) -> Self;
192 fn yn(&self, n: int) -> Self;
196 /// Collects the bitwise operators under one trait.
198 pub trait Bitwise: Not<Self>
206 fn population_count(&self) -> Self;
207 fn leading_zeros(&self) -> Self;
208 fn trailing_zeros(&self) -> Self;
212 // FIXME (#5527): These should be associated constants
213 fn min_value() -> Self;
214 fn max_value() -> Self;
218 /// Specifies the available operations common to all of Rust's core numeric primitives.
219 /// These may not always make sense from a purely mathematical point of view, but
220 /// may be useful for systems programming.
222 pub trait Primitive: Num
231 // FIXME (#5527): These should be associated constants
237 /// A collection of traits relevant to primitive signed and unsigned integers
239 pub trait Int: Integer
245 /// Primitive floating point numbers
247 pub trait Float: Real
250 // FIXME (#5527): These should be associated constants
252 fn infinity() -> Self;
253 fn neg_infinity() -> Self;
254 fn neg_zero() -> Self;
256 fn is_NaN(&self) -> bool;
257 fn is_infinite(&self) -> bool;
258 fn is_finite(&self) -> bool;
260 fn mantissa_digits() -> uint;
262 fn epsilon() -> Self;
265 fn min_10_exp() -> int;
266 fn max_10_exp() -> int;
268 fn mul_add(&self, a: Self, b: Self) -> Self;
269 fn next_after(&self, other: Self) -> Self;
273 /// Cast from one machine scalar to another
278 /// let twenty: f32 = num::cast(0x14);
279 /// assert_eq!(twenty, 20f32);
283 pub fn cast<T:NumCast,U:NumCast>(n: T) -> U {
288 /// An interface for casting between machine scalars
291 fn from<T:NumCast>(n: T) -> Self;
293 fn to_u8(&self) -> u8;
294 fn to_u16(&self) -> u16;
295 fn to_u32(&self) -> u32;
296 fn to_u64(&self) -> u64;
297 fn to_uint(&self) -> uint;
299 fn to_i8(&self) -> i8;
300 fn to_i16(&self) -> i16;
301 fn to_i32(&self) -> i32;
302 fn to_i64(&self) -> i64;
303 fn to_int(&self) -> int;
305 fn to_f32(&self) -> f32;
306 fn to_f64(&self) -> f64;
307 fn to_float(&self) -> float;
310 macro_rules! impl_num_cast(
311 ($T:ty, $conv:ident) => (
312 impl NumCast for $T {
314 fn from<N:NumCast>(n: N) -> $T {
315 // `$conv` could be generated using `concat_idents!`, but that
316 // macro seems to be broken at the moment
320 #[inline(always)] fn to_u8(&self) -> u8 { *self as u8 }
321 #[inline(always)] fn to_u16(&self) -> u16 { *self as u16 }
322 #[inline(always)] fn to_u32(&self) -> u32 { *self as u32 }
323 #[inline(always)] fn to_u64(&self) -> u64 { *self as u64 }
324 #[inline(always)] fn to_uint(&self) -> uint { *self as uint }
326 #[inline(always)] fn to_i8(&self) -> i8 { *self as i8 }
327 #[inline(always)] fn to_i16(&self) -> i16 { *self as i16 }
328 #[inline(always)] fn to_i32(&self) -> i32 { *self as i32 }
329 #[inline(always)] fn to_i64(&self) -> i64 { *self as i64 }
330 #[inline(always)] fn to_int(&self) -> int { *self as int }
332 #[inline(always)] fn to_f32(&self) -> f32 { *self as f32 }
333 #[inline(always)] fn to_f64(&self) -> f64 { *self as f64 }
334 #[inline(always)] fn to_float(&self) -> float { *self as float }
339 impl_num_cast!(u8, to_u8)
340 impl_num_cast!(u16, to_u16)
341 impl_num_cast!(u32, to_u32)
342 impl_num_cast!(u64, to_u64)
343 impl_num_cast!(uint, to_uint)
344 impl_num_cast!(i8, to_i8)
345 impl_num_cast!(i16, to_i16)
346 impl_num_cast!(i32, to_i32)
347 impl_num_cast!(i64, to_i64)
348 impl_num_cast!(int, to_int)
349 impl_num_cast!(f32, to_f32)
350 impl_num_cast!(f64, to_f64)
351 impl_num_cast!(float, to_float)
353 pub trait ToStrRadix {
354 pub fn to_str_radix(&self, radix: uint) -> ~str;
357 pub trait FromStrRadix {
358 pub fn from_str_radix(str: &str, radix: uint) -> Option<Self>;
362 /// Calculates a power to a given radix, optimized for uint `pow` and `radix`.
364 /// Returns `radix^pow` as `T`.
367 /// Also returns `1` for `0^0`, despite that technically being an
368 /// undefined number. The reason for this is twofold:
369 /// - If code written to use this function cares about that special case, it's
370 /// probably going to catch it before making the call.
371 /// - If code written to use this function doesn't care about it, it's
372 /// probably assuming that `x^0` always equals `1`.
374 pub fn pow_with_uint<T:NumCast+One+Zero+Copy+Quot<T,T>+Mul<T,T>>(
375 radix: uint, pow: uint) -> T {
376 let _0: T = Zero::zero();
377 let _1: T = One::one();
379 if pow == 0u { return _1; }
380 if radix == 0u { return _0; }
381 let mut my_pow = pow;
383 let mut multiplier = cast(radix as int);
384 while (my_pow > 0u) {
385 if my_pow % 2u == 1u {
389 multiplier *= multiplier;
394 /// Helper function for testing numeric operations
396 pub fn test_num<T:Num + NumCast>(ten: T, two: T) {
397 assert_eq!(ten.add(&two), cast(12));
398 assert_eq!(ten.sub(&two), cast(8));
399 assert_eq!(ten.mul(&two), cast(20));
400 assert_eq!(ten.div(&two), cast(5));
401 assert_eq!(ten.modulo(&two), cast(0));
403 assert_eq!(ten.add(&two), ten + two);
404 assert_eq!(ten.sub(&two), ten - two);
405 assert_eq!(ten.mul(&two), ten * two);
406 assert_eq!(ten.div(&two), ten / two);
407 assert_eq!(ten.modulo(&two), ten % two);
412 pub fn test_num<T:Num + NumCast>(ten: T, two: T) {
413 assert_eq!(ten.add(&two), cast(12));
414 assert_eq!(ten.sub(&two), cast(8));
415 assert_eq!(ten.mul(&two), cast(20));
416 assert_eq!(ten.quot(&two), cast(5));
417 assert_eq!(ten.rem(&two), cast(0));
419 assert_eq!(ten.add(&two), ten + two);
420 assert_eq!(ten.sub(&two), ten - two);
421 assert_eq!(ten.mul(&two), ten * two);
422 assert_eq!(ten.quot(&two), ten / two);
423 assert_eq!(ten.rem(&two), ten % two);
426 macro_rules! test_cast_20(
430 assert_eq!(20u, _20.to_uint());
431 assert_eq!(20u8, _20.to_u8());
432 assert_eq!(20u16, _20.to_u16());
433 assert_eq!(20u32, _20.to_u32());
434 assert_eq!(20u64, _20.to_u64());
435 assert_eq!(20i, _20.to_int());
436 assert_eq!(20i8, _20.to_i8());
437 assert_eq!(20i16, _20.to_i16());
438 assert_eq!(20i32, _20.to_i32());
439 assert_eq!(20i64, _20.to_i64());
440 assert_eq!(20f, _20.to_float());
441 assert_eq!(20f32, _20.to_f32());
442 assert_eq!(20f64, _20.to_f64());
444 assert_eq!(_20, NumCast::from(20u));
445 assert_eq!(_20, NumCast::from(20u8));
446 assert_eq!(_20, NumCast::from(20u16));
447 assert_eq!(_20, NumCast::from(20u32));
448 assert_eq!(_20, NumCast::from(20u64));
449 assert_eq!(_20, NumCast::from(20i));
450 assert_eq!(_20, NumCast::from(20i8));
451 assert_eq!(_20, NumCast::from(20i16));
452 assert_eq!(_20, NumCast::from(20i32));
453 assert_eq!(_20, NumCast::from(20i64));
454 assert_eq!(_20, NumCast::from(20f));
455 assert_eq!(_20, NumCast::from(20f32));
456 assert_eq!(_20, NumCast::from(20f64));
458 assert_eq!(_20, cast(20u));
459 assert_eq!(_20, cast(20u8));
460 assert_eq!(_20, cast(20u16));
461 assert_eq!(_20, cast(20u32));
462 assert_eq!(_20, cast(20u64));
463 assert_eq!(_20, cast(20i));
464 assert_eq!(_20, cast(20i8));
465 assert_eq!(_20, cast(20i16));
466 assert_eq!(_20, cast(20i32));
467 assert_eq!(_20, cast(20i64));
468 assert_eq!(_20, cast(20f));
469 assert_eq!(_20, cast(20f32));
470 assert_eq!(_20, cast(20f64));
474 #[test] fn test_u8_cast() { test_cast_20!(20u8) }
475 #[test] fn test_u16_cast() { test_cast_20!(20u16) }
476 #[test] fn test_u32_cast() { test_cast_20!(20u32) }
477 #[test] fn test_u64_cast() { test_cast_20!(20u64) }
478 #[test] fn test_uint_cast() { test_cast_20!(20u) }
479 #[test] fn test_i8_cast() { test_cast_20!(20i8) }
480 #[test] fn test_i16_cast() { test_cast_20!(20i16) }
481 #[test] fn test_i32_cast() { test_cast_20!(20i32) }
482 #[test] fn test_i64_cast() { test_cast_20!(20i64) }
483 #[test] fn test_int_cast() { test_cast_20!(20i) }
484 #[test] fn test_f32_cast() { test_cast_20!(20f32) }
485 #[test] fn test_f64_cast() { test_cast_20!(20f64) }
486 #[test] fn test_float_cast() { test_cast_20!(20f) }