123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512 |
- // Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT
- // file at the top-level directory of this distribution and at
- // http://rust-lang.org/COPYRIGHT.
- //
- // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
- // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
- // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
- // option. This file may not be copied, modified, or distributed
- // except according to those terms.
- //! Numeric traits for generic mathematics
- //!
- //! ## Compatibility
- //!
- //! The `num-traits` crate is tested for rustc 1.8 and greater.
- #![doc(html_root_url = "https://docs.rs/num-traits/0.2")]
- #![deny(unconditional_recursion)]
- #![no_std]
- #[cfg(feature = "std")]
- extern crate std;
- use core::fmt;
- use core::num::Wrapping;
- use core::ops::{Add, Div, Mul, Rem, Sub};
- use core::ops::{AddAssign, DivAssign, MulAssign, RemAssign, SubAssign};
- pub use bounds::Bounded;
- #[cfg(feature = "std")]
- pub use float::Float;
- pub use float::FloatConst;
- // pub use real::{FloatCore, Real}; // NOTE: Don't do this, it breaks `use num_traits::*;`.
- pub use cast::{cast, AsPrimitive, FromPrimitive, NumCast, ToPrimitive};
- pub use identities::{one, zero, One, Zero};
- pub use int::PrimInt;
- pub use ops::checked::{
- CheckedAdd, CheckedDiv, CheckedMul, CheckedNeg, CheckedRem, CheckedShl, CheckedShr, CheckedSub,
- };
- pub use ops::inv::Inv;
- pub use ops::mul_add::{MulAdd, MulAddAssign};
- pub use ops::saturating::Saturating;
- pub use ops::wrapping::{WrappingAdd, WrappingMul, WrappingShl, WrappingShr, WrappingSub};
- pub use pow::{checked_pow, pow, Pow};
- pub use sign::{abs, abs_sub, signum, Signed, Unsigned};
- #[macro_use]
- mod macros;
- pub mod bounds;
- pub mod cast;
- pub mod float;
- pub mod identities;
- pub mod int;
- pub mod ops;
- pub mod pow;
- #[cfg(feature = "std")]
- pub mod real;
- pub mod sign;
- /// The base trait for numeric types, covering `0` and `1` values,
- /// comparisons, basic numeric operations, and string conversion.
- pub trait Num: PartialEq + Zero + One + NumOps {
- type FromStrRadixErr;
- /// Convert from a string and radix <= 36.
- ///
- /// # Examples
- ///
- /// ```rust
- /// use num_traits::Num;
- ///
- /// let result = <i32 as Num>::from_str_radix("27", 10);
- /// assert_eq!(result, Ok(27));
- ///
- /// let result = <i32 as Num>::from_str_radix("foo", 10);
- /// assert!(result.is_err());
- /// ```
- fn from_str_radix(str: &str, radix: u32) -> Result<Self, Self::FromStrRadixErr>;
- }
- /// The trait for types implementing basic numeric operations
- ///
- /// This is automatically implemented for types which implement the operators.
- pub trait NumOps<Rhs = Self, Output = Self>:
- Add<Rhs, Output = Output>
- + Sub<Rhs, Output = Output>
- + Mul<Rhs, Output = Output>
- + Div<Rhs, Output = Output>
- + Rem<Rhs, Output = Output>
- {
- }
- impl<T, Rhs, Output> NumOps<Rhs, Output> for T where
- T: Add<Rhs, Output = Output>
- + Sub<Rhs, Output = Output>
- + Mul<Rhs, Output = Output>
- + Div<Rhs, Output = Output>
- + Rem<Rhs, Output = Output>
- {
- }
- /// The trait for `Num` types which also implement numeric operations taking
- /// the second operand by reference.
- ///
- /// This is automatically implemented for types which implement the operators.
- pub trait NumRef: Num + for<'r> NumOps<&'r Self> {}
- impl<T> NumRef for T where T: Num + for<'r> NumOps<&'r T> {}
- /// The trait for references which implement numeric operations, taking the
- /// second operand either by value or by reference.
- ///
- /// This is automatically implemented for types which implement the operators.
- pub trait RefNum<Base>: NumOps<Base, Base> + for<'r> NumOps<&'r Base, Base> {}
- impl<T, Base> RefNum<Base> for T where T: NumOps<Base, Base> + for<'r> NumOps<&'r Base, Base> {}
- /// The trait for types implementing numeric assignment operators (like `+=`).
- ///
- /// This is automatically implemented for types which implement the operators.
- pub trait NumAssignOps<Rhs = Self>:
- AddAssign<Rhs> + SubAssign<Rhs> + MulAssign<Rhs> + DivAssign<Rhs> + RemAssign<Rhs>
- {
- }
- impl<T, Rhs> NumAssignOps<Rhs> for T where
- T: AddAssign<Rhs> + SubAssign<Rhs> + MulAssign<Rhs> + DivAssign<Rhs> + RemAssign<Rhs>
- {
- }
- /// The trait for `Num` types which also implement assignment operators.
- ///
- /// This is automatically implemented for types which implement the operators.
- pub trait NumAssign: Num + NumAssignOps {}
- impl<T> NumAssign for T where T: Num + NumAssignOps {}
- /// The trait for `NumAssign` types which also implement assignment operations
- /// taking the second operand by reference.
- ///
- /// This is automatically implemented for types which implement the operators.
- pub trait NumAssignRef: NumAssign + for<'r> NumAssignOps<&'r Self> {}
- impl<T> NumAssignRef for T where T: NumAssign + for<'r> NumAssignOps<&'r T> {}
- macro_rules! int_trait_impl {
- ($name:ident for $($t:ty)*) => ($(
- impl $name for $t {
- type FromStrRadixErr = ::core::num::ParseIntError;
- #[inline]
- fn from_str_radix(s: &str, radix: u32)
- -> Result<Self, ::core::num::ParseIntError>
- {
- <$t>::from_str_radix(s, radix)
- }
- }
- )*)
- }
- int_trait_impl!(Num for usize u8 u16 u32 u64 isize i8 i16 i32 i64);
- #[cfg(has_i128)]
- int_trait_impl!(Num for u128 i128);
- impl<T: Num> Num for Wrapping<T>
- where
- Wrapping<T>: Add<Output = Wrapping<T>>
- + Sub<Output = Wrapping<T>>
- + Mul<Output = Wrapping<T>>
- + Div<Output = Wrapping<T>>
- + Rem<Output = Wrapping<T>>,
- {
- type FromStrRadixErr = T::FromStrRadixErr;
- fn from_str_radix(str: &str, radix: u32) -> Result<Self, Self::FromStrRadixErr> {
- T::from_str_radix(str, radix).map(Wrapping)
- }
- }
- #[derive(Debug)]
- pub enum FloatErrorKind {
- Empty,
- Invalid,
- }
- // FIXME: core::num::ParseFloatError is stable in 1.0, but opaque to us,
- // so there's not really any way for us to reuse it.
- #[derive(Debug)]
- pub struct ParseFloatError {
- pub kind: FloatErrorKind,
- }
- impl fmt::Display for ParseFloatError {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- let description = match self.kind {
- FloatErrorKind::Empty => "cannot parse float from empty string",
- FloatErrorKind::Invalid => "invalid float literal",
- };
- description.fmt(f)
- }
- }
- // FIXME: The standard library from_str_radix on floats was deprecated, so we're stuck
- // with this implementation ourselves until we want to make a breaking change.
- // (would have to drop it from `Num` though)
- macro_rules! float_trait_impl {
- ($name:ident for $($t:ident)*) => ($(
- impl $name for $t {
- type FromStrRadixErr = ParseFloatError;
- fn from_str_radix(src: &str, radix: u32)
- -> Result<Self, Self::FromStrRadixErr>
- {
- use self::FloatErrorKind::*;
- use self::ParseFloatError as PFE;
- // Special values
- match src {
- "inf" => return Ok(core::$t::INFINITY),
- "-inf" => return Ok(core::$t::NEG_INFINITY),
- "NaN" => return Ok(core::$t::NAN),
- _ => {},
- }
- fn slice_shift_char(src: &str) -> Option<(char, &str)> {
- src.chars().nth(0).map(|ch| (ch, &src[1..]))
- }
- let (is_positive, src) = match slice_shift_char(src) {
- None => return Err(PFE { kind: Empty }),
- Some(('-', "")) => return Err(PFE { kind: Empty }),
- Some(('-', src)) => (false, src),
- Some((_, _)) => (true, src),
- };
- // The significand to accumulate
- let mut sig = if is_positive { 0.0 } else { -0.0 };
- // Necessary to detect overflow
- let mut prev_sig = sig;
- let mut cs = src.chars().enumerate();
- // Exponent prefix and exponent index offset
- let mut exp_info = None::<(char, usize)>;
- // Parse the integer part of the significand
- for (i, c) in cs.by_ref() {
- match c.to_digit(radix) {
- Some(digit) => {
- // shift significand one digit left
- sig = sig * (radix as $t);
- // add/subtract current digit depending on sign
- if is_positive {
- sig = sig + ((digit as isize) as $t);
- } else {
- sig = sig - ((digit as isize) as $t);
- }
- // Detect overflow by comparing to last value, except
- // if we've not seen any non-zero digits.
- if prev_sig != 0.0 {
- if is_positive && sig <= prev_sig
- { return Ok(core::$t::INFINITY); }
- if !is_positive && sig >= prev_sig
- { return Ok(core::$t::NEG_INFINITY); }
- // Detect overflow by reversing the shift-and-add process
- if is_positive && (prev_sig != (sig - digit as $t) / radix as $t)
- { return Ok(core::$t::INFINITY); }
- if !is_positive && (prev_sig != (sig + digit as $t) / radix as $t)
- { return Ok(core::$t::NEG_INFINITY); }
- }
- prev_sig = sig;
- },
- None => match c {
- 'e' | 'E' | 'p' | 'P' => {
- exp_info = Some((c, i + 1));
- break; // start of exponent
- },
- '.' => {
- break; // start of fractional part
- },
- _ => {
- return Err(PFE { kind: Invalid });
- },
- },
- }
- }
- // If we are not yet at the exponent parse the fractional
- // part of the significand
- if exp_info.is_none() {
- let mut power = 1.0;
- for (i, c) in cs.by_ref() {
- match c.to_digit(radix) {
- Some(digit) => {
- // Decrease power one order of magnitude
- power = power / (radix as $t);
- // add/subtract current digit depending on sign
- sig = if is_positive {
- sig + (digit as $t) * power
- } else {
- sig - (digit as $t) * power
- };
- // Detect overflow by comparing to last value
- if is_positive && sig < prev_sig
- { return Ok(core::$t::INFINITY); }
- if !is_positive && sig > prev_sig
- { return Ok(core::$t::NEG_INFINITY); }
- prev_sig = sig;
- },
- None => match c {
- 'e' | 'E' | 'p' | 'P' => {
- exp_info = Some((c, i + 1));
- break; // start of exponent
- },
- _ => {
- return Err(PFE { kind: Invalid });
- },
- },
- }
- }
- }
- // Parse and calculate the exponent
- let exp = match exp_info {
- Some((c, offset)) => {
- let base = match c {
- 'E' | 'e' if radix == 10 => 10.0,
- 'P' | 'p' if radix == 16 => 2.0,
- _ => return Err(PFE { kind: Invalid }),
- };
- // Parse the exponent as decimal integer
- let src = &src[offset..];
- let (is_positive, exp) = match slice_shift_char(src) {
- Some(('-', src)) => (false, src.parse::<usize>()),
- Some(('+', src)) => (true, src.parse::<usize>()),
- Some((_, _)) => (true, src.parse::<usize>()),
- None => return Err(PFE { kind: Invalid }),
- };
- #[cfg(feature = "std")]
- fn pow(base: $t, exp: usize) -> $t {
- Float::powi(base, exp as i32)
- }
- // otherwise uses the generic `pow` from the root
- match (is_positive, exp) {
- (true, Ok(exp)) => pow(base, exp),
- (false, Ok(exp)) => 1.0 / pow(base, exp),
- (_, Err(_)) => return Err(PFE { kind: Invalid }),
- }
- },
- None => 1.0, // no exponent
- };
- Ok(sig * exp)
- }
- }
- )*)
- }
- float_trait_impl!(Num for f32 f64);
- /// A value bounded by a minimum and a maximum
- ///
- /// If input is less than min then this returns min.
- /// If input is greater than max then this returns max.
- /// Otherwise this returns input.
- #[inline]
- pub fn clamp<T: PartialOrd>(input: T, min: T, max: T) -> T {
- debug_assert!(min <= max, "min must be less than or equal to max");
- if input < min {
- min
- } else if input > max {
- max
- } else {
- input
- }
- }
- /// A value bounded by a minimum value
- ///
- /// If input is less than min then this returns min.
- /// Otherwise this returns input.
- /// `clamp_min(std::f32::NAN, 1.0)` preserves `NAN` different from `f32::min(std::f32::NAN, 1.0)`.
- #[inline]
- pub fn clamp_min<T: PartialOrd>(input: T, min: T) -> T {
- if input < min {
- min
- } else {
- input
- }
- }
- /// A value bounded by a maximum value
- ///
- /// If input is less than min then this returns min.
- /// Otherwise this returns input.
- /// `clamp_max(std::f32::NAN, 1.0)` preserves `NAN` different from `f32::max(std::f32::NAN, 1.0)`.
- #[inline]
- pub fn clamp_max<T: PartialOrd>(input: T, max: T) -> T {
- if input > max {
- max
- } else {
- input
- }
- }
- #[test]
- fn clamp_test() {
- // Int test
- assert_eq!(1, clamp(1, -1, 2));
- assert_eq!(-1, clamp(-2, -1, 2));
- assert_eq!(2, clamp(3, -1, 2));
- assert_eq!(1, clamp_min(1, -1));
- assert_eq!(-1, clamp_min(-2, -1));
- assert_eq!(-1, clamp_max(1, -1));
- assert_eq!(-2, clamp_max(-2, -1));
- // Float test
- assert_eq!(1.0, clamp(1.0, -1.0, 2.0));
- assert_eq!(-1.0, clamp(-2.0, -1.0, 2.0));
- assert_eq!(2.0, clamp(3.0, -1.0, 2.0));
- assert_eq!(1.0, clamp_min(1.0, -1.0));
- assert_eq!(-1.0, clamp_min(-2.0, -1.0));
- assert_eq!(-1.0, clamp_max(1.0, -1.0));
- assert_eq!(-2.0, clamp_max(-2.0, -1.0));
- assert!(clamp(::core::f32::NAN, -1.0, 1.0).is_nan());
- assert!(clamp_min(::core::f32::NAN, 1.0).is_nan());
- assert!(clamp_max(::core::f32::NAN, 1.0).is_nan());
- }
- #[test]
- fn from_str_radix_unwrap() {
- // The Result error must impl Debug to allow unwrap()
- let i: i32 = Num::from_str_radix("0", 10).unwrap();
- assert_eq!(i, 0);
- let f: f32 = Num::from_str_radix("0.0", 10).unwrap();
- assert_eq!(f, 0.0);
- }
- #[test]
- fn wrapping_is_num() {
- fn require_num<T: Num>(_: &T) {}
- require_num(&Wrapping(42_u32));
- require_num(&Wrapping(-42));
- }
- #[test]
- fn wrapping_from_str_radix() {
- macro_rules! test_wrapping_from_str_radix {
- ($($t:ty)+) => {
- $(
- for &(s, r) in &[("42", 10), ("42", 2), ("-13.0", 10), ("foo", 10)] {
- let w = Wrapping::<$t>::from_str_radix(s, r).map(|w| w.0);
- assert_eq!(w, <$t as Num>::from_str_radix(s, r));
- }
- )+
- };
- }
- test_wrapping_from_str_radix!(usize u8 u16 u32 u64 isize i8 i16 i32 i64);
- }
- #[test]
- fn check_num_ops() {
- fn compute<T: Num + Copy>(x: T, y: T) -> T {
- x * y / y % y + y - y
- }
- assert_eq!(compute(1, 2), 1)
- }
- #[test]
- fn check_numref_ops() {
- fn compute<T: NumRef>(x: T, y: &T) -> T {
- x * y / y % y + y - y
- }
- assert_eq!(compute(1, &2), 1)
- }
- #[test]
- fn check_refnum_ops() {
- fn compute<T: Copy>(x: &T, y: T) -> T
- where
- for<'a> &'a T: RefNum<T>,
- {
- &(&(&(&(x * y) / y) % y) + y) - y
- }
- assert_eq!(compute(&1, 2), 1)
- }
- #[test]
- fn check_refref_ops() {
- fn compute<T>(x: &T, y: &T) -> T
- where
- for<'a> &'a T: RefNum<T>,
- {
- &(&(&(&(x * y) / y) % y) + y) - y
- }
- assert_eq!(compute(&1, &2), 1)
- }
- #[test]
- fn check_numassign_ops() {
- fn compute<T: NumAssign + Copy>(mut x: T, y: T) -> T {
- x *= y;
- x /= y;
- x %= y;
- x += y;
- x -= y;
- x
- }
- assert_eq!(compute(1, 2), 1)
- }
- // TODO test `NumAssignRef`, but even the standard numeric types don't
- // implement this yet. (see rust pr41336)
|