num_traits/
lib.rs

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