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 //! Numeric traits and functions for generic mathematics.
13 //! These are implemented for the primitive numeric types in `std::{u8, u16,
14 //! u32, u64, uint, i8, i16, i32, i64, int, f32, f64, float}`.
16 #[allow(missing_doc)];
18 use cmp::{Eq, ApproxEq, Ord};
19 use ops::{Add, Sub, Mul, Div, Rem, Neg};
20 use ops::{Not, BitAnd, BitOr, BitXor, Shl, Shr};
21 use option::{Option, Some, None};
22 use unstable::intrinsics;
26 /// The base trait for numeric types
27 pub trait Num: Eq + Zero + One
35 pub trait IntConvertible {
36 fn to_int(&self) -> int;
37 fn from_int(n: int) -> Self;
40 pub trait Orderable: Ord {
41 // These should be methods on `Ord`, with overridable default implementations. We don't want
42 // to encumber all implementors of Ord by requiring them to implement these functions, but at
43 // the same time we want to be able to take advantage of the speed of the specific numeric
44 // functions (like the `fmin` and `fmax` intrinsics).
45 fn min(&self, other: &Self) -> Self;
46 fn max(&self, other: &Self) -> Self;
47 fn clamp(&self, mn: &Self, mx: &Self) -> Self;
50 #[inline(always)] pub fn min<T: Orderable>(x: T, y: T) -> T { x.min(&y) }
51 #[inline(always)] pub fn max<T: Orderable>(x: T, y: T) -> T { x.max(&y) }
52 #[inline(always)] pub fn clamp<T: Orderable>(value: T, mn: T, mx: T) -> T { value.clamp(&mn, &mx) }
55 fn zero() -> Self; // FIXME (#5527): This should be an associated constant
56 fn is_zero(&self) -> bool;
59 #[inline(always)] pub fn zero<T: Zero>() -> T { Zero::zero() }
62 fn one() -> Self; // FIXME (#5527): This should be an associated constant
65 #[inline(always)] pub fn one<T: One>() -> T { One::one() }
69 fn abs(&self) -> Self;
70 fn abs_sub(&self, other: &Self) -> Self;
71 fn signum(&self) -> Self;
73 fn is_positive(&self) -> bool;
74 fn is_negative(&self) -> bool;
77 #[inline(always)] pub fn abs<T: Signed>(value: T) -> T { value.abs() }
78 #[inline(always)] pub fn abs_sub<T: Signed>(x: T, y: T) -> T { x.abs_sub(&y) }
79 #[inline(always)] pub fn signum<T: Signed>(value: T) -> T { value.signum() }
81 pub trait Unsigned: Num {}
83 pub trait Integer: Num
87 fn div_rem(&self, other: &Self) -> (Self,Self);
89 fn div_floor(&self, other: &Self) -> Self;
90 fn mod_floor(&self, other: &Self) -> Self;
91 fn div_mod_floor(&self, other: &Self) -> (Self,Self);
93 fn gcd(&self, other: &Self) -> Self;
94 fn lcm(&self, other: &Self) -> Self;
96 fn is_multiple_of(&self, other: &Self) -> bool;
97 fn is_even(&self) -> bool;
98 fn is_odd(&self) -> bool;
101 #[inline(always)] pub fn gcd<T: Integer>(x: T, y: T) -> T { x.gcd(&y) }
102 #[inline(always)] pub fn lcm<T: Integer>(x: T, y: T) -> T { x.lcm(&y) }
105 fn floor(&self) -> Self;
106 fn ceil(&self) -> Self;
107 fn round(&self) -> Self;
108 fn trunc(&self) -> Self;
109 fn fract(&self) -> Self;
112 pub trait Fractional: Num
116 fn recip(&self) -> Self;
119 pub trait Algebraic {
120 fn pow(&self, n: &Self) -> Self;
121 fn sqrt(&self) -> Self;
122 fn rsqrt(&self) -> Self;
123 fn cbrt(&self) -> Self;
124 fn hypot(&self, other: &Self) -> Self;
127 #[inline(always)] pub fn pow<T: Algebraic>(value: T, n: T) -> T { value.pow(&n) }
128 #[inline(always)] pub fn sqrt<T: Algebraic>(value: T) -> T { value.sqrt() }
129 #[inline(always)] pub fn rsqrt<T: Algebraic>(value: T) -> T { value.rsqrt() }
130 #[inline(always)] pub fn cbrt<T: Algebraic>(value: T) -> T { value.cbrt() }
131 #[inline(always)] pub fn hypot<T: Algebraic>(x: T, y: T) -> T { x.hypot(&y) }
133 pub trait Trigonometric {
134 fn sin(&self) -> Self;
135 fn cos(&self) -> Self;
136 fn tan(&self) -> Self;
138 fn asin(&self) -> Self;
139 fn acos(&self) -> Self;
140 fn atan(&self) -> Self;
142 fn atan2(&self, other: &Self) -> Self;
143 fn sin_cos(&self) -> (Self, Self);
146 #[inline(always)] pub fn sin<T: Trigonometric>(value: T) -> T { value.sin() }
147 #[inline(always)] pub fn cos<T: Trigonometric>(value: T) -> T { value.cos() }
148 #[inline(always)] pub fn tan<T: Trigonometric>(value: T) -> T { value.tan() }
150 #[inline(always)] pub fn asin<T: Trigonometric>(value: T) -> T { value.asin() }
151 #[inline(always)] pub fn acos<T: Trigonometric>(value: T) -> T { value.acos() }
152 #[inline(always)] pub fn atan<T: Trigonometric>(value: T) -> T { value.atan() }
154 #[inline(always)] pub fn atan2<T: Trigonometric>(x: T, y: T) -> T { x.atan2(&y) }
155 #[inline(always)] pub fn sin_cos<T: Trigonometric>(value: T) -> (T, T) { value.sin_cos() }
157 pub trait Exponential {
158 fn exp(&self) -> Self;
159 fn exp2(&self) -> Self;
161 fn ln(&self) -> Self;
162 fn log(&self, base: &Self) -> Self;
163 fn log2(&self) -> Self;
164 fn log10(&self) -> Self;
167 #[inline(always)] pub fn exp<T: Exponential>(value: T) -> T { value.exp() }
168 #[inline(always)] pub fn exp2<T: Exponential>(value: T) -> T { value.exp2() }
170 #[inline(always)] pub fn ln<T: Exponential>(value: T) -> T { value.ln() }
171 #[inline(always)] pub fn log<T: Exponential>(value: T, base: T) -> T { value.log(&base) }
172 #[inline(always)] pub fn log2<T: Exponential>(value: T) -> T { value.log2() }
173 #[inline(always)] pub fn log10<T: Exponential>(value: T) -> T { value.log10() }
175 pub trait Hyperbolic: Exponential {
176 fn sinh(&self) -> Self;
177 fn cosh(&self) -> Self;
178 fn tanh(&self) -> Self;
180 fn asinh(&self) -> Self;
181 fn acosh(&self) -> Self;
182 fn atanh(&self) -> Self;
185 #[inline(always)] pub fn sinh<T: Hyperbolic>(value: T) -> T { value.sinh() }
186 #[inline(always)] pub fn cosh<T: Hyperbolic>(value: T) -> T { value.cosh() }
187 #[inline(always)] pub fn tanh<T: Hyperbolic>(value: T) -> T { value.tanh() }
189 #[inline(always)] pub fn asinh<T: Hyperbolic>(value: T) -> T { value.asinh() }
190 #[inline(always)] pub fn acosh<T: Hyperbolic>(value: T) -> T { value.acosh() }
191 #[inline(always)] pub fn atanh<T: Hyperbolic>(value: T) -> T { value.atanh() }
193 /// Defines constants and methods common to real numbers
194 pub trait Real: Signed
200 // FIXME (#5527): These should be associated constants
203 fn frac_pi_2() -> Self;
204 fn frac_pi_3() -> Self;
205 fn frac_pi_4() -> Self;
206 fn frac_pi_6() -> Self;
207 fn frac_pi_8() -> Self;
208 fn frac_1_pi() -> Self;
209 fn frac_2_pi() -> Self;
210 fn frac_2_sqrtpi() -> Self;
212 fn frac_1_sqrt2() -> Self;
215 fn log10_e() -> Self;
219 // Angular conversions
220 fn to_degrees(&self) -> Self;
221 fn to_radians(&self) -> Self;
224 /// Methods that are harder to implement and not commonly used.
225 pub trait RealExt: Real {
226 // FIXME (#5527): usages of `int` should be replaced with an associated
227 // integer type once these are implemented
230 fn lgamma(&self) -> (int, Self);
231 fn tgamma(&self) -> Self;
234 fn j0(&self) -> Self;
235 fn j1(&self) -> Self;
236 fn jn(&self, n: int) -> Self;
237 fn y0(&self) -> Self;
238 fn y1(&self) -> Self;
239 fn yn(&self, n: int) -> Self;
242 /// Collects the bitwise operators under one trait.
243 pub trait Bitwise: Not<Self>
251 fn population_count(&self) -> Self;
252 fn leading_zeros(&self) -> Self;
253 fn trailing_zeros(&self) -> Self;
257 // FIXME (#5527): These should be associated constants
258 fn min_value() -> Self;
259 fn max_value() -> Self;
262 /// Specifies the available operations common to all of Rust's core numeric primitives.
263 /// These may not always make sense from a purely mathematical point of view, but
264 /// may be useful for systems programming.
265 pub trait Primitive: Num
274 // FIXME (#5527): These should be associated constants
279 /// A collection of traits relevant to primitive signed and unsigned integers
280 pub trait Int: Integer
285 /// Used for representing the classification of floating point numbers
287 pub enum FPCategory {
288 /// "Not a Number", often obtained by dividing by zero
290 /// Positive or negative infinity
292 /// Positive or negative zero
294 /// De-normalized floating point representation (less precise than `FPNormal`)
296 /// A regular floating point number
300 /// Primitive floating point numbers
301 pub trait Float: Real
305 // FIXME (#5527): These should be associated constants
307 fn infinity() -> Self;
308 fn neg_infinity() -> Self;
309 fn neg_zero() -> Self;
311 fn is_NaN(&self) -> bool;
312 fn is_infinite(&self) -> bool;
313 fn is_finite(&self) -> bool;
314 fn is_normal(&self) -> bool;
315 fn classify(&self) -> FPCategory;
317 fn mantissa_digits() -> uint;
319 fn epsilon() -> Self;
322 fn min_10_exp() -> int;
323 fn max_10_exp() -> int;
325 fn ldexp(x: Self, exp: int) -> Self;
326 fn frexp(&self) -> (Self, int);
328 fn exp_m1(&self) -> Self;
329 fn ln_1p(&self) -> Self;
330 fn mul_add(&self, a: Self, b: Self) -> Self;
331 fn next_after(&self, other: Self) -> Self;
334 #[inline(always)] pub fn exp_m1<T: Float>(value: T) -> T { value.exp_m1() }
335 #[inline(always)] pub fn ln_1p<T: Float>(value: T) -> T { value.ln_1p() }
336 #[inline(always)] pub fn mul_add<T: Float>(a: T, b: T, c: T) -> T { a.mul_add(b, c) }
338 /// Cast from one machine scalar to another
343 /// let twenty: f32 = num::cast(0x14);
344 /// assert_eq!(twenty, 20f32);
348 pub fn cast<T:NumCast,U:NumCast>(n: T) -> U {
352 /// An interface for casting between machine scalars
354 fn from<T:NumCast>(n: T) -> Self;
356 fn to_u8(&self) -> u8;
357 fn to_u16(&self) -> u16;
358 fn to_u32(&self) -> u32;
359 fn to_u64(&self) -> u64;
360 fn to_uint(&self) -> uint;
362 fn to_i8(&self) -> i8;
363 fn to_i16(&self) -> i16;
364 fn to_i32(&self) -> i32;
365 fn to_i64(&self) -> i64;
366 fn to_int(&self) -> int;
368 fn to_f32(&self) -> f32;
369 fn to_f64(&self) -> f64;
370 fn to_float(&self) -> float;
373 macro_rules! impl_num_cast(
374 ($T:ty, $conv:ident) => (
375 impl NumCast for $T {
377 fn from<N:NumCast>(n: N) -> $T {
378 // `$conv` could be generated using `concat_idents!`, but that
379 // macro seems to be broken at the moment
383 #[inline] fn to_u8(&self) -> u8 { *self as u8 }
384 #[inline] fn to_u16(&self) -> u16 { *self as u16 }
385 #[inline] fn to_u32(&self) -> u32 { *self as u32 }
386 #[inline] fn to_u64(&self) -> u64 { *self as u64 }
387 #[inline] fn to_uint(&self) -> uint { *self as uint }
389 #[inline] fn to_i8(&self) -> i8 { *self as i8 }
390 #[inline] fn to_i16(&self) -> i16 { *self as i16 }
391 #[inline] fn to_i32(&self) -> i32 { *self as i32 }
392 #[inline] fn to_i64(&self) -> i64 { *self as i64 }
393 #[inline] fn to_int(&self) -> int { *self as int }
395 #[inline] fn to_f32(&self) -> f32 { *self as f32 }
396 #[inline] fn to_f64(&self) -> f64 { *self as f64 }
397 #[inline] fn to_float(&self) -> float { *self as float }
402 impl_num_cast!(u8, to_u8)
403 impl_num_cast!(u16, to_u16)
404 impl_num_cast!(u32, to_u32)
405 impl_num_cast!(u64, to_u64)
406 impl_num_cast!(uint, to_uint)
407 impl_num_cast!(i8, to_i8)
408 impl_num_cast!(i16, to_i16)
409 impl_num_cast!(i32, to_i32)
410 impl_num_cast!(i64, to_i64)
411 impl_num_cast!(int, to_int)
412 impl_num_cast!(f32, to_f32)
413 impl_num_cast!(f64, to_f64)
414 impl_num_cast!(float, to_float)
416 pub trait ToStrRadix {
417 fn to_str_radix(&self, radix: uint) -> ~str;
420 pub trait FromStrRadix {
421 fn from_str_radix(str: &str, radix: uint) -> Option<Self>;
424 /// Calculates a power to a given radix, optimized for uint `pow` and `radix`.
426 /// Returns `radix^pow` as `T`.
429 /// Also returns `1` for `0^0`, despite that technically being an
430 /// undefined number. The reason for this is twofold:
431 /// - If code written to use this function cares about that special case, it's
432 /// probably going to catch it before making the call.
433 /// - If code written to use this function doesn't care about it, it's
434 /// probably assuming that `x^0` always equals `1`.
436 pub fn pow_with_uint<T:NumCast+One+Zero+Div<T,T>+Mul<T,T>>(radix: uint, pow: uint) -> T {
437 let _0: T = Zero::zero();
438 let _1: T = One::one();
440 if pow == 0u { return _1; }
441 if radix == 0u { return _0; }
442 let mut my_pow = pow;
444 let mut multiplier = cast(radix);
445 while (my_pow > 0u) {
446 if my_pow % 2u == 1u {
447 total = total * multiplier;
449 my_pow = my_pow / 2u;
450 multiplier = multiplier * multiplier;
455 impl<T: Zero + 'static> Zero for @mut T {
456 fn zero() -> @mut T { @mut Zero::zero() }
457 fn is_zero(&self) -> bool { (**self).is_zero() }
460 impl<T: Zero + 'static> Zero for @T {
461 fn zero() -> @T { @Zero::zero() }
462 fn is_zero(&self) -> bool { (**self).is_zero() }
465 impl<T: Zero> Zero for ~T {
466 fn zero() -> ~T { ~Zero::zero() }
467 fn is_zero(&self) -> bool { (**self).is_zero() }
470 /// Saturating math operations
471 pub trait Saturating {
472 /// Saturating addition operator.
473 /// Returns a+b, saturating at the numeric bounds instead of overflowing.
474 fn saturating_add(self, v: Self) -> Self;
476 /// Saturating subtraction operator.
477 /// Returns a-b, saturating at the numeric bounds instead of overflowing.
478 fn saturating_sub(self, v: Self) -> Self;
481 impl<T: CheckedAdd+CheckedSub+Zero+Ord+Bounded> Saturating for T {
483 fn saturating_add(self, v: T) -> T {
484 match self.checked_add(&v) {
486 None => if v >= Zero::zero() {
487 Bounded::max_value::<T>()
489 Bounded::min_value::<T>()
495 fn saturating_sub(self, v: T) -> T {
496 match self.checked_sub(&v) {
498 None => if v >= Zero::zero() {
499 Bounded::min_value::<T>()
501 Bounded::max_value::<T>()
507 pub trait CheckedAdd: Add<Self, Self> {
508 fn checked_add(&self, v: &Self) -> Option<Self>;
511 impl CheckedAdd for i8 {
513 fn checked_add(&self, v: &i8) -> Option<i8> {
515 let (x, y) = intrinsics::i8_add_with_overflow(*self, *v);
516 if y { None } else { Some(x) }
521 impl CheckedAdd for i16 {
523 fn checked_add(&self, v: &i16) -> Option<i16> {
525 let (x, y) = intrinsics::i16_add_with_overflow(*self, *v);
526 if y { None } else { Some(x) }
531 impl CheckedAdd for i32 {
533 fn checked_add(&self, v: &i32) -> Option<i32> {
535 let (x, y) = intrinsics::i32_add_with_overflow(*self, *v);
536 if y { None } else { Some(x) }
541 impl CheckedAdd for i64 {
543 fn checked_add(&self, v: &i64) -> Option<i64> {
545 let (x, y) = intrinsics::i64_add_with_overflow(*self, *v);
546 if y { None } else { Some(x) }
551 #[cfg(target_word_size = "32")]
552 impl CheckedAdd for int {
554 fn checked_add(&self, v: &int) -> Option<int> {
556 let (x, y) = intrinsics::i32_add_with_overflow(*self as i32, *v as i32);
557 if y { None } else { Some(x as int) }
562 #[cfg(target_word_size = "64")]
563 impl CheckedAdd for int {
565 fn checked_add(&self, v: &int) -> Option<int> {
567 let (x, y) = intrinsics::i64_add_with_overflow(*self as i64, *v as i64);
568 if y { None } else { Some(x as int) }
573 impl CheckedAdd for u8 {
575 fn checked_add(&self, v: &u8) -> Option<u8> {
577 let (x, y) = intrinsics::u8_add_with_overflow(*self, *v);
578 if y { None } else { Some(x) }
583 impl CheckedAdd for u16 {
585 fn checked_add(&self, v: &u16) -> Option<u16> {
587 let (x, y) = intrinsics::u16_add_with_overflow(*self, *v);
588 if y { None } else { Some(x) }
593 impl CheckedAdd for u32 {
595 fn checked_add(&self, v: &u32) -> Option<u32> {
597 let (x, y) = intrinsics::u32_add_with_overflow(*self, *v);
598 if y { None } else { Some(x) }
603 impl CheckedAdd for u64 {
605 fn checked_add(&self, v: &u64) -> Option<u64> {
607 let (x, y) = intrinsics::u64_add_with_overflow(*self, *v);
608 if y { None } else { Some(x) }
613 #[cfg(target_word_size = "32")]
614 impl CheckedAdd for uint {
616 fn checked_add(&self, v: &uint) -> Option<uint> {
618 let (x, y) = intrinsics::u32_add_with_overflow(*self as u32, *v as u32);
619 if y { None } else { Some(x as uint) }
624 #[cfg(target_word_size = "64")]
625 impl CheckedAdd for uint {
627 fn checked_add(&self, v: &uint) -> Option<uint> {
629 let (x, y) = intrinsics::u64_add_with_overflow(*self as u64, *v as u64);
630 if y { None } else { Some(x as uint) }
635 pub trait CheckedSub: Sub<Self, Self> {
636 fn checked_sub(&self, v: &Self) -> Option<Self>;
639 impl CheckedSub for i8 {
641 fn checked_sub(&self, v: &i8) -> Option<i8> {
643 let (x, y) = intrinsics::i8_sub_with_overflow(*self, *v);
644 if y { None } else { Some(x) }
649 impl CheckedSub for i16 {
651 fn checked_sub(&self, v: &i16) -> Option<i16> {
653 let (x, y) = intrinsics::i16_sub_with_overflow(*self, *v);
654 if y { None } else { Some(x) }
659 impl CheckedSub for i32 {
661 fn checked_sub(&self, v: &i32) -> Option<i32> {
663 let (x, y) = intrinsics::i32_sub_with_overflow(*self, *v);
664 if y { None } else { Some(x) }
669 impl CheckedSub for i64 {
671 fn checked_sub(&self, v: &i64) -> Option<i64> {
673 let (x, y) = intrinsics::i64_sub_with_overflow(*self, *v);
674 if y { None } else { Some(x) }
679 #[cfg(target_word_size = "32")]
680 impl CheckedSub for int {
682 fn checked_sub(&self, v: &int) -> Option<int> {
684 let (x, y) = intrinsics::i32_sub_with_overflow(*self as i32, *v as i32);
685 if y { None } else { Some(x as int) }
690 #[cfg(target_word_size = "64")]
691 impl CheckedSub for int {
693 fn checked_sub(&self, v: &int) -> Option<int> {
695 let (x, y) = intrinsics::i64_sub_with_overflow(*self as i64, *v as i64);
696 if y { None } else { Some(x as int) }
701 impl CheckedSub for u8 {
703 fn checked_sub(&self, v: &u8) -> Option<u8> {
705 let (x, y) = intrinsics::u8_sub_with_overflow(*self, *v);
706 if y { None } else { Some(x) }
711 impl CheckedSub for u16 {
713 fn checked_sub(&self, v: &u16) -> Option<u16> {
715 let (x, y) = intrinsics::u16_sub_with_overflow(*self, *v);
716 if y { None } else { Some(x) }
721 impl CheckedSub for u32 {
723 fn checked_sub(&self, v: &u32) -> Option<u32> {
725 let (x, y) = intrinsics::u32_sub_with_overflow(*self, *v);
726 if y { None } else { Some(x) }
731 impl CheckedSub for u64 {
733 fn checked_sub(&self, v: &u64) -> Option<u64> {
735 let (x, y) = intrinsics::u64_sub_with_overflow(*self, *v);
736 if y { None } else { Some(x) }
741 #[cfg(target_word_size = "32")]
742 impl CheckedSub for uint {
744 fn checked_sub(&self, v: &uint) -> Option<uint> {
746 let (x, y) = intrinsics::u32_sub_with_overflow(*self as u32, *v as u32);
747 if y { None } else { Some(x as uint) }
752 #[cfg(target_word_size = "64")]
753 impl CheckedSub for uint {
755 fn checked_sub(&self, v: &uint) -> Option<uint> {
757 let (x, y) = intrinsics::u64_sub_with_overflow(*self as u64, *v as u64);
758 if y { None } else { Some(x as uint) }
763 pub trait CheckedMul: Mul<Self, Self> {
764 fn checked_mul(&self, v: &Self) -> Option<Self>;
767 impl CheckedMul for i8 {
769 fn checked_mul(&self, v: &i8) -> Option<i8> {
771 let (x, y) = intrinsics::i8_mul_with_overflow(*self, *v);
772 if y { None } else { Some(x) }
777 impl CheckedMul for i16 {
779 fn checked_mul(&self, v: &i16) -> Option<i16> {
781 let (x, y) = intrinsics::i16_mul_with_overflow(*self, *v);
782 if y { None } else { Some(x) }
787 impl CheckedMul for i32 {
789 fn checked_mul(&self, v: &i32) -> Option<i32> {
791 let (x, y) = intrinsics::i32_mul_with_overflow(*self, *v);
792 if y { None } else { Some(x) }
797 // FIXME: #8449: should not be disabled on 32-bit
798 #[cfg(target_word_size = "64")]
799 impl CheckedMul for i64 {
801 fn checked_mul(&self, v: &i64) -> Option<i64> {
803 let (x, y) = intrinsics::i64_mul_with_overflow(*self, *v);
804 if y { None } else { Some(x) }
809 #[cfg(target_word_size = "32")]
810 impl CheckedMul for int {
812 fn checked_mul(&self, v: &int) -> Option<int> {
814 let (x, y) = intrinsics::i32_mul_with_overflow(*self as i32, *v as i32);
815 if y { None } else { Some(x as int) }
820 #[cfg(target_word_size = "64")]
821 impl CheckedMul for int {
823 fn checked_mul(&self, v: &int) -> Option<int> {
825 let (x, y) = intrinsics::i64_mul_with_overflow(*self as i64, *v as i64);
826 if y { None } else { Some(x as int) }
831 impl CheckedMul for u8 {
833 fn checked_mul(&self, v: &u8) -> Option<u8> {
835 let (x, y) = intrinsics::u8_mul_with_overflow(*self, *v);
836 if y { None } else { Some(x) }
841 impl CheckedMul for u16 {
843 fn checked_mul(&self, v: &u16) -> Option<u16> {
845 let (x, y) = intrinsics::u16_mul_with_overflow(*self, *v);
846 if y { None } else { Some(x) }
851 impl CheckedMul for u32 {
853 fn checked_mul(&self, v: &u32) -> Option<u32> {
855 let (x, y) = intrinsics::u32_mul_with_overflow(*self, *v);
856 if y { None } else { Some(x) }
861 // FIXME: #8449: should not be disabled on 32-bit
862 #[cfg(target_word_size = "64")]
863 impl CheckedMul for u64 {
865 fn checked_mul(&self, v: &u64) -> Option<u64> {
867 let (x, y) = intrinsics::u64_mul_with_overflow(*self, *v);
868 if y { None } else { Some(x) }
873 #[cfg(target_word_size = "32")]
874 impl CheckedMul for uint {
876 fn checked_mul(&self, v: &uint) -> Option<uint> {
878 let (x, y) = intrinsics::u32_mul_with_overflow(*self as u32, *v as u32);
879 if y { None } else { Some(x as uint) }
884 #[cfg(target_word_size = "64")]
885 impl CheckedMul for uint {
887 fn checked_mul(&self, v: &uint) -> Option<uint> {
889 let (x, y) = intrinsics::u64_mul_with_overflow(*self as u64, *v as u64);
890 if y { None } else { Some(x as uint) }
895 pub trait CheckedDiv: Div<Self, Self> {
896 fn checked_div(&self, v: &Self) -> Option<Self>;
899 /// Helper function for testing numeric operations
901 pub fn test_num<T:Num + NumCast>(ten: T, two: T) {
902 assert_eq!(ten.add(&two), cast(12));
903 assert_eq!(ten.sub(&two), cast(8));
904 assert_eq!(ten.mul(&two), cast(20));
905 assert_eq!(ten.div(&two), cast(5));
906 assert_eq!(ten.rem(&two), cast(0));
908 assert_eq!(ten.add(&two), ten + two);
909 assert_eq!(ten.sub(&two), ten - two);
910 assert_eq!(ten.mul(&two), ten * two);
911 assert_eq!(ten.div(&two), ten / two);
912 assert_eq!(ten.rem(&two), ten % two);
921 macro_rules! test_cast_20(
925 assert_eq!(20u, _20.to_uint());
926 assert_eq!(20u8, _20.to_u8());
927 assert_eq!(20u16, _20.to_u16());
928 assert_eq!(20u32, _20.to_u32());
929 assert_eq!(20u64, _20.to_u64());
930 assert_eq!(20i, _20.to_int());
931 assert_eq!(20i8, _20.to_i8());
932 assert_eq!(20i16, _20.to_i16());
933 assert_eq!(20i32, _20.to_i32());
934 assert_eq!(20i64, _20.to_i64());
935 assert_eq!(20f, _20.to_float());
936 assert_eq!(20f32, _20.to_f32());
937 assert_eq!(20f64, _20.to_f64());
939 assert_eq!(_20, NumCast::from(20u));
940 assert_eq!(_20, NumCast::from(20u8));
941 assert_eq!(_20, NumCast::from(20u16));
942 assert_eq!(_20, NumCast::from(20u32));
943 assert_eq!(_20, NumCast::from(20u64));
944 assert_eq!(_20, NumCast::from(20i));
945 assert_eq!(_20, NumCast::from(20i8));
946 assert_eq!(_20, NumCast::from(20i16));
947 assert_eq!(_20, NumCast::from(20i32));
948 assert_eq!(_20, NumCast::from(20i64));
949 assert_eq!(_20, NumCast::from(20f));
950 assert_eq!(_20, NumCast::from(20f32));
951 assert_eq!(_20, NumCast::from(20f64));
953 assert_eq!(_20, cast(20u));
954 assert_eq!(_20, cast(20u8));
955 assert_eq!(_20, cast(20u16));
956 assert_eq!(_20, cast(20u32));
957 assert_eq!(_20, cast(20u64));
958 assert_eq!(_20, cast(20i));
959 assert_eq!(_20, cast(20i8));
960 assert_eq!(_20, cast(20i16));
961 assert_eq!(_20, cast(20i32));
962 assert_eq!(_20, cast(20i64));
963 assert_eq!(_20, cast(20f));
964 assert_eq!(_20, cast(20f32));
965 assert_eq!(_20, cast(20f64));
969 #[test] fn test_u8_cast() { test_cast_20!(20u8) }
970 #[test] fn test_u16_cast() { test_cast_20!(20u16) }
971 #[test] fn test_u32_cast() { test_cast_20!(20u32) }
972 #[test] fn test_u64_cast() { test_cast_20!(20u64) }
973 #[test] fn test_uint_cast() { test_cast_20!(20u) }
974 #[test] fn test_i8_cast() { test_cast_20!(20i8) }
975 #[test] fn test_i16_cast() { test_cast_20!(20i16) }
976 #[test] fn test_i32_cast() { test_cast_20!(20i32) }
977 #[test] fn test_i64_cast() { test_cast_20!(20i64) }
978 #[test] fn test_int_cast() { test_cast_20!(20i) }
979 #[test] fn test_f32_cast() { test_cast_20!(20f32) }
980 #[test] fn test_f64_cast() { test_cast_20!(20f64) }
981 #[test] fn test_float_cast() { test_cast_20!(20f) }
984 fn test_saturating_add_uint() {
986 assert_eq!(3u.saturating_add(5u), 8u);
987 assert_eq!(3u.saturating_add(max_value-1), max_value);
988 assert_eq!(max_value.saturating_add(max_value), max_value);
989 assert_eq!((max_value-2).saturating_add(1), max_value-1);
993 fn test_saturating_sub_uint() {
995 assert_eq!(5u.saturating_sub(3u), 2u);
996 assert_eq!(3u.saturating_sub(5u), 0u);
997 assert_eq!(0u.saturating_sub(1u), 0u);
998 assert_eq!((max_value-1).saturating_sub(max_value), 0);
1002 fn test_saturating_add_int() {
1003 use int::{min_value,max_value};
1004 assert_eq!(3i.saturating_add(5i), 8i);
1005 assert_eq!(3i.saturating_add(max_value-1), max_value);
1006 assert_eq!(max_value.saturating_add(max_value), max_value);
1007 assert_eq!((max_value-2).saturating_add(1), max_value-1);
1008 assert_eq!(3i.saturating_add(-5i), -2i);
1009 assert_eq!(min_value.saturating_add(-1i), min_value);
1010 assert_eq!((-2i).saturating_add(-max_value), min_value);
1014 fn test_saturating_sub_int() {
1015 use int::{min_value,max_value};
1016 assert_eq!(3i.saturating_sub(5i), -2i);
1017 assert_eq!(min_value.saturating_sub(1i), min_value);
1018 assert_eq!((-2i).saturating_sub(max_value), min_value);
1019 assert_eq!(3i.saturating_sub(-5i), 8i);
1020 assert_eq!(3i.saturating_sub(-(max_value-1)), max_value);
1021 assert_eq!(max_value.saturating_sub(-max_value), max_value);
1022 assert_eq!((max_value-2).saturating_sub(-1), max_value-1);
1026 fn test_checked_add() {
1027 let five_less = uint::max_value - 5;
1028 assert_eq!(five_less.checked_add(&0), Some(uint::max_value - 5));
1029 assert_eq!(five_less.checked_add(&1), Some(uint::max_value - 4));
1030 assert_eq!(five_less.checked_add(&2), Some(uint::max_value - 3));
1031 assert_eq!(five_less.checked_add(&3), Some(uint::max_value - 2));
1032 assert_eq!(five_less.checked_add(&4), Some(uint::max_value - 1));
1033 assert_eq!(five_less.checked_add(&5), Some(uint::max_value));
1034 assert_eq!(five_less.checked_add(&6), None);
1035 assert_eq!(five_less.checked_add(&7), None);
1039 fn test_checked_sub() {
1040 assert_eq!(5u.checked_sub(&0), Some(5));
1041 assert_eq!(5u.checked_sub(&1), Some(4));
1042 assert_eq!(5u.checked_sub(&2), Some(3));
1043 assert_eq!(5u.checked_sub(&3), Some(2));
1044 assert_eq!(5u.checked_sub(&4), Some(1));
1045 assert_eq!(5u.checked_sub(&5), Some(0));
1046 assert_eq!(5u.checked_sub(&6), None);
1047 assert_eq!(5u.checked_sub(&7), None);
1051 fn test_checked_mul() {
1052 let third = uint::max_value / 3;
1053 assert_eq!(third.checked_mul(&0), Some(0));
1054 assert_eq!(third.checked_mul(&1), Some(third));
1055 assert_eq!(third.checked_mul(&2), Some(third * 2));
1056 assert_eq!(third.checked_mul(&3), Some(third * 3));
1057 assert_eq!(third.checked_mul(&4), None);