1use tetcore_std::{ops::{self, Add, Sub, Mul, Div}, fmt::Debug, prelude::*, convert::{TryInto, TryFrom}};
21use codec::{Encode, Decode, CompactAs};
22use crate::{
23 helpers_128bit::multiply_by_rational, PerThing,
24 traits::{
25 SaturatedConversion, CheckedSub, CheckedAdd, CheckedMul, CheckedDiv, CheckedNeg,
26 Bounded, Saturating, UniqueSaturatedInto, Zero, One
27 },
28};
29
30#[cfg(feature = "std")]
31use serde::{de, Deserialize, Deserializer, Serialize, Serializer};
32
33pub trait FixedPointOperand: Copy + Clone + Bounded + Zero + Saturating
35 + PartialOrd + UniqueSaturatedInto<u128> + TryFrom<u128> + CheckedNeg {}
36
37impl FixedPointOperand for i128 {}
38impl FixedPointOperand for u128 {}
39impl FixedPointOperand for i64 {}
40impl FixedPointOperand for u64 {}
41impl FixedPointOperand for i32 {}
42impl FixedPointOperand for u32 {}
43impl FixedPointOperand for i16 {}
44impl FixedPointOperand for u16 {}
45impl FixedPointOperand for i8 {}
46impl FixedPointOperand for u8 {}
47
48pub trait FixedPointNumber:
56 Sized + Copy + Default + Debug
57 + Saturating + Bounded
58 + Eq + PartialEq + Ord + PartialOrd
59 + CheckedSub + CheckedAdd + CheckedMul + CheckedDiv
60 + Add + Sub + Div + Mul
61{
62 type Inner: Debug + One + CheckedMul + CheckedDiv + FixedPointOperand;
64
65 const DIV: Self::Inner;
67
68 const SIGNED: bool;
70
71 fn accuracy() -> Self::Inner {
73 Self::DIV
74 }
75
76 fn from_inner(int: Self::Inner) -> Self;
78
79 fn into_inner(self) -> Self::Inner;
81
82 fn saturating_from_integer<N: FixedPointOperand>(int: N) -> Self {
86 let mut n: I129 = int.into();
87 n.value = n.value.saturating_mul(Self::DIV.saturated_into());
88 Self::from_inner(from_i129(n).unwrap_or_else(|| to_bound(int, 0)))
89 }
90
91 fn checked_from_integer(int: Self::Inner) -> Option<Self> {
95 int.checked_mul(&Self::DIV).map(|inner| Self::from_inner(inner))
96 }
97
98 fn saturating_from_rational<N: FixedPointOperand, D: FixedPointOperand>(n: N, d: D) -> Self {
102 if d == D::zero() {
103 panic!("attempt to divide by zero")
104 }
105 Self::checked_from_rational(n, d).unwrap_or_else(|| to_bound(n, d))
106 }
107
108 fn checked_from_rational<N: FixedPointOperand, D: FixedPointOperand>(n: N, d: D) -> Option<Self> {
112 if d == D::zero() {
113 return None
114 }
115
116 let n: I129 = n.into();
117 let d: I129 = d.into();
118 let negative = n.negative != d.negative;
119
120 multiply_by_rational(n.value, Self::DIV.unique_saturated_into(), d.value).ok()
121 .and_then(|value| from_i129(I129 { value, negative }))
122 .map(|inner| Self::from_inner(inner))
123 }
124
125 fn checked_mul_int<N: FixedPointOperand>(self, n: N) -> Option<N> {
129 let lhs: I129 = self.into_inner().into();
130 let rhs: I129 = n.into();
131 let negative = lhs.negative != rhs.negative;
132
133 multiply_by_rational(lhs.value, rhs.value, Self::DIV.unique_saturated_into()).ok()
134 .and_then(|value| from_i129(I129 { value, negative }))
135 }
136
137 fn saturating_mul_int<N: FixedPointOperand>(self, n: N) -> N {
141 self.checked_mul_int(n).unwrap_or_else(|| to_bound(self.into_inner(), n))
142 }
143
144 fn checked_div_int<N: FixedPointOperand>(self, d: N) -> Option<N> {
148 let lhs: I129 = self.into_inner().into();
149 let rhs: I129 = d.into();
150 let negative = lhs.negative != rhs.negative;
151
152 lhs.value.checked_div(rhs.value)
153 .and_then(|n| n.checked_div(Self::DIV.unique_saturated_into()))
154 .and_then(|value| from_i129(I129 { value, negative }))
155 }
156
157 fn saturating_div_int<N: FixedPointOperand>(self, d: N) -> N {
161 if d == N::zero() {
162 panic!("attempt to divide by zero")
163 }
164 self.checked_div_int(d).unwrap_or_else(|| to_bound(self.into_inner(), d))
165 }
166
167 fn saturating_mul_acc_int<N: FixedPointOperand>(self, n: N) -> N {
172 if self.is_negative() && n > N::zero() {
173 n.saturating_sub(Self::zero().saturating_sub(self).saturating_mul_int(n))
174 } else {
175 self.saturating_mul_int(n).saturating_add(n)
176 }
177 }
178
179 fn saturating_abs(self) -> Self {
183 let inner = self.into_inner();
184 if inner >= Self::Inner::zero() {
185 self
186 } else {
187 Self::from_inner(inner.checked_neg().unwrap_or_else(|| Self::Inner::max_value()))
188 }
189 }
190
191 fn reciprocal(self) -> Option<Self> {
195 Self::one().checked_div(&self)
196 }
197
198 fn zero() -> Self {
200 Self::from_inner(Self::Inner::zero())
201 }
202
203 fn is_zero(&self) -> bool {
205 self.into_inner() == Self::Inner::zero()
206 }
207
208 fn one() -> Self {
210 Self::from_inner(Self::DIV)
211 }
212
213 fn is_one(&self) -> bool {
215 self.into_inner() == Self::Inner::one()
216 }
217
218 fn is_positive(self) -> bool {
220 self.into_inner() > Self::Inner::zero()
221 }
222
223 fn is_negative(self) -> bool {
225 self.into_inner() < Self::Inner::zero()
226 }
227
228 fn trunc(self) -> Self {
230 self.into_inner().checked_div(&Self::DIV)
231 .expect("panics only if DIV is zero, DIV is not zero; qed")
232 .checked_mul(&Self::DIV)
233 .map(|inner| Self::from_inner(inner))
234 .expect("can not overflow since fixed number is >= integer part")
235 }
236
237 fn frac(self) -> Self {
242 let integer = self.trunc();
243 let fractional = self.saturating_sub(integer);
244 if integer == Self::zero() {
245 fractional
246 } else {
247 fractional.saturating_abs()
248 }
249 }
250
251 fn ceil(self) -> Self {
255 if self.is_negative() {
256 self.trunc()
257 } else {
258 if self.frac() == Self::zero() {
259 self
260 } else {
261 self.saturating_add(Self::one()).trunc()
262 }
263 }
264 }
265
266 fn floor(self) -> Self {
270 if self.is_negative() {
271 self.saturating_sub(Self::one()).trunc()
272 } else {
273 self.trunc()
274 }
275 }
276
277 fn round(self) -> Self {
281 let n = self.frac().saturating_mul(Self::saturating_from_integer(10));
282 if n < Self::saturating_from_integer(5) {
283 self.trunc()
284 } else {
285 if self.is_positive() {
286 self.saturating_add(Self::one()).trunc()
287 } else {
288 self.saturating_sub(Self::one()).trunc()
289 }
290 }
291 }
292}
293
294struct I129 {
296 value: u128,
297 negative: bool,
298}
299
300impl<N: FixedPointOperand> From<N> for I129 {
301 fn from(n: N) -> I129 {
302 if n < N::zero() {
303 let value: u128 = n.checked_neg()
304 .map(|n| n.unique_saturated_into())
305 .unwrap_or_else(|| N::max_value().unique_saturated_into().saturating_add(1));
306 I129 { value, negative: true }
307 } else {
308 I129 { value: n.unique_saturated_into(), negative: false }
309 }
310 }
311}
312
313fn from_i129<N: FixedPointOperand>(n: I129) -> Option<N> {
315 let max_plus_one: u128 = N::max_value().unique_saturated_into().saturating_add(1);
316 if n.negative && N::min_value() < N::zero() && n.value == max_plus_one {
317 Some(N::min_value())
318 } else {
319 let unsigned_inner: N = n.value.try_into().ok()?;
320 let inner = if n.negative { unsigned_inner.checked_neg()? } else { unsigned_inner };
321 Some(inner)
322 }
323}
324
325fn to_bound<N: FixedPointOperand, D: FixedPointOperand, R: Bounded>(n: N, m: D) -> R {
327 if (n < N::zero()) != (m < D::zero()) {
328 R::min_value()
329 } else {
330 R::max_value()
331 }
332}
333
334macro_rules! implement_fixed {
335 (
336 $name:ident,
337 $test_mod:ident,
338 $inner_type:ty,
339 $signed:tt,
340 $div:tt,
341 $title:expr $(,)?
342 ) => {
343 #[doc = $title]
346 #[derive(Encode, Decode, CompactAs, Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
347 pub struct $name($inner_type);
348
349 impl From<$inner_type> for $name {
350 fn from(int: $inner_type) -> Self {
351 $name::saturating_from_integer(int)
352 }
353 }
354
355 impl<N: FixedPointOperand, D: FixedPointOperand> From<(N, D)> for $name {
356 fn from(r: (N, D)) -> Self {
357 $name::saturating_from_rational(r.0, r.1)
358 }
359 }
360
361 impl FixedPointNumber for $name {
362 type Inner = $inner_type;
363
364 const DIV: Self::Inner = $div;
365 const SIGNED: bool = $signed;
366
367 fn from_inner(inner: Self::Inner) -> Self {
368 Self(inner)
369 }
370
371 fn into_inner(self) -> Self::Inner {
372 self.0
373 }
374 }
375
376 impl $name {
377 pub const fn from_inner(inner: $inner_type) -> Self {
379 Self(inner)
380 }
381
382 #[cfg(any(feature = "std", test))]
383 pub fn from_fraction(x: f64) -> Self {
384 Self((x * (<Self as FixedPointNumber>::DIV as f64)) as $inner_type)
385 }
386
387 #[cfg(any(feature = "std", test))]
388 pub fn to_fraction(self) -> f64 {
389 self.0 as f64 / <Self as FixedPointNumber>::DIV as f64
390 }
391 }
392
393 impl Saturating for $name {
394 fn saturating_add(self, rhs: Self) -> Self {
395 Self(self.0.saturating_add(rhs.0))
396 }
397
398 fn saturating_sub(self, rhs: Self) -> Self {
399 Self(self.0.saturating_sub(rhs.0))
400 }
401
402 fn saturating_mul(self, rhs: Self) -> Self {
403 self.checked_mul(&rhs).unwrap_or_else(|| to_bound(self.0, rhs.0))
404 }
405
406 fn saturating_pow(self, exp: usize) -> Self {
407 if exp == 0 {
408 return Self::saturating_from_integer(1);
409 }
410
411 let exp = exp as u32;
412 let msb_pos = 32 - exp.leading_zeros();
413
414 let mut result = Self::saturating_from_integer(1);
415 let mut pow_val = self;
416 for i in 0..msb_pos {
417 if ((1 << i) & exp) > 0 {
418 result = result.saturating_mul(pow_val);
419 }
420 pow_val = pow_val.saturating_mul(pow_val);
421 }
422 result
423 }
424 }
425
426 impl ops::Neg for $name {
427 type Output = Self;
428
429 fn neg(self) -> Self::Output {
430 Self(<Self as FixedPointNumber>::Inner::zero() - self.0)
431 }
432 }
433
434 impl ops::Add for $name {
435 type Output = Self;
436
437 fn add(self, rhs: Self) -> Self::Output {
438 Self(self.0 + rhs.0)
439 }
440 }
441
442 impl ops::Sub for $name {
443 type Output = Self;
444
445 fn sub(self, rhs: Self) -> Self::Output {
446 Self(self.0 - rhs.0)
447 }
448 }
449
450 impl ops::Mul for $name {
451 type Output = Self;
452
453 fn mul(self, rhs: Self) -> Self::Output {
454 self.checked_mul(&rhs)
455 .unwrap_or_else(|| panic!("attempt to multiply with overflow"))
456 }
457 }
458
459 impl ops::Div for $name {
460 type Output = Self;
461
462 fn div(self, rhs: Self) -> Self::Output {
463 if rhs.0 == 0 {
464 panic!("attempt to divide by zero")
465 }
466 self.checked_div(&rhs)
467 .unwrap_or_else(|| panic!("attempt to divide with overflow"))
468 }
469 }
470
471 impl CheckedSub for $name {
472 fn checked_sub(&self, rhs: &Self) -> Option<Self> {
473 self.0.checked_sub(rhs.0).map(Self)
474 }
475 }
476
477 impl CheckedAdd for $name {
478 fn checked_add(&self, rhs: &Self) -> Option<Self> {
479 self.0.checked_add(rhs.0).map(Self)
480 }
481 }
482
483 impl CheckedDiv for $name {
484 fn checked_div(&self, other: &Self) -> Option<Self> {
485 if other.0 == 0 {
486 return None
487 }
488
489 let lhs: I129 = self.0.into();
490 let rhs: I129 = other.0.into();
491 let negative = lhs.negative != rhs.negative;
492
493 multiply_by_rational(lhs.value, Self::DIV as u128, rhs.value).ok()
494 .and_then(|value| from_i129(I129 { value, negative }))
495 .map(Self)
496 }
497 }
498
499 impl CheckedMul for $name {
500 fn checked_mul(&self, other: &Self) -> Option<Self> {
501 let lhs: I129 = self.0.into();
502 let rhs: I129 = other.0.into();
503 let negative = lhs.negative != rhs.negative;
504
505 multiply_by_rational(lhs.value, rhs.value, Self::DIV as u128).ok()
506 .and_then(|value| from_i129(I129 { value, negative }))
507 .map(Self)
508 }
509 }
510
511 impl Bounded for $name {
512 fn min_value() -> Self {
513 Self(<Self as FixedPointNumber>::Inner::min_value())
514 }
515
516 fn max_value() -> Self {
517 Self(<Self as FixedPointNumber>::Inner::max_value())
518 }
519 }
520
521 impl tetcore_std::fmt::Debug for $name {
522 #[cfg(feature = "std")]
523 fn fmt(&self, f: &mut tetcore_std::fmt::Formatter) -> tetcore_std::fmt::Result {
524 let integral = {
525 let int = self.0 / Self::accuracy();
526 let signum_for_zero = if int == 0 && self.is_negative() { "-" } else { "" };
527 format!("{}{}", signum_for_zero, int)
528 };
529 let precision = (Self::accuracy() as f64).log10() as usize;
530 let fractional = format!("{:0>weight$}", ((self.0 % Self::accuracy()) as i128).abs(), weight=precision);
531 write!(f, "{}({}.{})", stringify!($name), integral, fractional)
532 }
533
534 #[cfg(not(feature = "std"))]
535 fn fmt(&self, _: &mut tetcore_std::fmt::Formatter) -> tetcore_std::fmt::Result {
536 Ok(())
537 }
538 }
539
540 impl<P: PerThing> From<P> for $name where P::Inner: FixedPointOperand {
541 fn from(p: P) -> Self {
542 let accuracy = P::ACCURACY;
543 let value = p.deconstruct();
544 $name::saturating_from_rational(value, accuracy)
545 }
546 }
547
548 #[cfg(feature = "std")]
549 impl tetcore_std::fmt::Display for $name {
550 fn fmt(&self, f: &mut tetcore_std::fmt::Formatter) -> tetcore_std::fmt::Result {
551 write!(f, "{}", self.0)
552 }
553 }
554
555 #[cfg(feature = "std")]
556 impl tetcore_std::str::FromStr for $name {
557 type Err = &'static str;
558
559 fn from_str(s: &str) -> Result<Self, Self::Err> {
560 let inner: <Self as FixedPointNumber>::Inner = s.parse()
561 .map_err(|_| "invalid string input for fixed point number")?;
562 Ok(Self::from_inner(inner))
563 }
564 }
565
566 #[cfg(feature = "std")]
569 impl Serialize for $name {
570 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
571 where
572 S: Serializer,
573 {
574 serializer.serialize_str(&self.to_string())
575 }
576 }
577
578 #[cfg(feature = "std")]
581 impl<'de> Deserialize<'de> for $name {
582 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
583 where
584 D: Deserializer<'de>,
585 {
586 use tetcore_std::str::FromStr;
587 let s = String::deserialize(deserializer)?;
588 $name::from_str(&s).map_err(|err_str| de::Error::custom(err_str))
589 }
590 }
591
592 #[cfg(test)]
593 mod $test_mod {
594 use super::*;
595 use crate::{Perbill, Percent, Permill, Perquintill};
596
597 fn max() -> $name {
598 $name::max_value()
599 }
600
601 fn min() -> $name {
602 $name::min_value()
603 }
604
605 fn precision() -> usize {
606 ($name::accuracy() as f64).log10() as usize
607 }
608
609 #[test]
610 fn macro_preconditions() {
611 assert!($name::DIV > 0);
612 }
613
614 #[test]
615 fn from_i129_works() {
616 let a = I129 {
617 value: 1,
618 negative: true,
619 };
620
621 assert_eq!(from_i129::<u128>(a), None);
623
624 let a = I129 {
625 value: u128::max_value() - 1,
626 negative: false,
627 };
628
629 assert_eq!(from_i129::<u128>(a), Some(u128::max_value() - 1));
631
632 let a = I129 {
633 value: u128::max_value(),
634 negative: false,
635 };
636
637 assert_eq!(from_i129::<u128>(a), Some(u128::max_value()));
639
640 let a = I129 {
641 value: i128::max_value() as u128 + 1,
642 negative: true,
643 };
644
645 assert_eq!(from_i129::<i128>(a), Some(i128::min_value()));
647
648 let a = I129 {
649 value: i128::max_value() as u128 + 1,
650 negative: false,
651 };
652
653 assert_eq!(from_i129::<i128>(a), None);
655
656 let a = I129 {
657 value: i128::max_value() as u128,
658 negative: false,
659 };
660
661 assert_eq!(from_i129::<i128>(a), Some(i128::max_value()));
663 }
664
665 #[test]
666 fn to_bound_works() {
667 let a = 1i32;
668 let b = 1i32;
669
670 assert_eq!(to_bound::<_, _, i32>(a, b), i32::max_value());
672
673 let a = -1i32;
674 let b = -1i32;
675
676 assert_eq!(to_bound::<_, _, i32>(a, b), i32::max_value());
678
679 let a = 1i32;
680 let b = -1i32;
681
682 assert_eq!(to_bound::<_, _, i32>(a, b), i32::min_value());
684
685 let a = -1i32;
686 let b = 1i32;
687
688 assert_eq!(to_bound::<_, _, i32>(a, b), i32::min_value());
690
691 let a = 1i32;
692 let b = -1i32;
693
694 assert_eq!(to_bound::<_, _, u32>(a, b), 0);
696 }
697
698 #[test]
699 fn op_neg_works() {
700 let a = $name::zero();
701 let b = -a;
702
703 assert_eq!(a, b);
705
706 if $name::SIGNED {
707 let a = $name::saturating_from_integer(5);
708 let b = -a;
709
710 assert_eq!($name::saturating_from_integer(-5), b);
712
713 let a = $name::saturating_from_integer(-5);
714 let b = -a;
715
716 assert_eq!($name::saturating_from_integer(5), b);
718
719 let a = $name::max_value();
720 let b = -a;
721
722 assert_eq!($name::min_value() + $name::from_inner(1), b);
724
725 let a = $name::min_value() + $name::from_inner(1);
726 let b = -a;
727
728 assert_eq!($name::max_value(), b);
730
731 }
732 }
733
734 #[test]
735 fn op_checked_add_overflow_works() {
736 let a = $name::max_value();
737 let b = 1.into();
738 assert!(a.checked_add(&b).is_none());
739 }
740
741 #[test]
742 fn op_add_works() {
743 let a = $name::saturating_from_rational(5, 2);
744 let b = $name::saturating_from_rational(1, 2);
745
746 assert_eq!($name::saturating_from_integer(3), a + b);
748
749 if $name::SIGNED {
750 let b = $name::saturating_from_rational(1, -2);
752 assert_eq!($name::saturating_from_integer(2), a + b);
753 }
754 }
755
756 #[test]
757 fn op_checked_sub_underflow_works() {
758 let a = $name::min_value();
759 let b = 1.into();
760 assert!(a.checked_sub(&b).is_none());
761 }
762
763 #[test]
764 fn op_sub_works() {
765 let a = $name::saturating_from_rational(5, 2);
766 let b = $name::saturating_from_rational(1, 2);
767
768 assert_eq!($name::saturating_from_integer(2), a - b);
769 assert_eq!($name::saturating_from_integer(-2), b.saturating_sub(a));
770 }
771
772 #[test]
773 fn op_checked_mul_overflow_works() {
774 let a = $name::max_value();
775 let b = 2.into();
776 assert!(a.checked_mul(&b).is_none());
777 }
778
779 #[test]
780 fn op_mul_works() {
781 let a = $name::saturating_from_integer(42);
782 let b = $name::saturating_from_integer(2);
783 assert_eq!($name::saturating_from_integer(84), a * b);
784
785 let a = $name::saturating_from_integer(42);
786 let b = $name::saturating_from_integer(-2);
787 assert_eq!($name::saturating_from_integer(-84), a * b);
788 }
789
790 #[test]
791 #[should_panic(expected = "attempt to divide by zero")]
792 fn op_div_panics_on_zero_divisor() {
793 let a = $name::saturating_from_integer(1);
794 let b = 0.into();
795 let _c = a / b;
796 }
797
798 #[test]
799 fn op_checked_div_overflow_works() {
800 if $name::SIGNED {
801 let a = $name::min_value();
802 let b = $name::zero().saturating_sub($name::one());
803 assert!(a.checked_div(&b).is_none());
804 }
805 }
806
807 #[test]
808 fn op_div_works() {
809 let a = $name::saturating_from_integer(42);
810 let b = $name::saturating_from_integer(2);
811 assert_eq!($name::saturating_from_integer(21), a / b);
812
813 if $name::SIGNED {
814 let a = $name::saturating_from_integer(42);
815 let b = $name::saturating_from_integer(-2);
816 assert_eq!($name::saturating_from_integer(-21), a / b);
817 }
818 }
819
820 #[test]
821 fn saturating_from_integer_works() {
822 let inner_max = <$name as FixedPointNumber>::Inner::max_value();
823 let inner_min = <$name as FixedPointNumber>::Inner::min_value();
824 let accuracy = $name::accuracy();
825
826 let a = $name::saturating_from_integer(42);
828 assert_eq!(a.into_inner(), 42 * accuracy);
829
830 let a = $name::saturating_from_integer(-42);
831 assert_eq!(a.into_inner(), 0.saturating_sub(42 * accuracy));
832
833 let a = $name::saturating_from_integer(inner_max / accuracy);
835 assert_eq!(a.into_inner(), (inner_max / accuracy) * accuracy);
836
837 let a = $name::saturating_from_integer(inner_min / accuracy);
838 assert_eq!(a.into_inner(), (inner_min / accuracy) * accuracy);
839
840 let a = $name::saturating_from_integer(inner_max / accuracy + 1);
842 assert_eq!(a.into_inner(), inner_max);
843
844 let a = $name::saturating_from_integer((inner_min / accuracy).saturating_sub(1));
845 assert_eq!(a.into_inner(), inner_min);
846 }
847
848 #[test]
849 fn checked_from_integer_works() {
850 let inner_max = <$name as FixedPointNumber>::Inner::max_value();
851 let inner_min = <$name as FixedPointNumber>::Inner::min_value();
852 let accuracy = $name::accuracy();
853
854 let a = $name::checked_from_integer(42)
856 .expect("42 * accuracy <= inner_max; qed");
857 assert_eq!(a.into_inner(), 42 * accuracy);
858
859 let a = $name::checked_from_integer(inner_max / accuracy)
861 .expect("(inner_max / accuracy) * accuracy <= inner_max; qed");
862 assert_eq!(a.into_inner(), (inner_max / accuracy) * accuracy);
863
864 let a = $name::checked_from_integer(inner_max / accuracy + 1);
866 assert_eq!(a, None);
867
868 if $name::SIGNED {
869 let a = $name::checked_from_integer(0.saturating_sub(42))
871 .expect("-42 * accuracy >= inner_min; qed");
872 assert_eq!(a.into_inner(), 0 - 42 * accuracy);
873
874 let a = $name::checked_from_integer(inner_min / accuracy)
876 .expect("(inner_min / accuracy) * accuracy <= inner_min; qed");
877 assert_eq!(a.into_inner(), (inner_min / accuracy) * accuracy);
878
879 let a = $name::checked_from_integer(inner_min / accuracy - 1);
881 assert_eq!(a, None);
882 }
883 }
884
885 #[test]
886 fn from_inner_works() {
887 let inner_max = <$name as FixedPointNumber>::Inner::max_value();
888 let inner_min = <$name as FixedPointNumber>::Inner::min_value();
889
890 assert_eq!(max(), $name::from_inner(inner_max));
891 assert_eq!(min(), $name::from_inner(inner_min));
892 }
893
894 #[test]
895 #[should_panic(expected = "attempt to divide by zero")]
896 fn saturating_from_rational_panics_on_zero_divisor() {
897 let _ = $name::saturating_from_rational(1, 0);
898 }
899
900 #[test]
901 fn saturating_from_rational_works() {
902 let inner_max = <$name as FixedPointNumber>::Inner::max_value();
903 let inner_min = <$name as FixedPointNumber>::Inner::min_value();
904 let accuracy = $name::accuracy();
905
906 let a = $name::saturating_from_rational(5, 2);
907
908 assert_eq!(a.into_inner(), 25 * accuracy / 10);
910
911 let a = $name::saturating_from_rational(inner_max - 1, accuracy);
913 assert_eq!(a.into_inner(), inner_max - 1);
914
915 let a = $name::saturating_from_rational(inner_min + 1, accuracy);
917 assert_eq!(a.into_inner(), inner_min + 1);
918
919 let a = $name::saturating_from_rational(inner_max, accuracy);
921 assert_eq!(a.into_inner(), inner_max);
922
923 let a = $name::saturating_from_rational(inner_min, accuracy);
925 assert_eq!(a.into_inner(), inner_min);
926
927 let a = $name::saturating_from_rational(0, 1);
929 assert_eq!(a.into_inner(), 0);
930
931 if $name::SIGNED {
932 let a = $name::saturating_from_rational(-5, 2);
934 assert_eq!(a.into_inner(), 0 - 25 * accuracy / 10);
935
936 let a = $name::saturating_from_rational(5, -2);
938 assert_eq!(a.into_inner(), 0 - 25 * accuracy / 10);
939
940 let a = $name::saturating_from_rational(-5, -2);
942 assert_eq!(a.into_inner(), 25 * accuracy / 10);
943
944 let a = $name::saturating_from_rational(inner_max as u128 + 1, accuracy);
946 assert_eq!(a.into_inner(), inner_max);
947
948 let a = $name::saturating_from_rational(inner_max as u128 + 2, 0 - accuracy);
950 assert_eq!(a.into_inner(), inner_min);
951
952 let a = $name::saturating_from_rational(inner_max, 0 - accuracy);
953 assert_eq!(a.into_inner(), 0 - inner_max);
954
955 let a = $name::saturating_from_rational(inner_min, 0 - accuracy);
956 assert_eq!(a.into_inner(), inner_max);
957
958 let a = $name::saturating_from_rational(inner_min + 1, 0 - accuracy);
959 assert_eq!(a.into_inner(), inner_max);
960
961 let a = $name::saturating_from_rational(inner_min, 0 - 1);
962 assert_eq!(a.into_inner(), inner_max);
963
964 let a = $name::saturating_from_rational(inner_max, 0 - 1);
965 assert_eq!(a.into_inner(), inner_min);
966
967 let a = $name::saturating_from_rational(inner_max, 0 - inner_max);
968 assert_eq!(a.into_inner(), 0 - accuracy);
969
970 let a = $name::saturating_from_rational(0 - inner_max, inner_max);
971 assert_eq!(a.into_inner(), 0 - accuracy);
972
973 let a = $name::saturating_from_rational(inner_max, 0 - 3 * accuracy);
974 assert_eq!(a.into_inner(), 0 - inner_max / 3);
975
976 let a = $name::saturating_from_rational(inner_min, 0 - accuracy / 3);
977 assert_eq!(a.into_inner(), inner_max);
978
979 let a = $name::saturating_from_rational(1, 0 - accuracy);
980 assert_eq!(a.into_inner(), 0.saturating_sub(1));
981
982 let a = $name::saturating_from_rational(inner_min, inner_min);
983 assert_eq!(a.into_inner(), accuracy);
984
985 let a = $name::saturating_from_rational(1, 0 - accuracy - 1);
987 assert_eq!(a.into_inner(), 0);
988 }
989
990 let a = $name::saturating_from_rational(inner_max - 1, accuracy);
991 assert_eq!(a.into_inner(), inner_max - 1);
992
993 let a = $name::saturating_from_rational(inner_min + 1, accuracy);
994 assert_eq!(a.into_inner(), inner_min + 1);
995
996 let a = $name::saturating_from_rational(inner_max, 1);
997 assert_eq!(a.into_inner(), inner_max);
998
999 let a = $name::saturating_from_rational(inner_min, 1);
1000 assert_eq!(a.into_inner(), inner_min);
1001
1002 let a = $name::saturating_from_rational(inner_max, inner_max);
1003 assert_eq!(a.into_inner(), accuracy);
1004
1005 let a = $name::saturating_from_rational(inner_max, 3 * accuracy);
1006 assert_eq!(a.into_inner(), inner_max / 3);
1007
1008 let a = $name::saturating_from_rational(inner_min, 2 * accuracy);
1009 assert_eq!(a.into_inner(), inner_min / 2);
1010
1011 let a = $name::saturating_from_rational(inner_min, accuracy / 3);
1012 assert_eq!(a.into_inner(), inner_min);
1013
1014 let a = $name::saturating_from_rational(1, accuracy);
1015 assert_eq!(a.into_inner(), 1);
1016
1017 let a = $name::saturating_from_rational(1, accuracy + 1);
1019 assert_eq!(a.into_inner(), 0);
1020 }
1021
1022 #[test]
1023 fn checked_from_rational_works() {
1024 let inner_max = <$name as FixedPointNumber>::Inner::max_value();
1025 let inner_min = <$name as FixedPointNumber>::Inner::min_value();
1026 let accuracy = $name::accuracy();
1027
1028 let a = $name::checked_from_rational(1, 0);
1030 assert_eq!(a, None);
1031
1032 let a = $name::checked_from_rational(inner_max - 1, accuracy).unwrap();
1034 assert_eq!(a.into_inner(), inner_max - 1);
1035
1036 let a = $name::checked_from_rational(inner_min + 1, accuracy).unwrap();
1038 assert_eq!(a.into_inner(), inner_min + 1);
1039
1040 let a = $name::checked_from_rational(inner_max, accuracy).unwrap();
1042 assert_eq!(a.into_inner(), inner_max);
1043
1044 let a = $name::checked_from_rational(inner_min, accuracy).unwrap();
1046 assert_eq!(a.into_inner(), inner_min);
1047
1048 let a = $name::checked_from_rational(inner_min, 0.saturating_sub(accuracy));
1050 assert_eq!(a, None);
1051
1052 if $name::SIGNED {
1053 let a = $name::checked_from_rational(inner_max as u128 + 2, 0.saturating_sub(accuracy));
1055 assert_eq!(a, None);
1056
1057 let a = $name::checked_from_rational(inner_max, 0 - 3 * accuracy).unwrap();
1058 assert_eq!(a.into_inner(), 0 - inner_max / 3);
1059
1060 let a = $name::checked_from_rational(inner_min, 0 - accuracy / 3);
1061 assert_eq!(a, None);
1062
1063 let a = $name::checked_from_rational(1, 0 - accuracy).unwrap();
1064 assert_eq!(a.into_inner(), 0.saturating_sub(1));
1065
1066 let a = $name::checked_from_rational(1, 0 - accuracy - 1).unwrap();
1067 assert_eq!(a.into_inner(), 0);
1068
1069 let a = $name::checked_from_rational(inner_min, accuracy / 3);
1070 assert_eq!(a, None);
1071 }
1072
1073 let a = $name::checked_from_rational(inner_max, 3 * accuracy).unwrap();
1074 assert_eq!(a.into_inner(), inner_max / 3);
1075
1076 let a = $name::checked_from_rational(inner_min, 2 * accuracy).unwrap();
1077 assert_eq!(a.into_inner(), inner_min / 2);
1078
1079 let a = $name::checked_from_rational(1, accuracy).unwrap();
1080 assert_eq!(a.into_inner(), 1);
1081
1082 let a = $name::checked_from_rational(1, accuracy + 1).unwrap();
1083 assert_eq!(a.into_inner(), 0);
1084 }
1085
1086 #[test]
1087 fn checked_mul_int_works() {
1088 let a = $name::saturating_from_integer(2);
1089 assert_eq!(a.checked_mul_int((i128::max_value() - 1) / 2), Some(i128::max_value() - 1));
1091 assert_eq!(a.checked_mul_int(i128::max_value() / 2), Some(i128::max_value() - 1));
1093 assert_eq!(a.checked_mul_int(i128::max_value() / 2 + 1), None);
1095
1096 if $name::SIGNED {
1097 assert_eq!(a.checked_mul_int((i128::min_value() + 1) / 2), Some(i128::min_value() + 2));
1099 assert_eq!(a.checked_mul_int(i128::min_value() / 2), Some(i128::min_value()));
1101 assert_eq!(a.checked_mul_int(i128::min_value() / 2 - 1), None);
1103
1104 let b = $name::saturating_from_rational(1, -2);
1105 assert_eq!(b.checked_mul_int(42i128), Some(-21));
1106 assert_eq!(b.checked_mul_int(u128::max_value()), None);
1107 assert_eq!(b.checked_mul_int(i128::max_value()), Some(i128::max_value() / -2));
1108 assert_eq!(b.checked_mul_int(i128::min_value()), Some(i128::min_value() / -2));
1109 }
1110
1111 let a = $name::saturating_from_rational(1, 2);
1112 assert_eq!(a.checked_mul_int(42i128), Some(21));
1113 assert_eq!(a.checked_mul_int(i128::max_value()), Some(i128::max_value() / 2));
1114 assert_eq!(a.checked_mul_int(i128::min_value()), Some(i128::min_value() / 2));
1115
1116 let c = $name::saturating_from_integer(255);
1117 assert_eq!(c.checked_mul_int(2i8), None);
1118 assert_eq!(c.checked_mul_int(2i128), Some(510));
1119 assert_eq!(c.checked_mul_int(i128::max_value()), None);
1120 assert_eq!(c.checked_mul_int(i128::min_value()), None);
1121 }
1122
1123 #[test]
1124 fn saturating_mul_int_works() {
1125 let a = $name::saturating_from_integer(2);
1126 assert_eq!(a.saturating_mul_int((i128::max_value() - 1) / 2), i128::max_value() - 1);
1128 assert_eq!(a.saturating_mul_int(i128::max_value() / 2), i128::max_value() - 1);
1130 assert_eq!(a.saturating_mul_int(i128::max_value() / 2 + 1), i128::max_value());
1132
1133 assert_eq!(a.saturating_mul_int((i128::min_value() + 1) / 2), i128::min_value() + 2);
1135 assert_eq!(a.saturating_mul_int(i128::min_value() / 2), i128::min_value());
1137 assert_eq!(a.saturating_mul_int(i128::min_value() / 2 - 1), i128::min_value());
1139
1140 if $name::SIGNED {
1141 let b = $name::saturating_from_rational(1, -2);
1142 assert_eq!(b.saturating_mul_int(42i32), -21);
1143 assert_eq!(b.saturating_mul_int(i128::max_value()), i128::max_value() / -2);
1144 assert_eq!(b.saturating_mul_int(i128::min_value()), i128::min_value() / -2);
1145 assert_eq!(b.saturating_mul_int(u128::max_value()), u128::min_value());
1146 }
1147
1148 let a = $name::saturating_from_rational(1, 2);
1149 assert_eq!(a.saturating_mul_int(42i32), 21);
1150 assert_eq!(a.saturating_mul_int(i128::max_value()), i128::max_value() / 2);
1151 assert_eq!(a.saturating_mul_int(i128::min_value()), i128::min_value() / 2);
1152
1153 let c = $name::saturating_from_integer(255);
1154 assert_eq!(c.saturating_mul_int(2i8), i8::max_value());
1155 assert_eq!(c.saturating_mul_int(-2i8), i8::min_value());
1156 assert_eq!(c.saturating_mul_int(i128::max_value()), i128::max_value());
1157 assert_eq!(c.saturating_mul_int(i128::min_value()), i128::min_value());
1158 }
1159
1160 #[test]
1161 fn checked_mul_works() {
1162 let inner_max = <$name as FixedPointNumber>::Inner::max_value();
1163 let inner_min = <$name as FixedPointNumber>::Inner::min_value();
1164
1165 let a = $name::saturating_from_integer(2);
1166
1167 let b = $name::from_inner(inner_max - 1);
1169 assert_eq!(a.checked_mul(&(b/2.into())), Some(b));
1170
1171 let c = $name::from_inner(inner_max);
1173 assert_eq!(a.checked_mul(&(c/2.into())), Some(b));
1174
1175 let e = $name::from_inner(1);
1177 assert_eq!(a.checked_mul(&(c/2.into()+e)), None);
1178
1179 if $name::SIGNED {
1180 let b = $name::from_inner(inner_min + 1) / 2.into();
1182 let c = $name::from_inner(inner_min + 2);
1183 assert_eq!(a.checked_mul(&b), Some(c));
1184
1185 let b = $name::from_inner(inner_min) / 2.into();
1187 let c = $name::from_inner(inner_min);
1188 assert_eq!(a.checked_mul(&b), Some(c));
1189
1190 let b = $name::from_inner(inner_min) / 2.into() - $name::from_inner(1);
1192 assert_eq!(a.checked_mul(&b), None);
1193
1194 let c = $name::saturating_from_integer(255);
1195 let b = $name::saturating_from_rational(1, -2);
1196
1197 assert_eq!(b.checked_mul(&42.into()), Some(0.saturating_sub(21).into()));
1198 assert_eq!(b.checked_mul(&$name::max_value()), $name::max_value().checked_div(&0.saturating_sub(2).into()));
1199 assert_eq!(b.checked_mul(&$name::min_value()), $name::min_value().checked_div(&0.saturating_sub(2).into()));
1200 assert_eq!(c.checked_mul(&$name::min_value()), None);
1201 }
1202
1203 let a = $name::saturating_from_rational(1, 2);
1204 let c = $name::saturating_from_integer(255);
1205
1206 assert_eq!(a.checked_mul(&42.into()), Some(21.into()));
1207 assert_eq!(c.checked_mul(&2.into()), Some(510.into()));
1208 assert_eq!(c.checked_mul(&$name::max_value()), None);
1209 assert_eq!(a.checked_mul(&$name::max_value()), $name::max_value().checked_div(&2.into()));
1210 assert_eq!(a.checked_mul(&$name::min_value()), $name::min_value().checked_div(&2.into()));
1211 }
1212
1213 #[test]
1214 fn checked_div_int_works() {
1215 let inner_max = <$name as FixedPointNumber>::Inner::max_value();
1216 let inner_min = <$name as FixedPointNumber>::Inner::min_value();
1217 let accuracy = $name::accuracy();
1218
1219 let a = $name::from_inner(inner_max);
1220 let b = $name::from_inner(inner_min);
1221 let c = $name::zero();
1222 let d = $name::one();
1223 let e = $name::saturating_from_integer(6);
1224 let f = $name::saturating_from_integer(5);
1225
1226 assert_eq!(e.checked_div_int(2.into()), Some(3));
1227 assert_eq!(f.checked_div_int(2.into()), Some(2));
1228
1229 assert_eq!(a.checked_div_int(i128::max_value()), Some(0));
1230 assert_eq!(a.checked_div_int(2), Some(inner_max / (2 * accuracy)));
1231 assert_eq!(a.checked_div_int(inner_max / accuracy), Some(1));
1232 assert_eq!(a.checked_div_int(1i8), None);
1233
1234 if b < c {
1235 assert_eq!(a.checked_div_int(0.saturating_sub(2)), Some(0.saturating_sub(inner_max / (2 * accuracy))));
1237 assert_eq!(a.checked_div_int(0.saturating_sub(inner_max / accuracy)), Some(0.saturating_sub(1)));
1238 assert_eq!(b.checked_div_int(i128::min_value()), Some(0));
1239 assert_eq!(b.checked_div_int(inner_min / accuracy), Some(1));
1240 assert_eq!(b.checked_div_int(1i8), None);
1241 assert_eq!(b.checked_div_int(0.saturating_sub(2)), Some(0.saturating_sub(inner_min / (2 * accuracy))));
1242 assert_eq!(b.checked_div_int(0.saturating_sub(inner_min / accuracy)), Some(0.saturating_sub(1)));
1243 assert_eq!(c.checked_div_int(i128::min_value()), Some(0));
1244 assert_eq!(d.checked_div_int(i32::min_value()), Some(0));
1245 }
1246
1247 assert_eq!(b.checked_div_int(2), Some(inner_min / (2 * accuracy)));
1248
1249 assert_eq!(c.checked_div_int(1), Some(0));
1250 assert_eq!(c.checked_div_int(i128::max_value()), Some(0));
1251 assert_eq!(c.checked_div_int(1i8), Some(0));
1252
1253 assert_eq!(d.checked_div_int(1), Some(1));
1254 assert_eq!(d.checked_div_int(i32::max_value()), Some(0));
1255 assert_eq!(d.checked_div_int(1i8), Some(1));
1256
1257 assert_eq!(a.checked_div_int(0), None);
1258 assert_eq!(b.checked_div_int(0), None);
1259 assert_eq!(c.checked_div_int(0), None);
1260 assert_eq!(d.checked_div_int(0), None);
1261 }
1262
1263 #[test]
1264 #[should_panic(expected = "attempt to divide by zero")]
1265 fn saturating_div_int_panics_when_divisor_is_zero() {
1266 let _ = $name::one().saturating_div_int(0);
1267 }
1268
1269 #[test]
1270 fn saturating_div_int_works() {
1271 let inner_max = <$name as FixedPointNumber>::Inner::max_value();
1272 let inner_min = <$name as FixedPointNumber>::Inner::min_value();
1273 let accuracy = $name::accuracy();
1274
1275 let a = $name::saturating_from_integer(5);
1276 assert_eq!(a.saturating_div_int(2), 2);
1277
1278 let a = $name::min_value();
1279 assert_eq!(a.saturating_div_int(1i128), (inner_min / accuracy) as i128);
1280
1281 if $name::SIGNED {
1282 let a = $name::saturating_from_integer(5);
1283 assert_eq!(a.saturating_div_int(-2), -2);
1284
1285 let a = $name::min_value();
1286 assert_eq!(a.saturating_div_int(-1i128), (inner_max / accuracy) as i128);
1287 }
1288 }
1289
1290 #[test]
1291 fn saturating_abs_works() {
1292 let inner_max = <$name as FixedPointNumber>::Inner::max_value();
1293 let inner_min = <$name as FixedPointNumber>::Inner::min_value();
1294
1295 assert_eq!($name::from_inner(inner_max).saturating_abs(), $name::max_value());
1296 assert_eq!($name::zero().saturating_abs(), 0.into());
1297
1298 if $name::SIGNED {
1299 assert_eq!($name::from_inner(inner_min).saturating_abs(), $name::max_value());
1300 assert_eq!($name::saturating_from_rational(-1, 2).saturating_abs(), (1, 2).into());
1301 }
1302 }
1303
1304 #[test]
1305 fn saturating_mul_acc_int_works() {
1306 assert_eq!($name::zero().saturating_mul_acc_int(42i8), 42i8);
1307 assert_eq!($name::one().saturating_mul_acc_int(42i8), 2 * 42i8);
1308
1309 assert_eq!($name::one().saturating_mul_acc_int(i128::max_value()), i128::max_value());
1310 assert_eq!($name::one().saturating_mul_acc_int(i128::min_value()), i128::min_value());
1311
1312 assert_eq!($name::one().saturating_mul_acc_int(u128::max_value() / 2), u128::max_value() - 1);
1313 assert_eq!($name::one().saturating_mul_acc_int(u128::min_value()), u128::min_value());
1314
1315 if $name::SIGNED {
1316 let a = $name::saturating_from_rational(-1, 2);
1317 assert_eq!(a.saturating_mul_acc_int(42i8), 21i8);
1318 assert_eq!(a.saturating_mul_acc_int(42u8), 21u8);
1319 assert_eq!(a.saturating_mul_acc_int(u128::max_value() - 1), u128::max_value() / 2);
1320 }
1321 }
1322
1323 #[test]
1324 fn saturating_pow_should_work() {
1325 assert_eq!($name::saturating_from_integer(2).saturating_pow(0), $name::saturating_from_integer(1));
1326 assert_eq!($name::saturating_from_integer(2).saturating_pow(1), $name::saturating_from_integer(2));
1327 assert_eq!($name::saturating_from_integer(2).saturating_pow(2), $name::saturating_from_integer(4));
1328 assert_eq!($name::saturating_from_integer(2).saturating_pow(3), $name::saturating_from_integer(8));
1329 assert_eq!($name::saturating_from_integer(2).saturating_pow(50),
1330 $name::saturating_from_integer(1125899906842624i64));
1331
1332 assert_eq!($name::saturating_from_integer(1).saturating_pow(1000), (1).into());
1333 assert_eq!($name::saturating_from_integer(1).saturating_pow(usize::max_value()), (1).into());
1334
1335 if $name::SIGNED {
1336 assert_eq!($name::saturating_from_integer(2).saturating_pow(68), $name::max_value());
1338
1339 assert_eq!($name::saturating_from_integer(-1).saturating_pow(1000), (1).into());
1340 assert_eq!($name::saturating_from_integer(-1).saturating_pow(1001), 0.saturating_sub(1).into());
1341 assert_eq!($name::saturating_from_integer(-1).saturating_pow(usize::max_value()), 0.saturating_sub(1).into());
1342 assert_eq!($name::saturating_from_integer(-1).saturating_pow(usize::max_value() - 1), (1).into());
1343 }
1344
1345 assert_eq!($name::saturating_from_integer(114209).saturating_pow(5), $name::max_value());
1346
1347 assert_eq!($name::saturating_from_integer(1).saturating_pow(usize::max_value()), (1).into());
1348 assert_eq!($name::saturating_from_integer(0).saturating_pow(usize::max_value()), (0).into());
1349 assert_eq!($name::saturating_from_integer(2).saturating_pow(usize::max_value()), $name::max_value());
1350 }
1351
1352 #[test]
1353 fn checked_div_works() {
1354 let inner_max = <$name as FixedPointNumber>::Inner::max_value();
1355 let inner_min = <$name as FixedPointNumber>::Inner::min_value();
1356
1357 let a = $name::from_inner(inner_max);
1358 let b = $name::from_inner(inner_min);
1359 let c = $name::zero();
1360 let d = $name::one();
1361 let e = $name::saturating_from_integer(6);
1362 let f = $name::saturating_from_integer(5);
1363
1364 assert_eq!(e.checked_div(&2.into()), Some(3.into()));
1365 assert_eq!(f.checked_div(&2.into()), Some((5, 2).into()));
1366
1367 assert_eq!(a.checked_div(&inner_max.into()), Some(1.into()));
1368 assert_eq!(a.checked_div(&2.into()), Some($name::from_inner(inner_max / 2)));
1369 assert_eq!(a.checked_div(&$name::max_value()), Some(1.into()));
1370 assert_eq!(a.checked_div(&d), Some(a));
1371
1372 if b < c {
1373 assert_eq!(a.checked_div(&0.saturating_sub(2).into()), Some($name::from_inner(0.saturating_sub(inner_max / 2))));
1375 assert_eq!(a.checked_div(&-$name::max_value()), Some(0.saturating_sub(1).into()));
1376 assert_eq!(b.checked_div(&0.saturating_sub(2).into()), Some($name::from_inner(0.saturating_sub(inner_min / 2))));
1377 assert_eq!(c.checked_div(&$name::max_value()), Some(0.into()));
1378 assert_eq!(b.checked_div(&b), Some($name::one()));
1379 }
1380
1381 assert_eq!(b.checked_div(&2.into()), Some($name::from_inner(inner_min / 2)));
1382 assert_eq!(b.checked_div(&a), Some(0.saturating_sub(1).into()));
1383 assert_eq!(c.checked_div(&1.into()), Some(0.into()));
1384 assert_eq!(d.checked_div(&1.into()), Some(1.into()));
1385
1386 assert_eq!(a.checked_div(&$name::one()), Some(a));
1387 assert_eq!(b.checked_div(&$name::one()), Some(b));
1388 assert_eq!(c.checked_div(&$name::one()), Some(c));
1389 assert_eq!(d.checked_div(&$name::one()), Some(d));
1390
1391 assert_eq!(a.checked_div(&$name::zero()), None);
1392 assert_eq!(b.checked_div(&$name::zero()), None);
1393 assert_eq!(c.checked_div(&$name::zero()), None);
1394 assert_eq!(d.checked_div(&$name::zero()), None);
1395 }
1396
1397 #[test]
1398 fn is_positive_negative_works() {
1399 let one = $name::one();
1400 assert!(one.is_positive());
1401 assert!(!one.is_negative());
1402
1403 let zero = $name::zero();
1404 assert!(!zero.is_positive());
1405 assert!(!zero.is_negative());
1406
1407 if $signed {
1408 let minus_one = $name::saturating_from_integer(-1);
1409 assert!(minus_one.is_negative());
1410 assert!(!minus_one.is_positive());
1411 }
1412 }
1413
1414 #[test]
1415 fn trunc_works() {
1416 let n = $name::saturating_from_rational(5, 2).trunc();
1417 assert_eq!(n, $name::saturating_from_integer(2));
1418
1419 if $name::SIGNED {
1420 let n = $name::saturating_from_rational(-5, 2).trunc();
1421 assert_eq!(n, $name::saturating_from_integer(-2));
1422 }
1423 }
1424
1425 #[test]
1426 fn frac_works() {
1427 let n = $name::saturating_from_rational(5, 2);
1428 let i = n.trunc();
1429 let f = n.frac();
1430
1431 assert_eq!(n, i + f);
1432
1433 let n = $name::saturating_from_rational(5, 2)
1434 .frac()
1435 .saturating_mul(10.into());
1436 assert_eq!(n, 5.into());
1437
1438 let n = $name::saturating_from_rational(1, 2)
1439 .frac()
1440 .saturating_mul(10.into());
1441 assert_eq!(n, 5.into());
1442
1443 if $name::SIGNED {
1444 let n = $name::saturating_from_rational(-5, 2);
1445 let i = n.trunc();
1446 let f = n.frac();
1447 assert_eq!(n, i - f);
1448
1449 let n = $name::saturating_from_rational(-5, 2)
1451 .frac()
1452 .saturating_mul(10.into());
1453 assert_eq!(n, 5.into());
1454
1455 let n = $name::saturating_from_rational(-1, 2)
1456 .frac()
1457 .saturating_mul(10.into());
1458 assert_eq!(n, 0.saturating_sub(5).into());
1459 }
1460 }
1461
1462 #[test]
1463 fn ceil_works() {
1464 let n = $name::saturating_from_rational(5, 2);
1465 assert_eq!(n.ceil(), 3.into());
1466
1467 let n = $name::saturating_from_rational(-5, 2);
1468 assert_eq!(n.ceil(), 0.saturating_sub(2).into());
1469
1470 let n = $name::max_value();
1472 assert_eq!(n.ceil(), n.trunc());
1473
1474 let n = $name::min_value();
1475 assert_eq!(n.ceil(), n.trunc());
1476 }
1477
1478 #[test]
1479 fn floor_works() {
1480 let n = $name::saturating_from_rational(5, 2);
1481 assert_eq!(n.floor(), 2.into());
1482
1483 let n = $name::saturating_from_rational(-5, 2);
1484 assert_eq!(n.floor(), 0.saturating_sub(3).into());
1485
1486 let n = $name::max_value();
1488 assert_eq!(n.floor(), n.trunc());
1489
1490 let n = $name::min_value();
1491 assert_eq!(n.floor(), n.trunc());
1492 }
1493
1494 #[test]
1495 fn round_works() {
1496 let n = $name::zero();
1497 assert_eq!(n.round(), n);
1498
1499 let n = $name::one();
1500 assert_eq!(n.round(), n);
1501
1502 let n = $name::saturating_from_rational(5, 2);
1503 assert_eq!(n.round(), 3.into());
1504
1505 let n = $name::saturating_from_rational(-5, 2);
1506 assert_eq!(n.round(), 0.saturating_sub(3).into());
1507
1508 let n = $name::max_value();
1510 assert_eq!(n.round(), n.trunc());
1511
1512 let n = $name::min_value();
1513 assert_eq!(n.round(), n.trunc());
1514
1515 let n = $name::max_value()
1519 .saturating_sub(1.into())
1520 .trunc()
1521 .saturating_add((1, 3).into());
1522
1523 assert_eq!(n.round(), ($name::max_value() - 1.into()).trunc());
1524
1525 let n = $name::max_value()
1527 .saturating_sub(1.into())
1528 .trunc()
1529 .saturating_add((1, 2).into());
1530
1531 assert_eq!(n.round(), $name::max_value().trunc());
1532
1533 if $name::SIGNED {
1534 let n = $name::min_value()
1536 .saturating_add(1.into())
1537 .trunc()
1538 .saturating_sub((1, 3).into());
1539
1540 assert_eq!(n.round(), ($name::min_value() + 1.into()).trunc());
1541
1542 let n = $name::min_value()
1544 .saturating_add(1.into())
1545 .trunc()
1546 .saturating_sub((1, 2).into());
1547
1548 assert_eq!(n.round(), $name::min_value().trunc());
1549 }
1550 }
1551
1552 #[test]
1553 fn perthing_into_works() {
1554 let ten_percent_percent: $name = Percent::from_percent(10).into();
1555 assert_eq!(ten_percent_percent.into_inner(), $name::accuracy() / 10);
1556
1557 let ten_percent_permill: $name = Permill::from_percent(10).into();
1558 assert_eq!(ten_percent_permill.into_inner(), $name::accuracy() / 10);
1559
1560 let ten_percent_perbill: $name = Perbill::from_percent(10).into();
1561 assert_eq!(ten_percent_perbill.into_inner(), $name::accuracy() / 10);
1562
1563 let ten_percent_perquintill: $name = Perquintill::from_percent(10).into();
1564 assert_eq!(ten_percent_perquintill.into_inner(), $name::accuracy() / 10);
1565 }
1566
1567 #[test]
1568 fn fmt_should_work() {
1569 let zero = $name::zero();
1570 assert_eq!(format!("{:?}", zero), format!("{}(0.{:0>weight$})", stringify!($name), 0, weight=precision()));
1571
1572 let one = $name::one();
1573 assert_eq!(format!("{:?}", one), format!("{}(1.{:0>weight$})", stringify!($name), 0, weight=precision()));
1574
1575 let frac = $name::saturating_from_rational(1, 2);
1576 assert_eq!(format!("{:?}", frac), format!("{}(0.{:0<weight$})", stringify!($name), 5, weight=precision()));
1577
1578 let frac = $name::saturating_from_rational(5, 2);
1579 assert_eq!(format!("{:?}", frac), format!("{}(2.{:0<weight$})", stringify!($name), 5, weight=precision()));
1580
1581 let frac = $name::saturating_from_rational(314, 100);
1582 assert_eq!(format!("{:?}", frac), format!("{}(3.{:0<weight$})", stringify!($name), 14, weight=precision()));
1583
1584 if $name::SIGNED {
1585 let neg = -$name::one();
1586 assert_eq!(format!("{:?}", neg), format!("{}(-1.{:0>weight$})", stringify!($name), 0, weight=precision()));
1587
1588 let frac = $name::saturating_from_rational(-314, 100);
1589 assert_eq!(format!("{:?}", frac), format!("{}(-3.{:0<weight$})", stringify!($name), 14, weight=precision()));
1590 }
1591 }
1592 }
1593 }
1594}
1595
1596implement_fixed!(
1597 FixedI64,
1598 test_fixed_i64,
1599 i64,
1600 true,
1601 1_000_000_000,
1602 "_Fixed Point 64 bits signed, range = [-9223372036.854775808, 9223372036.854775807]_",
1603);
1604
1605implement_fixed!(
1606 FixedI128,
1607 test_fixed_i128,
1608 i128,
1609 true,
1610 1_000_000_000_000_000_000,
1611 "_Fixed Point 128 bits signed, range = \
1612 [-170141183460469231731.687303715884105728, 170141183460469231731.687303715884105727]_",
1613);
1614
1615implement_fixed!(
1616 FixedU128,
1617 test_fixed_u128,
1618 u128,
1619 false,
1620 1_000_000_000_000_000_000,
1621 "_Fixed Point 128 bits unsigned, range = \
1622 [0.000000000000000000, 340282366920938463463.374607431768211455]_",
1623);