1mod add;
2mod bitand;
3mod bitor;
4mod bitxor;
5mod cmp;
6mod debug;
7mod default;
8mod display;
9mod div;
10mod from;
11mod index;
12mod mul;
13mod neg;
14mod partial_eq;
15mod pow;
16mod radix;
17mod rem;
18mod shl;
19mod shr;
20mod sub;
21#[cfg(test)]
22mod test_util;
23mod to_f64;
24
25use core::{cmp::Ordering, iter::once};
26
27use crate::{
28 common::{div_mod::DivMod, iter::Iter, sized_index::SizedIndex, uint::Uint},
29 sign::Sign,
30 vm::{Any, IContainer, IVm, error},
31};
32
33const MAX_WORDS: u64 = 1 << 14;
54
55const RHS_GREATER: &str = "abs_sub_vec: rhs is greater than self";
57
58enum ShiftAmount {
62 Noop,
64 TooWide,
66 Words(u64, u64),
68}
69
70fn trim(words: &mut Vec<u64>) {
79 while words.last() == Some(&0) {
80 words.pop();
81 }
82}
83
84fn cmp_words<T: SizedIndex<usize, Output = u64> + ?Sized>(a: &T, b: &T) -> Ordering {
88 a.length().cmp(&b.length()).then_with(|| {
89 let words = (0..a.length()).rev();
90 words.clone().map(|i| a[i]).cmp(words.map(|i| b[i]))
91 })
92}
93
94fn sub_words_borrow(a: &mut [u64], b: impl IntoIterator<Item = u64>) -> bool {
102 let mut b = b.into_iter();
103 let mut borrow = false;
104 for word in a.iter_mut() {
105 let (diff, under_b) = word.overflowing_sub(b.next().unwrap_or(0));
106 let (diff, under_borrow) = diff.overflowing_sub(borrow as u64);
107 *word = diff;
108 borrow = under_b || under_borrow;
109 }
110 borrow
111}
112
113fn sub_words_assign(a: &mut Vec<u64>, b: &[u64]) {
118 sub_words_borrow(a, b.iter().copied());
119 trim(a);
120}
121
122fn add_one(words: &mut Vec<u64>) {
125 for word in words.iter_mut() {
126 let (sum, overflow) = word.overflowing_add(1);
127 *word = sum;
128 if !overflow {
129 return;
130 }
131 }
132 words.push(1);
133}
134
135fn sub_one(words: &mut [u64]) {
139 for word in words.iter_mut() {
140 let (diff, underflow) = word.overflowing_sub(1);
141 *word = diff;
142 if !underflow {
143 return;
144 }
145 }
146}
147
148fn magnitude_from_twos_complement(mut words: Vec<u64>) -> Vec<u64> {
155 for word in words.iter_mut() {
156 *word = !*word;
157 }
158 add_one(&mut words);
159 trim(&mut words);
160 words
161}
162
163#[derive(Clone)]
173pub struct BigInt<A: IVm>(A::InternalBigInt);
174
175impl<A: IVm> BigInt<A> {
176 pub(crate) fn within_limit(self) -> Result<Self, Any<A>> {
180 if u64::from(self.length()) > MAX_WORDS {
181 return Err(error::bigint_too_large());
182 }
183 Ok(self)
184 }
185
186 pub(crate) fn mul_bounded(self, rhs: Self) -> Self {
191 (self * rhs).expect("a binary64's exact arithmetic is far under BigInt's size limit")
192 }
193
194 pub(crate) fn add_bounded(self, rhs: Self) -> Self {
197 (self + rhs).expect("a binary64's exact arithmetic is far under BigInt's size limit")
198 }
199
200 pub(crate) fn is_zero(&self) -> bool {
204 self.0.items().is_empty()
205 }
206
207 fn sign(&self) -> Sign {
208 *self.0.header()
209 }
210
211 fn unchecked_new(sign: Sign, items: impl IntoIterator<Item = u64>) -> Self {
213 Self(A::InternalBigInt::new_ok(sign, items))
214 }
215
216 pub fn normalize_new(sign: Sign, items: impl IntoIterator<Item = u64>) -> Self {
219 let mut vec: Vec<u64> = items.into_iter().collect();
220 trim(&mut vec);
222 if vec.is_empty() {
223 Self::default()
224 } else {
225 Self::unchecked_new(sign, vec)
226 }
227 }
228
229 fn shift_amount(&self, rhs: &Self) -> ShiftAmount {
231 if self.length() == 0 {
232 return ShiftAmount::Noop;
233 }
234 match rhs.length() {
235 0 => ShiftAmount::Noop,
236 1 => {
237 let (word_shift, bit_shift) = rhs[0].div_mod(64);
238 ShiftAmount::Words(word_shift, bit_shift)
239 }
240 _ => ShiftAmount::TooWide,
241 }
242 }
243
244 fn new_one(sign: Sign, value: u64) -> Self {
245 Self::unchecked_new(sign, once(value))
246 }
247
248 fn add_signed(self, rhs: Self, rhs_sign: Sign) -> Self {
255 let lhs_sign = self.sign();
256 let (sign, vec) = if lhs_sign == rhs_sign {
257 (lhs_sign, self.abs_add_vec(rhs))
258 } else {
259 match self.clone().abs_cmp_vec(rhs.clone()) {
261 Ordering::Equal => return Self::default(),
262 Ordering::Greater => (lhs_sign, self.abs_sub_vec(rhs)),
263 Ordering::Less => (rhs_sign, rhs.abs_sub_vec(self)),
264 }
265 };
266 Self::unchecked_new(sign, vec)
267 }
268
269 pub fn div_mod(self, rhs: Self) -> Result<(Self, Self), Any<A>> {
278 if rhs.is_zero() {
279 return Err(error::division_by_zero());
280 }
281 let lhs_sign = self.sign();
282 let quotient_sign = lhs_sign * rhs.sign();
283 let (quotient, remainder) = self.abs_divmod_vec(rhs);
284 Ok((
285 Self::normalize_new(quotient_sign, quotient),
286 Self::normalize_new(lhs_sign, remainder),
287 ))
288 }
289
290 fn add_to_vec(mut vec: Vec<u64>, index: u32, add: u128) -> Vec<u64> {
291 let sum = vec[index as usize] as u128 + add;
293 vec[index as usize] = sum as u64;
294 let carry = sum >> 64;
295 if carry > 0 {
296 vec = Self::add_to_vec(vec, index + 1, carry);
297 }
298 vec
299 }
300
301 fn assert_normalized(&self) {
304 assert_slice_normalized(self.0.items());
305 }
306
307 fn assert_normalized_with(&self, rhs: &Self) {
310 self.assert_normalized();
311 rhs.assert_normalized();
312 }
313
314 fn abs_cmp_vec(self, rhs: Self) -> Ordering {
319 self.assert_normalized_with(&rhs);
320 cmp_words(self.0.items(), rhs.0.items())
321 }
322
323 fn abs_add_vec(self, rhs: Self) -> Vec<u64> {
324 self.assert_normalized_with(&rhs);
325
326 let mut carry: u128 = 0;
327 let mut out: Vec<u64> = self
328 .index_iter()
329 .zip_longest(rhs.index_iter())
330 .map(|(a, b)| {
331 let sum = a.unwrap_or_default() as u128 + b.unwrap_or_default() as u128 + carry;
332 carry = sum >> 64;
333 sum as u64
334 })
335 .collect();
336
337 if carry > 0 {
338 out.push(carry as u64);
339 }
340
341 assert_slice_normalized(out.as_slice());
343 out
344 }
345
346 fn abs_sub_vec(self, rhs: Self) -> Vec<u64> {
351 self.assert_normalized_with(&rhs);
352
353 if rhs.length() > self.length() {
356 panic!("{RHS_GREATER}");
357 }
358 let mut out: Vec<u64> = self.index_iter().collect();
359 if sub_words_borrow(&mut out, rhs.index_iter()) {
360 panic!("{RHS_GREATER}");
361 }
362 trim(&mut out);
363 out
364 }
365
366 fn abs_divmod_vec(self, rhs: Self) -> (Vec<u64>, Vec<u64>) {
373 self.assert_normalized_with(&rhs);
374
375 let denom: Vec<u64> = rhs.index_iter().collect();
376 let numer: Vec<u64> = self.index_iter().collect();
377
378 let mut quotient: Vec<u64> = vec![0; numer.len()];
379 let mut remainder: Vec<u64> = Vec::new();
380 for bit in (0..numer.len() as u32 * 64).rev() {
381 let numer_bit = (numer[(bit / 64) as usize] >> (bit % 64)) & 1;
382
383 let mut carry = numer_bit;
384 for word in remainder.iter_mut() {
385 let next_carry = *word >> 63;
386 *word = (*word << 1) | carry;
387 carry = next_carry;
388 }
389 if carry != 0 {
390 remainder.push(carry);
391 }
392
393 if cmp_words(remainder.as_slice(), denom.as_slice()) != Ordering::Less {
394 sub_words_assign(&mut remainder, &denom);
395 quotient[(bit / 64) as usize] |= 1u64 << (bit % 64);
396 }
397 }
398
399 trim(&mut quotient);
400 (quotient, remainder)
401 }
402
403 fn twos_complement_words(self, len: u32) -> Vec<u64> {
412 let sign = self.sign();
413 let mut words: Vec<u64> = self.index_iter().collect();
414 words.resize(len as usize, 0);
415 if sign == Sign::Negative {
416 sub_one(&mut words);
417 for word in words.iter_mut() {
418 *word = !*word;
419 }
420 }
421 words
422 }
423
424 fn bitwise_op(
432 self,
433 rhs: Self,
434 word_op: impl Fn(u64, u64) -> u64,
435 result_negative: impl Fn(bool, bool) -> bool,
436 ) -> Self {
437 let self_negative = self.sign() == Sign::Negative;
438 let rhs_negative = rhs.sign() == Sign::Negative;
439 let len = self.length().max(rhs.length());
440 let a = self.twos_complement_words(len);
441 let b = rhs.twos_complement_words(len);
442 let out: Vec<u64> = a
443 .iter()
444 .zip(b.iter())
445 .map(|(&x, &y)| word_op(x, y))
446 .collect();
447 if result_negative(self_negative, rhs_negative) {
448 Self::normalize_new(Sign::Negative, magnitude_from_twos_complement(out))
449 } else {
450 Self::normalize_new(Sign::Positive, out)
451 }
452 }
453}
454
455fn assert_slice_normalized<I: Uint, T: SizedIndex<I, Output = u64> + ?Sized>(v: &T) {
458 if let Some(&last) = v.last()
459 && last == 0
460 {
461 panic!("BigInt is not normalized (has leading zero words)");
462 }
463}
464
465#[cfg(test)]
466mod tests {
467 use super::{
468 add_one, cmp_words, sub_one, sub_words_assign, sub_words_borrow,
469 test_util::{T, int, pos},
470 trim,
471 };
472 use core::cmp::Ordering;
473
474 #[test]
477 fn test_trim() {
478 for (words, trimmed) in [
479 ([].to_vec(), [].to_vec()),
480 ([0].to_vec(), [].to_vec()),
481 ([0, 0].to_vec(), [].to_vec()),
482 ([1, 0, 0].to_vec(), [1].to_vec()),
483 ([0, 1].to_vec(), [0, 1].to_vec()),
484 ([0, 1, 0].to_vec(), [0, 1].to_vec()),
485 ] {
486 let mut words: Vec<u64> = words;
487 trim(&mut words);
488 assert_eq!(words, trimmed);
489 }
490 }
491
492 #[test]
493 fn test_cmp_words() {
494 let cmp = |a: &[u64], b: &[u64]| cmp_words(a, b);
495 assert_eq!(cmp(&[], &[]), Ordering::Equal);
496 assert_eq!(cmp(&[], &[1]), Ordering::Less);
497 assert_eq!(cmp(&[u64::MAX], &[0, 1]), Ordering::Less);
498 assert_eq!(cmp(&[5, 10], &[20, 9]), Ordering::Greater);
499 assert_eq!(cmp(&[20, 9], &[5, 10]), Ordering::Less);
500 assert_eq!(cmp(&[2, 7], &[1, 7]), Ordering::Greater);
501 assert_eq!(cmp(&[1, 7], &[1, 7]), Ordering::Equal);
502 }
503
504 #[test]
505 fn test_sub_words_borrow() {
506 let mut a = [300u64, 2];
508 assert!(!sub_words_borrow(&mut a, [100u64]));
509 assert_eq!(a, [200, 2]);
510 let mut a = [0u64, 0, 1];
512 assert!(!sub_words_borrow(&mut a, [1u64]));
513 assert_eq!(a, [u64::MAX, u64::MAX, 0]);
514 let mut a = [1u64];
516 assert!(sub_words_borrow(&mut a, [2u64]));
517 assert_eq!(a, [u64::MAX]);
518 let mut a = [0u64, 5];
520 assert!(!sub_words_borrow(&mut a, [1u64, 4]));
521 assert_eq!(a, [u64::MAX, 0]);
522 }
523
524 #[test]
525 fn test_sub_words_assign_trims() {
526 let mut a = [0u64, 5].to_vec();
527 sub_words_assign(&mut a, &[1, 4]);
528 assert_eq!(a, [u64::MAX]);
529 let mut a = [7u64, 3].to_vec();
530 sub_words_assign(&mut a, &[7, 3]);
531 assert_eq!(a, []);
532 }
533
534 #[test]
535 fn test_add_one() {
536 for (words, sum) in [
537 ([].to_vec(), [1].to_vec()),
538 ([41].to_vec(), [42].to_vec()),
539 ([u64::MAX, 3].to_vec(), [0, 4].to_vec()),
540 ([u64::MAX, u64::MAX].to_vec(), [0, 0, 1].to_vec()),
541 ] {
542 let mut words: Vec<u64> = words;
543 add_one(&mut words);
544 assert_eq!(words, sum);
545 }
546 }
547
548 #[test]
549 fn test_sub_one() {
550 let mut words = [42u64];
551 sub_one(&mut words);
552 assert_eq!(words, [41]);
553 let mut words = [0u64, 0, 1];
555 sub_one(&mut words);
556 assert_eq!(words, [u64::MAX, u64::MAX, 0]);
557 let mut words = [0u64, 4];
558 sub_one(&mut words);
559 assert_eq!(words, [u64::MAX, 3]);
560 }
561
562 #[test]
563 fn test_abs_cmp_vec_equal_numbers() {
564 let a: T = 12_345u64.into();
565 let b: T = 12_345u64.into();
566 assert_eq!(a.abs_cmp_vec(b), Ordering::Equal);
567 }
568
569 #[test]
570 fn test_abs_cmp_vec_equal_zero() {
571 let a: T = 0u64.into();
572 let b: T = 0u64.into();
573 assert_eq!(a.abs_cmp_vec(b), Ordering::Equal);
574 }
575
576 #[test]
577 fn test_abs_cmp_vec_simple_different_lengths() {
578 let one_digit = pos([100u64]);
579 let two_digits = pos([100u64, 1u64]);
580 assert_eq!(
581 two_digits.clone().abs_cmp_vec(one_digit.clone()),
582 Ordering::Greater
583 );
584 assert_eq!(one_digit.abs_cmp_vec(two_digits), Ordering::Less);
585 }
586
587 #[test]
588 fn test_abs_cmp_vec_same_length_first_greater() {
589 let a: T = 12_346u64.into();
590 let b: T = 12_345u64.into();
591 assert_eq!(a.abs_cmp_vec(b), Ordering::Greater);
592 }
593
594 #[test]
595 fn test_abs_cmp_vec_same_length_first_less() {
596 let a: T = 12_344u64.into();
597 let b: T = 12_345u64.into();
598 assert_eq!(a.abs_cmp_vec(b), Ordering::Less);
599 }
600
601 #[test]
602 fn test_abs_cmp_vec_most_significant_digit_differs() {
603 let a: T = 0x8000_0000_0000_0000u64.into();
604 let b: T = 0x7FFF_FFFF_FFFF_FFFFu64.into();
605 assert_eq!(a.abs_cmp_vec(b), Ordering::Greater);
606 }
607
608 #[test]
609 fn test_abs_cmp_vec_least_significant_digit_differs() {
610 let a: T = 0x1000_0000_0000_0001u64.into();
611 let b: T = 0x1000_0000_0000_0000u64.into();
612 assert_eq!(a.abs_cmp_vec(b), Ordering::Greater);
613 }
614
615 #[test]
616 fn test_abs_cmp_vec_zero_vs_nonzero() {
617 let a: T = 0u64.into();
618 let b: T = 1u64.into();
619 assert_eq!(a.abs_cmp_vec(b), Ordering::Less);
620
621 let a: T = 1u64.into();
622 let b: T = 0u64.into();
623 assert_eq!(a.abs_cmp_vec(b), Ordering::Greater);
624 }
625
626 #[test]
627 fn test_abs_cmp_vec_simple_large_numbers() {
628 let large1: T = 0xFFFF_FFFF_FFFF_FFFFu64.into();
630 let large2: T = 0xFFFF_FFFF_FFFF_FFFEu64.into();
631
632 assert_eq!(
633 large1.clone().abs_cmp_vec(large2.clone()),
634 Ordering::Greater
635 );
636 assert_eq!(large2.clone().abs_cmp_vec(large1.clone()), Ordering::Less);
637 assert_eq!(large1.clone().abs_cmp_vec(large1.clone()), Ordering::Equal);
638 }
639
640 #[test]
641 fn test_abs_cmp_vec_simple_equal() {
642 let large1: T = 0x1234_5678_9ABC_DEF0u64.into();
643 let large2: T = 0x1234_5678_9ABC_DEF0u64.into();
644
645 assert_eq!(large1.abs_cmp_vec(large2), Ordering::Equal);
646 }
647
648 #[test]
649 fn test_abs_cmp_vec_simple_digit_difference() {
650 let large1: T = 0x8000_0000_0000_0000u64.into();
652 let large2: T = 0x7FFF_FFFF_FFFF_FFFFu64.into();
653
654 assert_eq!(large1.abs_cmp_vec(large2), Ordering::Greater);
655 }
656
657 #[test]
658 fn test_abs_cmp_vec_two_digits_higher_word_dominates() {
659 let self_val = pos([5u64, 10u64]);
664 let rhs_val = pos([20u64, 9u64]);
665
666 assert_eq!(self_val.abs_cmp_vec(rhs_val), Ordering::Greater);
667 }
668
669 #[test]
670 fn test_div_mod_pairs_quotient_and_remainder() {
671 for (a, b, q, r) in [
672 (10, 3, 3, 1),
673 (-10, 3, -3, -1),
674 (10, -3, -3, 1),
675 (-10, -3, 3, -1),
676 (-1, 2, 0, -1),
679 (1, -2, 0, 1),
680 (-4, 2, -2, 0),
681 (4, -2, -2, 0),
682 ] {
683 let (quotient, remainder) = int(a).div_mod(int(b)).unwrap();
684 assert_eq!(quotient.sign(), int(q).sign());
686 assert_eq!(remainder.sign(), int(r).sign());
687 assert_eq!(quotient, int(q));
688 assert_eq!(remainder, int(r));
689 }
690 }
691
692 #[test]
693 fn test_div_mod_zero_divisor_throws() {
694 let a: T = 5u64.into();
695 assert!(a.div_mod(T::default()).is_err());
696 }
697
698 #[test]
701 fn test_abs_add_vec_basic() {
702 let a: T = 123u64.into();
703 let b: T = 456u64.into();
704 let result = a.abs_add_vec(b);
705 let expected = pos(result);
706 let expected_value: T = 579u64.into();
707 assert_eq!(expected.abs_cmp_vec(expected_value), Ordering::Equal);
708 }
709
710 #[test]
711 fn test_abs_add_vec_zero() {
712 let a: T = 42u64.into();
713 let b: T = 0u64.into();
714 let result = a.clone().abs_add_vec(b);
715 let result_bigint = pos(result);
716 assert_eq!(result_bigint.abs_cmp_vec(a), Ordering::Equal);
717
718 let c: T = 0u64.into();
719 let d: T = 17u64.into();
720 let result2 = c.abs_add_vec(d.clone());
721 let result2_bigint = pos(result2);
722 assert_eq!(result2_bigint.abs_cmp_vec(d), Ordering::Equal);
723 }
724
725 #[test]
726 fn test_abs_add_vec_carry() {
727 let a: T = u64::MAX.into();
728 let b: T = 1u64.into();
729 let result = a.abs_add_vec(b);
730
731 assert_eq!(result.len(), 2);
733 assert_eq!(result[0], 0u64);
734 assert_eq!(result[1], 1u64);
735 }
736
737 #[test]
738 fn test_abs_add_vec_different_lengths() {
739 let small = pos([100u64]);
740 let large = pos([200u64, 1u64]);
741
742 let result1 = small.clone().abs_add_vec(large.clone());
743 let result2 = large.abs_add_vec(small);
744
745 assert_eq!(result1.len(), result2.len());
747 for (a, b) in result1.iter().zip(result2.iter()) {
748 assert_eq!(a, b);
749 }
750
751 assert_eq!(result1[0], 300u64);
753 assert_eq!(result1[1], 1u64);
754 }
755
756 #[test]
757 fn test_abs_add_vec_multiple_carries() {
758 let a = pos([u64::MAX, u64::MAX]);
759 let b: T = 1u64.into();
760
761 let result = a.abs_add_vec(b);
762
763 assert_eq!(result.len(), 3);
765 assert_eq!(result[0], 0u64);
766 assert_eq!(result[1], 0u64);
767 assert_eq!(result[2], 1u64);
768 }
769
770 #[test]
771 fn test_abs_add_vec_same_large_numbers() {
772 let large: T = 0x7FFF_FFFF_FFFF_FFFFu64.into();
773 let result = large.clone().abs_add_vec(large);
774 let result_bigint = pos(result);
775
776 let expected: T = 0xFFFF_FFFF_FFFF_FFFEu64.into();
777 assert_eq!(result_bigint.abs_cmp_vec(expected), Ordering::Equal);
778 }
779
780 #[test]
781 fn test_abs_add_vec_no_carry() {
782 let a: T = 1_000u64.into();
783 let b: T = 2_000u64.into();
784 let result = a.abs_add_vec(b);
785
786 assert_eq!(result.len(), 1);
787 assert_eq!(result[0], 3_000u64);
788 }
789
790 #[test]
791 fn test_abs_add_vec_both_zero() {
792 let a: T = 0u64.into();
793 let b: T = 0u64.into();
794 let result = a.abs_add_vec(b);
795
796 assert!(result.is_empty() || (result.len() == 1 && result[0] == 0u64));
798 }
799
800 #[test]
803 fn test_abs_sub_vec_basic() {
804 let a: T = 456u64.into();
805 let b: T = 123u64.into();
806 let result = a.abs_sub_vec(b);
807 let result_bigint = pos(result);
808 let expected: T = 333u64.into();
809 assert_eq!(result_bigint.abs_cmp_vec(expected), Ordering::Equal);
810 }
811
812 #[test]
813 fn test_abs_sub_vec_same_numbers() {
814 let a: T = 12_345u64.into();
815 let result = a.clone().abs_sub_vec(a);
816
817 assert!(result.is_empty() || (result.len() == 1 && result[0] == 0u64));
819 }
820
821 #[test]
822 fn test_abs_sub_vec_subtract_zero() {
823 let a: T = 42u64.into();
824 let b: T = 0u64.into();
825 let result = a.clone().abs_sub_vec(b);
826 let result_bigint = pos(result);
827 assert_eq!(result_bigint.abs_cmp_vec(a), Ordering::Equal);
828 }
829
830 #[test]
831 fn test_abs_sub_vec_with_borrow() {
832 let a: T = 1_000u64.into();
833 let b: T = 1u64.into();
834 let result = a.abs_sub_vec(b);
835
836 assert_eq!(result.len(), 1);
837 assert_eq!(result[0], 999u64);
838 }
839
840 #[test]
841 fn test_abs_sub_vec_different_lengths() {
842 let large = pos([300u64, 2u64]);
843 let small = pos([100u64]);
844
845 let result = large.abs_sub_vec(small);
846
847 assert_eq!(result.len(), 2);
849 assert_eq!(result[0], 200u64);
850 assert_eq!(result[1], 2u64);
851 }
852
853 #[test]
854 fn test_abs_sub_vec_borrow_propagation() {
855 let a = pos([0u64, 1u64]); let b: T = 1u64.into();
857
858 let result = a.abs_sub_vec(b);
859
860 assert_eq!(result.len(), 1);
862 assert_eq!(result[0], u64::MAX);
863 }
864
865 #[test]
866 fn test_abs_sub_vec_leading_zero_trim() {
867 let a = pos([100u64, 1u64]);
868 let b = pos([100u64, 1u64]);
869
870 let result = a.abs_sub_vec(b);
871
872 assert!(result.is_empty() || (result.len() == 1 && result[0] == 0u64));
874 }
875
876 #[test]
877 fn test_abs_sub_vec_large_numbers() {
878 let a: T = u64::MAX.into();
879 let b: T = (u64::MAX - 1_000u64).into();
880 let result = a.abs_sub_vec(b);
881
882 assert_eq!(result.len(), 1);
883 assert_eq!(result[0], 1_000u64);
884 }
885
886 #[test]
887 fn test_abs_sub_vec_no_borrow() {
888 let a: T = 5_000u64.into();
889 let b: T = 2_000u64.into();
890 let result = a.abs_sub_vec(b);
891
892 assert_eq!(result.len(), 1);
893 assert_eq!(result[0], 3_000u64);
894 }
895
896 #[test]
897 #[should_panic(expected = "abs_sub_vec: rhs is greater than self")]
898 fn test_abs_sub_vec_panic_rhs_greater() {
899 let a: T = 100u64.into();
900 let b: T = 200u64.into();
901 let _ = a.abs_sub_vec(b); }
903
904 #[test]
905 #[should_panic(expected = "abs_sub_vec: rhs is greater than self")]
906 fn test_abs_sub_vec_panic_different_lengths() {
907 let small = pos([100u64]);
908 let large = pos([100u64, 1u64]);
909 let _ = small.abs_sub_vec(large); }
911}