1#![doc = docify::embed!("./src/lib.rs", fixed_u64)]
22#![doc = docify::embed!(
29 "./src/lib.rs",
30 fixed_u64_block_computation_example
31)]
32#![doc = docify::embed!(
40 "./src/lib.rs",
41 fixed_u64_operation_example
42)]
43use crate::{
46 helpers_128bit::{multiply_by_rational_with_rounding, sqrt},
47 traits::{
48 Bounded, CheckedAdd, CheckedDiv, CheckedMul, CheckedNeg, CheckedSub, One,
49 SaturatedConversion, Saturating, UniqueSaturatedInto, Zero,
50 },
51 PerThing, Perbill, Rounding, SignedRounding,
52};
53use codec::{CompactAs, Decode, DecodeWithMemTracking, Encode};
54use core::{
55 fmt::Debug,
56 ops::{self, Add, Div, Mul, Sub},
57};
58
59#[cfg(feature = "serde")]
60use serde::{de, Deserialize, Deserializer, Serialize, Serializer};
61
62#[cfg(all(not(feature = "std"), feature = "serde"))]
63use alloc::string::{String, ToString};
64
65pub trait FixedPointOperand:
67 Copy
68 + Clone
69 + Bounded
70 + Zero
71 + Saturating
72 + PartialOrd<Self>
73 + UniqueSaturatedInto<u128>
74 + TryFrom<u128>
75 + CheckedNeg
76{
77}
78
79impl<T> FixedPointOperand for T where
80 T: Copy
81 + Clone
82 + Bounded
83 + Zero
84 + Saturating
85 + PartialOrd<Self>
86 + UniqueSaturatedInto<u128>
87 + TryFrom<u128>
88 + CheckedNeg
89{
90}
91
92pub trait FixedPointNumber:
100 Sized
101 + Copy
102 + Default
103 + Debug
104 + Saturating
105 + Bounded
106 + Eq
107 + PartialEq
108 + Ord
109 + PartialOrd
110 + CheckedSub
111 + CheckedAdd
112 + CheckedMul
113 + CheckedDiv
114 + Add
115 + Sub
116 + Div
117 + Mul
118 + Zero
119 + One
120{
121 type Inner: Debug + One + CheckedMul + CheckedDiv + FixedPointOperand;
123
124 const DIV: Self::Inner;
126
127 const SIGNED: bool;
129
130 fn accuracy() -> Self::Inner {
132 Self::DIV
133 }
134
135 fn from_inner(int: Self::Inner) -> Self;
137
138 fn into_inner(self) -> Self::Inner;
140
141 #[must_use]
143 fn checked_sqrt(self) -> Option<Self>;
144
145 #[must_use]
149 fn saturating_from_integer<N: FixedPointOperand>(int: N) -> Self {
150 let mut n: I129 = int.into();
151 n.value = n.value.saturating_mul(Self::DIV.saturated_into());
152 Self::from_inner(from_i129(n).unwrap_or_else(|| to_bound(int, 0)))
153 }
154
155 #[must_use]
159 fn checked_from_integer<N: Into<Self::Inner>>(int: N) -> Option<Self> {
160 let int: Self::Inner = int.into();
161 int.checked_mul(&Self::DIV).map(Self::from_inner)
162 }
163
164 #[must_use]
168 fn saturating_from_rational<N: FixedPointOperand, D: FixedPointOperand>(n: N, d: D) -> Self {
169 if d == D::zero() {
170 panic!("attempt to divide by zero")
171 }
172 Self::checked_from_rational(n, d).unwrap_or_else(|| to_bound(n, d))
173 }
174
175 #[must_use]
179 fn checked_from_rational<N: FixedPointOperand, D: FixedPointOperand>(
180 n: N,
181 d: D,
182 ) -> Option<Self> {
183 if d == D::zero() {
184 return None;
185 }
186
187 let n: I129 = n.into();
188 let d: I129 = d.into();
189 let negative = n.negative != d.negative;
190
191 multiply_by_rational_with_rounding(
192 n.value,
193 Self::DIV.unique_saturated_into(),
194 d.value,
195 Rounding::from_signed(SignedRounding::Minor, negative),
196 )
197 .and_then(|value| from_i129(I129 { value, negative }))
198 .map(Self::from_inner)
199 }
200
201 #[must_use]
205 fn checked_mul_int<N: FixedPointOperand>(self, n: N) -> Option<N> {
206 let lhs: I129 = self.into_inner().into();
207 let rhs: I129 = n.into();
208 let negative = lhs.negative != rhs.negative;
209
210 multiply_by_rational_with_rounding(
211 lhs.value,
212 rhs.value,
213 Self::DIV.unique_saturated_into(),
214 Rounding::from_signed(SignedRounding::Minor, negative),
215 )
216 .and_then(|value| from_i129(I129 { value, negative }))
217 }
218
219 #[must_use]
223 fn saturating_mul_int<N: FixedPointOperand>(self, n: N) -> N {
224 self.checked_mul_int(n).unwrap_or_else(|| to_bound(self.into_inner(), n))
225 }
226
227 #[must_use]
231 fn checked_div_int<N: FixedPointOperand>(self, d: N) -> Option<N> {
232 let lhs: I129 = self.into_inner().into();
233 let rhs: I129 = d.into();
234 let negative = lhs.negative != rhs.negative;
235
236 lhs.value
237 .checked_div(rhs.value)
238 .and_then(|n| n.checked_div(Self::DIV.unique_saturated_into()))
239 .and_then(|value| from_i129(I129 { value, negative }))
240 }
241
242 #[must_use]
246 fn saturating_div_int<N: FixedPointOperand>(self, d: N) -> N {
247 if d == N::zero() {
248 panic!("attempt to divide by zero")
249 }
250 self.checked_div_int(d).unwrap_or_else(|| to_bound(self.into_inner(), d))
251 }
252
253 #[must_use]
258 fn saturating_mul_acc_int<N: FixedPointOperand>(self, n: N) -> N {
259 if self.is_negative() && n > N::zero() {
260 n.saturating_sub(Self::zero().saturating_sub(self).saturating_mul_int(n))
261 } else {
262 self.saturating_mul_int(n).saturating_add(n)
263 }
264 }
265
266 #[must_use]
270 fn saturating_abs(self) -> Self {
271 let inner = self.into_inner();
272 if inner >= Self::Inner::zero() {
273 self
274 } else {
275 Self::from_inner(inner.checked_neg().unwrap_or_else(Self::Inner::max_value))
276 }
277 }
278
279 #[must_use]
283 fn reciprocal(self) -> Option<Self> {
284 Self::one().checked_div(&self)
285 }
286
287 fn is_one(&self) -> bool {
289 self.into_inner() == Self::Inner::one()
290 }
291
292 fn is_positive(self) -> bool {
294 self.into_inner() > Self::Inner::zero()
295 }
296
297 fn is_negative(self) -> bool {
299 self.into_inner() < Self::Inner::zero()
300 }
301
302 #[must_use]
304 fn trunc(self) -> Self {
305 self.into_inner()
306 .checked_div(&Self::DIV)
307 .expect("panics only if DIV is zero, DIV is not zero; qed")
308 .checked_mul(&Self::DIV)
309 .map(Self::from_inner)
310 .expect("can not overflow since fixed number is >= integer part")
311 }
312
313 #[must_use]
318 fn frac(self) -> Self {
319 let integer = self.trunc();
320 let fractional = self.saturating_sub(integer);
321 if integer == Self::zero() {
322 fractional
323 } else {
324 fractional.saturating_abs()
325 }
326 }
327
328 #[must_use]
332 fn ceil(self) -> Self {
333 if self.is_negative() {
334 self.trunc()
335 } else if self.frac() == Self::zero() {
336 self
337 } else {
338 self.saturating_add(Self::one()).trunc()
339 }
340 }
341
342 #[must_use]
346 fn floor(self) -> Self {
347 if self.is_negative() {
348 self.saturating_sub(Self::one()).trunc()
349 } else {
350 self.trunc()
351 }
352 }
353
354 #[must_use]
358 fn round(self) -> Self {
359 let n = self.frac().saturating_mul(Self::saturating_from_integer(10));
360 if n < Self::saturating_from_integer(5) {
361 self.trunc()
362 } else if self.is_positive() {
363 self.saturating_add(Self::one()).trunc()
364 } else {
365 self.saturating_sub(Self::one()).trunc()
366 }
367 }
368}
369
370struct I129 {
372 value: u128,
373 negative: bool,
374}
375
376impl<N: FixedPointOperand> From<N> for I129 {
377 fn from(n: N) -> I129 {
378 if n < N::zero() {
379 let value: u128 = n
380 .checked_neg()
381 .map(|n| n.unique_saturated_into())
382 .unwrap_or_else(|| N::max_value().unique_saturated_into().saturating_add(1));
383 I129 { value, negative: true }
384 } else {
385 I129 { value: n.unique_saturated_into(), negative: false }
386 }
387 }
388}
389
390fn from_i129<N: FixedPointOperand>(n: I129) -> Option<N> {
392 let max_plus_one: u128 = N::max_value().unique_saturated_into().saturating_add(1);
393 if n.negative && N::min_value() < N::zero() && n.value == max_plus_one {
394 Some(N::min_value())
395 } else {
396 let unsigned_inner: N = n.value.try_into().ok()?;
397 let inner = if n.negative { unsigned_inner.checked_neg()? } else { unsigned_inner };
398 Some(inner)
399 }
400}
401
402fn to_bound<N: FixedPointOperand, D: FixedPointOperand, R: Bounded>(n: N, m: D) -> R {
404 if (n < N::zero()) != (m < D::zero()) {
405 R::min_value()
406 } else {
407 R::max_value()
408 }
409}
410
411macro_rules! implement_fixed {
412 (
413 $name:ident,
414 $test_mod:ident,
415 $inner_type:ty,
416 $signed:tt,
417 $div:tt,
418 $title:expr $(,)?
419 ) => {
420 #[doc = $title]
422 #[derive(
423 Encode,
424 Decode,
425 DecodeWithMemTracking,
426 CompactAs,
427 Default,
428 Copy,
429 Clone,
430 codec::MaxEncodedLen,
431 PartialEq,
432 Eq,
433 PartialOrd,
434 Ord,
435 scale_info::TypeInfo,
436 )]
437 pub struct $name($inner_type);
438
439 impl From<$inner_type> for $name {
440 fn from(int: $inner_type) -> Self {
441 $name::saturating_from_integer(int)
442 }
443 }
444
445 impl<N: FixedPointOperand, D: FixedPointOperand> From<(N, D)> for $name {
446 fn from(r: (N, D)) -> Self {
447 $name::saturating_from_rational(r.0, r.1)
448 }
449 }
450
451 impl FixedPointNumber for $name {
452 type Inner = $inner_type;
453
454 const DIV: Self::Inner = $div;
455 const SIGNED: bool = $signed;
456
457 fn from_inner(inner: Self::Inner) -> Self {
458 Self(inner)
459 }
460
461 fn into_inner(self) -> Self::Inner {
462 self.0
463 }
464
465 fn checked_sqrt(self) -> Option<Self> {
466 self.checked_sqrt()
467 }
468 }
469
470 impl $name {
471 pub const fn from_inner(inner: $inner_type) -> Self {
475 Self(inner)
476 }
477
478 pub const fn into_inner(self) -> $inner_type {
482 self.0
483 }
484
485 pub const fn from_u32(n: u32) -> Self {
490 Self::from_inner((n as $inner_type) * $div)
491 }
492
493 #[cfg(any(feature = "std", test))]
495 pub fn from_float(x: f64) -> Self {
496 Self((x * (<Self as FixedPointNumber>::DIV as f64)) as $inner_type)
497 }
498
499 pub const fn from_perbill(n: Perbill) -> Self {
501 Self::from_rational(n.deconstruct() as u128, 1_000_000_000)
502 }
503
504 pub const fn into_perbill(self) -> Perbill {
506 if self.0 <= 0 {
507 Perbill::zero()
508 } else if self.0 >= $div {
509 Perbill::one()
510 } else {
511 match multiply_by_rational_with_rounding(
512 self.0 as u128,
513 1_000_000_000,
514 Self::DIV as u128,
515 Rounding::NearestPrefDown,
516 ) {
517 Some(value) => {
518 if value > (u32::max_value() as u128) {
519 panic!(
520 "prior logic ensures 0<self.0<DIV; \
521 multiply ensures 0<self.0<1000000000; \
522 qed"
523 );
524 }
525 Perbill::from_parts(value as u32)
526 },
527 None => Perbill::zero(),
528 }
529 }
530 }
531
532 #[cfg(any(feature = "std", test))]
534 pub fn to_float(self) -> f64 {
535 self.0 as f64 / <Self as FixedPointNumber>::DIV as f64
536 }
537
538 pub fn try_into_perthing<P: PerThing>(self) -> Result<P, P> {
542 if self < Self::zero() {
543 Err(P::zero())
544 } else if self > Self::one() {
545 Err(P::one())
546 } else {
547 Ok(P::from_rational(self.0 as u128, $div))
548 }
549 }
550
551 pub fn into_clamped_perthing<P: PerThing>(self) -> P {
554 if self < Self::zero() {
555 P::zero()
556 } else if self > Self::one() {
557 P::one()
558 } else {
559 P::from_rational(self.0 as u128, $div)
560 }
561 }
562
563 pub const fn neg(self) -> Self {
568 Self(0 - self.0)
569 }
570
571 pub const fn sqrt(self) -> Self {
576 match self.checked_sqrt() {
577 Some(v) => v,
578 None => panic!("sqrt overflow or negative input"),
579 }
580 }
581
582 #[deprecated(
583 note = "`try_sqrt` will be removed after October 2025. Use `checked_sqrt` instead."
584 )]
585 pub const fn try_sqrt(self) -> Option<Self> {
586 self.checked_sqrt()
587 }
588
589 pub const fn checked_sqrt(self) -> Option<Self> {
591 if self.0 == 0 {
592 return Some(Self(0));
593 }
594 if self.0 < 1 {
595 return None;
596 }
597 let v = self.0 as u128;
598
599 let maybe_vd = u128::checked_mul(v, $div);
609 let r = if let Some(vd) = maybe_vd { sqrt(vd) } else { sqrt(v) * sqrt($div) };
610 Some(Self(r as $inner_type))
611 }
612
613 pub const fn add(self, rhs: Self) -> Self {
618 Self(self.0 + rhs.0)
619 }
620
621 pub const fn sub(self, rhs: Self) -> Self {
626 Self(self.0 - rhs.0)
627 }
628
629 pub const fn mul(self, rhs: Self) -> Self {
637 match $name::const_checked_mul(self, rhs) {
638 Some(v) => v,
639 None => panic!("attempt to multiply with overflow"),
640 }
641 }
642
643 pub const fn div(self, rhs: Self) -> Self {
651 match $name::const_checked_div(self, rhs) {
652 Some(v) => v,
653 None => panic!("attempt to divide with overflow or NaN"),
654 }
655 }
656
657 const fn into_i129(self) -> I129 {
662 #[allow(unused_comparisons)]
663 if self.0 < 0 {
664 let value = match self.0.checked_neg() {
665 Some(n) => n as u128,
666 None => u128::saturating_add(<$inner_type>::max_value() as u128, 1),
667 };
668 I129 { value, negative: true }
669 } else {
670 I129 { value: self.0 as u128, negative: false }
671 }
672 }
673
674 const fn from_i129(n: I129) -> Option<Self> {
679 let max_plus_one = u128::saturating_add(<$inner_type>::max_value() as u128, 1);
680 #[allow(unused_comparisons)]
681 let inner = if n.negative && <$inner_type>::min_value() < 0 && n.value == max_plus_one {
682 <$inner_type>::min_value()
683 } else {
684 let unsigned_inner = n.value as $inner_type;
685 if unsigned_inner as u128 != n.value || (unsigned_inner > 0) != (n.value > 0) {
686 return None;
687 };
688 if n.negative {
689 match unsigned_inner.checked_neg() {
690 Some(v) => v,
691 None => return None,
692 }
693 } else {
694 unsigned_inner
695 }
696 };
697 Some(Self(inner))
698 }
699
700 pub const fn from_rational(a: u128, b: u128) -> Self {
708 Self::from_rational_with_rounding(a, b, Rounding::NearestPrefDown)
709 }
710
711 pub const fn from_rational_with_rounding(a: u128, b: u128, rounding: Rounding) -> Self {
716 if b == 0 {
717 panic!("attempt to divide by zero in from_rational")
718 }
719 match multiply_by_rational_with_rounding(Self::DIV as u128, a, b, rounding) {
720 Some(value) => match Self::from_i129(I129 { value, negative: false }) {
721 Some(x) => x,
722 None => panic!("overflow in from_rational"),
723 },
724 None => panic!("overflow in from_rational"),
725 }
726 }
727
728 pub const fn const_checked_mul(self, other: Self) -> Option<Self> {
733 self.const_checked_mul_with_rounding(other, SignedRounding::NearestPrefLow)
734 }
735
736 pub const fn const_checked_mul_with_rounding(
742 self,
743 other: Self,
744 rounding: SignedRounding,
745 ) -> Option<Self> {
746 let lhs = self.into_i129();
747 let rhs = other.into_i129();
748 let negative = lhs.negative != rhs.negative;
749
750 match multiply_by_rational_with_rounding(
751 lhs.value,
752 rhs.value,
753 Self::DIV as u128,
754 Rounding::from_signed(rounding, negative),
755 ) {
756 Some(value) => Self::from_i129(I129 { value, negative }),
757 None => None,
758 }
759 }
760
761 pub const fn const_checked_div(self, other: Self) -> Option<Self> {
766 self.checked_rounding_div(other, SignedRounding::NearestPrefLow)
767 }
768
769 pub const fn checked_rounding_div(
775 self,
776 other: Self,
777 rounding: SignedRounding,
778 ) -> Option<Self> {
779 if other.0 == 0 {
780 return None;
781 }
782
783 let lhs = self.into_i129();
784 let rhs = other.into_i129();
785 let negative = lhs.negative != rhs.negative;
786
787 match multiply_by_rational_with_rounding(
788 lhs.value,
789 Self::DIV as u128,
790 rhs.value,
791 Rounding::from_signed(rounding, negative),
792 ) {
793 Some(value) => Self::from_i129(I129 { value, negative }),
794 None => None,
795 }
796 }
797 }
798
799 impl Saturating for $name {
800 fn saturating_add(self, rhs: Self) -> Self {
801 Self(self.0.saturating_add(rhs.0))
802 }
803
804 fn saturating_sub(self, rhs: Self) -> Self {
805 Self(self.0.saturating_sub(rhs.0))
806 }
807
808 fn saturating_mul(self, rhs: Self) -> Self {
809 self.checked_mul(&rhs).unwrap_or_else(|| to_bound(self.0, rhs.0))
810 }
811
812 fn saturating_pow(self, exp: usize) -> Self {
813 if exp == 0 {
814 return Self::saturating_from_integer(1);
815 }
816
817 let exp = exp as u32;
818 let msb_pos = 32 - exp.leading_zeros();
819
820 let mut result = Self::saturating_from_integer(1);
821 let mut pow_val = self;
822 for i in 0..msb_pos {
823 if ((1 << i) & exp) > 0 {
824 result = result.saturating_mul(pow_val);
825 }
826 pow_val = pow_val.saturating_mul(pow_val);
827 }
828 result
829 }
830 }
831
832 impl ops::Neg for $name {
833 type Output = Self;
834
835 fn neg(self) -> Self::Output {
836 Self(<Self as FixedPointNumber>::Inner::zero() - self.0)
837 }
838 }
839
840 impl ops::Add for $name {
841 type Output = Self;
842
843 fn add(self, rhs: Self) -> Self::Output {
844 Self(self.0 + rhs.0)
845 }
846 }
847
848 impl ops::Sub for $name {
849 type Output = Self;
850
851 fn sub(self, rhs: Self) -> Self::Output {
852 Self(self.0 - rhs.0)
853 }
854 }
855
856 impl ops::Mul for $name {
857 type Output = Self;
858
859 fn mul(self, rhs: Self) -> Self::Output {
860 self.checked_mul(&rhs)
861 .unwrap_or_else(|| panic!("attempt to multiply with overflow"))
862 }
863 }
864
865 impl ops::Div for $name {
866 type Output = Self;
867
868 fn div(self, rhs: Self) -> Self::Output {
869 if rhs.0 == 0 {
870 panic!("attempt to divide by zero")
871 }
872 self.checked_div(&rhs)
873 .unwrap_or_else(|| panic!("attempt to divide with overflow"))
874 }
875 }
876
877 impl CheckedSub for $name {
878 fn checked_sub(&self, rhs: &Self) -> Option<Self> {
879 self.0.checked_sub(rhs.0).map(Self)
880 }
881 }
882
883 impl CheckedAdd for $name {
884 fn checked_add(&self, rhs: &Self) -> Option<Self> {
885 self.0.checked_add(rhs.0).map(Self)
886 }
887 }
888
889 impl CheckedDiv for $name {
890 fn checked_div(&self, other: &Self) -> Option<Self> {
891 if other.0 == 0 {
892 return None;
893 }
894
895 let lhs: I129 = self.0.into();
896 let rhs: I129 = other.0.into();
897 let negative = lhs.negative != rhs.negative;
898
899 multiply_by_rational_with_rounding(
904 lhs.value,
905 Self::DIV as u128,
906 rhs.value,
907 Rounding::from_signed(SignedRounding::Minor, negative),
908 )
909 .and_then(|value| from_i129(I129 { value, negative }))
910 .map(Self)
911 }
912 }
913
914 impl CheckedMul for $name {
915 fn checked_mul(&self, other: &Self) -> Option<Self> {
916 let lhs: I129 = self.0.into();
917 let rhs: I129 = other.0.into();
918 let negative = lhs.negative != rhs.negative;
919
920 multiply_by_rational_with_rounding(
921 lhs.value,
922 rhs.value,
923 Self::DIV as u128,
924 Rounding::from_signed(SignedRounding::Minor, negative),
925 )
926 .and_then(|value| from_i129(I129 { value, negative }))
927 .map(Self)
928 }
929 }
930
931 impl Bounded for $name {
932 fn min_value() -> Self {
933 Self(<Self as FixedPointNumber>::Inner::min_value())
934 }
935
936 fn max_value() -> Self {
937 Self(<Self as FixedPointNumber>::Inner::max_value())
938 }
939 }
940
941 impl Zero for $name {
942 fn zero() -> Self {
943 Self::from_inner(<Self as FixedPointNumber>::Inner::zero())
944 }
945
946 fn is_zero(&self) -> bool {
947 self.into_inner() == <Self as FixedPointNumber>::Inner::zero()
948 }
949 }
950
951 impl One for $name {
952 fn one() -> Self {
953 Self::from_inner(Self::DIV)
954 }
955 }
956
957 impl ::core::fmt::Debug for $name {
958 #[cfg(feature = "std")]
959 fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
960 let integral = {
961 let int = self.0 / Self::accuracy();
962 let signum_for_zero = if int == 0 && self.is_negative() { "-" } else { "" };
963 format!("{}{}", signum_for_zero, int)
964 };
965 let precision = (Self::accuracy() as f64).log10() as usize;
966 let fractional = format!(
967 "{:0>weight$}",
968 ((self.0 % Self::accuracy()) as i128).abs(),
969 weight = precision
970 );
971 write!(f, "{}({}.{})", stringify!($name), integral, fractional)
972 }
973
974 #[cfg(not(feature = "std"))]
975 fn fmt(&self, _: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
976 Ok(())
977 }
978 }
979
980 impl<P: PerThing> From<P> for $name
981 where
982 P::Inner: FixedPointOperand,
983 {
984 fn from(p: P) -> Self {
985 let accuracy = P::ACCURACY;
986 let value = p.deconstruct();
987 $name::saturating_from_rational(value, accuracy)
988 }
989 }
990
991 impl ::core::fmt::Display for $name {
992 fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
993 write!(f, "{}", self.0)
994 }
995 }
996
997 impl ::core::str::FromStr for $name {
998 type Err = &'static str;
999
1000 fn from_str(s: &str) -> Result<Self, Self::Err> {
1001 let s = s.trim();
1002
1003 if let Some(dot_pos) = s.find('.') {
1005 let (integer_part, fractional_part) = s.split_at(dot_pos);
1007 let fractional_part = &fractional_part[1..]; let is_negative = integer_part.starts_with('-');
1011
1012 if is_negative && !$name::SIGNED {
1014 return Err(
1015 "negative numbers not supported for unsigned fixed point types",
1016 );
1017 }
1018
1019 let integer: i128 = if integer_part.is_empty() {
1021 0
1022 } else {
1023 integer_part
1024 .parse()
1025 .map_err(|_| "invalid integer part in decimal number")?
1026 };
1027
1028 let fractional_raw: u128 = if fractional_part.is_empty() {
1030 0
1031 } else {
1032 fractional_part
1033 .parse()
1034 .map_err(|_| "invalid fractional part in decimal number")?
1035 };
1036
1037 let fractional_digits = fractional_part.len() as u32;
1039
1040 let fractional_scaled: i128 = if fractional_digits > 0 {
1042 let Some(scale_factor) = 10u128.checked_pow(fractional_digits) else {
1044 return Err("fractional part has too many digits");
1045 };
1046
1047 let div_u128 = Self::DIV as u128;
1049
1050 let quotient = fractional_raw / scale_factor;
1054 let remainder = fractional_raw % scale_factor;
1055 quotient
1056 .checked_mul(div_u128)
1057 .and_then(|base| {
1058 let remainder_scaled = (remainder * div_u128) / scale_factor;
1059 base.checked_add(remainder_scaled)
1060 })
1061 .ok_or("fractional part overflow")?
1062 .try_into()
1063 .map_err(|_| "fractional part too large for signed representation")?
1064 } else {
1065 0
1066 };
1067
1068 let div_i128 = Self::DIV as i128;
1070 let integer_scaled =
1071 integer.checked_mul(div_i128).ok_or("integer part overflow")?;
1072
1073 let result = if is_negative {
1074 integer_scaled
1075 .checked_sub(fractional_scaled)
1076 .ok_or("number too large for fixed point representation")?
1077 } else {
1078 integer_scaled
1079 .checked_add(fractional_scaled)
1080 .ok_or("number too large for fixed point representation")?
1081 };
1082
1083 let inner = <Self as FixedPointNumber>::Inner::try_from(result)
1085 .map_err(|_| "number out of range for fixed point type")?;
1086
1087 Ok(Self::from_inner(inner))
1088 } else {
1089 let inner: <Self as FixedPointNumber>::Inner =
1091 s.parse().map_err(|_| "invalid string input for fixed point number")?;
1092 Ok(Self::from_inner(inner))
1093 }
1094 }
1095 }
1096
1097 #[cfg(feature = "serde")]
1100 impl Serialize for $name {
1101 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
1102 where
1103 S: Serializer,
1104 {
1105 serializer.serialize_str(&self.to_string())
1106 }
1107 }
1108
1109 #[cfg(feature = "serde")]
1112 impl<'de> Deserialize<'de> for $name {
1113 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
1114 where
1115 D: Deserializer<'de>,
1116 {
1117 use ::core::str::FromStr;
1118 let s = String::deserialize(deserializer)?;
1119 $name::from_str(&s).map_err(de::Error::custom)
1120 }
1121 }
1122
1123 #[cfg(test)]
1124 mod $test_mod {
1125 use super::*;
1126 use crate::{Perbill, Percent, Permill, Perquintill};
1127
1128 fn max() -> $name {
1129 $name::max_value()
1130 }
1131
1132 fn min() -> $name {
1133 $name::min_value()
1134 }
1135
1136 fn precision() -> usize {
1137 ($name::accuracy() as f64).log10() as usize
1138 }
1139
1140 #[test]
1141 fn macro_preconditions() {
1142 assert!($name::DIV > 0);
1143 }
1144
1145 #[test]
1146 fn has_max_encoded_len() {
1147 struct AsMaxEncodedLen<T: codec::MaxEncodedLen> {
1148 _data: T,
1149 }
1150
1151 let _ = AsMaxEncodedLen { _data: $name::min_value() };
1152 }
1153
1154 #[test]
1155 fn from_i129_works() {
1156 let a = I129 { value: 1, negative: true };
1157
1158 assert_eq!(from_i129::<u128>(a), None);
1160
1161 let a = I129 { value: u128::MAX - 1, negative: false };
1162
1163 assert_eq!(from_i129::<u128>(a), Some(u128::MAX - 1));
1165
1166 let a = I129 { value: u128::MAX, negative: false };
1167
1168 assert_eq!(from_i129::<u128>(a), Some(u128::MAX));
1170
1171 let a = I129 { value: i128::MAX as u128 + 1, negative: true };
1172
1173 assert_eq!(from_i129::<i128>(a), Some(i128::MIN));
1175
1176 let a = I129 { value: i128::MAX as u128 + 1, negative: false };
1177
1178 assert_eq!(from_i129::<i128>(a), None);
1180
1181 let a = I129 { value: i128::MAX as u128, negative: false };
1182
1183 assert_eq!(from_i129::<i128>(a), Some(i128::MAX));
1185 }
1186
1187 #[test]
1188 fn to_bound_works() {
1189 let a = 1i32;
1190 let b = 1i32;
1191
1192 assert_eq!(to_bound::<_, _, i32>(a, b), i32::MAX);
1194
1195 let a = -1i32;
1196 let b = -1i32;
1197
1198 assert_eq!(to_bound::<_, _, i32>(a, b), i32::MAX);
1200
1201 let a = 1i32;
1202 let b = -1i32;
1203
1204 assert_eq!(to_bound::<_, _, i32>(a, b), i32::MIN);
1206
1207 let a = -1i32;
1208 let b = 1i32;
1209
1210 assert_eq!(to_bound::<_, _, i32>(a, b), i32::MIN);
1212
1213 let a = 1i32;
1214 let b = -1i32;
1215
1216 assert_eq!(to_bound::<_, _, u32>(a, b), 0);
1218 }
1219
1220 #[test]
1221 fn op_neg_works() {
1222 let a = $name::zero();
1223 let b = -a;
1224
1225 assert_eq!(a, b);
1227
1228 if $name::SIGNED {
1229 let a = $name::saturating_from_integer(5);
1230 let b = -a;
1231
1232 assert_eq!($name::saturating_from_integer(-5), b);
1234
1235 let a = $name::saturating_from_integer(-5);
1236 let b = -a;
1237
1238 assert_eq!($name::saturating_from_integer(5), b);
1240
1241 let a = $name::max_value();
1242 let b = -a;
1243
1244 assert_eq!($name::min_value() + $name::from_inner(1), b);
1246
1247 let a = $name::min_value() + $name::from_inner(1);
1248 let b = -a;
1249
1250 assert_eq!($name::max_value(), b);
1252 }
1253 }
1254
1255 #[test]
1256 fn op_checked_add_overflow_works() {
1257 let a = $name::max_value();
1258 let b = 1.into();
1259 assert!(a.checked_add(&b).is_none());
1260 }
1261
1262 #[test]
1263 fn op_add_works() {
1264 let a = $name::saturating_from_rational(5, 2);
1265 let b = $name::saturating_from_rational(1, 2);
1266
1267 assert_eq!($name::saturating_from_integer(3), a + b);
1269
1270 if $name::SIGNED {
1271 let b = $name::saturating_from_rational(1, -2);
1273 assert_eq!($name::saturating_from_integer(2), a + b);
1274 }
1275 }
1276
1277 #[test]
1278 fn op_checked_sub_underflow_works() {
1279 let a = $name::min_value();
1280 let b = 1.into();
1281 assert!(a.checked_sub(&b).is_none());
1282 }
1283
1284 #[test]
1285 fn op_sub_works() {
1286 let a = $name::saturating_from_rational(5, 2);
1287 let b = $name::saturating_from_rational(1, 2);
1288
1289 assert_eq!($name::saturating_from_integer(2), a - b);
1290 assert_eq!($name::saturating_from_integer(-2), b.saturating_sub(a));
1291 }
1292
1293 #[test]
1294 fn op_checked_mul_overflow_works() {
1295 let a = $name::max_value();
1296 let b = 2.into();
1297 assert!(a.checked_mul(&b).is_none());
1298 }
1299
1300 #[test]
1301 fn op_mul_works() {
1302 let a = $name::saturating_from_integer(42);
1303 let b = $name::saturating_from_integer(2);
1304 assert_eq!($name::saturating_from_integer(84), a * b);
1305
1306 let a = $name::saturating_from_integer(42);
1307 let b = $name::saturating_from_integer(-2);
1308 assert_eq!($name::saturating_from_integer(-84), a * b);
1309 }
1310
1311 #[test]
1312 #[should_panic(expected = "attempt to divide by zero")]
1313 fn op_div_panics_on_zero_divisor() {
1314 let a = $name::saturating_from_integer(1);
1315 let b = 0.into();
1316 let _c = a / b;
1317 }
1318
1319 #[test]
1320 fn op_checked_div_overflow_works() {
1321 if $name::SIGNED {
1322 let a = $name::min_value();
1323 let b = $name::zero().saturating_sub($name::one());
1324 assert!(a.checked_div(&b).is_none());
1325 }
1326 }
1327
1328 #[test]
1329 fn op_sqrt_works() {
1330 for i in 1..1_000i64 {
1331 let x = $name::saturating_from_rational(i, 1_000i64);
1332 assert_eq!((x * x).checked_sqrt(), Some(x));
1333 let x = $name::saturating_from_rational(i, 1i64);
1334 assert_eq!((x * x).checked_sqrt(), Some(x));
1335 }
1336 }
1337
1338 #[test]
1339 fn op_div_works() {
1340 let a = $name::saturating_from_integer(42);
1341 let b = $name::saturating_from_integer(2);
1342 assert_eq!($name::saturating_from_integer(21), a / b);
1343
1344 if $name::SIGNED {
1345 let a = $name::saturating_from_integer(42);
1346 let b = $name::saturating_from_integer(-2);
1347 assert_eq!($name::saturating_from_integer(-21), a / b);
1348 }
1349 }
1350
1351 #[test]
1352 fn saturating_from_integer_works() {
1353 let inner_max = <$name as FixedPointNumber>::Inner::max_value();
1354 let inner_min = <$name as FixedPointNumber>::Inner::min_value();
1355 let accuracy = $name::accuracy();
1356
1357 let a = $name::saturating_from_integer(42);
1359 assert_eq!(a.into_inner(), 42 * accuracy);
1360
1361 let a = $name::saturating_from_integer(-42);
1362 assert_eq!(a.into_inner(), 0.saturating_sub(42 * accuracy));
1363
1364 let a = $name::saturating_from_integer(inner_max / accuracy);
1366 assert_eq!(a.into_inner(), (inner_max / accuracy) * accuracy);
1367
1368 let a = $name::saturating_from_integer(inner_min / accuracy);
1369 assert_eq!(a.into_inner(), (inner_min / accuracy) * accuracy);
1370
1371 let a = $name::saturating_from_integer(inner_max / accuracy + 1);
1373 assert_eq!(a.into_inner(), inner_max);
1374
1375 let a = $name::saturating_from_integer((inner_min / accuracy).saturating_sub(1));
1376 assert_eq!(a.into_inner(), inner_min);
1377 }
1378
1379 #[test]
1380 fn checked_from_integer_works() {
1381 let inner_max = <$name as FixedPointNumber>::Inner::max_value();
1382 let inner_min = <$name as FixedPointNumber>::Inner::min_value();
1383 let accuracy = $name::accuracy();
1384
1385 let a = $name::checked_from_integer::<$inner_type>(42)
1387 .expect("42 * accuracy <= inner_max; qed");
1388 assert_eq!(a.into_inner(), 42 * accuracy);
1389
1390 let a = $name::checked_from_integer::<$inner_type>(inner_max / accuracy)
1392 .expect("(inner_max / accuracy) * accuracy <= inner_max; qed");
1393 assert_eq!(a.into_inner(), (inner_max / accuracy) * accuracy);
1394
1395 let a = $name::checked_from_integer::<$inner_type>(inner_max / accuracy + 1);
1397 assert_eq!(a, None);
1398
1399 if $name::SIGNED {
1400 let a = $name::checked_from_integer::<$inner_type>(0.saturating_sub(42))
1402 .expect("-42 * accuracy >= inner_min; qed");
1403 assert_eq!(a.into_inner(), 0 - 42 * accuracy);
1404
1405 let a = $name::checked_from_integer::<$inner_type>(inner_min / accuracy)
1407 .expect("(inner_min / accuracy) * accuracy <= inner_min; qed");
1408 assert_eq!(a.into_inner(), (inner_min / accuracy) * accuracy);
1409
1410 let a = $name::checked_from_integer::<$inner_type>(inner_min / accuracy - 1);
1412 assert_eq!(a, None);
1413 }
1414 }
1415
1416 #[test]
1417 fn from_inner_works() {
1418 let inner_max = <$name as FixedPointNumber>::Inner::max_value();
1419 let inner_min = <$name as FixedPointNumber>::Inner::min_value();
1420
1421 assert_eq!(max(), $name::from_inner(inner_max));
1422 assert_eq!(min(), $name::from_inner(inner_min));
1423 }
1424
1425 #[test]
1426 #[should_panic(expected = "attempt to divide by zero")]
1427 fn saturating_from_rational_panics_on_zero_divisor() {
1428 let _ = $name::saturating_from_rational(1, 0);
1429 }
1430
1431 #[test]
1432 fn saturating_from_rational_works() {
1433 let inner_max = <$name as FixedPointNumber>::Inner::max_value();
1434 let inner_min = <$name as FixedPointNumber>::Inner::min_value();
1435 let accuracy = $name::accuracy();
1436
1437 let a = $name::saturating_from_rational(5, 2);
1438
1439 assert_eq!(a.into_inner(), 25 * accuracy / 10);
1441
1442 let a = $name::saturating_from_rational(inner_max - 1, accuracy);
1444 assert_eq!(a.into_inner(), inner_max - 1);
1445
1446 let a = $name::saturating_from_rational(inner_min + 1, accuracy);
1448 assert_eq!(a.into_inner(), inner_min + 1);
1449
1450 let a = $name::saturating_from_rational(inner_max, accuracy);
1452 assert_eq!(a.into_inner(), inner_max);
1453
1454 let a = $name::saturating_from_rational(inner_min, accuracy);
1456 assert_eq!(a.into_inner(), inner_min);
1457
1458 let a = $name::saturating_from_rational(0, 1);
1460 assert_eq!(a.into_inner(), 0);
1461
1462 if $name::SIGNED {
1463 let a = $name::saturating_from_rational(-5, 2);
1465 assert_eq!(a.into_inner(), 0 - 25 * accuracy / 10);
1466
1467 let a = $name::saturating_from_rational(5, -2);
1469 assert_eq!(a.into_inner(), 0 - 25 * accuracy / 10);
1470
1471 let a = $name::saturating_from_rational(-5, -2);
1473 assert_eq!(a.into_inner(), 25 * accuracy / 10);
1474
1475 let a = $name::saturating_from_rational(inner_max as u128 + 1, accuracy);
1477 assert_eq!(a.into_inner(), inner_max);
1478
1479 let a = $name::saturating_from_rational(inner_max as u128 + 2, 0 - accuracy);
1481 assert_eq!(a.into_inner(), inner_min);
1482
1483 let a = $name::saturating_from_rational(inner_max, 0 - accuracy);
1484 assert_eq!(a.into_inner(), 0 - inner_max);
1485
1486 let a = $name::saturating_from_rational(inner_min, 0 - accuracy);
1487 assert_eq!(a.into_inner(), inner_max);
1488
1489 let a = $name::saturating_from_rational(inner_min + 1, 0 - accuracy);
1490 assert_eq!(a.into_inner(), inner_max);
1491
1492 let a = $name::saturating_from_rational(inner_min, 0 - 1);
1493 assert_eq!(a.into_inner(), inner_max);
1494
1495 let a = $name::saturating_from_rational(inner_max, 0 - 1);
1496 assert_eq!(a.into_inner(), inner_min);
1497
1498 let a = $name::saturating_from_rational(inner_max, 0 - inner_max);
1499 assert_eq!(a.into_inner(), 0 - accuracy);
1500
1501 let a = $name::saturating_from_rational(0 - inner_max, inner_max);
1502 assert_eq!(a.into_inner(), 0 - accuracy);
1503
1504 let a = $name::saturating_from_rational(inner_max, 0 - 3 * accuracy);
1505 assert_eq!(a.into_inner(), 0 - inner_max / 3);
1506
1507 let a = $name::saturating_from_rational(inner_min, 0 - accuracy / 3);
1508 assert_eq!(a.into_inner(), inner_max);
1509
1510 let a = $name::saturating_from_rational(1, 0 - accuracy);
1511 assert_eq!(a.into_inner(), 0.saturating_sub(1));
1512
1513 let a = $name::saturating_from_rational(inner_min, inner_min);
1514 assert_eq!(a.into_inner(), accuracy);
1515
1516 let a = $name::saturating_from_rational(1, 0 - accuracy - 1);
1518 assert_eq!(a.into_inner(), 0);
1519 }
1520
1521 let a = $name::saturating_from_rational(inner_max - 1, accuracy);
1522 assert_eq!(a.into_inner(), inner_max - 1);
1523
1524 let a = $name::saturating_from_rational(inner_min + 1, accuracy);
1525 assert_eq!(a.into_inner(), inner_min + 1);
1526
1527 let a = $name::saturating_from_rational(inner_max, 1);
1528 assert_eq!(a.into_inner(), inner_max);
1529
1530 let a = $name::saturating_from_rational(inner_min, 1);
1531 assert_eq!(a.into_inner(), inner_min);
1532
1533 let a = $name::saturating_from_rational(inner_max, inner_max);
1534 assert_eq!(a.into_inner(), accuracy);
1535
1536 let a = $name::saturating_from_rational(inner_max, 3 * accuracy);
1537 assert_eq!(a.into_inner(), inner_max / 3);
1538
1539 let a = $name::saturating_from_rational(inner_min, 2 * accuracy);
1540 assert_eq!(a.into_inner(), inner_min / 2);
1541
1542 let a = $name::saturating_from_rational(inner_min, accuracy / 3);
1543 assert_eq!(a.into_inner(), inner_min);
1544
1545 let a = $name::saturating_from_rational(1, accuracy);
1546 assert_eq!(a.into_inner(), 1);
1547
1548 let a = $name::saturating_from_rational(1, accuracy + 1);
1550 assert_eq!(a.into_inner(), 0);
1551 }
1552
1553 #[test]
1554 fn checked_from_rational_works() {
1555 let inner_max = <$name as FixedPointNumber>::Inner::max_value();
1556 let inner_min = <$name as FixedPointNumber>::Inner::min_value();
1557 let accuracy = $name::accuracy();
1558
1559 let a = $name::checked_from_rational(1, 0);
1561 assert_eq!(a, None);
1562
1563 let a = $name::checked_from_rational(inner_max - 1, accuracy).unwrap();
1565 assert_eq!(a.into_inner(), inner_max - 1);
1566
1567 let a = $name::checked_from_rational(inner_min + 1, accuracy).unwrap();
1569 assert_eq!(a.into_inner(), inner_min + 1);
1570
1571 let a = $name::checked_from_rational(inner_max, accuracy).unwrap();
1573 assert_eq!(a.into_inner(), inner_max);
1574
1575 let a = $name::checked_from_rational(inner_min, accuracy).unwrap();
1577 assert_eq!(a.into_inner(), inner_min);
1578
1579 let a = $name::checked_from_rational(inner_min, 0.saturating_sub(accuracy));
1581 assert_eq!(a, None);
1582
1583 if $name::SIGNED {
1584 let a = $name::checked_from_rational(
1586 inner_max as u128 + 2,
1587 0.saturating_sub(accuracy),
1588 );
1589 assert_eq!(a, None);
1590
1591 let a = $name::checked_from_rational(inner_max, 0 - 3 * accuracy).unwrap();
1592 assert_eq!(a.into_inner(), 0 - inner_max / 3);
1593
1594 let a = $name::checked_from_rational(inner_min, 0 - accuracy / 3);
1595 assert_eq!(a, None);
1596
1597 let a = $name::checked_from_rational(1, 0 - accuracy).unwrap();
1598 assert_eq!(a.into_inner(), 0.saturating_sub(1));
1599
1600 let a = $name::checked_from_rational(1, 0 - accuracy - 1).unwrap();
1601 assert_eq!(a.into_inner(), 0);
1602
1603 let a = $name::checked_from_rational(inner_min, accuracy / 3);
1604 assert_eq!(a, None);
1605 }
1606
1607 let a = $name::checked_from_rational(inner_max, 3 * accuracy).unwrap();
1608 assert_eq!(a.into_inner(), inner_max / 3);
1609
1610 let a = $name::checked_from_rational(inner_min, 2 * accuracy).unwrap();
1611 assert_eq!(a.into_inner(), inner_min / 2);
1612
1613 let a = $name::checked_from_rational(1, accuracy).unwrap();
1614 assert_eq!(a.into_inner(), 1);
1615
1616 let a = $name::checked_from_rational(1, accuracy + 1).unwrap();
1617 assert_eq!(a.into_inner(), 0);
1618 }
1619
1620 #[test]
1621 fn from_rational_works() {
1622 let inner_max: u128 = <$name as FixedPointNumber>::Inner::max_value() as u128;
1623 let inner_min: u128 = 0;
1624 let accuracy: u128 = $name::accuracy() as u128;
1625
1626 let a = $name::from_rational(inner_max - 1, accuracy);
1628 assert_eq!(a.into_inner() as u128, inner_max - 1);
1629
1630 let a = $name::from_rational(inner_min + 1, accuracy);
1632 assert_eq!(a.into_inner() as u128, inner_min + 1);
1633
1634 let a = $name::from_rational(inner_max, accuracy);
1636 assert_eq!(a.into_inner() as u128, inner_max);
1637
1638 let a = $name::from_rational(inner_min, accuracy);
1640 assert_eq!(a.into_inner() as u128, inner_min);
1641
1642 let a = $name::from_rational(inner_max, 3 * accuracy);
1643 assert_eq!(a.into_inner() as u128, inner_max / 3);
1644
1645 let a = $name::from_rational(1, accuracy);
1646 assert_eq!(a.into_inner() as u128, 1);
1647
1648 let a = $name::from_rational(1, accuracy + 1);
1649 assert_eq!(a.into_inner() as u128, 1);
1650
1651 let a = $name::from_rational_with_rounding(1, accuracy + 1, Rounding::Down);
1652 assert_eq!(a.into_inner() as u128, 0);
1653 }
1654
1655 #[test]
1656 fn checked_mul_int_works() {
1657 let a = $name::saturating_from_integer(2);
1658 assert_eq!(a.checked_mul_int((i128::MAX - 1) / 2), Some(i128::MAX - 1));
1660 assert_eq!(a.checked_mul_int(i128::MAX / 2), Some(i128::MAX - 1));
1662 assert_eq!(a.checked_mul_int(i128::MAX / 2 + 1), None);
1664
1665 if $name::SIGNED {
1666 assert_eq!(a.checked_mul_int((i128::MIN + 1) / 2), Some(i128::MIN + 2));
1668 assert_eq!(a.checked_mul_int(i128::MIN / 2), Some(i128::MIN));
1670 assert_eq!(a.checked_mul_int(i128::MIN / 2 - 1), None);
1672
1673 let b = $name::saturating_from_rational(1, -2);
1674 assert_eq!(b.checked_mul_int(42i128), Some(-21));
1675 assert_eq!(b.checked_mul_int(u128::MAX), None);
1676 assert_eq!(b.checked_mul_int(i128::MAX), Some(i128::MAX / -2));
1677 assert_eq!(b.checked_mul_int(i128::MIN), Some(i128::MIN / -2));
1678 }
1679
1680 let a = $name::saturating_from_rational(1, 2);
1681 assert_eq!(a.checked_mul_int(42i128), Some(21));
1682 assert_eq!(a.checked_mul_int(i128::MAX), Some(i128::MAX / 2));
1683 assert_eq!(a.checked_mul_int(i128::MIN), Some(i128::MIN / 2));
1684
1685 let c = $name::saturating_from_integer(255);
1686 assert_eq!(c.checked_mul_int(2i8), None);
1687 assert_eq!(c.checked_mul_int(2i128), Some(510));
1688 assert_eq!(c.checked_mul_int(i128::MAX), None);
1689 assert_eq!(c.checked_mul_int(i128::MIN), None);
1690 }
1691
1692 #[test]
1693 fn saturating_mul_int_works() {
1694 let a = $name::saturating_from_integer(2);
1695 assert_eq!(a.saturating_mul_int((i128::MAX - 1) / 2), i128::MAX - 1);
1697 assert_eq!(a.saturating_mul_int(i128::MAX / 2), i128::MAX - 1);
1699 assert_eq!(a.saturating_mul_int(i128::MAX / 2 + 1), i128::MAX);
1701
1702 assert_eq!(a.saturating_mul_int((i128::MIN + 1) / 2), i128::MIN + 2);
1704 assert_eq!(a.saturating_mul_int(i128::MIN / 2), i128::MIN);
1706 assert_eq!(a.saturating_mul_int(i128::MIN / 2 - 1), i128::MIN);
1708
1709 if $name::SIGNED {
1710 let b = $name::saturating_from_rational(1, -2);
1711 assert_eq!(b.saturating_mul_int(42i32), -21);
1712 assert_eq!(b.saturating_mul_int(i128::MAX), i128::MAX / -2);
1713 assert_eq!(b.saturating_mul_int(i128::MIN), i128::MIN / -2);
1714 assert_eq!(b.saturating_mul_int(u128::MAX), u128::MIN);
1715 }
1716
1717 let a = $name::saturating_from_rational(1, 2);
1718 assert_eq!(a.saturating_mul_int(42i32), 21);
1719 assert_eq!(a.saturating_mul_int(i128::MAX), i128::MAX / 2);
1720 assert_eq!(a.saturating_mul_int(i128::MIN), i128::MIN / 2);
1721
1722 let c = $name::saturating_from_integer(255);
1723 assert_eq!(c.saturating_mul_int(2i8), i8::MAX);
1724 assert_eq!(c.saturating_mul_int(-2i8), i8::MIN);
1725 assert_eq!(c.saturating_mul_int(i128::MAX), i128::MAX);
1726 assert_eq!(c.saturating_mul_int(i128::MIN), i128::MIN);
1727 }
1728
1729 #[test]
1730 fn checked_mul_works() {
1731 let inner_max = <$name as FixedPointNumber>::Inner::max_value();
1732 let inner_min = <$name as FixedPointNumber>::Inner::min_value();
1733
1734 let a = $name::saturating_from_integer(2);
1735
1736 let b = $name::from_inner(inner_max - 1);
1738 assert_eq!(a.checked_mul(&(b / 2.into())), Some(b));
1739
1740 let c = $name::from_inner(inner_max);
1742 assert_eq!(a.checked_mul(&(c / 2.into())), Some(b));
1743
1744 let e = $name::from_inner(1);
1746 assert_eq!(a.checked_mul(&(c / 2.into() + e)), None);
1747
1748 if $name::SIGNED {
1749 let b = $name::from_inner(inner_min + 1) / 2.into();
1751 let c = $name::from_inner(inner_min + 2);
1752 assert_eq!(a.checked_mul(&b), Some(c));
1753
1754 let b = $name::from_inner(inner_min) / 2.into();
1756 let c = $name::from_inner(inner_min);
1757 assert_eq!(a.checked_mul(&b), Some(c));
1758
1759 let b = $name::from_inner(inner_min) / 2.into() - $name::from_inner(1);
1761 assert_eq!(a.checked_mul(&b), None);
1762
1763 let c = $name::saturating_from_integer(255);
1764 let b = $name::saturating_from_rational(1, -2);
1765
1766 assert_eq!(b.checked_mul(&42.into()), Some(0.saturating_sub(21).into()));
1767 assert_eq!(
1768 b.checked_mul(&$name::max_value()),
1769 $name::max_value().checked_div(&0.saturating_sub(2).into())
1770 );
1771 assert_eq!(
1772 b.checked_mul(&$name::min_value()),
1773 $name::min_value().checked_div(&0.saturating_sub(2).into())
1774 );
1775 assert_eq!(c.checked_mul(&$name::min_value()), None);
1776 }
1777
1778 let a = $name::saturating_from_rational(1, 2);
1779 let c = $name::saturating_from_integer(255);
1780
1781 assert_eq!(a.checked_mul(&42.into()), Some(21.into()));
1782 assert_eq!(c.checked_mul(&2.into()), Some(510.into()));
1783 assert_eq!(c.checked_mul(&$name::max_value()), None);
1784 assert_eq!(
1785 a.checked_mul(&$name::max_value()),
1786 $name::max_value().checked_div(&2.into())
1787 );
1788 assert_eq!(
1789 a.checked_mul(&$name::min_value()),
1790 $name::min_value().checked_div(&2.into())
1791 );
1792 }
1793
1794 #[test]
1795 fn const_checked_mul_works() {
1796 let inner_max = <$name as FixedPointNumber>::Inner::max_value();
1797 let inner_min = <$name as FixedPointNumber>::Inner::min_value();
1798
1799 let a = $name::saturating_from_integer(2u32);
1800
1801 let b = $name::from_inner(inner_max - 1);
1803 assert_eq!(a.const_checked_mul(b / 2.into()), Some(b));
1804
1805 let c = $name::from_inner(inner_max);
1807 assert_eq!(a.const_checked_mul(c / 2.into()), Some(b));
1808
1809 let e = $name::from_inner(1);
1811 assert_eq!(a.const_checked_mul(c / 2.into() + e), None);
1812
1813 if $name::SIGNED {
1814 let b = $name::from_inner(inner_min + 1) / 2.into();
1816 let c = $name::from_inner(inner_min + 2);
1817 assert_eq!(a.const_checked_mul(b), Some(c));
1818
1819 let b = $name::from_inner(inner_min) / 2.into();
1821 let c = $name::from_inner(inner_min);
1822 assert_eq!(a.const_checked_mul(b), Some(c));
1823
1824 let b = $name::from_inner(inner_min) / 2.into() - $name::from_inner(1);
1826 assert_eq!(a.const_checked_mul(b), None);
1827
1828 let b = $name::saturating_from_rational(1i32, -2i32);
1829 let c = $name::saturating_from_integer(-21i32);
1830 let d = $name::saturating_from_integer(42);
1831
1832 assert_eq!(b.const_checked_mul(d), Some(c));
1833
1834 let minus_two = $name::saturating_from_integer(-2i32);
1835 assert_eq!(
1836 b.const_checked_mul($name::max_value()),
1837 $name::max_value().const_checked_div(minus_two)
1838 );
1839 assert_eq!(
1840 b.const_checked_mul($name::min_value()),
1841 $name::min_value().const_checked_div(minus_two)
1842 );
1843
1844 let c = $name::saturating_from_integer(255u32);
1845 assert_eq!(c.const_checked_mul($name::min_value()), None);
1846 }
1847
1848 let a = $name::saturating_from_rational(1i32, 2i32);
1849 let c = $name::saturating_from_integer(255i32);
1850
1851 assert_eq!(a.const_checked_mul(42.into()), Some(21.into()));
1852 assert_eq!(c.const_checked_mul(2.into()), Some(510.into()));
1853 assert_eq!(c.const_checked_mul($name::max_value()), None);
1854 assert_eq!(
1855 a.const_checked_mul($name::max_value()),
1856 $name::max_value().checked_div(&2.into())
1857 );
1858 assert_eq!(
1859 a.const_checked_mul($name::min_value()),
1860 $name::min_value().const_checked_div($name::saturating_from_integer(2))
1861 );
1862 }
1863
1864 #[test]
1865 fn checked_div_int_works() {
1866 let inner_max = <$name as FixedPointNumber>::Inner::max_value();
1867 let inner_min = <$name as FixedPointNumber>::Inner::min_value();
1868 let accuracy = $name::accuracy();
1869
1870 let a = $name::from_inner(inner_max);
1871 let b = $name::from_inner(inner_min);
1872 let c = $name::zero();
1873 let d = $name::one();
1874 let e = $name::saturating_from_integer(6);
1875 let f = $name::saturating_from_integer(5);
1876
1877 assert_eq!(e.checked_div_int(2.into()), Some(3));
1878 assert_eq!(f.checked_div_int(2.into()), Some(2));
1879
1880 assert_eq!(a.checked_div_int(i128::MAX), Some(0));
1881 assert_eq!(a.checked_div_int(2), Some(inner_max / (2 * accuracy)));
1882 assert_eq!(a.checked_div_int(inner_max / accuracy), Some(1));
1883 assert_eq!(a.checked_div_int(1i8), None);
1884
1885 if b < c {
1886 assert_eq!(
1888 a.checked_div_int(0.saturating_sub(2)),
1889 Some(0.saturating_sub(inner_max / (2 * accuracy)))
1890 );
1891 assert_eq!(
1892 a.checked_div_int(0.saturating_sub(inner_max / accuracy)),
1893 Some(0.saturating_sub(1))
1894 );
1895 assert_eq!(b.checked_div_int(i128::MIN), Some(0));
1896 assert_eq!(b.checked_div_int(inner_min / accuracy), Some(1));
1897 assert_eq!(b.checked_div_int(1i8), None);
1898 assert_eq!(
1899 b.checked_div_int(0.saturating_sub(2)),
1900 Some(0.saturating_sub(inner_min / (2 * accuracy)))
1901 );
1902 assert_eq!(
1903 b.checked_div_int(0.saturating_sub(inner_min / accuracy)),
1904 Some(0.saturating_sub(1))
1905 );
1906 assert_eq!(c.checked_div_int(i128::MIN), Some(0));
1907 assert_eq!(d.checked_div_int(i32::MIN), Some(0));
1908 }
1909
1910 assert_eq!(b.checked_div_int(2), Some(inner_min / (2 * accuracy)));
1911
1912 assert_eq!(c.checked_div_int(1), Some(0));
1913 assert_eq!(c.checked_div_int(i128::MAX), Some(0));
1914 assert_eq!(c.checked_div_int(1i8), Some(0));
1915
1916 assert_eq!(d.checked_div_int(1), Some(1));
1917 assert_eq!(d.checked_div_int(i32::MAX), Some(0));
1918 assert_eq!(d.checked_div_int(1i8), Some(1));
1919
1920 assert_eq!(a.checked_div_int(0), None);
1921 assert_eq!(b.checked_div_int(0), None);
1922 assert_eq!(c.checked_div_int(0), None);
1923 assert_eq!(d.checked_div_int(0), None);
1924 }
1925
1926 #[test]
1927 #[should_panic(expected = "attempt to divide by zero")]
1928 fn saturating_div_int_panics_when_divisor_is_zero() {
1929 let _ = $name::one().saturating_div_int(0);
1930 }
1931
1932 #[test]
1933 fn saturating_div_int_works() {
1934 let inner_max = <$name as FixedPointNumber>::Inner::max_value();
1935 let inner_min = <$name as FixedPointNumber>::Inner::min_value();
1936 let accuracy = $name::accuracy();
1937
1938 let a = $name::saturating_from_integer(5);
1939 assert_eq!(a.saturating_div_int(2), 2);
1940
1941 let a = $name::min_value();
1942 assert_eq!(a.saturating_div_int(1i128), (inner_min / accuracy) as i128);
1943
1944 if $name::SIGNED {
1945 let a = $name::saturating_from_integer(5);
1946 assert_eq!(a.saturating_div_int(-2), -2);
1947
1948 let a = $name::min_value();
1949 assert_eq!(a.saturating_div_int(-1i128), (inner_max / accuracy) as i128);
1950 }
1951 }
1952
1953 #[test]
1954 fn saturating_abs_works() {
1955 let inner_max = <$name as FixedPointNumber>::Inner::max_value();
1956 let inner_min = <$name as FixedPointNumber>::Inner::min_value();
1957
1958 assert_eq!($name::from_inner(inner_max).saturating_abs(), $name::max_value());
1959 assert_eq!($name::zero().saturating_abs(), 0.into());
1960
1961 if $name::SIGNED {
1962 assert_eq!($name::from_inner(inner_min).saturating_abs(), $name::max_value());
1963 assert_eq!(
1964 $name::saturating_from_rational(-1, 2).saturating_abs(),
1965 (1, 2).into()
1966 );
1967 }
1968 }
1969
1970 #[test]
1971 fn saturating_mul_acc_int_works() {
1972 assert_eq!($name::zero().saturating_mul_acc_int(42i8), 42i8);
1973 assert_eq!($name::one().saturating_mul_acc_int(42i8), 2 * 42i8);
1974
1975 assert_eq!($name::one().saturating_mul_acc_int(i128::MAX), i128::MAX);
1976 assert_eq!($name::one().saturating_mul_acc_int(i128::MIN), i128::MIN);
1977
1978 assert_eq!($name::one().saturating_mul_acc_int(u128::MAX / 2), u128::MAX - 1);
1979 assert_eq!($name::one().saturating_mul_acc_int(u128::MIN), u128::MIN);
1980
1981 if $name::SIGNED {
1982 let a = $name::saturating_from_rational(-1, 2);
1983 assert_eq!(a.saturating_mul_acc_int(42i8), 21i8);
1984 assert_eq!(a.saturating_mul_acc_int(42u8), 21u8);
1985 assert_eq!(a.saturating_mul_acc_int(u128::MAX - 1), u128::MAX / 2);
1986 }
1987 }
1988
1989 #[test]
1990 fn saturating_pow_should_work() {
1991 assert_eq!(
1992 $name::saturating_from_integer(2).saturating_pow(0),
1993 $name::saturating_from_integer(1)
1994 );
1995 assert_eq!(
1996 $name::saturating_from_integer(2).saturating_pow(1),
1997 $name::saturating_from_integer(2)
1998 );
1999 assert_eq!(
2000 $name::saturating_from_integer(2).saturating_pow(2),
2001 $name::saturating_from_integer(4)
2002 );
2003 assert_eq!(
2004 $name::saturating_from_integer(2).saturating_pow(3),
2005 $name::saturating_from_integer(8)
2006 );
2007 assert_eq!(
2008 $name::saturating_from_integer(2).saturating_pow(50),
2009 $name::saturating_from_integer(1125899906842624i64)
2010 );
2011
2012 assert_eq!($name::saturating_from_integer(1).saturating_pow(1000), (1).into());
2013 assert_eq!(
2014 $name::saturating_from_integer(1).saturating_pow(usize::MAX),
2015 (1).into()
2016 );
2017
2018 if $name::SIGNED {
2019 assert_eq!(
2021 $name::saturating_from_integer(2).saturating_pow(68),
2022 $name::max_value()
2023 );
2024
2025 assert_eq!($name::saturating_from_integer(-1).saturating_pow(1000), (1).into());
2026 assert_eq!(
2027 $name::saturating_from_integer(-1).saturating_pow(1001),
2028 0.saturating_sub(1).into()
2029 );
2030 assert_eq!(
2031 $name::saturating_from_integer(-1).saturating_pow(usize::MAX),
2032 0.saturating_sub(1).into()
2033 );
2034 assert_eq!(
2035 $name::saturating_from_integer(-1).saturating_pow(usize::MAX - 1),
2036 (1).into()
2037 );
2038 }
2039
2040 assert_eq!(
2041 $name::saturating_from_integer(114209).saturating_pow(5),
2042 $name::max_value()
2043 );
2044
2045 assert_eq!(
2046 $name::saturating_from_integer(1).saturating_pow(usize::MAX),
2047 (1).into()
2048 );
2049 assert_eq!(
2050 $name::saturating_from_integer(0).saturating_pow(usize::MAX),
2051 (0).into()
2052 );
2053 assert_eq!(
2054 $name::saturating_from_integer(2).saturating_pow(usize::MAX),
2055 $name::max_value()
2056 );
2057 }
2058
2059 #[test]
2060 fn checked_div_works() {
2061 let inner_max = <$name as FixedPointNumber>::Inner::max_value();
2062 let inner_min = <$name as FixedPointNumber>::Inner::min_value();
2063
2064 let a = $name::from_inner(inner_max);
2065 let b = $name::from_inner(inner_min);
2066 let c = $name::zero();
2067 let d = $name::one();
2068 let e = $name::saturating_from_integer(6);
2069 let f = $name::saturating_from_integer(5);
2070
2071 assert_eq!(e.checked_div(&2.into()), Some(3.into()));
2072 assert_eq!(f.checked_div(&2.into()), Some((5, 2).into()));
2073
2074 assert_eq!(a.checked_div(&inner_max.into()), Some(1.into()));
2075 assert_eq!(a.checked_div(&2.into()), Some($name::from_inner(inner_max / 2)));
2076 assert_eq!(a.checked_div(&$name::max_value()), Some(1.into()));
2077 assert_eq!(a.checked_div(&d), Some(a));
2078
2079 if b < c {
2080 assert_eq!(
2082 a.checked_div(&0.saturating_sub(2).into()),
2083 Some($name::from_inner(0.saturating_sub(inner_max / 2)))
2084 );
2085 assert_eq!(
2086 a.checked_div(&-$name::max_value()),
2087 Some(0.saturating_sub(1).into())
2088 );
2089 assert_eq!(
2090 b.checked_div(&0.saturating_sub(2).into()),
2091 Some($name::from_inner(0.saturating_sub(inner_min / 2)))
2092 );
2093 assert_eq!(c.checked_div(&$name::max_value()), Some(0.into()));
2094 assert_eq!(b.checked_div(&b), Some($name::one()));
2095 }
2096
2097 assert_eq!(b.checked_div(&2.into()), Some($name::from_inner(inner_min / 2)));
2098 assert_eq!(b.checked_div(&a), Some(0.saturating_sub(1).into()));
2099 assert_eq!(c.checked_div(&1.into()), Some(0.into()));
2100 assert_eq!(d.checked_div(&1.into()), Some(1.into()));
2101
2102 assert_eq!(a.checked_div(&$name::one()), Some(a));
2103 assert_eq!(b.checked_div(&$name::one()), Some(b));
2104 assert_eq!(c.checked_div(&$name::one()), Some(c));
2105 assert_eq!(d.checked_div(&$name::one()), Some(d));
2106
2107 assert_eq!(a.checked_div(&$name::zero()), None);
2108 assert_eq!(b.checked_div(&$name::zero()), None);
2109 assert_eq!(c.checked_div(&$name::zero()), None);
2110 assert_eq!(d.checked_div(&$name::zero()), None);
2111 }
2112
2113 #[test]
2114 fn is_positive_negative_works() {
2115 let one = $name::one();
2116 assert!(one.is_positive());
2117 assert!(!one.is_negative());
2118
2119 let zero = $name::zero();
2120 assert!(!zero.is_positive());
2121 assert!(!zero.is_negative());
2122
2123 if $signed {
2124 let minus_one = $name::saturating_from_integer(-1);
2125 assert!(minus_one.is_negative());
2126 assert!(!minus_one.is_positive());
2127 }
2128 }
2129
2130 #[test]
2131 fn trunc_works() {
2132 let n = $name::saturating_from_rational(5, 2).trunc();
2133 assert_eq!(n, $name::saturating_from_integer(2));
2134
2135 if $name::SIGNED {
2136 let n = $name::saturating_from_rational(-5, 2).trunc();
2137 assert_eq!(n, $name::saturating_from_integer(-2));
2138 }
2139 }
2140
2141 #[test]
2142 fn frac_works() {
2143 let n = $name::saturating_from_rational(5, 2);
2144 let i = n.trunc();
2145 let f = n.frac();
2146
2147 assert_eq!(n, i + f);
2148
2149 let n = $name::saturating_from_rational(5, 2).frac().saturating_mul(10.into());
2150 assert_eq!(n, 5.into());
2151
2152 let n = $name::saturating_from_rational(1, 2).frac().saturating_mul(10.into());
2153 assert_eq!(n, 5.into());
2154
2155 if $name::SIGNED {
2156 let n = $name::saturating_from_rational(-5, 2);
2157 let i = n.trunc();
2158 let f = n.frac();
2159 assert_eq!(n, i - f);
2160
2161 let n = $name::saturating_from_rational(-5, 2).frac().saturating_mul(10.into());
2163 assert_eq!(n, 5.into());
2164
2165 let n = $name::saturating_from_rational(-1, 2).frac().saturating_mul(10.into());
2166 assert_eq!(n, 0.saturating_sub(5).into());
2167 }
2168 }
2169
2170 #[test]
2171 fn ceil_works() {
2172 let n = $name::saturating_from_rational(5, 2);
2173 assert_eq!(n.ceil(), 3.into());
2174
2175 let n = $name::saturating_from_rational(-5, 2);
2176 assert_eq!(n.ceil(), 0.saturating_sub(2).into());
2177
2178 let n = $name::max_value();
2180 assert_eq!(n.ceil(), n.trunc());
2181
2182 let n = $name::min_value();
2183 assert_eq!(n.ceil(), n.trunc());
2184 }
2185
2186 #[test]
2187 fn floor_works() {
2188 let n = $name::saturating_from_rational(5, 2);
2189 assert_eq!(n.floor(), 2.into());
2190
2191 let n = $name::saturating_from_rational(-5, 2);
2192 assert_eq!(n.floor(), 0.saturating_sub(3).into());
2193
2194 let n = $name::max_value();
2196 assert_eq!(n.floor(), n.trunc());
2197
2198 let n = $name::min_value();
2199 assert_eq!(n.floor(), n.trunc());
2200 }
2201
2202 #[test]
2203 fn round_works() {
2204 let n = $name::zero();
2205 assert_eq!(n.round(), n);
2206
2207 let n = $name::one();
2208 assert_eq!(n.round(), n);
2209
2210 let n = $name::saturating_from_rational(5, 2);
2211 assert_eq!(n.round(), 3.into());
2212
2213 let n = $name::saturating_from_rational(-5, 2);
2214 assert_eq!(n.round(), 0.saturating_sub(3).into());
2215
2216 let n = $name::max_value();
2218 assert_eq!(n.round(), n.trunc());
2219
2220 let n = $name::min_value();
2221 assert_eq!(n.round(), n.trunc());
2222
2223 let n = $name::max_value()
2227 .saturating_sub(1.into())
2228 .trunc()
2229 .saturating_add((1, 3).into());
2230
2231 assert_eq!(n.round(), ($name::max_value() - 1.into()).trunc());
2232
2233 let n = $name::max_value()
2235 .saturating_sub(1.into())
2236 .trunc()
2237 .saturating_add((1, 2).into());
2238
2239 assert_eq!(n.round(), $name::max_value().trunc());
2240
2241 if $name::SIGNED {
2242 let n = $name::min_value()
2244 .saturating_add(1.into())
2245 .trunc()
2246 .saturating_sub((1, 3).into());
2247
2248 assert_eq!(n.round(), ($name::min_value() + 1.into()).trunc());
2249
2250 let n = $name::min_value()
2252 .saturating_add(1.into())
2253 .trunc()
2254 .saturating_sub((1, 2).into());
2255
2256 assert_eq!(n.round(), $name::min_value().trunc());
2257 }
2258 }
2259
2260 #[test]
2261 fn perthing_into_works() {
2262 let ten_percent_percent: $name = Percent::from_percent(10).into();
2263 assert_eq!(ten_percent_percent.into_inner(), $name::accuracy() / 10);
2264
2265 let ten_percent_permill: $name = Permill::from_percent(10).into();
2266 assert_eq!(ten_percent_permill.into_inner(), $name::accuracy() / 10);
2267
2268 let ten_percent_perbill: $name = Perbill::from_percent(10).into();
2269 assert_eq!(ten_percent_perbill.into_inner(), $name::accuracy() / 10);
2270
2271 let ten_percent_perquintill: $name = Perquintill::from_percent(10).into();
2272 assert_eq!(ten_percent_perquintill.into_inner(), $name::accuracy() / 10);
2273 }
2274
2275 #[test]
2276 fn fmt_should_work() {
2277 let zero = $name::zero();
2278 assert_eq!(
2279 format!("{:?}", zero),
2280 format!("{}(0.{:0>weight$})", stringify!($name), 0, weight = precision())
2281 );
2282
2283 let one = $name::one();
2284 assert_eq!(
2285 format!("{:?}", one),
2286 format!("{}(1.{:0>weight$})", stringify!($name), 0, weight = precision())
2287 );
2288
2289 let frac = $name::saturating_from_rational(1, 2);
2290 assert_eq!(
2291 format!("{:?}", frac),
2292 format!("{}(0.{:0<weight$})", stringify!($name), 5, weight = precision())
2293 );
2294
2295 let frac = $name::saturating_from_rational(5, 2);
2296 assert_eq!(
2297 format!("{:?}", frac),
2298 format!("{}(2.{:0<weight$})", stringify!($name), 5, weight = precision())
2299 );
2300
2301 let frac = $name::saturating_from_rational(314, 100);
2302 assert_eq!(
2303 format!("{:?}", frac),
2304 format!("{}(3.{:0<weight$})", stringify!($name), 14, weight = precision())
2305 );
2306
2307 if $name::SIGNED {
2308 let neg = -$name::one();
2309 assert_eq!(
2310 format!("{:?}", neg),
2311 format!("{}(-1.{:0>weight$})", stringify!($name), 0, weight = precision())
2312 );
2313
2314 let frac = $name::saturating_from_rational(-314, 100);
2315 assert_eq!(
2316 format!("{:?}", frac),
2317 format!("{}(-3.{:0<weight$})", stringify!($name), 14, weight = precision())
2318 );
2319 }
2320 }
2321
2322 #[test]
2323 fn from_str_works() {
2324 use core::str::FromStr;
2325 let val = $name::from_str("1.0").unwrap();
2327 assert_eq!(val.into_inner(), $name::accuracy());
2328
2329 let val = $name::from_str("0.5").unwrap();
2330 assert_eq!(val.into_inner(), $name::accuracy() / 2);
2331
2332 let val = $name::from_str("2.5").unwrap();
2333 assert_eq!(val.into_inner(), $name::accuracy() * 5 / 2);
2334
2335 let val = $name::from_str("42").unwrap();
2337 assert_eq!(val.into_inner(), 42);
2338
2339 let val = $name::from_str("100.0").unwrap();
2340 assert_eq!(val.into_inner(), $name::accuracy() * 100);
2341
2342 let val = $name::from_str("0.25").unwrap();
2344 assert_eq!(val.into_inner(), $name::accuracy() / 4);
2345
2346 let val = $name::from_str(".5").unwrap();
2347 assert_eq!(val.into_inner(), $name::accuracy() / 2);
2348
2349 let val = $name::from_str("1.00045").unwrap();
2351 let expected = $name::accuracy() + ($name::accuracy() * 45 / 100000);
2352 assert_eq!(val.into_inner(), expected);
2353
2354 if $name::accuracy() >= 1_000_000_000_000_000_000 {
2356 let val = $name::from_str("0.123456789012345678").unwrap();
2358 let expected = ($name::accuracy() as u128 * 123456789012345678u128) /
2359 1000000000000000000u128;
2360 assert_eq!(val.into_inner() as u128, expected);
2361 } else {
2362 let val = $name::from_str("0.123456789").unwrap();
2364 let expected = ($name::accuracy() as u128 * 123456789u128) / 1000000000u128;
2365 assert_eq!(val.into_inner() as u128, expected);
2366 }
2367
2368 let val = $name::from_str("1000000000").unwrap();
2370 assert_eq!(val.into_inner(), 1000000000);
2371
2372 if $name::SIGNED {
2373 let val = $name::from_str("-1.0").unwrap();
2375 assert_eq!(val.into_inner(), 0 - $name::accuracy());
2376
2377 let val = $name::from_str("-0.5").unwrap();
2378 assert_eq!(val.into_inner(), 0 - $name::accuracy() / 2);
2379
2380 let val = $name::from_str("-2.5").unwrap();
2381 assert_eq!(val.into_inner(), 0 - $name::accuracy() * 5 / 2);
2382 } else {
2383 assert!($name::from_str("-1.0").is_err());
2385 assert!($name::from_str("-0.5").is_err());
2386 assert!($name::from_str("-123.456").is_err());
2387 }
2388
2389 assert!($name::from_str("").is_err());
2391 assert!($name::from_str("abc").is_err());
2392 assert!($name::from_str("1.2.3").is_err());
2393 assert!($name::from_str("1.abc").is_err());
2394 assert!($name::from_str("abc.1").is_err());
2395 }
2396 }
2397 };
2398}
2399
2400#[cfg(test)]
2401mod precision_tests {
2402 use super::*;
2403 use core::str::FromStr;
2404
2405 #[test]
2406 fn test_from_str_precision_verification() {
2407 let val = FixedU64::from_str("0.123456789").unwrap();
2409 let expected = 123456789u64; assert_eq!(val.into_inner(), expected);
2411
2412 let val = FixedU128::from_str("0.123456789012345678").unwrap();
2414 let expected = 123456789012345678u128; assert_eq!(val.into_inner(), expected);
2416
2417 let val = FixedU128::from_str("1.123456789012345678").unwrap();
2419 let expected = 1000000000000000000u128 + 123456789012345678u128;
2420 assert_eq!(val.into_inner(), expected);
2421
2422 let val = FixedI64::from_str("-0.123456789").unwrap();
2424 let expected = -123456789i64; assert_eq!(val.into_inner(), expected);
2426
2427 let val = FixedU64::from_str("1.000000001").unwrap();
2429 let expected = 1000000001u64; assert_eq!(val.into_inner(), expected);
2431
2432 let val = FixedU64::from_str("0.1234567891234").unwrap();
2434 let expected = 123456789u64; assert_eq!(val.into_inner(), expected);
2436 }
2437}
2438
2439implement_fixed!(
2440 FixedI64,
2441 test_fixed_i64,
2442 i64,
2443 true,
2444 1_000_000_000,
2445 "_Fixed Point 64 bits signed, range = [-9223372036.854775808, 9223372036.854775807]_",
2446);
2447
2448implement_fixed!(
2449 FixedU64,
2450 test_fixed_u64,
2451 u64,
2452 false,
2453 1_000_000_000,
2454 "_Fixed Point 64 bits unsigned, range = [0.000000000, 18446744073.709551615]_",
2455);
2456
2457implement_fixed!(
2458 FixedI128,
2459 test_fixed_i128,
2460 i128,
2461 true,
2462 1_000_000_000_000_000_000,
2463 "_Fixed Point 128 bits signed, range = \
2464 [-170141183460469231731.687303715884105728, 170141183460469231731.687303715884105727]_",
2465);
2466
2467implement_fixed!(
2468 FixedU128,
2469 test_fixed_u128,
2470 u128,
2471 false,
2472 1_000_000_000_000_000_000,
2473 "_Fixed Point 128 bits unsigned, range = \
2474 [0.000000000000000000, 340282366920938463463.374607431768211455]_",
2475);