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.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
11 //! Numeric traits for generic mathematics
15 //! The `num-traits` crate is tested for rustc 1.8 and greater.
17 #![doc(html_root_url = "https://docs.rs/num-traits/0.2")]
18 #![deny(unconditional_recursion)]
20 #[cfg(feature = "std")]
23 // Only `no_std` builds actually use `libm`.
24 #[cfg(all(not(feature = "std"), feature = "libm"))]
28 use core
::num
::Wrapping
;
29 use core
::ops
::{Add, Div, Mul, Rem, Sub}
;
30 use core
::ops
::{AddAssign, DivAssign, MulAssign, RemAssign, SubAssign}
;
32 pub use bounds
::Bounded
;
33 #[cfg(any(feature = "std", feature = "libm"))]
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}
;
40 pub use ops
::checked
::{
41 CheckedAdd
, CheckedDiv
, CheckedMul
, CheckedNeg
, CheckedRem
, CheckedShl
, CheckedShr
, CheckedSub
,
43 pub use ops
::inv
::Inv
;
44 pub use ops
::mul_add
::{MulAdd, MulAddAssign}
;
45 pub use ops
::saturating
::{Saturating, SaturatingAdd, SaturatingMul, SaturatingSub}
;
46 pub use ops
::wrapping
::{
47 WrappingAdd
, WrappingMul
, WrappingNeg
, WrappingShl
, WrappingShr
, WrappingSub
,
49 pub use pow
::{checked_pow, pow, Pow}
;
50 pub use sign
::{abs, abs_sub, signum, Signed, Unsigned}
;
65 /// The base trait for numeric types, covering `0` and `1` values,
66 /// comparisons, basic numeric operations, and string conversion.
67 pub trait Num
: PartialEq
+ Zero
+ One
+ NumOps
{
70 /// Convert from a string and radix (typically `2..=36`).
75 /// use num_traits::Num;
77 /// let result = <i32 as Num>::from_str_radix("27", 10);
78 /// assert_eq!(result, Ok(27));
80 /// let result = <i32 as Num>::from_str_radix("foo", 10);
81 /// assert!(result.is_err());
84 /// # Supported radices
86 /// The exact range of supported radices is at the discretion of each type implementation. For
87 /// primitive integers, this is implemented by the inherent `from_str_radix` methods in the
88 /// standard library, which **panic** if the radix is not in the range from 2 to 36. The
89 /// implementation in this crate for primitive floats is similar.
91 /// For third-party types, it is suggested that implementations should follow suit and at least
92 /// accept `2..=36` without panicking, but an `Err` may be returned for any unsupported radix.
93 /// It's possible that a type might not even support the common radix 10, nor any, if string
94 /// parsing doesn't make sense for that type.
95 fn from_str_radix(str: &str, radix
: u32) -> Result
<Self, Self::FromStrRadixErr
>;
98 /// The trait for types implementing basic numeric operations
100 /// This is automatically implemented for types which implement the operators.
101 pub trait NumOps
<Rhs
= Self, Output
= Self>:
102 Add
<Rhs
, Output
= Output
>
103 + Sub
<Rhs
, Output
= Output
>
104 + Mul
<Rhs
, Output
= Output
>
105 + Div
<Rhs
, Output
= Output
>
106 + Rem
<Rhs
, Output
= Output
>
110 impl<T
, Rhs
, Output
> NumOps
<Rhs
, Output
> for T
where
111 T
: Add
<Rhs
, Output
= Output
>
112 + Sub
<Rhs
, Output
= Output
>
113 + Mul
<Rhs
, Output
= Output
>
114 + Div
<Rhs
, Output
= Output
>
115 + Rem
<Rhs
, Output
= Output
>
119 /// The trait for `Num` types which also implement numeric operations taking
120 /// the second operand by reference.
122 /// This is automatically implemented for types which implement the operators.
123 pub trait NumRef
: Num
+ for<'r
> NumOps
<&'r
Self> {}
124 impl<T
> NumRef
for T
where T
: Num
+ for<'r
> NumOps
<&'r T
> {}
126 /// The trait for references which implement numeric operations, taking the
127 /// second operand either by value or by reference.
129 /// This is automatically implemented for types which implement the operators.
130 pub trait RefNum
<Base
>: NumOps
<Base
, Base
> + for<'r
> NumOps
<&'r Base
, Base
> {}
131 impl<T
, Base
> RefNum
<Base
> for T
where T
: NumOps
<Base
, Base
> + for<'r
> NumOps
<&'r Base
, Base
> {}
133 /// The trait for types implementing numeric assignment operators (like `+=`).
135 /// This is automatically implemented for types which implement the operators.
136 pub trait NumAssignOps
<Rhs
= Self>:
137 AddAssign
<Rhs
> + SubAssign
<Rhs
> + MulAssign
<Rhs
> + DivAssign
<Rhs
> + RemAssign
<Rhs
>
141 impl<T
, Rhs
> NumAssignOps
<Rhs
> for T
where
142 T
: AddAssign
<Rhs
> + SubAssign
<Rhs
> + MulAssign
<Rhs
> + DivAssign
<Rhs
> + RemAssign
<Rhs
>
146 /// The trait for `Num` types which also implement assignment operators.
148 /// This is automatically implemented for types which implement the operators.
149 pub trait NumAssign
: Num
+ NumAssignOps {}
150 impl<T
> NumAssign
for T
where T
: Num
+ NumAssignOps {}
152 /// The trait for `NumAssign` types which also implement assignment operations
153 /// taking the second operand by reference.
155 /// This is automatically implemented for types which implement the operators.
156 pub trait NumAssignRef
: NumAssign
+ for<'r
> NumAssignOps
<&'r
Self> {}
157 impl<T
> NumAssignRef
for T
where T
: NumAssign
+ for<'r
> NumAssignOps
<&'r T
> {}
159 macro_rules
! int_trait_impl
{
160 ($name
:ident
for $
($t
:ty
)*) => ($
(
162 type FromStrRadixErr
= ::core
::num
::ParseIntError
;
164 fn from_str_radix(s
: &str, radix
: u32)
165 -> Result
<Self, ::core
::num
::ParseIntError
>
167 <$t
>::from_str_radix(s
, radix
)
172 int_trait_impl
!(Num
for usize u8 u16 u32 u64 isize i8 i16 i32 i64);
174 int_trait_impl
!(Num
for u128 i128
);
176 impl<T
: Num
> Num
for Wrapping
<T
>
178 Wrapping
<T
>: Add
<Output
= Wrapping
<T
>>
179 + Sub
<Output
= Wrapping
<T
>>
180 + Mul
<Output
= Wrapping
<T
>>
181 + Div
<Output
= Wrapping
<T
>>
182 + Rem
<Output
= Wrapping
<T
>>,
184 type FromStrRadixErr
= T
::FromStrRadixErr
;
185 fn from_str_radix(str: &str, radix
: u32) -> Result
<Self, Self::FromStrRadixErr
> {
186 T
::from_str_radix(str, radix
).map(Wrapping
)
191 pub enum FloatErrorKind
{
195 // FIXME: core::num::ParseFloatError is stable in 1.0, but opaque to us,
196 // so there's not really any way for us to reuse it.
198 pub struct ParseFloatError
{
199 pub kind
: FloatErrorKind
,
202 impl fmt
::Display
for ParseFloatError
{
203 fn fmt(&self, f
: &mut fmt
::Formatter
) -> fmt
::Result
{
204 let description
= match self.kind
{
205 FloatErrorKind
::Empty
=> "cannot parse float from empty string",
206 FloatErrorKind
::Invalid
=> "invalid float literal",
213 // FIXME: The standard library from_str_radix on floats was deprecated, so we're stuck
214 // with this implementation ourselves until we want to make a breaking change.
215 // (would have to drop it from `Num` though)
216 macro_rules
! float_trait_impl
{
217 ($name
:ident
for $
($t
:ident
)*) => ($
(
219 type FromStrRadixErr
= ParseFloatError
;
221 fn from_str_radix(src
: &str, radix
: u32)
222 -> Result
<Self, Self::FromStrRadixErr
>
224 use self::FloatErrorKind
::*;
225 use self::ParseFloatError
as PFE
;
229 "inf" => return Ok(core
::$t
::INFINITY
),
230 "-inf" => return Ok(core
::$t
::NEG_INFINITY
),
231 "NaN" => return Ok(core
::$t
::NAN
),
235 fn slice_shift_char(src
: &str) -> Option
<(char, &str)> {
236 let mut chars
= src
.chars();
237 if let Some(ch
) = chars
.next() {
238 Some((ch
, chars
.as_str()))
244 let (is_positive
, src
) = match slice_shift_char(src
) {
245 None
=> return Err(PFE { kind: Empty }
),
246 Some(('
-'
, "")) => return Err(PFE { kind: Empty }
),
247 Some(('
-'
, src
)) => (false, src
),
248 Some((_
, _
)) => (true, src
),
251 // The significand to accumulate
252 let mut sig
= if is_positive { 0.0 }
else { -0.0 }
;
253 // Necessary to detect overflow
254 let mut prev_sig
= sig
;
255 let mut cs
= src
.chars().enumerate();
256 // Exponent prefix and exponent index offset
257 let mut exp_info
= None
::<(char, usize)>;
259 // Parse the integer part of the significand
260 for (i
, c
) in cs
.by_ref() {
261 match c
.to_digit(radix
) {
263 // shift significand one digit left
264 sig
= sig
* (radix
as $t
);
266 // add/subtract current digit depending on sign
268 sig
= sig
+ ((digit
as isize) as $t
);
270 sig
= sig
- ((digit
as isize) as $t
);
273 // Detect overflow by comparing to last value, except
274 // if we've not seen any non-zero digits.
276 if is_positive
&& sig
<= prev_sig
277 { return Ok(core::$t::INFINITY); }
278 if !is_positive
&& sig
>= prev_sig
279 { return Ok(core::$t::NEG_INFINITY); }
281 // Detect overflow by reversing the shift-and-add process
282 if is_positive
&& (prev_sig
!= (sig
- digit
as $t
) / radix
as $t
)
283 { return Ok(core::$t::INFINITY); }
284 if !is_positive
&& (prev_sig
!= (sig
+ digit
as $t
) / radix
as $t
)
285 { return Ok(core::$t::NEG_INFINITY); }
290 'e'
| 'E'
| 'p'
| 'P'
=> {
291 exp_info
= Some((c
, i
+ 1));
292 break; // start of exponent
295 break; // start of fractional part
298 return Err(PFE { kind: Invalid }
);
304 // If we are not yet at the exponent parse the fractional
305 // part of the significand
306 if exp_info
.is_none() {
308 for (i
, c
) in cs
.by_ref() {
309 match c
.to_digit(radix
) {
311 // Decrease power one order of magnitude
312 power
= power
/ (radix
as $t
);
313 // add/subtract current digit depending on sign
314 sig
= if is_positive
{
315 sig
+ (digit
as $t
) * power
317 sig
- (digit
as $t
) * power
319 // Detect overflow by comparing to last value
320 if is_positive
&& sig
< prev_sig
321 { return Ok(core::$t::INFINITY); }
322 if !is_positive
&& sig
> prev_sig
323 { return Ok(core::$t::NEG_INFINITY); }
327 'e'
| 'E'
| 'p'
| 'P'
=> {
328 exp_info
= Some((c
, i
+ 1));
329 break; // start of exponent
332 return Err(PFE { kind: Invalid }
);
339 // Parse and calculate the exponent
340 let exp
= match exp_info
{
341 Some((c
, offset
)) => {
343 'E'
| 'e'
if radix
== 10 => 10.0,
344 'P'
| 'p'
if radix
== 16 => 2.0,
345 _
=> return Err(PFE { kind: Invalid }
),
348 // Parse the exponent as decimal integer
349 let src
= &src
[offset
..];
350 let (is_positive
, exp
) = match slice_shift_char(src
) {
351 Some(('
-'
, src
)) => (false, src
.parse
::<usize>()),
352 Some(('
+'
, src
)) => (true, src
.parse
::<usize>()),
353 Some((_
, _
)) => (true, src
.parse
::<usize>()),
354 None
=> return Err(PFE { kind: Invalid }
),
357 #[cfg(feature = "std")]
358 fn pow(base
: $t
, exp
: usize) -> $t
{
359 Float
::powi(base
, exp
as i32)
361 // otherwise uses the generic `pow` from the root
363 match (is_positive
, exp
) {
364 (true, Ok(exp
)) => pow(base
, exp
),
365 (false, Ok(exp
)) => 1.0 / pow(base
, exp
),
366 (_
, Err(_
)) => return Err(PFE { kind: Invalid }
),
369 None
=> 1.0, // no exponent
377 float_trait_impl
!(Num
for f32 f64);
379 /// A value bounded by a minimum and a maximum
381 /// If input is less than min then this returns min.
382 /// If input is greater than max then this returns max.
383 /// Otherwise this returns input.
385 /// **Panics** in debug mode if `!(min <= max)`.
387 pub fn clamp
<T
: PartialOrd
>(input
: T
, min
: T
, max
: T
) -> T
{
388 debug_assert
!(min
<= max
, "min must be less than or equal to max");
391 } else if input
> max
{
398 /// A value bounded by a minimum value
400 /// If input is less than min then this returns min.
401 /// Otherwise this returns input.
402 /// `clamp_min(std::f32::NAN, 1.0)` preserves `NAN` different from `f32::min(std::f32::NAN, 1.0)`.
404 /// **Panics** in debug mode if `!(min == min)`. (This occurs if `min` is `NAN`.)
406 pub fn clamp_min
<T
: PartialOrd
>(input
: T
, min
: T
) -> T
{
407 debug_assert
!(min
== min
, "min must not be NAN");
415 /// A value bounded by a maximum value
417 /// If input is greater than max then this returns max.
418 /// Otherwise this returns input.
419 /// `clamp_max(std::f32::NAN, 1.0)` preserves `NAN` different from `f32::max(std::f32::NAN, 1.0)`.
421 /// **Panics** in debug mode if `!(max == max)`. (This occurs if `max` is `NAN`.)
423 pub fn clamp_max
<T
: PartialOrd
>(input
: T
, max
: T
) -> T
{
424 debug_assert
!(max
== max
, "max must not be NAN");
435 assert_eq
!(1, clamp(1, -1, 2));
436 assert_eq
!(-1, clamp(-2, -1, 2));
437 assert_eq
!(2, clamp(3, -1, 2));
438 assert_eq
!(1, clamp_min(1, -1));
439 assert_eq
!(-1, clamp_min(-2, -1));
440 assert_eq
!(-1, clamp_max(1, -1));
441 assert_eq
!(-2, clamp_max(-2, -1));
444 assert_eq
!(1.0, clamp(1.0, -1.0, 2.0));
445 assert_eq
!(-1.0, clamp(-2.0, -1.0, 2.0));
446 assert_eq
!(2.0, clamp(3.0, -1.0, 2.0));
447 assert_eq
!(1.0, clamp_min(1.0, -1.0));
448 assert_eq
!(-1.0, clamp_min(-2.0, -1.0));
449 assert_eq
!(-1.0, clamp_max(1.0, -1.0));
450 assert_eq
!(-2.0, clamp_max(-2.0, -1.0));
451 assert
!(clamp(::core
::f32::NAN
, -1.0, 1.0).is_nan());
452 assert
!(clamp_min(::core
::f32::NAN
, 1.0).is_nan());
453 assert
!(clamp_max(::core
::f32::NAN
, 1.0).is_nan());
458 #[cfg(debug_assertions)]
460 clamp(0., ::core
::f32::NAN
, 1.);
465 #[cfg(debug_assertions)]
467 clamp(0., -1., ::core
::f32::NAN
);
472 #[cfg(debug_assertions)]
473 fn clamp_nan_min_max() {
474 clamp(0., ::core
::f32::NAN
, ::core
::f32::NAN
);
479 #[cfg(debug_assertions)]
480 fn clamp_min_nan_min() {
481 clamp_min(0., ::core
::f32::NAN
);
486 #[cfg(debug_assertions)]
487 fn clamp_max_nan_max() {
488 clamp_max(0., ::core
::f32::NAN
);
492 fn from_str_radix_unwrap() {
493 // The Result error must impl Debug to allow unwrap()
495 let i
: i32 = Num
::from_str_radix("0", 10).unwrap();
498 let f
: f32 = Num
::from_str_radix("0.0", 10).unwrap();
503 fn from_str_radix_multi_byte_fail() {
504 // Ensure parsing doesn't panic, even on invalid sign characters
505 assert
!(f32::from_str_radix("™0.2", 10).is_err());
507 // Even when parsing the exponent sign
508 assert
!(f32::from_str_radix("0.2E™1", 10).is_err());
512 fn wrapping_is_num() {
513 fn require_num
<T
: Num
>(_
: &T
) {}
514 require_num(&Wrapping(42_u32));
515 require_num(&Wrapping(-42));
519 fn wrapping_from_str_radix() {
520 macro_rules
! test_wrapping_from_str_radix
{
523 for &(s
, r
) in &[("42", 10), ("42", 2), ("-13.0", 10), ("foo", 10)] {
524 let w
= Wrapping
::<$t
>::from_str_radix(s
, r
).map(|w
| w
.0);
525 assert_eq
!(w
, <$t
as Num
>::from_str_radix(s
, r
));
531 test_wrapping_from_str_radix
!(usize u8 u16 u32 u64 isize i8 i16 i32 i64);
536 fn compute
<T
: Num
+ Copy
>(x
: T
, y
: T
) -> T
{
537 x
* y
/ y
% y
+ y
- y
539 assert_eq
!(compute(1, 2), 1)
543 fn check_numref_ops() {
544 fn compute
<T
: NumRef
>(x
: T
, y
: &T
) -> T
{
545 x
* y
/ y
% y
+ y
- y
547 assert_eq
!(compute(1, &2), 1)
551 fn check_refnum_ops() {
552 fn compute
<T
: Copy
>(x
: &T
, y
: T
) -> T
554 for<'a
> &'a T
: RefNum
<T
>,
556 &(&(&(&(x
* y
) / y
) % y
) + y
) - y
558 assert_eq
!(compute(&1, 2), 1)
562 fn check_refref_ops() {
563 fn compute
<T
>(x
: &T
, y
: &T
) -> T
565 for<'a
> &'a T
: RefNum
<T
>,
567 &(&(&(&(x
* y
) / y
) % y
) + y
) - y
569 assert_eq
!(compute(&1, &2), 1)
573 fn check_numassign_ops() {
574 fn compute
<T
: NumAssign
+ Copy
>(mut x
: T
, y
: T
) -> T
{
582 assert_eq
!(compute(1, 2), 1)
585 // TODO test `NumAssignRef`, but even the standard numeric types don't
586 // implement this yet. (see rust pr41336)