lib.rs 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  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. use std::ops::{Add, Sub, Mul, Div, Rem};
  12. pub use bounds::Bounded;
  13. pub use float::Float;
  14. pub use identities::{Zero, One, zero, one};
  15. pub use ops::checked::*;
  16. pub use ops::saturating::Saturating;
  17. pub use sign::{Signed, Unsigned, abs, abs_sub, signum};
  18. pub use cast::*;
  19. pub use int::PrimInt;
  20. pub use pow::{pow, checked_pow};
  21. pub mod identities;
  22. pub mod sign;
  23. pub mod ops;
  24. pub mod bounds;
  25. pub mod float;
  26. pub mod cast;
  27. pub mod int;
  28. pub mod pow;
  29. /// The base trait for numeric types
  30. pub trait Num: PartialEq + Zero + One
  31. + Add<Output = Self> + Sub<Output = Self>
  32. + Mul<Output = Self> + Div<Output = Self> + Rem<Output = Self>
  33. {
  34. type FromStrRadixErr;
  35. /// Convert from a string and radix <= 36.
  36. fn from_str_radix(str: &str, radix: u32) -> Result<Self, Self::FromStrRadixErr>;
  37. }
  38. macro_rules! int_trait_impl {
  39. ($name:ident for $($t:ty)*) => ($(
  40. impl $name for $t {
  41. type FromStrRadixErr = ::std::num::ParseIntError;
  42. fn from_str_radix(s: &str, radix: u32)
  43. -> Result<Self, ::std::num::ParseIntError>
  44. {
  45. <$t>::from_str_radix(s, radix)
  46. }
  47. }
  48. )*)
  49. }
  50. int_trait_impl!(Num for usize u8 u16 u32 u64 isize i8 i16 i32 i64);
  51. #[derive(Debug)]
  52. pub enum FloatErrorKind {
  53. Empty,
  54. Invalid,
  55. }
  56. // FIXME: std::num::ParseFloatError is stable in 1.0, but opaque to us,
  57. // so there's not really any way for us to reuse it.
  58. #[derive(Debug)]
  59. pub struct ParseFloatError {
  60. pub kind: FloatErrorKind,
  61. }
  62. // FIXME: The standard library from_str_radix on floats was deprecated, so we're stuck
  63. // with this implementation ourselves until we want to make a breaking change.
  64. // (would have to drop it from `Num` though)
  65. macro_rules! float_trait_impl {
  66. ($name:ident for $($t:ty)*) => ($(
  67. impl $name for $t {
  68. type FromStrRadixErr = ParseFloatError;
  69. fn from_str_radix(src: &str, radix: u32)
  70. -> Result<Self, Self::FromStrRadixErr>
  71. {
  72. use self::FloatErrorKind::*;
  73. use self::ParseFloatError as PFE;
  74. // Special values
  75. match src {
  76. "inf" => return Ok(Float::infinity()),
  77. "-inf" => return Ok(Float::neg_infinity()),
  78. "NaN" => return Ok(Float::nan()),
  79. _ => {},
  80. }
  81. fn slice_shift_char(src: &str) -> Option<(char, &str)> {
  82. src.chars().nth(0).map(|ch| (ch, &src[1..]))
  83. }
  84. let (is_positive, src) = match slice_shift_char(src) {
  85. None => return Err(PFE { kind: Empty }),
  86. Some(('-', "")) => return Err(PFE { kind: Empty }),
  87. Some(('-', src)) => (false, src),
  88. Some((_, _)) => (true, src),
  89. };
  90. // The significand to accumulate
  91. let mut sig = if is_positive { 0.0 } else { -0.0 };
  92. // Necessary to detect overflow
  93. let mut prev_sig = sig;
  94. let mut cs = src.chars().enumerate();
  95. // Exponent prefix and exponent index offset
  96. let mut exp_info = None::<(char, usize)>;
  97. // Parse the integer part of the significand
  98. for (i, c) in cs.by_ref() {
  99. match c.to_digit(radix) {
  100. Some(digit) => {
  101. // shift significand one digit left
  102. sig = sig * (radix as $t);
  103. // add/subtract current digit depending on sign
  104. if is_positive {
  105. sig = sig + ((digit as isize) as $t);
  106. } else {
  107. sig = sig - ((digit as isize) as $t);
  108. }
  109. // Detect overflow by comparing to last value, except
  110. // if we've not seen any non-zero digits.
  111. if prev_sig != 0.0 {
  112. if is_positive && sig <= prev_sig
  113. { return Ok(Float::infinity()); }
  114. if !is_positive && sig >= prev_sig
  115. { return Ok(Float::neg_infinity()); }
  116. // Detect overflow by reversing the shift-and-add process
  117. if is_positive && (prev_sig != (sig - digit as $t) / radix as $t)
  118. { return Ok(Float::infinity()); }
  119. if !is_positive && (prev_sig != (sig + digit as $t) / radix as $t)
  120. { return Ok(Float::neg_infinity()); }
  121. }
  122. prev_sig = sig;
  123. },
  124. None => match c {
  125. 'e' | 'E' | 'p' | 'P' => {
  126. exp_info = Some((c, i + 1));
  127. break; // start of exponent
  128. },
  129. '.' => {
  130. break; // start of fractional part
  131. },
  132. _ => {
  133. return Err(PFE { kind: Invalid });
  134. },
  135. },
  136. }
  137. }
  138. // If we are not yet at the exponent parse the fractional
  139. // part of the significand
  140. if exp_info.is_none() {
  141. let mut power = 1.0;
  142. for (i, c) in cs.by_ref() {
  143. match c.to_digit(radix) {
  144. Some(digit) => {
  145. // Decrease power one order of magnitude
  146. power = power / (radix as $t);
  147. // add/subtract current digit depending on sign
  148. sig = if is_positive {
  149. sig + (digit as $t) * power
  150. } else {
  151. sig - (digit as $t) * power
  152. };
  153. // Detect overflow by comparing to last value
  154. if is_positive && sig < prev_sig
  155. { return Ok(Float::infinity()); }
  156. if !is_positive && sig > prev_sig
  157. { return Ok(Float::neg_infinity()); }
  158. prev_sig = sig;
  159. },
  160. None => match c {
  161. 'e' | 'E' | 'p' | 'P' => {
  162. exp_info = Some((c, i + 1));
  163. break; // start of exponent
  164. },
  165. _ => {
  166. return Err(PFE { kind: Invalid });
  167. },
  168. },
  169. }
  170. }
  171. }
  172. // Parse and calculate the exponent
  173. let exp = match exp_info {
  174. Some((c, offset)) => {
  175. let base = match c {
  176. 'E' | 'e' if radix == 10 => 10.0,
  177. 'P' | 'p' if radix == 16 => 2.0,
  178. _ => return Err(PFE { kind: Invalid }),
  179. };
  180. // Parse the exponent as decimal integer
  181. let src = &src[offset..];
  182. let (is_positive, exp) = match slice_shift_char(src) {
  183. Some(('-', src)) => (false, src.parse::<usize>()),
  184. Some(('+', src)) => (true, src.parse::<usize>()),
  185. Some((_, _)) => (true, src.parse::<usize>()),
  186. None => return Err(PFE { kind: Invalid }),
  187. };
  188. match (is_positive, exp) {
  189. (true, Ok(exp)) => base.powi(exp as i32),
  190. (false, Ok(exp)) => 1.0 / base.powi(exp as i32),
  191. (_, Err(_)) => return Err(PFE { kind: Invalid }),
  192. }
  193. },
  194. None => 1.0, // no exponent
  195. };
  196. Ok(sig * exp)
  197. }
  198. }
  199. )*)
  200. }
  201. float_trait_impl!(Num for f32 f64);
  202. #[test]
  203. fn from_str_radix_unwrap() {
  204. // The Result error must impl Debug to allow unwrap()
  205. let i: i32 = Num::from_str_radix("0", 10).unwrap();
  206. assert_eq!(i, 0);
  207. let f: f32 = Num::from_str_radix("0.0", 10).unwrap();
  208. assert_eq!(f, 0.0);
  209. }