referrerpolicy=no-referrer-when-downgrade

sp_arithmetic/
fixed_point.rs

1// This file is part of Substrate.
2
3// Copyright (C) Parity Technologies (UK) Ltd.
4// SPDX-License-Identifier: Apache-2.0
5
6// Licensed under the Apache License, Version 2.0 (the "License");
7// you may not use this file except in compliance with the License.
8// You may obtain a copy of the License at
9//
10// 	http://www.apache.org/licenses/LICENSE-2.0
11//
12// Unless required by applicable law or agreed to in writing, software
13// distributed under the License is distributed on an "AS IS" BASIS,
14// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15// See the License for the specific language governing permissions and
16// limitations under the License.
17
18//! Decimal Fixed Point implementations for Substrate runtime.
19//! Similar to types that implement [`PerThing`](crate::per_things), these are also
20//! fixed-point types, however, they are able to represent larger fractions:
21#![doc = docify::embed!("./src/lib.rs", fixed_u64)]
22//! ### Fixed Point Types in Practice
23//!
24//! If one needs to exceed the value of one (1), then
25//! [`FixedU64`](FixedU64) (and its signed and `u128` counterparts) can be utilized.
26//! Take for example this very rudimentary pricing mechanism, where we wish to calculate the demand
27//! / supply to get a price for some on-chain compute:
28#![doc = docify::embed!(
29	"./src/lib.rs",
30	fixed_u64_block_computation_example
31)]
32//! For a much more comprehensive example, be sure to look at the source for broker (the "coretime")
33//! pallet.
34//!
35//! #### Fixed Point Types in Practice
36//!
37//! Just as with [`PerThing`](PerThing), you can also perform regular mathematical
38//! expressions:
39#![doc = docify::embed!(
40	"./src/lib.rs",
41	fixed_u64_operation_example
42)]
43//!
44
45use 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
65/// Integer types that can be used to interact with `FixedPointNumber` implementations.
66pub 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
92/// Something that implements a decimal fixed point number.
93///
94/// The precision is given by `Self::DIV`, i.e. `1 / DIV` can be represented.
95///
96/// Each type can store numbers from `Self::Inner::min_value() / Self::DIV`
97/// to `Self::Inner::max_value() / Self::DIV`.
98/// This is also referred to as the _accuracy_ of the type in the documentation.
99pub 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	/// The underlying data type used for this fixed point number.
122	type Inner: Debug + One + CheckedMul + CheckedDiv + FixedPointOperand;
123
124	/// Precision of this fixed point implementation. It should be a power of `10`.
125	const DIV: Self::Inner;
126
127	/// Indicates if this fixed point implementation is signed or not.
128	const SIGNED: bool;
129
130	/// Precision of this fixed point implementation.
131	fn accuracy() -> Self::Inner {
132		Self::DIV
133	}
134
135	/// Builds this type from an integer number.
136	fn from_inner(int: Self::Inner) -> Self;
137
138	/// Consumes `self` and returns the inner raw value.
139	fn into_inner(self) -> Self::Inner;
140
141	/// Compute the square root. If it overflows or is negative, then `None` is returned.
142	#[must_use]
143	fn checked_sqrt(self) -> Option<Self>;
144
145	/// Creates self from an integer number `int`.
146	///
147	/// Returns `Self::max` or `Self::min` if `int` exceeds accuracy.
148	#[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	/// Creates `self` from an integer number `int`.
156	///
157	/// Returns `None` if `int` exceeds accuracy.
158	#[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	/// Creates `self` from a rational number. Equal to `n / d`.
165	///
166	/// Panics if `d = 0`. Returns `Self::max` or `Self::min` if `n / d` exceeds accuracy.
167	#[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	/// Creates `self` from a rational number. Equal to `n / d`.
176	///
177	/// Returns `None` if `d == 0` or `n / d` exceeds accuracy.
178	#[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	/// Checked multiplication for integer type `N`. Equal to `self * n`.
202	///
203	/// Returns `None` if the result does not fit in `N`.
204	#[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	/// Saturating multiplication for integer type `N`. Equal to `self * n`.
220	///
221	/// Returns `N::min` or `N::max` if the result does not fit in `N`.
222	#[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	/// Checked division for integer type `N`. Equal to `self / d`.
228	///
229	/// Returns `None` if the result does not fit in `N` or `d == 0`.
230	#[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	/// Saturating division for integer type `N`. Equal to `self / d`.
243	///
244	/// Panics if `d == 0`. Returns `N::min` or `N::max` if the result does not fit in `N`.
245	#[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	/// Saturating multiplication for integer type `N`, adding the result back.
254	/// Equal to `self * n + n`.
255	///
256	/// Returns `N::min` or `N::max` if the multiplication or final result does not fit in `N`.
257	#[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	/// Saturating absolute value.
267	///
268	/// Returns `Self::max` if `self == Self::min`.
269	#[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	/// Takes the reciprocal (inverse). Equal to `1 / self`.
280	///
281	/// Returns `None` if `self = 0`.
282	#[must_use]
283	fn reciprocal(self) -> Option<Self> {
284		Self::one().checked_div(&self)
285	}
286
287	/// Checks if the number is one.
288	fn is_one(&self) -> bool {
289		self.into_inner() == Self::Inner::one()
290	}
291
292	/// Returns `true` if `self` is positive and `false` if the number is zero or negative.
293	fn is_positive(self) -> bool {
294		self.into_inner() > Self::Inner::zero()
295	}
296
297	/// Returns `true` if `self` is negative and `false` if the number is zero or positive.
298	fn is_negative(self) -> bool {
299		self.into_inner() < Self::Inner::zero()
300	}
301
302	/// Returns the integer part.
303	#[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	/// Returns the fractional part.
314	///
315	/// Note: the returned fraction will be non-negative for negative numbers,
316	/// except in the case where the integer part is zero.
317	#[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	/// Returns the smallest integer greater than or equal to a number.
329	///
330	/// Saturates to `Self::max` (truncated) if the result does not fit.
331	#[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	/// Returns the largest integer less than or equal to a number.
343	///
344	/// Saturates to `Self::min` (truncated) if the result does not fit.
345	#[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	/// Returns the number rounded to the nearest integer. Rounds half-way cases away from 0.0.
355	///
356	/// Saturates to `Self::min` or `Self::max` (truncated) if the result does not fit.
357	#[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
370/// Data type used as intermediate storage in some computations to avoid overflow.
371struct 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
390/// Transforms an `I129` to `N` if it is possible.
391fn 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
402/// Returns `R::max` if the sign of `n * m` is positive, `R::min` otherwise.
403fn 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		/// A fixed point number representation in the range.
421		#[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			/// Create a new instance from the given `inner` value.
472			///
473			/// `const` version of `FixedPointNumber::from_inner`.
474			pub const fn from_inner(inner: $inner_type) -> Self {
475				Self(inner)
476			}
477
478			/// Return the instance's inner value.
479			///
480			/// `const` version of `FixedPointNumber::into_inner`.
481			pub const fn into_inner(self) -> $inner_type {
482				self.0
483			}
484
485			/// Creates self from a `u32`.
486			///
487			/// WARNING: This is a `const` function designed for convenient use at build time and
488			/// will panic on overflow. Ensure that any inputs are sensible.
489			pub const fn from_u32(n: u32) -> Self {
490				Self::from_inner((n as $inner_type) * $div)
491			}
492
493			/// Convert from a `float` value.
494			#[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			/// Convert from a `Perbill` value.
500			pub const fn from_perbill(n: Perbill) -> Self {
501				Self::from_rational(n.deconstruct() as u128, 1_000_000_000)
502			}
503
504			/// Convert into a `Perbill` value. Will saturate if above one or below zero.
505			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			/// Convert into a `float` value.
533			#[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			/// Attempt to convert into a `PerThing`. This will succeed iff `self` is at least zero
539			/// and at most one. If it is out of bounds, it will result in an error returning the
540			/// clamped value.
541			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			/// Attempt to convert into a `PerThing`. This will always succeed resulting in a
552			/// clamped value if `self` is less than zero or greater than one.
553			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			/// Negate the value.
564			///
565			/// WARNING: This is a `const` function designed for convenient use at build time and
566			/// will panic on overflow. Ensure that any inputs are sensible.
567			pub const fn neg(self) -> Self {
568				Self(0 - self.0)
569			}
570
571			/// Take the square root of a positive value.
572			///
573			/// WARNING: This is a `const` function designed for convenient use at build time and
574			/// will panic on overflow. Ensure that any inputs are sensible.
575			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			/// Compute the square root. If it overflows or is negative, then `None` is returned.
583			pub const fn checked_sqrt(self) -> Option<Self> {
584				if self.0 == 0 {
585					return Some(Self(0));
586				}
587				if self.0 < 1 {
588					return None;
589				}
590				let v = self.0 as u128;
591
592				// Want x' = sqrt(x) where x = n/D and x' = n'/D (D is fixed)
593				// Our preferred way is:
594				//   sqrt(n/D) = sqrt(nD / D^2) = sqrt(nD)/sqrt(D^2) = sqrt(nD)/D
595				//   ergo n' = sqrt(nD)
596				// but this requires nD to fit into our type.
597				// if nD doesn't fit then we can fall back on:
598				//   sqrt(nD) = sqrt(n)*sqrt(D)
599				// computing them individually and taking the product at the end. we will lose some
600				// precision though.
601				let maybe_vd = u128::checked_mul(v, $div);
602				let r = if let Some(vd) = maybe_vd { sqrt(vd) } else { sqrt(v) * sqrt($div) };
603				Some(Self(r as $inner_type))
604			}
605
606			/// Add a value and return the result.
607			///
608			/// WARNING: This is a `const` function designed for convenient use at build time and
609			/// will panic on overflow. Ensure that any inputs are sensible.
610			pub const fn add(self, rhs: Self) -> Self {
611				Self(self.0 + rhs.0)
612			}
613
614			/// Subtract a value and return the result.
615			///
616			/// WARNING: This is a `const` function designed for convenient use at build time and
617			/// will panic on overflow. Ensure that any inputs are sensible.
618			pub const fn sub(self, rhs: Self) -> Self {
619				Self(self.0 - rhs.0)
620			}
621
622			/// Multiply by a value and return the result.
623			///
624			/// Result will be rounded to the nearest representable value, rounding down if it is
625			/// equidistant between two neighbours.
626			///
627			/// WARNING: This is a `const` function designed for convenient use at build time and
628			/// will panic on overflow. Ensure that any inputs are sensible.
629			pub const fn mul(self, rhs: Self) -> Self {
630				match $name::const_checked_mul(self, rhs) {
631					Some(v) => v,
632					None => panic!("attempt to multiply with overflow"),
633				}
634			}
635
636			/// Divide by a value and return the result.
637			///
638			/// Result will be rounded to the nearest representable value, rounding down if it is
639			/// equidistant between two neighbours.
640			///
641			/// WARNING: This is a `const` function designed for convenient use at build time and
642			/// will panic on overflow. Ensure that any inputs are sensible.
643			pub const fn div(self, rhs: Self) -> Self {
644				match $name::const_checked_div(self, rhs) {
645					Some(v) => v,
646					None => panic!("attempt to divide with overflow or NaN"),
647				}
648			}
649
650			/// Convert into an `I129` format value.
651			///
652			/// WARNING: This is a `const` function designed for convenient use at build time and
653			/// will panic on overflow. Ensure that any inputs are sensible.
654			const fn into_i129(self) -> I129 {
655				#[allow(unused_comparisons)]
656				if self.0 < 0 {
657					let value = match self.0.checked_neg() {
658						Some(n) => n as u128,
659						None => u128::saturating_add(<$inner_type>::max_value() as u128, 1),
660					};
661					I129 { value, negative: true }
662				} else {
663					I129 { value: self.0 as u128, negative: false }
664				}
665			}
666
667			/// Convert from an `I129` format value.
668			///
669			/// WARNING: This is a `const` function designed for convenient use at build time and
670			/// will panic on overflow. Ensure that any inputs are sensible.
671			const fn from_i129(n: I129) -> Option<Self> {
672				let max_plus_one = u128::saturating_add(<$inner_type>::max_value() as u128, 1);
673				#[allow(unused_comparisons)]
674				let inner = if n.negative && <$inner_type>::min_value() < 0 && n.value == max_plus_one {
675					<$inner_type>::min_value()
676				} else {
677					let unsigned_inner = n.value as $inner_type;
678					if unsigned_inner as u128 != n.value || (unsigned_inner > 0) != (n.value > 0) {
679						return None;
680					};
681					if n.negative {
682						match unsigned_inner.checked_neg() {
683							Some(v) => v,
684							None => return None,
685						}
686					} else {
687						unsigned_inner
688					}
689				};
690				Some(Self(inner))
691			}
692
693			/// Calculate an approximation of a rational.
694			///
695			/// Result will be rounded to the nearest representable value, rounding down if it is
696			/// equidistant between two neighbours.
697			///
698			/// WARNING: This is a `const` function designed for convenient use at build time and
699			/// will panic on overflow. Ensure that any inputs are sensible.
700			pub const fn from_rational(a: u128, b: u128) -> Self {
701				Self::from_rational_with_rounding(a, b, Rounding::NearestPrefDown)
702			}
703
704			/// Calculate an approximation of a rational with custom rounding.
705			///
706			/// WARNING: This is a `const` function designed for convenient use at build time and
707			/// will panic on overflow. Ensure that any inputs are sensible.
708			pub const fn from_rational_with_rounding(a: u128, b: u128, rounding: Rounding) -> Self {
709				if b == 0 {
710					panic!("attempt to divide by zero in from_rational")
711				}
712				match multiply_by_rational_with_rounding(Self::DIV as u128, a, b, rounding) {
713					Some(value) => match Self::from_i129(I129 { value, negative: false }) {
714						Some(x) => x,
715						None => panic!("overflow in from_rational"),
716					},
717					None => panic!("overflow in from_rational"),
718				}
719			}
720
721			/// Multiply by another value, returning `None` in the case of an error.
722			///
723			/// Result will be rounded to the nearest representable value, rounding down if it is
724			/// equidistant between two neighbours.
725			pub const fn const_checked_mul(self, other: Self) -> Option<Self> {
726				self.const_checked_mul_with_rounding(other, SignedRounding::NearestPrefLow)
727			}
728
729			/// Multiply by another value with custom rounding, returning `None` in the case of an
730			/// error.
731			///
732			/// Result will be rounded to the nearest representable value, rounding down if it is
733			/// equidistant between two neighbours.
734			pub const fn const_checked_mul_with_rounding(
735				self,
736				other: Self,
737				rounding: SignedRounding,
738			) -> Option<Self> {
739				let lhs = self.into_i129();
740				let rhs = other.into_i129();
741				let negative = lhs.negative != rhs.negative;
742
743				match multiply_by_rational_with_rounding(
744					lhs.value,
745					rhs.value,
746					Self::DIV as u128,
747					Rounding::from_signed(rounding, negative),
748				) {
749					Some(value) => Self::from_i129(I129 { value, negative }),
750					None => None,
751				}
752			}
753
754			/// Divide by another value, returning `None` in the case of an error.
755			///
756			/// Result will be rounded to the nearest representable value, rounding down if it is
757			/// equidistant between two neighbours.
758			pub const fn const_checked_div(self, other: Self) -> Option<Self> {
759				self.checked_rounding_div(other, SignedRounding::NearestPrefLow)
760			}
761
762			/// Divide by another value with custom rounding, returning `None` in the case of an
763			/// error.
764			///
765			/// Result will be rounded to the nearest representable value, rounding down if it is
766			/// equidistant between two neighbours.
767			pub const fn checked_rounding_div(
768				self,
769				other: Self,
770				rounding: SignedRounding,
771			) -> Option<Self> {
772				if other.0 == 0 {
773					return None;
774				}
775
776				let lhs = self.into_i129();
777				let rhs = other.into_i129();
778				let negative = lhs.negative != rhs.negative;
779
780				match multiply_by_rational_with_rounding(
781					lhs.value,
782					Self::DIV as u128,
783					rhs.value,
784					Rounding::from_signed(rounding, negative),
785				) {
786					Some(value) => Self::from_i129(I129 { value, negative }),
787					None => None,
788				}
789			}
790		}
791
792		impl Saturating for $name {
793			fn saturating_add(self, rhs: Self) -> Self {
794				Self(self.0.saturating_add(rhs.0))
795			}
796
797			fn saturating_sub(self, rhs: Self) -> Self {
798				Self(self.0.saturating_sub(rhs.0))
799			}
800
801			fn saturating_mul(self, rhs: Self) -> Self {
802				self.checked_mul(&rhs).unwrap_or_else(|| to_bound(self.0, rhs.0))
803			}
804
805			fn saturating_pow(self, exp: usize) -> Self {
806				if exp == 0 {
807					return Self::saturating_from_integer(1);
808				}
809
810				let exp = exp as u32;
811				let msb_pos = 32 - exp.leading_zeros();
812
813				let mut result = Self::saturating_from_integer(1);
814				let mut pow_val = self;
815				for i in 0..msb_pos {
816					if ((1 << i) & exp) > 0 {
817						result = result.saturating_mul(pow_val);
818					}
819					pow_val = pow_val.saturating_mul(pow_val);
820				}
821				result
822			}
823		}
824
825		impl ops::Neg for $name {
826			type Output = Self;
827
828			fn neg(self) -> Self::Output {
829				Self(<Self as FixedPointNumber>::Inner::zero() - self.0)
830			}
831		}
832
833		impl ops::Add for $name {
834			type Output = Self;
835
836			fn add(self, rhs: Self) -> Self::Output {
837				Self(self.0 + rhs.0)
838			}
839		}
840
841		impl ops::Sub for $name {
842			type Output = Self;
843
844			fn sub(self, rhs: Self) -> Self::Output {
845				Self(self.0 - rhs.0)
846			}
847		}
848
849		impl ops::Mul for $name {
850			type Output = Self;
851
852			fn mul(self, rhs: Self) -> Self::Output {
853				self.checked_mul(&rhs)
854					.unwrap_or_else(|| panic!("attempt to multiply with overflow"))
855			}
856		}
857
858		impl ops::Div for $name {
859			type Output = Self;
860
861			fn div(self, rhs: Self) -> Self::Output {
862				if rhs.0 == 0 {
863					panic!("attempt to divide by zero")
864				}
865				self.checked_div(&rhs)
866					.unwrap_or_else(|| panic!("attempt to divide with overflow"))
867			}
868		}
869
870		impl CheckedSub for $name {
871			fn checked_sub(&self, rhs: &Self) -> Option<Self> {
872				self.0.checked_sub(rhs.0).map(Self)
873			}
874		}
875
876		impl CheckedAdd for $name {
877			fn checked_add(&self, rhs: &Self) -> Option<Self> {
878				self.0.checked_add(rhs.0).map(Self)
879			}
880		}
881
882		impl CheckedDiv for $name {
883			fn checked_div(&self, other: &Self) -> Option<Self> {
884				if other.0 == 0 {
885					return None;
886				}
887
888				let lhs: I129 = self.0.into();
889				let rhs: I129 = other.0.into();
890				let negative = lhs.negative != rhs.negative;
891
892				// Note that this uses the old (well-tested) code with sign-ignorant rounding. This
893				// is equivalent to the `SignedRounding::NearestPrefMinor`. This means it is
894				// expected to give exactly the same result as `const_checked_div` when the result
895				// is positive and a result up to one epsilon greater when it is negative.
896				multiply_by_rational_with_rounding(
897					lhs.value,
898					Self::DIV as u128,
899					rhs.value,
900					Rounding::from_signed(SignedRounding::Minor, negative),
901				)
902				.and_then(|value| from_i129(I129 { value, negative }))
903				.map(Self)
904			}
905		}
906
907		impl CheckedMul for $name {
908			fn checked_mul(&self, other: &Self) -> Option<Self> {
909				let lhs: I129 = self.0.into();
910				let rhs: I129 = other.0.into();
911				let negative = lhs.negative != rhs.negative;
912
913				multiply_by_rational_with_rounding(
914					lhs.value,
915					rhs.value,
916					Self::DIV as u128,
917					Rounding::from_signed(SignedRounding::Minor, negative),
918				)
919				.and_then(|value| from_i129(I129 { value, negative }))
920				.map(Self)
921			}
922		}
923
924		impl Bounded for $name {
925			fn min_value() -> Self {
926				Self(<Self as FixedPointNumber>::Inner::min_value())
927			}
928
929			fn max_value() -> Self {
930				Self(<Self as FixedPointNumber>::Inner::max_value())
931			}
932		}
933
934		impl Zero for $name {
935			fn zero() -> Self {
936				Self::from_inner(<Self as FixedPointNumber>::Inner::zero())
937			}
938
939			fn is_zero(&self) -> bool {
940				self.into_inner() == <Self as FixedPointNumber>::Inner::zero()
941			}
942		}
943
944		impl One for $name {
945			fn one() -> Self {
946				Self::from_inner(Self::DIV)
947			}
948		}
949
950		impl ::core::fmt::Debug for $name {
951			#[cfg(feature = "std")]
952			fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
953				let integral = {
954					let int = self.0 / Self::accuracy();
955					let signum_for_zero = if int == 0 && self.is_negative() { "-" } else { "" };
956					format!("{}{}", signum_for_zero, int)
957				};
958				let precision = (Self::accuracy() as f64).log10() as usize;
959				let fractional = format!(
960					"{:0>weight$}",
961					((self.0 % Self::accuracy()) as i128).abs(),
962					weight = precision
963				);
964				write!(f, "{}({}.{})", stringify!($name), integral, fractional)
965			}
966
967			#[cfg(not(feature = "std"))]
968			fn fmt(&self, _: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
969				Ok(())
970			}
971		}
972
973		impl<P: PerThing> From<P> for $name
974		where
975			P::Inner: FixedPointOperand,
976		{
977			fn from(p: P) -> Self {
978				let accuracy = P::ACCURACY;
979				let value = p.deconstruct();
980				$name::saturating_from_rational(value, accuracy)
981			}
982		}
983
984		impl ::core::fmt::Display for $name {
985			fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
986				write!(f, "{}", self.0)
987			}
988		}
989
990		impl ::core::str::FromStr for $name {
991			type Err = &'static str;
992
993			fn from_str(s: &str) -> Result<Self, Self::Err> {
994				let s = s.trim();
995
996				// Check if the string contains a decimal point
997				if let Some(dot_pos) = s.find('.') {
998					// Parse as decimal number (e.g., "1.0", "123.456")
999					let (integer_part, fractional_part) = s.split_at(dot_pos);
1000					let fractional_part = &fractional_part[1..]; // Skip the '.'
1001
1002					// Check if it's a negative number
1003					let is_negative = integer_part.starts_with('-');
1004
1005					// For unsigned types, reject negative numbers
1006					if is_negative && !$name::SIGNED {
1007						return Err(
1008							"negative numbers not supported for unsigned fixed point types",
1009						);
1010					}
1011
1012					// Parse integer part
1013					let integer: i128 = if integer_part.is_empty() {
1014						0
1015					} else {
1016						integer_part
1017							.parse()
1018							.map_err(|_| "invalid integer part in decimal number")?
1019					};
1020
1021					// Parse fractional part
1022					let fractional_raw: u128 = if fractional_part.is_empty() {
1023						0
1024					} else {
1025						fractional_part
1026							.parse()
1027							.map_err(|_| "invalid fractional part in decimal number")?
1028					};
1029
1030					// Convert fractional part to the appropriate scale
1031					let fractional_digits = fractional_part.len() as u32;
1032
1033					// Calculate fractional value using more careful arithmetic
1034					let fractional_scaled: i128 = if fractional_digits > 0 {
1035						// Checked math to avoid overflow
1036						let Some(scale_factor) = 10u128.checked_pow(fractional_digits) else {
1037							return Err("fractional part has too many digits");
1038						};
1039
1040						// For very large DIV values, we need to be more careful
1041						let div_u128 = Self::DIV as u128;
1042
1043						// Calculate: fractional_raw * DIV / scale_factor
1044						// We do this carefully to avoid intermediate overflow
1045						// Use alternative calculation: (fractional_raw / scale_factor) * DIV
1046						let quotient = fractional_raw / scale_factor;
1047						let remainder = fractional_raw % scale_factor;
1048						quotient
1049							.checked_mul(div_u128)
1050							.and_then(|base| {
1051								let remainder_scaled = (remainder * div_u128) / scale_factor;
1052								base.checked_add(remainder_scaled)
1053							})
1054							.ok_or("fractional part overflow")?
1055							.try_into()
1056							.map_err(|_| "fractional part too large for signed representation")?
1057					} else {
1058						0
1059					};
1060
1061					// Combine integer and fractional parts using wider arithmetic
1062					let div_i128 = Self::DIV as i128;
1063					let integer_scaled =
1064						integer.checked_mul(div_i128).ok_or("integer part overflow")?;
1065
1066					let result = if is_negative {
1067						integer_scaled
1068							.checked_sub(fractional_scaled)
1069							.ok_or("number too large for fixed point representation")?
1070					} else {
1071						integer_scaled
1072							.checked_add(fractional_scaled)
1073							.ok_or("number too large for fixed point representation")?
1074					};
1075
1076					// Convert to target type
1077					let inner = <Self as FixedPointNumber>::Inner::try_from(result)
1078						.map_err(|_| "number out of range for fixed point type")?;
1079
1080					Ok(Self::from_inner(inner))
1081				} else {
1082					// Parse as raw inner value (legacy behavior)
1083					let inner: <Self as FixedPointNumber>::Inner =
1084						s.parse().map_err(|_| "invalid string input for fixed point number")?;
1085					Ok(Self::from_inner(inner))
1086				}
1087			}
1088		}
1089
1090		// Manual impl `Serialize` as serde_json does not support i128.
1091		// TODO: remove impl if issue https://github.com/serde-rs/json/issues/548 fixed.
1092		#[cfg(feature = "serde")]
1093		impl Serialize for $name {
1094			fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
1095			where
1096				S: Serializer,
1097			{
1098				serializer.serialize_str(&self.to_string())
1099			}
1100		}
1101
1102		// Manual impl `Deserialize` as serde_json does not support i128.
1103		// TODO: remove impl if issue https://github.com/serde-rs/json/issues/548 fixed.
1104		#[cfg(feature = "serde")]
1105		impl<'de> Deserialize<'de> for $name {
1106			fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
1107			where
1108				D: Deserializer<'de>,
1109			{
1110				use ::core::str::FromStr;
1111				let s = String::deserialize(deserializer)?;
1112				$name::from_str(&s).map_err(de::Error::custom)
1113			}
1114		}
1115
1116		#[cfg(test)]
1117		mod $test_mod {
1118			use super::*;
1119			use crate::{Perbill, Percent, Permill, Perquintill};
1120
1121			fn max() -> $name {
1122				$name::max_value()
1123			}
1124
1125			fn min() -> $name {
1126				$name::min_value()
1127			}
1128
1129			fn precision() -> usize {
1130				($name::accuracy() as f64).log10() as usize
1131			}
1132
1133			#[test]
1134			fn macro_preconditions() {
1135				assert!($name::DIV > 0);
1136			}
1137
1138			#[test]
1139			fn has_max_encoded_len() {
1140				struct AsMaxEncodedLen<T: codec::MaxEncodedLen> {
1141					_data: T,
1142				}
1143
1144				let _ = AsMaxEncodedLen { _data: $name::min_value() };
1145			}
1146
1147			#[test]
1148			fn from_i129_works() {
1149				let a = I129 { value: 1, negative: true };
1150
1151				// Can't convert negative number to unsigned.
1152				assert_eq!(from_i129::<u128>(a), None);
1153
1154				let a = I129 { value: u128::MAX - 1, negative: false };
1155
1156				// Max - 1 value fits.
1157				assert_eq!(from_i129::<u128>(a), Some(u128::MAX - 1));
1158
1159				let a = I129 { value: u128::MAX, negative: false };
1160
1161				// Max value fits.
1162				assert_eq!(from_i129::<u128>(a), Some(u128::MAX));
1163
1164				let a = I129 { value: i128::MAX as u128 + 1, negative: true };
1165
1166				// Min value fits.
1167				assert_eq!(from_i129::<i128>(a), Some(i128::MIN));
1168
1169				let a = I129 { value: i128::MAX as u128 + 1, negative: false };
1170
1171				// Max + 1 does not fit.
1172				assert_eq!(from_i129::<i128>(a), None);
1173
1174				let a = I129 { value: i128::MAX as u128, negative: false };
1175
1176				// Max value fits.
1177				assert_eq!(from_i129::<i128>(a), Some(i128::MAX));
1178			}
1179
1180			#[test]
1181			fn to_bound_works() {
1182				let a = 1i32;
1183				let b = 1i32;
1184
1185				// Pos + Pos => Max.
1186				assert_eq!(to_bound::<_, _, i32>(a, b), i32::MAX);
1187
1188				let a = -1i32;
1189				let b = -1i32;
1190
1191				// Neg + Neg => Max.
1192				assert_eq!(to_bound::<_, _, i32>(a, b), i32::MAX);
1193
1194				let a = 1i32;
1195				let b = -1i32;
1196
1197				// Pos + Neg => Min.
1198				assert_eq!(to_bound::<_, _, i32>(a, b), i32::MIN);
1199
1200				let a = -1i32;
1201				let b = 1i32;
1202
1203				// Neg + Pos => Min.
1204				assert_eq!(to_bound::<_, _, i32>(a, b), i32::MIN);
1205
1206				let a = 1i32;
1207				let b = -1i32;
1208
1209				// Pos + Neg => Min (unsigned).
1210				assert_eq!(to_bound::<_, _, u32>(a, b), 0);
1211			}
1212
1213			#[test]
1214			fn op_neg_works() {
1215				let a = $name::zero();
1216				let b = -a;
1217
1218				// Zero.
1219				assert_eq!(a, b);
1220
1221				if $name::SIGNED {
1222					let a = $name::saturating_from_integer(5);
1223					let b = -a;
1224
1225					// Positive.
1226					assert_eq!($name::saturating_from_integer(-5), b);
1227
1228					let a = $name::saturating_from_integer(-5);
1229					let b = -a;
1230
1231					// Negative
1232					assert_eq!($name::saturating_from_integer(5), b);
1233
1234					let a = $name::max_value();
1235					let b = -a;
1236
1237					// Max.
1238					assert_eq!($name::min_value() + $name::from_inner(1), b);
1239
1240					let a = $name::min_value() + $name::from_inner(1);
1241					let b = -a;
1242
1243					// Min.
1244					assert_eq!($name::max_value(), b);
1245				}
1246			}
1247
1248			#[test]
1249			fn op_checked_add_overflow_works() {
1250				let a = $name::max_value();
1251				let b = 1.into();
1252				assert!(a.checked_add(&b).is_none());
1253			}
1254
1255			#[test]
1256			fn op_add_works() {
1257				let a = $name::saturating_from_rational(5, 2);
1258				let b = $name::saturating_from_rational(1, 2);
1259
1260				// Positive case: 6/2 = 3.
1261				assert_eq!($name::saturating_from_integer(3), a + b);
1262
1263				if $name::SIGNED {
1264					// Negative case: 4/2 = 2.
1265					let b = $name::saturating_from_rational(1, -2);
1266					assert_eq!($name::saturating_from_integer(2), a + b);
1267				}
1268			}
1269
1270			#[test]
1271			fn op_checked_sub_underflow_works() {
1272				let a = $name::min_value();
1273				let b = 1.into();
1274				assert!(a.checked_sub(&b).is_none());
1275			}
1276
1277			#[test]
1278			fn op_sub_works() {
1279				let a = $name::saturating_from_rational(5, 2);
1280				let b = $name::saturating_from_rational(1, 2);
1281
1282				assert_eq!($name::saturating_from_integer(2), a - b);
1283				assert_eq!($name::saturating_from_integer(-2), b.saturating_sub(a));
1284			}
1285
1286			#[test]
1287			fn op_checked_mul_overflow_works() {
1288				let a = $name::max_value();
1289				let b = 2.into();
1290				assert!(a.checked_mul(&b).is_none());
1291			}
1292
1293			#[test]
1294			fn op_mul_works() {
1295				let a = $name::saturating_from_integer(42);
1296				let b = $name::saturating_from_integer(2);
1297				assert_eq!($name::saturating_from_integer(84), a * b);
1298
1299				let a = $name::saturating_from_integer(42);
1300				let b = $name::saturating_from_integer(-2);
1301				assert_eq!($name::saturating_from_integer(-84), a * b);
1302			}
1303
1304			#[test]
1305			#[should_panic(expected = "attempt to divide by zero")]
1306			fn op_div_panics_on_zero_divisor() {
1307				let a = $name::saturating_from_integer(1);
1308				let b = 0.into();
1309				let _c = a / b;
1310			}
1311
1312			#[test]
1313			fn op_checked_div_overflow_works() {
1314				if $name::SIGNED {
1315					let a = $name::min_value();
1316					let b = $name::zero().saturating_sub($name::one());
1317					assert!(a.checked_div(&b).is_none());
1318				}
1319			}
1320
1321			#[test]
1322			fn op_sqrt_works() {
1323				for i in 1..1_000i64 {
1324					let x = $name::saturating_from_rational(i, 1_000i64);
1325					assert_eq!((x * x).checked_sqrt(), Some(x));
1326					let x = $name::saturating_from_rational(i, 1i64);
1327					assert_eq!((x * x).checked_sqrt(), Some(x));
1328				}
1329			}
1330
1331			#[test]
1332			fn op_div_works() {
1333				let a = $name::saturating_from_integer(42);
1334				let b = $name::saturating_from_integer(2);
1335				assert_eq!($name::saturating_from_integer(21), a / b);
1336
1337				if $name::SIGNED {
1338					let a = $name::saturating_from_integer(42);
1339					let b = $name::saturating_from_integer(-2);
1340					assert_eq!($name::saturating_from_integer(-21), a / b);
1341				}
1342			}
1343
1344			#[test]
1345			fn saturating_from_integer_works() {
1346				let inner_max = <$name as FixedPointNumber>::Inner::max_value();
1347				let inner_min = <$name as FixedPointNumber>::Inner::min_value();
1348				let accuracy = $name::accuracy();
1349
1350				// Cases where integer fits.
1351				let a = $name::saturating_from_integer(42);
1352				assert_eq!(a.into_inner(), 42 * accuracy);
1353
1354				let a = $name::saturating_from_integer(-42);
1355				assert_eq!(a.into_inner(), 0.saturating_sub(42 * accuracy));
1356
1357				// Max/min integers that fit.
1358				let a = $name::saturating_from_integer(inner_max / accuracy);
1359				assert_eq!(a.into_inner(), (inner_max / accuracy) * accuracy);
1360
1361				let a = $name::saturating_from_integer(inner_min / accuracy);
1362				assert_eq!(a.into_inner(), (inner_min / accuracy) * accuracy);
1363
1364				// Cases where integer doesn't fit, so it saturates.
1365				let a = $name::saturating_from_integer(inner_max / accuracy + 1);
1366				assert_eq!(a.into_inner(), inner_max);
1367
1368				let a = $name::saturating_from_integer((inner_min / accuracy).saturating_sub(1));
1369				assert_eq!(a.into_inner(), inner_min);
1370			}
1371
1372			#[test]
1373			fn checked_from_integer_works() {
1374				let inner_max = <$name as FixedPointNumber>::Inner::max_value();
1375				let inner_min = <$name as FixedPointNumber>::Inner::min_value();
1376				let accuracy = $name::accuracy();
1377
1378				// Case where integer fits.
1379				let a = $name::checked_from_integer::<$inner_type>(42)
1380					.expect("42 * accuracy <= inner_max; qed");
1381				assert_eq!(a.into_inner(), 42 * accuracy);
1382
1383				// Max integer that fit.
1384				let a = $name::checked_from_integer::<$inner_type>(inner_max / accuracy)
1385					.expect("(inner_max / accuracy) * accuracy <= inner_max; qed");
1386				assert_eq!(a.into_inner(), (inner_max / accuracy) * accuracy);
1387
1388				// Case where integer doesn't fit, so it returns `None`.
1389				let a = $name::checked_from_integer::<$inner_type>(inner_max / accuracy + 1);
1390				assert_eq!(a, None);
1391
1392				if $name::SIGNED {
1393					// Case where integer fits.
1394					let a = $name::checked_from_integer::<$inner_type>(0.saturating_sub(42))
1395						.expect("-42 * accuracy >= inner_min; qed");
1396					assert_eq!(a.into_inner(), 0 - 42 * accuracy);
1397
1398					// Min integer that fit.
1399					let a = $name::checked_from_integer::<$inner_type>(inner_min / accuracy)
1400						.expect("(inner_min / accuracy) * accuracy <= inner_min; qed");
1401					assert_eq!(a.into_inner(), (inner_min / accuracy) * accuracy);
1402
1403					// Case where integer doesn't fit, so it returns `None`.
1404					let a = $name::checked_from_integer::<$inner_type>(inner_min / accuracy - 1);
1405					assert_eq!(a, None);
1406				}
1407			}
1408
1409			#[test]
1410			fn from_inner_works() {
1411				let inner_max = <$name as FixedPointNumber>::Inner::max_value();
1412				let inner_min = <$name as FixedPointNumber>::Inner::min_value();
1413
1414				assert_eq!(max(), $name::from_inner(inner_max));
1415				assert_eq!(min(), $name::from_inner(inner_min));
1416			}
1417
1418			#[test]
1419			#[should_panic(expected = "attempt to divide by zero")]
1420			fn saturating_from_rational_panics_on_zero_divisor() {
1421				let _ = $name::saturating_from_rational(1, 0);
1422			}
1423
1424			#[test]
1425			fn saturating_from_rational_works() {
1426				let inner_max = <$name as FixedPointNumber>::Inner::max_value();
1427				let inner_min = <$name as FixedPointNumber>::Inner::min_value();
1428				let accuracy = $name::accuracy();
1429
1430				let a = $name::saturating_from_rational(5, 2);
1431
1432				// Positive case: 2.5
1433				assert_eq!(a.into_inner(), 25 * accuracy / 10);
1434
1435				// Max - 1.
1436				let a = $name::saturating_from_rational(inner_max - 1, accuracy);
1437				assert_eq!(a.into_inner(), inner_max - 1);
1438
1439				// Min + 1.
1440				let a = $name::saturating_from_rational(inner_min + 1, accuracy);
1441				assert_eq!(a.into_inner(), inner_min + 1);
1442
1443				// Max.
1444				let a = $name::saturating_from_rational(inner_max, accuracy);
1445				assert_eq!(a.into_inner(), inner_max);
1446
1447				// Min.
1448				let a = $name::saturating_from_rational(inner_min, accuracy);
1449				assert_eq!(a.into_inner(), inner_min);
1450
1451				// Zero.
1452				let a = $name::saturating_from_rational(0, 1);
1453				assert_eq!(a.into_inner(), 0);
1454
1455				if $name::SIGNED {
1456					// Negative case: -2.5
1457					let a = $name::saturating_from_rational(-5, 2);
1458					assert_eq!(a.into_inner(), 0 - 25 * accuracy / 10);
1459
1460					// Other negative case: -2.5
1461					let a = $name::saturating_from_rational(5, -2);
1462					assert_eq!(a.into_inner(), 0 - 25 * accuracy / 10);
1463
1464					// Other positive case: 2.5
1465					let a = $name::saturating_from_rational(-5, -2);
1466					assert_eq!(a.into_inner(), 25 * accuracy / 10);
1467
1468					// Max + 1, saturates.
1469					let a = $name::saturating_from_rational(inner_max as u128 + 1, accuracy);
1470					assert_eq!(a.into_inner(), inner_max);
1471
1472					// Min - 1, saturates.
1473					let a = $name::saturating_from_rational(inner_max as u128 + 2, 0 - accuracy);
1474					assert_eq!(a.into_inner(), inner_min);
1475
1476					let a = $name::saturating_from_rational(inner_max, 0 - accuracy);
1477					assert_eq!(a.into_inner(), 0 - inner_max);
1478
1479					let a = $name::saturating_from_rational(inner_min, 0 - accuracy);
1480					assert_eq!(a.into_inner(), inner_max);
1481
1482					let a = $name::saturating_from_rational(inner_min + 1, 0 - accuracy);
1483					assert_eq!(a.into_inner(), inner_max);
1484
1485					let a = $name::saturating_from_rational(inner_min, 0 - 1);
1486					assert_eq!(a.into_inner(), inner_max);
1487
1488					let a = $name::saturating_from_rational(inner_max, 0 - 1);
1489					assert_eq!(a.into_inner(), inner_min);
1490
1491					let a = $name::saturating_from_rational(inner_max, 0 - inner_max);
1492					assert_eq!(a.into_inner(), 0 - accuracy);
1493
1494					let a = $name::saturating_from_rational(0 - inner_max, inner_max);
1495					assert_eq!(a.into_inner(), 0 - accuracy);
1496
1497					let a = $name::saturating_from_rational(inner_max, 0 - 3 * accuracy);
1498					assert_eq!(a.into_inner(), 0 - inner_max / 3);
1499
1500					let a = $name::saturating_from_rational(inner_min, 0 - accuracy / 3);
1501					assert_eq!(a.into_inner(), inner_max);
1502
1503					let a = $name::saturating_from_rational(1, 0 - accuracy);
1504					assert_eq!(a.into_inner(), 0.saturating_sub(1));
1505
1506					let a = $name::saturating_from_rational(inner_min, inner_min);
1507					assert_eq!(a.into_inner(), accuracy);
1508
1509					// Out of accuracy.
1510					let a = $name::saturating_from_rational(1, 0 - accuracy - 1);
1511					assert_eq!(a.into_inner(), 0);
1512				}
1513
1514				let a = $name::saturating_from_rational(inner_max - 1, accuracy);
1515				assert_eq!(a.into_inner(), inner_max - 1);
1516
1517				let a = $name::saturating_from_rational(inner_min + 1, accuracy);
1518				assert_eq!(a.into_inner(), inner_min + 1);
1519
1520				let a = $name::saturating_from_rational(inner_max, 1);
1521				assert_eq!(a.into_inner(), inner_max);
1522
1523				let a = $name::saturating_from_rational(inner_min, 1);
1524				assert_eq!(a.into_inner(), inner_min);
1525
1526				let a = $name::saturating_from_rational(inner_max, inner_max);
1527				assert_eq!(a.into_inner(), accuracy);
1528
1529				let a = $name::saturating_from_rational(inner_max, 3 * accuracy);
1530				assert_eq!(a.into_inner(), inner_max / 3);
1531
1532				let a = $name::saturating_from_rational(inner_min, 2 * accuracy);
1533				assert_eq!(a.into_inner(), inner_min / 2);
1534
1535				let a = $name::saturating_from_rational(inner_min, accuracy / 3);
1536				assert_eq!(a.into_inner(), inner_min);
1537
1538				let a = $name::saturating_from_rational(1, accuracy);
1539				assert_eq!(a.into_inner(), 1);
1540
1541				// Out of accuracy.
1542				let a = $name::saturating_from_rational(1, accuracy + 1);
1543				assert_eq!(a.into_inner(), 0);
1544			}
1545
1546			#[test]
1547			fn checked_from_rational_works() {
1548				let inner_max = <$name as FixedPointNumber>::Inner::max_value();
1549				let inner_min = <$name as FixedPointNumber>::Inner::min_value();
1550				let accuracy = $name::accuracy();
1551
1552				// Divide by zero => None.
1553				let a = $name::checked_from_rational(1, 0);
1554				assert_eq!(a, None);
1555
1556				// Max - 1.
1557				let a = $name::checked_from_rational(inner_max - 1, accuracy).unwrap();
1558				assert_eq!(a.into_inner(), inner_max - 1);
1559
1560				// Min + 1.
1561				let a = $name::checked_from_rational(inner_min + 1, accuracy).unwrap();
1562				assert_eq!(a.into_inner(), inner_min + 1);
1563
1564				// Max.
1565				let a = $name::checked_from_rational(inner_max, accuracy).unwrap();
1566				assert_eq!(a.into_inner(), inner_max);
1567
1568				// Min.
1569				let a = $name::checked_from_rational(inner_min, accuracy).unwrap();
1570				assert_eq!(a.into_inner(), inner_min);
1571
1572				// Max + 1 => Overflow => None.
1573				let a = $name::checked_from_rational(inner_min, 0.saturating_sub(accuracy));
1574				assert_eq!(a, None);
1575
1576				if $name::SIGNED {
1577					// Min - 1 => Underflow => None.
1578					let a = $name::checked_from_rational(
1579						inner_max as u128 + 2,
1580						0.saturating_sub(accuracy),
1581					);
1582					assert_eq!(a, None);
1583
1584					let a = $name::checked_from_rational(inner_max, 0 - 3 * accuracy).unwrap();
1585					assert_eq!(a.into_inner(), 0 - inner_max / 3);
1586
1587					let a = $name::checked_from_rational(inner_min, 0 - accuracy / 3);
1588					assert_eq!(a, None);
1589
1590					let a = $name::checked_from_rational(1, 0 - accuracy).unwrap();
1591					assert_eq!(a.into_inner(), 0.saturating_sub(1));
1592
1593					let a = $name::checked_from_rational(1, 0 - accuracy - 1).unwrap();
1594					assert_eq!(a.into_inner(), 0);
1595
1596					let a = $name::checked_from_rational(inner_min, accuracy / 3);
1597					assert_eq!(a, None);
1598				}
1599
1600				let a = $name::checked_from_rational(inner_max, 3 * accuracy).unwrap();
1601				assert_eq!(a.into_inner(), inner_max / 3);
1602
1603				let a = $name::checked_from_rational(inner_min, 2 * accuracy).unwrap();
1604				assert_eq!(a.into_inner(), inner_min / 2);
1605
1606				let a = $name::checked_from_rational(1, accuracy).unwrap();
1607				assert_eq!(a.into_inner(), 1);
1608
1609				let a = $name::checked_from_rational(1, accuracy + 1).unwrap();
1610				assert_eq!(a.into_inner(), 0);
1611			}
1612
1613			#[test]
1614			fn from_rational_works() {
1615				let inner_max: u128 = <$name as FixedPointNumber>::Inner::max_value() as u128;
1616				let inner_min: u128 = 0;
1617				let accuracy: u128 = $name::accuracy() as u128;
1618
1619				// Max - 1.
1620				let a = $name::from_rational(inner_max - 1, accuracy);
1621				assert_eq!(a.into_inner() as u128, inner_max - 1);
1622
1623				// Min + 1.
1624				let a = $name::from_rational(inner_min + 1, accuracy);
1625				assert_eq!(a.into_inner() as u128, inner_min + 1);
1626
1627				// Max.
1628				let a = $name::from_rational(inner_max, accuracy);
1629				assert_eq!(a.into_inner() as u128, inner_max);
1630
1631				// Min.
1632				let a = $name::from_rational(inner_min, accuracy);
1633				assert_eq!(a.into_inner() as u128, inner_min);
1634
1635				let a = $name::from_rational(inner_max, 3 * accuracy);
1636				assert_eq!(a.into_inner() as u128, inner_max / 3);
1637
1638				let a = $name::from_rational(1, accuracy);
1639				assert_eq!(a.into_inner() as u128, 1);
1640
1641				let a = $name::from_rational(1, accuracy + 1);
1642				assert_eq!(a.into_inner() as u128, 1);
1643
1644				let a = $name::from_rational_with_rounding(1, accuracy + 1, Rounding::Down);
1645				assert_eq!(a.into_inner() as u128, 0);
1646			}
1647
1648			#[test]
1649			fn checked_mul_int_works() {
1650				let a = $name::saturating_from_integer(2);
1651				// Max - 1.
1652				assert_eq!(a.checked_mul_int((i128::MAX - 1) / 2), Some(i128::MAX - 1));
1653				// Max.
1654				assert_eq!(a.checked_mul_int(i128::MAX / 2), Some(i128::MAX - 1));
1655				// Max + 1 => None.
1656				assert_eq!(a.checked_mul_int(i128::MAX / 2 + 1), None);
1657
1658				if $name::SIGNED {
1659					// Min - 1.
1660					assert_eq!(a.checked_mul_int((i128::MIN + 1) / 2), Some(i128::MIN + 2));
1661					// Min.
1662					assert_eq!(a.checked_mul_int(i128::MIN / 2), Some(i128::MIN));
1663					// Min + 1 => None.
1664					assert_eq!(a.checked_mul_int(i128::MIN / 2 - 1), None);
1665
1666					let b = $name::saturating_from_rational(1, -2);
1667					assert_eq!(b.checked_mul_int(42i128), Some(-21));
1668					assert_eq!(b.checked_mul_int(u128::MAX), None);
1669					assert_eq!(b.checked_mul_int(i128::MAX), Some(i128::MAX / -2));
1670					assert_eq!(b.checked_mul_int(i128::MIN), Some(i128::MIN / -2));
1671				}
1672
1673				let a = $name::saturating_from_rational(1, 2);
1674				assert_eq!(a.checked_mul_int(42i128), Some(21));
1675				assert_eq!(a.checked_mul_int(i128::MAX), Some(i128::MAX / 2));
1676				assert_eq!(a.checked_mul_int(i128::MIN), Some(i128::MIN / 2));
1677
1678				let c = $name::saturating_from_integer(255);
1679				assert_eq!(c.checked_mul_int(2i8), None);
1680				assert_eq!(c.checked_mul_int(2i128), Some(510));
1681				assert_eq!(c.checked_mul_int(i128::MAX), None);
1682				assert_eq!(c.checked_mul_int(i128::MIN), None);
1683			}
1684
1685			#[test]
1686			fn saturating_mul_int_works() {
1687				let a = $name::saturating_from_integer(2);
1688				// Max - 1.
1689				assert_eq!(a.saturating_mul_int((i128::MAX - 1) / 2), i128::MAX - 1);
1690				// Max.
1691				assert_eq!(a.saturating_mul_int(i128::MAX / 2), i128::MAX - 1);
1692				// Max + 1 => saturates to max.
1693				assert_eq!(a.saturating_mul_int(i128::MAX / 2 + 1), i128::MAX);
1694
1695				// Min - 1.
1696				assert_eq!(a.saturating_mul_int((i128::MIN + 1) / 2), i128::MIN + 2);
1697				// Min.
1698				assert_eq!(a.saturating_mul_int(i128::MIN / 2), i128::MIN);
1699				// Min + 1 => saturates to min.
1700				assert_eq!(a.saturating_mul_int(i128::MIN / 2 - 1), i128::MIN);
1701
1702				if $name::SIGNED {
1703					let b = $name::saturating_from_rational(1, -2);
1704					assert_eq!(b.saturating_mul_int(42i32), -21);
1705					assert_eq!(b.saturating_mul_int(i128::MAX), i128::MAX / -2);
1706					assert_eq!(b.saturating_mul_int(i128::MIN), i128::MIN / -2);
1707					assert_eq!(b.saturating_mul_int(u128::MAX), u128::MIN);
1708				}
1709
1710				let a = $name::saturating_from_rational(1, 2);
1711				assert_eq!(a.saturating_mul_int(42i32), 21);
1712				assert_eq!(a.saturating_mul_int(i128::MAX), i128::MAX / 2);
1713				assert_eq!(a.saturating_mul_int(i128::MIN), i128::MIN / 2);
1714
1715				let c = $name::saturating_from_integer(255);
1716				assert_eq!(c.saturating_mul_int(2i8), i8::MAX);
1717				assert_eq!(c.saturating_mul_int(-2i8), i8::MIN);
1718				assert_eq!(c.saturating_mul_int(i128::MAX), i128::MAX);
1719				assert_eq!(c.saturating_mul_int(i128::MIN), i128::MIN);
1720			}
1721
1722			#[test]
1723			fn checked_mul_works() {
1724				let inner_max = <$name as FixedPointNumber>::Inner::max_value();
1725				let inner_min = <$name as FixedPointNumber>::Inner::min_value();
1726
1727				let a = $name::saturating_from_integer(2);
1728
1729				// Max - 1.
1730				let b = $name::from_inner(inner_max - 1);
1731				assert_eq!(a.checked_mul(&(b / 2.into())), Some(b));
1732
1733				// Max.
1734				let c = $name::from_inner(inner_max);
1735				assert_eq!(a.checked_mul(&(c / 2.into())), Some(b));
1736
1737				// Max + 1 => None.
1738				let e = $name::from_inner(1);
1739				assert_eq!(a.checked_mul(&(c / 2.into() + e)), None);
1740
1741				if $name::SIGNED {
1742					// Min + 1.
1743					let b = $name::from_inner(inner_min + 1) / 2.into();
1744					let c = $name::from_inner(inner_min + 2);
1745					assert_eq!(a.checked_mul(&b), Some(c));
1746
1747					// Min.
1748					let b = $name::from_inner(inner_min) / 2.into();
1749					let c = $name::from_inner(inner_min);
1750					assert_eq!(a.checked_mul(&b), Some(c));
1751
1752					// Min - 1 => None.
1753					let b = $name::from_inner(inner_min) / 2.into() - $name::from_inner(1);
1754					assert_eq!(a.checked_mul(&b), None);
1755
1756					let c = $name::saturating_from_integer(255);
1757					let b = $name::saturating_from_rational(1, -2);
1758
1759					assert_eq!(b.checked_mul(&42.into()), Some(0.saturating_sub(21).into()));
1760					assert_eq!(
1761						b.checked_mul(&$name::max_value()),
1762						$name::max_value().checked_div(&0.saturating_sub(2).into())
1763					);
1764					assert_eq!(
1765						b.checked_mul(&$name::min_value()),
1766						$name::min_value().checked_div(&0.saturating_sub(2).into())
1767					);
1768					assert_eq!(c.checked_mul(&$name::min_value()), None);
1769				}
1770
1771				let a = $name::saturating_from_rational(1, 2);
1772				let c = $name::saturating_from_integer(255);
1773
1774				assert_eq!(a.checked_mul(&42.into()), Some(21.into()));
1775				assert_eq!(c.checked_mul(&2.into()), Some(510.into()));
1776				assert_eq!(c.checked_mul(&$name::max_value()), None);
1777				assert_eq!(
1778					a.checked_mul(&$name::max_value()),
1779					$name::max_value().checked_div(&2.into())
1780				);
1781				assert_eq!(
1782					a.checked_mul(&$name::min_value()),
1783					$name::min_value().checked_div(&2.into())
1784				);
1785			}
1786
1787			#[test]
1788			fn const_checked_mul_works() {
1789				let inner_max = <$name as FixedPointNumber>::Inner::max_value();
1790				let inner_min = <$name as FixedPointNumber>::Inner::min_value();
1791
1792				let a = $name::saturating_from_integer(2u32);
1793
1794				// Max - 1.
1795				let b = $name::from_inner(inner_max - 1);
1796				assert_eq!(a.const_checked_mul(b / 2.into()), Some(b));
1797
1798				// Max.
1799				let c = $name::from_inner(inner_max);
1800				assert_eq!(a.const_checked_mul(c / 2.into()), Some(b));
1801
1802				// Max + 1 => None.
1803				let e = $name::from_inner(1);
1804				assert_eq!(a.const_checked_mul(c / 2.into() + e), None);
1805
1806				if $name::SIGNED {
1807					// Min + 1.
1808					let b = $name::from_inner(inner_min + 1) / 2.into();
1809					let c = $name::from_inner(inner_min + 2);
1810					assert_eq!(a.const_checked_mul(b), Some(c));
1811
1812					// Min.
1813					let b = $name::from_inner(inner_min) / 2.into();
1814					let c = $name::from_inner(inner_min);
1815					assert_eq!(a.const_checked_mul(b), Some(c));
1816
1817					// Min - 1 => None.
1818					let b = $name::from_inner(inner_min) / 2.into() - $name::from_inner(1);
1819					assert_eq!(a.const_checked_mul(b), None);
1820
1821					let b = $name::saturating_from_rational(1i32, -2i32);
1822					let c = $name::saturating_from_integer(-21i32);
1823					let d = $name::saturating_from_integer(42);
1824
1825					assert_eq!(b.const_checked_mul(d), Some(c));
1826
1827					let minus_two = $name::saturating_from_integer(-2i32);
1828					assert_eq!(
1829						b.const_checked_mul($name::max_value()),
1830						$name::max_value().const_checked_div(minus_two)
1831					);
1832					assert_eq!(
1833						b.const_checked_mul($name::min_value()),
1834						$name::min_value().const_checked_div(minus_two)
1835					);
1836
1837					let c = $name::saturating_from_integer(255u32);
1838					assert_eq!(c.const_checked_mul($name::min_value()), None);
1839				}
1840
1841				let a = $name::saturating_from_rational(1i32, 2i32);
1842				let c = $name::saturating_from_integer(255i32);
1843
1844				assert_eq!(a.const_checked_mul(42.into()), Some(21.into()));
1845				assert_eq!(c.const_checked_mul(2.into()), Some(510.into()));
1846				assert_eq!(c.const_checked_mul($name::max_value()), None);
1847				assert_eq!(
1848					a.const_checked_mul($name::max_value()),
1849					$name::max_value().checked_div(&2.into())
1850				);
1851				assert_eq!(
1852					a.const_checked_mul($name::min_value()),
1853					$name::min_value().const_checked_div($name::saturating_from_integer(2))
1854				);
1855			}
1856
1857			#[test]
1858			fn checked_div_int_works() {
1859				let inner_max = <$name as FixedPointNumber>::Inner::max_value();
1860				let inner_min = <$name as FixedPointNumber>::Inner::min_value();
1861				let accuracy = $name::accuracy();
1862
1863				let a = $name::from_inner(inner_max);
1864				let b = $name::from_inner(inner_min);
1865				let c = $name::zero();
1866				let d = $name::one();
1867				let e = $name::saturating_from_integer(6);
1868				let f = $name::saturating_from_integer(5);
1869
1870				assert_eq!(e.checked_div_int(2.into()), Some(3));
1871				assert_eq!(f.checked_div_int(2.into()), Some(2));
1872
1873				assert_eq!(a.checked_div_int(i128::MAX), Some(0));
1874				assert_eq!(a.checked_div_int(2), Some(inner_max / (2 * accuracy)));
1875				assert_eq!(a.checked_div_int(inner_max / accuracy), Some(1));
1876				assert_eq!(a.checked_div_int(1i8), None);
1877
1878				if b < c {
1879					// Not executed by unsigned inners.
1880					assert_eq!(
1881						a.checked_div_int(0.saturating_sub(2)),
1882						Some(0.saturating_sub(inner_max / (2 * accuracy)))
1883					);
1884					assert_eq!(
1885						a.checked_div_int(0.saturating_sub(inner_max / accuracy)),
1886						Some(0.saturating_sub(1))
1887					);
1888					assert_eq!(b.checked_div_int(i128::MIN), Some(0));
1889					assert_eq!(b.checked_div_int(inner_min / accuracy), Some(1));
1890					assert_eq!(b.checked_div_int(1i8), None);
1891					assert_eq!(
1892						b.checked_div_int(0.saturating_sub(2)),
1893						Some(0.saturating_sub(inner_min / (2 * accuracy)))
1894					);
1895					assert_eq!(
1896						b.checked_div_int(0.saturating_sub(inner_min / accuracy)),
1897						Some(0.saturating_sub(1))
1898					);
1899					assert_eq!(c.checked_div_int(i128::MIN), Some(0));
1900					assert_eq!(d.checked_div_int(i32::MIN), Some(0));
1901				}
1902
1903				assert_eq!(b.checked_div_int(2), Some(inner_min / (2 * accuracy)));
1904
1905				assert_eq!(c.checked_div_int(1), Some(0));
1906				assert_eq!(c.checked_div_int(i128::MAX), Some(0));
1907				assert_eq!(c.checked_div_int(1i8), Some(0));
1908
1909				assert_eq!(d.checked_div_int(1), Some(1));
1910				assert_eq!(d.checked_div_int(i32::MAX), Some(0));
1911				assert_eq!(d.checked_div_int(1i8), Some(1));
1912
1913				assert_eq!(a.checked_div_int(0), None);
1914				assert_eq!(b.checked_div_int(0), None);
1915				assert_eq!(c.checked_div_int(0), None);
1916				assert_eq!(d.checked_div_int(0), None);
1917			}
1918
1919			#[test]
1920			#[should_panic(expected = "attempt to divide by zero")]
1921			fn saturating_div_int_panics_when_divisor_is_zero() {
1922				let _ = $name::one().saturating_div_int(0);
1923			}
1924
1925			#[test]
1926			fn saturating_div_int_works() {
1927				let inner_max = <$name as FixedPointNumber>::Inner::max_value();
1928				let inner_min = <$name as FixedPointNumber>::Inner::min_value();
1929				let accuracy = $name::accuracy();
1930
1931				let a = $name::saturating_from_integer(5);
1932				assert_eq!(a.saturating_div_int(2), 2);
1933
1934				let a = $name::min_value();
1935				assert_eq!(a.saturating_div_int(1i128), (inner_min / accuracy) as i128);
1936
1937				if $name::SIGNED {
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_max / accuracy) as i128);
1943				}
1944			}
1945
1946			#[test]
1947			fn saturating_abs_works() {
1948				let inner_max = <$name as FixedPointNumber>::Inner::max_value();
1949				let inner_min = <$name as FixedPointNumber>::Inner::min_value();
1950
1951				assert_eq!($name::from_inner(inner_max).saturating_abs(), $name::max_value());
1952				assert_eq!($name::zero().saturating_abs(), 0.into());
1953
1954				if $name::SIGNED {
1955					assert_eq!($name::from_inner(inner_min).saturating_abs(), $name::max_value());
1956					assert_eq!(
1957						$name::saturating_from_rational(-1, 2).saturating_abs(),
1958						(1, 2).into()
1959					);
1960				}
1961			}
1962
1963			#[test]
1964			fn saturating_mul_acc_int_works() {
1965				assert_eq!($name::zero().saturating_mul_acc_int(42i8), 42i8);
1966				assert_eq!($name::one().saturating_mul_acc_int(42i8), 2 * 42i8);
1967
1968				assert_eq!($name::one().saturating_mul_acc_int(i128::MAX), i128::MAX);
1969				assert_eq!($name::one().saturating_mul_acc_int(i128::MIN), i128::MIN);
1970
1971				assert_eq!($name::one().saturating_mul_acc_int(u128::MAX / 2), u128::MAX - 1);
1972				assert_eq!($name::one().saturating_mul_acc_int(u128::MIN), u128::MIN);
1973
1974				if $name::SIGNED {
1975					let a = $name::saturating_from_rational(-1, 2);
1976					assert_eq!(a.saturating_mul_acc_int(42i8), 21i8);
1977					assert_eq!(a.saturating_mul_acc_int(42u8), 21u8);
1978					assert_eq!(a.saturating_mul_acc_int(u128::MAX - 1), u128::MAX / 2);
1979				}
1980			}
1981
1982			#[test]
1983			fn saturating_pow_should_work() {
1984				assert_eq!(
1985					$name::saturating_from_integer(2).saturating_pow(0),
1986					$name::saturating_from_integer(1)
1987				);
1988				assert_eq!(
1989					$name::saturating_from_integer(2).saturating_pow(1),
1990					$name::saturating_from_integer(2)
1991				);
1992				assert_eq!(
1993					$name::saturating_from_integer(2).saturating_pow(2),
1994					$name::saturating_from_integer(4)
1995				);
1996				assert_eq!(
1997					$name::saturating_from_integer(2).saturating_pow(3),
1998					$name::saturating_from_integer(8)
1999				);
2000				assert_eq!(
2001					$name::saturating_from_integer(2).saturating_pow(50),
2002					$name::saturating_from_integer(1125899906842624i64)
2003				);
2004
2005				assert_eq!($name::saturating_from_integer(1).saturating_pow(1000), (1).into());
2006				assert_eq!(
2007					$name::saturating_from_integer(1).saturating_pow(usize::MAX),
2008					(1).into()
2009				);
2010
2011				if $name::SIGNED {
2012					// Saturating.
2013					assert_eq!(
2014						$name::saturating_from_integer(2).saturating_pow(68),
2015						$name::max_value()
2016					);
2017
2018					assert_eq!($name::saturating_from_integer(-1).saturating_pow(1000), (1).into());
2019					assert_eq!(
2020						$name::saturating_from_integer(-1).saturating_pow(1001),
2021						0.saturating_sub(1).into()
2022					);
2023					assert_eq!(
2024						$name::saturating_from_integer(-1).saturating_pow(usize::MAX),
2025						0.saturating_sub(1).into()
2026					);
2027					assert_eq!(
2028						$name::saturating_from_integer(-1).saturating_pow(usize::MAX - 1),
2029						(1).into()
2030					);
2031				}
2032
2033				assert_eq!(
2034					$name::saturating_from_integer(114209).saturating_pow(5),
2035					$name::max_value()
2036				);
2037
2038				assert_eq!(
2039					$name::saturating_from_integer(1).saturating_pow(usize::MAX),
2040					(1).into()
2041				);
2042				assert_eq!(
2043					$name::saturating_from_integer(0).saturating_pow(usize::MAX),
2044					(0).into()
2045				);
2046				assert_eq!(
2047					$name::saturating_from_integer(2).saturating_pow(usize::MAX),
2048					$name::max_value()
2049				);
2050			}
2051
2052			#[test]
2053			fn checked_div_works() {
2054				let inner_max = <$name as FixedPointNumber>::Inner::max_value();
2055				let inner_min = <$name as FixedPointNumber>::Inner::min_value();
2056
2057				let a = $name::from_inner(inner_max);
2058				let b = $name::from_inner(inner_min);
2059				let c = $name::zero();
2060				let d = $name::one();
2061				let e = $name::saturating_from_integer(6);
2062				let f = $name::saturating_from_integer(5);
2063
2064				assert_eq!(e.checked_div(&2.into()), Some(3.into()));
2065				assert_eq!(f.checked_div(&2.into()), Some((5, 2).into()));
2066
2067				assert_eq!(a.checked_div(&inner_max.into()), Some(1.into()));
2068				assert_eq!(a.checked_div(&2.into()), Some($name::from_inner(inner_max / 2)));
2069				assert_eq!(a.checked_div(&$name::max_value()), Some(1.into()));
2070				assert_eq!(a.checked_div(&d), Some(a));
2071
2072				if b < c {
2073					// Not executed by unsigned inners.
2074					assert_eq!(
2075						a.checked_div(&0.saturating_sub(2).into()),
2076						Some($name::from_inner(0.saturating_sub(inner_max / 2)))
2077					);
2078					assert_eq!(
2079						a.checked_div(&-$name::max_value()),
2080						Some(0.saturating_sub(1).into())
2081					);
2082					assert_eq!(
2083						b.checked_div(&0.saturating_sub(2).into()),
2084						Some($name::from_inner(0.saturating_sub(inner_min / 2)))
2085					);
2086					assert_eq!(c.checked_div(&$name::max_value()), Some(0.into()));
2087					assert_eq!(b.checked_div(&b), Some($name::one()));
2088				}
2089
2090				assert_eq!(b.checked_div(&2.into()), Some($name::from_inner(inner_min / 2)));
2091				assert_eq!(b.checked_div(&a), Some(0.saturating_sub(1).into()));
2092				assert_eq!(c.checked_div(&1.into()), Some(0.into()));
2093				assert_eq!(d.checked_div(&1.into()), Some(1.into()));
2094
2095				assert_eq!(a.checked_div(&$name::one()), Some(a));
2096				assert_eq!(b.checked_div(&$name::one()), Some(b));
2097				assert_eq!(c.checked_div(&$name::one()), Some(c));
2098				assert_eq!(d.checked_div(&$name::one()), Some(d));
2099
2100				assert_eq!(a.checked_div(&$name::zero()), None);
2101				assert_eq!(b.checked_div(&$name::zero()), None);
2102				assert_eq!(c.checked_div(&$name::zero()), None);
2103				assert_eq!(d.checked_div(&$name::zero()), None);
2104			}
2105
2106			#[test]
2107			fn is_positive_negative_works() {
2108				let one = $name::one();
2109				assert!(one.is_positive());
2110				assert!(!one.is_negative());
2111
2112				let zero = $name::zero();
2113				assert!(!zero.is_positive());
2114				assert!(!zero.is_negative());
2115
2116				if $signed {
2117					let minus_one = $name::saturating_from_integer(-1);
2118					assert!(minus_one.is_negative());
2119					assert!(!minus_one.is_positive());
2120				}
2121			}
2122
2123			#[test]
2124			fn trunc_works() {
2125				let n = $name::saturating_from_rational(5, 2).trunc();
2126				assert_eq!(n, $name::saturating_from_integer(2));
2127
2128				if $name::SIGNED {
2129					let n = $name::saturating_from_rational(-5, 2).trunc();
2130					assert_eq!(n, $name::saturating_from_integer(-2));
2131				}
2132			}
2133
2134			#[test]
2135			fn frac_works() {
2136				let n = $name::saturating_from_rational(5, 2);
2137				let i = n.trunc();
2138				let f = n.frac();
2139
2140				assert_eq!(n, i + f);
2141
2142				let n = $name::saturating_from_rational(5, 2).frac().saturating_mul(10.into());
2143				assert_eq!(n, 5.into());
2144
2145				let n = $name::saturating_from_rational(1, 2).frac().saturating_mul(10.into());
2146				assert_eq!(n, 5.into());
2147
2148				if $name::SIGNED {
2149					let n = $name::saturating_from_rational(-5, 2);
2150					let i = n.trunc();
2151					let f = n.frac();
2152					assert_eq!(n, i - f);
2153
2154					// The sign is attached to the integer part unless it is zero.
2155					let n = $name::saturating_from_rational(-5, 2).frac().saturating_mul(10.into());
2156					assert_eq!(n, 5.into());
2157
2158					let n = $name::saturating_from_rational(-1, 2).frac().saturating_mul(10.into());
2159					assert_eq!(n, 0.saturating_sub(5).into());
2160				}
2161			}
2162
2163			#[test]
2164			fn ceil_works() {
2165				let n = $name::saturating_from_rational(5, 2);
2166				assert_eq!(n.ceil(), 3.into());
2167
2168				let n = $name::saturating_from_rational(-5, 2);
2169				assert_eq!(n.ceil(), 0.saturating_sub(2).into());
2170
2171				// On the limits:
2172				let n = $name::max_value();
2173				assert_eq!(n.ceil(), n.trunc());
2174
2175				let n = $name::min_value();
2176				assert_eq!(n.ceil(), n.trunc());
2177			}
2178
2179			#[test]
2180			fn floor_works() {
2181				let n = $name::saturating_from_rational(5, 2);
2182				assert_eq!(n.floor(), 2.into());
2183
2184				let n = $name::saturating_from_rational(-5, 2);
2185				assert_eq!(n.floor(), 0.saturating_sub(3).into());
2186
2187				// On the limits:
2188				let n = $name::max_value();
2189				assert_eq!(n.floor(), n.trunc());
2190
2191				let n = $name::min_value();
2192				assert_eq!(n.floor(), n.trunc());
2193			}
2194
2195			#[test]
2196			fn round_works() {
2197				let n = $name::zero();
2198				assert_eq!(n.round(), n);
2199
2200				let n = $name::one();
2201				assert_eq!(n.round(), n);
2202
2203				let n = $name::saturating_from_rational(5, 2);
2204				assert_eq!(n.round(), 3.into());
2205
2206				let n = $name::saturating_from_rational(-5, 2);
2207				assert_eq!(n.round(), 0.saturating_sub(3).into());
2208
2209				// Saturating:
2210				let n = $name::max_value();
2211				assert_eq!(n.round(), n.trunc());
2212
2213				let n = $name::min_value();
2214				assert_eq!(n.round(), n.trunc());
2215
2216				// On the limit:
2217
2218				// floor(max - 1) + 0.33..
2219				let n = $name::max_value()
2220					.saturating_sub(1.into())
2221					.trunc()
2222					.saturating_add((1, 3).into());
2223
2224				assert_eq!(n.round(), ($name::max_value() - 1.into()).trunc());
2225
2226				// floor(max - 1) + 0.5
2227				let n = $name::max_value()
2228					.saturating_sub(1.into())
2229					.trunc()
2230					.saturating_add((1, 2).into());
2231
2232				assert_eq!(n.round(), $name::max_value().trunc());
2233
2234				if $name::SIGNED {
2235					// floor(min + 1) - 0.33..
2236					let n = $name::min_value()
2237						.saturating_add(1.into())
2238						.trunc()
2239						.saturating_sub((1, 3).into());
2240
2241					assert_eq!(n.round(), ($name::min_value() + 1.into()).trunc());
2242
2243					// floor(min + 1) - 0.5
2244					let n = $name::min_value()
2245						.saturating_add(1.into())
2246						.trunc()
2247						.saturating_sub((1, 2).into());
2248
2249					assert_eq!(n.round(), $name::min_value().trunc());
2250				}
2251			}
2252
2253			#[test]
2254			fn perthing_into_works() {
2255				let ten_percent_percent: $name = Percent::from_percent(10).into();
2256				assert_eq!(ten_percent_percent.into_inner(), $name::accuracy() / 10);
2257
2258				let ten_percent_permill: $name = Permill::from_percent(10).into();
2259				assert_eq!(ten_percent_permill.into_inner(), $name::accuracy() / 10);
2260
2261				let ten_percent_perbill: $name = Perbill::from_percent(10).into();
2262				assert_eq!(ten_percent_perbill.into_inner(), $name::accuracy() / 10);
2263
2264				let ten_percent_perquintill: $name = Perquintill::from_percent(10).into();
2265				assert_eq!(ten_percent_perquintill.into_inner(), $name::accuracy() / 10);
2266			}
2267
2268			#[test]
2269			fn fmt_should_work() {
2270				let zero = $name::zero();
2271				assert_eq!(
2272					format!("{:?}", zero),
2273					format!("{}(0.{:0>weight$})", stringify!($name), 0, weight = precision())
2274				);
2275
2276				let one = $name::one();
2277				assert_eq!(
2278					format!("{:?}", one),
2279					format!("{}(1.{:0>weight$})", stringify!($name), 0, weight = precision())
2280				);
2281
2282				let frac = $name::saturating_from_rational(1, 2);
2283				assert_eq!(
2284					format!("{:?}", frac),
2285					format!("{}(0.{:0<weight$})", stringify!($name), 5, weight = precision())
2286				);
2287
2288				let frac = $name::saturating_from_rational(5, 2);
2289				assert_eq!(
2290					format!("{:?}", frac),
2291					format!("{}(2.{:0<weight$})", stringify!($name), 5, weight = precision())
2292				);
2293
2294				let frac = $name::saturating_from_rational(314, 100);
2295				assert_eq!(
2296					format!("{:?}", frac),
2297					format!("{}(3.{:0<weight$})", stringify!($name), 14, weight = precision())
2298				);
2299
2300				if $name::SIGNED {
2301					let neg = -$name::one();
2302					assert_eq!(
2303						format!("{:?}", neg),
2304						format!("{}(-1.{:0>weight$})", stringify!($name), 0, weight = precision())
2305					);
2306
2307					let frac = $name::saturating_from_rational(-314, 100);
2308					assert_eq!(
2309						format!("{:?}", frac),
2310						format!("{}(-3.{:0<weight$})", stringify!($name), 14, weight = precision())
2311					);
2312				}
2313			}
2314
2315			#[test]
2316			fn from_str_works() {
2317				use core::str::FromStr;
2318				// Test decimal notation
2319				let val = $name::from_str("1.0").unwrap();
2320				assert_eq!(val.into_inner(), $name::accuracy());
2321
2322				let val = $name::from_str("0.5").unwrap();
2323				assert_eq!(val.into_inner(), $name::accuracy() / 2);
2324
2325				let val = $name::from_str("2.5").unwrap();
2326				assert_eq!(val.into_inner(), $name::accuracy() * 5 / 2);
2327
2328				// Test whole numbers
2329				let val = $name::from_str("42").unwrap();
2330				assert_eq!(val.into_inner(), 42);
2331
2332				let val = $name::from_str("100.0").unwrap();
2333				assert_eq!(val.into_inner(), $name::accuracy() * 100);
2334
2335				// Test fractional-only
2336				let val = $name::from_str("0.25").unwrap();
2337				assert_eq!(val.into_inner(), $name::accuracy() / 4);
2338
2339				let val = $name::from_str(".5").unwrap();
2340				assert_eq!(val.into_inner(), $name::accuracy() / 2);
2341
2342				// Test precision with multiple decimal places
2343				let val = $name::from_str("1.00045").unwrap();
2344				let expected = $name::accuracy() + ($name::accuracy() * 45 / 100000);
2345				assert_eq!(val.into_inner(), expected);
2346
2347				// Test high precision fractional - use precision appropriate for each type
2348				if $name::accuracy() >= 1_000_000_000_000_000_000 {
2349					// FixedU128/FixedI128: Test full 18 decimal places
2350					let val = $name::from_str("0.123456789012345678").unwrap();
2351					let expected = ($name::accuracy() as u128 * 123456789012345678u128) /
2352						1000000000000000000u128;
2353					assert_eq!(val.into_inner() as u128, expected);
2354				} else {
2355					// FixedU64/FixedI64: Test 9 decimal places
2356					let val = $name::from_str("0.123456789").unwrap();
2357					let expected = ($name::accuracy() as u128 * 123456789u128) / 1000000000u128;
2358					assert_eq!(val.into_inner() as u128, expected);
2359				}
2360
2361				// Test legacy behavior (raw inner values)
2362				let val = $name::from_str("1000000000").unwrap();
2363				assert_eq!(val.into_inner(), 1000000000);
2364
2365				if $name::SIGNED {
2366					// Test negative values
2367					let val = $name::from_str("-1.0").unwrap();
2368					assert_eq!(val.into_inner(), 0 - $name::accuracy());
2369
2370					let val = $name::from_str("-0.5").unwrap();
2371					assert_eq!(val.into_inner(), 0 - $name::accuracy() / 2);
2372
2373					let val = $name::from_str("-2.5").unwrap();
2374					assert_eq!(val.into_inner(), 0 - $name::accuracy() * 5 / 2);
2375				} else {
2376					// Test negative number rejection for unsigned types
2377					assert!($name::from_str("-1.0").is_err());
2378					assert!($name::from_str("-0.5").is_err());
2379					assert!($name::from_str("-123.456").is_err());
2380				}
2381
2382				// Test error cases
2383				assert!($name::from_str("").is_err());
2384				assert!($name::from_str("abc").is_err());
2385				assert!($name::from_str("1.2.3").is_err());
2386				assert!($name::from_str("1.abc").is_err());
2387				assert!($name::from_str("abc.1").is_err());
2388			}
2389		}
2390	};
2391}
2392
2393#[cfg(test)]
2394mod precision_tests {
2395	use super::*;
2396	use core::str::FromStr;
2397
2398	#[test]
2399	fn test_from_str_precision_verification() {
2400		// Test FixedU64 (DIV = 1_000_000_000)
2401		let val = FixedU64::from_str("0.123456789").unwrap();
2402		let expected = 123456789u64; // 0.123456789 * 1_000_000_000
2403		assert_eq!(val.into_inner(), expected);
2404
2405		// Test FixedU128 (DIV = 1_000_000_000_000_000_000)
2406		let val = FixedU128::from_str("0.123456789012345678").unwrap();
2407		let expected = 123456789012345678u128; // 0.123456789012345678 * 1_000_000_000_000_000_000
2408		assert_eq!(val.into_inner(), expected);
2409
2410		// Test a more complex case with FixedU128
2411		let val = FixedU128::from_str("1.123456789012345678").unwrap();
2412		let expected = 1000000000000000000u128 + 123456789012345678u128;
2413		assert_eq!(val.into_inner(), expected);
2414
2415		// Test FixedI64 negative values
2416		let val = FixedI64::from_str("-0.123456789").unwrap();
2417		let expected = -123456789i64; // -0.123456789 * 1_000_000_000
2418		assert_eq!(val.into_inner(), expected);
2419
2420		// Test edge case: exact precision match for FixedU64
2421		let val = FixedU64::from_str("1.000000001").unwrap();
2422		let expected = 1000000001u64; // Should be exactly 1 * 1_000_000_000 + 1
2423		assert_eq!(val.into_inner(), expected);
2424
2425		// Test fractional precision truncation for FixedU64 with more than 9 digits
2426		let val = FixedU64::from_str("0.1234567891234").unwrap();
2427		let expected = 123456789u64; // Should truncate after 9 digits: 0.123456789
2428		assert_eq!(val.into_inner(), expected);
2429	}
2430}
2431
2432implement_fixed!(
2433	FixedI64,
2434	test_fixed_i64,
2435	i64,
2436	true,
2437	1_000_000_000,
2438	"_Fixed Point 64 bits signed, range = [-9223372036.854775808, 9223372036.854775807]_",
2439);
2440
2441implement_fixed!(
2442	FixedU64,
2443	test_fixed_u64,
2444	u64,
2445	false,
2446	1_000_000_000,
2447	"_Fixed Point 64 bits unsigned, range = [0.000000000, 18446744073.709551615]_",
2448);
2449
2450implement_fixed!(
2451	FixedI128,
2452	test_fixed_i128,
2453	i128,
2454	true,
2455	1_000_000_000_000_000_000,
2456	"_Fixed Point 128 bits signed, range = \
2457		[-170141183460469231731.687303715884105728, 170141183460469231731.687303715884105727]_",
2458);
2459
2460implement_fixed!(
2461	FixedU128,
2462	test_fixed_u128,
2463	u128,
2464	false,
2465	1_000_000_000_000_000_000,
2466	"_Fixed Point 128 bits unsigned, range = \
2467		[0.000000000000000000, 340282366920938463463.374607431768211455]_",
2468);