1 // Copyright 2013-2014 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 for generic mathematics
12 //!
13 //! ## Compatibility
14 //!
15 //! The `num-traits` crate is tested for rustc 1.8 and greater.
16 
17 #![doc(html_root_url = "https://docs.rs/num-traits/0.2")]
18 #![deny(unconditional_recursion)]
19 #![no_std]
20 #[cfg(feature = "std")]
21 extern crate std;
22 
23 // Only `no_std` builds actually use `libm`.
24 #[cfg(all(not(feature = "std"), feature = "libm"))]
25 extern crate libm;
26 
27 use core::fmt;
28 use core::num::Wrapping;
29 use core::ops::{Add, Div, Mul, Rem, Sub};
30 use core::ops::{AddAssign, DivAssign, MulAssign, RemAssign, SubAssign};
31 
32 pub use bounds::Bounded;
33 #[cfg(any(feature = "std", feature = "libm"))]
34 pub use float::Float;
35 pub use float::FloatConst;
36 // pub use real::{FloatCore, Real}; // NOTE: Don't do this, it breaks `use num_traits::*;`.
37 pub use cast::{cast, AsPrimitive, FromPrimitive, NumCast, ToPrimitive};
38 pub use identities::{one, zero, One, Zero};
39 pub use int::PrimInt;
40 pub use ops::checked::{
41     CheckedAdd, CheckedDiv, CheckedMul, CheckedNeg, CheckedRem, CheckedShl, CheckedShr, CheckedSub,
42 };
43 pub use ops::inv::Inv;
44 pub use ops::mul_add::{MulAdd, MulAddAssign};
45 pub use ops::saturating::Saturating;
46 pub use ops::wrapping::{WrappingAdd, WrappingMul, WrappingShl, WrappingShr, WrappingSub};
47 pub use pow::{checked_pow, pow, Pow};
48 pub use sign::{abs, abs_sub, signum, Signed, Unsigned};
49 
50 #[macro_use]
51 mod macros;
52 
53 pub mod bounds;
54 pub mod cast;
55 pub mod float;
56 pub mod identities;
57 pub mod int;
58 pub mod ops;
59 pub mod pow;
60 pub mod real;
61 pub mod sign;
62 
63 /// The base trait for numeric types, covering `0` and `1` values,
64 /// comparisons, basic numeric operations, and string conversion.
65 pub trait Num: PartialEq + Zero + One + NumOps {
66     type FromStrRadixErr;
67 
68     /// Convert from a string and radix <= 36.
69     ///
70     /// # Examples
71     ///
72     /// ```rust
73     /// use num_traits::Num;
74     ///
75     /// let result = <i32 as Num>::from_str_radix("27", 10);
76     /// assert_eq!(result, Ok(27));
77     ///
78     /// let result = <i32 as Num>::from_str_radix("foo", 10);
79     /// assert!(result.is_err());
80     /// ```
from_str_radix(str: &str, radix: u32) -> Result<Self, Self::FromStrRadixErr>81     fn from_str_radix(str: &str, radix: u32) -> Result<Self, Self::FromStrRadixErr>;
82 }
83 
84 /// The trait for types implementing basic numeric operations
85 ///
86 /// This is automatically implemented for types which implement the operators.
87 pub trait NumOps<Rhs = Self, Output = Self>:
88     Add<Rhs, Output = Output>
89     + Sub<Rhs, Output = Output>
90     + Mul<Rhs, Output = Output>
91     + Div<Rhs, Output = Output>
92     + Rem<Rhs, Output = Output>
93 {
94 }
95 
96 impl<T, Rhs, Output> NumOps<Rhs, Output> for T where
97     T: Add<Rhs, Output = Output>
98         + Sub<Rhs, Output = Output>
99         + Mul<Rhs, Output = Output>
100         + Div<Rhs, Output = Output>
101         + Rem<Rhs, Output = Output>
102 {
103 }
104 
105 /// The trait for `Num` types which also implement numeric operations taking
106 /// the second operand by reference.
107 ///
108 /// This is automatically implemented for types which implement the operators.
109 pub trait NumRef: Num + for<'r> NumOps<&'r Self> {}
110 impl<T> NumRef for T where T: Num + for<'r> NumOps<&'r T> {}
111 
112 /// The trait for references which implement numeric operations, taking the
113 /// second operand either by value or by reference.
114 ///
115 /// This is automatically implemented for types which implement the operators.
116 pub trait RefNum<Base>: NumOps<Base, Base> + for<'r> NumOps<&'r Base, Base> {}
117 impl<T, Base> RefNum<Base> for T where T: NumOps<Base, Base> + for<'r> NumOps<&'r Base, Base> {}
118 
119 /// The trait for types implementing numeric assignment operators (like `+=`).
120 ///
121 /// This is automatically implemented for types which implement the operators.
122 pub trait NumAssignOps<Rhs = Self>:
123     AddAssign<Rhs> + SubAssign<Rhs> + MulAssign<Rhs> + DivAssign<Rhs> + RemAssign<Rhs>
124 {
125 }
126 
127 impl<T, Rhs> NumAssignOps<Rhs> for T where
128     T: AddAssign<Rhs> + SubAssign<Rhs> + MulAssign<Rhs> + DivAssign<Rhs> + RemAssign<Rhs>
129 {
130 }
131 
132 /// The trait for `Num` types which also implement assignment operators.
133 ///
134 /// This is automatically implemented for types which implement the operators.
135 pub trait NumAssign: Num + NumAssignOps {}
136 impl<T> NumAssign for T where T: Num + NumAssignOps {}
137 
138 /// The trait for `NumAssign` types which also implement assignment operations
139 /// taking the second operand by reference.
140 ///
141 /// This is automatically implemented for types which implement the operators.
142 pub trait NumAssignRef: NumAssign + for<'r> NumAssignOps<&'r Self> {}
143 impl<T> NumAssignRef for T where T: NumAssign + for<'r> NumAssignOps<&'r T> {}
144 
145 macro_rules! int_trait_impl {
146     ($name:ident for $($t:ty)*) => ($(
147         impl $name for $t {
148             type FromStrRadixErr = ::core::num::ParseIntError;
149             #[inline]
150             fn from_str_radix(s: &str, radix: u32)
151                               -> Result<Self, ::core::num::ParseIntError>
152             {
153                 <$t>::from_str_radix(s, radix)
154             }
155         }
156     )*)
157 }
158 int_trait_impl!(Num for usize u8 u16 u32 u64 isize i8 i16 i32 i64);
159 #[cfg(has_i128)]
160 int_trait_impl!(Num for u128 i128);
161 
162 impl<T: Num> Num for Wrapping<T>
163 where
164     Wrapping<T>: Add<Output = Wrapping<T>>
165         + Sub<Output = Wrapping<T>>
166         + Mul<Output = Wrapping<T>>
167         + Div<Output = Wrapping<T>>
168         + Rem<Output = Wrapping<T>>,
169 {
170     type FromStrRadixErr = T::FromStrRadixErr;
from_str_radix(str: &str, radix: u32) -> Result<Self, Self::FromStrRadixErr>171     fn from_str_radix(str: &str, radix: u32) -> Result<Self, Self::FromStrRadixErr> {
172         T::from_str_radix(str, radix).map(Wrapping)
173     }
174 }
175 
176 #[derive(Debug)]
177 pub enum FloatErrorKind {
178     Empty,
179     Invalid,
180 }
181 // FIXME: core::num::ParseFloatError is stable in 1.0, but opaque to us,
182 // so there's not really any way for us to reuse it.
183 #[derive(Debug)]
184 pub struct ParseFloatError {
185     pub kind: FloatErrorKind,
186 }
187 
188 impl fmt::Display for ParseFloatError {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result189     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
190         let description = match self.kind {
191             FloatErrorKind::Empty => "cannot parse float from empty string",
192             FloatErrorKind::Invalid => "invalid float literal",
193         };
194 
195         description.fmt(f)
196     }
197 }
198 
199 // FIXME: The standard library from_str_radix on floats was deprecated, so we're stuck
200 // with this implementation ourselves until we want to make a breaking change.
201 // (would have to drop it from `Num` though)
202 macro_rules! float_trait_impl {
203     ($name:ident for $($t:ident)*) => ($(
204         impl $name for $t {
205             type FromStrRadixErr = ParseFloatError;
206 
207             fn from_str_radix(src: &str, radix: u32)
208                               -> Result<Self, Self::FromStrRadixErr>
209             {
210                 use self::FloatErrorKind::*;
211                 use self::ParseFloatError as PFE;
212 
213                 // Special values
214                 match src {
215                     "inf"   => return Ok(core::$t::INFINITY),
216                     "-inf"  => return Ok(core::$t::NEG_INFINITY),
217                     "NaN"   => return Ok(core::$t::NAN),
218                     _       => {},
219                 }
220 
221                 fn slice_shift_char(src: &str) -> Option<(char, &str)> {
222                     let mut chars = src.chars();
223                     if let Some(ch) = chars.next() {
224                         Some((ch, chars.as_str()))
225                     } else {
226                         None
227                     }
228                 }
229 
230                 let (is_positive, src) =  match slice_shift_char(src) {
231                     None             => return Err(PFE { kind: Empty }),
232                     Some(('-', ""))  => return Err(PFE { kind: Empty }),
233                     Some(('-', src)) => (false, src),
234                     Some((_, _))     => (true,  src),
235                 };
236 
237                 // The significand to accumulate
238                 let mut sig = if is_positive { 0.0 } else { -0.0 };
239                 // Necessary to detect overflow
240                 let mut prev_sig = sig;
241                 let mut cs = src.chars().enumerate();
242                 // Exponent prefix and exponent index offset
243                 let mut exp_info = None::<(char, usize)>;
244 
245                 // Parse the integer part of the significand
246                 for (i, c) in cs.by_ref() {
247                     match c.to_digit(radix) {
248                         Some(digit) => {
249                             // shift significand one digit left
250                             sig = sig * (radix as $t);
251 
252                             // add/subtract current digit depending on sign
253                             if is_positive {
254                                 sig = sig + ((digit as isize) as $t);
255                             } else {
256                                 sig = sig - ((digit as isize) as $t);
257                             }
258 
259                             // Detect overflow by comparing to last value, except
260                             // if we've not seen any non-zero digits.
261                             if prev_sig != 0.0 {
262                                 if is_positive && sig <= prev_sig
263                                     { return Ok(core::$t::INFINITY); }
264                                 if !is_positive && sig >= prev_sig
265                                     { return Ok(core::$t::NEG_INFINITY); }
266 
267                                 // Detect overflow by reversing the shift-and-add process
268                                 if is_positive && (prev_sig != (sig - digit as $t) / radix as $t)
269                                     { return Ok(core::$t::INFINITY); }
270                                 if !is_positive && (prev_sig != (sig + digit as $t) / radix as $t)
271                                     { return Ok(core::$t::NEG_INFINITY); }
272                             }
273                             prev_sig = sig;
274                         },
275                         None => match c {
276                             'e' | 'E' | 'p' | 'P' => {
277                                 exp_info = Some((c, i + 1));
278                                 break;  // start of exponent
279                             },
280                             '.' => {
281                                 break;  // start of fractional part
282                             },
283                             _ => {
284                                 return Err(PFE { kind: Invalid });
285                             },
286                         },
287                     }
288                 }
289 
290                 // If we are not yet at the exponent parse the fractional
291                 // part of the significand
292                 if exp_info.is_none() {
293                     let mut power = 1.0;
294                     for (i, c) in cs.by_ref() {
295                         match c.to_digit(radix) {
296                             Some(digit) => {
297                                 // Decrease power one order of magnitude
298                                 power = power / (radix as $t);
299                                 // add/subtract current digit depending on sign
300                                 sig = if is_positive {
301                                     sig + (digit as $t) * power
302                                 } else {
303                                     sig - (digit as $t) * power
304                                 };
305                                 // Detect overflow by comparing to last value
306                                 if is_positive && sig < prev_sig
307                                     { return Ok(core::$t::INFINITY); }
308                                 if !is_positive && sig > prev_sig
309                                     { return Ok(core::$t::NEG_INFINITY); }
310                                 prev_sig = sig;
311                             },
312                             None => match c {
313                                 'e' | 'E' | 'p' | 'P' => {
314                                     exp_info = Some((c, i + 1));
315                                     break; // start of exponent
316                                 },
317                                 _ => {
318                                     return Err(PFE { kind: Invalid });
319                                 },
320                             },
321                         }
322                     }
323                 }
324 
325                 // Parse and calculate the exponent
326                 let exp = match exp_info {
327                     Some((c, offset)) => {
328                         let base = match c {
329                             'E' | 'e' if radix == 10 => 10.0,
330                             'P' | 'p' if radix == 16 => 2.0,
331                             _ => return Err(PFE { kind: Invalid }),
332                         };
333 
334                         // Parse the exponent as decimal integer
335                         let src = &src[offset..];
336                         let (is_positive, exp) = match slice_shift_char(src) {
337                             Some(('-', src)) => (false, src.parse::<usize>()),
338                             Some(('+', src)) => (true,  src.parse::<usize>()),
339                             Some((_, _))     => (true,  src.parse::<usize>()),
340                             None             => return Err(PFE { kind: Invalid }),
341                         };
342 
343                         #[cfg(feature = "std")]
344                         fn pow(base: $t, exp: usize) -> $t {
345                             Float::powi(base, exp as i32)
346                         }
347                         // otherwise uses the generic `pow` from the root
348 
349                         match (is_positive, exp) {
350                             (true,  Ok(exp)) => pow(base, exp),
351                             (false, Ok(exp)) => 1.0 / pow(base, exp),
352                             (_, Err(_))      => return Err(PFE { kind: Invalid }),
353                         }
354                     },
355                     None => 1.0, // no exponent
356                 };
357 
358                 Ok(sig * exp)
359             }
360         }
361     )*)
362 }
363 float_trait_impl!(Num for f32 f64);
364 
365 /// A value bounded by a minimum and a maximum
366 ///
367 ///  If input is less than min then this returns min.
368 ///  If input is greater than max then this returns max.
369 ///  Otherwise this returns input.
370 ///
371 /// **Panics** in debug mode if `!(min <= max)`.
372 #[inline]
clamp<T: PartialOrd>(input: T, min: T, max: T) -> T373 pub fn clamp<T: PartialOrd>(input: T, min: T, max: T) -> T {
374     debug_assert!(min <= max, "min must be less than or equal to max");
375     if input < min {
376         min
377     } else if input > max {
378         max
379     } else {
380         input
381     }
382 }
383 
384 /// A value bounded by a minimum value
385 ///
386 ///  If input is less than min then this returns min.
387 ///  Otherwise this returns input.
388 ///  `clamp_min(std::f32::NAN, 1.0)` preserves `NAN` different from `f32::min(std::f32::NAN, 1.0)`.
389 ///
390 /// **Panics** in debug mode if `!(min == min)`. (This occurs if `min` is `NAN`.)
391 #[inline]
clamp_min<T: PartialOrd>(input: T, min: T) -> T392 pub fn clamp_min<T: PartialOrd>(input: T, min: T) -> T {
393     debug_assert!(min == min, "min must not be NAN");
394     if input < min {
395         min
396     } else {
397         input
398     }
399 }
400 
401 /// A value bounded by a maximum value
402 ///
403 ///  If input is greater than max then this returns max.
404 ///  Otherwise this returns input.
405 ///  `clamp_max(std::f32::NAN, 1.0)` preserves `NAN` different from `f32::max(std::f32::NAN, 1.0)`.
406 ///
407 /// **Panics** in debug mode if `!(max == max)`. (This occurs if `max` is `NAN`.)
408 #[inline]
clamp_max<T: PartialOrd>(input: T, max: T) -> T409 pub fn clamp_max<T: PartialOrd>(input: T, max: T) -> T {
410     debug_assert!(max == max, "max must not be NAN");
411     if input > max {
412         max
413     } else {
414         input
415     }
416 }
417 
418 #[test]
clamp_test()419 fn clamp_test() {
420     // Int test
421     assert_eq!(1, clamp(1, -1, 2));
422     assert_eq!(-1, clamp(-2, -1, 2));
423     assert_eq!(2, clamp(3, -1, 2));
424     assert_eq!(1, clamp_min(1, -1));
425     assert_eq!(-1, clamp_min(-2, -1));
426     assert_eq!(-1, clamp_max(1, -1));
427     assert_eq!(-2, clamp_max(-2, -1));
428 
429     // Float test
430     assert_eq!(1.0, clamp(1.0, -1.0, 2.0));
431     assert_eq!(-1.0, clamp(-2.0, -1.0, 2.0));
432     assert_eq!(2.0, clamp(3.0, -1.0, 2.0));
433     assert_eq!(1.0, clamp_min(1.0, -1.0));
434     assert_eq!(-1.0, clamp_min(-2.0, -1.0));
435     assert_eq!(-1.0, clamp_max(1.0, -1.0));
436     assert_eq!(-2.0, clamp_max(-2.0, -1.0));
437     assert!(clamp(::core::f32::NAN, -1.0, 1.0).is_nan());
438     assert!(clamp_min(::core::f32::NAN, 1.0).is_nan());
439     assert!(clamp_max(::core::f32::NAN, 1.0).is_nan());
440 }
441 
442 #[test]
443 #[should_panic]
444 #[cfg(debug_assertions)]
clamp_nan_min()445 fn clamp_nan_min() {
446     clamp(0., ::core::f32::NAN, 1.);
447 }
448 
449 #[test]
450 #[should_panic]
451 #[cfg(debug_assertions)]
clamp_nan_max()452 fn clamp_nan_max() {
453     clamp(0., -1., ::core::f32::NAN);
454 }
455 
456 #[test]
457 #[should_panic]
458 #[cfg(debug_assertions)]
clamp_nan_min_max()459 fn clamp_nan_min_max() {
460     clamp(0., ::core::f32::NAN, ::core::f32::NAN);
461 }
462 
463 #[test]
464 #[should_panic]
465 #[cfg(debug_assertions)]
clamp_min_nan_min()466 fn clamp_min_nan_min() {
467     clamp_min(0., ::core::f32::NAN);
468 }
469 
470 #[test]
471 #[should_panic]
472 #[cfg(debug_assertions)]
clamp_max_nan_max()473 fn clamp_max_nan_max() {
474     clamp_max(0., ::core::f32::NAN);
475 }
476 
477 #[test]
from_str_radix_unwrap()478 fn from_str_radix_unwrap() {
479     // The Result error must impl Debug to allow unwrap()
480 
481     let i: i32 = Num::from_str_radix("0", 10).unwrap();
482     assert_eq!(i, 0);
483 
484     let f: f32 = Num::from_str_radix("0.0", 10).unwrap();
485     assert_eq!(f, 0.0);
486 }
487 
488 #[test]
from_str_radix_multi_byte_fail()489 fn from_str_radix_multi_byte_fail() {
490     // Ensure parsing doesn't panic, even on invalid sign characters
491     assert!(f32::from_str_radix("™0.2", 10).is_err());
492 
493     // Even when parsing the exponent sign
494     assert!(f32::from_str_radix("0.2E™1", 10).is_err());
495 }
496 
497 #[test]
wrapping_is_num()498 fn wrapping_is_num() {
499     fn require_num<T: Num>(_: &T) {}
500     require_num(&Wrapping(42_u32));
501     require_num(&Wrapping(-42));
502 }
503 
504 #[test]
wrapping_from_str_radix()505 fn wrapping_from_str_radix() {
506     macro_rules! test_wrapping_from_str_radix {
507         ($($t:ty)+) => {
508             $(
509                 for &(s, r) in &[("42", 10), ("42", 2), ("-13.0", 10), ("foo", 10)] {
510                     let w = Wrapping::<$t>::from_str_radix(s, r).map(|w| w.0);
511                     assert_eq!(w, <$t as Num>::from_str_radix(s, r));
512                 }
513             )+
514         };
515     }
516 
517     test_wrapping_from_str_radix!(usize u8 u16 u32 u64 isize i8 i16 i32 i64);
518 }
519 
520 #[test]
check_num_ops()521 fn check_num_ops() {
522     fn compute<T: Num + Copy>(x: T, y: T) -> T {
523         x * y / y % y + y - y
524     }
525     assert_eq!(compute(1, 2), 1)
526 }
527 
528 #[test]
check_numref_ops()529 fn check_numref_ops() {
530     fn compute<T: NumRef>(x: T, y: &T) -> T {
531         x * y / y % y + y - y
532     }
533     assert_eq!(compute(1, &2), 1)
534 }
535 
536 #[test]
check_refnum_ops()537 fn check_refnum_ops() {
538     fn compute<T: Copy>(x: &T, y: T) -> T
539     where
540         for<'a> &'a T: RefNum<T>,
541     {
542         &(&(&(&(x * y) / y) % y) + y) - y
543     }
544     assert_eq!(compute(&1, 2), 1)
545 }
546 
547 #[test]
check_refref_ops()548 fn check_refref_ops() {
549     fn compute<T>(x: &T, y: &T) -> T
550     where
551         for<'a> &'a T: RefNum<T>,
552     {
553         &(&(&(&(x * y) / y) % y) + y) - y
554     }
555     assert_eq!(compute(&1, &2), 1)
556 }
557 
558 #[test]
check_numassign_ops()559 fn check_numassign_ops() {
560     fn compute<T: NumAssign + Copy>(mut x: T, y: T) -> T {
561         x *= y;
562         x /= y;
563         x %= y;
564         x += y;
565         x -= y;
566         x
567     }
568     assert_eq!(compute(1, 2), 1)
569 }
570 
571 // TODO test `NumAssignRef`, but even the standard numeric types don't
572 // implement this yet. (see rust pr41336)
573