Skip to main content

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			#[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			/// Compute the square root. If it overflows or is negative, then `None` is returned.
590			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				// Want x' = sqrt(x) where x = n/D and x' = n'/D (D is fixed)
600				// Our preferred way is:
601				//   sqrt(n/D) = sqrt(nD / D^2) = sqrt(nD)/sqrt(D^2) = sqrt(nD)/D
602				//   ergo n' = sqrt(nD)
603				// but this requires nD to fit into our type.
604				// if nD doesn't fit then we can fall back on:
605				//   sqrt(nD) = sqrt(n)*sqrt(D)
606				// computing them individually and taking the product at the end. we will lose some
607				// precision though.
608				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			/// Add a value and return the result.
614			///
615			/// WARNING: This is a `const` function designed for convenient use at build time and
616			/// will panic on overflow. Ensure that any inputs are sensible.
617			pub const fn add(self, rhs: Self) -> Self {
618				Self(self.0 + rhs.0)
619			}
620
621			/// Subtract a value and return the result.
622			///
623			/// WARNING: This is a `const` function designed for convenient use at build time and
624			/// will panic on overflow. Ensure that any inputs are sensible.
625			pub const fn sub(self, rhs: Self) -> Self {
626				Self(self.0 - rhs.0)
627			}
628
629			/// Multiply by a value and return the result.
630			///
631			/// Result will be rounded to the nearest representable value, rounding down if it is
632			/// equidistant between two neighbours.
633			///
634			/// WARNING: This is a `const` function designed for convenient use at build time and
635			/// will panic on overflow. Ensure that any inputs are sensible.
636			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			/// Divide by a value and return the result.
644			///
645			/// Result will be rounded to the nearest representable value, rounding down if it is
646			/// equidistant between two neighbours.
647			///
648			/// WARNING: This is a `const` function designed for convenient use at build time and
649			/// will panic on overflow. Ensure that any inputs are sensible.
650			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			/// Convert into an `I129` format value.
658			///
659			/// WARNING: This is a `const` function designed for convenient use at build time and
660			/// will panic on overflow. Ensure that any inputs are sensible.
661			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			/// Convert from an `I129` format value.
675			///
676			/// WARNING: This is a `const` function designed for convenient use at build time and
677			/// will panic on overflow. Ensure that any inputs are sensible.
678			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			/// Calculate an approximation of a rational.
701			///
702			/// Result will be rounded to the nearest representable value, rounding down if it is
703			/// equidistant between two neighbours.
704			///
705			/// WARNING: This is a `const` function designed for convenient use at build time and
706			/// will panic on overflow. Ensure that any inputs are sensible.
707			pub const fn from_rational(a: u128, b: u128) -> Self {
708				Self::from_rational_with_rounding(a, b, Rounding::NearestPrefDown)
709			}
710
711			/// Calculate an approximation of a rational with custom rounding.
712			///
713			/// WARNING: This is a `const` function designed for convenient use at build time and
714			/// will panic on overflow. Ensure that any inputs are sensible.
715			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			/// Multiply by another value, returning `None` in the case of an error.
729			///
730			/// Result will be rounded to the nearest representable value, rounding down if it is
731			/// equidistant between two neighbours.
732			pub const fn const_checked_mul(self, other: Self) -> Option<Self> {
733				self.const_checked_mul_with_rounding(other, SignedRounding::NearestPrefLow)
734			}
735
736			/// Multiply by another value with custom rounding, returning `None` in the case of an
737			/// error.
738			///
739			/// Result will be rounded to the nearest representable value, rounding down if it is
740			/// equidistant between two neighbours.
741			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			/// Divide by another value, returning `None` in the case of an error.
762			///
763			/// Result will be rounded to the nearest representable value, rounding down if it is
764			/// equidistant between two neighbours.
765			pub const fn const_checked_div(self, other: Self) -> Option<Self> {
766				self.checked_rounding_div(other, SignedRounding::NearestPrefLow)
767			}
768
769			/// Divide by another value with custom rounding, returning `None` in the case of an
770			/// error.
771			///
772			/// Result will be rounded to the nearest representable value, rounding down if it is
773			/// equidistant between two neighbours.
774			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				// Note that this uses the old (well-tested) code with sign-ignorant rounding. This
900				// is equivalent to the `SignedRounding::NearestPrefMinor`. This means it is
901				// expected to give exactly the same result as `const_checked_div` when the result
902				// is positive and a result up to one epsilon greater when it is negative.
903				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				// Check if the string contains a decimal point
1004				if let Some(dot_pos) = s.find('.') {
1005					// Parse as decimal number (e.g., "1.0", "123.456")
1006					let (integer_part, fractional_part) = s.split_at(dot_pos);
1007					let fractional_part = &fractional_part[1..]; // Skip the '.'
1008
1009					// Check if it's a negative number
1010					let is_negative = integer_part.starts_with('-');
1011
1012					// For unsigned types, reject negative numbers
1013					if is_negative && !$name::SIGNED {
1014						return Err(
1015							"negative numbers not supported for unsigned fixed point types",
1016						);
1017					}
1018
1019					// Parse integer part
1020					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					// Parse fractional part
1029					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					// Convert fractional part to the appropriate scale
1038					let fractional_digits = fractional_part.len() as u32;
1039
1040					// Calculate fractional value using more careful arithmetic
1041					let fractional_scaled: i128 = if fractional_digits > 0 {
1042						// Checked math to avoid overflow
1043						let Some(scale_factor) = 10u128.checked_pow(fractional_digits) else {
1044							return Err("fractional part has too many digits");
1045						};
1046
1047						// For very large DIV values, we need to be more careful
1048						let div_u128 = Self::DIV as u128;
1049
1050						// Calculate: fractional_raw * DIV / scale_factor
1051						// We do this carefully to avoid intermediate overflow
1052						// Use alternative calculation: (fractional_raw / scale_factor) * DIV
1053						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					// Combine integer and fractional parts using wider arithmetic
1069					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					// Convert to target type
1084					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					// Parse as raw inner value (legacy behavior)
1090					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		// Manual impl `Serialize` as serde_json does not support i128.
1098		// TODO: remove impl if issue https://github.com/serde-rs/json/issues/548 fixed.
1099		#[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		// Manual impl `Deserialize` as serde_json does not support i128.
1110		// TODO: remove impl if issue https://github.com/serde-rs/json/issues/548 fixed.
1111		#[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				// Can't convert negative number to unsigned.
1159				assert_eq!(from_i129::<u128>(a), None);
1160
1161				let a = I129 { value: u128::MAX - 1, negative: false };
1162
1163				// Max - 1 value fits.
1164				assert_eq!(from_i129::<u128>(a), Some(u128::MAX - 1));
1165
1166				let a = I129 { value: u128::MAX, negative: false };
1167
1168				// Max value fits.
1169				assert_eq!(from_i129::<u128>(a), Some(u128::MAX));
1170
1171				let a = I129 { value: i128::MAX as u128 + 1, negative: true };
1172
1173				// Min value fits.
1174				assert_eq!(from_i129::<i128>(a), Some(i128::MIN));
1175
1176				let a = I129 { value: i128::MAX as u128 + 1, negative: false };
1177
1178				// Max + 1 does not fit.
1179				assert_eq!(from_i129::<i128>(a), None);
1180
1181				let a = I129 { value: i128::MAX as u128, negative: false };
1182
1183				// Max value fits.
1184				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				// Pos + Pos => Max.
1193				assert_eq!(to_bound::<_, _, i32>(a, b), i32::MAX);
1194
1195				let a = -1i32;
1196				let b = -1i32;
1197
1198				// Neg + Neg => Max.
1199				assert_eq!(to_bound::<_, _, i32>(a, b), i32::MAX);
1200
1201				let a = 1i32;
1202				let b = -1i32;
1203
1204				// Pos + Neg => Min.
1205				assert_eq!(to_bound::<_, _, i32>(a, b), i32::MIN);
1206
1207				let a = -1i32;
1208				let b = 1i32;
1209
1210				// Neg + Pos => Min.
1211				assert_eq!(to_bound::<_, _, i32>(a, b), i32::MIN);
1212
1213				let a = 1i32;
1214				let b = -1i32;
1215
1216				// Pos + Neg => Min (unsigned).
1217				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				// Zero.
1226				assert_eq!(a, b);
1227
1228				if $name::SIGNED {
1229					let a = $name::saturating_from_integer(5);
1230					let b = -a;
1231
1232					// Positive.
1233					assert_eq!($name::saturating_from_integer(-5), b);
1234
1235					let a = $name::saturating_from_integer(-5);
1236					let b = -a;
1237
1238					// Negative
1239					assert_eq!($name::saturating_from_integer(5), b);
1240
1241					let a = $name::max_value();
1242					let b = -a;
1243
1244					// Max.
1245					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					// Min.
1251					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				// Positive case: 6/2 = 3.
1268				assert_eq!($name::saturating_from_integer(3), a + b);
1269
1270				if $name::SIGNED {
1271					// Negative case: 4/2 = 2.
1272					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				// Cases where integer fits.
1358				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				// Max/min integers that fit.
1365				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				// Cases where integer doesn't fit, so it saturates.
1372				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				// Case where integer fits.
1386				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				// Max integer that fit.
1391				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				// Case where integer doesn't fit, so it returns `None`.
1396				let a = $name::checked_from_integer::<$inner_type>(inner_max / accuracy + 1);
1397				assert_eq!(a, None);
1398
1399				if $name::SIGNED {
1400					// Case where integer fits.
1401					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					// Min integer that fit.
1406					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					// Case where integer doesn't fit, so it returns `None`.
1411					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				// Positive case: 2.5
1440				assert_eq!(a.into_inner(), 25 * accuracy / 10);
1441
1442				// Max - 1.
1443				let a = $name::saturating_from_rational(inner_max - 1, accuracy);
1444				assert_eq!(a.into_inner(), inner_max - 1);
1445
1446				// Min + 1.
1447				let a = $name::saturating_from_rational(inner_min + 1, accuracy);
1448				assert_eq!(a.into_inner(), inner_min + 1);
1449
1450				// Max.
1451				let a = $name::saturating_from_rational(inner_max, accuracy);
1452				assert_eq!(a.into_inner(), inner_max);
1453
1454				// Min.
1455				let a = $name::saturating_from_rational(inner_min, accuracy);
1456				assert_eq!(a.into_inner(), inner_min);
1457
1458				// Zero.
1459				let a = $name::saturating_from_rational(0, 1);
1460				assert_eq!(a.into_inner(), 0);
1461
1462				if $name::SIGNED {
1463					// Negative case: -2.5
1464					let a = $name::saturating_from_rational(-5, 2);
1465					assert_eq!(a.into_inner(), 0 - 25 * accuracy / 10);
1466
1467					// Other negative case: -2.5
1468					let a = $name::saturating_from_rational(5, -2);
1469					assert_eq!(a.into_inner(), 0 - 25 * accuracy / 10);
1470
1471					// Other positive case: 2.5
1472					let a = $name::saturating_from_rational(-5, -2);
1473					assert_eq!(a.into_inner(), 25 * accuracy / 10);
1474
1475					// Max + 1, saturates.
1476					let a = $name::saturating_from_rational(inner_max as u128 + 1, accuracy);
1477					assert_eq!(a.into_inner(), inner_max);
1478
1479					// Min - 1, saturates.
1480					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					// Out of accuracy.
1517					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				// Out of accuracy.
1549				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				// Divide by zero => None.
1560				let a = $name::checked_from_rational(1, 0);
1561				assert_eq!(a, None);
1562
1563				// Max - 1.
1564				let a = $name::checked_from_rational(inner_max - 1, accuracy).unwrap();
1565				assert_eq!(a.into_inner(), inner_max - 1);
1566
1567				// Min + 1.
1568				let a = $name::checked_from_rational(inner_min + 1, accuracy).unwrap();
1569				assert_eq!(a.into_inner(), inner_min + 1);
1570
1571				// Max.
1572				let a = $name::checked_from_rational(inner_max, accuracy).unwrap();
1573				assert_eq!(a.into_inner(), inner_max);
1574
1575				// Min.
1576				let a = $name::checked_from_rational(inner_min, accuracy).unwrap();
1577				assert_eq!(a.into_inner(), inner_min);
1578
1579				// Max + 1 => Overflow => None.
1580				let a = $name::checked_from_rational(inner_min, 0.saturating_sub(accuracy));
1581				assert_eq!(a, None);
1582
1583				if $name::SIGNED {
1584					// Min - 1 => Underflow => None.
1585					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				// Max - 1.
1627				let a = $name::from_rational(inner_max - 1, accuracy);
1628				assert_eq!(a.into_inner() as u128, inner_max - 1);
1629
1630				// Min + 1.
1631				let a = $name::from_rational(inner_min + 1, accuracy);
1632				assert_eq!(a.into_inner() as u128, inner_min + 1);
1633
1634				// Max.
1635				let a = $name::from_rational(inner_max, accuracy);
1636				assert_eq!(a.into_inner() as u128, inner_max);
1637
1638				// Min.
1639				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				// Max - 1.
1659				assert_eq!(a.checked_mul_int((i128::MAX - 1) / 2), Some(i128::MAX - 1));
1660				// Max.
1661				assert_eq!(a.checked_mul_int(i128::MAX / 2), Some(i128::MAX - 1));
1662				// Max + 1 => None.
1663				assert_eq!(a.checked_mul_int(i128::MAX / 2 + 1), None);
1664
1665				if $name::SIGNED {
1666					// Min - 1.
1667					assert_eq!(a.checked_mul_int((i128::MIN + 1) / 2), Some(i128::MIN + 2));
1668					// Min.
1669					assert_eq!(a.checked_mul_int(i128::MIN / 2), Some(i128::MIN));
1670					// Min + 1 => None.
1671					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				// Max - 1.
1696				assert_eq!(a.saturating_mul_int((i128::MAX - 1) / 2), i128::MAX - 1);
1697				// Max.
1698				assert_eq!(a.saturating_mul_int(i128::MAX / 2), i128::MAX - 1);
1699				// Max + 1 => saturates to max.
1700				assert_eq!(a.saturating_mul_int(i128::MAX / 2 + 1), i128::MAX);
1701
1702				// Min - 1.
1703				assert_eq!(a.saturating_mul_int((i128::MIN + 1) / 2), i128::MIN + 2);
1704				// Min.
1705				assert_eq!(a.saturating_mul_int(i128::MIN / 2), i128::MIN);
1706				// Min + 1 => saturates to min.
1707				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				// Max - 1.
1737				let b = $name::from_inner(inner_max - 1);
1738				assert_eq!(a.checked_mul(&(b / 2.into())), Some(b));
1739
1740				// Max.
1741				let c = $name::from_inner(inner_max);
1742				assert_eq!(a.checked_mul(&(c / 2.into())), Some(b));
1743
1744				// Max + 1 => None.
1745				let e = $name::from_inner(1);
1746				assert_eq!(a.checked_mul(&(c / 2.into() + e)), None);
1747
1748				if $name::SIGNED {
1749					// Min + 1.
1750					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					// Min.
1755					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					// Min - 1 => None.
1760					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				// Max - 1.
1802				let b = $name::from_inner(inner_max - 1);
1803				assert_eq!(a.const_checked_mul(b / 2.into()), Some(b));
1804
1805				// Max.
1806				let c = $name::from_inner(inner_max);
1807				assert_eq!(a.const_checked_mul(c / 2.into()), Some(b));
1808
1809				// Max + 1 => None.
1810				let e = $name::from_inner(1);
1811				assert_eq!(a.const_checked_mul(c / 2.into() + e), None);
1812
1813				if $name::SIGNED {
1814					// Min + 1.
1815					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					// Min.
1820					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					// Min - 1 => None.
1825					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					// Not executed by unsigned inners.
1887					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					// Saturating.
2020					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					// Not executed by unsigned inners.
2081					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					// The sign is attached to the integer part unless it is zero.
2162					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				// On the limits:
2179				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				// On the limits:
2195				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				// Saturating:
2217				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				// On the limit:
2224
2225				// floor(max - 1) + 0.33..
2226				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				// floor(max - 1) + 0.5
2234				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					// floor(min + 1) - 0.33..
2243					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					// floor(min + 1) - 0.5
2251					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				// Test decimal notation
2326				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				// Test whole numbers
2336				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				// Test fractional-only
2343				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				// Test precision with multiple decimal places
2350				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				// Test high precision fractional - use precision appropriate for each type
2355				if $name::accuracy() >= 1_000_000_000_000_000_000 {
2356					// FixedU128/FixedI128: Test full 18 decimal places
2357					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					// FixedU64/FixedI64: Test 9 decimal places
2363					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				// Test legacy behavior (raw inner values)
2369				let val = $name::from_str("1000000000").unwrap();
2370				assert_eq!(val.into_inner(), 1000000000);
2371
2372				if $name::SIGNED {
2373					// Test negative values
2374					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					// Test negative number rejection for unsigned types
2384					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				// Test error cases
2390				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		// Test FixedU64 (DIV = 1_000_000_000)
2408		let val = FixedU64::from_str("0.123456789").unwrap();
2409		let expected = 123456789u64; // 0.123456789 * 1_000_000_000
2410		assert_eq!(val.into_inner(), expected);
2411
2412		// Test FixedU128 (DIV = 1_000_000_000_000_000_000)
2413		let val = FixedU128::from_str("0.123456789012345678").unwrap();
2414		let expected = 123456789012345678u128; // 0.123456789012345678 * 1_000_000_000_000_000_000
2415		assert_eq!(val.into_inner(), expected);
2416
2417		// Test a more complex case with FixedU128
2418		let val = FixedU128::from_str("1.123456789012345678").unwrap();
2419		let expected = 1000000000000000000u128 + 123456789012345678u128;
2420		assert_eq!(val.into_inner(), expected);
2421
2422		// Test FixedI64 negative values
2423		let val = FixedI64::from_str("-0.123456789").unwrap();
2424		let expected = -123456789i64; // -0.123456789 * 1_000_000_000
2425		assert_eq!(val.into_inner(), expected);
2426
2427		// Test edge case: exact precision match for FixedU64
2428		let val = FixedU64::from_str("1.000000001").unwrap();
2429		let expected = 1000000001u64; // Should be exactly 1 * 1_000_000_000 + 1
2430		assert_eq!(val.into_inner(), expected);
2431
2432		// Test fractional precision truncation for FixedU64 with more than 9 digits
2433		let val = FixedU64::from_str("0.1234567891234").unwrap();
2434		let expected = 123456789u64; // Should truncate after 9 digits: 0.123456789
2435		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);