lib.rs 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435
  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. #![doc(html_logo_url = "https://rust-num.github.io/num/rust-logo-128x128-blk-v2.png",
  12. html_favicon_url = "https://rust-num.github.io/num/favicon.ico",
  13. html_root_url = "https://rust-num.github.io/num/",
  14. html_playground_url = "http://play.integer32.com/")]
  15. use std::ops::{Add, Sub, Mul, Div, Rem};
  16. use std::ops::{AddAssign, SubAssign, MulAssign, DivAssign, RemAssign};
  17. use std::num::Wrapping;
  18. pub use bounds::Bounded;
  19. pub use float::{Float, FloatConst};
  20. pub use identities::{Zero, One, zero, one};
  21. pub use ops::checked::*;
  22. pub use ops::wrapping::*;
  23. pub use ops::saturating::Saturating;
  24. pub use sign::{Signed, Unsigned, abs, abs_sub, signum};
  25. pub use cast::*;
  26. pub use int::PrimInt;
  27. pub use pow::{pow, checked_pow};
  28. pub mod identities;
  29. pub mod sign;
  30. pub mod ops;
  31. pub mod bounds;
  32. pub mod float;
  33. pub mod cast;
  34. pub mod int;
  35. pub mod pow;
  36. /// The base trait for numeric types, covering `0` and `1` values,
  37. /// comparisons, basic numeric operations, and string conversion.
  38. pub trait Num: PartialEq + Zero + One + NumOps
  39. {
  40. type FromStrRadixErr;
  41. /// Convert from a string and radix <= 36.
  42. ///
  43. /// # Examples
  44. ///
  45. /// ```rust
  46. /// use num_traits::Num;
  47. ///
  48. /// let result = <i32 as Num>::from_str_radix("27", 10);
  49. /// assert_eq!(result, Ok(27));
  50. ///
  51. /// let result = <i32 as Num>::from_str_radix("foo", 10);
  52. /// assert!(result.is_err());
  53. /// ```
  54. fn from_str_radix(str: &str, radix: u32) -> Result<Self, Self::FromStrRadixErr>;
  55. }
  56. /// The trait for types implementing basic numeric operations
  57. ///
  58. /// This is automatically implemented for types which implement the operators.
  59. pub trait NumOps<Rhs = Self, Output = Self>
  60. : Add<Rhs, Output = Output>
  61. + Sub<Rhs, Output = Output>
  62. + Mul<Rhs, Output = Output>
  63. + Div<Rhs, Output = Output>
  64. + Rem<Rhs, Output = Output>
  65. {}
  66. impl<T, Rhs, Output> NumOps<Rhs, Output> for T
  67. where T: Add<Rhs, Output = Output>
  68. + Sub<Rhs, Output = Output>
  69. + Mul<Rhs, Output = Output>
  70. + Div<Rhs, Output = Output>
  71. + Rem<Rhs, Output = Output>
  72. {}
  73. /// The trait for `Num` types which also implement numeric operations taking
  74. /// the second operand by reference.
  75. ///
  76. /// This is automatically implemented for types which implement the operators.
  77. pub trait NumRef: Num + for<'r> NumOps<&'r Self> {}
  78. impl<T> NumRef for T where T: Num + for<'r> NumOps<&'r T> {}
  79. /// The trait for references which implement numeric operations, taking the
  80. /// second operand either by value or by reference.
  81. ///
  82. /// This is automatically implemented for all `&T` implementing the operators.
  83. pub trait RefNum<Base>: NumOps<Base, Base> + for<'r> NumOps<&'r Base, Base> {}
  84. impl<'a, T> RefNum<T> for &'a T where &'a T: NumOps<T, T> + for<'r> NumOps<&'r T, T> {}
  85. /// The trait for types implementing numeric assignment operators (like `+=`).
  86. ///
  87. /// This is automatically implemented for types which implement the operators.
  88. pub trait NumAssignOps<Rhs = Self>
  89. : AddAssign<Rhs>
  90. + SubAssign<Rhs>
  91. + MulAssign<Rhs>
  92. + DivAssign<Rhs>
  93. + RemAssign<Rhs>
  94. {}
  95. impl<T, Rhs> NumAssignOps<Rhs> for T
  96. where T: AddAssign<Rhs>
  97. + SubAssign<Rhs>
  98. + MulAssign<Rhs>
  99. + DivAssign<Rhs>
  100. + RemAssign<Rhs>
  101. {}
  102. /// The trait for `Num` types which also implement assignment operators.
  103. ///
  104. /// This is automatically implemented for types which implement the operators.
  105. pub trait NumAssign: Num + NumAssignOps {}
  106. impl<T> NumAssign for T where T: Num + NumAssignOps {}
  107. /// The trait for `NumAssign` types which also implement assignment operations
  108. /// taking the second operand by reference.
  109. ///
  110. /// This is automatically implemented for types which implement the operators.
  111. pub trait NumAssignRef: NumAssign + for<'r> NumAssignOps<&'r Self> {}
  112. impl<T> NumAssignRef for T where T: NumAssign + for<'r> NumAssignOps<&'r T> {}
  113. macro_rules! int_trait_impl {
  114. ($name:ident for $($t:ty)*) => ($(
  115. impl $name for $t {
  116. type FromStrRadixErr = ::std::num::ParseIntError;
  117. #[inline]
  118. fn from_str_radix(s: &str, radix: u32)
  119. -> Result<Self, ::std::num::ParseIntError>
  120. {
  121. <$t>::from_str_radix(s, radix)
  122. }
  123. }
  124. )*)
  125. }
  126. int_trait_impl!(Num for usize u8 u16 u32 u64 isize i8 i16 i32 i64);
  127. impl<T: Num> Num for Wrapping<T>
  128. where Wrapping<T>:
  129. Add<Output = Wrapping<T>> + Sub<Output = Wrapping<T>>
  130. + Mul<Output = Wrapping<T>> + Div<Output = Wrapping<T>> + Rem<Output = Wrapping<T>>
  131. {
  132. type FromStrRadixErr = T::FromStrRadixErr;
  133. fn from_str_radix(str: &str, radix: u32) -> Result<Self, Self::FromStrRadixErr> {
  134. T::from_str_radix(str, radix).map(Wrapping)
  135. }
  136. }
  137. #[derive(Debug)]
  138. pub enum FloatErrorKind {
  139. Empty,
  140. Invalid,
  141. }
  142. // FIXME: std::num::ParseFloatError is stable in 1.0, but opaque to us,
  143. // so there's not really any way for us to reuse it.
  144. #[derive(Debug)]
  145. pub struct ParseFloatError {
  146. pub kind: FloatErrorKind,
  147. }
  148. // FIXME: The standard library from_str_radix on floats was deprecated, so we're stuck
  149. // with this implementation ourselves until we want to make a breaking change.
  150. // (would have to drop it from `Num` though)
  151. macro_rules! float_trait_impl {
  152. ($name:ident for $($t:ty)*) => ($(
  153. impl $name for $t {
  154. type FromStrRadixErr = ParseFloatError;
  155. fn from_str_radix(src: &str, radix: u32)
  156. -> Result<Self, Self::FromStrRadixErr>
  157. {
  158. use self::FloatErrorKind::*;
  159. use self::ParseFloatError as PFE;
  160. // Special values
  161. match src {
  162. "inf" => return Ok(Float::infinity()),
  163. "-inf" => return Ok(Float::neg_infinity()),
  164. "NaN" => return Ok(Float::nan()),
  165. _ => {},
  166. }
  167. fn slice_shift_char(src: &str) -> Option<(char, &str)> {
  168. src.chars().nth(0).map(|ch| (ch, &src[1..]))
  169. }
  170. let (is_positive, src) = match slice_shift_char(src) {
  171. None => return Err(PFE { kind: Empty }),
  172. Some(('-', "")) => return Err(PFE { kind: Empty }),
  173. Some(('-', src)) => (false, src),
  174. Some((_, _)) => (true, src),
  175. };
  176. // The significand to accumulate
  177. let mut sig = if is_positive { 0.0 } else { -0.0 };
  178. // Necessary to detect overflow
  179. let mut prev_sig = sig;
  180. let mut cs = src.chars().enumerate();
  181. // Exponent prefix and exponent index offset
  182. let mut exp_info = None::<(char, usize)>;
  183. // Parse the integer part of the significand
  184. for (i, c) in cs.by_ref() {
  185. match c.to_digit(radix) {
  186. Some(digit) => {
  187. // shift significand one digit left
  188. sig = sig * (radix as $t);
  189. // add/subtract current digit depending on sign
  190. if is_positive {
  191. sig = sig + ((digit as isize) as $t);
  192. } else {
  193. sig = sig - ((digit as isize) as $t);
  194. }
  195. // Detect overflow by comparing to last value, except
  196. // if we've not seen any non-zero digits.
  197. if prev_sig != 0.0 {
  198. if is_positive && sig <= prev_sig
  199. { return Ok(Float::infinity()); }
  200. if !is_positive && sig >= prev_sig
  201. { return Ok(Float::neg_infinity()); }
  202. // Detect overflow by reversing the shift-and-add process
  203. if is_positive && (prev_sig != (sig - digit as $t) / radix as $t)
  204. { return Ok(Float::infinity()); }
  205. if !is_positive && (prev_sig != (sig + digit as $t) / radix as $t)
  206. { return Ok(Float::neg_infinity()); }
  207. }
  208. prev_sig = sig;
  209. },
  210. None => match c {
  211. 'e' | 'E' | 'p' | 'P' => {
  212. exp_info = Some((c, i + 1));
  213. break; // start of exponent
  214. },
  215. '.' => {
  216. break; // start of fractional part
  217. },
  218. _ => {
  219. return Err(PFE { kind: Invalid });
  220. },
  221. },
  222. }
  223. }
  224. // If we are not yet at the exponent parse the fractional
  225. // part of the significand
  226. if exp_info.is_none() {
  227. let mut power = 1.0;
  228. for (i, c) in cs.by_ref() {
  229. match c.to_digit(radix) {
  230. Some(digit) => {
  231. // Decrease power one order of magnitude
  232. power = power / (radix as $t);
  233. // add/subtract current digit depending on sign
  234. sig = if is_positive {
  235. sig + (digit as $t) * power
  236. } else {
  237. sig - (digit as $t) * power
  238. };
  239. // Detect overflow by comparing to last value
  240. if is_positive && sig < prev_sig
  241. { return Ok(Float::infinity()); }
  242. if !is_positive && sig > prev_sig
  243. { return Ok(Float::neg_infinity()); }
  244. prev_sig = sig;
  245. },
  246. None => match c {
  247. 'e' | 'E' | 'p' | 'P' => {
  248. exp_info = Some((c, i + 1));
  249. break; // start of exponent
  250. },
  251. _ => {
  252. return Err(PFE { kind: Invalid });
  253. },
  254. },
  255. }
  256. }
  257. }
  258. // Parse and calculate the exponent
  259. let exp = match exp_info {
  260. Some((c, offset)) => {
  261. let base = match c {
  262. 'E' | 'e' if radix == 10 => 10.0,
  263. 'P' | 'p' if radix == 16 => 2.0,
  264. _ => return Err(PFE { kind: Invalid }),
  265. };
  266. // Parse the exponent as decimal integer
  267. let src = &src[offset..];
  268. let (is_positive, exp) = match slice_shift_char(src) {
  269. Some(('-', src)) => (false, src.parse::<usize>()),
  270. Some(('+', src)) => (true, src.parse::<usize>()),
  271. Some((_, _)) => (true, src.parse::<usize>()),
  272. None => return Err(PFE { kind: Invalid }),
  273. };
  274. match (is_positive, exp) {
  275. (true, Ok(exp)) => base.powi(exp as i32),
  276. (false, Ok(exp)) => 1.0 / base.powi(exp as i32),
  277. (_, Err(_)) => return Err(PFE { kind: Invalid }),
  278. }
  279. },
  280. None => 1.0, // no exponent
  281. };
  282. Ok(sig * exp)
  283. }
  284. }
  285. )*)
  286. }
  287. float_trait_impl!(Num for f32 f64);
  288. /// A value bounded by a minimum and a maximum
  289. ///
  290. /// If input is less than min then this returns min.
  291. /// If input is greater than max then this returns max.
  292. /// Otherwise this returns input.
  293. #[inline]
  294. pub fn clamp<T: PartialOrd>(input: T, min: T, max: T) -> T {
  295. debug_assert!(min <= max, "min must be less than or equal to max");
  296. if input < min {
  297. min
  298. } else if input > max {
  299. max
  300. } else {
  301. input
  302. }
  303. }
  304. #[test]
  305. fn clamp_test() {
  306. // Int test
  307. assert_eq!(1, clamp(1, -1, 2));
  308. assert_eq!(-1, clamp(-2, -1, 2));
  309. assert_eq!(2, clamp(3, -1, 2));
  310. // Float test
  311. assert_eq!(1.0, clamp(1.0, -1.0, 2.0));
  312. assert_eq!(-1.0, clamp(-2.0, -1.0, 2.0));
  313. assert_eq!(2.0, clamp(3.0, -1.0, 2.0));
  314. }
  315. #[test]
  316. fn from_str_radix_unwrap() {
  317. // The Result error must impl Debug to allow unwrap()
  318. let i: i32 = Num::from_str_radix("0", 10).unwrap();
  319. assert_eq!(i, 0);
  320. let f: f32 = Num::from_str_radix("0.0", 10).unwrap();
  321. assert_eq!(f, 0.0);
  322. }
  323. macro_rules! test_wrapping_from_str_radix {
  324. ($($t:ty)+) => {
  325. $(
  326. for &(s, r) in &[("42", 10), ("42", 2), ("-13.0", 10), ("foo", 10)] {
  327. let w = Wrapping::<$t>::from_str_radix(s, r).map(|w| w.0);
  328. assert_eq!(w, <$t as Num>::from_str_radix(s, r));
  329. }
  330. )+
  331. };
  332. }
  333. #[test]
  334. fn wrapping_is_num() {
  335. fn require_num<T: Num>(_: &T) {}
  336. require_num(&Wrapping(42_u32));
  337. require_num(&Wrapping(-42));
  338. }
  339. #[test]
  340. fn wrapping_from_str_radix() {
  341. test_wrapping_from_str_radix!(usize u8 u16 u32 u64 isize i8 i16 i32 i64);
  342. }
  343. #[test]
  344. fn check_num_ops() {
  345. fn compute<T: Num + Copy>(x: T, y: T) -> T {
  346. x * y / y % y + y - y
  347. }
  348. assert_eq!(compute(1, 2), 1)
  349. }
  350. #[test]
  351. fn check_numref_ops() {
  352. fn compute<T: NumRef>(x: T, y: &T) -> T {
  353. x * y / y % y + y - y
  354. }
  355. assert_eq!(compute(1, &2), 1)
  356. }
  357. #[test]
  358. fn check_refnum_ops() {
  359. fn compute<T: Copy>(x: &T, y: T) -> T
  360. where for<'a> &'a T: RefNum<T>
  361. {
  362. &(&(&(&(x * y) / y) % y) + y) - y
  363. }
  364. assert_eq!(compute(&1, 2), 1)
  365. }
  366. #[test]
  367. fn check_refref_ops() {
  368. fn compute<T>(x: &T, y: &T) -> T
  369. where for<'a> &'a T: RefNum<T>
  370. {
  371. &(&(&(&(x * y) / y) % y) + y) - y
  372. }
  373. assert_eq!(compute(&1, &2), 1)
  374. }
  375. #[test]
  376. fn check_numassign_ops() {
  377. fn compute<T: NumAssign + Copy>(mut x: T, y: T) -> T {
  378. x *= y;
  379. x /= y;
  380. x %= y;
  381. x += y;
  382. x -= y;
  383. x
  384. }
  385. assert_eq!(compute(1, 2), 1)
  386. }
  387. // TODO test `NumAssignRef`, but even the standard numeric types don't
  388. // implement this yet. (see rust pr41336)