lib.rs 21 KB

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