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