]> git.lizzy.rs Git - rust.git/blob - src/libstd/num/num.rs
auto merge of #8459 : thestinger/rust/checked, r=graydon
[rust.git] / src / libstd / num / num.rs
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.
4 //
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.
10
11 //! Numeric traits and functions for generic mathematics.
12 //!
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}`.
15
16 #[allow(missing_doc)];
17
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;
23
24 pub mod strconv;
25
26 /// The base trait for numeric types
27 pub trait Num: Eq + Zero + One
28              + Neg<Self>
29              + Add<Self,Self>
30              + Sub<Self,Self>
31              + Mul<Self,Self>
32              + Div<Self,Self>
33              + Rem<Self,Self> {}
34
35 pub trait IntConvertible {
36     fn to_int(&self) -> int;
37     fn from_int(n: int) -> Self;
38 }
39
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;
48 }
49
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) }
53
54 pub trait Zero {
55     fn zero() -> Self;      // FIXME (#5527): This should be an associated constant
56     fn is_zero(&self) -> bool;
57 }
58
59 #[inline(always)] pub fn zero<T: Zero>() -> T { Zero::zero() }
60
61 pub trait One {
62     fn one() -> Self;       // FIXME (#5527): This should be an associated constant
63 }
64
65 #[inline(always)] pub fn one<T: One>() -> T { One::one() }
66
67 pub trait Signed: Num
68                 + Neg<Self> {
69     fn abs(&self) -> Self;
70     fn abs_sub(&self, other: &Self) -> Self;
71     fn signum(&self) -> Self;
72
73     fn is_positive(&self) -> bool;
74     fn is_negative(&self) -> bool;
75 }
76
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() }
80
81 pub trait Unsigned: Num {}
82
83 pub trait Integer: Num
84                  + Orderable
85                  + Div<Self,Self>
86                  + Rem<Self,Self> {
87     fn div_rem(&self, other: &Self) -> (Self,Self);
88
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);
92
93     fn gcd(&self, other: &Self) -> Self;
94     fn lcm(&self, other: &Self) -> Self;
95
96     fn is_multiple_of(&self, other: &Self) -> bool;
97     fn is_even(&self) -> bool;
98     fn is_odd(&self) -> bool;
99 }
100
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) }
103
104 pub trait Round {
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;
110 }
111
112 pub trait Fractional: Num
113                     + Orderable
114                     + Round
115                     + Div<Self,Self> {
116     fn recip(&self) -> Self;
117 }
118
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;
125 }
126
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) }
132
133 pub trait Trigonometric {
134     fn sin(&self) -> Self;
135     fn cos(&self) -> Self;
136     fn tan(&self) -> Self;
137
138     fn asin(&self) -> Self;
139     fn acos(&self) -> Self;
140     fn atan(&self) -> Self;
141
142     fn atan2(&self, other: &Self) -> Self;
143     fn sin_cos(&self) -> (Self, Self);
144 }
145
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() }
149
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() }
153
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() }
156
157 pub trait Exponential {
158     fn exp(&self) -> Self;
159     fn exp2(&self) -> Self;
160
161     fn ln(&self) -> Self;
162     fn log(&self, base: &Self) -> Self;
163     fn log2(&self) -> Self;
164     fn log10(&self) -> Self;
165 }
166
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() }
169
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() }
174
175 pub trait Hyperbolic: Exponential {
176     fn sinh(&self) -> Self;
177     fn cosh(&self) -> Self;
178     fn tanh(&self) -> Self;
179
180     fn asinh(&self) -> Self;
181     fn acosh(&self) -> Self;
182     fn atanh(&self) -> Self;
183 }
184
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() }
188
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() }
192
193 /// Defines constants and methods common to real numbers
194 pub trait Real: Signed
195               + Fractional
196               + Algebraic
197               + Trigonometric
198               + Hyperbolic {
199     // Common Constants
200     // FIXME (#5527): These should be associated constants
201     fn pi() -> Self;
202     fn two_pi() -> Self;
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;
211     fn sqrt2() -> Self;
212     fn frac_1_sqrt2() -> Self;
213     fn e() -> Self;
214     fn log2_e() -> Self;
215     fn log10_e() -> Self;
216     fn ln_2() -> Self;
217     fn ln_10() -> Self;
218
219     // Angular conversions
220     fn to_degrees(&self) -> Self;
221     fn to_radians(&self) -> Self;
222 }
223
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
228
229     // Gamma functions
230     fn lgamma(&self) -> (int, Self);
231     fn tgamma(&self) -> Self;
232
233     // Bessel functions
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;
240 }
241
242 /// Collects the bitwise operators under one trait.
243 pub trait Bitwise: Not<Self>
244                  + BitAnd<Self,Self>
245                  + BitOr<Self,Self>
246                  + BitXor<Self,Self>
247                  + Shl<Self,Self>
248                  + Shr<Self,Self> {}
249
250 pub trait BitCount {
251     fn population_count(&self) -> Self;
252     fn leading_zeros(&self) -> Self;
253     fn trailing_zeros(&self) -> Self;
254 }
255
256 pub trait Bounded {
257     // FIXME (#5527): These should be associated constants
258     fn min_value() -> Self;
259     fn max_value() -> Self;
260 }
261
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
266                    + NumCast
267                    + Bounded
268                    + Neg<Self>
269                    + Add<Self,Self>
270                    + Sub<Self,Self>
271                    + Mul<Self,Self>
272                    + Div<Self,Self>
273                    + Rem<Self,Self> {
274     // FIXME (#5527): These should be associated constants
275     fn bits() -> uint;
276     fn bytes() -> uint;
277 }
278
279 /// A collection of traits relevant to primitive signed and unsigned integers
280 pub trait Int: Integer
281              + Primitive
282              + Bitwise
283              + BitCount {}
284
285 /// Used for representing the classification of floating point numbers
286 #[deriving(Eq)]
287 pub enum FPCategory {
288     /// "Not a Number", often obtained by dividing by zero
289     FPNaN,
290     /// Positive or negative infinity
291     FPInfinite ,
292     /// Positive or negative zero
293     FPZero,
294     /// De-normalized floating point representation (less precise than `FPNormal`)
295     FPSubnormal,
296     /// A regular floating point number
297     FPNormal,
298 }
299
300 /// Primitive floating point numbers
301 pub trait Float: Real
302                + Signed
303                + Primitive
304                + ApproxEq<Self> {
305     // FIXME (#5527): These should be associated constants
306     fn NaN() -> Self;
307     fn infinity() -> Self;
308     fn neg_infinity() -> Self;
309     fn neg_zero() -> Self;
310
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;
316
317     fn mantissa_digits() -> uint;
318     fn digits() -> uint;
319     fn epsilon() -> Self;
320     fn min_exp() -> int;
321     fn max_exp() -> int;
322     fn min_10_exp() -> int;
323     fn max_10_exp() -> int;
324
325     fn ldexp(x: Self, exp: int) -> Self;
326     fn frexp(&self) -> (Self, int);
327
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;
332 }
333
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) }
337
338 /// Cast from one machine scalar to another
339 ///
340 /// # Example
341 ///
342 /// ~~~
343 /// let twenty: f32 = num::cast(0x14);
344 /// assert_eq!(twenty, 20f32);
345 /// ~~~
346 ///
347 #[inline]
348 pub fn cast<T:NumCast,U:NumCast>(n: T) -> U {
349     NumCast::from(n)
350 }
351
352 /// An interface for casting between machine scalars
353 pub trait NumCast {
354     fn from<T:NumCast>(n: T) -> Self;
355
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;
361
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;
367
368     fn to_f32(&self) -> f32;
369     fn to_f64(&self) -> f64;
370     fn to_float(&self) -> float;
371 }
372
373 macro_rules! impl_num_cast(
374     ($T:ty, $conv:ident) => (
375         impl NumCast for $T {
376             #[inline]
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
380                 n.$conv()
381             }
382
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  }
388
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   }
394
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 }
398         }
399     )
400 )
401
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)
415
416 pub trait ToStrRadix {
417     fn to_str_radix(&self, radix: uint) -> ~str;
418 }
419
420 pub trait FromStrRadix {
421     fn from_str_radix(str: &str, radix: uint) -> Option<Self>;
422 }
423
424 /// Calculates a power to a given radix, optimized for uint `pow` and `radix`.
425 ///
426 /// Returns `radix^pow` as `T`.
427 ///
428 /// Note:
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`.
435 ///
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();
439
440     if pow   == 0u { return _1; }
441     if radix == 0u { return _0; }
442     let mut my_pow     = pow;
443     let mut total      = _1;
444     let mut multiplier = cast(radix);
445     while (my_pow > 0u) {
446         if my_pow % 2u == 1u {
447             total = total * multiplier;
448         }
449         my_pow = my_pow / 2u;
450         multiplier = multiplier * multiplier;
451     }
452     total
453 }
454
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() }
458 }
459
460 impl<T: Zero + 'static> Zero for @T {
461     fn zero() -> @T { @Zero::zero() }
462     fn is_zero(&self) -> bool { (**self).is_zero() }
463 }
464
465 impl<T: Zero> Zero for ~T {
466     fn zero() -> ~T { ~Zero::zero() }
467     fn is_zero(&self) -> bool { (**self).is_zero() }
468 }
469
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;
475
476     /// Saturating subtraction operator.
477     /// Returns a-b, saturating at the numeric bounds instead of overflowing.
478     fn saturating_sub(self, v: Self) -> Self;
479 }
480
481 impl<T: CheckedAdd+CheckedSub+Zero+Ord+Bounded> Saturating for T {
482     #[inline]
483     fn saturating_add(self, v: T) -> T {
484         match self.checked_add(&v) {
485             Some(x) => x,
486             None => if v >= Zero::zero() {
487                 Bounded::max_value::<T>()
488             } else {
489                 Bounded::min_value::<T>()
490             }
491         }
492     }
493
494     #[inline]
495     fn saturating_sub(self, v: T) -> T {
496         match self.checked_sub(&v) {
497             Some(x) => x,
498             None => if v >= Zero::zero() {
499                 Bounded::min_value::<T>()
500             } else {
501                 Bounded::max_value::<T>()
502             }
503         }
504     }
505 }
506
507 pub trait CheckedAdd: Add<Self, Self> {
508     fn checked_add(&self, v: &Self) -> Option<Self>;
509 }
510
511 impl CheckedAdd for i8 {
512     #[inline]
513     fn checked_add(&self, v: &i8) -> Option<i8> {
514         unsafe {
515             let (x, y) = intrinsics::i8_add_with_overflow(*self, *v);
516             if y { None } else { Some(x) }
517         }
518     }
519 }
520
521 impl CheckedAdd for i16 {
522     #[inline]
523     fn checked_add(&self, v: &i16) -> Option<i16> {
524         unsafe {
525             let (x, y) = intrinsics::i16_add_with_overflow(*self, *v);
526             if y { None } else { Some(x) }
527         }
528     }
529 }
530
531 impl CheckedAdd for i32 {
532     #[inline]
533     fn checked_add(&self, v: &i32) -> Option<i32> {
534         unsafe {
535             let (x, y) = intrinsics::i32_add_with_overflow(*self, *v);
536             if y { None } else { Some(x) }
537         }
538     }
539 }
540
541 impl CheckedAdd for i64 {
542     #[inline]
543     fn checked_add(&self, v: &i64) -> Option<i64> {
544         unsafe {
545             let (x, y) = intrinsics::i64_add_with_overflow(*self, *v);
546             if y { None } else { Some(x) }
547         }
548     }
549 }
550
551 #[cfg(target_word_size = "32")]
552 impl CheckedAdd for int {
553     #[inline]
554     fn checked_add(&self, v: &int) -> Option<int> {
555         unsafe {
556             let (x, y) = intrinsics::i32_add_with_overflow(*self as i32, *v as i32);
557             if y { None } else { Some(x as int) }
558         }
559     }
560 }
561
562 #[cfg(target_word_size = "64")]
563 impl CheckedAdd for int {
564     #[inline]
565     fn checked_add(&self, v: &int) -> Option<int> {
566         unsafe {
567             let (x, y) = intrinsics::i64_add_with_overflow(*self as i64, *v as i64);
568             if y { None } else { Some(x as int) }
569         }
570     }
571 }
572
573 impl CheckedAdd for u8 {
574     #[inline]
575     fn checked_add(&self, v: &u8) -> Option<u8> {
576         unsafe {
577             let (x, y) = intrinsics::u8_add_with_overflow(*self, *v);
578             if y { None } else { Some(x) }
579         }
580     }
581 }
582
583 impl CheckedAdd for u16 {
584     #[inline]
585     fn checked_add(&self, v: &u16) -> Option<u16> {
586         unsafe {
587             let (x, y) = intrinsics::u16_add_with_overflow(*self, *v);
588             if y { None } else { Some(x) }
589         }
590     }
591 }
592
593 impl CheckedAdd for u32 {
594     #[inline]
595     fn checked_add(&self, v: &u32) -> Option<u32> {
596         unsafe {
597             let (x, y) = intrinsics::u32_add_with_overflow(*self, *v);
598             if y { None } else { Some(x) }
599         }
600     }
601 }
602
603 impl CheckedAdd for u64 {
604     #[inline]
605     fn checked_add(&self, v: &u64) -> Option<u64> {
606         unsafe {
607             let (x, y) = intrinsics::u64_add_with_overflow(*self, *v);
608             if y { None } else { Some(x) }
609         }
610     }
611 }
612
613 #[cfg(target_word_size = "32")]
614 impl CheckedAdd for uint {
615     #[inline]
616     fn checked_add(&self, v: &uint) -> Option<uint> {
617         unsafe {
618             let (x, y) = intrinsics::u32_add_with_overflow(*self as u32, *v as u32);
619             if y { None } else { Some(x as uint) }
620         }
621     }
622 }
623
624 #[cfg(target_word_size = "64")]
625 impl CheckedAdd for uint {
626     #[inline]
627     fn checked_add(&self, v: &uint) -> Option<uint> {
628         unsafe {
629             let (x, y) = intrinsics::u64_add_with_overflow(*self as u64, *v as u64);
630             if y { None } else { Some(x as uint) }
631         }
632     }
633 }
634
635 pub trait CheckedSub: Sub<Self, Self> {
636     fn checked_sub(&self, v: &Self) -> Option<Self>;
637 }
638
639 impl CheckedSub for i8 {
640     #[inline]
641     fn checked_sub(&self, v: &i8) -> Option<i8> {
642         unsafe {
643             let (x, y) = intrinsics::i8_sub_with_overflow(*self, *v);
644             if y { None } else { Some(x) }
645         }
646     }
647 }
648
649 impl CheckedSub for i16 {
650     #[inline]
651     fn checked_sub(&self, v: &i16) -> Option<i16> {
652         unsafe {
653             let (x, y) = intrinsics::i16_sub_with_overflow(*self, *v);
654             if y { None } else { Some(x) }
655         }
656     }
657 }
658
659 impl CheckedSub for i32 {
660     #[inline]
661     fn checked_sub(&self, v: &i32) -> Option<i32> {
662         unsafe {
663             let (x, y) = intrinsics::i32_sub_with_overflow(*self, *v);
664             if y { None } else { Some(x) }
665         }
666     }
667 }
668
669 impl CheckedSub for i64 {
670     #[inline]
671     fn checked_sub(&self, v: &i64) -> Option<i64> {
672         unsafe {
673             let (x, y) = intrinsics::i64_sub_with_overflow(*self, *v);
674             if y { None } else { Some(x) }
675         }
676     }
677 }
678
679 #[cfg(target_word_size = "32")]
680 impl CheckedSub for int {
681     #[inline]
682     fn checked_sub(&self, v: &int) -> Option<int> {
683         unsafe {
684             let (x, y) = intrinsics::i32_sub_with_overflow(*self as i32, *v as i32);
685             if y { None } else { Some(x as int) }
686         }
687     }
688 }
689
690 #[cfg(target_word_size = "64")]
691 impl CheckedSub for int {
692     #[inline]
693     fn checked_sub(&self, v: &int) -> Option<int> {
694         unsafe {
695             let (x, y) = intrinsics::i64_sub_with_overflow(*self as i64, *v as i64);
696             if y { None } else { Some(x as int) }
697         }
698     }
699 }
700
701 impl CheckedSub for u8 {
702     #[inline]
703     fn checked_sub(&self, v: &u8) -> Option<u8> {
704         unsafe {
705             let (x, y) = intrinsics::u8_sub_with_overflow(*self, *v);
706             if y { None } else { Some(x) }
707         }
708     }
709 }
710
711 impl CheckedSub for u16 {
712     #[inline]
713     fn checked_sub(&self, v: &u16) -> Option<u16> {
714         unsafe {
715             let (x, y) = intrinsics::u16_sub_with_overflow(*self, *v);
716             if y { None } else { Some(x) }
717         }
718     }
719 }
720
721 impl CheckedSub for u32 {
722     #[inline]
723     fn checked_sub(&self, v: &u32) -> Option<u32> {
724         unsafe {
725             let (x, y) = intrinsics::u32_sub_with_overflow(*self, *v);
726             if y { None } else { Some(x) }
727         }
728     }
729 }
730
731 impl CheckedSub for u64 {
732     #[inline]
733     fn checked_sub(&self, v: &u64) -> Option<u64> {
734         unsafe {
735             let (x, y) = intrinsics::u64_sub_with_overflow(*self, *v);
736             if y { None } else { Some(x) }
737         }
738     }
739 }
740
741 #[cfg(target_word_size = "32")]
742 impl CheckedSub for uint {
743     #[inline]
744     fn checked_sub(&self, v: &uint) -> Option<uint> {
745         unsafe {
746             let (x, y) = intrinsics::u32_sub_with_overflow(*self as u32, *v as u32);
747             if y { None } else { Some(x as uint) }
748         }
749     }
750 }
751
752 #[cfg(target_word_size = "64")]
753 impl CheckedSub for uint {
754     #[inline]
755     fn checked_sub(&self, v: &uint) -> Option<uint> {
756         unsafe {
757             let (x, y) = intrinsics::u64_sub_with_overflow(*self as u64, *v as u64);
758             if y { None } else { Some(x as uint) }
759         }
760     }
761 }
762
763 pub trait CheckedMul: Mul<Self, Self> {
764     fn checked_mul(&self, v: &Self) -> Option<Self>;
765 }
766
767 impl CheckedMul for i8 {
768     #[inline]
769     fn checked_mul(&self, v: &i8) -> Option<i8> {
770         unsafe {
771             let (x, y) = intrinsics::i8_mul_with_overflow(*self, *v);
772             if y { None } else { Some(x) }
773         }
774     }
775 }
776
777 impl CheckedMul for i16 {
778     #[inline]
779     fn checked_mul(&self, v: &i16) -> Option<i16> {
780         unsafe {
781             let (x, y) = intrinsics::i16_mul_with_overflow(*self, *v);
782             if y { None } else { Some(x) }
783         }
784     }
785 }
786
787 impl CheckedMul for i32 {
788     #[inline]
789     fn checked_mul(&self, v: &i32) -> Option<i32> {
790         unsafe {
791             let (x, y) = intrinsics::i32_mul_with_overflow(*self, *v);
792             if y { None } else { Some(x) }
793         }
794     }
795 }
796
797 // FIXME: #8449: should not be disabled on 32-bit
798 #[cfg(target_word_size = "64")]
799 impl CheckedMul for i64 {
800     #[inline]
801     fn checked_mul(&self, v: &i64) -> Option<i64> {
802         unsafe {
803             let (x, y) = intrinsics::i64_mul_with_overflow(*self, *v);
804             if y { None } else { Some(x) }
805         }
806     }
807 }
808
809 #[cfg(target_word_size = "32")]
810 impl CheckedMul for int {
811     #[inline]
812     fn checked_mul(&self, v: &int) -> Option<int> {
813         unsafe {
814             let (x, y) = intrinsics::i32_mul_with_overflow(*self as i32, *v as i32);
815             if y { None } else { Some(x as int) }
816         }
817     }
818 }
819
820 #[cfg(target_word_size = "64")]
821 impl CheckedMul for int {
822     #[inline]
823     fn checked_mul(&self, v: &int) -> Option<int> {
824         unsafe {
825             let (x, y) = intrinsics::i64_mul_with_overflow(*self as i64, *v as i64);
826             if y { None } else { Some(x as int) }
827         }
828     }
829 }
830
831 impl CheckedMul for u8 {
832     #[inline]
833     fn checked_mul(&self, v: &u8) -> Option<u8> {
834         unsafe {
835             let (x, y) = intrinsics::u8_mul_with_overflow(*self, *v);
836             if y { None } else { Some(x) }
837         }
838     }
839 }
840
841 impl CheckedMul for u16 {
842     #[inline]
843     fn checked_mul(&self, v: &u16) -> Option<u16> {
844         unsafe {
845             let (x, y) = intrinsics::u16_mul_with_overflow(*self, *v);
846             if y { None } else { Some(x) }
847         }
848     }
849 }
850
851 impl CheckedMul for u32 {
852     #[inline]
853     fn checked_mul(&self, v: &u32) -> Option<u32> {
854         unsafe {
855             let (x, y) = intrinsics::u32_mul_with_overflow(*self, *v);
856             if y { None } else { Some(x) }
857         }
858     }
859 }
860
861 // FIXME: #8449: should not be disabled on 32-bit
862 #[cfg(target_word_size = "64")]
863 impl CheckedMul for u64 {
864     #[inline]
865     fn checked_mul(&self, v: &u64) -> Option<u64> {
866         unsafe {
867             let (x, y) = intrinsics::u64_mul_with_overflow(*self, *v);
868             if y { None } else { Some(x) }
869         }
870     }
871 }
872
873 #[cfg(target_word_size = "32")]
874 impl CheckedMul for uint {
875     #[inline]
876     fn checked_mul(&self, v: &uint) -> Option<uint> {
877         unsafe {
878             let (x, y) = intrinsics::u32_mul_with_overflow(*self as u32, *v as u32);
879             if y { None } else { Some(x as uint) }
880         }
881     }
882 }
883
884 #[cfg(target_word_size = "64")]
885 impl CheckedMul for uint {
886     #[inline]
887     fn checked_mul(&self, v: &uint) -> Option<uint> {
888         unsafe {
889             let (x, y) = intrinsics::u64_mul_with_overflow(*self as u64, *v as u64);
890             if y { None } else { Some(x as uint) }
891         }
892     }
893 }
894
895 pub trait CheckedDiv: Div<Self, Self> {
896     fn checked_div(&self, v: &Self) -> Option<Self>;
897 }
898
899 /// Helper function for testing numeric operations
900 #[cfg(test)]
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));
907
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);
913 }
914
915 #[cfg(test)]
916 mod tests {
917     use prelude::*;
918     use uint;
919     use super::*;
920
921     macro_rules! test_cast_20(
922         ($_20:expr) => ({
923             let _20 = $_20;
924
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());
938
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));
952
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));
966         })
967     )
968
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)   }
982
983     #[test]
984     fn test_saturating_add_uint() {
985         use uint::max_value;
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);
990     }
991
992     #[test]
993     fn test_saturating_sub_uint() {
994         use uint::max_value;
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);
999     }
1000
1001     #[test]
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);
1011     }
1012
1013     #[test]
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);
1023     }
1024
1025     #[test]
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);
1036     }
1037
1038     #[test]
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);
1048     }
1049
1050     #[test]
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);
1058     }
1059 }