Skip to main content

percolator/
wide_math.rs

1// ============================================================================
2// Wide 256-bit Arithmetic for Risk Engine
3// ============================================================================
4//
5// Provides U256 and I256 types plus spec section 4.6 helpers (floor division,
6// ceiling division, mul-div with 512-bit intermediate) for the percolator
7// risk engine.
8//
9// DUAL-MODE LAYOUT (mirrors src/i128.rs):
10//   - Kani builds: `#[repr(transparent)]` wrapper around `[u128; 2]` so the
11//     SAT solver works on native 128-bit words instead of 64-bit limb arrays.
12//   - BPF / host builds: `#[repr(C)] [u64; 4]` for consistent 8-byte
13//     alignment across all Solana targets.
14//
15// No external crates. No unsafe code. Pure `core::` only.
16
17use core::cmp::Ordering;
18
19// ============================================================================
20// U256 -- Kani version
21// ============================================================================
22#[cfg(kani)]
23#[repr(transparent)]
24#[derive(Clone, Copy, Debug, PartialEq, Eq)]
25pub struct U256([u128; 2]); // [lo, hi]
26
27#[cfg(kani)]
28impl U256 {
29    pub const ZERO: Self = Self([0, 0]);
30    pub const ONE: Self = Self([1, 0]);
31    pub const MAX: Self = Self([u128::MAX, u128::MAX]);
32
33    #[inline(always)]
34    pub const fn new(lo: u128, hi: u128) -> Self {
35        Self([lo, hi])
36    }
37
38    #[inline(always)]
39    pub const fn from_u128(v: u128) -> Self {
40        Self([v, 0])
41    }
42
43    #[inline(always)]
44    pub const fn from_u64(v: u64) -> Self {
45        Self([v as u128, 0])
46    }
47
48    #[inline(always)]
49    pub const fn lo(&self) -> u128 {
50        self.0[0]
51    }
52
53    #[inline(always)]
54    pub const fn hi(&self) -> u128 {
55        self.0[1]
56    }
57
58    #[inline(always)]
59    pub const fn is_zero(&self) -> bool {
60        self.0[0] == 0 && self.0[1] == 0
61    }
62
63    #[inline(always)]
64    pub fn try_into_u128(&self) -> Option<u128> {
65        if self.0[1] == 0 {
66            Some(self.0[0])
67        } else {
68            None
69        }
70    }
71
72    // -- checked arithmetic --
73
74    pub fn checked_add(self, rhs: U256) -> Option<U256> {
75        let (lo, carry) = self.0[0].overflowing_add(rhs.0[0]);
76        let hi = self.0[1].checked_add(rhs.0[1])?;
77        let hi = if carry { hi.checked_add(1)? } else { hi };
78        Some(U256([lo, hi]))
79    }
80
81    pub fn checked_sub(self, rhs: U256) -> Option<U256> {
82        let (lo, borrow) = self.0[0].overflowing_sub(rhs.0[0]);
83        let hi = self.0[1].checked_sub(rhs.0[1])?;
84        let hi = if borrow { hi.checked_sub(1)? } else { hi };
85        Some(U256([lo, hi]))
86    }
87
88    pub fn checked_mul(self, rhs: U256) -> Option<U256> {
89        // Schoolbook multiply: split each u128 into two u64 halves, giving
90        // four u64 limbs per operand, then accumulate with carries.
91        //
92        // However since we only need the low 256 bits and an overflow flag,
93        // we can use a simpler approach: treat each U256 as (lo: u128, hi: u128).
94        //
95        //   result_lo_full = self.lo * rhs.lo          (up to 256 bits)
96        //   cross1         = self.lo * rhs.hi          (up to 256 bits)
97        //   cross2         = self.hi * rhs.lo          (up to 256 bits)
98        //   high_high      = self.hi * rhs.hi          (must be zero or overflow)
99        //
100        // We need widening 128x128 -> 256 for self.lo * rhs.lo.
101
102        // If both hi words are nonzero, definitely overflows.
103        if self.0[1] != 0 && rhs.0[1] != 0 {
104            return None;
105        }
106
107        let (prod_lo, prod_hi) = widening_mul_u128(self.0[0], rhs.0[0]);
108
109        // cross1 = self.lo * rhs.hi (only the low 128 bits matter for result hi)
110        // cross2 = self.hi * rhs.lo
111        // If the cross product itself exceeds 128 bits, we overflow.
112        let cross1 = if rhs.0[1] != 0 {
113            let (c, overflow) = widening_mul_u128(self.0[0], rhs.0[1]);
114            if overflow != 0 {
115                return None;
116            }
117            c
118        } else {
119            0u128
120        };
121
122        let cross2 = if self.0[1] != 0 {
123            let (c, overflow) = widening_mul_u128(self.0[1], rhs.0[0]);
124            if overflow != 0 {
125                return None;
126            }
127            c
128        } else {
129            0u128
130        };
131
132        let hi = prod_hi.checked_add(cross1)?;
133        let hi = hi.checked_add(cross2)?;
134
135        Some(U256([prod_lo, hi]))
136    }
137
138    pub fn checked_div(self, rhs: U256) -> Option<U256> {
139        if rhs.is_zero() {
140            return None;
141        }
142        Some(div_rem_u256(self, rhs).0)
143    }
144
145    pub fn checked_rem(self, rhs: U256) -> Option<U256> {
146        if rhs.is_zero() {
147            return None;
148        }
149        Some(div_rem_u256(self, rhs).1)
150    }
151
152    // -- overflowing --
153
154    pub fn overflowing_add(self, rhs: U256) -> (U256, bool) {
155        let (lo, carry) = self.0[0].overflowing_add(rhs.0[0]);
156        let (hi, overflow1) = self.0[1].overflowing_add(rhs.0[1]);
157        let (hi, overflow2) = if carry {
158            hi.overflowing_add(1)
159        } else {
160            (hi, false)
161        };
162        (U256([lo, hi]), overflow1 || overflow2)
163    }
164
165    pub fn overflowing_sub(self, rhs: U256) -> (U256, bool) {
166        let (lo, borrow) = self.0[0].overflowing_sub(rhs.0[0]);
167        let (hi, underflow1) = self.0[1].overflowing_sub(rhs.0[1]);
168        let (hi, underflow2) = if borrow {
169            hi.overflowing_sub(1)
170        } else {
171            (hi, false)
172        };
173        (U256([lo, hi]), underflow1 || underflow2)
174    }
175
176    // -- saturating --
177
178    pub fn saturating_add(self, rhs: U256) -> U256 {
179        self.checked_add(rhs).unwrap_or(U256::MAX)
180    }
181
182    pub fn saturating_sub(self, rhs: U256) -> U256 {
183        self.checked_sub(rhs).unwrap_or(U256::ZERO)
184    }
185
186    // -- shifts --
187
188    pub fn shl(self, bits: u32) -> U256 {
189        if bits >= 256 {
190            return U256::ZERO;
191        }
192        if bits == 0 {
193            return self;
194        }
195        if bits >= 128 {
196            let s = bits - 128;
197            U256([0, self.0[0] << s])
198        } else {
199            let lo = self.0[0] << bits;
200            let hi = (self.0[1] << bits) | (self.0[0] >> (128 - bits));
201            U256([lo, hi])
202        }
203    }
204
205    pub fn shr(self, bits: u32) -> U256 {
206        if bits >= 256 {
207            return U256::ZERO;
208        }
209        if bits == 0 {
210            return self;
211        }
212        if bits >= 128 {
213            let s = bits - 128;
214            U256([self.0[1] >> s, 0])
215        } else {
216            let hi = self.0[1] >> bits;
217            let lo = (self.0[0] >> bits) | (self.0[1] << (128 - bits));
218            U256([lo, hi])
219        }
220    }
221
222    // -- bitwise --
223
224    pub fn bitand(self, rhs: U256) -> U256 {
225        U256([self.0[0] & rhs.0[0], self.0[1] & rhs.0[1]])
226    }
227
228    pub fn bitor(self, rhs: U256) -> U256 {
229        U256([self.0[0] | rhs.0[0], self.0[1] | rhs.0[1]])
230    }
231}
232
233// ============================================================================
234// U256 -- BPF version
235// ============================================================================
236#[cfg(not(kani))]
237#[repr(C)]
238#[derive(Clone, Copy, Debug, PartialEq, Eq)]
239pub struct U256([u64; 4]); // [limb0 (least significant), limb1, limb2, limb3]
240
241#[cfg(not(kani))]
242impl U256 {
243    pub const ZERO: Self = Self([0, 0, 0, 0]);
244    pub const ONE: Self = Self([1, 0, 0, 0]);
245    pub const MAX: Self = Self([u64::MAX, u64::MAX, u64::MAX, u64::MAX]);
246
247    /// Create from low 128 bits and high 128 bits.
248    #[inline]
249    pub const fn new(lo: u128, hi: u128) -> Self {
250        Self([lo as u64, (lo >> 64) as u64, hi as u64, (hi >> 64) as u64])
251    }
252
253    #[inline]
254    pub const fn from_u128(v: u128) -> Self {
255        Self::new(v, 0)
256    }
257
258    #[inline]
259    pub const fn from_u64(v: u64) -> Self {
260        Self([v, 0, 0, 0])
261    }
262
263    #[inline]
264    pub const fn lo(&self) -> u128 {
265        (self.0[0] as u128) | ((self.0[1] as u128) << 64)
266    }
267
268    #[inline]
269    pub const fn hi(&self) -> u128 {
270        (self.0[2] as u128) | ((self.0[3] as u128) << 64)
271    }
272
273    #[inline]
274    pub const fn is_zero(&self) -> bool {
275        self.0[0] == 0 && self.0[1] == 0 && self.0[2] == 0 && self.0[3] == 0
276    }
277
278    #[inline]
279    pub fn try_into_u128(&self) -> Option<u128> {
280        if self.0[2] == 0 && self.0[3] == 0 {
281            Some(self.lo())
282        } else {
283            None
284        }
285    }
286
287    // -- checked arithmetic --
288
289    pub fn checked_add(self, rhs: U256) -> Option<U256> {
290        let (lo, carry) = add_u128_carry(self.lo(), rhs.lo(), false);
291        let (hi, overflow) = add_u128_carry(self.hi(), rhs.hi(), carry);
292        if overflow {
293            None
294        } else {
295            Some(U256::new(lo, hi))
296        }
297    }
298
299    pub fn checked_sub(self, rhs: U256) -> Option<U256> {
300        let (lo, borrow) = sub_u128_borrow(self.lo(), rhs.lo(), false);
301        let (hi, underflow) = sub_u128_borrow(self.hi(), rhs.hi(), borrow);
302        if underflow {
303            None
304        } else {
305            Some(U256::new(lo, hi))
306        }
307    }
308
309    pub fn checked_mul(self, rhs: U256) -> Option<U256> {
310        if self.hi() != 0 && rhs.hi() != 0 {
311            return None;
312        }
313
314        let (prod_lo, prod_hi) = widening_mul_u128(self.lo(), rhs.lo());
315
316        let cross1 = if rhs.hi() != 0 {
317            let (c, overflow) = widening_mul_u128(self.lo(), rhs.hi());
318            if overflow != 0 {
319                return None;
320            }
321            c
322        } else {
323            0u128
324        };
325
326        let cross2 = if self.hi() != 0 {
327            let (c, overflow) = widening_mul_u128(self.hi(), rhs.lo());
328            if overflow != 0 {
329                return None;
330            }
331            c
332        } else {
333            0u128
334        };
335
336        let hi = prod_hi.checked_add(cross1)?;
337        let hi = hi.checked_add(cross2)?;
338
339        Some(U256::new(prod_lo, hi))
340    }
341
342    pub fn checked_div(self, rhs: U256) -> Option<U256> {
343        if rhs.is_zero() {
344            return None;
345        }
346        Some(div_rem_u256(self, rhs).0)
347    }
348
349    pub fn checked_rem(self, rhs: U256) -> Option<U256> {
350        if rhs.is_zero() {
351            return None;
352        }
353        Some(div_rem_u256(self, rhs).1)
354    }
355
356    // -- overflowing --
357
358    pub fn overflowing_add(self, rhs: U256) -> (U256, bool) {
359        let (lo, carry) = add_u128_carry(self.lo(), rhs.lo(), false);
360        let (hi, overflow) = add_u128_carry(self.hi(), rhs.hi(), carry);
361        (U256::new(lo, hi), overflow)
362    }
363
364    pub fn overflowing_sub(self, rhs: U256) -> (U256, bool) {
365        let (lo, borrow) = sub_u128_borrow(self.lo(), rhs.lo(), false);
366        let (hi, underflow) = sub_u128_borrow(self.hi(), rhs.hi(), borrow);
367        (U256::new(lo, hi), underflow)
368    }
369
370    // -- saturating --
371
372    pub fn saturating_add(self, rhs: U256) -> U256 {
373        self.checked_add(rhs).unwrap_or(U256::MAX)
374    }
375
376    pub fn saturating_sub(self, rhs: U256) -> U256 {
377        self.checked_sub(rhs).unwrap_or(U256::ZERO)
378    }
379
380    // -- shifts --
381
382    pub fn shl(self, bits: u32) -> U256 {
383        if bits >= 256 {
384            return U256::ZERO;
385        }
386        if bits == 0 {
387            return self;
388        }
389        let lo = self.lo();
390        let hi = self.hi();
391        if bits >= 128 {
392            let s = bits - 128;
393            U256::new(0, lo << s)
394        } else {
395            let new_lo = lo << bits;
396            let new_hi = (hi << bits) | (lo >> (128 - bits));
397            U256::new(new_lo, new_hi)
398        }
399    }
400
401    pub fn shr(self, bits: u32) -> U256 {
402        if bits >= 256 {
403            return U256::ZERO;
404        }
405        if bits == 0 {
406            return self;
407        }
408        let lo = self.lo();
409        let hi = self.hi();
410        if bits >= 128 {
411            let s = bits - 128;
412            U256::new(hi >> s, 0)
413        } else {
414            let new_hi = hi >> bits;
415            let new_lo = (lo >> bits) | (hi << (128 - bits));
416            U256::new(new_lo, new_hi)
417        }
418    }
419
420    // -- bitwise --
421
422    pub fn bitand(self, rhs: U256) -> U256 {
423        U256::new(self.lo() & rhs.lo(), self.hi() & rhs.hi())
424    }
425
426    pub fn bitor(self, rhs: U256) -> U256 {
427        U256::new(self.lo() | rhs.lo(), self.hi() | rhs.hi())
428    }
429}
430
431// ============================================================================
432// U256 - Ord / PartialOrd (shared logic, both modes)
433// ============================================================================
434impl PartialOrd for U256 {
435    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
436        Some(self.cmp(other))
437    }
438}
439
440impl Ord for U256 {
441    fn cmp(&self, other: &Self) -> Ordering {
442        match self.hi().cmp(&other.hi()) {
443            Ordering::Equal => self.lo().cmp(&other.lo()),
444            ord => ord,
445        }
446    }
447}
448
449// ============================================================================
450// U256 - core::ops traits (shared logic, both modes)
451// ============================================================================
452impl core::ops::Add for U256 {
453    type Output = Self;
454    #[inline]
455    fn add(self, rhs: Self) -> Self {
456        self.checked_add(rhs).expect("U256 add overflow")
457    }
458}
459
460impl core::ops::Sub for U256 {
461    type Output = Self;
462    #[inline]
463    fn sub(self, rhs: Self) -> Self {
464        self.checked_sub(rhs).expect("U256 sub underflow")
465    }
466}
467
468impl core::ops::Mul for U256 {
469    type Output = Self;
470    #[inline]
471    fn mul(self, rhs: Self) -> Self {
472        self.checked_mul(rhs).expect("U256 mul overflow")
473    }
474}
475
476impl core::ops::Div for U256 {
477    type Output = Self;
478    #[inline]
479    fn div(self, rhs: Self) -> Self {
480        self.checked_div(rhs).expect("U256 div by zero")
481    }
482}
483
484impl core::ops::Rem for U256 {
485    type Output = Self;
486    #[inline]
487    fn rem(self, rhs: Self) -> Self {
488        self.checked_rem(rhs).expect("U256 rem by zero")
489    }
490}
491
492impl core::ops::Shl<u32> for U256 {
493    type Output = Self;
494    #[inline]
495    fn shl(self, bits: u32) -> Self {
496        self.shl(bits)
497    }
498}
499
500impl core::ops::Shr<u32> for U256 {
501    type Output = Self;
502    #[inline]
503    fn shr(self, bits: u32) -> Self {
504        self.shr(bits)
505    }
506}
507
508impl core::ops::BitAnd for U256 {
509    type Output = Self;
510    #[inline]
511    fn bitand(self, rhs: Self) -> Self {
512        self.bitand(rhs)
513    }
514}
515
516impl core::ops::BitOr for U256 {
517    type Output = Self;
518    #[inline]
519    fn bitor(self, rhs: Self) -> Self {
520        self.bitor(rhs)
521    }
522}
523
524impl core::ops::AddAssign for U256 {
525    #[inline]
526    fn add_assign(&mut self, rhs: Self) {
527        *self = *self + rhs;
528    }
529}
530
531impl core::ops::SubAssign for U256 {
532    #[inline]
533    fn sub_assign(&mut self, rhs: Self) {
534        *self = *self - rhs;
535    }
536}
537
538// ============================================================================
539// I256 -- Kani version
540// ============================================================================
541#[cfg(kani)]
542#[repr(transparent)]
543#[derive(Clone, Copy, Debug, PartialEq, Eq)]
544pub struct I256([u128; 2]); // two's complement [lo, hi]; sign bit is bit 127 of hi
545
546#[cfg(kani)]
547impl I256 {
548    pub const ZERO: Self = Self([0, 0]);
549    pub const ONE: Self = Self([1, 0]);
550    pub const MINUS_ONE: Self = Self([u128::MAX, u128::MAX]); // all ones in two's complement
551    /// Largest positive value: hi = 0x7FFF...FFFF, lo = 0xFFFF...FFFF
552    pub const MAX: Self = Self([u128::MAX, u128::MAX >> 1]);
553    /// Most negative value: hi = 0x8000...0000, lo = 0
554    pub const MIN: Self = Self([0, 1u128 << 127]);
555
556    pub fn from_i128(v: i128) -> Self {
557        // Sign-extend into hi word.
558        let lo = v as u128;
559        let hi = if v < 0 { u128::MAX } else { 0 };
560        Self([lo, hi])
561    }
562
563    pub fn from_u128(v: u128) -> Self {
564        // Must be non-negative and fit in I256 (i.e. hi sign bit must be 0).
565        // Since lo = v and hi = 0, the sign bit is clear as long as v < 2^128.
566        // But v is u128 so this always fits (I256::MAX has hi = 2^127-1 > 0).
567        Self([v, 0])
568    }
569
570    pub fn try_into_i128(&self) -> Option<i128> {
571        // Value fits in i128 iff hi is the sign-extension of lo's sign bit.
572        let lo = self.0[0];
573        let hi = self.0[1];
574        let lo_sign_ext = if (lo as i128) < 0 { u128::MAX } else { 0 };
575        if hi == lo_sign_ext {
576            Some(lo as i128)
577        } else {
578            None
579        }
580    }
581
582    pub fn is_zero(&self) -> bool {
583        self.0[0] == 0 && self.0[1] == 0
584    }
585
586    pub fn is_negative(&self) -> bool {
587        (self.0[1] >> 127) != 0
588    }
589
590    pub fn is_positive(&self) -> bool {
591        !self.is_zero() && !self.is_negative()
592    }
593
594    pub fn signum(&self) -> i8 {
595        if self.is_zero() {
596            0
597        } else if self.is_negative() {
598            -1
599        } else {
600            1
601        }
602    }
603
604    /// Return the absolute value as U256. Panics on I256::MIN.
605    pub fn abs_u256(self) -> U256 {
606        if self.is_negative() {
607            // Negate: invert + 1. Panics for MIN since ~MIN+1 overflows back to MIN
608            // which would be 2^255, i.e. U256 with hi = 1<<127, which is fine actually.
609            // But the spec says panics for MIN, so we check.
610            assert!(self != Self::MIN, "abs_u256 called on I256::MIN");
611            let inv_lo = !self.0[0];
612            let inv_hi = !self.0[1];
613            let (neg_lo, carry) = inv_lo.overflowing_add(1);
614            let neg_hi = inv_hi.wrapping_add(if carry { 1 } else { 0 });
615            U256::new(neg_lo, neg_hi)
616        } else {
617            U256::new(self.0[0], self.0[1])
618        }
619    }
620
621    // -- checked arithmetic --
622
623    pub fn checked_add(self, rhs: I256) -> Option<I256> {
624        let (lo, carry) = self.0[0].overflowing_add(rhs.0[0]);
625        let (hi, overflow1) = self.0[1].overflowing_add(rhs.0[1]);
626        let (hi, overflow2) = hi.overflowing_add(if carry { 1 } else { 0 });
627        let result = I256([lo, hi]);
628
629        // Signed overflow: if both operands have the same sign and the result
630        // has a different sign, we overflowed.
631        let self_neg = self.is_negative();
632        let rhs_neg = rhs.is_negative();
633        let res_neg = result.is_negative();
634
635        // Unsigned carries should be consistent with sign expectations:
636        // For two's complement addition, overflow iff same-sign inputs produce
637        // different-sign result.
638        if self_neg == rhs_neg && res_neg != self_neg {
639            None
640        } else {
641            Some(result)
642        }
643    }
644
645    pub fn checked_sub(self, rhs: I256) -> Option<I256> {
646        let neg_rhs = match rhs.checked_neg() {
647            Some(n) => n,
648            None => {
649                // rhs == MIN. self - MIN = self + 2^255.
650                // This is valid only if self is non-negative (result fits in I256).
651                // self - MIN: we'll do it directly.
652                let (lo, borrow) = self.0[0].overflowing_sub(rhs.0[0]);
653                let (hi, underflow1) = self.0[1].overflowing_sub(rhs.0[1]);
654                let (hi, underflow2) = hi.overflowing_sub(if borrow { 1 } else { 0 });
655                let result = I256([lo, hi]);
656                // Check: subtracting a negative from anything should not make it
657                // more negative. self - MIN where MIN is negative. If self >= 0,
658                // result = self + |MIN| which could overflow. If self < 0,
659                // result = self + |MIN| which could be in range.
660                let self_neg = self.is_negative();
661                let rhs_neg = true; // MIN is negative
662                let res_neg = result.is_negative();
663                // sub overflow: signs differ (self_neg != rhs_neg) and result
664                // sign != self sign.
665                if self_neg != rhs_neg && res_neg != self_neg {
666                    return None;
667                }
668                return Some(result);
669            }
670        };
671        self.checked_add(neg_rhs)
672    }
673
674    pub fn checked_neg(self) -> Option<I256> {
675        if self == Self::MIN {
676            return None;
677        }
678        let inv_lo = !self.0[0];
679        let inv_hi = !self.0[1];
680        let (neg_lo, carry) = inv_lo.overflowing_add(1);
681        let neg_hi = inv_hi.wrapping_add(if carry { 1 } else { 0 });
682        Some(I256([neg_lo, neg_hi]))
683    }
684
685    pub fn saturating_add(self, rhs: I256) -> I256 {
686        match self.checked_add(rhs) {
687            Some(v) => v,
688            None => {
689                if rhs.is_negative() {
690                    I256::MIN
691                } else {
692                    I256::MAX
693                }
694            }
695        }
696    }
697
698    /// Convert this I256 to a raw U256 (reinterpret the bits).
699    fn as_raw_u256(self) -> U256 {
700        U256::new(self.0[0], self.0[1])
701    }
702
703    /// Create I256 from raw U256 bits (reinterpret).
704    pub fn from_raw_u256(v: U256) -> Self {
705        I256([v.lo(), v.hi()])
706    }
707}
708
709// ============================================================================
710// I256 -- BPF version
711// ============================================================================
712#[cfg(not(kani))]
713#[repr(C)]
714#[derive(Clone, Copy, Debug, PartialEq, Eq)]
715pub struct I256([u64; 4]); // two's complement, little-endian limbs
716
717#[cfg(not(kani))]
718impl I256 {
719    pub const ZERO: Self = Self([0, 0, 0, 0]);
720    pub const ONE: Self = Self([1, 0, 0, 0]);
721    pub const MINUS_ONE: Self = Self([u64::MAX, u64::MAX, u64::MAX, u64::MAX]);
722    pub const MAX: Self = Self([u64::MAX, u64::MAX, u64::MAX, u64::MAX >> 1]);
723    pub const MIN: Self = Self([0, 0, 0, 1u64 << 63]);
724
725    pub fn from_i128(v: i128) -> Self {
726        let lo = v as u128;
727        let hi: u128 = if v < 0 { u128::MAX } else { 0 };
728        Self::from_lo_hi(lo, hi)
729    }
730
731    pub fn from_u128(v: u128) -> Self {
732        Self::from_lo_hi(v, 0)
733    }
734
735    pub fn try_into_i128(&self) -> Option<i128> {
736        let lo = self.lo_u128();
737        let hi = self.hi_u128();
738        let lo_sign_ext = if (lo as i128) < 0 { u128::MAX } else { 0 };
739        if hi == lo_sign_ext {
740            Some(lo as i128)
741        } else {
742            None
743        }
744    }
745
746    pub fn is_zero(&self) -> bool {
747        self.0[0] == 0 && self.0[1] == 0 && self.0[2] == 0 && self.0[3] == 0
748    }
749
750    pub fn is_negative(&self) -> bool {
751        (self.0[3] >> 63) != 0
752    }
753
754    pub fn is_positive(&self) -> bool {
755        !self.is_zero() && !self.is_negative()
756    }
757
758    pub fn signum(&self) -> i8 {
759        if self.is_zero() {
760            0
761        } else if self.is_negative() {
762            -1
763        } else {
764            1
765        }
766    }
767
768    pub fn abs_u256(self) -> U256 {
769        if self.is_negative() {
770            assert!(self != Self::MIN, "abs_u256 called on I256::MIN");
771            let lo = self.lo_u128();
772            let hi = self.hi_u128();
773            let inv_lo = !lo;
774            let inv_hi = !hi;
775            let (neg_lo, carry) = inv_lo.overflowing_add(1);
776            let neg_hi = inv_hi.wrapping_add(if carry { 1 } else { 0 });
777            U256::new(neg_lo, neg_hi)
778        } else {
779            U256::new(self.lo_u128(), self.hi_u128())
780        }
781    }
782
783    // -- checked arithmetic --
784
785    pub fn checked_add(self, rhs: I256) -> Option<I256> {
786        let s_lo = self.lo_u128();
787        let s_hi = self.hi_u128();
788        let r_lo = rhs.lo_u128();
789        let r_hi = rhs.hi_u128();
790        let (lo, carry) = s_lo.overflowing_add(r_lo);
791        let (hi, overflow1) = s_hi.overflowing_add(r_hi);
792        let (hi, overflow2) = hi.overflowing_add(if carry { 1 } else { 0 });
793        let result = I256::from_lo_hi(lo, hi);
794
795        let self_neg = self.is_negative();
796        let rhs_neg = rhs.is_negative();
797        let res_neg = result.is_negative();
798
799        if self_neg == rhs_neg && res_neg != self_neg {
800            None
801        } else {
802            Some(result)
803        }
804    }
805
806    pub fn checked_sub(self, rhs: I256) -> Option<I256> {
807        let neg_rhs = match rhs.checked_neg() {
808            Some(n) => n,
809            None => {
810                let s_lo = self.lo_u128();
811                let s_hi = self.hi_u128();
812                let r_lo = rhs.lo_u128();
813                let r_hi = rhs.hi_u128();
814                let (lo, borrow) = s_lo.overflowing_sub(r_lo);
815                let (hi, _underflow1) = s_hi.overflowing_sub(r_hi);
816                let (hi, _underflow2) = hi.overflowing_sub(if borrow { 1 } else { 0 });
817                let result = I256::from_lo_hi(lo, hi);
818                let self_neg = self.is_negative();
819                let res_neg = result.is_negative();
820                if self_neg != true && res_neg != self_neg {
821                    return None;
822                }
823                return Some(result);
824            }
825        };
826        self.checked_add(neg_rhs)
827    }
828
829    pub fn checked_neg(self) -> Option<I256> {
830        if self == Self::MIN {
831            return None;
832        }
833        let lo = self.lo_u128();
834        let hi = self.hi_u128();
835        let inv_lo = !lo;
836        let inv_hi = !hi;
837        let (neg_lo, carry) = inv_lo.overflowing_add(1);
838        let neg_hi = inv_hi.wrapping_add(if carry { 1 } else { 0 });
839        Some(I256::from_lo_hi(neg_lo, neg_hi))
840    }
841
842    pub fn saturating_add(self, rhs: I256) -> I256 {
843        match self.checked_add(rhs) {
844            Some(v) => v,
845            None => {
846                if rhs.is_negative() {
847                    I256::MIN
848                } else {
849                    I256::MAX
850                }
851            }
852        }
853    }
854
855    // internal helpers
856    fn lo_u128(&self) -> u128 {
857        (self.0[0] as u128) | ((self.0[1] as u128) << 64)
858    }
859
860    fn hi_u128(&self) -> u128 {
861        (self.0[2] as u128) | ((self.0[3] as u128) << 64)
862    }
863
864    fn from_lo_hi(lo: u128, hi: u128) -> Self {
865        Self([lo as u64, (lo >> 64) as u64, hi as u64, (hi >> 64) as u64])
866    }
867
868    fn as_raw_u256(self) -> U256 {
869        U256::new(self.lo_u128(), self.hi_u128())
870    }
871
872    pub fn from_raw_u256(v: U256) -> Self {
873        Self::from_lo_hi(v.lo(), v.hi())
874    }
875}
876
877// ============================================================================
878// I256 - Ord / PartialOrd (shared, both modes)
879// ============================================================================
880impl PartialOrd for I256 {
881    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
882        Some(self.cmp(other))
883    }
884}
885
886impl Ord for I256 {
887    fn cmp(&self, other: &Self) -> Ordering {
888        let self_neg = self.is_negative();
889        let other_neg = other.is_negative();
890        match (self_neg, other_neg) {
891            (true, false) => Ordering::Less,
892            (false, true) => Ordering::Greater,
893            _ => {
894                // Same sign: compare as unsigned (works for two's complement
895                // when both values have the same sign bit).
896                self.as_raw_u256().cmp(&other.as_raw_u256())
897            }
898        }
899    }
900}
901
902// ============================================================================
903// I256 - core::ops traits (shared, both modes)
904// ============================================================================
905impl core::ops::Add for I256 {
906    type Output = Self;
907    #[inline]
908    fn add(self, rhs: Self) -> Self {
909        self.checked_add(rhs).expect("I256 add overflow")
910    }
911}
912
913impl core::ops::Sub for I256 {
914    type Output = Self;
915    #[inline]
916    fn sub(self, rhs: Self) -> Self {
917        self.checked_sub(rhs).expect("I256 sub overflow")
918    }
919}
920
921impl core::ops::Neg for I256 {
922    type Output = Self;
923    #[inline]
924    fn neg(self) -> Self {
925        self.checked_neg().expect("I256 neg overflow (MIN)")
926    }
927}
928
929// ============================================================================
930// Shared helpers (used by both Kani and BPF)
931// ============================================================================
932
933/// Widening multiply: u128 * u128 -> (lo: u128, hi: u128).
934/// Schoolbook on u64 halves.
935fn widening_mul_u128(a: u128, b: u128) -> (u128, u128) {
936    let a_lo = a as u64 as u128;
937    let a_hi = (a >> 64) as u64 as u128;
938    let b_lo = b as u64 as u128;
939    let b_hi = (b >> 64) as u64 as u128;
940
941    let ll = a_lo * b_lo; // 0..2^128
942    let lh = a_lo * b_hi; // 0..2^128
943    let hl = a_hi * b_lo; // 0..2^128
944    let hh = a_hi * b_hi; // 0..2^128
945
946    // Accumulate:
947    //   result = ll + (lh + hl) << 64 + hh << 128
948    let (mid, mid_carry) = lh.overflowing_add(hl); // mid_carry means +2^128
949
950    let (lo, lo_carry) = ll.overflowing_add(mid << 64);
951    let hi = hh + (mid >> 64) + ((mid_carry as u128) << 64) + (lo_carry as u128);
952    // lo_carry is at most 1, captured in hi
953
954    (lo, hi)
955}
956
957/// Add two u128 with an incoming carry, returning (result, carry_out).
958#[cfg(not(kani))]
959fn add_u128_carry(a: u128, b: u128, carry_in: bool) -> (u128, bool) {
960    let (s1, c1) = a.overflowing_add(b);
961    let (s2, c2) = s1.overflowing_add(carry_in as u128);
962    (s2, c1 || c2)
963}
964
965/// Subtract two u128 with an incoming borrow, returning (result, borrow_out).
966#[cfg(not(kani))]
967fn sub_u128_borrow(a: u128, b: u128, borrow_in: bool) -> (u128, bool) {
968    let (d1, b1) = a.overflowing_sub(b);
969    let (d2, b2) = d1.overflowing_sub(borrow_in as u128);
970    (d2, b1 || b2)
971}
972
973// ============================================================================
974// U256 division: binary long division
975// ============================================================================
976
977/// Count leading zeros of a U256.
978fn leading_zeros_u256(v: U256) -> u32 {
979    if v.hi() != 0 {
980        v.hi().leading_zeros()
981    } else {
982        128 + v.lo().leading_zeros()
983    }
984}
985
986/// Divide U256 by U256, returning (quotient, remainder). Panics if divisor is zero.
987fn div_rem_u256(num: U256, den: U256) -> (U256, U256) {
988    if den.is_zero() {
989        panic!("U256 division by zero");
990    }
991    if num.is_zero() {
992        return (U256::ZERO, U256::ZERO);
993    }
994
995    // If denominator > numerator, quotient = 0
996    if den > num {
997        return (U256::ZERO, num);
998    }
999
1000    // If denominator fits in u128 and numerator fits in u128, do it natively.
1001    if num.hi() == 0 && den.hi() == 0 {
1002        let q = num.lo() / den.lo();
1003        let r = num.lo() % den.lo();
1004        return (U256::from_u128(q), U256::from_u128(r));
1005    }
1006
1007    // Binary long division
1008    let shift = leading_zeros_u256(den) - leading_zeros_u256(num);
1009    let mut remainder = num;
1010    let mut quotient = U256::ZERO;
1011    let mut divisor = den.shl(shift);
1012
1013    // We iterate shift+1 times (from bit `shift` down to 0)
1014    let mut i = shift as i32;
1015    while i >= 0 {
1016        if remainder >= divisor {
1017            remainder = remainder.saturating_sub(divisor);
1018            quotient = quotient.bitor(U256::ONE.shl(i as u32));
1019        }
1020        divisor = divisor.shr(1);
1021        i -= 1;
1022    }
1023
1024    (quotient, remainder)
1025}
1026
1027// ============================================================================
1028// U512 - private intermediate for mul_div operations
1029// ============================================================================
1030
1031/// Private 512-bit unsigned integer for intermediate computations.
1032/// Stored as [u128; 4] in little-endian order.
1033#[derive(Clone, Copy, Debug, PartialEq, Eq)]
1034struct U512([u128; 4]);
1035
1036impl U512 {
1037    const ZERO: Self = Self([0, 0, 0, 0]);
1038
1039    fn is_zero(&self) -> bool {
1040        self.0[0] == 0 && self.0[1] == 0 && self.0[2] == 0 && self.0[3] == 0
1041    }
1042
1043    fn from_u256(v: U256) -> Self {
1044        Self([v.lo(), v.hi(), 0, 0])
1045    }
1046
1047    /// Widening multiply of two U256 values into U512.
1048    fn mul_u256(a: U256, b: U256) -> Self {
1049        // Schoolbook: a = [a0, a1], b = [b0, b1] where each is u128.
1050        let a0 = a.lo();
1051        let a1 = a.hi();
1052        let b0 = b.lo();
1053        let b1 = b.hi();
1054
1055        // a0*b0 -> occupies [0..1]
1056        let (r0, c0) = widening_mul_u128(a0, b0);
1057
1058        // a0*b1 -> occupies [1..2]
1059        let (x1, x2) = widening_mul_u128(a0, b1);
1060
1061        // a1*b0 -> occupies [1..2]
1062        let (y1, y2) = widening_mul_u128(a1, b0);
1063
1064        // a1*b1 -> occupies [2..3]
1065        let (z2, z3) = widening_mul_u128(a1, b1);
1066
1067        // Accumulate into 4 limbs [r0, r1, r2, r3]
1068        // r0 is already set.
1069        // r1 = c0 + x1 + y1   (with carries into r2)
1070        let (r1, carry1a) = c0.overflowing_add(x1);
1071        let (r1, carry1b) = r1.overflowing_add(y1);
1072        let carry1 = (carry1a as u128) + (carry1b as u128);
1073
1074        // r2 = x2 + y2 + z2 + carry1
1075        let (r2, carry2a) = x2.overflowing_add(y2);
1076        let (r2, carry2b) = r2.overflowing_add(z2);
1077        let (r2, carry2c) = r2.overflowing_add(carry1);
1078        let carry2 = (carry2a as u128) + (carry2b as u128) + (carry2c as u128);
1079
1080        // r3 = z3 + carry2
1081        let r3 = z3 + carry2; // cannot overflow because max product is (2^256-1)^2 < 2^512
1082
1083        Self([r0, r1, r2, r3])
1084    }
1085
1086    /// Compare two U512 values.
1087    fn cmp_u512(&self, other: &Self) -> Ordering {
1088        for i in (0..4).rev() {
1089            match self.0[i].cmp(&other.0[i]) {
1090                Ordering::Equal => continue,
1091                ord => return ord,
1092            }
1093        }
1094        Ordering::Equal
1095    }
1096
1097    /// Shift left by `bits`. Saturates to zero if bits >= 512.
1098    fn shl_u512(self, bits: u32) -> Self {
1099        if bits >= 512 {
1100            return Self::ZERO;
1101        }
1102        if bits == 0 {
1103            return self;
1104        }
1105        let word_shift = (bits / 128) as usize;
1106        let bit_shift = bits % 128;
1107
1108        let mut result = [0u128; 4];
1109        for i in word_shift..4 {
1110            result[i] = self.0[i - word_shift] << bit_shift;
1111            if bit_shift > 0 && i > word_shift {
1112                result[i] |= self.0[i - word_shift - 1] >> (128 - bit_shift);
1113            }
1114        }
1115        Self(result)
1116    }
1117
1118    /// Shift right by `bits`.
1119    fn shr_u512(self, bits: u32) -> Self {
1120        if bits >= 512 {
1121            return Self::ZERO;
1122        }
1123        if bits == 0 {
1124            return self;
1125        }
1126        let word_shift = (bits / 128) as usize;
1127        let bit_shift = bits % 128;
1128
1129        let mut result = [0u128; 4];
1130        for i in 0..(4 - word_shift) {
1131            result[i] = self.0[i + word_shift] >> bit_shift;
1132            if bit_shift > 0 && (i + word_shift + 1) < 4 {
1133                result[i] |= self.0[i + word_shift + 1] << (128 - bit_shift);
1134            }
1135        }
1136        Self(result)
1137    }
1138
1139    /// Subtract rhs from self. Assumes self >= rhs.
1140    fn sub_u512(self, rhs: Self) -> Self {
1141        let mut result = [0u128; 4];
1142        let mut borrow = false;
1143        for i in 0..4 {
1144            let (d1, b1) = self.0[i].overflowing_sub(rhs.0[i]);
1145            let (d2, b2) = d1.overflowing_sub(borrow as u128);
1146            result[i] = d2;
1147            borrow = b1 || b2;
1148        }
1149        Self(result)
1150    }
1151
1152    /// Bitwise OR with a U512 that has only the bit at position `bit` set.
1153    fn set_bit(self, bit: u32) -> Self {
1154        if bit >= 512 {
1155            return self;
1156        }
1157        let word = (bit / 128) as usize;
1158        let b = bit % 128;
1159        let mut result = self.0;
1160        result[word] |= 1u128 << b;
1161        Self(result)
1162    }
1163
1164    /// Count leading zeros.
1165    fn leading_zeros(&self) -> u32 {
1166        for i in (0..4).rev() {
1167            if self.0[i] != 0 {
1168                return (3 - i as u32) * 128 + self.0[i].leading_zeros();
1169            }
1170        }
1171        512
1172    }
1173
1174    /// Convert to U256, returning None if the value doesn't fit.
1175    fn try_into_u256(self) -> Option<U256> {
1176        if self.0[2] != 0 || self.0[3] != 0 {
1177            None
1178        } else {
1179            Some(U256::new(self.0[0], self.0[1]))
1180        }
1181    }
1182
1183    /// Divide U512 by U256, returning (quotient as U256, remainder as U256).
1184    /// Panics if divisor is zero or quotient doesn't fit in U256.
1185    fn div_rem_by_u256(self, den: U256) -> (U256, U256) {
1186        match self.checked_div_rem_by_u256(den) {
1187            Some(result) => result,
1188            None => panic!("mul_div quotient must fit U256"),
1189        }
1190    }
1191
1192    /// Checked variant: returns None if quotient doesn't fit in U256.
1193    fn checked_div_rem_by_u256(self, den: U256) -> Option<(U256, U256)> {
1194        assert!(!den.is_zero(), "U512 division by zero");
1195
1196        if self.is_zero() {
1197            return Some((U256::ZERO, U256::ZERO));
1198        }
1199
1200        let den_512 = U512::from_u256(den);
1201
1202        if self.cmp_u512(&den_512) == Ordering::Less {
1203            let r = self.try_into_u256().expect("remainder must fit U256");
1204            return Some((U256::ZERO, r));
1205        }
1206
1207        let num_lz = self.leading_zeros();
1208        let den_lz = den_512.leading_zeros();
1209
1210        if den_lz < num_lz {
1211            let r = self.try_into_u256().expect("remainder must fit U256");
1212            return Some((U256::ZERO, r));
1213        }
1214
1215        let shift = den_lz - num_lz;
1216        let mut remainder = self;
1217        let mut quotient = U512::ZERO;
1218        let mut divisor = den_512.shl_u512(shift);
1219
1220        let mut i = shift as i32;
1221        while i >= 0 {
1222            if remainder.cmp_u512(&divisor) != Ordering::Less {
1223                remainder = remainder.sub_u512(divisor);
1224                quotient = quotient.set_bit(i as u32);
1225            }
1226            divisor = divisor.shr_u512(1);
1227            i -= 1;
1228        }
1229
1230        let q = quotient.try_into_u256()?;
1231        let r = remainder.try_into_u256().expect("remainder must fit U256");
1232        Some((q, r))
1233    }
1234}
1235
1236// ============================================================================
1237// Spec section 4.6 helpers
1238// ============================================================================
1239
1240/// Spec section 4.6: signed floor division with positive denominator.
1241///
1242/// Computes floor(n / d) where d > 0. Uses truncation toward zero, then
1243/// adjusts: if n < 0 and there is a non-zero remainder, subtract 1.
1244pub fn floor_div_signed_conservative(n: I256, d: U256) -> I256 {
1245    assert!(
1246        !d.is_zero(),
1247        "floor_div_signed_conservative: zero denominator"
1248    );
1249
1250    if n.is_zero() {
1251        return I256::ZERO;
1252    }
1253
1254    let negative = n.is_negative();
1255
1256    // Compute |n| without negating I256 directly for MIN safety.
1257    // We reinterpret the bits and do unsigned division.
1258    if !negative {
1259        // n >= 0: floor(n/d) = trunc(n/d) since both positive.
1260        let n_u = n.abs_u256();
1261        let (q, _r) = div_rem_u256(n_u, d);
1262        // q fits in I256 since n was positive and q <= n.
1263        I256::from_raw_u256(q)
1264    } else {
1265        // n < 0. We need floor(n / d).
1266        // n = -|n|. trunc(n/d) = -(|n| / d). floor = trunc - (1 if |n| % d != 0).
1267        //
1268        // Work with the raw bits to avoid I256::MIN negation issues.
1269        //
1270        // Two's complement: if n is negative, its unsigned representation is 2^256 - |n|.
1271        // We can compute |n| = ~n + 1 (bitwise not + 1).
1272        let raw = n.as_raw_u256();
1273        // |n| = ~raw + 1
1274        let inv = U256::new(!raw.lo(), !raw.hi());
1275        let abs_n = inv.checked_add(U256::ONE).expect("abs of negative I256");
1276
1277        let (q, r) = div_rem_u256(abs_n, d);
1278
1279        // Result = -q if r == 0, else -(q+1)
1280        let q_final = if r.is_zero() {
1281            q
1282        } else {
1283            q.checked_add(U256::ONE)
1284                .expect("floor_div quotient overflow")
1285        };
1286
1287        // Negate q_final to get the negative I256 result.
1288        // q_final as I256 then negate.
1289        if q_final.is_zero() {
1290            I256::ZERO
1291        } else {
1292            let qi = I256::from_raw_u256(q_final);
1293            qi.checked_neg().expect("floor_div result out of range")
1294        }
1295    }
1296}
1297
1298/// Native i128 floor division: floor(n / d) for positive d, rounding toward
1299/// negative infinity. Mirrors `floor_div_signed_conservative` but uses native
1300/// i128/u128 arithmetic for the funding-term computation (spec §5.4).
1301pub fn floor_div_signed_conservative_i128(n: i128, d: u128) -> i128 {
1302    assert!(
1303        d != 0,
1304        "floor_div_signed_conservative_i128: zero denominator"
1305    );
1306
1307    if n == 0 {
1308        return 0;
1309    }
1310
1311    if n > 0 {
1312        // Non-negative: floor = truncation
1313        (n as u128 / d) as i128
1314    } else {
1315        // Negative: floor(n/d) = -(|n| / d) - (if |n| % d != 0 then 1 else 0)
1316        let abs_n = n.unsigned_abs();
1317        let q = abs_n / d;
1318        let r = abs_n % d;
1319        let q_final = if r != 0 { q + 1 } else { q };
1320        assert!(
1321            q_final <= i128::MAX as u128,
1322            "floor_div_signed_conservative_i128: result out of range"
1323        );
1324        -(q_final as i128)
1325    }
1326}
1327
1328/// Spec section 4.6: positive ceiling division.
1329/// ceil(n / d) = (n + d - 1) / d, but we use the remainder form to avoid overflow:
1330/// ceil(n / d) = trunc(n / d) + (1 if n % d != 0 else 0).
1331pub fn ceil_div_positive_checked(n: U256, d: U256) -> U256 {
1332    assert!(!d.is_zero(), "ceil_div_positive_checked: zero denominator");
1333    let (q, r) = div_rem_u256(n, d);
1334    if r.is_zero() {
1335        q
1336    } else {
1337        q.checked_add(U256::ONE).expect("ceil_div overflow")
1338    }
1339}
1340
1341/// Spec section 4.6: exact wide product then floor divide.
1342/// Computes floor(a * b / d) using a U512 intermediate to avoid overflow.
1343pub fn mul_div_floor_u256(a: U256, b: U256, d: U256) -> U256 {
1344    assert!(!d.is_zero(), "mul_div_floor_u256: zero denominator");
1345    let product = U512::mul_u256(a, b);
1346    let (q, _r) = product.div_rem_by_u256(d);
1347    q
1348}
1349
1350/// Like mul_div_floor_u256 but also returns the remainder.
1351/// Returns (floor(a * b / d), (a * b) mod d).
1352pub fn mul_div_floor_u256_with_rem(a: U256, b: U256, d: U256) -> (U256, U256) {
1353    assert!(
1354        !d.is_zero(),
1355        "mul_div_floor_u256_with_rem: zero denominator"
1356    );
1357    let product = U512::mul_u256(a, b);
1358    product.div_rem_by_u256(d)
1359}
1360
1361/// Spec section 4.6: exact wide product then ceiling divide.
1362/// Computes ceil(a * b / d) using a U512 intermediate.
1363pub fn mul_div_ceil_u256(a: U256, b: U256, d: U256) -> U256 {
1364    assert!(!d.is_zero(), "mul_div_ceil_u256: zero denominator");
1365    let product = U512::mul_u256(a, b);
1366    let (q, r) = product.div_rem_by_u256(d);
1367    if r.is_zero() {
1368        q
1369    } else {
1370        q.checked_add(U256::ONE).expect("mul_div_ceil overflow")
1371    }
1372}
1373
1374/// Checked variant of mul_div_ceil_u256.
1375/// Returns None if the quotient doesn't fit in U256.
1376#[allow(dead_code)]
1377pub fn checked_mul_div_ceil_u256(a: U256, b: U256, d: U256) -> Option<U256> {
1378    if d.is_zero() {
1379        return None;
1380    }
1381    let product = U512::mul_u256(a, b);
1382    let (q, r) = product.checked_div_rem_by_u256(d)?;
1383    if r.is_zero() {
1384        Some(q)
1385    } else {
1386        q.checked_add(U256::ONE)
1387    }
1388}
1389
1390/// Spec section 4.6: saturating multiply for warmup cap.
1391pub fn saturating_mul_u256_u64(a: U256, b: u64) -> U256 {
1392    let rhs = U256::from_u64(b);
1393    a.checked_mul(rhs).unwrap_or(U256::MAX)
1394}
1395
1396/// Spec section 4.6: checked fee-debt conversion.
1397/// If fee_credits < 0, the account owes fees. Returns the unsigned debt.
1398/// If fee_credits >= 0, returns 0 (no debt).
1399pub fn fee_debt_u128_checked(fee_credits: i128) -> u128 {
1400    if fee_credits < 0 {
1401        // debt = -fee_credits. Use checked_neg to handle i128::MIN.
1402        // i128::MIN.unsigned_abs() is safe and returns 2^127.
1403        fee_credits.unsigned_abs()
1404    } else {
1405        0
1406    }
1407}
1408
1409/// Spec section 1.5 item 11: wide signed mul-div for pnl_delta.
1410///
1411/// Computes floor_div_signed_conservative(abs_basis * k_diff, denominator)
1412/// where the numerator may exceed 256 bits.
1413///
1414/// Uses the sign of `k_diff`. Computes `abs_basis * abs(k_diff)` as U512,
1415/// then applies floor_div_signed_conservative logic.
1416pub fn wide_signed_mul_div_floor(abs_basis: U256, k_diff: I256, denominator: U256) -> I256 {
1417    assert!(
1418        !denominator.is_zero(),
1419        "wide_signed_mul_div_floor: zero denominator"
1420    );
1421
1422    if k_diff.is_zero() || abs_basis.is_zero() {
1423        return I256::ZERO;
1424    }
1425
1426    let negative = k_diff.is_negative();
1427    let abs_k = if negative {
1428        assert!(
1429            k_diff != I256::MIN,
1430            "wide_signed_mul_div_floor: k_diff == I256::MIN"
1431        );
1432        k_diff.abs_u256()
1433    } else {
1434        k_diff.abs_u256()
1435    };
1436
1437    // Wide product: abs_basis * abs_k as U512
1438    let product = U512::mul_u256(abs_basis, abs_k);
1439    let (q, r) = product.div_rem_by_u256(denominator);
1440
1441    if !negative {
1442        // Positive: floor division = truncation
1443        I256::from_raw_u256(q)
1444    } else {
1445        // Negative: if remainder != 0, subtract 1 from quotient (floor toward -inf)
1446        let q_final = if r.is_zero() {
1447            q
1448        } else {
1449            q.checked_add(U256::ONE)
1450                .expect("wide_signed_mul_div_floor quotient overflow")
1451        };
1452        if q_final.is_zero() {
1453            I256::ZERO
1454        } else {
1455            let qi = I256::from_raw_u256(q_final);
1456            qi.checked_neg()
1457                .expect("wide_signed_mul_div_floor result out of I256 range")
1458        }
1459    }
1460}
1461
1462// ============================================================================
1463// Helper: I256 from_raw_u256 / as_raw_u256 -- unified access
1464// ============================================================================
1465// These are defined as methods in each cfg block above. The free functions
1466// below delegate to them for use in shared code.
1467
1468impl I256 {
1469    // Ensure the shared free-standing code can use these regardless of cfg.
1470    // (The methods are already defined in each cfg block.)
1471}
1472
1473// ============================================================================
1474// §4.8 v11.31 Native 128-bit Arithmetic Helpers
1475// ============================================================================
1476
1477/// Native multiply-divide floor. Product a*b must not overflow u128. Panics on d==0.
1478pub fn mul_div_floor_u128(a: u128, b: u128, d: u128) -> u128 {
1479    assert!(d > 0, "mul_div_floor_u128: division by zero");
1480    let p = a.checked_mul(b).expect("mul_div_floor_u128: a*b overflow");
1481    p / d
1482}
1483
1484/// Native multiply-divide ceil. Product a*b must not overflow u128. Panics on d==0.
1485pub fn mul_div_ceil_u128(a: u128, b: u128, d: u128) -> u128 {
1486    assert!(d > 0, "mul_div_ceil_u128: division by zero");
1487    let p = a.checked_mul(b).expect("mul_div_ceil_u128: a*b overflow");
1488    let q = p / d;
1489    if p % d != 0 {
1490        q + 1
1491    } else {
1492        q
1493    }
1494}
1495
1496/// Exact wide multiply-divide floor using U256 intermediate.
1497/// Used for haircut paths where a*b can exceed u128::MAX.
1498pub fn wide_mul_div_floor_u128(a: u128, b: u128, d: u128) -> u128 {
1499    assert!(d > 0, "wide_mul_div_floor_u128: division by zero");
1500    let result = mul_div_floor_u256(U256::from_u128(a), U256::from_u128(b), U256::from_u128(d));
1501    result
1502        .try_into_u128()
1503        .expect("wide_mul_div_floor_u128: result exceeds u128")
1504}
1505
1506/// Safe K-difference settlement (spec §4.8 lines 720-732).
1507/// Computes K-difference in wide intermediate, then multiplies and divides.
1508pub fn wide_signed_mul_div_floor_from_k_pair(
1509    abs_basis: u128,
1510    k_then: i128,
1511    k_now: i128,
1512    den: u128,
1513) -> i128 {
1514    assert!(den > 0, "wide_signed_mul_div_floor_from_k_pair: den == 0");
1515    // Compute d = k_now - k_then in wide signed to avoid i128 overflow (spec §4.8)
1516    let k_now_wide = I256::from_i128(k_now);
1517    let k_then_wide = I256::from_i128(k_then);
1518    let d = k_now_wide
1519        .checked_sub(k_then_wide)
1520        .expect("K-diff overflow in wide");
1521    if d.is_zero() || abs_basis == 0 {
1522        return 0i128;
1523    }
1524    let abs_d = d.abs_u256();
1525    let abs_basis_u256 = U256::from_u128(abs_basis);
1526    let den_u256 = U256::from_u128(den);
1527    // p = abs_basis * abs(d), exact wide product
1528    let p = abs_basis_u256
1529        .checked_mul(abs_d)
1530        .expect("wide product overflow");
1531    let (q, rem) = div_rem_u256(p, den_u256);
1532    if d.is_negative() {
1533        // mag = q + 1 if r != 0 else q
1534        let mag = if !rem.is_zero() {
1535            q.checked_add(U256::ONE).expect("mag overflow")
1536        } else {
1537            q
1538        };
1539        let mag_u128 = mag.try_into_u128().expect("mag exceeds u128");
1540        assert!(
1541            mag_u128 <= i128::MAX as u128,
1542            "wide_signed_mul_div_floor_from_k_pair: mag > i128::MAX"
1543        );
1544        -(mag_u128 as i128)
1545    } else {
1546        let q_u128 = q.try_into_u128().expect("quotient exceeds u128");
1547        assert!(
1548            q_u128 <= i128::MAX as u128,
1549            "wide_signed_mul_div_floor_from_k_pair: q > i128::MAX"
1550        );
1551        q_u128 as i128
1552    }
1553}
1554
1555/// ADL delta_K representability check error.
1556#[derive(Clone, Copy, Debug, PartialEq, Eq)]
1557pub struct OverI128Magnitude;
1558
1559/// ADL delta_K representability check.
1560/// Returns Ok(v) if the ceil result fits in i128 magnitude, Err otherwise.
1561pub fn wide_mul_div_ceil_u128_or_over_i128max(
1562    a: u128,
1563    b: u128,
1564    d: u128,
1565) -> core::result::Result<u128, OverI128Magnitude> {
1566    assert!(
1567        d > 0,
1568        "wide_mul_div_ceil_u128_or_over_i128max: division by zero"
1569    );
1570    let result = mul_div_ceil_u256(U256::from_u128(a), U256::from_u128(b), U256::from_u128(d));
1571    match result.try_into_u128() {
1572        Some(v) if v <= i128::MAX as u128 => Ok(v),
1573        _ => Err(OverI128Magnitude),
1574    }
1575}
1576
1577/// Saturating multiply for warmup cap computation.
1578pub fn saturating_mul_u128_u64(a: u128, b: u64) -> u128 {
1579    if a == 0 || b == 0 {
1580        return 0;
1581    }
1582    let b128 = b as u128;
1583    a.checked_mul(b128).unwrap_or(u128::MAX)
1584}
1585
1586// ============================================================================
1587// Tests
1588// ============================================================================
1589#[cfg(test)]
1590mod tests {
1591    use super::*;
1592
1593    // --- U256 basic construction ---
1594    #[test]
1595    fn test_u256_zero_one_max() {
1596        assert!(U256::ZERO.is_zero());
1597        assert!(!U256::ONE.is_zero());
1598        assert_eq!(U256::ONE.lo(), 1);
1599        assert_eq!(U256::ONE.hi(), 0);
1600        assert_eq!(U256::MAX.lo(), u128::MAX);
1601        assert_eq!(U256::MAX.hi(), u128::MAX);
1602    }
1603
1604    #[test]
1605    fn test_u256_from_u128() {
1606        let v = U256::from_u128(42);
1607        assert_eq!(v.lo(), 42);
1608        assert_eq!(v.hi(), 0);
1609        assert_eq!(v.try_into_u128(), Some(42));
1610    }
1611
1612    #[test]
1613    fn test_u256_try_into_u128_overflow() {
1614        let v = U256::new(1, 1);
1615        assert_eq!(v.try_into_u128(), None);
1616    }
1617
1618    // --- U256 addition ---
1619    #[test]
1620    fn test_u256_checked_add() {
1621        let a = U256::from_u128(100);
1622        let b = U256::from_u128(200);
1623        assert_eq!(a.checked_add(b), Some(U256::from_u128(300)));
1624    }
1625
1626    #[test]
1627    fn test_u256_add_with_carry() {
1628        let a = U256::new(u128::MAX, 0);
1629        let b = U256::new(1, 0);
1630        let c = a.checked_add(b).unwrap();
1631        assert_eq!(c.lo(), 0);
1632        assert_eq!(c.hi(), 1);
1633    }
1634
1635    #[test]
1636    fn test_u256_add_overflow() {
1637        assert_eq!(U256::MAX.checked_add(U256::ONE), None);
1638    }
1639
1640    #[test]
1641    fn test_u256_saturating_add() {
1642        assert_eq!(U256::MAX.saturating_add(U256::ONE), U256::MAX);
1643    }
1644
1645    // --- U256 subtraction ---
1646    #[test]
1647    fn test_u256_checked_sub() {
1648        let a = U256::from_u128(300);
1649        let b = U256::from_u128(100);
1650        assert_eq!(a.checked_sub(b), Some(U256::from_u128(200)));
1651    }
1652
1653    #[test]
1654    fn test_u256_sub_underflow() {
1655        let a = U256::from_u128(1);
1656        let b = U256::from_u128(2);
1657        assert_eq!(a.checked_sub(b), None);
1658    }
1659
1660    // --- U256 multiplication ---
1661    #[test]
1662    fn test_u256_checked_mul_small() {
1663        let a = U256::from_u128(1_000_000);
1664        let b = U256::from_u128(1_000_000);
1665        assert_eq!(a.checked_mul(b), Some(U256::from_u128(1_000_000_000_000)));
1666    }
1667
1668    #[test]
1669    fn test_u256_checked_mul_cross() {
1670        // (2^128) * 2 = 2^129
1671        let a = U256::new(0, 1); // 2^128
1672        let b = U256::from_u128(2);
1673        let c = a.checked_mul(b).unwrap();
1674        assert_eq!(c.lo(), 0);
1675        assert_eq!(c.hi(), 2);
1676    }
1677
1678    #[test]
1679    fn test_u256_mul_overflow() {
1680        let a = U256::new(0, 1); // 2^128
1681        let b = U256::new(0, 1); // 2^128
1682                                 // Product would be 2^256, which overflows.
1683        assert_eq!(a.checked_mul(b), None);
1684    }
1685
1686    // --- U256 division ---
1687    #[test]
1688    fn test_u256_div_basic() {
1689        let a = U256::from_u128(1000);
1690        let b = U256::from_u128(3);
1691        assert_eq!(a.checked_div(b), Some(U256::from_u128(333)));
1692        assert_eq!(a.checked_rem(b), Some(U256::from_u128(1)));
1693    }
1694
1695    #[test]
1696    fn test_u256_div_large() {
1697        // Divide a 256-bit number by a 128-bit number
1698        let a = U256::new(0, 4); // 4 * 2^128
1699        let b = U256::from_u128(2);
1700        let q = a.checked_div(b).unwrap();
1701        assert_eq!(q, U256::new(0, 2)); // 2 * 2^128
1702    }
1703
1704    #[test]
1705    fn test_u256_div_by_zero() {
1706        assert_eq!(U256::ONE.checked_div(U256::ZERO), None);
1707    }
1708
1709    // --- U256 comparison ---
1710    #[test]
1711    fn test_u256_ordering() {
1712        assert!(U256::ZERO < U256::ONE);
1713        assert!(U256::ONE < U256::MAX);
1714        assert!(U256::new(0, 1) > U256::new(u128::MAX, 0));
1715    }
1716
1717    // --- U256 shifts ---
1718    #[test]
1719    fn test_u256_shl_shr() {
1720        let a = U256::ONE;
1721        let b = a.shl(128);
1722        assert_eq!(b, U256::new(0, 1));
1723        let c = b.shr(128);
1724        assert_eq!(c, U256::ONE);
1725
1726        // Shift by 256 gives zero
1727        assert_eq!(U256::MAX.shl(256), U256::ZERO);
1728        assert_eq!(U256::MAX.shr(256), U256::ZERO);
1729    }
1730
1731    // --- U256 bitwise ---
1732    #[test]
1733    fn test_u256_bitand_bitor() {
1734        let a = U256::new(0xFF, 0xFF00);
1735        let b = U256::new(0x0F, 0xFF00);
1736        assert_eq!(a.bitand(b), U256::new(0x0F, 0xFF00));
1737        assert_eq!(a.bitor(b), U256::new(0xFF, 0xFF00));
1738    }
1739
1740    // --- I256 basic ---
1741    #[test]
1742    fn test_i256_zero_one_minusone() {
1743        assert!(I256::ZERO.is_zero());
1744        assert!(I256::ONE.is_positive());
1745        assert!(I256::MINUS_ONE.is_negative());
1746        assert_eq!(I256::ONE.signum(), 1);
1747        assert_eq!(I256::ZERO.signum(), 0);
1748        assert_eq!(I256::MINUS_ONE.signum(), -1);
1749    }
1750
1751    #[test]
1752    fn test_i256_from_i128() {
1753        let v = I256::from_i128(-42);
1754        assert!(v.is_negative());
1755        assert_eq!(v.try_into_i128(), Some(-42));
1756
1757        let v2 = I256::from_i128(i128::MAX);
1758        assert_eq!(v2.try_into_i128(), Some(i128::MAX));
1759
1760        let v3 = I256::from_i128(i128::MIN);
1761        assert_eq!(v3.try_into_i128(), Some(i128::MIN));
1762    }
1763
1764    // --- I256 addition / subtraction ---
1765    #[test]
1766    fn test_i256_add() {
1767        let a = I256::from_i128(100);
1768        let b = I256::from_i128(-50);
1769        let c = a.checked_add(b).unwrap();
1770        assert_eq!(c.try_into_i128(), Some(50));
1771    }
1772
1773    #[test]
1774    fn test_i256_sub() {
1775        let a = I256::from_i128(10);
1776        let b = I256::from_i128(20);
1777        let c = a.checked_sub(b).unwrap();
1778        assert_eq!(c.try_into_i128(), Some(-10));
1779    }
1780
1781    #[test]
1782    fn test_i256_neg() {
1783        let a = I256::from_i128(42);
1784        let b = a.checked_neg().unwrap();
1785        assert_eq!(b.try_into_i128(), Some(-42));
1786
1787        // MIN cannot be negated
1788        assert_eq!(I256::MIN.checked_neg(), None);
1789    }
1790
1791    #[test]
1792    fn test_i256_overflow() {
1793        // MAX + 1 overflows
1794        assert_eq!(I256::MAX.checked_add(I256::ONE), None);
1795        // MIN - 1 overflows
1796        assert_eq!(I256::MIN.checked_sub(I256::ONE), None);
1797    }
1798
1799    #[test]
1800    fn test_i256_abs_u256() {
1801        let v = I256::from_i128(-100);
1802        let a = v.abs_u256();
1803        assert_eq!(a, U256::from_u128(100));
1804    }
1805
1806    // --- I256 comparison ---
1807    #[test]
1808    fn test_i256_ordering() {
1809        assert!(I256::MIN < I256::MINUS_ONE);
1810        assert!(I256::MINUS_ONE < I256::ZERO);
1811        assert!(I256::ZERO < I256::ONE);
1812        assert!(I256::ONE < I256::MAX);
1813    }
1814
1815    // --- floor_div_signed_conservative ---
1816    #[test]
1817    fn test_floor_div_positive() {
1818        // 7 / 3 = 2 (floor = trunc for positive)
1819        let n = I256::from_i128(7);
1820        let d = U256::from_u128(3);
1821        let q = floor_div_signed_conservative(n, d);
1822        assert_eq!(q.try_into_i128(), Some(2));
1823    }
1824
1825    #[test]
1826    fn test_floor_div_negative_exact() {
1827        // -6 / 3 = -2 (exact, no rounding)
1828        let n = I256::from_i128(-6);
1829        let d = U256::from_u128(3);
1830        let q = floor_div_signed_conservative(n, d);
1831        assert_eq!(q.try_into_i128(), Some(-2));
1832    }
1833
1834    #[test]
1835    fn test_floor_div_negative_remainder() {
1836        // -7 / 3: trunc = -2, remainder = 1, floor = -3
1837        let n = I256::from_i128(-7);
1838        let d = U256::from_u128(3);
1839        let q = floor_div_signed_conservative(n, d);
1840        assert_eq!(q.try_into_i128(), Some(-3));
1841    }
1842
1843    // --- mul_div_floor / mul_div_ceil ---
1844    #[test]
1845    fn test_mul_div_floor() {
1846        // 10 * 20 / 3 = 200 / 3 = 66
1847        let a = U256::from_u128(10);
1848        let b = U256::from_u128(20);
1849        let d = U256::from_u128(3);
1850        assert_eq!(mul_div_floor_u256(a, b, d), U256::from_u128(66));
1851    }
1852
1853    #[test]
1854    fn test_mul_div_ceil() {
1855        // 10 * 20 / 3 = 200 / 3 = ceil(66.67) = 67
1856        let a = U256::from_u128(10);
1857        let b = U256::from_u128(20);
1858        let d = U256::from_u128(3);
1859        assert_eq!(mul_div_ceil_u256(a, b, d), U256::from_u128(67));
1860    }
1861
1862    #[test]
1863    fn test_mul_div_large() {
1864        // Test with values that would overflow U256 in intermediate:
1865        // (2^200) * (2^200) / (2^200) = 2^200
1866        let big = U256::ONE.shl(200);
1867        assert_eq!(mul_div_floor_u256(big, big, big), big);
1868    }
1869
1870    #[test]
1871    fn test_mul_div_exact() {
1872        // 6 * 7 / 42 = 1 exactly
1873        let a = U256::from_u128(6);
1874        let b = U256::from_u128(7);
1875        let d = U256::from_u128(42);
1876        assert_eq!(mul_div_floor_u256(a, b, d), U256::ONE);
1877        assert_eq!(mul_div_ceil_u256(a, b, d), U256::ONE);
1878    }
1879
1880    // --- ceil_div_positive_checked ---
1881    #[test]
1882    fn test_ceil_div_positive() {
1883        // ceil(7 / 3) = 3
1884        assert_eq!(
1885            ceil_div_positive_checked(U256::from_u128(7), U256::from_u128(3)),
1886            U256::from_u128(3)
1887        );
1888        // ceil(6 / 3) = 2
1889        assert_eq!(
1890            ceil_div_positive_checked(U256::from_u128(6), U256::from_u128(3)),
1891            U256::from_u128(2)
1892        );
1893    }
1894
1895    // --- saturating_mul_u256_u64 ---
1896    #[test]
1897    fn test_saturating_mul_u256_u64() {
1898        let a = U256::from_u128(100);
1899        assert_eq!(saturating_mul_u256_u64(a, 5), U256::from_u128(500));
1900        // Saturates on overflow
1901        assert_eq!(saturating_mul_u256_u64(U256::MAX, 2), U256::MAX);
1902    }
1903
1904    // --- fee_debt_u128_checked ---
1905    #[test]
1906    fn test_fee_debt() {
1907        assert_eq!(fee_debt_u128_checked(-100), 100);
1908        assert_eq!(fee_debt_u128_checked(100), 0);
1909        assert_eq!(fee_debt_u128_checked(0), 0);
1910        assert_eq!(fee_debt_u128_checked(i128::MIN), 1u128 << 127);
1911    }
1912
1913    // --- wide_signed_mul_div_floor ---
1914    #[test]
1915    fn test_wide_signed_mul_div_floor_positive() {
1916        // 10 * 20 / 3 = floor(200/3) = 66
1917        let abs_basis = U256::from_u128(10);
1918        let k_diff = I256::from_i128(20);
1919        let denom = U256::from_u128(3);
1920        let result = wide_signed_mul_div_floor(abs_basis, k_diff, denom);
1921        assert_eq!(result.try_into_i128(), Some(66));
1922    }
1923
1924    #[test]
1925    fn test_wide_signed_mul_div_floor_negative() {
1926        // 10 * (-7) / 3 = floor(-70/3) = floor(-23.33) = -24
1927        let abs_basis = U256::from_u128(10);
1928        let k_diff = I256::from_i128(-7);
1929        let denom = U256::from_u128(3);
1930        let result = wide_signed_mul_div_floor(abs_basis, k_diff, denom);
1931        assert_eq!(result.try_into_i128(), Some(-24));
1932    }
1933
1934    #[test]
1935    fn test_wide_signed_mul_div_floor_exact_negative() {
1936        // 10 * (-6) / 3 = floor(-60/3) = -20 (exact)
1937        let abs_basis = U256::from_u128(10);
1938        let k_diff = I256::from_i128(-6);
1939        let denom = U256::from_u128(3);
1940        let result = wide_signed_mul_div_floor(abs_basis, k_diff, denom);
1941        assert_eq!(result.try_into_i128(), Some(-20));
1942    }
1943
1944    #[test]
1945    fn test_wide_signed_mul_div_floor_zero() {
1946        let abs_basis = U256::from_u128(10);
1947        let k_diff = I256::ZERO;
1948        let denom = U256::from_u128(3);
1949        let result = wide_signed_mul_div_floor(abs_basis, k_diff, denom);
1950        assert_eq!(result, I256::ZERO);
1951    }
1952
1953    // --- U256 operator traits ---
1954    #[test]
1955    #[should_panic(expected = "U256 add overflow")]
1956    fn test_u256_add_op_panic() {
1957        let _ = U256::MAX + U256::ONE;
1958    }
1959
1960    #[test]
1961    #[should_panic(expected = "U256 sub underflow")]
1962    fn test_u256_sub_op_panic() {
1963        let _ = U256::ZERO - U256::ONE;
1964    }
1965
1966    #[test]
1967    fn test_u256_overflowing() {
1968        let (val, overflow) = U256::MAX.overflowing_add(U256::ONE);
1969        assert!(overflow);
1970        assert_eq!(val, U256::ZERO);
1971
1972        let (val, underflow) = U256::ZERO.overflowing_sub(U256::ONE);
1973        assert!(underflow);
1974        assert_eq!(val, U256::MAX);
1975    }
1976
1977    // --- I256 from_u128 (positive only) ---
1978    #[test]
1979    fn test_i256_from_u128() {
1980        let v = I256::from_u128(100);
1981        assert!(v.is_positive());
1982        assert_eq!(v.try_into_i128(), Some(100));
1983    }
1984
1985    // --- I256 sub involving MIN ---
1986    #[test]
1987    fn test_i256_sub_min() {
1988        // 0 - MIN overflows (since |MIN| > MAX)
1989        assert_eq!(I256::ZERO.checked_sub(I256::MIN), None);
1990    }
1991
1992    // --- AddAssign / SubAssign ---
1993    #[test]
1994    fn test_u256_assign_ops() {
1995        let mut v = U256::from_u128(10);
1996        v += U256::from_u128(5);
1997        assert_eq!(v, U256::from_u128(15));
1998        v -= U256::from_u128(3);
1999        assert_eq!(v, U256::from_u128(12));
2000    }
2001
2002    // --- I256 saturating_add ---
2003    #[test]
2004    fn test_i256_saturating_add() {
2005        assert_eq!(I256::MAX.saturating_add(I256::ONE), I256::MAX);
2006        assert_eq!(I256::MIN.saturating_add(I256::MINUS_ONE), I256::MIN);
2007    }
2008
2009    // --- U256 widening mul u128 test ---
2010    #[test]
2011    fn test_widening_mul_u128() {
2012        let (lo, hi) = widening_mul_u128(u128::MAX, u128::MAX);
2013        // (2^128-1)^2 = 2^256 - 2^129 + 1
2014        // lo = 1, hi = 2^128 - 2 = u128::MAX - 1
2015        assert_eq!(lo, 1);
2016        assert_eq!(hi, u128::MAX - 1);
2017    }
2018
2019    // --- Large mul_div test ---
2020    #[test]
2021    fn test_mul_div_max() {
2022        // MAX * 1 / 1 = MAX
2023        assert_eq!(
2024            mul_div_floor_u256(U256::MAX, U256::ONE, U256::ONE),
2025            U256::MAX
2026        );
2027        // 1 * 1 / 1 = 1
2028        assert_eq!(
2029            mul_div_floor_u256(U256::ONE, U256::ONE, U256::ONE),
2030            U256::ONE
2031        );
2032    }
2033}