fixed_num/
dec19x19.rs

1use rand::Rng;
2use rand::SeedableRng;
3use rand::rngs::StdRng;
4use paste::paste;
5use std::str::FromStr;
6use fixed_num_helper::*;
7use crate::ops::*;
8
9pub use fixed_num_macro::*;
10
11// ============
12// === i256 ===
13// ============
14// The ethnum implementation is a bit faster, but it contained some serious bugs that we reported
15// during development and they got fixed. On the other hand, the arrow implementation did not have
16// any obvious bugs.
17
18#[cfg(feature="i256_arrow")]
19use arrow_buffer::i256;
20
21#[cfg(feature="i256_arrow")]
22#[inline(always)]
23const fn i256_from_i128(val: i128) -> i256 {
24    i256::from_i128(val)
25}
26
27#[cfg(feature="i256_arrow")]
28#[inline(always)]
29fn i256_to_i128(val: i256) -> Option<i128> {
30    i256::to_i128(val)
31}
32
33#[cfg(feature="i256_ethnum")]
34use ethnum::I256 as i256;
35
36#[cfg(feature="i256_ethnum")]
37#[inline(always)]
38const fn i256_from_i128(val: i128) -> i256 {
39    i256::new(val)
40}
41
42#[cfg(feature="i256_ethnum")]
43#[inline(always)]
44fn i256_to_i128(val: i256) -> Option<i128> {
45    i128::try_from(val).ok()
46}
47
48// =================
49// === Constants ===
50// =================
51
52const FRAC_SCALE_U128: u128 = FRAC_SCALE_I128 as u128;
53const FRAC_SCALE_F64: f64 = FRAC_SCALE_I128 as f64;
54const FRAC_SCALE_I256: i256 = i256_from_i128(FRAC_SCALE_I128);
55const FRAC_SCALE_I128_HALF: i128 = FRAC_SCALE_I128 / 2;
56const I256_TWO: i256 = i256_from_i128(2);
57const LN_2_I256: i256 = i256_from_i128(Dec19x19::LN_2.repr);
58
59// ================
60// === Dec19x19 ===
61// ================
62
63/// A high-precision, high-performance fixed-point decimal type.
64///
65/// Internally, values are stored as `i128`, which supports 39 digits with the first digit never
66/// exceeding `1`. The last 19 digits are interpreted as the fractional part. This allows all
67/// operations to perform without rounding or approximations within the full range of exactly 19
68/// fractional and 19 integer digits.
69#[repr(transparent)]
70pub struct Dec19x19 {
71    pub repr: i128,
72}
73
74impl Dec19x19 {
75    /// Creates a new `Dec19x19` from the given `i128` representation, assuming the last 19 digits
76    /// are the fractional part.
77    #[inline(always)]
78    pub const fn from_repr(repr: i128) -> Self {
79        Self { repr }
80    }
81
82    #[inline(always)]
83    pub const fn is_zero(self) -> bool {
84        self.repr == 0
85    }
86}
87
88// =================
89// === Std Impls ===
90// =================
91// Implemented manually to mark all methods as inline.
92
93impl Copy for Dec19x19 {}
94impl Clone for Dec19x19 {
95    #[inline(always)]
96    fn clone(&self) -> Self {
97        *self
98    }
99}
100
101impl Default for Dec19x19 {
102    #[inline(always)]
103    fn default() -> Self {
104        Self { repr: 0 }
105    }
106}
107
108impl Eq for Dec19x19 {}
109impl PartialEq for Dec19x19 {
110    #[inline(always)]
111    fn eq(&self, other: &Self) -> bool {
112        self.repr == other.repr
113    }
114}
115
116impl Ord for Dec19x19 {
117    #[inline(always)]
118    fn cmp(&self, other: &Self) -> std::cmp::Ordering {
119        self.repr.cmp(&other.repr)
120    }
121}
122
123impl PartialOrd for Dec19x19 {
124    #[inline(always)]
125    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
126        Some(self.cmp(other))
127    }
128}
129
130#[cfg(nightly)]
131impl std::iter::Step for Dec19x19 {
132    #[inline(always)]
133    fn forward(start: Self, count: usize) -> Self {
134        Self::from_repr(<i128 as std::iter::Step>::forward(start.repr, count))
135    }
136
137    #[inline(always)]
138    fn backward(start: Self, count: usize) -> Self {
139        Self::from_repr(<i128 as std::iter::Step>::backward(start.repr, count))
140    }
141
142    #[inline(always)]
143    unsafe fn forward_unchecked(start: Self, count: usize) -> Self {
144        unsafe {
145            Self::from_repr(<i128 as std::iter::Step>::forward_unchecked(start.repr, count))
146        }
147    }
148
149    #[inline(always)]
150    unsafe fn backward_unchecked(start: Self, count: usize) -> Self {
151        unsafe {
152            Self::from_repr(<i128 as std::iter::Step>::backward_unchecked(start.repr, count))
153        }
154    }
155
156    #[inline(always)]
157    fn steps_between(start: &Self, end: &Self) -> (usize, Option<usize>) {
158        <i128 as std::iter::Step>::steps_between(&start.repr, &end.repr)
159    }
160
161    #[inline(always)]
162    fn forward_checked(start: Self, count: usize) -> Option<Self> {
163        <i128 as std::iter::Step>::forward_checked(start.repr, count).map(Self::from_repr)
164    }
165
166    #[inline(always)]
167    fn backward_checked(start: Self, count: usize) -> Option<Self> {
168        <i128 as std::iter::Step>::backward_checked(start.repr, count).map(Self::from_repr)
169    }
170}
171
172// ==========================
173// === Dec19x19 Constants ===
174// ==========================
175
176impl Dec19x19 {
177    /// The biggest possible integer value that can be stored in a `Dec19x19`.
178    ///
179    /// # Tests
180    ///
181    /// ```
182    /// # use fixed_num::*;
183    /// assert_eq!(Dec19x19::MAX_INT, Dec19x19::MAX.trunc());
184    /// ```
185    pub const MAX_INT: Self = Dec19x19!(17_014_118_346_046_923_173);
186
187    /// The smallest possible integer value that can be stored in a `Dec19x19`.
188    ///
189    /// # Tests
190    ///
191    /// ```
192    /// # use fixed_num::*;
193    /// assert_eq!(Dec19x19::MIN_INT, Dec19x19::MIN.trunc());
194    /// ```
195    pub const MIN_INT: Self = Dec19x19!(-17_014_118_346_046_923_173);
196
197    /// The natural logarithm of 2 (`ln(2)`), accurate to all 19 decimal places of the `Dec19x19`
198    /// fixed-point format.
199    pub const LN_2: Self = Dec19x19!(0.693_147_180_559_945_309_4);
200
201    /// The smallest possible value that can be stored in a `Dec19x19`.
202    ///
203    /// # Tests
204    ///
205    /// ```
206    /// # use fixed_num::*;
207    /// assert_eq!(Dec19x19::SMALLEST_STEP / Dec19x19!(2), Dec19x19!(0));
208    /// ```
209    pub const SMALLEST_STEP: Self = Dec19x19!(0.000_000_000_000_000_000_1);
210}
211
212// ==============
213// === Random ===
214// ==============
215
216/// Generates a deterministic random `Dec19x19` value using a seed, an integer precision, and a
217/// fractional precision. Never returns zero.
218///
219/// # Tests
220///
221/// ```
222/// # use fixed_num::*;
223/// # use validator::*;
224/// check! ( [Dec19x19::rand] {
225///     (0,  6, 0) => Dec19x19!(-758_415),
226///     (1,  6, 0) => Dec19x19!(-717_558),
227///     (2,  6, 0) => Dec19x19!(-149_577),
228///     (3,  6, 0) => Dec19x19!(-442_649),
229///     (4,  6, 0) => Dec19x19!( 658_419),
230///     (5,  6, 0) => Dec19x19!( 165_296),
231///
232///     (6,  3, 0) => Dec19x19!(-787),
233///     (7,  3, 0) => Dec19x19!(-354),
234///     (8,  3, 0) => Dec19x19!( 745),
235///     (9,  3, 0) => Dec19x19!( 163),
236///     (10, 3, 0) => Dec19x19!(-211),
237///     (11, 3, 0) => Dec19x19!(-719),
238///
239///     (12, 3, 3) => Dec19x19!(-698.488),
240///     (13, 3, 3) => Dec19x19!( 354.710),
241///     (14, 3, 3) => Dec19x19!( 807.648),
242///     (15, 3, 3) => Dec19x19!(-392.145),
243///     (16, 3, 3) => Dec19x19!(-243.552),
244///     (17, 3, 3) => Dec19x19!( 378.313),
245///
246///     (18, 6, 6) => Dec19x19!( 428_879.493_071),
247///     (19, 6, 6) => Dec19x19!( 414_719.622_665),
248///     (20, 6, 6) => Dec19x19!( 154_184.335_022),
249///     (21, 6, 6) => Dec19x19!( 335_592.781_210),
250///     (22, 6, 6) => Dec19x19!(-562_472.732_119),
251///     (23, 6, 6) => Dec19x19!(-990_435.673_210),
252///
253///     (0, 0, 6) => Dec19x19!(-0.758_415),
254///     (1, 0, 6) => Dec19x19!(-0.617_558),
255///     (2, 0, 6) => Dec19x19!(-0.049_577),
256///     (3, 0, 6) => Dec19x19!(-0.342_649),
257///     (4, 0, 6) => Dec19x19!( 0.658_419),
258///     (5, 0, 6) => Dec19x19!( 0.065_296),
259///
260///     (1, 19, 19) => Dec19x19!(-7_175_586_050_193_843_404.647_199_936_274_331_797_4),
261///
262///     (0, 0, 0) => Dec19x19!(-7),
263///     (1, 0, 0) => Dec19x19!(-6),
264///     (2, 0, 0) => Dec19x19!(-1),
265///     (3, 0, 0) => Dec19x19!(-3),
266///     (4, 0, 0) => Dec19x19!(6),
267///     (5, 0, 0) => Dec19x19!(1),
268///
269///     (1, 0..=9, 0..=9) => Dec19x19!(42545517.614973869),
270///     (2, 0..=9, 0..=9) => Dec19x19!(-0.41),
271///     (3, 0..=9, 0..=9) => Dec19x19!(-224053),
272///     (4, 0..=9, 0..=9) => Dec19x19!(662259.83081),
273///     (5, 0..=9, 0..=9) => Dec19x19!(-5.748),
274/// });
275/// ```
276impl Rand for Dec19x19 {
277    fn rand(seed: u64, int: impl IntoRandRange, frac: impl IntoRandRange) -> Self {
278        let int_prec_range = int.into_rand_range();
279        let frac_prec_range = frac.into_rand_range();
280        assert!(*int_prec_range.end() <= 19);
281        assert!(*frac_prec_range.end() <= 19);
282        let mut rng = StdRng::seed_from_u64(seed);
283        let int_prec = if int_prec_range.start() == int_prec_range.end() {
284            *int_prec_range.start()
285        } else {
286            rng.random_range(int_prec_range)
287        };
288        let frac_prec = if frac_prec_range.start() == frac_prec_range.end() {
289            *frac_prec_range.start()
290        } else {
291            rng.random_range(frac_prec_range)
292        };
293
294        let digit_count = (int_prec + frac_prec).max(1);
295        let scale = 10_i128.pow(digit_count - 1);
296        let max_val = scale - 1;
297        let first_digit_start = if int_prec > 0 { 1 } else { 0 };
298        let first_digit = rng.random_range(first_digit_start..=9);
299        let mut val = first_digit * scale + rng.random_range(0..=max_val);
300        if val == 0 {
301            val = 1;
302        }
303
304        val *= 10_i128.pow(19 - frac_prec);
305        if rng.random_bool(0.5) {
306            val = -val;
307        }
308        Self::from_repr(val)
309    }
310}
311
312// ====================
313// === Impl Helpers ===
314// ====================
315
316macro_rules! impl_op_for_refs {
317    ($op:ident :: $f:ident) => {
318        impl<'t> $op<&'t Dec19x19> for &'t Dec19x19 {
319            type Output = Dec19x19;
320            #[inline(always)]
321            fn $f(self, rhs: Self) -> Self::Output {
322                $op::<Dec19x19>::$f(*self, *rhs)
323            }
324        }
325
326        impl<'t> $op<&'t Dec19x19> for Dec19x19 {
327            type Output = Dec19x19;
328            #[inline(always)]
329            fn $f(self, rhs: &'t Dec19x19) -> Self::Output {
330                $op::<Dec19x19>::$f(self, *rhs)
331            }
332        }
333
334        impl $op<Dec19x19> for &Dec19x19 {
335            type Output = Dec19x19;
336            #[inline(always)]
337            fn $f(self, rhs: Dec19x19) -> Self::Output {
338                $op::<Dec19x19>::$f(*self, rhs)
339            }
340        }
341    };
342}
343
344#[cfg(nightly)]
345macro_rules! const_impl {
346    ($(#$meta:tt)* impl $($ts:tt)*) => {
347        $(#$meta)*
348        impl const $($ts)*
349    };
350}
351
352#[cfg(not(nightly))]
353macro_rules! const_impl {
354    ($(#$meta:tt)* impl $($ts:tt)*) => {
355        $(#$meta)*
356        impl $($ts)*
357    };
358}
359
360// =================
361// === Max / Min ===
362// =================
363
364const_impl!{
365/// The biggest possible value that can be stored in a `Dec19x19`, equal to
366/// ```
367/// # assert_eq!(fixed_num::Dec19x19!(
368/// 17_014_118_346_046_923_173.168_730_371_588_410_572_7
369/// # ).repr, i128::MAX);
370/// ```
371impl HasMax for Dec19x19 {
372    const MAX: Self = Self { repr: i128::MAX };
373    fn is_max(self) -> bool {
374        self.repr == i128::MAX
375    }
376}}
377
378const_impl!{
379/// The smallest possible value that can be stored in a `Dec19x19`, equal to
380/// ```
381/// # assert_eq!(fixed_num::Dec19x19!(
382/// -17_014_118_346_046_923_173.168_730_371_588_410_572_8
383/// # ).repr, i128::MIN);
384/// ```
385impl HasMin for Dec19x19 {
386    const MIN: Self = Self { repr: i128::MIN };
387    fn is_min(self) -> bool {
388        self.repr == i128::MIN
389    }
390}}
391
392// ==============
393// === Signum ===
394// ==============
395
396const_impl!{
397/// # Tests
398///
399/// ```
400/// # use fixed_num::*;
401/// # use validator::*;
402/// check! ( [Dec19x19::signum] {
403///     (Dec19x19::MAX)   => Dec19x19!(1.0),
404///     (Dec19x19!(3.0))  => Dec19x19!(1.0),
405///     (Dec19x19!(0.0))  => Dec19x19!(0.0),
406///     (Dec19x19!(-3.0)) => Dec19x19!(-1.0),
407///     (Dec19x19::MIN)   => Dec19x19!(-1.0),
408/// });
409/// ```
410impl Signum for Dec19x19 {
411    #[inline(always)]
412    fn signum(self) -> Self {
413        Self { repr: self.signum_i128() * FRAC_SCALE_I128 }
414    }
415
416    #[inline(always)]
417    fn signum_i128(self) -> i128 {
418        self.repr.signum()
419    }
420}}
421
422// ===========
423// === Neg ===
424// ===========
425
426/// # Tests
427///
428/// ```
429/// # use fixed_num::*;
430/// # use validator::*;
431/// check! ( [Dec19x19::neg] {
432///     (Dec19x19::MAX)   => Dec19x19::MIN + Dec19x19::SMALLEST_STEP,
433///     (Dec19x19!(3.0))  => Dec19x19!(-3.0),
434///     (Dec19x19!(0.0))  => Dec19x19!(0.0),
435///     (Dec19x19!(-3.0)) => Dec19x19!(3.0),
436///     (Dec19x19::MIN)   => Dec19x19::MAX,
437///     ((Dec19x19::MIN + Dec19x19::SMALLEST_STEP)) => Dec19x19::MAX,
438/// });
439/// ```
440impl Neg for Dec19x19 {
441    type Output = Self;
442    #[inline(always)]
443    fn neg(self) -> Self::Output {
444        if self == Self::MIN {
445            Self::MAX
446        } else {
447            Self::from_repr(-self.repr)
448        }
449    }
450}
451
452// ===========
453// === Abs ===
454// ===========
455
456const_impl!{
457/// # Tests
458///
459/// ```
460/// # use fixed_num::*;
461/// # use validator::*;
462/// check!( [Dec19x19::abs] {
463///     (Dec19x19::MAX)   => Dec19x19::MAX,
464///     (Dec19x19!(3.0))  => Dec19x19!(3.0),
465///     (Dec19x19!(0.0))  => Dec19x19!(0.0),
466///     (Dec19x19!(-3.0)) => Dec19x19!(3.0),
467///     (Dec19x19::MIN)   => Dec19x19::MAX,
468/// });
469/// ```
470impl Abs for Dec19x19 {
471    #[inline(always)]
472    fn abs(self) -> Self {
473        if self.is_min() {
474            return Self::MAX;
475        }
476        Self { repr: self.repr.abs() }
477    }
478}}
479
480// ===========
481// === Rem ===
482// ===========
483
484/// # Tests
485///
486/// ```
487/// # use fixed_num::*;
488/// # use validator::*;
489/// check!( [Dec19x19::rem] {
490///     (Dec19x19!(14.7), Dec19x19!(5))             => Dec19x19!(4.7),
491///     (Dec19x19!(14.7), Dec19x19!(0))             => Dec19x19!(14.7),
492///     (Dec19x19!(14.7), Dec19x19::SMALLEST_STEP)  => Dec19x19!(0),
493///     (Dec19x19::MAX,   Dec19x19::SMALLEST_STEP)  => Dec19x19!(0),
494///     (Dec19x19::MIN,   -Dec19x19::SMALLEST_STEP) => Dec19x19!(0),
495///     (Dec19x19::MAX,   Dec19x19::MAX)            => Dec19x19!(0),
496///     (Dec19x19::MIN,   Dec19x19::MIN)            => Dec19x19!(0),
497///     (Dec19x19::MAX,   Dec19x19::MIN)            => Dec19x19::MAX,
498///     (Dec19x19::MIN,   Dec19x19::MAX)            => -Dec19x19::SMALLEST_STEP,
499/// });
500/// ```
501impl Rem for Dec19x19 {
502    type Output = Self;
503    #[inline(always)]
504    fn rem(self, rhs: Self) -> Self::Output {
505        if rhs.repr == 0 {
506            self
507        } else if self == Self::MIN && rhs == -Self::SMALLEST_STEP {
508            Dec19x19!(0)
509        } else {
510            Self { repr: self.repr % rhs.repr }
511        }
512    }
513}
514
515// ===========
516// === Add ===
517// ===========
518
519/// # Tests
520///
521/// ```
522/// # use fixed_num::*;
523/// # use validator::*;
524/// check!( [Dec19x19::add, Dec19x19::checked_add] {
525///     (Dec19x19::MAX, Dec19x19::MIN) => -Dec19x19::SMALLEST_STEP,
526///     (Dec19x19::MAX - Dec19x19!(1), Dec19x19!(1)) => Dec19x19::MAX,
527///     (Dec19x19::MAX, Dec19x19!(0)) => Dec19x19::MAX,
528///     (Dec19x19::MIN, Dec19x19!(0)) => Dec19x19::MIN,
529///     (Dec19x19::MAX, Dec19x19::SMALLEST_STEP) => FAIL,
530///     (Dec19x19::MAX, Dec19x19!(1)) => FAIL,
531///     (Dec19x19::MIN, -Dec19x19::SMALLEST_STEP) => FAIL
532/// });
533/// ```
534///
535/// # Fuzzy
536///
537/// ```
538/// # use fixed_num::*;
539/// # use validator::*;
540/// fuzzy2::<Dec19x19, BigDecimal>(Series::new(0..=18, 0..=19), Series::new(0..=18, 0..=19),
541///     |(f1, b1), (f2, b2)| should_eq(f1 + f2, b1 + b2)
542/// );
543/// ```
544impl Add for Dec19x19 {
545    type Output = Self;
546    #[track_caller]
547    #[inline(always)]
548    fn add(self, rhs: Self) -> Self {
549        self.unchecked_add(rhs)
550    }
551}
552
553const_impl!{ impl UncheckedAdd for Dec19x19 {
554    type Output = Self;
555    #[track_caller]
556    #[inline(always)]
557    fn unchecked_add(self, rhs: Self) -> Self {
558        Self::from_repr(self.repr + rhs.repr)
559    }
560}}
561
562const_impl!{ impl CheckedAdd for Dec19x19 {
563    type Output = Self;
564    #[track_caller]
565    #[inline(always)]
566    fn checked_add(self, rhs: Self) -> Option<Self> {
567        if let Some(result) = self.repr.checked_add(rhs.repr) {
568            Some(Self::from_repr(result))
569        } else {
570            None
571        }
572    }
573}}
574
575const_impl!{
576/// # Tests
577///
578/// ```
579/// # use fixed_num::*;
580/// # use validator::*;
581/// check! ( [Dec19x19::saturating_add] {
582///     (Dec19x19::MAX,  Dec19x19::SMALLEST_STEP) => Dec19x19::MAX,
583///     (Dec19x19::MIN, -Dec19x19::SMALLEST_STEP) => Dec19x19::MIN,
584/// });
585/// ```
586impl SaturatingAdd for Dec19x19 {
587    type Output = Self;
588    #[track_caller]
589    #[inline(always)]
590    fn saturating_add(self, rhs: Self) -> Self {
591        if let Some(result) = self.checked_add(rhs) {
592            result
593        } else if self.signum_i128() >= 0 {
594            Self::MAX
595        } else {
596            Self::MIN
597        }
598    }
599}}
600
601impl AddAssign for Dec19x19 {
602    #[track_caller]
603    #[inline(always)]
604    fn add_assign(&mut self, rhs: Self) {
605        *self = *self + rhs;
606    }
607}
608
609impl_op_for_refs!(Add::add);
610
611// ===========
612// === Sub ===
613// ===========
614
615/// # Tests
616///
617/// ```
618/// # use fixed_num::*;
619/// # use validator::*;
620/// check!( [Dec19x19::sub, Dec19x19::checked_sub] {
621///     (Dec19x19::MIN + Dec19x19!(1), Dec19x19!(1)) => Dec19x19::MIN,
622///     (-Dec19x19::SMALLEST_STEP, Dec19x19::MIN) => Dec19x19::MAX,
623///     (Dec19x19::MIN, Dec19x19::SMALLEST_STEP) => FAIL,
624///     (Dec19x19::MIN, Dec19x19!(1)) => FAIL,
625///     (Dec19x19!(0), Dec19x19::MIN) => FAIL,
626/// });
627/// ```
628///
629/// # Fuzzy
630///
631/// ```
632/// # use fixed_num::*;
633/// # use validator::*;
634/// fuzzy2::<Dec19x19, BigDecimal>(Series::new(0..=18, 0..=19), Series::new(0..=18, 0..=19),
635///     |(f1, b1), (f2, b2)| should_eq(f1 - f2, b1 - b2)
636/// );
637/// ```
638impl Sub for Dec19x19 {
639    type Output = Self;
640    #[track_caller]
641    #[inline(always)]
642    fn sub(self, rhs: Self) -> Self {
643        self.unchecked_sub(rhs)
644    }
645}
646
647const_impl!{ impl UncheckedSub for Dec19x19 {
648    type Output = Self;
649    #[track_caller]
650    #[inline(always)]
651    fn unchecked_sub(self, rhs: Self) -> Self {
652        Self::from_repr(self.repr - rhs.repr)
653    }
654}}
655
656const_impl!{ impl CheckedSub for Dec19x19 {
657    type Output = Self;
658    #[track_caller]
659    #[inline(always)]
660    fn checked_sub(self, rhs: Self) -> Option<Self> {
661        if let Some(result) = self.repr.checked_sub(rhs.repr) {
662            Some(Self::from_repr(result))
663        } else {
664            None
665        }
666    }
667}}
668
669const_impl!{
670/// # Tests
671///
672/// ```
673/// # use fixed_num::*;
674/// # use validator::*;
675/// check! ( [Dec19x19::saturating_sub] {
676///     (Dec19x19::MIN, Dec19x19!(1))  => Dec19x19::MIN,
677///     (Dec19x19!(10), Dec19x19::MIN) => Dec19x19::MAX,
678///     (Dec19x19!(0), Dec19x19::MIN)  => Dec19x19::MAX,
679/// });
680/// ```
681impl SaturatingSub for Dec19x19 {
682    type Output = Self;
683    #[track_caller]
684    #[inline(always)]
685    fn saturating_sub(self, rhs: Self) -> Self {
686        if let Some(result) = self.checked_sub(rhs) {
687            result
688        } else if self.signum_i128() >= 0 {
689            Self::MAX
690        } else {
691            Self::MIN
692        }
693    }
694}}
695
696impl SubAssign for Dec19x19 {
697    #[track_caller]
698    #[inline(always)]
699    fn sub_assign(&mut self, rhs: Self) {
700        *self = *self - rhs;
701    }
702}
703
704impl_op_for_refs!(Sub::sub);
705
706// ==========
707// === Mul ==
708// ==========
709
710/// # Tests
711///
712/// ```
713/// # use fixed_num::*;
714/// # use validator::*;
715/// check!(
716///     [
717///         Dec19x19::unchecked_mul_no_opt,
718///         Dec19x19::unchecked_mul_opt,
719///         Dec19x19::checked_mul_no_opt,
720///         Dec19x19::checked_mul_opt,
721///     ] {
722///     (Dec19x19!(20), Dec19x19!(2.2)) => Dec19x19!(44.0),
723///     (Dec19x19::MAX, Dec19x19!(10)) => FAIL,
724///     (Dec19x19::MAX - Dec19x19!(10), Dec19x19!(2)) => FAIL,
725/// });
726/// ```
727///
728/// # Fuzzy
729///
730/// ```
731/// # use fixed_num::*;
732/// # use validator::*;
733/// let series = [
734///     Series::new(0..=9, 0..=19),
735///     Series::new(9, 19),
736///     Series::new(0, 19),
737///     Series::new(9, 0),
738/// ];
739/// for s in series {
740///     fuzzy2::<Dec19x19, BigDecimal>(s.clone(), s,
741///         |(f1, b1), (f2, b2)| {
742///             should_eq(f1.unchecked_mul_opt(f2), b1.clone() * b2.clone());
743///             should_eq(f1.unchecked_mul_no_opt(f2), b1.clone() * b2.clone());
744///             should_eq(f1.checked_mul_opt(f2).unwrap(), b1.clone() * b2.clone());
745///             should_eq(f1.checked_mul_no_opt(f2).unwrap(), b1 * b2);
746///         }
747///     );
748/// }
749/// ```
750impl Mul for Dec19x19 {
751    type Output = Self;
752    #[track_caller]
753    #[inline(always)]
754    fn mul(self, rhs: Self) -> Self {
755        self.unchecked_mul(rhs)
756    }
757}
758
759impl Dec19x19 {
760    /// Multiplication without checking for overflow and no optimization for LHS or RHS being ints
761    /// or fracs only. You probably want to use `Dec19x19::mul` with `mul_opt` flag disabled
762    /// instead.
763    #[track_caller]
764    #[inline(always)]
765    pub fn unchecked_mul_no_opt(self, rhs: Self) -> Self {
766        // 1) sign & magnitudes
767        let neg = (self.repr < 0) ^ (rhs.repr < 0);
768        let ua  = self.repr.unsigned_abs();
769        let ub  = rhs.repr.unsigned_abs();
770
771        // 2) split into integer/fraction parts
772        let ai = ua / FRAC_SCALE_U128;
773        let af = ua % FRAC_SCALE_U128;
774        let bi = ub / FRAC_SCALE_U128;
775        let bf = ub % FRAC_SCALE_U128;
776
777        // 3) 128×128 multiplies
778        let int   = ai * bi;
779        let cross = ai * bf + bi * af;
780        let frac  = af * bf / FRAC_SCALE_U128;
781
782        // 4) reassemble
783        let mag = int * FRAC_SCALE_U128 + cross + frac;
784        let mut repr: i128 = mag.try_into().expect("Overflow");
785        if neg { repr = -repr; }
786        Self { repr }
787    }
788
789    /// Multiplication without checking for overflow and optimization for LHS or RHS being ints or
790    /// fracs only. You probably want to use `Dec19x19::mul` with `mul_opt` flag enabled instead
791    /// (default).
792    #[track_caller]
793    #[inline(always)]
794    pub fn unchecked_mul_opt(self, rhs: Self) -> Self {
795        // 1) sign & magnitudes
796        let neg = (self.repr < 0) ^ (rhs.repr < 0);
797        let ua  = self.repr.unsigned_abs();
798        let ub  = rhs.repr.unsigned_abs();
799
800        // 2) split into integer/fraction parts
801        let bi = ub / FRAC_SCALE_U128;
802        let bf = ub % FRAC_SCALE_U128;
803
804        // 3) 28×128 multiplies
805        let mag = if bf == 0 {
806            ua * bi
807        } else if bi == 0 {
808            let ai = ua / FRAC_SCALE_U128;
809            let af = ua % FRAC_SCALE_U128;
810            let cross = ai * bf;
811            let frac = af * bf / FRAC_SCALE_U128;
812            cross + frac
813        } else {
814            let ai = ua / FRAC_SCALE_U128;
815            let af = ua % FRAC_SCALE_U128;
816            let int = ai * bi * FRAC_SCALE_U128;
817            if af == 0 {
818                let cross = ai * bf;
819                int + cross
820            } else {
821                let cross = ai * bf + bi * af;
822                let frac = af * bf / FRAC_SCALE_U128;
823                int + cross + frac
824            }
825        };
826
827        // 4) reassemble
828        let mut repr: i128 = mag.try_into().expect("Overflow");
829        if neg { repr = -repr; }
830        Self { repr }
831    }
832
833    /// Multiplication with checking for overflow and no optimization for LHS or RHS being ints. You
834    /// probably want to use `Dec19x19::checked_mul` with `mul_opt` flag disabled instead.
835    #[track_caller]
836    #[inline(always)]
837    pub fn checked_mul_no_opt(self, rhs: Self) -> Option<Self> {
838        // 1) sign & magnitudes
839        let neg = (self.repr < 0) ^ (rhs.repr < 0);
840        let ua  = self.repr.unsigned_abs();
841        let ub  = rhs.repr.unsigned_abs();
842
843        // 2) split into integer/fraction parts
844        let ai = ua / FRAC_SCALE_U128;
845        let af = ua % FRAC_SCALE_U128;
846        let bi = ub / FRAC_SCALE_U128;
847        let bf = ub % FRAC_SCALE_U128;
848
849        // 3) 128×128 multiplies
850        let int      = ai.checked_mul(bi)?;
851        let t1       = ai.checked_mul(bf)?;
852        let t2       = bi.checked_mul(af)?;
853        let cross    = t1.checked_add(t2)?;
854        let frac_mul = af.checked_mul(bf)?;
855        let frac     = frac_mul / FRAC_SCALE_U128; // Safe
856
857        // 4) reassemble
858        let scaled_int = int.checked_mul(FRAC_SCALE_U128)?;
859        let sum1       = scaled_int.checked_add(cross)?;
860        let mag        = sum1.checked_add(frac)?;
861        let mut repr: i128 = mag.try_into().ok()?;
862        if neg { repr = repr.checked_neg()?; }
863        Some(Self { repr })
864    }
865
866    /// Multiplication with checking for overflow and optimization for LHS or RHS being ints. You
867    /// probably want to use `Dec19x19::checked_mul` with `mul_opt` flag enabled instead.
868    #[track_caller]
869    #[inline(always)]
870    pub fn checked_mul_opt(self, rhs: Self) -> Option<Self> {
871        // 1) sign & magnitudes
872        let neg = (self.repr < 0) ^ (rhs.repr < 0);
873        let ua  = self.repr.unsigned_abs();
874        let ub  = rhs.repr.unsigned_abs();
875
876        // 2) split into integer/fraction parts
877
878        let bi = ub / FRAC_SCALE_U128;
879        let bf = ub % FRAC_SCALE_U128;
880
881        // 3) 128×128 multiplies
882        let mag = if bf == 0 {
883            ua.checked_mul(bi)?
884        } else if bi == 0 {
885            let ai = ua / FRAC_SCALE_U128;
886            let af = ua % FRAC_SCALE_U128;
887            let cross    = ai.checked_mul(bf)?;
888            let frac_mul = af.checked_mul(bf)?;
889            let frac     = frac_mul / FRAC_SCALE_U128; // Safe
890            cross.checked_add(frac)?
891        } else {
892            let ai = ua / FRAC_SCALE_U128;
893            let af = ua % FRAC_SCALE_U128;
894            let int = ai.checked_mul(bi)?.checked_mul(FRAC_SCALE_U128)?;
895            if af == 0 {
896                let cross = ai.checked_mul(bf)?;
897                int.checked_add(cross)?
898            } else {
899                let t1       = ai.checked_mul(bf)?;
900                let t2       = bi.checked_mul(af)?;
901                let cross    = t1.checked_add(t2)?;
902                let frac_mul = af.checked_mul(bf)?;
903                let frac     = frac_mul / FRAC_SCALE_U128; // Safe
904                let sum1     = int.checked_add(cross)?;
905                sum1.checked_add(frac)?
906            }
907        };
908        let mut repr: i128 = mag.try_into().ok()?;
909        if neg { repr = repr.checked_neg()?; }
910        Some(Self { repr })
911    }
912}
913
914impl UncheckedMul for Dec19x19 {
915    type Output = Self;
916    #[track_caller]
917    #[inline(always)]
918    fn unchecked_mul(self, rhs: Self) -> Self {
919        #[cfg(feature = "mul_opt")]
920        { self.unchecked_mul_opt(rhs) }
921        #[cfg(not(feature = "mul_opt"))]
922        { self.unchecked_mul_no_opt(rhs) }
923    }
924}
925
926impl CheckedMul for Dec19x19 {
927    type Output = Self;
928    #[track_caller]
929    #[inline(always)]
930    fn checked_mul(self, rhs: Self) -> Option<Self> {
931        #[cfg(feature = "mul_opt")]
932        { self.checked_mul_opt(rhs) }
933        #[cfg(not(feature = "mul_opt"))]
934        { self.checked_mul_no_opt(rhs) }
935    }
936}
937
938/// # Tests
939///
940/// ```
941/// # use fixed_num::*;
942/// # use validator::*;
943/// check! ( [Dec19x19::saturating_mul] {
944///     (Dec19x19::MAX - Dec19x19!(10), Dec19x19!(2)) => Dec19x19::MAX,
945///     (Dec19x19::MAX - Dec19x19!(10), Dec19x19!(-2)) => Dec19x19::MIN,
946/// });
947/// ```
948impl SaturatingMul for Dec19x19 {
949    type Output = Self;
950    #[track_caller]
951    #[inline(always)]
952    fn saturating_mul(self, rhs: Self) -> Self {
953        self.checked_mul(rhs).unwrap_or_else(||
954            if self.signum_i128() * rhs.signum_i128() > 0 { Self::MAX } else { Self::MIN },
955        )
956    }
957}
958
959impl MulAssign for Dec19x19 {
960    #[track_caller]
961    #[inline(always)]
962    fn mul_assign(&mut self, rhs: Self) {
963        *self = *self * rhs;
964    }
965}
966
967impl_op_for_refs!(Mul::mul);
968
969// ===========
970// === Div ===
971// ===========
972
973/// # Tests
974///
975/// ```
976/// # use fixed_num::*;
977/// # use validator::*;
978/// check! ( [Dec19x19::div, Dec19x19::checked_div] {
979///     (Dec19x19!(20), Dec19x19!(0.2)) => Dec19x19!(100.0),
980///     (Dec19x19::MAX, Dec19x19!(-1)) => Dec19x19::MIN + Dec19x19::SMALLEST_STEP,
981///     (Dec19x19::MIN + Dec19x19::SMALLEST_STEP, Dec19x19!(-1)) => Dec19x19::MAX,
982///     (Dec19x19::MAX - Dec19x19!(10), Dec19x19!(0.1)) => FAIL,
983///     (Dec19x19::MAX - Dec19x19!(10), Dec19x19!(0)) => FAIL,
984///     (Dec19x19!(10), Dec19x19!(0)) => FAIL,
985///     (Dec19x19::MAX, Dec19x19!(0.1)) => FAIL,
986/// });
987/// ```
988///
989/// # Fuzzy
990///
991/// ```
992/// # use fixed_num::*;
993/// # use validator::*;
994/// fuzzy2::<Dec19x19, BigDecimal>(Series::new(0..=9, 0..=9), Series::new(0..=9, 0..=9),
995///     |(f1, b1), (f2, b2)| should_eq(f1 / f2, b1 / b2)
996/// );
997/// ```
998impl Div for Dec19x19 {
999    type Output = Self;
1000    #[track_caller]
1001    #[inline(always)]
1002    fn div(self, rhs: Self) -> Self {
1003        self.unchecked_div(rhs)
1004    }
1005}
1006
1007impl UncheckedDiv for Dec19x19 {
1008    type Output = Self;
1009    #[track_caller]
1010    #[inline(always)]
1011    fn unchecked_div(self, rhs: Self) -> Self {
1012        let lhs_i256 = i256_from_i128(self.repr);
1013        let scaled_lhs = lhs_i256 * FRAC_SCALE_I256;
1014        let result = scaled_lhs / rhs.repr;
1015        #[cfg(inherit_overflow_checks)]
1016        { Self::from_repr(i256_to_i128(result).expect("Overflow in Dec19x19 division")) }
1017        #[cfg(not(inherit_overflow_checks))]
1018        { Self::from_repr(result.as_i128()) }
1019    }
1020}
1021
1022impl CheckedDiv for Dec19x19 {
1023    type Output = Self;
1024    #[track_caller]
1025    #[inline(always)]
1026    fn checked_div(self, rhs: Self) -> Option<Self> {
1027        let lhs_i256 = i256_from_i128(self.repr);
1028        let rhs_i256 = i256_from_i128(rhs.repr);
1029        let scaled_lhs = lhs_i256 * FRAC_SCALE_I256;
1030        let result = scaled_lhs.checked_div(rhs_i256)?;
1031        i256_to_i128(result).map(Self::from_repr)
1032    }
1033}
1034
1035/// # Tests
1036///
1037/// ```
1038/// # use fixed_num::*;
1039/// assert_eq!((Dec19x19::MAX - Dec19x19!(10)).saturating_div(Dec19x19!(0.1)), Dec19x19::MAX);
1040/// assert_eq!((Dec19x19::MAX - Dec19x19!(10)).saturating_div(Dec19x19!(-0.1)), Dec19x19::MIN);
1041/// assert_eq!(Dec19x19::MIN.saturating_div(Dec19x19!(-1)), Dec19x19::MAX);
1042/// ```
1043impl SaturatingDiv for Dec19x19 {
1044    type Output = Self;
1045    #[track_caller]
1046    #[inline(always)]
1047    fn saturating_div(self, rhs: Self) -> Self {
1048        self.checked_div(rhs).unwrap_or_else(||
1049            if self.signum_i128() * rhs.signum_i128() >= 0 { Self::MAX } else { Self::MIN },
1050        )
1051    }
1052}
1053
1054impl DivAssign for Dec19x19 {
1055    #[track_caller]
1056    #[inline(always)]
1057    fn div_assign(&mut self, rhs: Self) {
1058        *self = *self / rhs;
1059    }
1060}
1061
1062impl_op_for_refs!(Div::div);
1063
1064// =============
1065// === Trunc ===
1066// =============
1067
1068/// # Tests
1069///
1070/// ```
1071/// # use fixed_num::*;
1072/// # use validator::*;
1073/// check! ( [Dec19x19::trunc_to] {
1074///     (Dec19x19::MAX, 0) => Dec19x19::MAX_INT,
1075///     (Dec19x19!( 3.9), 0) => Dec19x19!( 3.0),
1076///     (Dec19x19!( 3.1), 0) => Dec19x19!( 3.0),
1077///     (Dec19x19!( 3.0), 0) => Dec19x19!( 3.0),
1078///     (Dec19x19!(-3.9), 0) => Dec19x19!(-3.0),
1079///     (Dec19x19!(-3.1), 0) => Dec19x19!(-3.0),
1080///     (Dec19x19!(-3.0), 0) => Dec19x19!(-3.0),
1081///     (Dec19x19::MIN, 0) => Dec19x19::MIN_INT,
1082///
1083///     // Border `to` values.
1084///     (Dec19x19::MAX,  18) => Dec19x19!(17_014_118_346_046_923_173.168_730_371_588_410_572),
1085///     (Dec19x19::MAX,  19) => Dec19x19!(17_014_118_346_046_923_173.168_730_371_588_410_572_7),
1086///     (Dec19x19::MAX,  99) => Dec19x19!(17_014_118_346_046_923_173.168_730_371_588_410_572_7),
1087///     (Dec19x19::MAX, -18) => Dec19x19!(17_000_000_000_000_000_000),
1088///     (Dec19x19::MAX, -19) => Dec19x19!(10_000_000_000_000_000_000),
1089///     (Dec19x19::MAX, -99) => Dec19x19!(10_000_000_000_000_000_000),
1090/// });
1091/// ```
1092impl Dec19x19 {
1093    #[track_caller]
1094    #[inline(always)]
1095    const fn trunc_impl(self, scale: i128) -> Self {
1096        let int_part = self.repr / scale;
1097        Self { repr: int_part * scale }
1098    }
1099}
1100
1101const_impl!{ impl Trunc for Dec19x19 {
1102    #[track_caller]
1103    #[inline(always)]
1104    fn trunc(self) -> Self {
1105        self.trunc_impl(FRAC_SCALE_I128)
1106    }
1107}}
1108
1109const_impl!{ impl TruncTo for Dec19x19 {
1110    #[track_caller]
1111    #[inline(always)]
1112    fn trunc_to(self, digits: i64) -> Self {
1113        let scale = crate::i128_ops::scale_for(digits);
1114        self.trunc_impl(scale)
1115    }
1116}}
1117
1118// =============
1119// === Floor ===
1120// =============
1121
1122/// # Tests
1123///
1124/// ```
1125/// # use fixed_num::*;
1126/// # use validator::*;
1127/// check! ( [Dec19x19::floor_to] {
1128///     (Dec19x19::MAX,     0) => Dec19x19::MAX_INT,
1129///     (Dec19x19!(3.9),    0) => Dec19x19!(3.0),
1130///     (Dec19x19!(3.1),    0) => Dec19x19!(3.0),
1131///     (Dec19x19!(3.0),    0) => Dec19x19!(3.0),
1132///     (Dec19x19!(-3.9),   0) => Dec19x19!(-4.0),
1133///     (Dec19x19!(-3.1),   0) => Dec19x19!(-4.0),
1134///     (Dec19x19!(-3.0),   0) => Dec19x19!(-3.0),
1135///     (Dec19x19::MIN_INT, 0) => Dec19x19::MIN_INT,
1136///
1137///     // No flooring below MIN_INT
1138///     ((Dec19x19::MIN_INT + Dec19x19::SMALLEST_STEP), 0) => Dec19x19::MIN_INT,
1139///     ((Dec19x19::MIN_INT - Dec19x19::SMALLEST_STEP), 0) => Dec19x19::MIN_INT - Dec19x19::SMALLEST_STEP,
1140///     (Dec19x19::MIN, 0) => Dec19x19::MIN,
1141///
1142///     // Border `to` values.
1143///     (Dec19x19::MAX,  18) => Dec19x19!(17_014_118_346_046_923_173.168_730_371_588_410_572),
1144///     (Dec19x19::MAX,  19) => Dec19x19!(17_014_118_346_046_923_173.168_730_371_588_410_572_7),
1145///     (Dec19x19::MAX,  99) => Dec19x19!(17_014_118_346_046_923_173.168_730_371_588_410_572_7),
1146///     (Dec19x19::MAX, -18) => Dec19x19!(17_000_000_000_000_000_000),
1147///     (Dec19x19::MAX, -19) => Dec19x19!(10_000_000_000_000_000_000),
1148///     (Dec19x19::MAX, -99) => Dec19x19!(10_000_000_000_000_000_000),
1149/// });
1150/// ```
1151impl Dec19x19 {
1152    #[track_caller]
1153    #[inline(always)]
1154    const fn floor_impl(self, scale: i128) -> Self {
1155        let frac = self.repr % scale;
1156        let has_fraction = frac != 0;
1157        let is_negative = self.repr < 0;
1158        let subtract_one = has_fraction & is_negative;
1159        let truncated = (self.repr / scale) * scale;
1160        let repr = if subtract_one {
1161            if let Some(result) = truncated.checked_sub(scale) {
1162                result
1163            } else {
1164                self.repr
1165            }
1166        } else {
1167            truncated
1168        };
1169        Self { repr }
1170    }
1171}
1172
1173const_impl!{ impl Floor for Dec19x19 {
1174    #[track_caller]
1175    #[inline(always)]
1176    fn floor(self) -> Self {
1177        self.floor_impl(FRAC_SCALE_I128)
1178    }
1179}}
1180
1181const_impl!{ impl FloorTo for Dec19x19 {
1182    #[track_caller]
1183    #[inline(always)]
1184    fn floor_to(self, digits: i64) -> Self {
1185        let scale = crate::i128_ops::scale_for(digits);
1186        self.floor_impl(scale)
1187    }
1188}}
1189
1190// ============
1191// === Ceil ===
1192// ============
1193
1194/// # Tests
1195///
1196/// ```
1197/// # use fixed_num::*;
1198/// # use validator::*;
1199/// check! ( [Dec19x19::ceil_to] {
1200///     (Dec19x19::MAX,   0) => Dec19x19::MAX,
1201///     (Dec19x19!( 3.9), 0) => Dec19x19!( 4.0),
1202///     (Dec19x19!( 3.1), 0) => Dec19x19!( 4.0),
1203///     (Dec19x19!( 3.0), 0) => Dec19x19!( 3.0),
1204///     (Dec19x19!(-3.9), 0) => Dec19x19!(-3.0),
1205///     (Dec19x19!(-3.1), 0) => Dec19x19!(-3.0),
1206///     (Dec19x19!(-3.0), 0) => Dec19x19!(-3.0),
1207///     (Dec19x19::MIN,   0) => Dec19x19::MIN_INT,
1208///
1209///     // No ceiling above MAX_INT
1210///     ((Dec19x19::MAX - Dec19x19::SMALLEST_STEP), 0) => Dec19x19::MAX - Dec19x19::SMALLEST_STEP,
1211///     (Dec19x19::MAX_INT, 0) => Dec19x19::MAX_INT,
1212///     ((Dec19x19::MAX_INT - Dec19x19::SMALLEST_STEP), 0) => Dec19x19::MAX_INT,
1213///     ((Dec19x19::MAX_INT + Dec19x19::SMALLEST_STEP), 0) => Dec19x19::MAX_INT + Dec19x19::SMALLEST_STEP,
1214///
1215///     // Border `to` values.
1216///     (Dec19x19::MIN,  18) => Dec19x19!(-17_014_118_346_046_923_173.168_730_371_588_410_572),
1217///     (Dec19x19::MIN,  19) => Dec19x19!(-17_014_118_346_046_923_173.168_730_371_588_410_572_8),
1218///     (Dec19x19::MIN,  99) => Dec19x19!(-17_014_118_346_046_923_173.168_730_371_588_410_572_8),
1219///     (Dec19x19::MIN, -18) => Dec19x19!(-17_000_000_000_000_000_000),
1220///     (Dec19x19::MIN, -19) => Dec19x19!(-10_000_000_000_000_000_000),
1221///     (Dec19x19::MIN, -99) => Dec19x19!(-10_000_000_000_000_000_000),
1222/// });
1223/// ```
1224impl Dec19x19 {
1225    #[track_caller]
1226    #[inline(always)]
1227    const fn ceil_impl(self, scale: i128) -> Self {
1228        let frac = self.repr % scale;
1229        let has_fraction = frac != 0;
1230        let is_positive = self.repr > 0;
1231        let add_one = has_fraction & is_positive;
1232        let truncated = (self.repr / scale) * scale;
1233        let repr = if add_one {
1234            if let Some(result) = truncated.checked_add(scale) {
1235                result
1236            } else {
1237                self.repr
1238            }
1239        } else {
1240            truncated
1241        };
1242        Self { repr }
1243    }
1244}
1245
1246const_impl!{ impl Ceil for Dec19x19 {
1247    #[track_caller]
1248    #[inline(always)]
1249    fn ceil(self) -> Self {
1250        self.ceil_impl(FRAC_SCALE_I128)
1251    }
1252}}
1253
1254const_impl!{ impl CeilTo for Dec19x19 {
1255    #[track_caller]
1256    #[inline(always)]
1257    fn ceil_to(self, digits: i64) -> Self {
1258        let scale = crate::i128_ops::scale_for(digits);
1259        self.ceil_impl(scale)
1260    }
1261}}
1262
1263// =============
1264// === Round ===
1265// =============
1266
1267/// # Tests
1268///
1269/// ```
1270/// # use fixed_num::*;
1271/// # use validator::*;
1272/// check! ( [Dec19x19::round_to] {
1273///     (Dec19x19!(3.9),  0) => Dec19x19!(4.0),
1274///     (Dec19x19!(3.6),  0) => Dec19x19!(4.0),
1275///     (Dec19x19!(3.5),  0) => Dec19x19!(4.0),
1276///     (Dec19x19!(3.4),  0) => Dec19x19!(3.0),
1277///     (Dec19x19!(3.0),  0) => Dec19x19!(3.0),
1278///     (Dec19x19!(-3.9), 0) => Dec19x19!(-4.0),
1279///     (Dec19x19!(-3.6), 0) => Dec19x19!(-4.0),
1280///     (Dec19x19!(-3.5), 0) => Dec19x19!(-4.0),
1281///     (Dec19x19!(-3.4), 0) => Dec19x19!(-3.0),
1282///     (Dec19x19!(-3.0), 0) => Dec19x19!(-3.0),
1283///
1284///     (Dec19x19!(0.39),  1) => Dec19x19!(0.4),
1285///     (Dec19x19!(0.36),  1) => Dec19x19!(0.4),
1286///     (Dec19x19!(0.35),  1) => Dec19x19!(0.4),
1287///     (Dec19x19!(0.34),  1) => Dec19x19!(0.3),
1288///     (Dec19x19!(0.30),  1) => Dec19x19!(0.3),
1289///     (Dec19x19!(-0.39), 1) => Dec19x19!(-0.4),
1290///     (Dec19x19!(-0.36), 1) => Dec19x19!(-0.4),
1291///     (Dec19x19!(-0.35), 1) => Dec19x19!(-0.4),
1292///     (Dec19x19!(-0.34), 1) => Dec19x19!(-0.3),
1293///     (Dec19x19!(-0.30), 1) => Dec19x19!(-0.3),
1294///
1295///     (Dec19x19!(39.0),  -1) => Dec19x19!(40),
1296///     (Dec19x19!(36.0),  -1) => Dec19x19!(40),
1297///     (Dec19x19!(35.0),  -1) => Dec19x19!(40),
1298///     (Dec19x19!(34.0),  -1) => Dec19x19!(30),
1299///     (Dec19x19!(30.0),  -1) => Dec19x19!(30),
1300///     (Dec19x19!(-39.0), -1) => Dec19x19!(-40),
1301///     (Dec19x19!(-36.0), -1) => Dec19x19!(-40),
1302///     (Dec19x19!(-35.0), -1) => Dec19x19!(-40),
1303///     (Dec19x19!(-34.0), -1) => Dec19x19!(-30),
1304///     (Dec19x19!(-30.0), -1) => Dec19x19!(-30),
1305///
1306///     // Possible to round values up.
1307///     ((Dec19x19::MAX - Dec19x19!(1)), 0) => Dec19x19::MAX_INT - Dec19x19!(1),
1308///     ((Dec19x19::MAX - Dec19x19!(1)), 1) => Dec19x19!(17_014_118_346_046_923_172.2),
1309///     ((Dec19x19::MAX - Dec19x19!(1)), 2) => Dec19x19!(17_014_118_346_046_923_172.17),
1310///     ((Dec19x19::MAX - Dec19x19!(1)), 3) => Dec19x19!(17_014_118_346_046_923_172.169),
1311///
1312///     // Impossible to round values up.
1313///     (Dec19x19::MAX, 0) => Dec19x19::MAX_INT,
1314///     (Dec19x19::MAX, 1) => Dec19x19!(17_014_118_346_046_923_173.1),
1315///     (Dec19x19::MAX, 2) => Dec19x19!(17_014_118_346_046_923_173.16),
1316///     (Dec19x19::MAX, 3) => Dec19x19!(17_014_118_346_046_923_173.168),
1317///
1318///     // Possible to round values down.
1319///     ((Dec19x19::MIN + Dec19x19!(1)), 0) => Dec19x19::MIN_INT + Dec19x19!(1),
1320///     ((Dec19x19::MIN + Dec19x19!(1)), 1) => Dec19x19!(-17_014_118_346_046_923_172.2),
1321///     ((Dec19x19::MIN + Dec19x19!(1)), 2) => Dec19x19!(-17_014_118_346_046_923_172.17),
1322///     ((Dec19x19::MIN + Dec19x19!(1)), 3) => Dec19x19!(-17_014_118_346_046_923_172.169),
1323///
1324///     // Impossible to round values down.
1325///     (Dec19x19::MIN, 0) => Dec19x19::MIN_INT,
1326///     (Dec19x19::MIN, 1) => Dec19x19!(-17_014_118_346_046_923_173.1),
1327///     (Dec19x19::MIN, 2) => Dec19x19!(-17_014_118_346_046_923_173.16),
1328///     (Dec19x19::MIN, 3) => Dec19x19!(-17_014_118_346_046_923_173.168),
1329///
1330///     // Rounding at the border of precision.
1331///     (Dec19x19!(1.123_456_789_012_345_678_0), 19) => Dec19x19!(1.123_456_789_012_345_678_0),
1332///     (Dec19x19!(1.123_456_789_012_345_678_4), 19) => Dec19x19!(1.123_456_789_012_345_678_4),
1333///     (Dec19x19!(1.123_456_789_012_345_678_5), 19) => Dec19x19!(1.123_456_789_012_345_678_5),
1334///     (Dec19x19!(1.123_456_789_012_345_678_6), 19) => Dec19x19!(1.123_456_789_012_345_678_6),
1335///     (Dec19x19!(1.123_456_789_012_345_678_9), 19) => Dec19x19!(1.123_456_789_012_345_678_9),
1336///     (Dec19x19!(1.123_456_789_012_345_678_0), 18) => Dec19x19!(1.123_456_789_012_345_678),
1337///     (Dec19x19!(1.123_456_789_012_345_678_4), 18) => Dec19x19!(1.123_456_789_012_345_678),
1338///     (Dec19x19!(1.123_456_789_012_345_678_5), 18) => Dec19x19!(1.123_456_789_012_345_679),
1339///     (Dec19x19!(1.123_456_789_012_345_678_6), 18) => Dec19x19!(1.123_456_789_012_345_679),
1340///     (Dec19x19!(1.123_456_789_012_345_678_9), 18) => Dec19x19!(1.123_456_789_012_345_679),
1341///
1342///     (Dec19x19::MAX,  18) => Dec19x19!(17_014_118_346_046_923_173.168_730_371_588_410_572),
1343///     (Dec19x19::MAX,  19) => Dec19x19!(17_014_118_346_046_923_173.168_730_371_588_410_572_7),
1344///     (Dec19x19::MAX,  99) => Dec19x19!(17_014_118_346_046_923_173.168_730_371_588_410_572_7),
1345///     (Dec19x19::MAX, -18) => Dec19x19!(17_000_000_000_000_000_000),
1346///     (Dec19x19::MAX, -19) => Dec19x19!(10_000_000_000_000_000_000),
1347///     (Dec19x19::MAX, -99) => Dec19x19!(10_000_000_000_000_000_000),
1348/// });
1349/// ```
1350///
1351/// # Validation
1352///
1353/// Note that the rounding here behaves slightly differently than `BigDecimal` crate. It might
1354/// fail if we change the scope or seed.
1355/// [Bug report](https://github.com/akubera/bigdecimal-rs/issues/149).
1356/// ```
1357/// // # use fixed_num::*;
1358/// // # use validator::*;
1359/// // for i in -7 ..= 7 {
1360/// //     fuzzy::<Dec19x19, BigDecimal>(Series::new(0..=19, 0..=19), Series::new(0..=19, 0..=19),
1361/// //         |(f1, b1), (f2, b2)| should_eq(f1.round_to(i), b1.round(i))
1362/// //     );
1363/// // }
1364/// ```
1365impl Dec19x19 {
1366    #[track_caller]
1367    #[inline(always)]
1368    const fn round_impl(self, scale: i128, scale_half: i128) -> Self {
1369        let sign = self.repr >> 127; // 0 for +, -1 for -
1370        let bias = (scale_half ^ sign) - sign; // HALF or -HALF without branches
1371        let rounded = if let Some(t) = self.repr.checked_add(bias) {
1372            t / scale
1373        } else {
1374            self.repr / scale
1375        };
1376        Self { repr: rounded * scale }
1377    }
1378}
1379
1380const_impl!{ impl Round for Dec19x19 {
1381    #[track_caller]
1382    #[inline(always)]
1383    fn round(self) -> Self {
1384        self.round_impl(FRAC_SCALE_I128, FRAC_SCALE_I128_HALF)
1385    }
1386}}
1387
1388const_impl!{ impl RoundTo for Dec19x19 {
1389    #[track_caller]
1390    #[inline(always)]
1391    fn round_to(self, digits: i64) -> Self {
1392        let scale = crate::i128_ops::scale_for(digits);
1393        let scale_half = scale / 2;
1394        self.round_impl(scale, scale_half)
1395    }
1396}}
1397
1398// ============
1399// === Sqrt ===
1400// ============
1401
1402/// # Tests
1403///
1404/// ```
1405/// # use fixed_num::*;
1406/// # use validator::*;
1407/// check! ( [Dec19x19::unchecked_sqrt, Dec19x19::checked_sqrt] {
1408///     (Dec19x19!(0)) => Dec19x19!(0),
1409///     (Dec19x19::MAX) => Dec19x19!(4_124_817_371.235_594_858_790_322_117_5),
1410///     (-Dec19x19::SMALLEST_STEP) => FAIL,
1411/// });
1412/// // Precision test.
1413/// assert_eq!(Dec19x19!(1e-18).unchecked_sqrt() * Dec19x19!(1e-18).unchecked_sqrt(), Dec19x19!(1e-18));
1414/// ```
1415///
1416/// # Validation
1417///
1418/// ```
1419/// # use fixed_num::*;
1420/// # use validator::*;
1421/// fuzzy1::<Dec19x19, BigDecimal>(Series::new(0..=19, 0..=19),
1422///     |f1, b1| should_eq(f1.abs().unchecked_sqrt(), b1.abs().sqrt().unwrap())
1423/// );
1424/// ```
1425impl UncheckedSqrt for Dec19x19 {
1426    #[track_caller]
1427    #[inline(always)]
1428    fn unchecked_sqrt(self) -> Self {
1429        assert!(self.repr >= 0, "sqrt: negative number");
1430        if self.repr == 0 {
1431            return Self::from_repr(0);
1432        }
1433        let initial_guess = {
1434            let self_f64 = self.repr as f64 / FRAC_SCALE_F64;
1435            let approx_sqrt = self_f64.sqrt();
1436            i256_from_i128((approx_sqrt * FRAC_SCALE_F64) as i128)
1437        };
1438        let x = i256_from_i128(self.repr);
1439        let scale = FRAC_SCALE_I256;
1440        let mut guess = initial_guess;
1441        let mut last;
1442
1443        // Newton-Raphson loop
1444        loop {
1445            last = guess;
1446            guess = (guess + (x * scale) / guess) / I256_TWO;
1447            if (last - guess).wrapping_abs() <= i256::ONE {
1448                break;
1449            }
1450        }
1451        Self::from_repr(guess.as_i128())
1452    }
1453}
1454
1455impl CheckedSqrt for Dec19x19 {
1456    #[track_caller]
1457    #[inline(always)]
1458    fn checked_sqrt(self) -> Option<Self> {
1459        if self.repr < 0 {
1460            None
1461        } else {
1462            Some(self.unchecked_sqrt())
1463        }
1464    }
1465}
1466
1467// ==================
1468// === Log10Floor ===
1469// ==================
1470
1471const_impl!{
1472/// # Tests
1473///
1474/// ```
1475/// # use fixed_num::*;
1476/// # use validator::*;
1477/// check! ( [Dec19x19::unchecked_log10_floor, Dec19x19::checked_log10_floor] {
1478///     (Dec19x19::MAX)   => Dec19x19!(19),
1479///     (Dec19x19!(10.1)) => Dec19x19!(1),
1480///     (Dec19x19!(10.0)) => Dec19x19!(1),
1481///     (Dec19x19!(9.99)) => Dec19x19!(0),
1482///     (Dec19x19!(1.17)) => Dec19x19!(0),
1483///     (Dec19x19!(1.0))  => Dec19x19!(0),
1484///     (Dec19x19!(0.9))  => Dec19x19!(-1),
1485///     (Dec19x19!(0.11)) => Dec19x19!(-1),
1486///     (Dec19x19!(0.1))  => Dec19x19!(-1),
1487///     (Dec19x19!(0.09)) => Dec19x19!(-2),
1488///     (-Dec19x19::SMALLEST_STEP) => FAIL,
1489/// });
1490/// ```
1491impl UncheckedLog10Floor for Dec19x19 {
1492    #[track_caller]
1493    #[inline(always)]
1494    fn unchecked_log10_floor(self) -> Self {
1495        assert!(self.repr > 0);
1496        // log10(repr / 10^19) = digit_count - 1 - 19
1497        Self::from_i32(crate::i128_ops::digit_count(self.repr) - 20)
1498    }
1499}}
1500
1501const_impl!{ impl CheckedLog10Floor for Dec19x19 {
1502    #[track_caller]
1503    #[inline(always)]
1504    fn checked_log10_floor(self) -> Option<Self> {
1505        if self.repr >= 0 {
1506            Some(self.unchecked_log10_floor())
1507        } else {
1508            None
1509        }
1510    }
1511}}
1512
1513// ==========
1514// === Ln ===
1515// ==========
1516
1517// sqrt(2) * 10^19   = 1.4142135623730950488e19
1518const SQRT2_UP_I128: i128 = 14_142_135_623_730_950_488;
1519// (10^19 / sqrt(2)) = 7.071067811865475244e18
1520const SQRT2_DN_I128: i128 =  7_071_067_811_865_475_244;
1521
1522const SQRT2_UP_I256: i256 = i256_from_i128(SQRT2_UP_I128);
1523const SQRT2_DN_I256: i256 = i256_from_i128(SQRT2_DN_I128);
1524
1525/// # Tests
1526///
1527/// ```
1528/// # use fixed_num::*;
1529/// # use validator::*;
1530/// let trunc = |t: Dec19x19| t.trunc_to(17);
1531/// check!( [|t| trunc(Dec19x19::unchecked_ln(t)), |t| Dec19x19::checked_ln(t).map(trunc)] {
1532///     (Dec19x19::MAX) =>  trunc(Dec19x19!(44.280_575_164_226_186_298_3)),
1533///     (Dec19x19!(10)) =>  trunc(Dec19x19!(2.302_585_092_994_045_684_0)),
1534///     (Dec19x19!(100)) => trunc(Dec19x19!(4.605_170_185_988_091_367_8)),
1535///     (Dec19x19!(0.1)) => trunc(Dec19x19!(-2.302_585_092_994_045_683_7)),
1536///     (Dec19x19!(2.718281828459045239)) => Dec19x19!(1),
1537///     (-Dec19x19::SMALLEST_STEP) => FAIL,
1538/// });
1539/// ```
1540impl UncheckedLn for Dec19x19 {
1541    #[track_caller]
1542    #[inline(always)]
1543    fn unchecked_ln(self) -> Self {
1544        debug_assert!(self.repr > 0);
1545
1546        // 1) lift into i256
1547        let mut v      = i256_from_i128(self.repr);
1548        let scale      = FRAC_SCALE_I256;  // = 10^19 in i256
1549        let two        = I256_TWO;
1550        let ln2        = LN_2_I256;
1551        let sqrt2_up   = SQRT2_UP_I256;    // = scale*√2
1552        let sqrt2_dn   = SQRT2_DN_I256;    // = scale/√2
1553
1554        // 2) range‑reduce v so that v ∈ [scale/√2, scale*√2]
1555        let mut exp = 0i128;
1556        while v > sqrt2_up {
1557            v /= two;
1558            exp += 1;
1559        }
1560        while v < sqrt2_dn {
1561            v *= two;
1562            exp -= 1;
1563        }
1564
1565        // 3) atanh trick: u = (v−scale)/(v+scale), scaled by `scale`
1566        let num = v - scale;
1567        let den = v + scale;
1568        let u = (num * scale) / den;
1569
1570        // 4) atanh-series: ln(v/scale) = 2·Σₖ [ u^(2k+1) / (2k+1) ]
1571        let mut u_pow = u;
1572        let mut sum   = u;
1573        let mut k     = 1i128;
1574        loop {
1575            // u_pow ← u_pow · u² / scale²
1576            u_pow = (u_pow * u / scale) * u / scale;
1577            k += 2;
1578            let term = u_pow / i256_from_i128(k);
1579            if term == i256::ZERO {
1580                break;
1581            }
1582            sum += term;
1583        }
1584        let ln_mant = sum * i256_from_i128(2);
1585
1586        // 5) add back exponent·ln(2)
1587        let result = ln_mant + ln2 * i256_from_i128(exp);
1588
1589        // 6) to Dec19x19, preserving your overflow‑checks cfg
1590        #[cfg(inherit_overflow_checks)]
1591        { Self::from_repr(i256_to_i128(result).expect("Overflow")) }
1592        #[cfg(not(inherit_overflow_checks))]
1593        { Self::from_repr(result.as_i128()) }
1594    }
1595}
1596
1597impl CheckedLn for Dec19x19 {
1598    #[track_caller]
1599    #[inline(always)]
1600    fn checked_ln(self) -> Option<Self> {
1601        (self.repr > 0).then(|| self.unchecked_ln())
1602    }
1603}
1604
1605// ===========
1606// === Pow ===
1607// ===========
1608
1609/// ```
1610/// # use fixed_num::*;
1611/// # use validator::*;
1612/// check! ( [Dec19x19::unchecked_pow, Dec19x19::checked_pow] {
1613///     // Identity and basic powers
1614///     (Dec19x19!(2), 0_i32) => Dec19x19!(1),
1615///     (Dec19x19!(2), 1_i32) => Dec19x19!(2),
1616///     (Dec19x19!(2), 3_i32) => Dec19x19!(8),
1617///     (Dec19x19!(2), 4_i32) => Dec19x19!(16),
1618///     (Dec19x19!(2), 5_i32) => Dec19x19!(32),
1619///     (Dec19x19!(2), 6_i32) => Dec19x19!(64),
1620///     (Dec19x19!(2), 7_i32) => Dec19x19!(128),
1621///     (Dec19x19!(2), 8_i32) => Dec19x19!(256),
1622///     (Dec19x19!(2), 9_i32) => Dec19x19!(512),
1623///     (Dec19x19!(2), 10_i32) => Dec19x19!(1024),
1624///     (Dec19x19!(2), 11_i32) => Dec19x19!(2048),
1625///     (Dec19x19!(2), 12_i32) => Dec19x19!(4096),
1626///     (Dec19x19!(2), 13_i32) => Dec19x19!(8192),
1627///     (Dec19x19!(2), 14_i32) => Dec19x19!(16384),
1628///     (Dec19x19!(2), 15_i32) => Dec19x19!(32768),
1629///     (Dec19x19!(2), 16_i32) => Dec19x19!(65536),
1630///
1631///     // Zero exponent
1632///     (Dec19x19!(20), 0) => Dec19x19!(1),
1633///
1634///     // Negative exponents
1635///     (Dec19x19!(2), -1_i32) => Dec19x19!(0.5),
1636///     (Dec19x19!(2), -2_i32) => Dec19x19!(0.25),
1637///
1638///     // Fractional bases
1639///     (Dec19x19!(0.5), 2_i32) => Dec19x19!(0.25),
1640///     (Dec19x19!(0.5), 3_i32) => Dec19x19!(0.125),
1641///     (Dec19x19!(0.5), -1_i32) => Dec19x19!(2.0),
1642///
1643///     // Fractional result rounding
1644///     (Dec19x19!(1.1), 2_i32) => Dec19x19!(1.21),
1645///     (Dec19x19!(1.5), 2_i32) => Dec19x19!(2.25),
1646///
1647///     // Larger integer base
1648///     (Dec19x19!(10), 3_i32) => Dec19x19!(1000),
1649///
1650///     (Dec19x19::MAX, -1_i32) => Dec19x19!(0),
1651///
1652///     (Dec19x19!(2), 63_i32) => Dec19x19!(9_223_372_036_854_775_808),
1653///     (Dec19x19!(2), 64) => FAIL,
1654///
1655///     (Dec19x19!(0), -1_i32) => FAIL,
1656///     (Dec19x19::MAX, 2_i32) => FAIL,
1657///     (Dec19x19::MIN, 2_i32) => FAIL,
1658/// });
1659///```
1660impl UncheckedPow<i32> for Dec19x19 {
1661    type Output = Self;
1662    #[track_caller]
1663    #[inline(always)]
1664    fn unchecked_pow(self, exp: i32) -> Self::Output {
1665        let mut result = Dec19x19!(1);
1666        let mut base   = if exp >= 0 { self } else { Dec19x19!(1) / self };
1667        let mut e      = exp.unsigned_abs();
1668        macro_rules! step {() => {
1669            let e2 = e / 2;
1670            let f2 = e % 2;
1671            if f2 == 1 {
1672                result *= base;
1673            }
1674            e = e2;
1675        };}
1676        if e > 0 { step!(); }
1677        while e > 0 {
1678            base = base * base;
1679            step!();
1680        }
1681        result
1682    }
1683}
1684
1685impl CheckedPow<i32> for Dec19x19 {
1686    type Output = Self;
1687    #[track_caller]
1688    #[inline(always)]
1689    fn checked_pow(self, exp: i32) -> Option<Self::Output> {
1690        let mut result = Dec19x19!(1);
1691        let mut base   = if exp >= 0 { self } else { Dec19x19!(1) / self };
1692        let mut e      = exp.unsigned_abs();
1693        macro_rules! step {() => {
1694            let e2 = e / 2;
1695            let f2 = e % 2;
1696            if f2 == 1 {
1697                result = result.checked_mul(base)?;
1698            }
1699            e = e2;
1700        };}
1701        if e > 0 { step!(); }
1702        while e > 0 {
1703            base = base.checked_mul(base)?;
1704            step!();
1705        }
1706        Some(result)
1707    }
1708}
1709
1710// =================================
1711// === Conversions X -> Dec19x19 ===
1712// =================================
1713
1714macro_rules! gen_from_x_for_fix128 {
1715    ($($i:ident),* $(,)?) => { paste! {
1716        $(
1717            impl From<$i> for Dec19x19 {
1718                #[track_caller]
1719                #[inline(always)]
1720                fn from(value: $i) -> Self {
1721                    Self::[<from_ $i>](value)
1722                }
1723            }
1724
1725            impl Dec19x19 {
1726                #[track_caller]
1727                #[inline(always)]
1728                pub const fn [<from_ $i>](value: $i) -> Self {
1729                    Self { repr: value as i128 * FRAC_SCALE_I128 }
1730                }
1731            }
1732        )*
1733    }};
1734}
1735
1736macro_rules! gen_fn_try_from_x_for_fix128 {
1737    ($($i:ident),* $(,)?) => { paste! {
1738        $(
1739            impl Dec19x19 {
1740                #[track_caller]
1741                #[inline(always)]
1742                pub fn [<try_from_ $i>](value: $i) -> Result<Self, <Self as TryFrom<$i>>::Error> {
1743                    value.try_into()
1744                }
1745            }
1746        )*
1747    }};
1748}
1749
1750// Creates a new `Dec19x19` from the given `i64` integer, assuming it has no fractional part.
1751// It is safe, as i64 has at most 19 digits.
1752gen_from_x_for_fix128! { i64, i32, i16, i8, u32, u16, u8 }
1753gen_fn_try_from_x_for_fix128!{ i128, u64, u128, f32, f64 }
1754
1755impl TryFrom<i128> for Dec19x19 {
1756    type Error = &'static str;
1757    #[track_caller]
1758    #[inline(always)]
1759    fn try_from(value: i128) -> Result<Self, Self::Error> {
1760        let err = "Overflow: Value too large to store in Dec19x19.";
1761        let repr = value.checked_mul(FRAC_SCALE_I128).ok_or(err)?;
1762        Ok(Self { repr })
1763    }
1764}
1765
1766impl TryFrom<u64> for Dec19x19 {
1767    type Error = &'static str;
1768    #[track_caller]
1769    #[inline(always)]
1770    fn try_from(value: u64) -> Result<Self, Self::Error> {
1771        (value as i128).try_into()
1772    }
1773}
1774
1775impl TryFrom<u128> for Dec19x19 {
1776    type Error = &'static str;
1777    #[track_caller]
1778    #[inline(always)]
1779    fn try_from(value: u128) -> Result<Self, Self::Error> {
1780        let err = "Overflow: Value too large to store in Dec19x19.";
1781        i128::try_from(value).ok().ok_or(err)?.try_into()
1782    }
1783}
1784
1785impl TryFrom<f64> for Dec19x19 {
1786    type Error = &'static str;
1787    #[track_caller]
1788    #[inline(always)]
1789    fn try_from(value: f64) -> Result<Self, Self::Error> {
1790        let err_nan = "Cannot convert NaN or infinite value to Dec19x19.";
1791        let err_overflow = "Overflow: Value too large to store in Dec19x19.";
1792        let err_underflow = "Underflow: Value too small to store in Dec19x19.";
1793        let scaled = value * FRAC_SCALE_I128 as f64;
1794        let repr_f64 = scaled.round();
1795        if !repr_f64.is_finite() { return Err(err_nan); }
1796        if repr_f64 > i128::MAX as f64 { return Err(err_overflow); }
1797        if repr_f64 < i128::MIN as f64 { return Err(err_underflow); }
1798        Ok(Self { repr: repr_f64 as i128 })
1799    }
1800}
1801
1802impl TryFrom<f32> for Dec19x19 {
1803    type Error = &'static str;
1804    #[track_caller]
1805    #[inline(always)]
1806    fn try_from(value: f32) -> Result<Self, Self::Error>  {
1807        (value as f64).try_into()
1808    }
1809}
1810
1811// =================================
1812// === Conversions Dec19x19 -> X ===
1813// =================================
1814
1815macro_rules! gen_from_fix128_for_x {
1816    ($($i:ident),* $(,)?) => {
1817        $(
1818            impl From<Dec19x19> for $i {
1819                #[track_caller]
1820                #[inline(always)]
1821                #[allow(trivial_numeric_casts)]
1822                fn from(value: Dec19x19) -> Self {
1823                    (value.repr / FRAC_SCALE_I128) as Self
1824                }
1825            }
1826        )*
1827    };
1828}
1829
1830macro_rules! gen_fn_from_fix128_for_x {
1831    ($($i:ident),* $(,)?) => { paste! {
1832        $(
1833            impl Dec19x19 {
1834                #[track_caller]
1835                #[inline(always)]
1836                pub fn [<into_ $i>](self) -> $i {
1837                    self.into()
1838                }
1839            }
1840        )*
1841    }};
1842}
1843
1844gen_from_fix128_for_x! { u64, i128, u128 }
1845gen_fn_from_fix128_for_x! { u64, i128, u128, f64, f32 }
1846
1847macro_rules! gen_try_from_fix128_for_x {
1848    ($($i:ident),* $(,)?) => {
1849        $(
1850            impl TryFrom<Dec19x19> for $i {
1851                type Error = &'static str;
1852                #[track_caller]
1853                #[inline(always)]
1854                fn try_from(value: Dec19x19) -> Result<Self, Self::Error> {
1855                    let val = value.repr / FRAC_SCALE_I128;
1856                    if val > $i::MAX as i128 || val < $i::MIN as i128 {
1857                        return Err("Overflow: Dec19x19 too large or too small.");
1858                    }
1859                    Ok(val as $i)
1860                }
1861            }
1862        )*
1863    };
1864}
1865
1866macro_rules! gen_fn_try_from_fix128_for_x {
1867    ($($i:ident),* $(,)?) => { paste! {
1868        $(
1869            impl Dec19x19 {
1870                #[track_caller]
1871                #[inline(always)]
1872                pub fn [<try_into_ $i>](self) -> Result<$i, <$i as TryFrom<Self>>::Error> {
1873                    self.try_into()
1874                }
1875            }
1876        )*
1877    }};
1878}
1879
1880gen_try_from_fix128_for_x! { i64, u32, i32, u16, i16, u8, i8 }
1881gen_fn_try_from_fix128_for_x! { i64, u32, i32, u16, i16, u8, i8 }
1882
1883impl From<Dec19x19> for f64 {
1884    #[track_caller]
1885    #[inline(always)]
1886    fn from(value: Dec19x19) -> Self {
1887        let int_part = (value.repr / FRAC_SCALE_I128) as Self;
1888        let frac_part = (value.repr % FRAC_SCALE_I128) as Self / FRAC_SCALE_I128 as Self;
1889        int_part + frac_part
1890    }
1891}
1892
1893impl From<Dec19x19> for f32 {
1894    #[track_caller]
1895    #[inline(always)]
1896    fn from(value: Dec19x19) -> Self {
1897        f64::from(value) as Self
1898    }
1899}
1900
1901// ===========================
1902// === Parsing and Display ===
1903// ===========================
1904
1905/// # Tests
1906///
1907/// ```
1908/// # use fixed_num::*;
1909/// # use validator::*;
1910/// use std::str::FromStr;
1911/// assert_eq!(Dec19x19!(17_014_118_346_046_923_173.168_730_371_588_410_572_7).repr, i128::MAX);
1912/// assert_eq!(Dec19x19!(-17_014_118_346_046_923_173.168_730_371_588_410_572_8).repr, i128::MIN);
1913/// assert_eq!(Dec19x19!(987e-19), Dec19x19!(0.000_000_000_000_000_098_7));
1914/// assert_eq!(Dec19x19!(987e-2), Dec19x19!(9.87));
1915/// assert_eq!(Dec19x19!(987e-1), Dec19x19!(98.7));
1916/// assert_eq!(Dec19x19!(987e-0), Dec19x19!(987));
1917/// assert_eq!(Dec19x19!(987e0), Dec19x19!(987));
1918/// assert_eq!(Dec19x19!(987e+0), Dec19x19!(987));
1919/// assert_eq!(Dec19x19!(987e+1), Dec19x19!(9_870));
1920/// assert_eq!(Dec19x19!(987e+2), Dec19x19!(98_700));
1921/// assert_eq!(Dec19x19!(987e16), Dec19x19!(9_870_000_000_000_000_000));
1922/// assert_eq!(Dec19x19!(1_000_000_000_000_000e-34), Dec19x19::SMALLEST_STEP);
1923/// assert_eq!(Dec19x19!(0.000_000_000_000_000e34), Dec19x19!(0));
1924/// assert!(Dec19x19::from_str("17_014_118_346_046_923_173.168_730_371_588_410_572_8").is_err());
1925/// assert!(Dec19x19::from_str("-17_014_118_346_046_923_173.168_730_371_588_410_572_9").is_err());
1926/// assert!(Dec19x19::from_str("987e+17").is_err());
1927/// assert!(Dec19x19::from_str("987e-20").is_err());
1928/// ```
1929impl FromStr for Dec19x19 {
1930    type Err = ParseDec19x19Error;
1931    fn from_str(s: &str) -> Result<Self, Self::Err> {
1932        let repr = parse_dec19x19_internal(s)?;
1933        Ok(Self { repr })
1934    }
1935}
1936
1937impl<'t> TryFrom<&'t str> for Dec19x19 {
1938    type Error = ParseDec19x19Error;
1939    fn try_from(s: &'t str) -> Result<Self, Self::Error> {
1940        Self::from_str(s)
1941    }
1942}
1943
1944impl<'t> TryFrom<&'t String> for Dec19x19 {
1945    type Error = ParseDec19x19Error;
1946    fn try_from(s: &'t String) -> Result<Self, Self::Error> {
1947        Self::from_str(s)
1948    }
1949}
1950
1951impl TryFrom<String> for Dec19x19 {
1952    type Error = ParseDec19x19Error;
1953    fn try_from(s: String) -> Result<Self, Self::Error> {
1954        Self::from_str(&s)
1955    }
1956}
1957
1958impl std::fmt::Display for Dec19x19 {
1959    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1960        let separator = f.alternate().then_some('_');
1961        let mut formatter = Formatter {
1962            separator,
1963            precision: f.precision(),
1964            width: f.width(),
1965            align: f.align(),
1966            fill: f.fill(),
1967            sign_plus: f.sign_plus(),
1968        };
1969        write!(f, "{}", self.format(&mut formatter))
1970    }
1971}
1972
1973impl std::fmt::Debug for Dec19x19 {
1974    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1975        std::fmt::Display::fmt(self, f)
1976    }
1977}
1978
1979// Tested in README.md.
1980impl Format for Dec19x19 {
1981    fn format(&self, f: &mut Formatter) -> String {
1982        let this = f.precision.map_or(*self, |p| self.round_to(p.min(19) as i64));
1983        let int_part = this.repr / FRAC_SCALE_I128;
1984        let frac_part = (this.repr % FRAC_SCALE_I128).abs();
1985
1986        let mut frac_str = format!("{:0width$}", frac_part, width = FRAC_PLACES as usize)
1987            .trim_end_matches('0')
1988            .to_string();
1989
1990        if let Some(prec) = f.precision {
1991            if frac_str.len() < prec {
1992                let zeros_needed = prec - frac_str.len();
1993                frac_str.push_str(&"0".repeat(zeros_needed));
1994            }
1995        }
1996
1997        let int_str = int_part.abs().to_string();
1998        let sign_len = 1;
1999        let int_str_len = int_str.len();
2000        let int_len = int_str_len + int_str_len / 3;
2001        let frac_len = frac_str.len() + frac_str.len() / 3;
2002        let mut result = String::with_capacity(sign_len + int_len + frac_len + 1);
2003        if this.repr < 0 {
2004            result.push('-');
2005        } else if f.sign_plus {
2006            result.push('+');
2007        }
2008
2009        for (i, c) in int_str.chars().enumerate() {
2010            let j = int_str_len - i;
2011            if i != 0 && j > 0 && j % 3 == 0 {
2012                if let Some(sep) = f.separator {
2013                    result.push(sep);
2014                }
2015            }
2016            result.push(c);
2017        }
2018
2019        if !frac_str.is_empty() {
2020            result.push('.');
2021            for (i, c) in frac_str.chars().enumerate() {
2022                if i > 0 && i % 3 == 0 {
2023                    if let Some(sep) = f.separator {
2024                        result.push(sep);
2025                    }
2026                }
2027                result.push(c);
2028            }
2029        }
2030
2031        if let Some(width) = f.width {
2032            let fill = f.fill.to_string();
2033            let padding = width.saturating_sub(result.len());
2034            match f.align {
2035                Some(std::fmt::Alignment::Right) => result.push_str(&fill.repeat(padding)),
2036                Some(std::fmt::Alignment::Center) => {
2037                    let left_padding = padding / 2;
2038                    let right_padding = padding - left_padding;
2039                    result.insert_str(0, &fill.repeat(left_padding));
2040                    result.push_str(&fill.repeat(right_padding));
2041                }
2042                _ => result.insert_str(0, &fill.repeat(padding)),
2043            }
2044        }
2045
2046        result
2047    }
2048}