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}