1use core::ops::*;
5
6#[allow(non_camel_case_types)]
8pub type umax = u128;
9
10#[allow(non_camel_case_types)]
12pub type imax = i128;
13
14const HALF_BITS: u32 = umax::BITS / 2;
15
16#[inline(always)]
18const fn split(v: umax) -> (umax, umax) {
19 (v >> HALF_BITS, v & (umax::MAX >> HALF_BITS))
20}
21
22#[inline(always)]
23const fn div_rem(n: umax, d: umax) -> (umax, umax) {
24 (n / d, n % d)
25}
26
27#[must_use]
28#[allow(non_camel_case_types)]
29#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
30pub struct udouble {
36 pub hi: umax,
38 pub lo: umax,
40}
41
42impl udouble {
43 pub const MAX: Self = Self {
44 lo: umax::MAX,
45 hi: umax::MAX,
46 };
47
48 #[inline]
50 pub const fn widening_add(lhs: umax, rhs: umax) -> Self {
51 let (sum, carry) = lhs.overflowing_add(rhs);
52 udouble {
53 hi: carry as umax,
54 lo: sum,
55 }
56 }
57
58 #[inline]
62 pub const fn widening_mul(lhs: umax, rhs: umax) -> Self {
63 let ((x1, x0), (y1, y0)) = (split(lhs), split(rhs));
64
65 let z2 = x1 * y1;
66 let (c0, z0) = split(x0 * y0); let (c1, z1) = split(x1 * y0 + c0);
68 let z2 = z2 + c1;
69 let (c1, z1) = split(x0 * y1 + z1);
70 Self {
71 hi: z2 + c1,
72 lo: z0 | z1 << HALF_BITS,
73 }
74 }
75
76 #[inline]
79 pub const fn widening_square(x: umax) -> Self {
80 let (x1, x0) = split(x);
82
83 let z2 = x1 * x1;
84 let m = x1 * x0;
85 let (c0, z0) = split(x0 * x0);
86 let (c1, z1) = split(m + c0);
87 let z2 = z2 + c1;
88 let (c1, z1) = split(m + z1);
89 Self {
90 hi: z2 + c1,
91 lo: z0 | z1 << HALF_BITS,
92 }
93 }
94
95 #[inline]
97 pub const fn overflowing_add(&self, rhs: Self) -> (Self, bool) {
98 let (lo, carry) = self.lo.overflowing_add(rhs.lo);
99 let (hi, of1) = self.hi.overflowing_add(rhs.hi);
100 let (hi, of2) = hi.overflowing_add(carry as umax);
101 (Self { lo, hi }, of1 || of2)
102 }
103
104 #[allow(dead_code)]
106 fn overflowing_mul(&self, rhs: Self) -> (Self, bool) {
107 let c2 = self.hi != 0 && rhs.hi != 0;
108 let Self { lo: z0, hi: c0 } = Self::widening_mul(self.lo, rhs.lo);
109 let (z1x, c1x) = umax::overflowing_mul(self.lo, rhs.hi);
110 let (z1y, c1y) = umax::overflowing_mul(self.hi, rhs.lo);
111 let (z1z, c1z) = umax::overflowing_add(z1x, z1y);
112 let (z1, c1) = z1z.overflowing_add(c0);
113 (Self { hi: z1, lo: z0 }, c1x | c1y | c1z | c1 | c2)
114 }
115
116 #[inline]
119 pub const fn overflowing_mul1(&self, rhs: umax) -> (Self, bool) {
120 let Self { lo: z0, hi: c0 } = Self::widening_mul(self.lo, rhs);
121 let (z1, c1) = self.hi.overflowing_mul(rhs);
122 let (z1, cs1) = z1.overflowing_add(c0);
123 (Self { hi: z1, lo: z0 }, c1 | cs1)
124 }
125
126 #[must_use]
129 #[inline]
130 pub fn checked_mul1(&self, rhs: umax) -> Option<Self> {
131 let Self { lo: z0, hi: c0 } = Self::widening_mul(self.lo, rhs);
132 let z1 = self.hi.checked_mul(rhs)?.checked_add(c0)?;
133 Some(Self { hi: z1, lo: z0 })
134 }
135
136 #[must_use]
138 #[inline]
139 pub fn checked_shl(self, rhs: u32) -> Option<Self> {
140 if rhs < umax::BITS * 2 {
141 Some(self << rhs)
142 } else {
143 None
144 }
145 }
146
147 #[must_use]
149 #[inline]
150 pub fn checked_shr(self, rhs: u32) -> Option<Self> {
151 if rhs < umax::BITS * 2 {
152 Some(self >> rhs)
153 } else {
154 None
155 }
156 }
157
158 #[inline]
160 pub const fn shl_u32(self, rhs: u32) -> Self {
161 match rhs {
162 0 => self,
163 s if s >= umax::BITS => Self {
164 hi: self.lo << (s - umax::BITS),
165 lo: 0,
166 },
167 s => Self {
168 lo: self.lo << s,
169 hi: (self.hi << s) | (self.lo >> (umax::BITS - s)),
170 },
171 }
172 }
173
174 #[inline]
176 pub const fn shr_u32(self, rhs: u32) -> Self {
177 match rhs {
178 0 => self,
179 s if s >= umax::BITS => Self {
180 lo: self.hi >> (rhs - umax::BITS),
181 hi: 0,
182 },
183 s => Self {
184 hi: self.hi >> s,
185 lo: (self.lo >> s) | (self.hi << (umax::BITS - s)),
186 },
187 }
188 }
189}
190
191impl From<umax> for udouble {
192 #[inline]
193 fn from(v: umax) -> Self {
194 Self { lo: v, hi: 0 }
195 }
196}
197
198impl Add for udouble {
199 type Output = udouble;
200
201 #[inline]
203 fn add(self, rhs: Self) -> Self::Output {
204 let (lo, carry) = self.lo.overflowing_add(rhs.lo);
205 let (hi_mid, overflow1) = self.hi.overflowing_add(rhs.hi);
206 let (hi, overflow2) = hi_mid.overflowing_add(umax::from(carry));
207 debug_assert!(
208 !(overflow1 || overflow2),
209 "udouble addition overflowed 256-bit width"
210 );
211 Self { lo, hi }
212 }
213}
214impl Add<umax> for udouble {
216 type Output = udouble;
217 #[inline]
218 fn add(self, rhs: umax) -> Self::Output {
219 let (lo, carry) = self.lo.overflowing_add(rhs);
220 let hi = if carry { self.hi + 1 } else { self.hi };
221 Self { lo, hi }
222 }
223}
224impl AddAssign for udouble {
225 #[inline]
226 fn add_assign(&mut self, rhs: Self) {
227 let (lo, carry) = self.lo.overflowing_add(rhs.lo);
228 let (hi_mid, overflow1) = self.hi.overflowing_add(rhs.hi);
229 let (hi, overflow2) = hi_mid.overflowing_add(umax::from(carry));
230 debug_assert!(
231 !(overflow1 || overflow2),
232 "udouble addition overflowed 256-bit width"
233 );
234 self.lo = lo;
235 self.hi = hi;
236 }
237}
238impl AddAssign<umax> for udouble {
239 #[inline]
240 fn add_assign(&mut self, rhs: umax) {
241 let (lo, carry) = self.lo.overflowing_add(rhs);
242 self.lo = lo;
243 if carry {
244 self.hi += 1
245 }
246 }
247}
248
249impl Sub for udouble {
251 type Output = Self;
252 #[inline]
253 fn sub(self, rhs: Self) -> Self::Output {
254 let carry = self.lo < rhs.lo;
255 let lo = self.lo.wrapping_sub(rhs.lo);
256 let (hi_mid, overflow1) = self.hi.overflowing_sub(rhs.hi);
257 let (hi, overflow2) = hi_mid.overflowing_sub(umax::from(carry));
258 debug_assert!(
259 !(overflow1 || overflow2),
260 "udouble subtraction underflowed 256-bit width"
261 );
262 Self { lo, hi }
263 }
264}
265impl Sub<umax> for udouble {
266 type Output = Self;
267 #[inline]
268 fn sub(self, rhs: umax) -> Self::Output {
269 let carry = self.lo < rhs;
270 let lo = self.lo.wrapping_sub(rhs);
271 let hi = if carry { self.hi - 1 } else { self.hi };
272 Self { lo, hi }
273 }
274}
275impl SubAssign for udouble {
277 #[inline]
278 fn sub_assign(&mut self, rhs: Self) {
279 let carry = self.lo < rhs.lo;
280 self.lo = self.lo.wrapping_sub(rhs.lo);
281 let (hi_mid, overflow1) = self.hi.overflowing_sub(rhs.hi);
282 let (hi, overflow2) = hi_mid.overflowing_sub(umax::from(carry));
283 debug_assert!(
284 !(overflow1 || overflow2),
285 "udouble subtraction underflowed 256-bit width"
286 );
287 self.hi = hi;
288 }
289}
290impl SubAssign<umax> for udouble {
291 #[inline]
292 fn sub_assign(&mut self, rhs: umax) {
293 let carry = self.lo < rhs;
294 self.lo = self.lo.wrapping_sub(rhs);
295 if carry {
296 self.hi -= 1;
297 }
298 }
299}
300
301macro_rules! impl_sh_ops {
302 ($t:ty) => {
303 impl Shl<$t> for udouble {
305 type Output = Self;
306 #[inline]
307 fn shl(self, rhs: $t) -> Self::Output {
308 match rhs {
309 0 => self, s if s >= umax::BITS as $t => Self {
311 hi: self.lo << (s - umax::BITS as $t),
312 lo: 0,
313 },
314 s => Self {
315 lo: self.lo << s,
316 hi: (self.hi << s) | (self.lo >> (umax::BITS as $t - s)),
317 },
318 }
319 }
320 }
321 impl ShlAssign<$t> for udouble {
323 #[inline]
324 fn shl_assign(&mut self, rhs: $t) {
325 match rhs {
326 0 => {}
327 s if s >= umax::BITS as $t => {
328 self.hi = self.lo << (s - umax::BITS as $t);
329 self.lo = 0;
330 }
331 s => {
332 self.hi <<= s;
333 self.hi |= self.lo >> (umax::BITS as $t - s);
334 self.lo <<= s;
335 }
336 }
337 }
338 }
339 impl Shr<$t> for udouble {
341 type Output = Self;
342 #[inline]
343 fn shr(self, rhs: $t) -> Self::Output {
344 match rhs {
345 0 => self,
346 s if s >= umax::BITS as $t => Self {
347 lo: self.hi >> (rhs - umax::BITS as $t),
348 hi: 0,
349 },
350 s => Self {
351 hi: self.hi >> s,
352 lo: (self.lo >> s) | (self.hi << (umax::BITS as $t - s)),
353 },
354 }
355 }
356 }
357 impl ShrAssign<$t> for udouble {
359 #[inline]
360 fn shr_assign(&mut self, rhs: $t) {
361 match rhs {
362 0 => {}
363 s if s >= umax::BITS as $t => {
364 self.lo = self.hi >> (rhs - umax::BITS as $t);
365 self.hi = 0;
366 }
367 s => {
368 self.lo >>= s;
369 self.lo |= self.hi << (umax::BITS as $t - s);
370 self.hi >>= s;
371 }
372 }
373 }
374 }
375 };
376}
377
378impl_sh_ops!(u8);
380impl_sh_ops!(u16);
381impl_sh_ops!(u32);
382
383impl BitAnd for udouble {
385 type Output = Self;
386 #[inline]
387 fn bitand(self, rhs: Self) -> Self::Output {
388 Self {
389 lo: self.lo & rhs.lo,
390 hi: self.hi & rhs.hi,
391 }
392 }
393}
394impl BitAndAssign for udouble {
396 #[inline]
397 fn bitand_assign(&mut self, rhs: Self) {
398 self.lo &= rhs.lo;
399 self.hi &= rhs.hi;
400 }
401}
402impl BitOr for udouble {
404 type Output = Self;
405 #[inline]
406 fn bitor(self, rhs: Self) -> Self::Output {
407 Self {
408 lo: self.lo | rhs.lo,
409 hi: self.hi | rhs.hi,
410 }
411 }
412}
413impl BitOrAssign for udouble {
415 #[inline]
416 fn bitor_assign(&mut self, rhs: Self) {
417 self.lo |= rhs.lo;
418 self.hi |= rhs.hi;
419 }
420}
421impl BitXor for udouble {
423 type Output = Self;
424 #[inline]
425 fn bitxor(self, rhs: Self) -> Self::Output {
426 Self {
427 lo: self.lo ^ rhs.lo,
428 hi: self.hi ^ rhs.hi,
429 }
430 }
431}
432impl BitXorAssign for udouble {
434 #[inline]
435 fn bitxor_assign(&mut self, rhs: Self) {
436 self.lo ^= rhs.lo;
437 self.hi ^= rhs.hi;
438 }
439}
440impl Not for udouble {
442 type Output = Self;
443 #[inline]
444 fn not(self) -> Self::Output {
445 Self {
446 lo: !self.lo,
447 hi: !self.hi,
448 }
449 }
450}
451
452impl udouble {
453 #[must_use]
455 #[inline]
456 pub const fn leading_zeros(self) -> u32 {
457 if self.hi == 0 {
458 self.lo.leading_zeros() + umax::BITS
459 } else {
460 self.hi.leading_zeros()
461 }
462 }
463
464 #[allow(dead_code)]
467 fn div_rem_2by2(self, other: Self) -> (Self, Self) {
468 let mut n = self; let mut d = other; let mut q = Self { lo: 0, hi: 0 }; let nbits = (2 * umax::BITS - n.leading_zeros()) as u16; let dbits = (2 * umax::BITS - d.leading_zeros()) as u16;
474 assert!(dbits != 0, "division by zero");
475
476 if nbits < dbits {
478 return (q, n);
479 }
480
481 let mut shift = nbits - dbits;
483 d <<= shift;
484 loop {
485 if n >= d {
486 q += 1;
487 n -= d;
488 }
489 if shift == 0 {
490 break;
491 }
492
493 d >>= 1u8;
494 q <<= 1u8;
495 shift -= 1;
496 }
497 (q, n)
498 }
499
500 #[must_use]
504 pub const fn div_rem_2by1(self, other: umax) -> (umax, umax) {
505 const B: umax = 1 << HALF_BITS; let s = other.leading_zeros();
510 let (n, d) = (self.shl_u32(s), other << s); let (d1, d0) = split(d);
512 let (n1, n0) = split(n.lo); let (mut q1, mut rhat) = div_rem(n.hi, d1);
516
517 while q1 >= B || q1 * d0 > B * rhat + n1 {
519 q1 -= 1;
520 rhat += d1;
521 if rhat >= B {
522 break;
523 }
524 }
525
526 let r21 =
527 n.hi.wrapping_mul(B)
528 .wrapping_add(n1)
529 .wrapping_sub(q1.wrapping_mul(d));
530
531 let (mut q0, mut rhat) = div_rem(r21, d1);
533
534 while q0 >= B || q0 * d0 > B * rhat + n0 {
536 q0 -= 1;
537 rhat += d1;
538 if rhat >= B {
539 break;
540 }
541 }
542
543 let r = (r21
544 .wrapping_mul(B)
545 .wrapping_add(n0)
546 .wrapping_sub(q0.wrapping_mul(d)))
547 >> s;
548 let q = q1 * B + q0;
549 (q, r)
550 }
551}
552
553impl Mul<umax> for udouble {
554 type Output = Self;
555 #[inline]
556 fn mul(self, rhs: umax) -> Self::Output {
557 self.checked_mul1(rhs).expect("multiplication overflow!")
558 }
559}
560
561impl Div<umax> for udouble {
562 type Output = Self;
563 #[inline]
564 fn div(self, rhs: umax) -> Self::Output {
565 if self.hi < rhs {
567 Self {
569 lo: self.div_rem_2by1(rhs).0,
570 hi: 0,
571 }
572 } else {
573 let (q, r) = div_rem(self.hi, rhs);
574 Self {
575 lo: Self { lo: self.lo, hi: r }.div_rem_2by1(rhs).0,
576 hi: q,
577 }
578 }
579 }
580}
581
582impl Rem<umax> for udouble {
584 type Output = umax;
585 #[inline]
586 fn rem(self, rhs: umax) -> Self::Output {
587 if self.hi < rhs {
588 self.div_rem_2by1(rhs).1
590 } else {
591 Self {
592 lo: self.lo,
593 hi: self.hi % rhs,
594 }
595 .div_rem_2by1(rhs)
596 .1
597 }
598 }
599}
600
601#[cfg(test)]
602mod tests {
603 use super::*;
604 use rand::random;
605
606 #[test]
607 fn test_construction() {
608 assert_eq!(udouble { hi: 0, lo: 2 }, udouble::widening_add(1, 1));
610 assert_eq!(
611 udouble {
612 hi: 1,
613 lo: umax::MAX - 1
614 },
615 udouble::widening_add(umax::MAX, umax::MAX)
616 );
617
618 assert_eq!(udouble { hi: 0, lo: 1 }, udouble::widening_mul(1, 1));
619 assert_eq!(udouble { hi: 0, lo: 1 }, udouble::widening_square(1));
620 assert_eq!(
621 udouble { hi: 1 << 32, lo: 0 },
622 udouble::widening_mul(1 << 80, 1 << 80)
623 );
624 assert_eq!(
625 udouble { hi: 1 << 32, lo: 0 },
626 udouble::widening_square(1 << 80)
627 );
628 assert_eq!(
629 udouble {
630 hi: 1 << 32,
631 lo: 2 << 120 | 1 << 80
632 },
633 udouble::widening_mul(1 << 80 | 1 << 40, 1 << 80 | 1 << 40)
634 );
635 assert_eq!(
636 udouble {
637 hi: 1 << 32,
638 lo: 2 << 120 | 1 << 80
639 },
640 udouble::widening_square(1 << 80 | 1 << 40)
641 );
642 assert_eq!(
643 udouble {
644 hi: umax::MAX - 1,
645 lo: 1
646 },
647 udouble::widening_mul(umax::MAX, umax::MAX)
648 );
649 assert_eq!(
650 udouble {
651 hi: umax::MAX - 1,
652 lo: 1
653 },
654 udouble::widening_square(umax::MAX)
655 );
656 }
657
658 #[test]
659 fn test_ops() {
660 const ONE: udouble = udouble { hi: 0, lo: 1 };
661 const TWO: udouble = udouble { hi: 0, lo: 2 };
662 const MAX: udouble = udouble {
663 hi: 0,
664 lo: umax::MAX,
665 };
666 const ONEZERO: udouble = udouble { hi: 1, lo: 0 };
667 const ONEMAX: udouble = udouble {
668 hi: 1,
669 lo: umax::MAX,
670 };
671 const TWOZERO: udouble = udouble { hi: 2, lo: 0 };
672
673 assert_eq!(ONE + MAX, ONEZERO);
674 assert_eq!(ONE + ONEMAX, TWOZERO);
675 assert_eq!(ONEZERO - ONE, MAX);
676 assert_eq!(ONEZERO - MAX, ONE);
677 assert_eq!(TWOZERO - ONE, ONEMAX);
678 assert_eq!(TWOZERO - ONEMAX, ONE);
679
680 assert_eq!(ONE << umax::BITS, ONEZERO);
681 assert_eq!((MAX << 1u8) + 1, ONEMAX);
682 assert_eq!(
683 ONE << 200u8,
684 udouble {
685 lo: 0,
686 hi: 1 << (200 - umax::BITS)
687 }
688 );
689 assert_eq!(ONEZERO >> umax::BITS, ONE);
690 assert_eq!(ONEMAX >> 1u8, MAX);
691
692 assert_eq!(ONE * MAX.lo, MAX);
693 assert_eq!(ONEMAX * ONE.lo, ONEMAX);
694 assert_eq!(ONEMAX * TWO.lo, ONEMAX + ONEMAX);
695 assert_eq!(MAX / ONE.lo, MAX);
696 assert_eq!(MAX / MAX.lo, ONE);
697 assert_eq!(ONE / MAX.lo, udouble { lo: 0, hi: 0 });
698 assert_eq!(ONEMAX / ONE.lo, ONEMAX);
699 assert_eq!(ONEMAX / MAX.lo, TWO);
700 assert_eq!(ONEMAX / TWO.lo, MAX);
701 assert_eq!(ONE % MAX.lo, 1);
702 assert_eq!(TWO % MAX.lo, 2);
703 assert_eq!(ONEMAX % MAX.lo, 1);
704 assert_eq!(ONEMAX % TWO.lo, 1);
705
706 assert_eq!(ONEMAX.checked_mul1(MAX.lo), None);
707 assert_eq!(TWOZERO.checked_mul1(MAX.lo), None);
708 }
709
710 #[test]
711 fn test_assign_ops() {
712 for _ in 0..10 {
713 let x = udouble {
714 hi: random::<u32>() as umax,
715 lo: random(),
716 };
717 let y = udouble {
718 hi: random::<u32>() as umax,
719 lo: random(),
720 };
721 let mut z = x;
722
723 z += y;
724 assert_eq!(z, x + y);
725 z -= y;
726 assert_eq!(z, x);
727 }
728 }
729
730 #[test]
731 #[should_panic]
732 fn test_add_overflow_panics() {
733 let _ = udouble {
734 lo: 0,
735 hi: umax::MAX,
736 } + udouble { lo: 0, hi: 1 };
737 }
738
739 #[test]
740 #[should_panic]
741 fn test_sub_underflow_panics() {
742 let _ = udouble { lo: 0, hi: 0 } - udouble { lo: 0, hi: 1 };
743 }
744
745 #[test]
746 #[should_panic]
747 fn test_add_assign_overflow_panics() {
748 let mut x = udouble {
749 lo: 0,
750 hi: umax::MAX,
751 };
752 x += udouble { lo: 0, hi: 1 };
753 }
754
755 #[test]
756 #[should_panic]
757 fn test_sub_assign_underflow_panics() {
758 let mut x = udouble { lo: 0, hi: 0 };
759 x -= udouble { lo: 0, hi: 1 };
760 }
761}