/rust/registry/src/index.crates.io-6f17d22bba15001f/num-traits-0.2.15/src/lib.rs
Line | Count | Source (jump to first uncovered line) |
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::euclid::{CheckedEuclid, Euclid}; |
44 | | pub use ops::inv::Inv; |
45 | | pub use ops::mul_add::{MulAdd, MulAddAssign}; |
46 | | pub use ops::saturating::{Saturating, SaturatingAdd, SaturatingMul, SaturatingSub}; |
47 | | pub use ops::wrapping::{ |
48 | | WrappingAdd, WrappingMul, WrappingNeg, WrappingShl, WrappingShr, WrappingSub, |
49 | | }; |
50 | | pub use pow::{checked_pow, pow, Pow}; |
51 | | pub use sign::{abs, abs_sub, signum, Signed, Unsigned}; |
52 | | |
53 | | #[macro_use] |
54 | | mod macros; |
55 | | |
56 | | pub mod bounds; |
57 | | pub mod cast; |
58 | | pub mod float; |
59 | | pub mod identities; |
60 | | pub mod int; |
61 | | pub mod ops; |
62 | | pub mod pow; |
63 | | pub mod real; |
64 | | pub mod sign; |
65 | | |
66 | | /// The base trait for numeric types, covering `0` and `1` values, |
67 | | /// comparisons, basic numeric operations, and string conversion. |
68 | | pub 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. |
102 | | pub 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 | | |
111 | | impl<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. |
124 | | pub trait NumRef: Num + for<'r> NumOps<&'r Self> {} |
125 | | impl<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`. |
133 | | pub trait RefNum<Base>: NumOps<Base, Base> + for<'r> NumOps<&'r Base, Base> {} |
134 | | impl<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. |
139 | | pub trait NumAssignOps<Rhs = Self>: |
140 | | AddAssign<Rhs> + SubAssign<Rhs> + MulAssign<Rhs> + DivAssign<Rhs> + RemAssign<Rhs> |
141 | | { |
142 | | } |
143 | | |
144 | | impl<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. |
152 | | pub trait NumAssign: Num + NumAssignOps {} |
153 | | impl<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. |
159 | | pub trait NumAssignRef: NumAssign + for<'r> NumAssignOps<&'r Self> {} |
160 | | impl<T> NumAssignRef for T where T: NumAssign + for<'r> NumAssignOps<&'r T> {} |
161 | | |
162 | | macro_rules! int_trait_impl { |
163 | | ($name:ident for $($t:ty)*) => ($( |
164 | | impl $name for $t { |
165 | | type FromStrRadixErr = ::core::num::ParseIntError; |
166 | | #[inline] |
167 | 0 | fn from_str_radix(s: &str, radix: u32) |
168 | 0 | -> Result<Self, ::core::num::ParseIntError> |
169 | 0 | { |
170 | 0 | <$t>::from_str_radix(s, radix) |
171 | 0 | } Unexecuted instantiation: <usize as num_traits::Num>::from_str_radix Unexecuted instantiation: <u8 as num_traits::Num>::from_str_radix Unexecuted instantiation: <u16 as num_traits::Num>::from_str_radix Unexecuted instantiation: <u32 as num_traits::Num>::from_str_radix Unexecuted instantiation: <u64 as num_traits::Num>::from_str_radix Unexecuted instantiation: <isize as num_traits::Num>::from_str_radix Unexecuted instantiation: <i8 as num_traits::Num>::from_str_radix Unexecuted instantiation: <i16 as num_traits::Num>::from_str_radix Unexecuted instantiation: <i32 as num_traits::Num>::from_str_radix Unexecuted instantiation: <i64 as num_traits::Num>::from_str_radix Unexecuted instantiation: <u128 as num_traits::Num>::from_str_radix Unexecuted instantiation: <i128 as num_traits::Num>::from_str_radix |
172 | | } |
173 | | )*) |
174 | | } |
175 | | int_trait_impl!(Num for usize u8 u16 u32 u64 isize i8 i16 i32 i64); |
176 | | #[cfg(has_i128)] |
177 | | int_trait_impl!(Num for u128 i128); |
178 | | |
179 | | impl<T: Num> Num for Wrapping<T> |
180 | | where |
181 | | Wrapping<T>: NumOps, |
182 | | { |
183 | | type FromStrRadixErr = T::FromStrRadixErr; |
184 | 0 | fn from_str_radix(str: &str, radix: u32) -> Result<Self, Self::FromStrRadixErr> { |
185 | 0 | T::from_str_radix(str, radix).map(Wrapping) |
186 | 0 | } |
187 | | } |
188 | | |
189 | | #[derive(Debug)] |
190 | | pub 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)] |
197 | | pub struct ParseFloatError { |
198 | | pub kind: FloatErrorKind, |
199 | | } |
200 | | |
201 | | impl fmt::Display for ParseFloatError { |
202 | 0 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
203 | 0 | let description = match self.kind { |
204 | 0 | FloatErrorKind::Empty => "cannot parse float from empty string", |
205 | 0 | FloatErrorKind::Invalid => "invalid float literal", |
206 | | }; |
207 | | |
208 | 0 | description.fmt(f) |
209 | 0 | } |
210 | | } |
211 | | |
212 | 0 | fn str_to_ascii_lower_eq_str(a: &str, b: &str) -> bool { |
213 | 0 | a.len() == b.len() |
214 | 0 | && a.bytes().zip(b.bytes()).all(|(a, b)| { |
215 | 0 | let a_to_ascii_lower = a | (((b'A' <= a && a <= b'Z') as u8) << 5); |
216 | 0 | a_to_ascii_lower == b |
217 | 0 | }) |
218 | 0 | } |
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) |
223 | | macro_rules! float_trait_impl { |
224 | | ($name:ident for $($t:ident)*) => ($( |
225 | | impl $name for $t { |
226 | | type FromStrRadixErr = ParseFloatError; |
227 | | |
228 | 0 | fn from_str_radix(src: &str, radix: u32) |
229 | 0 | -> Result<Self, Self::FromStrRadixErr> |
230 | 0 | { |
231 | | use self::FloatErrorKind::*; |
232 | | use self::ParseFloatError as PFE; |
233 | | |
234 | | // Special case radix 10 to use more accurate standard library implementation |
235 | 0 | if radix == 10 { |
236 | 0 | return src.parse().map_err(|_| PFE { |
237 | 0 | kind: if src.is_empty() { Empty } else { Invalid }, |
238 | 0 | }); Unexecuted instantiation: <f32 as num_traits::Num>::from_str_radix::{closure#0} Unexecuted instantiation: <f64 as num_traits::Num>::from_str_radix::{closure#0} |
239 | 0 | } |
240 | 0 |
|
241 | 0 | // Special values |
242 | 0 | if str_to_ascii_lower_eq_str(src, "inf") |
243 | 0 | || str_to_ascii_lower_eq_str(src, "infinity") |
244 | | { |
245 | 0 | return Ok(core::$t::INFINITY); |
246 | 0 | } else if str_to_ascii_lower_eq_str(src, "-inf") |
247 | 0 | || str_to_ascii_lower_eq_str(src, "-infinity") |
248 | | { |
249 | 0 | return Ok(core::$t::NEG_INFINITY); |
250 | 0 | } else if str_to_ascii_lower_eq_str(src, "nan") { |
251 | 0 | return Ok(core::$t::NAN); |
252 | 0 | } else if str_to_ascii_lower_eq_str(src, "-nan") { |
253 | 0 | return Ok(-core::$t::NAN); |
254 | 0 | } |
255 | | |
256 | 0 | fn slice_shift_char(src: &str) -> Option<(char, &str)> { |
257 | 0 | let mut chars = src.chars(); |
258 | 0 | if let Some(ch) = chars.next() { |
259 | 0 | Some((ch, chars.as_str())) |
260 | | } else { |
261 | 0 | None |
262 | | } |
263 | 0 | } Unexecuted instantiation: <f32 as num_traits::Num>::from_str_radix::slice_shift_char Unexecuted instantiation: <f64 as num_traits::Num>::from_str_radix::slice_shift_char |
264 | | |
265 | 0 | let (is_positive, src) = match slice_shift_char(src) { |
266 | 0 | None => return Err(PFE { kind: Empty }), |
267 | 0 | Some(('-', "")) => return Err(PFE { kind: Empty }), |
268 | 0 | Some(('-', src)) => (false, src), |
269 | 0 | Some((_, _)) => (true, src), |
270 | | }; |
271 | | |
272 | | // The significand to accumulate |
273 | 0 | let mut sig = if is_positive { 0.0 } else { -0.0 }; |
274 | | // Necessary to detect overflow |
275 | 0 | let mut prev_sig = sig; |
276 | 0 | let mut cs = src.chars().enumerate(); |
277 | 0 | // Exponent prefix and exponent index offset |
278 | 0 | let mut exp_info = None::<(char, usize)>; |
279 | | |
280 | | // Parse the integer part of the significand |
281 | 0 | for (i, c) in cs.by_ref() { |
282 | 0 | match c.to_digit(radix) { |
283 | 0 | Some(digit) => { |
284 | 0 | // shift significand one digit left |
285 | 0 | sig = sig * (radix as $t); |
286 | 0 |
|
287 | 0 | // add/subtract current digit depending on sign |
288 | 0 | if is_positive { |
289 | 0 | sig = sig + ((digit as isize) as $t); |
290 | 0 | } else { |
291 | 0 | sig = sig - ((digit as isize) as $t); |
292 | 0 | } |
293 | | |
294 | | // Detect overflow by comparing to last value, except |
295 | | // if we've not seen any non-zero digits. |
296 | 0 | if prev_sig != 0.0 { |
297 | 0 | if is_positive && sig <= prev_sig |
298 | 0 | { return Ok(core::$t::INFINITY); } |
299 | 0 | if !is_positive && sig >= prev_sig |
300 | 0 | { return Ok(core::$t::NEG_INFINITY); } |
301 | 0 |
|
302 | 0 | // Detect overflow by reversing the shift-and-add process |
303 | 0 | if is_positive && (prev_sig != (sig - digit as $t) / radix as $t) |
304 | 0 | { return Ok(core::$t::INFINITY); } |
305 | 0 | if !is_positive && (prev_sig != (sig + digit as $t) / radix as $t) |
306 | 0 | { return Ok(core::$t::NEG_INFINITY); } |
307 | 0 | } |
308 | 0 | prev_sig = sig; |
309 | | }, |
310 | 0 | None => match c { |
311 | | 'e' | 'E' | 'p' | 'P' => { |
312 | 0 | exp_info = Some((c, i + 1)); |
313 | 0 | break; // start of exponent |
314 | | }, |
315 | | '.' => { |
316 | 0 | break; // start of fractional part |
317 | | }, |
318 | | _ => { |
319 | 0 | 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 | 0 | if exp_info.is_none() { |
328 | 0 | let mut power = 1.0; |
329 | 0 | for (i, c) in cs.by_ref() { |
330 | 0 | match c.to_digit(radix) { |
331 | 0 | Some(digit) => { |
332 | 0 | // Decrease power one order of magnitude |
333 | 0 | power = power / (radix as $t); |
334 | 0 | // add/subtract current digit depending on sign |
335 | 0 | sig = if is_positive { |
336 | 0 | sig + (digit as $t) * power |
337 | | } else { |
338 | 0 | sig - (digit as $t) * power |
339 | | }; |
340 | | // Detect overflow by comparing to last value |
341 | 0 | if is_positive && sig < prev_sig |
342 | 0 | { return Ok(core::$t::INFINITY); } |
343 | 0 | if !is_positive && sig > prev_sig |
344 | 0 | { return Ok(core::$t::NEG_INFINITY); } |
345 | 0 | prev_sig = sig; |
346 | | }, |
347 | 0 | None => match c { |
348 | | 'e' | 'E' | 'p' | 'P' => { |
349 | 0 | exp_info = Some((c, i + 1)); |
350 | 0 | break; // start of exponent |
351 | | }, |
352 | | _ => { |
353 | 0 | return Err(PFE { kind: Invalid }); |
354 | | }, |
355 | | }, |
356 | | } |
357 | | } |
358 | 0 | } |
359 | | |
360 | | // Parse and calculate the exponent |
361 | 0 | let exp = match exp_info { |
362 | 0 | Some((c, offset)) => { |
363 | 0 | let base = match c { |
364 | 0 | 'E' | 'e' if radix == 10 => 10.0, |
365 | 0 | 'P' | 'p' if radix == 16 => 2.0, |
366 | 0 | _ => return Err(PFE { kind: Invalid }), |
367 | | }; |
368 | | |
369 | | // Parse the exponent as decimal integer |
370 | 0 | let src = &src[offset..]; |
371 | 0 | let (is_positive, exp) = match slice_shift_char(src) { |
372 | 0 | Some(('-', src)) => (false, src.parse::<usize>()), |
373 | 0 | Some(('+', src)) => (true, src.parse::<usize>()), |
374 | 0 | Some((_, _)) => (true, src.parse::<usize>()), |
375 | 0 | None => return Err(PFE { kind: Invalid }), |
376 | | }; |
377 | | |
378 | | #[cfg(feature = "std")] |
379 | 0 | fn pow(base: $t, exp: usize) -> $t { |
380 | 0 | Float::powi(base, exp as i32) |
381 | 0 | } Unexecuted instantiation: <f32 as num_traits::Num>::from_str_radix::pow Unexecuted instantiation: <f64 as num_traits::Num>::from_str_radix::pow |
382 | | // otherwise uses the generic `pow` from the root |
383 | | |
384 | 0 | match (is_positive, exp) { |
385 | 0 | (true, Ok(exp)) => pow(base, exp), |
386 | 0 | (false, Ok(exp)) => 1.0 / pow(base, exp), |
387 | 0 | (_, Err(_)) => return Err(PFE { kind: Invalid }), |
388 | | } |
389 | | }, |
390 | 0 | None => 1.0, // no exponent |
391 | | }; |
392 | | |
393 | 0 | Ok(sig * exp) |
394 | 0 | } Unexecuted instantiation: <f32 as num_traits::Num>::from_str_radix Unexecuted instantiation: <f64 as num_traits::Num>::from_str_radix |
395 | | } |
396 | | )*) |
397 | | } |
398 | | float_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] |
408 | 0 | pub fn clamp<T: PartialOrd>(input: T, min: T, max: T) -> T { |
409 | 0 | debug_assert!(min <= max, "min must be less than or equal to max"); |
410 | 0 | if input < min { |
411 | 0 | min |
412 | 0 | } else if input > max { |
413 | 0 | max |
414 | | } else { |
415 | 0 | input |
416 | | } |
417 | 0 | } |
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] |
427 | 0 | pub fn clamp_min<T: PartialOrd>(input: T, min: T) -> T { |
428 | 0 | debug_assert!(min == min, "min must not be NAN"); |
429 | 0 | if input < min { |
430 | 0 | min |
431 | | } else { |
432 | 0 | input |
433 | | } |
434 | 0 | } |
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] |
444 | 0 | pub fn clamp_max<T: PartialOrd>(input: T, max: T) -> T { |
445 | 0 | debug_assert!(max == max, "max must not be NAN"); |
446 | 0 | if input > max { |
447 | 0 | max |
448 | | } else { |
449 | 0 | input |
450 | | } |
451 | 0 | } |
452 | | |
453 | | #[test] |
454 | | fn 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)] |
480 | | fn clamp_nan_min() { |
481 | | clamp(0., ::core::f32::NAN, 1.); |
482 | | } |
483 | | |
484 | | #[test] |
485 | | #[should_panic] |
486 | | #[cfg(debug_assertions)] |
487 | | fn clamp_nan_max() { |
488 | | clamp(0., -1., ::core::f32::NAN); |
489 | | } |
490 | | |
491 | | #[test] |
492 | | #[should_panic] |
493 | | #[cfg(debug_assertions)] |
494 | | fn clamp_nan_min_max() { |
495 | | clamp(0., ::core::f32::NAN, ::core::f32::NAN); |
496 | | } |
497 | | |
498 | | #[test] |
499 | | #[should_panic] |
500 | | #[cfg(debug_assertions)] |
501 | | fn clamp_min_nan_min() { |
502 | | clamp_min(0., ::core::f32::NAN); |
503 | | } |
504 | | |
505 | | #[test] |
506 | | #[should_panic] |
507 | | #[cfg(debug_assertions)] |
508 | | fn clamp_max_nan_max() { |
509 | | clamp_max(0., ::core::f32::NAN); |
510 | | } |
511 | | |
512 | | #[test] |
513 | | fn 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] |
524 | | fn 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] |
533 | | fn 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] |
555 | | fn 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] |
562 | | fn 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] |
578 | | fn 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] |
586 | | fn 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] |
594 | | fn 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] |
605 | | fn 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] |
616 | | fn 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] |
630 | | fn 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 | | } |