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