1use std::convert::TryFrom;
5use std::error::Error as StdError;
6use std::fmt::Debug;
7use std::fmt::Display;
8use std::fmt::Formatter;
9use std::fmt::Result as FmtResult;
10#[cfg(not(feature = "num-v02"))]
11use std::num::FpCategory;
12use std::ops::Add;
13use std::ops::AddAssign;
14use std::ops::Div;
15use std::ops::DivAssign;
16use std::ops::Mul;
17use std::ops::MulAssign;
18use std::ops::Neg;
19use std::ops::Rem;
20use std::ops::RemAssign;
21use std::ops::Sub;
22use std::ops::SubAssign;
23use std::str::FromStr;
24
25use num_traits::cast::ToPrimitive;
26use num_traits::identities::Zero;
27use num_traits::pow::Pow;
28use num_traits::sign::Signed;
29
30use crate::num_bigint::BigInt;
31use crate::num_bigint::ParseBigIntError;
32use crate::num_bigint::Sign;
33use crate::num_rational::BigRational;
34use crate::num_rational::Rational32;
35use crate::num_rational::Rational64;
36
37
38const MAX_PRECISION: usize = 8;
44
45
46fn round_to_even(val: &BigRational) -> BigRational {
52 let zero = BigInt::from(0);
53 let one = BigInt::from(1);
54 let two = BigInt::from(2);
55
56 let zero_ = BigRational::new(zero, one.clone());
57 let half = BigRational::new(one.clone(), two.clone());
58 let mut fract = val.fract();
60 if fract < zero_ {
61 fract = &zero_ - fract
62 };
63
64 let trunc = val.trunc();
65 if fract == half {
66 if &trunc % two == zero_ {
68 trunc
69 } else if trunc >= zero_ {
70 trunc + one
71 } else {
72 trunc - one
73 }
74 } else {
75 val.round()
78 }
79}
80
81fn format_impl(
82 value: &BigRational,
83 mut result: String,
84 depth: usize,
85 min_precision: usize,
86 precision: Option<usize>,
87) -> String {
88 debug_assert!(min_precision <= precision.unwrap_or(MAX_PRECISION));
89
90 let trunc = value.trunc().to_integer();
91 result += &trunc.to_string();
92
93 let numer = value.numer();
94 let denom = value.denom();
95 let value = numer - (trunc * denom);
96
97 let at_min = depth >= min_precision;
98 let at_max = depth >= precision.unwrap_or(MAX_PRECISION);
99 if (value.is_zero() && precision.is_none() && at_min) || at_max {
103 result
104 } else {
105 if depth == 0 {
106 result += ".";
107 }
108
109 let value = BigRational::new(value * 10, denom.clone());
110 format_impl(&value, result, depth + 1, min_precision, precision)
111 }
112}
113
114
115#[derive(Debug, PartialEq)]
117pub enum ParseNumError {
118 InvalidStrError(String),
120 ParseIntError(ParseBigIntError),
122}
123
124impl From<ParseBigIntError> for ParseNumError {
125 #[inline]
126 fn from(e: ParseBigIntError) -> Self {
127 Self::ParseIntError(e)
128 }
129}
130
131impl Display for ParseNumError {
132 #[inline]
133 fn fmt(&self, fmt: &mut Formatter<'_>) -> FmtResult {
134 match self {
135 Self::InvalidStrError(s) => write!(fmt, "{}", s),
136 Self::ParseIntError(err) => write!(fmt, "{}", err),
137 }
138 }
139}
140
141impl StdError for ParseNumError {
142 #[inline]
143 fn source(&self) -> Option<&(dyn StdError + 'static)> {
144 match self {
145 Self::InvalidStrError(..) => None,
146 Self::ParseIntError(err) => err.source(),
147 }
148 }
149}
150
151
152#[derive(Debug)]
154pub struct CustomDisplay<'n> {
155 num: &'n Num,
157 min_precision: Option<usize>,
159}
160
161impl<'n> CustomDisplay<'n> {
162 #[inline]
165 fn new(num: &'n Num) -> Self {
166 Self {
167 num,
168 min_precision: None,
169 }
170 }
171
172 #[inline]
176 pub fn min_precision(&mut self, min_precision: usize) -> &mut Self {
177 self.min_precision = Some(min_precision);
178 self
179 }
180}
181
182impl<'n> Display for CustomDisplay<'n> {
183 #[inline]
184 fn fmt(&self, fmt: &mut Formatter<'_>) -> FmtResult {
185 self.num.format(fmt, self.min_precision.unwrap_or(0))
186 }
187}
188
189
190macro_rules! impl_num {
191 ($(#[$meta:meta])* pub struct $name:ident($rational:ty), $int:ty) => {
192 $(#[$meta])*
193 pub struct $name(pub(crate) $rational);
194
195 impl $name {
196 #[inline]
198 pub fn new<T, U>(numer: T, denom: U) -> Self
199 where
200 $int: From<T>,
201 $int: From<U>,
202 {
203 let numer = <$int>::from(numer);
204 let denom = <$int>::from(denom);
205
206 Self(<$rational>::new(numer, denom))
207 }
208 }
209
210 impl Default for $name {
211 #[inline]
212 fn default() -> Self {
213 <$name>::from(0)
214 }
215 }
216
217 impl From<$name> for ($int, $int) {
218 #[inline]
219 fn from(other: $name) -> Self {
220 other.0.into()
221 }
222 }
223
224 impl Debug for $name {
228 #[inline]
229 fn fmt(&self, fmt: &mut Formatter<'_>) -> FmtResult {
230 debug_assert!(self.0.denom().is_positive());
234
235 write!(fmt, "{}/{}", self.0.numer(), self.0.denom())
236 }
237 }
238 };
239}
240
241
242impl_num! {
243 #[derive(Clone, Eq, Hash, Ord, PartialEq, PartialOrd)]
246 pub struct Num(BigRational), BigInt
247}
248
249impl Num {
250 #[inline]
258 pub fn round(&self) -> Self {
259 self.round_with(0)
260 }
261
262 pub fn round_with(&self, precision: usize) -> Self {
267 let factor = BigInt::from(10).pow(precision);
268 let value = &self.0 * &factor;
269
270 Num(round_to_even(&value).trunc() / factor)
271 }
272
273 #[inline]
275 pub fn trunc(&self) -> Self {
276 Num(self.0.trunc())
277 }
278
279 #[inline]
281 pub fn fract(&self) -> Self {
282 Num(self.0.fract())
283 }
284
285 #[inline]
287 pub fn to_integer(&self) -> BigInt {
288 self.0.to_integer()
289 }
290
291 #[inline]
297 pub fn to_i64(&self) -> Option<i64> {
298 self.to_integer().to_i64()
299 }
300
301 #[inline]
307 pub fn to_u64(&self) -> Option<u64> {
308 self.to_integer().to_u64()
309 }
310
311 pub fn to_f64(&self) -> Option<f64> {
316 let numer = self.0.numer().to_f64();
317 let denom = self.0.denom().to_f64();
318
319 match (numer, denom) {
320 #[cfg(feature = "num-v02")]
321 (Some(numer), Some(denom)) => Some(numer / denom),
322 #[cfg(not(feature = "num-v02"))]
323 (Some(numer), Some(denom)) => {
324 if !matches!(numer.classify(), FpCategory::Normal | FpCategory::Zero) {
325 return None
326 }
327 if !matches!(denom.classify(), FpCategory::Normal | FpCategory::Zero) {
328 return None
329 }
330 Some(numer / denom)
331 },
332 _ => None,
333 }
334 }
335
336 #[inline]
338 pub fn is_zero(&self) -> bool {
339 self.0.is_zero()
340 }
341
342 #[inline]
344 pub fn is_positive(&self) -> bool {
345 self.0.is_positive()
346 }
347
348 #[inline]
350 pub fn is_negative(&self) -> bool {
351 self.0.is_negative()
352 }
353
354 fn format(&self, fmt: &mut Formatter<'_>, min_precision: usize) -> FmtResult {
355 let non_negative = !self.0.is_negative();
356 let prefix = "";
357
358 let precision = fmt.precision();
359 let value = self.round_with(precision.unwrap_or(MAX_PRECISION)).0.abs();
360 let string = format_impl(&value, String::new(), 0, min_precision, precision);
365 fmt.pad_integral(non_negative, prefix, &string)
366 }
367
368 #[inline]
371 pub fn display(&self) -> CustomDisplay<'_> {
372 CustomDisplay::new(self)
373 }
374}
375
376impl Display for Num {
377 #[inline]
378 fn fmt(&self, fmt: &mut Formatter<'_>) -> FmtResult {
379 let min_precision = 0;
380 self.format(fmt, min_precision)
381 }
382}
383
384impl From<Num32> for Num {
385 fn from(other: Num32) -> Num {
386 let (numer, denom) = other.into();
387 Num::new(numer, denom)
388 }
389}
390
391impl From<Num64> for Num {
392 fn from(other: Num64) -> Num {
393 let (numer, denom) = other.into();
394 Num::new(numer, denom)
395 }
396}
397
398impl FromStr for Num {
399 type Err = ParseNumError;
400
401 fn from_str(s: &str) -> Result<Self, Self::Err> {
402 fn parse_istr(s: &str) -> Result<(Sign, BigInt), ParseBigIntError> {
403 let val = BigInt::from_str(s)?;
404
405 let sign = val.sign();
409 let sign = if sign == Sign::NoSign {
410 if s.starts_with('-') {
411 Sign::Minus
412 } else {
413 Sign::Plus
414 }
415 } else {
416 sign
417 };
418 Ok((sign, val))
419 }
420
421 fn parse_str(s: &str, sign: Sign) -> Result<BigInt, ParseNumError> {
422 if s.starts_with('-') || s.starts_with('+') {
423 return Err(ParseNumError::InvalidStrError(s.to_owned()));
424 }
425
426 let num = BigInt::parse_bytes(s.as_bytes(), 10)
427 .ok_or_else(|| ParseNumError::InvalidStrError(s.to_owned()))?;
428 let (_, bytes) = num.to_bytes_le();
429 let num = BigInt::from_bytes_le(sign, &bytes);
430 Ok(num)
431 }
432
433 let mut splits = s.splitn(2, '.');
434 let numer = splits
435 .next()
436 .ok_or_else(|| ParseNumError::InvalidStrError(s.to_owned()))?;
437 let (sign, numer) = parse_istr(numer)?;
438
439 if let Some(s) = splits.next() {
440 let denom = parse_str(s, sign)?;
441 let power = BigInt::from(10).pow(s.len());
442 let numer = numer * &power + denom;
443 Ok(Num(BigRational::new(numer, power)))
444 } else {
445 Ok(Num(BigRational::from_integer(numer)))
446 }
447 }
448}
449
450
451macro_rules! impl_from {
452 ($type:ty) => {
453 impl From<$type> for Num {
454 #[inline]
455 fn from(val: $type) -> Self {
456 Self(BigRational::from_integer(BigInt::from(val)))
457 }
458 }
459 };
460}
461
462impl_from!(i128);
463impl_from!(i16);
464impl_from!(i32);
465impl_from!(i64);
466impl_from!(i8);
467impl_from!(isize);
468impl_from!(u128);
469impl_from!(u16);
470impl_from!(u32);
471impl_from!(u64);
472impl_from!(u8);
473impl_from!(usize);
474impl_from!(BigInt);
475
476
477macro_rules! impl_neg {
478 ($lhs:ty) => {
479 impl Neg for $lhs {
480 type Output = Num;
481
482 #[inline]
483 fn neg(self) -> Self::Output {
484 let Num(int) = self;
485 Num(int.neg())
486 }
487 }
488 };
489}
490
491impl_neg!(Num);
492impl_neg!(&Num);
493
494
495macro_rules! impl_op {
496 (impl $imp:ident, $method:ident, $lhs:ty, $rhs:ty) => {
497 impl $imp<$rhs> for $lhs {
498 type Output = Num;
499
500 #[inline]
501 fn $method(self, rhs: $rhs) -> Self::Output {
502 let Num(lhs) = self;
503 let Num(rhs) = rhs;
504 Num(lhs.$method(rhs))
505 }
506 }
507 };
508}
509
510macro_rules! impl_int_op {
511 (impl $imp:ident, $method:ident, $lhs:ty) => {
512 impl<T> $imp<T> for $lhs
515 where
516 BigInt: From<T>,
517 {
518 type Output = Num;
519
520 #[inline]
521 fn $method(self, rhs: T) -> Self::Output {
522 let Num(lhs) = self;
523 let rhs = BigRational::from_integer(BigInt::from(rhs));
524 Num(lhs.$method(rhs))
525 }
526 }
527 };
528}
529
530macro_rules! impl_ops {
531 (impl $imp:ident, $method:ident) => {
532 impl_op!(impl $imp, $method, Num, Num);
533 impl_op!(impl $imp, $method, &Num, Num);
534 impl_op!(impl $imp, $method, Num, &Num);
535 impl_op!(impl $imp, $method, &Num, &Num);
536 impl_int_op!(impl $imp, $method, Num);
537 impl_int_op!(impl $imp, $method, &Num);
538 };
539}
540
541impl_ops!(impl Add, add);
542impl_ops!(impl Sub, sub);
543impl_ops!(impl Mul, mul);
544impl_ops!(impl Div, div);
545impl_ops!(impl Rem, rem);
546
547
548macro_rules! impl_assign_op {
549 (impl $imp:ident, $method:ident, $lhs:ty, $rhs:ty) => {
550 impl $imp<$rhs> for $lhs {
551 #[inline]
552 fn $method(&mut self, rhs: $rhs) {
553 let Num(rhs) = rhs;
554 (self.0).$method(rhs)
555 }
556 }
557 };
558}
559
560macro_rules! impl_assign_ops {
561 (impl $imp:ident, $method:ident) => {
562 impl<T> $imp<T> for Num
563 where
564 BigInt: From<T>,
565 {
566 #[inline]
567 fn $method(&mut self, rhs: T) {
568 let rhs = BigRational::from_integer(BigInt::from(rhs));
569 (self.0).$method(rhs)
570 }
571 }
572
573 impl_assign_op!(impl $imp, $method, Num, Num);
574 impl_assign_op!(impl $imp, $method, Num, &Num);
575 };
576}
577
578impl_assign_ops!(impl AddAssign, add_assign);
579impl_assign_ops!(impl SubAssign, sub_assign);
580impl_assign_ops!(impl MulAssign, mul_assign);
581impl_assign_ops!(impl DivAssign, div_assign);
582impl_assign_ops!(impl RemAssign, rem_assign);
583
584
585macro_rules! impl_try_from {
586 ($lhs:ty, $rhs:ty, $to_int:ident) => {
587 impl TryFrom<$rhs> for $lhs {
588 type Error = ();
589
590 fn try_from(other: $rhs) -> Result<Self, Self::Error> {
591 let numer = other.0.numer().$to_int().ok_or(())?;
592 let denom = other.0.denom().$to_int().ok_or(())?;
593
594 Ok(Self::new(numer, denom))
595 }
596 }
597 };
598}
599
600
601impl_num! {
602 #[derive(Clone, Copy, Eq, Hash, Ord, PartialEq, PartialOrd)]
611 pub struct Num32(Rational32), i32
612}
613
614impl Num32 {
615 pub fn approximate(num: Num) -> Self {
624 if let Ok(num32) = Num32::try_from(&num) {
627 return num32
628 }
629
630 let integer = num.to_integer();
631 if integer >= BigInt::from(i32::MAX) {
635 Num32::from(i32::MAX)
636 } else if integer <= BigInt::from(i32::MIN) {
637 Num32::from(i32::MIN)
638 } else {
639 match Self::continued_fractions(num, integer) {
642 Ok(num) | Err(num) => num,
643 }
644 }
645 }
646
647 fn continued_fractions(num: Num, integer: BigInt) -> Result<Num32, Num32> {
651 let mut q = num.0;
652 let mut a = integer;
653 let mut n0 = 0i32;
654 let mut d0 = 1i32;
655 let mut n1 = 1i32;
656 let mut d1 = 0i32;
657
658 loop {
659 if q.is_integer() {
660 break Ok(Num32::new(n1, d1))
661 }
662
663 let a32 = a.to_i32();
664 let n = a32
665 .and_then(|n| n.checked_mul(n1))
666 .and_then(|n| n.checked_add(n0))
667 .ok_or_else(|| Num32::new(n1, d1))?;
668 let d = a32
669 .and_then(|n| n.checked_mul(d1))
670 .and_then(|n| n.checked_add(d0))
671 .ok_or_else(|| Num32::new(n1, d1))?;
672
673 n0 = n1;
674 d0 = d1;
675 n1 = n;
676 d1 = d;
677
678 q = (q - a).recip();
679 a = q.to_integer();
680 }
681 }
682}
683
684impl<T> From<T> for Num32
685where
686 i32: From<T>,
687{
688 #[inline]
689 fn from(val: T) -> Self {
690 Self(Rational32::from(i32::from(val)))
691 }
692}
693
694impl_try_from!(Num32, Num, to_i32);
695impl_try_from!(Num32, &Num, to_i32);
696
697
698impl_num! {
699 #[derive(Clone, Copy, Eq, Hash, Ord, PartialEq, PartialOrd)]
708 pub struct Num64(Rational64), i64
709}
710
711impl<T> From<T> for Num64
712where
713 i64: From<T>,
714{
715 #[inline]
716 fn from(val: T) -> Self {
717 Self(Rational64::from(i64::from(val)))
718 }
719}
720
721impl_try_from!(Num64, Num, to_i64);
722impl_try_from!(Num64, &Num, to_i64);