1use std::fmt::Debug;
2
3use crate::divisibility::*;
4use crate::homomorphism::*;
5use crate::ordered::*;
6use crate::pid::*;
7use crate::reduce_lift::poly_eval::EvalPolyLocallyRing;
8use crate::reduce_lift::poly_factor_gcd::IntegerPolyGCDRing;
9use crate::ring::*;
10
11#[cfg(feature = "mpir")]
16pub type BigIntRing = crate::rings::mpir::MPZ;
17#[cfg(not(feature = "mpir"))]
22pub type BigIntRing = crate::rings::rust_bigint::RustBigintRing;
23#[cfg(feature = "mpir")]
28pub type BigIntRingBase = crate::rings::mpir::MPZBase;
29#[cfg(not(feature = "mpir"))]
34pub type BigIntRingBase = crate::rings::rust_bigint::RustBigintRingBase;
35
36pub trait IntegerRing:
51 Domain + EuclideanRing + OrderedRing + HashableElRing + IntegerPolyGCDRing + EvalPolyLocallyRing + Debug
52{
53 fn to_float_approx(&self, value: &Self::Element) -> f64;
87
88 fn from_float_approx(&self, value: f64) -> Option<Self::Element>;
97
98 fn abs_is_bit_set(&self, value: &Self::Element, i: usize) -> bool;
111
112 fn abs_highest_set_bit(&self, value: &Self::Element) -> Option<usize>;
125
126 fn abs_lowest_set_bit(&self, value: &Self::Element) -> Option<usize>;
140
141 fn euclidean_div_pow_2(&self, value: &mut Self::Element, power: usize);
155
156 fn mul_pow_2(&self, value: &mut Self::Element, power: usize);
158
159 fn get_uniformly_random_bits<G: FnMut() -> u64>(&self, log2_bound_exclusive: usize, rng: G) -> Self::Element;
162
163 fn rounded_div(&self, lhs: Self::Element, rhs: &Self::Element) -> Self::Element {
187 let mut rhs_half = self.abs(self.clone_el(rhs));
188 self.euclidean_div_pow_2(&mut rhs_half, 1);
189 if self.is_neg(&lhs) {
190 return self.euclidean_div(self.sub(lhs, rhs_half), rhs);
191 } else {
192 return self.euclidean_div(self.add(lhs, rhs_half), rhs);
193 }
194 }
195
196 fn ceil_div(&self, lhs: Self::Element, rhs: &Self::Element) -> Self::Element {
214 assert!(!self.is_zero(rhs));
215 if self.is_zero(&lhs) {
216 return self.zero();
217 }
218 let one = self.one();
219 return match (self.is_pos(&lhs), self.is_pos(rhs)) {
220 (true, true) => self.add(self.euclidean_div(self.sub_ref_snd(lhs, &one), rhs), one),
221 (false, true) => self.euclidean_div(lhs, rhs),
222 (true, false) => self.euclidean_div(lhs, rhs),
223 (false, false) => self.add(self.euclidean_div(self.add_ref_snd(lhs, &one), rhs), one),
224 };
225 }
226
227 fn floor_div(&self, lhs: Self::Element, rhs: &Self::Element) -> Self::Element {
245 self.negate(self.ceil_div(self.negate(lhs), rhs))
246 }
247
248 fn power_of_two(&self, power: usize) -> Self::Element {
250 let mut result = self.one();
251 self.mul_pow_2(&mut result, power);
252 return result;
253 }
254
255 fn representable_bits(&self) -> Option<usize>;
258
259 fn parse(&self, string: &str, base: u32) -> Result<Self::Element, ()> {
266 generic_impls::parse(RingRef::new(self), string, base)
267 }
268}
269
270impl<I, J> CanHomFrom<I> for J
271where
272 I: ?Sized + IntegerRing,
273 J: ?Sized + IntegerRing,
274{
275 type Homomorphism = ();
276
277 fn has_canonical_hom(&self, _: &I) -> Option<Self::Homomorphism> { Some(()) }
278
279 fn map_in(&self, from: &I, el: <I as RingBase>::Element, _: &Self::Homomorphism) -> Self::Element {
280 int_cast(el, &RingRef::new(self), &RingRef::new(from))
281 }
282
283 default fn map_in_ref(&self, from: &I, el: &<I as RingBase>::Element, hom: &Self::Homomorphism) -> Self::Element {
284 <J as CanHomFrom<I>>::map_in(self, from, from.clone_el(el), hom)
285 }
286}
287
288impl<I, J> CanIsoFromTo<I> for J
289where
290 I: ?Sized + IntegerRing,
291 J: ?Sized + IntegerRing,
292{
293 type Isomorphism = ();
294
295 fn has_canonical_iso(&self, _: &I) -> Option<Self::Isomorphism> { Some(()) }
296
297 fn map_out(&self, from: &I, el: Self::Element, _: &Self::Isomorphism) -> <I as RingBase>::Element {
298 int_cast(el, &RingRef::new(from), &RingRef::new(self))
299 }
300}
301
302pub trait IntCast<F: ?Sized + IntegerRing>: IntegerRing {
319 fn cast(&self, from: &F, value: F::Element) -> Self::Element;
324}
325
326impl<F: ?Sized + IntegerRing, T: ?Sized + IntegerRing> IntCast<F> for T {
327 default fn cast(&self, from: &F, value: F::Element) -> Self::Element {
328 generic_impls::map_from_integer_ring(RingRef::new(from), RingRef::new(self), value)
329 }
330}
331
332pub fn int_cast<T: RingStore, F: RingStore>(value: El<F>, to: T, from: F) -> El<T>
352where
353 T::Type: IntegerRing,
354 F::Type: IntegerRing,
355{
356 <T::Type as IntCast<F::Type>>::cast(to.get_ring(), from.get_ring(), value)
357}
358
359#[stability::unstable(feature = "enable")]
378pub fn binomial<I>(n: El<I>, k: &El<I>, ring: I) -> El<I>
379where
380 I: RingStore + Copy,
381 I::Type: IntegerRing,
382{
383 if ring.is_neg(&n) {
384 let mut result = binomial(ring.sub(ring.sub_ref_fst(k, n), ring.one()), k, ring);
385 if !ring.is_even(k) {
386 ring.negate_inplace(&mut result);
387 }
388 return result;
389 } else if ring.is_neg(k) || ring.is_gt(k, &n) {
390 return ring.zero();
391 } else {
392 let n_neg_k = ring.sub_ref(&n, k);
395 if ring.is_lt(&n_neg_k, k) {
396 return binomial(n, &n_neg_k, ring);
397 }
398 let mut result = ring.one();
399 let mut i = ring.one();
400 while ring.is_leq(&i, k) {
401 ring.mul_assign(&mut result, ring.sub_ref_snd(ring.add_ref_fst(&n, ring.one()), &i));
402 result = ring.checked_div(&result, &i).unwrap();
403 ring.add_assign(&mut i, ring.one());
404 }
405 return result;
406 }
407}
408
409#[stability::unstable(feature = "enable")]
410pub fn factorial<I>(n: &El<I>, ring: I) -> El<I>
411where
412 I: RingStore + Copy,
413 I::Type: IntegerRing,
414{
415 let mut current = ring.zero();
416 let one = ring.one();
417 return ring.prod((0..).map_while(|_| {
418 if ring.is_lt(¤t, n) {
419 ring.add_assign_ref(&mut current, &one);
420 return Some(ring.clone_el(¤t));
421 } else {
422 return None;
423 }
424 }));
425}
426
427pub trait IntegerRingStore: RingStore
430where
431 Self::Type: IntegerRing,
432{
433 delegate! { IntegerRing, fn to_float_approx(&self, value: &El<Self>) -> f64 }
434 delegate! { IntegerRing, fn from_float_approx(&self, value: f64) -> Option<El<Self>> }
435 delegate! { IntegerRing, fn abs_is_bit_set(&self, value: &El<Self>, i: usize) -> bool }
436 delegate! { IntegerRing, fn abs_highest_set_bit(&self, value: &El<Self>) -> Option<usize> }
437 delegate! { IntegerRing, fn abs_lowest_set_bit(&self, value: &El<Self>) -> Option<usize> }
438 delegate! { IntegerRing, fn euclidean_div_pow_2(&self, value: &mut El<Self>, power: usize) -> () }
439 delegate! { IntegerRing, fn mul_pow_2(&self, value: &mut El<Self>, power: usize) -> () }
440 delegate! { IntegerRing, fn power_of_two(&self, power: usize) -> El<Self> }
441 delegate! { IntegerRing, fn rounded_div(&self, lhs: El<Self>, rhs: &El<Self>) -> El<Self> }
442 delegate! { IntegerRing, fn floor_div(&self, lhs: El<Self>, rhs: &El<Self>) -> El<Self> }
443 delegate! { IntegerRing, fn ceil_div(&self, lhs: El<Self>, rhs: &El<Self>) -> El<Self> }
444 delegate! { IntegerRing, fn parse(&self, string: &str, base: u32) -> Result<El<Self>, ()> }
445
446 fn get_uniformly_random<G: FnMut() -> u64>(&self, bound_exclusive: &El<Self>, mut rng: G) -> El<Self> {
451 assert!(self.is_gt(bound_exclusive, &self.zero()));
452 let log2_ceil_bound = self.abs_highest_set_bit(bound_exclusive).unwrap() + 1;
453 let mut result = self.get_ring().get_uniformly_random_bits(log2_ceil_bound, &mut rng);
454 while self.is_geq(&result, bound_exclusive) {
455 result = self.get_ring().get_uniformly_random_bits(log2_ceil_bound, &mut rng);
456 }
457 return result;
458 }
459
460 fn abs_log2_floor(&self, value: &El<Self>) -> Option<usize> { self.abs_highest_set_bit(value) }
464
465 fn abs_log2_ceil(&self, value: &El<Self>) -> Option<usize> {
467 let highest_bit = self.abs_highest_set_bit(value)?;
468 if self.abs_lowest_set_bit(value).unwrap() == highest_bit {
469 return Some(highest_bit);
470 } else {
471 return Some(highest_bit + 1);
472 }
473 }
474
475 fn is_even(&self, value: &El<Self>) -> bool { !self.abs_is_bit_set(value, 0) }
477
478 fn is_odd(&self, value: &El<Self>) -> bool { !self.is_even(value) }
480
481 fn half_exact(&self, mut value: El<Self>) -> El<Self> {
483 assert!(self.is_even(&value));
484 self.euclidean_div_pow_2(&mut value, 1);
485 return value;
486 }
487}
488
489impl<R> IntegerRingStore for R
490where
491 R: RingStore,
492 R::Type: IntegerRing,
493{
494}
495
496pub mod generic_impls {
500 use super::*;
501 use crate::primitive_int::*;
502
503 #[stability::unstable(feature = "enable")]
504 pub fn map_from_integer_ring<I, R>(from: I, to: R, mut x: El<I>) -> El<R>
505 where
506 I: RingStore,
507 I::Type: IntegerRing,
508 R: RingStore,
509 {
510 let basis = to.int_hom().map(1 << 16);
511 let is_neg = if from.is_neg(&x) {
512 from.negate_inplace(&mut x);
513 true
514 } else {
515 false
516 };
517 let mut current = to.zero();
518 let mut current_pow = to.one();
519 while !from.is_zero(&x) {
520 let mut quo = from.clone_el(&x);
521 from.euclidean_div_pow_2(&mut quo, 16);
522 let mut rem = from.clone_el(&quo);
523 from.mul_pow_2(&mut rem, 16);
524 from.sub_self_assign(&mut rem, x);
525 let rem = int_cast(rem, StaticRing::<i32>::RING, &from);
526 to.add_assign(&mut current, to.mul_ref_snd(to.int_hom().map(rem), ¤t_pow));
527 x = quo;
528 to.mul_assign_ref(&mut current_pow, &basis);
529 }
530 if is_neg {
531 return to.negate(current);
532 } else {
533 return current;
534 }
535 }
536
537 #[stability::unstable(feature = "enable")]
538 pub fn parse<I>(ring: I, string: &str, base: u32) -> Result<El<I>, ()>
539 where
540 I: RingStore,
541 I::Type: IntegerRing,
542 {
543 let (negative, rest) = if string.starts_with('-') {
544 (true, string.split_at(1).1)
545 } else if string.starts_with('+') {
546 (false, string.split_at(1).1)
547 } else {
548 (false, string)
549 };
550 assert!(base >= 2);
551
552 let bits_per_chunk = u32::BITS as usize;
553 assert!(bits_per_chunk <= i64::BITS as usize - 2);
554 let chunk_size = (bits_per_chunk as f32 / (base as f32).log2()).floor() as usize;
555 let it = <str as AsRef<[u8]>>::as_ref(rest)
556 .rchunks(chunk_size)
557 .rev()
558 .map(std::str::from_utf8)
559 .map(|chunk| chunk.map_err(|_| ()))
560 .map(|chunk| chunk.and_then(|n| u64::from_str_radix(n, base).map_err(|_| ())));
561 let chunk_base = ring.pow(int_cast(base as i64, &ring, StaticRing::<i64>::RING), chunk_size);
562 let result = it.fold(Ok(ring.zero()), |current, next| {
563 current.and_then(|mut current| {
564 next.map(|next| {
565 ring.mul_assign_ref(&mut current, &chunk_base);
566 ring.add(current, int_cast(next as i64, &ring, StaticRing::<i64>::RING))
567 })
568 })
569 });
570 if negative {
571 return result.map(|result| ring.negate(result));
572 } else {
573 return result;
574 }
575 }
576}
577
578#[cfg(test)]
579use generic_impls::map_from_integer_ring;
580
581#[cfg(test)]
582use crate::primitive_int::*;
583
584#[allow(missing_docs)]
585#[cfg(any(test, feature = "generic_tests"))]
586pub mod generic_tests {
587
588 use super::*;
589 use crate::ring::El;
590
591 pub fn test_integer_get_uniformly_random<R: RingStore>(ring: R)
592 where
593 R::Type: IntegerRing,
594 {
595 for b in [15, 16] {
596 let bound = ring.int_hom().map(b);
597 let mut rng = oorandom::Rand64::new(1);
598 let elements: Vec<El<R>> = (0..1000)
599 .map(|_| ring.get_uniformly_random(&bound, || rng.rand_u64()))
600 .collect();
601 for i in 0..b {
602 assert!(elements.iter().any(|x| ring.eq_el(x, &ring.int_hom().map(i))))
603 }
604 for x in &elements {
605 assert!(ring.is_lt(x, &bound));
606 }
607 }
608 }
609
610 pub fn test_integer_axioms<R: IntegerRingStore, I: Iterator<Item = El<R>>>(ring: R, edge_case_elements: I)
611 where
612 R::Type: IntegerRing,
613 {
614 let elements = edge_case_elements.collect::<Vec<_>>();
615
616 assert_eq!(None, ring.abs_highest_set_bit(&ring.int_hom().map(0)));
618 assert_eq!(Some(0), ring.abs_highest_set_bit(&ring.int_hom().map(1)));
619 assert_eq!(Some(1), ring.abs_highest_set_bit(&ring.int_hom().map(2)));
620
621 for a in &elements {
623 let mut ceil_pow_2 = ring.int_hom().map(2);
624 ring.mul_pow_2(&mut ceil_pow_2, ring.abs_highest_set_bit(a).unwrap_or(0));
625 assert!(ring.is_lt(a, &ceil_pow_2));
626 assert!(ring.is_lt(&ring.negate(ring.clone_el(a)), &ceil_pow_2));
627
628 for i in 0..ring.abs_highest_set_bit(a).unwrap_or(0) {
629 let mut pow_2 = ring.one();
630 ring.mul_pow_2(&mut pow_2, i);
631 let mut b = ring.clone_el(a);
632 ring.mul_pow_2(&mut b, i);
633 assert_el_eq!(ring, b, ring.mul(ring.clone_el(a), ring.clone_el(&pow_2)));
634 ring.euclidean_div_pow_2(&mut b, i);
635 assert_el_eq!(ring, b, a);
636 ring.euclidean_div_pow_2(&mut b, i);
637 assert_el_eq!(ring, b, ring.euclidean_div(ring.clone_el(a), &pow_2));
638 }
639 }
640
641 let d = ring.int_hom().map(8);
643 for k in -10..=10 {
644 let mut a = ring.int_hom().map(k);
645 assert_el_eq!(
646 ring,
647 ring.int_hom().map(k / 8),
648 ring.euclidean_div(ring.clone_el(&a), &d)
649 );
650 ring.euclidean_div_pow_2(&mut a, 3);
651 assert_el_eq!(ring, ring.int_hom().map(k / 8), a);
652 }
653 let d = ring.int_hom().map(-8);
654 for k in -10..=10 {
655 let a = ring.int_hom().map(k);
656 assert_el_eq!(
657 ring,
658 ring.int_hom().map(k / -8),
659 ring.euclidean_div(ring.clone_el(&a), &d)
660 );
661 }
662
663 assert_el_eq!(
665 ring,
666 ring.int_hom().map(2),
667 ring.rounded_div(ring.int_hom().map(7), &ring.int_hom().map(3))
668 );
669 assert_el_eq!(
670 ring,
671 ring.int_hom().map(-2),
672 ring.rounded_div(ring.int_hom().map(-7), &ring.int_hom().map(3))
673 );
674 assert_el_eq!(
675 ring,
676 ring.int_hom().map(-2),
677 ring.rounded_div(ring.int_hom().map(7), &ring.int_hom().map(-3))
678 );
679 assert_el_eq!(
680 ring,
681 ring.int_hom().map(2),
682 ring.rounded_div(ring.int_hom().map(-7), &ring.int_hom().map(-3))
683 );
684
685 assert_el_eq!(
686 ring,
687 ring.int_hom().map(3),
688 ring.rounded_div(ring.int_hom().map(8), &ring.int_hom().map(3))
689 );
690 assert_el_eq!(
691 ring,
692 ring.int_hom().map(-3),
693 ring.rounded_div(ring.int_hom().map(-8), &ring.int_hom().map(3))
694 );
695 assert_el_eq!(
696 ring,
697 ring.int_hom().map(-3),
698 ring.rounded_div(ring.int_hom().map(8), &ring.int_hom().map(-3))
699 );
700 assert_el_eq!(
701 ring,
702 ring.int_hom().map(3),
703 ring.rounded_div(ring.int_hom().map(-8), &ring.int_hom().map(-3))
704 );
705
706 assert_el_eq!(
707 ring,
708 ring.int_hom().map(4),
709 ring.rounded_div(ring.int_hom().map(7), &ring.int_hom().map(2))
710 );
711 assert_el_eq!(
712 ring,
713 ring.int_hom().map(-4),
714 ring.rounded_div(ring.int_hom().map(-7), &ring.int_hom().map(2))
715 );
716 assert_el_eq!(
717 ring,
718 ring.int_hom().map(-4),
719 ring.rounded_div(ring.int_hom().map(7), &ring.int_hom().map(-2))
720 );
721 assert_el_eq!(
722 ring,
723 ring.int_hom().map(4),
724 ring.rounded_div(ring.int_hom().map(-7), &ring.int_hom().map(-2))
725 );
726 }
727}
728
729#[test]
730fn test_int_div_assumption() {
731 assert_eq!(-1, -10 / 8);
732 assert_eq!(-1, 10 / -8);
733 assert_eq!(1, 10 / 8);
734 assert_eq!(1, -10 / -8);
735}
736
737#[test]
738fn test_rounded_div() {
739 let ZZ = StaticRing::<i32>::RING;
740 assert_el_eq!(ZZ, 3, ZZ.rounded_div(20, &7));
741 assert_el_eq!(ZZ, -3, ZZ.rounded_div(-20, &7));
742 assert_el_eq!(ZZ, -3, ZZ.rounded_div(20, &-7));
743 assert_el_eq!(ZZ, 3, ZZ.rounded_div(-20, &-7));
744 assert_el_eq!(ZZ, 3, ZZ.rounded_div(22, &7));
745 assert_el_eq!(ZZ, -3, ZZ.rounded_div(-22, &7));
746 assert_el_eq!(ZZ, -3, ZZ.rounded_div(22, &-7));
747 assert_el_eq!(ZZ, 3, ZZ.rounded_div(-22, &-7));
748}
749
750#[test]
751fn test_binomial() {
752 let ZZ = StaticRing::<i32>::RING;
753 assert_eq!(0, binomial(-4, &-1, ZZ));
754 assert_eq!(1, binomial(-4, &0, ZZ));
755 assert_eq!(-4, binomial(-4, &1, ZZ));
756 assert_eq!(10, binomial(-4, &2, ZZ));
757 assert_eq!(-20, binomial(-4, &3, ZZ));
758 assert_eq!(35, binomial(-4, &4, ZZ));
759 assert_eq!(-56, binomial(-4, &5, ZZ));
760
761 assert_eq!(0, binomial(3, &-1, ZZ));
762 assert_eq!(1, binomial(3, &0, ZZ));
763 assert_eq!(3, binomial(3, &1, ZZ));
764 assert_eq!(3, binomial(3, &2, ZZ));
765 assert_eq!(1, binomial(3, &3, ZZ));
766 assert_eq!(0, binomial(3, &4, ZZ));
767
768 assert_eq!(0, binomial(8, &-1, ZZ));
769 assert_eq!(1, binomial(8, &0, ZZ));
770 assert_eq!(8, binomial(8, &1, ZZ));
771 assert_eq!(28, binomial(8, &2, ZZ));
772 assert_eq!(56, binomial(8, &3, ZZ));
773 assert_eq!(70, binomial(8, &4, ZZ));
774
775 assert_eq!(145422675, binomial(30, &14, ZZ));
777}
778
779#[test]
780fn test_factorial() {
781 let ZZ = StaticRing::<i32>::RING;
782 assert_eq!(1, factorial(&0, ZZ));
783 assert_eq!(1, factorial(&1, ZZ));
784 assert_eq!(2, factorial(&2, ZZ));
785 assert_eq!(6, factorial(&3, ZZ));
786 assert_eq!(24, factorial(&4, ZZ));
787}
788
789#[test]
790fn test_ceil_floor_div() {
791 let ZZ = StaticRing::<i32>::RING;
792 for rhs in [-10, -3, -2, -1, 1, 2, 3, 10] {
793 for lhs in [-10, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 10] {
794 let result = ZZ.ceil_div(lhs, &rhs);
795 assert_eq!(i32::div_ceil(lhs, rhs), result);
796 assert_eq!((lhs as f64 / rhs as f64).ceil() as i32, result);
797
798 let result = ZZ.floor_div(lhs, &rhs);
799 assert_eq!(i32::div_floor(lhs, rhs), result);
800 assert_eq!((lhs as f64 / rhs as f64).floor() as i32, result);
801 }
802 }
803}
804
805#[test]
806fn test_parse() {
807 let ZZbig = BigIntRing::RING;
808 assert_el_eq!(&ZZbig, &ZZbig.int_hom().map(3), ZZbig.parse("3", 10).unwrap());
809 assert_el_eq!(
810 &ZZbig,
811 &ZZbig.power_of_two(100),
812 ZZbig.parse("1267650600228229401496703205376", 10).unwrap()
813 );
814 assert_el_eq!(
815 &ZZbig,
816 &ZZbig.power_of_two(100),
817 ZZbig.parse("+1267650600228229401496703205376", 10).unwrap()
818 );
819 assert_el_eq!(
820 &ZZbig,
821 &ZZbig.negate(ZZbig.power_of_two(100)),
822 ZZbig.parse("-1267650600228229401496703205376", 10).unwrap()
823 );
824 assert_el_eq!(
825 &ZZbig,
826 &ZZbig.mul(ZZbig.pow(ZZbig.int_hom().map(11), 26), ZZbig.int_hom().map(10)),
827 ZZbig.parse("a00000000000000000000000000", 11).unwrap()
828 );
829 assert!(ZZbig.parse("238597a", 10).is_err());
830}
831
832#[test]
833fn test_map_from_integer() {
834 let ZZbig = BigIntRing::RING;
835 assert_el_eq!(
836 &ZZbig,
837 ZZbig.parse("0", 10).unwrap(),
838 map_from_integer_ring(ZZbig, ZZbig, ZZbig.parse("0", 10).unwrap())
839 );
840 assert_el_eq!(
841 &ZZbig,
842 ZZbig.parse("-1", 10).unwrap(),
843 map_from_integer_ring(ZZbig, ZZbig, ZZbig.parse("-1", 10).unwrap())
844 );
845 assert_el_eq!(
846 &ZZbig,
847 ZZbig.parse("80934517340527398320561", 10).unwrap(),
848 map_from_integer_ring(ZZbig, ZZbig, ZZbig.parse("80934517340527398320561", 10).unwrap())
849 );
850 assert_el_eq!(
851 &ZZbig,
852 ZZbig.parse("-4861235897136598713465987138952643", 10).unwrap(),
853 map_from_integer_ring(
854 ZZbig,
855 ZZbig,
856 ZZbig.parse("-4861235897136598713465987138952643", 10).unwrap()
857 )
858 );
859}