1extern crate alloc;
2
3#[cfg(not(feature = "std"))]
4use alloc::vec;
5use core::{cmp::Ordering, fmt::Display, ops::*, str::FromStr};
6use num_bigint::{BigInt, BigUint, Sign};
7use num_integer::Integer;
8use num_traits::{One, Signed, ToPrimitive, Zero};
9use quoth::Parsable;
10
11#[cfg(test)]
12use alloc::format;
13use alloc::vec::Vec;
14use lencode::dedupe::{DedupeDecoder, DedupeEncoder};
15#[cfg(test)]
16use lencode::io::Cursor;
17use lencode::io::{Error, Read, Write};
18use lencode::{Decode, Encode};
19#[cfg(test)]
20use std::time::{Duration, Instant};
21
22use crate::parsing::ParsedSafeInt;
23
24#[derive(Clone, Debug, Eq, Ord, Hash, Default, PartialEq, PartialOrd)]
38#[repr(transparent)]
39pub struct SafeInt(BigInt);
40
41pub const DEFAULT_MAX_ITERS: usize = 4_096;
44const MAX_EXACT_EXPONENT: u32 = 1_024;
45
46impl FromStr for SafeInt {
47 type Err = quoth::Error;
48
49 fn from_str(s: &str) -> Result<Self, Self::Err> {
50 let mut stream = quoth::ParseStream::from(s);
51 let parsed = ParsedSafeInt::parse(&mut stream)?;
52 Ok(parsed.value)
53 }
54}
55
56impl Display for SafeInt {
57 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
58 write!(f, "{}", self.0)
59 }
60}
61
62impl SafeInt {
63 pub fn zero() -> SafeInt {
65 SafeInt(BigInt::zero())
66 }
67 pub fn one() -> SafeInt {
69 SafeInt(BigInt::one())
70 }
71 pub fn neg_one() -> SafeInt {
73 -SafeInt::one()
74 }
75 pub const ONE: ConstSafeInt<2> = ConstSafeInt::from_bytes([0, 1]);
77 pub const NEG_ONE: ConstSafeInt<2> = ConstSafeInt::from_bytes([1, 1]);
79
80 #[inline(always)]
82 pub const fn raw(&self) -> &BigInt {
83 &self.0
84 }
85
86 #[inline(always)]
88 pub const fn from_raw(value: BigInt) -> SafeInt {
89 SafeInt(value)
90 }
91
92 #[inline(always)]
94 pub fn is_negative(&self) -> bool {
95 self.0.sign() == Sign::Minus
96 }
97
98 #[inline(always)]
100 pub fn is_even(&self) -> bool {
101 self.0.is_even()
102 }
103
104 #[inline(always)]
106 pub fn is_odd(&self) -> bool {
107 self.0.is_odd()
108 }
109
110 #[inline(always)]
112 pub fn is_zero(&self) -> bool {
113 self.0.is_zero()
114 }
115
116 #[inline(always)]
118 pub fn abs(self) -> SafeInt {
119 SafeInt(self.0.abs())
120 }
121
122 #[inline(always)]
124 pub fn pow(self, exp: u32) -> SafeInt {
125 SafeInt(self.0.pow(exp))
126 }
127
128 #[inline(always)]
131 pub fn div_rem(self, other: SafeInt) -> Option<(SafeInt, SafeInt)> {
132 if other.0.is_zero() {
133 None
134 } else {
135 let (div, rem) = self.0.div_rem(&other.0);
136 Some((SafeInt(div), SafeInt(rem)))
137 }
138 }
139
140 #[inline(always)]
142 pub fn to_u8(&self) -> Option<u8> {
143 self.0.to_u8()
144 }
145
146 #[inline(always)]
148 pub fn to_u16(&self) -> Option<u16> {
149 self.0.to_u16()
150 }
151
152 #[inline(always)]
154 pub fn to_u32(&self) -> Option<u32> {
155 self.0.to_u32()
156 }
157
158 #[inline(always)]
160 pub fn to_u64(&self) -> Option<u64> {
161 self.0.to_u64()
162 }
163
164 #[inline(always)]
166 pub fn to_u128(&self) -> Option<u128> {
167 self.0.to_u128()
168 }
169
170 #[inline(always)]
172 pub fn to_i8(&self) -> Option<i8> {
173 self.0.to_i8()
174 }
175
176 #[inline(always)]
178 pub fn to_i16(&self) -> Option<i16> {
179 self.0.to_i16()
180 }
181
182 #[inline(always)]
184 pub fn to_i32(&self) -> Option<i32> {
185 self.0.to_i32()
186 }
187
188 #[inline(always)]
190 pub fn to_i64(&self) -> Option<i64> {
191 self.0.to_i64()
192 }
193
194 #[inline(always)]
196 pub fn to_i128(&self) -> Option<i128> {
197 self.0.to_i128()
198 }
199
200 #[inline(always)]
202 pub fn to_usize(&self) -> Option<usize> {
203 self.0.to_usize()
204 }
205
206 #[inline(always)]
208 pub fn to_isize(&self) -> Option<isize> {
209 self.0.to_isize()
210 }
211
212 #[inline(always)]
214 pub fn ceil_div(&self, b: SafeInt) -> Option<SafeInt> {
215 let one = SafeInt::from(1);
216 Some(((self - one.clone()) / b)? + one)
217 }
218
219 pub fn pow_ratio_scaled(
244 base_numerator: &SafeInt,
245 base_denominator: &SafeInt,
246 exponent_numerator: &SafeInt,
247 exponent_denominator: &SafeInt,
248 precision: u32,
249 scale: &SafeInt,
250 ) -> Option<SafeInt> {
251 Self::pow_ratio_scaled_with_max_iters(
252 base_numerator,
253 base_denominator,
254 exponent_numerator,
255 exponent_denominator,
256 precision,
257 scale,
258 None,
259 )
260 }
261
262 pub fn pow_ratio_scaled_with_max_iters(
266 base_numerator: &SafeInt,
267 base_denominator: &SafeInt,
268 exponent_numerator: &SafeInt,
269 exponent_denominator: &SafeInt,
270 precision: u32,
271 scale: &SafeInt,
272 max_iters: Option<usize>,
273 ) -> Option<SafeInt> {
274 if base_denominator.is_zero() || exponent_denominator.is_zero() {
275 return None;
276 }
277 if base_numerator.is_zero() {
278 return Some(SafeInt::zero());
279 }
280 if scale.is_negative() {
281 return None;
282 }
283 if base_numerator.is_negative() || base_denominator.is_negative() {
285 return None;
286 }
287
288 let base_num = base_numerator.0.to_biguint()?;
289 let base_den = base_denominator.0.to_biguint()?;
290 let mut exp_num = exponent_numerator.0.to_biguint()?;
291 let mut exp_den = exponent_denominator.0.to_biguint()?;
292
293 if exp_num.is_zero() {
294 return Some(scale.clone());
295 }
296
297 let g = gcd_biguint(exp_num.clone(), exp_den.clone());
298 if g > BigUint::one() {
299 exp_num /= g.clone();
300 exp_den /= g;
301 }
302
303 let scale_abs = scale.0.to_biguint()?;
304 let scale_bits = u32::try_from(scale_abs.bits()).unwrap_or(u32::MAX);
305
306 let exp_num_bits = exp_num.bits();
307 let exp_den_bits = exp_den.bits();
308 if exp_num_bits <= 32 && exp_den_bits <= 32 {
309 let exp_num_u32 = exp_num.to_u32()?;
310 let exp_den_u32 = exp_den.to_u32()?;
311 if exp_den_u32 == 0 {
312 return None;
313 }
314
315 if exp_num_u32 <= MAX_EXACT_EXPONENT && exp_den_u32 <= MAX_EXACT_EXPONENT {
316 let base_num_pow = base_num.pow(exp_num_u32);
317 let base_den_pow = base_den.pow(exp_num_u32);
318 let scale_pow = scale_abs.pow(exp_den_u32);
319
320 let target_num = base_num_pow * scale_pow;
321 let target_den = base_den_pow;
322
323 let root = nth_root_ratio_floor(&target_num, &target_den, exp_den_u32);
324 return Some(SafeInt(BigInt::from_biguint(Sign::Plus, root)));
325 }
326 }
327
328 let requested_precision = precision.max(32).max(scale_bits.saturating_add(8));
335 let guard_bits: u32 = 24;
336 let internal_precision = requested_precision.saturating_add(guard_bits);
337 let default_max_iters = DEFAULT_MAX_ITERS.min(internal_precision as usize + 128);
338 let max_iters = max_iters.unwrap_or(default_max_iters).max(1);
339
340 let target_scale_uint = BigUint::one() << requested_precision;
341 let guard_factor_uint = BigUint::one() << guard_bits;
342 let internal_scale_uint = &target_scale_uint << guard_bits;
343
344 let target_scale = BigInt::from_biguint(Sign::Plus, target_scale_uint.clone());
345 let guard_factor = BigInt::from_biguint(Sign::Plus, guard_factor_uint.clone());
346 let internal_scale = BigInt::from_biguint(Sign::Plus, internal_scale_uint.clone());
347
348 let ln_half = ln1p_fixed(
349 &(-(&internal_scale >> 1usize)),
350 &internal_scale,
351 &guard_factor,
352 max_iters,
353 );
354 let ln_two = -ln_half;
355
356 let ln_num = ln_biguint(
359 &base_num,
360 internal_precision,
361 &internal_scale_uint,
362 &internal_scale,
363 &guard_factor,
364 &ln_two,
365 max_iters,
366 );
367 let ln_den = ln_biguint(
368 &base_den,
369 internal_precision,
370 &internal_scale_uint,
371 &internal_scale,
372 &guard_factor,
373 &ln_two,
374 max_iters,
375 );
376 let ln_base = ln_num - ln_den;
377
378 let ln_scaled = (ln_base * BigInt::from_biguint(Sign::Plus, exp_num))
379 .div_floor(&BigInt::from_biguint(Sign::Plus, exp_den));
380 let exp_fp = exp_fixed(&ln_scaled, &internal_scale, &guard_factor, max_iters);
381 let exp_requested = round_to_precision(&exp_fp, &guard_factor);
382 let result =
383 (exp_requested * BigInt::from_biguint(Sign::Plus, scale_abs)).div_floor(&target_scale);
384
385 Some(SafeInt(result))
386 }
387
388 pub fn pow_bigint_base(
391 base: &SafeInt,
392 exponent_numerator: &SafeInt,
393 exponent_denominator: &SafeInt,
394 precision: u32,
395 scale: &SafeInt,
396 ) -> Option<SafeInt> {
397 Self::pow_bigint_base_scaled_with_max_iters(
398 base,
399 exponent_numerator,
400 exponent_denominator,
401 precision,
402 scale,
403 None,
404 )
405 }
406
407 fn pow_bigint_base_scaled_with_max_iters(
408 base: &SafeInt,
409 exponent_numerator: &SafeInt,
410 exponent_denominator: &SafeInt,
411 precision: u32,
412 scale: &SafeInt,
413 max_iters: Option<usize>,
414 ) -> Option<SafeInt> {
415 use num_bigint::{BigInt, BigUint, Sign};
416 use num_integer::Integer;
417 use num_traits::{One, ToPrimitive, Zero};
418
419 if exponent_denominator.is_zero() {
421 return None;
422 }
423 if base.is_zero() {
424 return Some(SafeInt::zero());
427 }
428 if scale.is_negative() {
429 return None;
430 }
431 if base.is_negative() {
433 return None;
434 }
435
436 let base_uint = base.0.to_biguint()?;
438
439 let mut exp_num = exponent_numerator.0.to_biguint()?;
440 let mut exp_den = exponent_denominator.0.to_biguint()?;
441
442 if exp_num.is_zero() {
443 return Some(scale.clone());
445 }
446
447 let g = gcd_biguint(exp_num.clone(), exp_den.clone());
449 if g > BigUint::one() {
450 exp_num /= g.clone();
451 exp_den /= g;
452 }
453
454 let scale_abs = scale.0.to_biguint()?;
455 let scale_bits = u32::try_from(scale_abs.bits()).unwrap_or(u32::MAX);
456
457 let exp_num_bits = exp_num.bits();
459 let exp_den_bits = exp_den.bits();
460 if exp_num_bits <= 32 && exp_den_bits <= 32 {
461 let exp_num_u32 = exp_num.to_u32()?;
462 let exp_den_u32 = exp_den.to_u32()?;
463 if exp_den_u32 == 0 {
464 return None;
465 }
466
467 if exp_num_u32 <= MAX_EXACT_EXPONENT && exp_den_u32 <= MAX_EXACT_EXPONENT {
468 let base_pow = base_uint.pow(exp_num_u32);
475 let scale_pow = scale_abs.pow(exp_den_u32);
476
477 let target_num = base_pow * scale_pow;
478 let target_den = BigUint::one();
479
480 let root = nth_root_ratio_floor(&target_num, &target_den, exp_den_u32);
481 return Some(SafeInt(BigInt::from_biguint(Sign::Plus, root)));
482 }
483 }
484
485 let requested_precision = precision.max(32).max(scale_bits.saturating_add(8));
489 let guard_bits: u32 = 24;
490 let internal_precision = requested_precision.saturating_add(guard_bits);
491 let default_max_iters = DEFAULT_MAX_ITERS.min(internal_precision as usize + 128);
492 let max_iters = max_iters.unwrap_or(default_max_iters).max(1);
493
494 let target_scale_uint = BigUint::one() << requested_precision;
495 let guard_factor_uint = BigUint::one() << guard_bits;
496 let internal_scale_uint = &target_scale_uint << guard_bits;
497
498 let target_scale = BigInt::from_biguint(Sign::Plus, target_scale_uint.clone());
499 let guard_factor = BigInt::from_biguint(Sign::Plus, guard_factor_uint.clone());
500 let internal_scale = BigInt::from_biguint(Sign::Plus, internal_scale_uint.clone());
501
502 let ln_half = ln1p_fixed(
504 &(-(&internal_scale >> 1usize)),
505 &internal_scale,
506 &guard_factor,
507 max_iters,
508 );
509 let ln_two = -ln_half;
510
511 let ln_base = ln_biguint(
513 &base_uint,
514 internal_precision,
515 &internal_scale_uint,
516 &internal_scale,
517 &guard_factor,
518 &ln_two,
519 max_iters,
520 );
521
522 let ln_scaled = (ln_base * BigInt::from_biguint(Sign::Plus, exp_num))
524 .div_floor(&BigInt::from_biguint(Sign::Plus, exp_den));
525
526 let exp_fp = exp_fixed(&ln_scaled, &internal_scale, &guard_factor, max_iters);
528
529 let exp_requested = round_to_precision(&exp_fp, &guard_factor);
531
532 let result =
534 (exp_requested * BigInt::from_biguint(Sign::Plus, scale_abs)).div_floor(&target_scale);
535
536 Some(SafeInt(result))
537 }
538
539 #[inline(always)]
541 pub fn log10(
542 &self,
543 scale: &SafeInt,
544 precision: u32,
545 max_iters: Option<usize>,
546 ) -> Option<SafeInt> {
547 if self.is_negative() || self.is_zero() {
548 None
549 } else if *self < 10 {
550 Some(SafeInt::from(0))
551 } else {
552 let scale_abs = scale.0.to_biguint()?;
553 let scale_bits = u32::try_from(scale_abs.bits()).unwrap_or(u32::MAX);
554 let requested_precision = precision.max(32).max(scale_bits.saturating_add(8));
555 let guard_bits: u32 = 24;
556 let internal_precision = requested_precision.saturating_add(guard_bits);
557 let target_scale_uint = BigUint::one() << requested_precision;
558 let internal_scale_uint = &target_scale_uint << guard_bits;
559 let guard_factor_uint = BigUint::one() << guard_bits;
560 let guard_factor = BigInt::from_biguint(Sign::Plus, guard_factor_uint.clone());
561 let internal_scale = BigInt::from_biguint(Sign::Plus, internal_scale_uint.clone());
562 let default_max_iters = DEFAULT_MAX_ITERS.min(internal_precision as usize + 128);
563 let max_iters = max_iters.unwrap_or(default_max_iters).max(1);
564 let ln_half = ln1p_fixed(
565 &(-(&internal_scale >> 1usize)),
566 &internal_scale,
567 &guard_factor,
568 max_iters,
569 );
570 let ln_two = -ln_half;
571
572 let value_uint = self.0.to_biguint()?;
573 let ln_value = ln_biguint(
574 &value_uint,
575 internal_precision,
576 &internal_scale_uint,
577 &internal_scale,
578 &guard_factor,
579 &ln_two,
580 max_iters,
581 );
582 let ten_uint = BigUint::from(10u32);
583 let ln_ten = ln_biguint(
584 &ten_uint,
585 internal_precision,
586 &internal_scale_uint,
587 &internal_scale,
588 &guard_factor,
589 &ln_two,
590 max_iters,
591 );
592
593 let ln_value = SafeInt::from(ln_value);
595 let ln_ten = SafeInt::from(ln_ten);
596 ln_value / ln_ten
597 }
598 }
599}
600
601fn gcd_biguint(mut a: BigUint, mut b: BigUint) -> BigUint {
602 while !b.is_zero() {
603 let r = &a % &b;
604 a = b;
605 b = r;
606 }
607 a
608}
609
610fn pow_biguint(base: &BigUint, exp: u32) -> BigUint {
611 base.pow(exp)
612}
613
614fn nth_root_ratio_floor(target_num: &BigUint, target_den: &BigUint, q: u32) -> BigUint {
615 if q == 0 {
616 return BigUint::zero();
617 }
618
619 let mut low = BigUint::zero();
620 let mut high = BigUint::one();
621 while pow_biguint(&high, q) * target_den <= *target_num {
622 high <<= 1;
623 }
624
625 while low < high {
626 let mid = (&low + &high + 1u32) >> 1;
627 if pow_biguint(&mid, q) * target_den <= *target_num {
628 low = mid;
629 } else {
630 high = mid - BigUint::one();
631 }
632 }
633
634 low
635}
636
637fn ln1p_fixed(x_fp: &BigInt, scale: &BigInt, guard_factor: &BigInt, max_iters: usize) -> BigInt {
638 let mut term = x_fp.clone();
641 let mut result = term.clone();
642 let mut prev_rounded = round_to_precision(&result, guard_factor);
643 for n in 2..=max_iters {
644 term = (&term * x_fp).div_floor(scale);
645 if term.is_zero() {
646 break;
647 }
648
649 let next = term.div_floor(&BigInt::from(n as u32));
650 if next.is_zero() {
651 break;
652 }
653
654 if n % 2 == 0 {
655 result -= &next;
656 } else {
657 result += &next;
658 }
659
660 let rounded = round_to_precision(&result, guard_factor);
661 if next.abs() < guard_factor.abs() || rounded == prev_rounded {
662 break;
663 }
664 prev_rounded = rounded;
665 }
666
667 result
668}
669
670fn exp_fixed(x_fp: &BigInt, scale: &BigInt, guard_factor: &BigInt, max_iters: usize) -> BigInt {
671 let mut term = scale.clone(); let mut result = term.clone();
675 let mut prev_rounded = round_to_precision(&result, guard_factor);
676 for n in 1..=max_iters {
677 term = (&term * x_fp).div_floor(&(scale * BigInt::from(n as u32)));
678 if term.is_zero() {
679 break;
680 }
681 result += &term;
682
683 let rounded = round_to_precision(&result, guard_factor);
684 if term.abs() < guard_factor.abs() || rounded == prev_rounded {
685 break;
686 }
687 prev_rounded = rounded;
688 }
689
690 result
691}
692
693fn ln_biguint(
694 value: &BigUint,
695 internal_precision: u32,
696 internal_scale_uint: &BigUint,
697 internal_scale: &BigInt,
698 guard_factor: &BigInt,
699 ln_two: &BigInt,
700 max_iters: usize,
701) -> BigInt {
702 debug_assert!(!value.is_zero());
703 if value.is_zero() {
704 return BigInt::zero();
705 }
706
707 let int_prec = internal_precision as usize;
708 let mut shift = value.bits().saturating_sub(1);
709 let mut mantissa = value.clone() << int_prec;
710 mantissa >>= shift;
711
712 let half_scale = internal_scale_uint >> 1;
714 let scale_plus_half = internal_scale_uint + &half_scale;
715 if mantissa >= scale_plus_half {
716 mantissa >>= 1;
717 shift = shift.saturating_add(1);
718 }
719
720 let mantissa_int = BigInt::from_biguint(Sign::Plus, mantissa);
721 let ln_mantissa = ln1p_fixed(
722 &(mantissa_int - internal_scale),
723 internal_scale,
724 guard_factor,
725 max_iters,
726 );
727
728 ln_mantissa + ln_two * BigInt::from(shift)
729}
730
731fn round_to_precision(value: &BigInt, guard_factor: &BigInt) -> BigInt {
732 let (mut truncated, remainder) = value.div_rem(guard_factor);
733 if !remainder.is_zero() && (remainder.abs() << 1) >= guard_factor.abs() {
734 truncated += remainder.signum();
735 }
736 truncated
737}
738
739impl Neg for SafeInt {
740 type Output = SafeInt;
741
742 #[inline(always)]
743 fn neg(self) -> SafeInt {
744 SafeInt(-self.0)
745 }
746}
747
748impl Neg for &SafeInt {
749 type Output = SafeInt;
750
751 #[inline(always)]
752 fn neg(self) -> SafeInt {
753 SafeInt(-self.0.clone())
754 }
755}
756
757macro_rules! impl_pair_ops {
758 ($trait:ident, $method:ident) => {
759 impl $trait for SafeInt {
760 type Output = SafeInt;
761
762 #[inline(always)]
763 fn $method(self, other: SafeInt) -> SafeInt {
764 SafeInt(self.0.$method(other.0))
765 }
766 }
767
768 impl $trait<&SafeInt> for SafeInt {
769 type Output = SafeInt;
770
771 #[inline(always)]
772 fn $method(self, other: &SafeInt) -> SafeInt {
773 SafeInt(self.0.$method(&other.0))
774 }
775 }
776
777 impl $trait<SafeInt> for &SafeInt {
778 type Output = SafeInt;
779
780 #[inline(always)]
781 fn $method(self, other: SafeInt) -> SafeInt {
782 SafeInt(self.0.clone().$method(other.0))
783 }
784 }
785
786 impl $trait<&SafeInt> for &SafeInt {
787 type Output = SafeInt;
788
789 #[inline(always)]
790 fn $method(self, other: &SafeInt) -> SafeInt {
791 SafeInt(self.0.clone().$method(&other.0))
792 }
793 }
794 };
795}
796
797macro_rules! impl_pair_rem_ops {
798 () => {
799 impl Rem for SafeInt {
800 type Output = Option<SafeInt>;
801
802 #[inline(always)]
803 fn rem(self, other: SafeInt) -> Option<SafeInt> {
804 if other.0.is_zero() {
805 None
806 } else {
807 Some(SafeInt(self.0 % other.0))
808 }
809 }
810 }
811
812 impl Rem<&SafeInt> for SafeInt {
813 type Output = Option<SafeInt>;
814
815 #[inline(always)]
816 fn rem(self, other: &SafeInt) -> Option<SafeInt> {
817 if other.0.is_zero() {
818 None
819 } else {
820 Some(SafeInt(self.0 % &other.0))
821 }
822 }
823 }
824
825 impl Rem<SafeInt> for &SafeInt {
826 type Output = Option<SafeInt>;
827
828 #[inline(always)]
829 fn rem(self, other: SafeInt) -> Option<SafeInt> {
830 if other.0.is_zero() {
831 None
832 } else {
833 Some(SafeInt(self.0.clone() % other.0))
834 }
835 }
836 }
837
838 impl Rem<&SafeInt> for &SafeInt {
839 type Output = Option<SafeInt>;
840
841 #[inline(always)]
842 fn rem(self, other: &SafeInt) -> Option<SafeInt> {
843 if other.0.is_zero() {
844 None
845 } else {
846 Some(SafeInt(self.0.clone() % &other.0))
847 }
848 }
849 }
850 };
851}
852
853impl_pair_ops!(Add, add);
854impl_pair_ops!(Sub, sub);
855impl_pair_ops!(Mul, mul);
856impl_pair_rem_ops!();
857impl_pair_ops!(BitAnd, bitand);
858impl_pair_ops!(BitOr, bitor);
859impl_pair_ops!(BitXor, bitxor);
860
861macro_rules! impl_prim_ops {
862 ($trait:ident, $method:ident, [$($t:ty),*]) => {
863 $(
864 impl $trait<$t> for SafeInt {
865 type Output = SafeInt;
866
867 #[inline(always)]
868 fn $method(self, other: $t) -> SafeInt {
869 SafeInt(self.0.$method(BigInt::from(other)))
870 }
871 }
872
873 impl $trait<$t> for &SafeInt {
874 type Output = SafeInt;
875
876 #[inline(always)]
877 fn $method(self, other: $t) -> SafeInt {
878 SafeInt(self.0.clone().$method(BigInt::from(other)))
879 }
880 }
881
882 impl $trait<SafeInt> for $t {
883 type Output = SafeInt;
884
885 #[inline(always)]
886 fn $method(self, other: SafeInt) -> SafeInt {
887 SafeInt(BigInt::from(self).$method(other.0))
888 }
889 }
890
891 impl $trait<&SafeInt> for $t {
892 type Output = SafeInt;
893
894 #[inline(always)]
895 fn $method(self, other: &SafeInt) -> SafeInt {
896 SafeInt(BigInt::from(self).$method(other.0.clone()))
897 }
898 }
899 )*
900 };
901}
902
903macro_rules! impl_prim_rem_ops {
904 ($($t:ty),*) => {
905 $(
906 impl Rem<$t> for SafeInt {
907 type Output = Option<SafeInt>;
908
909 #[inline(always)]
910 fn rem(self, other: $t) -> Option<SafeInt> {
911 if other == 0 {
912 None
913 } else {
914 Some(SafeInt(self.0 % BigInt::from(other)))
915 }
916 }
917 }
918
919 impl Rem<$t> for &SafeInt {
920 type Output = Option<SafeInt>;
921
922 #[inline(always)]
923 fn rem(self, other: $t) -> Option<SafeInt> {
924 if other == 0 {
925 None
926 } else {
927 Some(SafeInt(self.0.clone() % BigInt::from(other)))
928 }
929 }
930 }
931
932 impl Rem<SafeInt> for $t {
933 type Output = Option<SafeInt>;
934
935 #[inline(always)]
936 fn rem(self, other: SafeInt) -> Option<SafeInt> {
937 if other.0.is_zero() {
938 None
939 } else {
940 Some(SafeInt(BigInt::from(self) % other.0))
941 }
942 }
943 }
944
945 impl Rem<&SafeInt> for $t {
946 type Output = Option<SafeInt>;
947
948 #[inline(always)]
949 fn rem(self, other: &SafeInt) -> Option<SafeInt> {
950 if other.0.is_zero() {
951 None
952 } else {
953 Some(SafeInt(BigInt::from(self) % other.0.clone()))
954 }
955 }
956 }
957 )*
958 };
959}
960
961impl_prim_ops!(
962 Add,
963 add,
964 [
965 u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize
966 ]
967);
968impl_prim_ops!(
969 Sub,
970 sub,
971 [
972 u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize
973 ]
974);
975impl_prim_ops!(
976 Mul,
977 mul,
978 [
979 u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize
980 ]
981);
982impl_prim_rem_ops!(
983 u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize
984);
985impl_prim_ops!(
986 BitAnd,
987 bitand,
988 [
989 u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize
990 ]
991);
992impl_prim_ops!(
993 BitOr,
994 bitor,
995 [
996 u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize
997 ]
998);
999impl_prim_ops!(
1000 BitXor,
1001 bitxor,
1002 [
1003 u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize
1004 ]
1005);
1006
1007impl AddAssign<SafeInt> for SafeInt {
1008 #[inline(always)]
1009 fn add_assign(&mut self, rhs: SafeInt) {
1010 self.0 += rhs.0;
1011 }
1012}
1013
1014impl AddAssign<&SafeInt> for SafeInt {
1015 #[inline(always)]
1016 fn add_assign(&mut self, rhs: &SafeInt) {
1017 self.0 += &rhs.0;
1018 }
1019}
1020
1021impl SubAssign<SafeInt> for SafeInt {
1022 #[inline(always)]
1023 fn sub_assign(&mut self, rhs: SafeInt) {
1024 self.0 -= rhs.0;
1025 }
1026}
1027
1028impl SubAssign<&SafeInt> for SafeInt {
1029 #[inline(always)]
1030 fn sub_assign(&mut self, rhs: &SafeInt) {
1031 self.0 -= &rhs.0;
1032 }
1033}
1034
1035impl MulAssign<SafeInt> for SafeInt {
1036 #[inline(always)]
1037 fn mul_assign(&mut self, rhs: SafeInt) {
1038 self.0 *= rhs.0;
1039 }
1040}
1041
1042impl MulAssign<&SafeInt> for SafeInt {
1043 #[inline(always)]
1044 fn mul_assign(&mut self, rhs: &SafeInt) {
1045 self.0 *= &rhs.0;
1046 }
1047}
1048
1049impl RemAssign<SafeInt> for SafeInt {
1050 #[inline(always)]
1051 fn rem_assign(&mut self, rhs: SafeInt) {
1052 if !rhs.0.is_zero() {
1053 self.0 %= rhs.0;
1054 }
1055 }
1056}
1057
1058impl RemAssign<&SafeInt> for SafeInt {
1059 #[inline(always)]
1060 fn rem_assign(&mut self, rhs: &SafeInt) {
1061 if !rhs.0.is_zero() {
1062 self.0 %= &rhs.0;
1063 }
1064 }
1065}
1066
1067impl BitAndAssign<SafeInt> for SafeInt {
1068 #[inline(always)]
1069 fn bitand_assign(&mut self, rhs: SafeInt) {
1070 self.0 &= rhs.0;
1071 }
1072}
1073
1074impl BitAndAssign<&SafeInt> for SafeInt {
1075 #[inline(always)]
1076 fn bitand_assign(&mut self, rhs: &SafeInt) {
1077 self.0 &= &rhs.0;
1078 }
1079}
1080
1081impl BitOrAssign<SafeInt> for SafeInt {
1082 #[inline(always)]
1083 fn bitor_assign(&mut self, rhs: SafeInt) {
1084 self.0 |= rhs.0;
1085 }
1086}
1087
1088impl BitOrAssign<&SafeInt> for SafeInt {
1089 #[inline(always)]
1090 fn bitor_assign(&mut self, rhs: &SafeInt) {
1091 self.0 |= &rhs.0;
1092 }
1093}
1094
1095impl BitXorAssign<SafeInt> for SafeInt {
1096 #[inline(always)]
1097 fn bitxor_assign(&mut self, rhs: SafeInt) {
1098 self.0 ^= rhs.0;
1099 }
1100}
1101
1102impl BitXorAssign<&SafeInt> for SafeInt {
1103 #[inline(always)]
1104 fn bitxor_assign(&mut self, rhs: &SafeInt) {
1105 self.0 ^= &rhs.0;
1106 }
1107}
1108
1109macro_rules! impl_assign_prim {
1110 ($trait:ident, $method:ident, $op:tt, [$($t:ty),*]) => {
1111 $(
1112 impl $trait<$t> for SafeInt {
1113 #[inline(always)]
1114 fn $method(&mut self, rhs: $t) {
1115 self.0 $op BigInt::from(rhs);
1116 }
1117 }
1118 )*
1119 };
1120}
1121
1122macro_rules! impl_rem_assign_prim {
1123 ($($t:ty),*) => {
1124 $(
1125 impl RemAssign<$t> for SafeInt {
1126 #[inline(always)]
1127 fn rem_assign(&mut self, rhs: $t) {
1128 if rhs != 0 {
1129 self.0 %= BigInt::from(rhs);
1130 }
1131 }
1132 }
1133 )*
1134 };
1135}
1136
1137impl_assign_prim!(AddAssign, add_assign, +=, [u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize]);
1138impl_assign_prim!(SubAssign, sub_assign, -=, [u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize]);
1139impl_assign_prim!(MulAssign, mul_assign, *=, [u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize]);
1140impl_rem_assign_prim!(
1141 u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize
1142);
1143impl_assign_prim!(BitAndAssign, bitand_assign, &=, [u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize]);
1144impl_assign_prim!(BitOrAssign, bitor_assign, |=, [u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize]);
1145impl_assign_prim!(BitXorAssign, bitxor_assign, ^=, [u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize]);
1146
1147impl Div for SafeInt {
1148 type Output = Option<SafeInt>;
1149
1150 #[inline(always)]
1151 fn div(self, other: SafeInt) -> Option<SafeInt> {
1152 if other.0.is_zero() {
1153 None
1154 } else {
1155 Some(SafeInt(self.0 / other.0))
1156 }
1157 }
1158}
1159
1160impl Div<&SafeInt> for SafeInt {
1161 type Output = Option<SafeInt>;
1162
1163 #[inline(always)]
1164 fn div(self, other: &SafeInt) -> Option<SafeInt> {
1165 if other.0.is_zero() {
1166 None
1167 } else {
1168 Some(SafeInt(self.0 / &other.0))
1169 }
1170 }
1171}
1172
1173impl Div<SafeInt> for &SafeInt {
1174 type Output = Option<SafeInt>;
1175
1176 #[inline(always)]
1177 fn div(self, other: SafeInt) -> Option<SafeInt> {
1178 if other.0.is_zero() {
1179 None
1180 } else {
1181 Some(SafeInt(self.0.clone() / other.0))
1182 }
1183 }
1184}
1185
1186impl Div<&SafeInt> for &SafeInt {
1187 type Output = Option<SafeInt>;
1188
1189 #[inline(always)]
1190 fn div(self, other: &SafeInt) -> Option<SafeInt> {
1191 if other.0.is_zero() {
1192 None
1193 } else {
1194 Some(SafeInt(self.0.clone() / &other.0))
1195 }
1196 }
1197}
1198
1199macro_rules! impl_div_safeint_rhs_prim {
1200 ($($t:ty),*) => {
1201 $(
1202 impl Div<$t> for SafeInt {
1203 type Output = Option<SafeInt>;
1204
1205 #[inline(always)]
1206 fn div(self, other: $t) -> Option<SafeInt> {
1207 if other == 0 {
1208 None
1209 } else {
1210 Some(SafeInt(self.0 / BigInt::from(other)))
1211 }
1212 }
1213 }
1214
1215 impl Div<$t> for &SafeInt {
1216 type Output = Option<SafeInt>;
1217
1218 #[inline(always)]
1219 fn div(self, other: $t) -> Option<SafeInt> {
1220 if other == 0 {
1221 None
1222 } else {
1223 Some(SafeInt(self.0.clone() / BigInt::from(other)))
1224 }
1225 }
1226 }
1227 )*
1228 };
1229}
1230
1231macro_rules! impl_div_prim_lhs_safeint {
1232 ($($t:ty),*) => {
1233 $(
1234 impl Div<SafeInt> for $t {
1235 type Output = Option<SafeInt>;
1236
1237 #[inline(always)]
1238 fn div(self, other: SafeInt) -> Option<SafeInt> {
1239 if other.0.is_zero() {
1240 None
1241 } else {
1242 Some(SafeInt(BigInt::from(self) / other.0))
1243 }
1244 }
1245 }
1246
1247 impl Div<&SafeInt> for $t {
1248 type Output = Option<SafeInt>;
1249
1250 #[inline(always)]
1251 fn div(self, other: &SafeInt) -> Option<SafeInt> {
1252 if other.0.is_zero() {
1253 None
1254 } else {
1255 Some(SafeInt(BigInt::from(self) / other.0.clone()))
1256 }
1257 }
1258 }
1259 )*
1260 };
1261}
1262
1263impl_div_safeint_rhs_prim!(
1264 u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize
1265);
1266impl_div_prim_lhs_safeint!(
1267 u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize
1268);
1269
1270impl<T: Into<BigInt>> From<T> for SafeInt {
1271 #[inline(always)]
1272 fn from(value: T) -> SafeInt {
1273 SafeInt(value.into())
1274 }
1275}
1276
1277impl<T> PartialEq<T> for SafeInt
1278where
1279 T: Copy,
1280 BigInt: From<T>,
1281{
1282 #[inline(always)]
1283 fn eq(&self, other: &T) -> bool {
1284 self.0 == BigInt::from(*other)
1285 }
1286}
1287
1288impl<T> PartialOrd<T> for SafeInt
1289where
1290 T: Copy,
1291 BigInt: From<T>,
1292{
1293 #[inline(always)]
1294 fn partial_cmp(&self, other: &T) -> Option<Ordering> {
1295 self.0.partial_cmp(&BigInt::from(*other))
1296 }
1297}
1298
1299macro_rules! impl_prim_cmp {
1300 ($($t:ty),*) => {
1301 $(
1302 impl PartialEq<SafeInt> for $t {
1303 #[inline(always)]
1304 fn eq(&self, other: &SafeInt) -> bool {
1305 BigInt::from(*self) == other.0
1306 }
1307 }
1308
1309 impl PartialOrd<SafeInt> for $t {
1310 #[inline(always)]
1311 fn partial_cmp(&self, other: &SafeInt) -> Option<Ordering> {
1312 BigInt::from(*self).partial_cmp(&other.0)
1313 }
1314 }
1315 )*
1316 };
1317}
1318
1319impl_prim_cmp!(
1320 u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize
1321);
1322
1323#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
1334#[repr(C)]
1335pub struct ConstSafeInt<const N: usize>([u8; N]);
1336
1337impl<const N: usize> ConstSafeInt<N> {
1338 pub const fn from_bytes(value: [u8; N]) -> Self {
1340 Self(value)
1341 }
1342
1343 pub const fn as_bytes(&self) -> &[u8; N] {
1345 &self.0
1346 }
1347
1348 pub fn to_val(self) -> SafeInt {
1350 self.into()
1351 }
1352}
1353
1354impl ConstSafeInt<17> {
1355 pub const fn from_i128(value: i128) -> Self {
1366 let is_neg = value < 0;
1367 let value = if value == i128::MIN {
1368 i128::MAX as u128 + 1
1369 } else {
1370 value.unsigned_abs()
1371 };
1372 let mut res = Self::from_u128(value);
1373 if is_neg {
1374 res.0[0] = 1;
1375 }
1376 res
1377 }
1378 pub const fn from_u128(value: u128) -> Self {
1380 let mut res = [0; 17];
1381 let mut value = value;
1382 let mut i = 17;
1383 while i > 0 {
1384 i -= 1;
1385 res[i] = (value & 0xff) as u8;
1386 value >>= 8;
1387 }
1388 Self(res)
1389 }
1390}
1391
1392impl<const N: usize> From<ConstSafeInt<N>> for SafeInt {
1393 #[inline(always)]
1394 fn from(value: ConstSafeInt<N>) -> SafeInt {
1395 let pos = value.0.first().cloned().unwrap_or(0) == 0;
1396 let magnitude = BigUint::from_bytes_be(&value.0[1..]);
1397 let mut res = SafeInt(BigInt::from_biguint(Sign::Plus, magnitude));
1398 if !pos {
1399 res = -res;
1400 }
1401 res
1402 }
1403}
1404
1405impl<const N: usize> From<&ConstSafeInt<N>> for SafeInt {
1406 #[inline(always)]
1407 fn from(value: &ConstSafeInt<N>) -> SafeInt {
1408 let pos = value.0.first().cloned().unwrap_or(0) == 0;
1409 let magnitude = BigUint::from_bytes_be(&value.0[1..]);
1410 let mut res = SafeInt(BigInt::from_biguint(Sign::Plus, magnitude));
1411 if !pos {
1412 res = -res;
1413 }
1414 res
1415 }
1416}
1417
1418const LENCODE_SAFE_INT_VARIANT_MASK: u8 = 0x80;
1419const LENCODE_SAFE_INT_VARIANT_BYTES: u8 = 0x80;
1420const LENCODE_SAFE_INT_SIZE_MASK: u8 = 0x40;
1421const LENCODE_SAFE_INT_SIZE_LARGE: u8 = 0x40;
1422const LENCODE_SAFE_INT_PAYLOAD_MASK: u8 = 0x3F;
1423const LENCODE_SAFE_INT_SMALL_MAX: u8 = LENCODE_SAFE_INT_PAYLOAD_MASK;
1424const LENCODE_MAX_VARINT_BYTES: usize = LENCODE_SAFE_INT_PAYLOAD_MASK as usize;
1425
1426#[inline(always)]
1427fn lencode_encode_biguint_varint_bytes(
1428 bytes: &[u8],
1429 writer: &mut impl Write,
1430) -> lencode::Result<usize> {
1431 if bytes.is_empty() {
1432 return writer.write(&[0u8]);
1433 }
1434 if bytes.len() == 1 && bytes[0] <= LENCODE_SAFE_INT_SMALL_MAX {
1435 return writer.write(&[bytes[0]]);
1436 }
1437 if bytes.len() > LENCODE_MAX_VARINT_BYTES {
1438 return Err(Error::IncorrectLength);
1439 }
1440
1441 let mut total = 0;
1442 total += writer.write(&[LENCODE_SAFE_INT_SIZE_LARGE | (bytes.len() as u8)])?;
1443 total += writer.write(bytes)?;
1444 Ok(total)
1445}
1446
1447#[inline(always)]
1448fn lencode_decode_biguint_varint_from_prefix(
1449 prefix: u8,
1450 reader: &mut impl Read,
1451) -> lencode::Result<BigUint> {
1452 if (prefix & LENCODE_SAFE_INT_SIZE_MASK) == 0 {
1453 return Ok(BigUint::from(prefix & LENCODE_SAFE_INT_PAYLOAD_MASK));
1454 }
1455
1456 let len = (prefix & LENCODE_SAFE_INT_PAYLOAD_MASK) as usize;
1457 if len == 0 {
1458 return Err(Error::InvalidData);
1459 }
1460
1461 let mut buf = vec![0u8; len];
1462 let mut read = 0usize;
1463 while read < len {
1464 let n = reader.read(&mut buf[read..])?;
1465 if n == 0 {
1466 return Err(Error::ReaderOutOfData);
1467 }
1468 read += n;
1469 }
1470 Ok(BigUint::from_bytes_le(&buf))
1471}
1472
1473#[inline(always)]
1474fn lencode_encode_biguint_with_variant(
1475 value: &BigUint,
1476 writer: &mut impl Write,
1477) -> lencode::Result<usize> {
1478 let bytes = value.to_bytes_le();
1479 if bytes.len() <= LENCODE_MAX_VARINT_BYTES {
1480 return lencode_encode_biguint_varint_bytes(&bytes, writer);
1481 }
1482
1483 let mut total = 0;
1484 total += writer.write(&[LENCODE_SAFE_INT_VARIANT_BYTES])?;
1485 total += bytes.encode(writer)?;
1486 Ok(total)
1487}
1488
1489#[inline(always)]
1490fn lencode_decode_biguint_with_variant(reader: &mut impl Read) -> lencode::Result<BigUint> {
1491 let mut tag = [0u8; 1];
1492 if reader.read(&mut tag)? != 1 {
1493 return Err(Error::ReaderOutOfData);
1494 }
1495
1496 if (tag[0] & LENCODE_SAFE_INT_VARIANT_MASK) != 0 {
1497 let bytes: Vec<u8> = Vec::decode(reader)?;
1498 Ok(BigUint::from_bytes_le(&bytes))
1499 } else {
1500 lencode_decode_biguint_varint_from_prefix(tag[0], reader)
1501 }
1502}
1503
1504#[inline(always)]
1505fn lencode_zigzag_encode_bigint(value: &BigInt) -> BigUint {
1506 if value.is_negative() {
1507 let magnitude = (-value).to_biguint().unwrap_or(BigUint::ZERO);
1508 (magnitude << 1usize) - BigUint::from(1u8)
1509 } else {
1510 let magnitude = value.to_biguint().unwrap_or(BigUint::ZERO);
1511 magnitude << 1usize
1512 }
1513}
1514
1515#[inline(always)]
1516fn lencode_zigzag_decode_biguint(value: BigUint) -> BigInt {
1517 if value.is_odd() {
1518 let magnitude = (value + BigUint::from(1u8)) >> 1usize;
1519 -BigInt::from(magnitude)
1520 } else {
1521 BigInt::from(value >> 1usize)
1522 }
1523}
1524
1525impl Encode for SafeInt {
1526 #[inline(always)]
1527 fn encode_ext(
1528 &self,
1529 writer: &mut impl Write,
1530 _dedupe_encoder: Option<&mut DedupeEncoder>,
1531 ) -> lencode::Result<usize> {
1532 let encoded = lencode_zigzag_encode_bigint(&self.0);
1533 lencode_encode_biguint_with_variant(&encoded, writer)
1534 }
1535}
1536
1537impl Decode for SafeInt {
1538 #[inline(always)]
1539 fn decode_ext(
1540 reader: &mut impl Read,
1541 _dedupe_decoder: Option<&mut DedupeDecoder>,
1542 ) -> lencode::Result<Self> {
1543 let unsigned = lencode_decode_biguint_with_variant(reader)?;
1544 Ok(SafeInt::from_raw(lencode_zigzag_decode_biguint(unsigned)))
1545 }
1546}
1547
1548#[test]
1549fn test_const_safe_int() {
1550 assert_eq!(
1551 SafeInt::from(ConstSafeInt::<4>::from_bytes([0, 0, 0, 1])),
1552 1
1553 );
1554 assert_eq!(SafeInt::from(ConstSafeInt::<2>::from_bytes([0, 1])), 1);
1555 assert_eq!(SafeInt::from(ConstSafeInt::<2>::from_bytes([1, 1])), -1);
1556 assert_eq!(SafeInt::from(ConstSafeInt::<2>::from_bytes([1, 0])), -0);
1557 assert_eq!(
1558 SafeInt::from(ConstSafeInt::<3>::from_bytes([1, 5, 254])),
1559 -1534
1560 );
1561 assert_eq!(
1562 SafeInt::from(ConstSafeInt::<17>::from_i128(-538525)),
1563 -538525
1564 );
1565 assert_eq!(
1566 SafeInt::from(ConstSafeInt::<17>::from_i128(123456789)),
1567 123456789
1568 );
1569 assert_eq!(
1570 SafeInt::from(ConstSafeInt::<17>::from_i128(i128::MIN)),
1571 i128::MIN
1572 );
1573 assert_eq!(
1574 SafeInt::from(ConstSafeInt::<17>::from_i128(i128::MAX)),
1575 i128::MAX
1576 );
1577 assert_eq!(
1578 SafeInt::from(ConstSafeInt::<17>::from_u128(u128::MAX)),
1579 u128::MAX
1580 );
1581 assert_eq!(
1582 SafeInt::from(ConstSafeInt::<17>::from_u128(39874398749837343434343434344)),
1583 39874398749837343434343434344u128
1584 );
1585 assert_eq!(SafeInt::from(ConstSafeInt::<17>::from_u128(0)), 0);
1586}
1587
1588#[test]
1589fn general() {
1590 let a = SafeInt::from(10);
1591 let b = SafeInt::from(20);
1592 let c = &a + &b;
1593 let d = a.clone() + c.clone();
1594 let e = a.clone() + &b;
1595 let f = &a + b.clone();
1596 assert_eq!(c, 30);
1597 assert!(d > a);
1598 assert!(a < d);
1599 assert!(a < b);
1600 assert_eq!(e, f);
1601 assert_eq!(f, a + b);
1602 assert_eq!((SafeInt::from(10) / SafeInt::from(3)).unwrap(), 3);
1603 assert_eq!(SafeInt::from(10) / SafeInt::from(0), None);
1604 assert_ne!(SafeInt::from(10), SafeInt::from(20));
1605 assert!(SafeInt::from(37984739847983497938479797988798789783u128).is_odd());
1606 assert!(
1607 SafeInt::from_str("3798473984798349793847979798879878978334738744739847983749837").unwrap()
1608 > 10
1609 );
1610 assert_eq!(
1611 SafeInt::from(33) / SafeInt::from(3),
1612 Some(SafeInt::from(11))
1613 );
1614 assert_eq!(33 / SafeInt::from(3), Some(SafeInt::from(11)));
1615 assert_eq!(SafeInt::from(33) / 3, Some(SafeInt::from(11)));
1616 assert_eq!(SafeInt::from(10) % SafeInt::from(3), Some(SafeInt::from(1)));
1617 assert_eq!(SafeInt::from(10) % SafeInt::from(0), None);
1618 assert_eq!(10 % SafeInt::from(3), Some(SafeInt::from(1)));
1619 assert_eq!(10 % SafeInt::from(0), None);
1620 assert_eq!(SafeInt::from(10) % 3, Some(SafeInt::from(1)));
1621 assert_eq!(SafeInt::from(10) % 0, None);
1622 assert_eq!(
1623 SafeInt::from(10).div_rem(SafeInt::from(3)),
1624 Some((SafeInt::from(3), SafeInt::from(1)))
1625 );
1626 assert_eq!(SafeInt::from(10).div_rem(SafeInt::from(0)), None);
1627 assert_eq!(33 + SafeInt::from(2), 35);
1628 assert_eq!(SafeInt::from(33) + 2, 35);
1629 assert_eq!(SafeInt::from(5) / SafeInt::from(0), None);
1630 assert_eq!(5 / SafeInt::from(0), None);
1631 assert_eq!(SafeInt::from(5) / 0, None);
1632 assert_eq!(&SafeInt::from(789) / 893797983, Some(SafeInt::from(0)));
1633 assert_eq!(&SafeInt::from(28249) / SafeInt::zero(), None);
1634}
1635
1636#[test]
1637fn test_safe_int_cmp_self() {
1638 let a = SafeInt::from(5);
1639 let b = SafeInt::from(7);
1640 let a2 = a.clone();
1641
1642 assert_eq!(a, a2);
1643 assert_ne!(a, b);
1644 assert!(a < b);
1645 assert!(b > a);
1646 assert!(a <= a2);
1647 assert!(a >= a2);
1648 assert_eq!(a.partial_cmp(&b), Some(Ordering::Less));
1649 assert_eq!(b.partial_cmp(&a), Some(Ordering::Greater));
1650 assert_eq!(a.cmp(&a2), Ordering::Equal);
1651 assert_eq!(a.cmp(&b), Ordering::Less);
1652}
1653
1654#[test]
1655fn test_perquintill_power() {
1656 const PRECISION: u32 = 256;
1657 const PERQUINTILL: u128 = 1_000_000_000_000_000_000;
1658
1659 let x = SafeInt::from(21_000_000_000_000_000u64);
1660 let delta = SafeInt::from(7_000_000_000_000_000u64);
1661 let w1 = SafeInt::from(600_000_000_000_000_000u128);
1662 let w2 = SafeInt::from(400_000_000_000_000_000u128);
1663 let denominator = &x + δ
1664 assert_eq!(w1.clone() + w2.clone(), SafeInt::from(PERQUINTILL));
1665
1666 let perquintill_result = SafeInt::pow_ratio_scaled(
1667 &x,
1668 &denominator,
1669 &w1,
1670 &w2,
1671 PRECISION,
1672 &SafeInt::from(PERQUINTILL),
1673 )
1674 .expect("perquintill integer result");
1675
1676 assert_eq!(
1677 perquintill_result,
1678 SafeInt::from(649_519_052_838_328_985u128)
1679 );
1680 let readable = crate::SafeDec::<18>::from_raw(perquintill_result);
1681 assert_eq!(format!("{}", readable), "0.649519052838328985");
1682}
1683
1684#[test]
1685fn pow_ratio_scaled_handles_large_weight_denominators() {
1686 let x = SafeInt::from(21_000_000_000_000_000i128);
1687 let denominator = SafeInt::from(21_000_000_000_000_100i128);
1688 let perquintill = SafeInt::from(1_000_000_000_000_000_000i128);
1689
1690 let cases = [
1691 (
1692 SafeInt::from(500_000_000_000_000_000i128),
1693 SafeInt::from(500_000_000_000_000_000i128),
1694 ),
1695 (
1696 SafeInt::from(499_999_999_999_500_000i128),
1697 SafeInt::from(500_000_000_000_500_000i128),
1698 ),
1699 (
1700 SafeInt::from(500_000_000_000_250_000i128),
1701 SafeInt::from(499_999_999_999_750_000i128),
1702 ),
1703 ];
1704
1705 for (w1, w2) in cases {
1706 let result =
1707 SafeInt::pow_ratio_scaled(&x, &denominator, &w1, &w2, 256, &perquintill).unwrap();
1708 assert_eq!(result, SafeInt::from(999_999_999_999_995_238i128));
1709 }
1710}
1711
1712#[test]
1713fn pow_ratio_scaled_converges_on_boundary_weights() {
1714 let x = SafeInt::from(21_000_000_000_000_000i128);
1715 let denominator = SafeInt::from(21_000_000_000_000_001i128);
1716 let w1 = SafeInt::from(499_999_999_500_000_000i128);
1717 let w2 = SafeInt::from(500_000_000_500_000_000i128);
1718 let scale = SafeInt::from(1_000_000_000_000_000_000i128);
1719 let precision = 256u32;
1720
1721 let start = std::time::Instant::now();
1722 let result = SafeInt::pow_ratio_scaled(&x, &denominator, &w1, &w2, precision, &scale).unwrap();
1723 let elapsed = start.elapsed();
1724
1725 assert_eq!(result, SafeInt::from(999_999_999_999_999_952i128));
1726 assert!(
1727 elapsed < core::time::Duration::from_secs(1),
1728 "pow_ratio_scaled took {:?}",
1729 elapsed
1730 );
1731}
1732
1733#[test]
1734fn pow_ratio_scaled_exact_path_handles_high_exponent() {
1735 let base_num = SafeInt::from(999_999_999i128);
1736 let base_den = SafeInt::from(1_000_000_001i128);
1737 let exp_num = SafeInt::from(MAX_EXACT_EXPONENT as i128 - 1);
1738 let exp_den = SafeInt::one();
1739 let scale = SafeInt::from(1_000_000i128);
1740 let precision = 64u32;
1741
1742 let start = std::time::Instant::now();
1743 let result =
1744 SafeInt::pow_ratio_scaled(&base_num, &base_den, &exp_num, &exp_den, precision, &scale)
1745 .expect("exact path should return");
1746 let elapsed = start.elapsed();
1747
1748 assert!(result > SafeInt::zero());
1749 assert!(
1750 elapsed < core::time::Duration::from_secs(1),
1751 "exact path took {:?}",
1752 elapsed
1753 );
1754}
1755
1756#[test]
1757fn pow_ratio_scaled_default_max_iters_completes_quickly() {
1758 let base_num = SafeInt::from(1i128);
1759 let base_den = SafeInt::from(1_000_000_000_000i128);
1760 let exp_num = SafeInt::one();
1761 let exp_den = SafeInt::from(1u128 << 40);
1762 let scale = SafeInt::one();
1763 let precision = 32u32;
1764
1765 let start = std::time::Instant::now();
1766 let default_iter =
1767 SafeInt::pow_ratio_scaled(&base_num, &base_den, &exp_num, &exp_den, precision, &scale)
1768 .unwrap();
1769 let elapsed = start.elapsed();
1770
1771 let explicit_default = SafeInt::pow_ratio_scaled_with_max_iters(
1772 &base_num,
1773 &base_den,
1774 &exp_num,
1775 &exp_den,
1776 precision,
1777 &scale,
1778 Some(DEFAULT_MAX_ITERS),
1779 )
1780 .unwrap();
1781
1782 assert_eq!(default_iter, explicit_default);
1783 assert!(
1784 elapsed < core::time::Duration::from_secs(2),
1785 "default iterations took {:?}",
1786 elapsed
1787 );
1788}
1789
1790#[test]
1791fn pow_ratio_scaled_uses_scale_to_pick_precision() {
1792 let base_num = SafeInt::from(123_456_789u64);
1795 let base_den = SafeInt::from(987_654_321u64);
1796 let exp_num = SafeInt::from(987_654_321_123_456_789u128);
1797 let exp_den = SafeInt::from(123_456_789_987_654_321u128);
1798 let scale = SafeInt::from(1_000_000_000_000_000_000i128);
1799
1800 let coarse = SafeInt::pow_ratio_scaled(&base_num, &base_den, &exp_num, &exp_den, 0, &scale)
1801 .expect("coarse precision result");
1802 let precise = SafeInt::pow_ratio_scaled(&base_num, &base_den, &exp_num, &exp_den, 256, &scale)
1803 .expect("high precision result");
1804 let delta = (precise.clone() - coarse.clone()).abs();
1805
1806 assert!(
1807 delta <= 1u32,
1808 "coarse {coarse} vs precise {precise} differed by {delta}"
1809 );
1810}
1811
1812#[test]
1813fn pow_ratio_scaled_handles_small_base_fractional_exponent() {
1814 let base_num = SafeInt::from(1u8);
1816 let base_den = SafeInt::from(10u8);
1817 let exp_num = SafeInt::from(500_000_000_001u64);
1818 let exp_den = SafeInt::from(1_000_000_000_000u64);
1819 let scale = SafeInt::from(1_000_000_000_000_000_000u128);
1820 let precision = 128u32;
1821
1822 let result =
1823 SafeInt::pow_ratio_scaled(&base_num, &base_den, &exp_num, &exp_den, precision, &scale)
1824 .expect("small base fractional exponent");
1825 let expected =
1826 ((0.1f64).powf(0.500000000001f64) * 1_000_000_000_000_000_000f64).floor() as u128;
1827 let delta = (result.clone() - SafeInt::from(expected)).abs();
1828
1829 assert!(
1830 delta <= 128u32,
1831 "result {result} vs expected {expected} (delta {delta})"
1832 );
1833}
1834
1835#[test]
1836fn pow_ratio_scaled_handles_extreme_delta_x() {
1837 let x = SafeInt::from(400_775_553u64);
1838 let dx = SafeInt::from(14_446_633_907_665_582u64);
1839 let base_den = &x + &dx;
1840 let w1 = SafeInt::from(102_337_248_363_782_924u128);
1841 let w2 = SafeInt::from(1_000_000_000_000_000_000u128) - &w1;
1842 let scale = SafeInt::from(1_000_000_000_000_000_000u128);
1843 let precision = 256u32;
1844
1845 let result = SafeInt::pow_ratio_scaled(&x, &base_den, &w1, &w2, precision, &scale)
1846 .expect("extreme delta x");
1847
1848 let expected = ((x.0.to_f64().unwrap() / base_den.0.to_f64().unwrap())
1849 .powf(w1.0.to_f64().unwrap() / w2.0.to_f64().unwrap())
1850 * 1_000_000_000_000_000_000f64)
1851 .floor() as u128;
1852 let delta = (result.clone() - SafeInt::from(expected)).abs();
1853
1854 assert!(
1855 delta <= 1_000_000u128,
1856 "result {result} vs expected {expected} (delta {delta})"
1857 );
1858}
1859
1860#[test]
1861fn pow_ratio_scaled_with_crafted_gcd_values() {
1862 let x_safe = SafeInt::from_str("2100000000000000000000000").unwrap();
1869 let denominator = SafeInt::from_str("210000000000000000000000").unwrap();
1870 let w1_safe = SafeInt::from_str("499").unwrap();
1871 let w2_safe = SafeInt::from_str("1538820023").unwrap();
1872 let precision = 256;
1873 let perquintill_scale = SafeInt::from_str("1000000000000000000").unwrap();
1874
1875 let start = Instant::now();
1876
1877 SafeInt::pow_ratio_scaled(
1878 &x_safe,
1879 &denominator,
1880 &w1_safe,
1881 &w2_safe,
1882 precision,
1883 &perquintill_scale,
1884 );
1885 let elapsed = start.elapsed();
1886
1887 assert!(
1888 elapsed < Duration::from_secs(1),
1889 "pow_ratio_scaled took {:?} (expected < 1s)",
1890 elapsed
1891 );
1892}
1893
1894#[test]
1895fn pow_bigint_base_with_crafted_gcd_values() {
1896 let x_safe = SafeInt::from_str("2100000000000000000000000").unwrap();
1903 let w1_safe = SafeInt::from_str("499").unwrap();
1904 let w2_safe = SafeInt::from_str("1538820023").unwrap();
1905 let precision = 256;
1906 let perquintill_scale = SafeInt::from_str("1000000000000000000").unwrap();
1907
1908 let start = Instant::now();
1909
1910 SafeInt::pow_bigint_base(&x_safe, &w1_safe, &w2_safe, precision, &perquintill_scale);
1911 let elapsed = start.elapsed();
1912
1913 assert!(
1914 elapsed < Duration::from_secs(1),
1915 "pow_ratio_scaled took {:?} (expected < 1s)",
1916 elapsed
1917 );
1918}
1919
1920#[test]
1921fn test_zero() {
1922 assert_eq!(SafeInt::zero(), 0);
1923 assert!(SafeInt::zero().is_zero());
1924}
1925
1926#[test]
1927fn test_one() {
1928 let one = SafeInt::one();
1929 assert_eq!(one, 1);
1930}
1931
1932#[cfg(test)]
1933#[inline(always)]
1934fn expected_varint_bytes(value: &BigUint) -> Vec<u8> {
1935 if *value <= BigUint::from(LENCODE_SAFE_INT_SMALL_MAX) {
1936 vec![value.to_u8().expect("value fits in u8")]
1937 } else {
1938 let bytes = value.to_bytes_le();
1939 let mut out = Vec::with_capacity(1 + bytes.len());
1940 out.push(LENCODE_SAFE_INT_SIZE_LARGE | (bytes.len() as u8));
1941 out.extend_from_slice(&bytes);
1942 out
1943 }
1944}
1945
1946#[test]
1947fn lencode_safe_int_roundtrip() {
1948 let big = BigInt::from(1u8) << 200usize;
1949 let values = [
1950 SafeInt::from(0),
1951 SafeInt::from(1),
1952 SafeInt::from(-1),
1953 SafeInt::from(127),
1954 SafeInt::from(128),
1955 SafeInt::from(-128),
1956 SafeInt::from(255),
1957 SafeInt::from(-255),
1958 SafeInt::from_raw(big.clone()),
1959 SafeInt::from_raw(-big),
1960 ];
1961
1962 for value in values {
1963 let mut buf = Vec::new();
1964 let written = value.encode(&mut buf).unwrap();
1965 assert_eq!(written, buf.len());
1966 let decoded = SafeInt::decode(&mut Cursor::new(&buf)).unwrap();
1967 assert_eq!(decoded, value);
1968 }
1969}
1970
1971#[test]
1972fn lencode_safe_int_known_encodings() {
1973 let cases: &[(i32, &[u8])] = &[
1974 (0, &[0x00]),
1975 (1, &[0x02]),
1976 (-1, &[0x01]),
1977 (63, &[0x41, 0x7E]),
1978 (-64, &[0x41, 0x7F]),
1979 (64, &[0x41, 0x80]),
1980 (128, &[0x42, 0x00, 0x01]),
1981 (-128, &[0x41, 0xFF]),
1982 (300, &[0x42, 0x58, 0x02]),
1983 ];
1984
1985 for &(value, expected) in cases {
1986 let mut buf = Vec::new();
1987 let written = SafeInt::from(value).encode(&mut buf).unwrap();
1988 assert_eq!(written, buf.len());
1989 assert_eq!(buf, expected);
1990 }
1991}
1992
1993#[test]
1994fn lencode_safe_int_large_encoding_structure() {
1995 let base = BigInt::from(1u8) << 200usize;
1996 let values = [
1997 SafeInt::from_raw(base.clone()),
1998 SafeInt::from_raw(base.clone() + BigInt::from(0x1234u32)),
1999 SafeInt::from_raw(-base),
2000 ];
2001
2002 for value in values {
2003 let mut buf = Vec::new();
2004 value.encode(&mut buf).unwrap();
2005
2006 let raw = value.raw();
2007 let zigzag = if raw.is_negative() {
2008 let magnitude = (-raw).to_biguint().expect("negative magnitude");
2009 (magnitude << 1usize) - BigUint::from(1u8)
2010 } else {
2011 let magnitude = raw.to_biguint().unwrap_or(BigUint::ZERO);
2012 magnitude << 1usize
2013 };
2014 let payload = zigzag.to_bytes_le();
2015 assert!(payload.len() > 1);
2016 assert_eq!(buf[0], LENCODE_SAFE_INT_SIZE_LARGE | (payload.len() as u8));
2017 assert_eq!(&buf[1..], payload.as_slice());
2018 }
2019}
2020
2021#[test]
2022fn lencode_safe_int_matches_varint_bytes() {
2023 let values = [
2024 SafeInt::from(0),
2025 SafeInt::from(42),
2026 SafeInt::from(-42),
2027 SafeInt::from(1_000_000),
2028 SafeInt::from(-1_000_000),
2029 ];
2030
2031 for value in values {
2032 let raw = value.raw();
2033 let zigzag = if raw.is_negative() {
2034 let magnitude = (-raw).to_biguint().expect("negative magnitude");
2035 (magnitude << 1usize) - BigUint::from(1u8)
2036 } else {
2037 let magnitude = raw.to_biguint().unwrap_or(BigUint::ZERO);
2038 magnitude << 1usize
2039 };
2040 let expected = expected_varint_bytes(&zigzag);
2041
2042 let mut buf = Vec::new();
2043 value.encode(&mut buf).unwrap();
2044 assert_eq!(buf, expected);
2045 }
2046}
2047
2048#[test]
2049fn lencode_safe_int_rejects_zero_length_prefix() {
2050 let data = [LENCODE_SAFE_INT_SIZE_LARGE];
2051 let err = SafeInt::decode(&mut Cursor::new(&data[..])).unwrap_err();
2052 assert!(matches!(err, Error::InvalidData));
2053}
2054
2055#[test]
2056fn lencode_safe_int_rejects_truncated_payload() {
2057 let data = [LENCODE_SAFE_INT_SIZE_LARGE | 0x02u8, 0x01];
2058 let err = SafeInt::decode(&mut Cursor::new(&data[..])).unwrap_err();
2059 assert!(matches!(err, Error::ReaderOutOfData));
2060}
2061
2062#[test]
2063fn lencode_safe_int_large_values_use_bytes_variant() {
2064 let too_large = BigInt::from(1u8) << (8 * LENCODE_MAX_VARINT_BYTES);
2065 let value = SafeInt::from_raw(too_large);
2066 let mut buf = Vec::new();
2067 value.encode(&mut buf).unwrap();
2068
2069 assert_eq!(buf[0], LENCODE_SAFE_INT_VARIANT_BYTES);
2070 let bytes: Vec<u8> = Vec::decode(&mut Cursor::new(&buf[1..])).unwrap();
2071 let zigzag = lencode_zigzag_encode_bigint(value.raw());
2072 assert_eq!(bytes, zigzag.to_bytes_le());
2073
2074 let decoded = SafeInt::decode(&mut Cursor::new(&buf)).unwrap();
2075 assert_eq!(decoded, value);
2076}
2077
2078#[test]
2079fn test_log10() {
2080 let scale = SafeInt::from(1_000_000_000_000_000_000i128);
2081 let precision = 256u32;
2082 let max_iters = Some(DEFAULT_MAX_ITERS);
2083
2084 [
2086 (1_u64, 0_u64),
2087 (10, 1),
2088 (11, 1),
2089 (99, 1),
2090 (101, 2),
2092 (999, 2),
2093 (1001, 3),
2095 (1_000_000_000_000_000_001, 18),
2096 (9_999_999_999_999_999_999, 18),
2097 ]
2098 .into_iter()
2099 .for_each(|(value, expected)| {
2100 assert_eq!(
2101 SafeInt::from(value).log10(&scale, precision, max_iters),
2102 Some(SafeInt::from(expected))
2103 );
2104 });
2105
2106 assert_eq!(SafeInt::from(0).log10(&scale, precision, max_iters), None);
2107 assert_eq!(SafeInt::from(-1).log10(&scale, precision, max_iters), None);
2108}