1use super::HeaplessBigInt;
12use crate::MachineWord;
13use const_num_traits::{
14 CarryingMul, Nct, OverflowingAdd, OverflowingMul, OverflowingSub, StrictAdd, StrictDiv,
15 StrictMul, StrictRem, StrictShl, StrictShr, StrictSub,
16};
17
18impl<T, const CAP: usize> StrictAdd for HeaplessBigInt<T, CAP, Nct>
19where
20 T: MachineWord,
21{
22 type Output = Self;
23 fn strict_add(self, v: Self) -> Self {
24 let (res, overflow) = OverflowingAdd::overflowing_add(self, v);
25 assert!(!overflow, "HeaplessBigInt: strict_add overflowed");
26 res
27 }
28}
29
30impl<T, const CAP: usize> StrictSub for HeaplessBigInt<T, CAP, Nct>
31where
32 T: MachineWord,
33{
34 type Output = Self;
35 fn strict_sub(self, v: Self) -> Self {
36 let (res, overflow) = OverflowingSub::overflowing_sub(self, v);
37 assert!(!overflow, "HeaplessBigInt: strict_sub underflowed");
38 res
39 }
40}
41
42impl<T, const CAP: usize> StrictMul for HeaplessBigInt<T, CAP, Nct>
43where
44 T: MachineWord + CarryingMul<Unsigned = T, Output = T>,
45{
46 type Output = Self;
47 fn strict_mul(self, v: Self) -> Self {
48 let (res, overflow) = OverflowingMul::overflowing_mul(self, v);
49 assert!(!overflow, "HeaplessBigInt: strict_mul overflowed");
50 res
51 }
52}
53
54impl<T, const CAP: usize> StrictDiv for HeaplessBigInt<T, CAP, Nct>
55where
56 T: MachineWord + CarryingMul<Unsigned = T, Output = T>,
57{
58 type Output = Self;
59 fn strict_div(self, v: Self) -> Self {
60 self / v
62 }
63}
64
65impl<T, const CAP: usize> StrictRem for HeaplessBigInt<T, CAP, Nct>
66where
67 T: MachineWord + CarryingMul<Unsigned = T, Output = T>,
68{
69 type Output = Self;
70 fn strict_rem(self, v: Self) -> Self {
71 self % v
72 }
73}
74
75impl<T, const CAP: usize> StrictShl for HeaplessBigInt<T, CAP, Nct>
76where
77 T: MachineWord,
78{
79 type Output = Self;
80 fn strict_shl(self, rhs: u32) -> Self {
81 let value_bits = self.len() as u32 * (core::mem::size_of::<T>() as u32 * 8);
82 assert!(
83 rhs < value_bits,
84 "HeaplessBigInt: strict_shl shift exceeds the value width"
85 );
86 self << (rhs as usize)
87 }
88}
89
90impl<T, const CAP: usize> StrictShr for HeaplessBigInt<T, CAP, Nct>
91where
92 T: MachineWord,
93{
94 type Output = Self;
95 fn strict_shr(self, rhs: u32) -> Self {
96 let value_bits = self.len() as u32 * (core::mem::size_of::<T>() as u32 * 8);
97 assert!(
98 rhs < value_bits,
99 "HeaplessBigInt: strict_shr shift exceeds the value width"
100 );
101 self >> (rhs as usize)
102 }
103}
104
105impl<T, const CAP: usize> StrictAdd for &HeaplessBigInt<T, CAP, Nct>
109where
110 T: MachineWord,
111{
112 type Output = HeaplessBigInt<T, CAP, Nct>;
113 fn strict_add(self, v: Self) -> Self::Output {
114 <HeaplessBigInt<T, CAP, Nct> as StrictAdd>::strict_add(*self, *v)
115 }
116}
117
118impl<T, const CAP: usize> StrictSub for &HeaplessBigInt<T, CAP, Nct>
119where
120 T: MachineWord,
121{
122 type Output = HeaplessBigInt<T, CAP, Nct>;
123 fn strict_sub(self, v: Self) -> Self::Output {
124 <HeaplessBigInt<T, CAP, Nct> as StrictSub>::strict_sub(*self, *v)
125 }
126}
127
128impl<T, const CAP: usize> StrictMul for &HeaplessBigInt<T, CAP, Nct>
129where
130 T: MachineWord + CarryingMul<Unsigned = T, Output = T>,
131{
132 type Output = HeaplessBigInt<T, CAP, Nct>;
133 fn strict_mul(self, v: Self) -> Self::Output {
134 <HeaplessBigInt<T, CAP, Nct> as StrictMul>::strict_mul(*self, *v)
135 }
136}
137
138impl<T, const CAP: usize> StrictDiv for &HeaplessBigInt<T, CAP, Nct>
139where
140 T: MachineWord + CarryingMul<Unsigned = T, Output = T>,
141{
142 type Output = HeaplessBigInt<T, CAP, Nct>;
143 fn strict_div(self, v: Self) -> Self::Output {
144 <HeaplessBigInt<T, CAP, Nct> as StrictDiv>::strict_div(*self, *v)
145 }
146}
147
148impl<T, const CAP: usize> StrictRem for &HeaplessBigInt<T, CAP, Nct>
149where
150 T: MachineWord + CarryingMul<Unsigned = T, Output = T>,
151{
152 type Output = HeaplessBigInt<T, CAP, Nct>;
153 fn strict_rem(self, v: Self) -> Self::Output {
154 <HeaplessBigInt<T, CAP, Nct> as StrictRem>::strict_rem(*self, *v)
155 }
156}
157
158impl<T, const CAP: usize> StrictShl for &HeaplessBigInt<T, CAP, Nct>
159where
160 T: MachineWord,
161{
162 type Output = HeaplessBigInt<T, CAP, Nct>;
163 fn strict_shl(self, rhs: u32) -> Self::Output {
164 <HeaplessBigInt<T, CAP, Nct> as StrictShl>::strict_shl(*self, rhs)
165 }
166}
167
168impl<T, const CAP: usize> StrictShr for &HeaplessBigInt<T, CAP, Nct>
169where
170 T: MachineWord,
171{
172 type Output = HeaplessBigInt<T, CAP, Nct>;
173 fn strict_shr(self, rhs: u32) -> Self::Output {
174 <HeaplessBigInt<T, CAP, Nct> as StrictShr>::strict_shr(*self, rhs)
175 }
176}
177
178#[cfg(test)]
179mod tests {
180 use super::HeaplessBigInt;
181 use const_num_traits::{StrictAdd, StrictMul, StrictShl, StrictSub};
182
183 type H = HeaplessBigInt<u8, 4>; #[test]
186 fn strict_ok_paths() {
187 let a = H::from(10u8).widened(4);
188 assert_eq!(StrictAdd::strict_add(a, H::from(20u8)), H::from(30u8));
189 assert_eq!(StrictSub::strict_sub(a, H::from(3u8)), H::from(7u8));
190 assert_eq!(StrictMul::strict_mul(a, H::from(3u8)), H::from(30u8));
191 assert_eq!(
192 StrictShl::strict_shl(H::from(1u8).widened(4), 8),
193 H::from(256u16)
194 );
195 }
196
197 #[test]
198 #[should_panic(expected = "strict_add overflowed")]
199 fn strict_add_overflow_panics() {
200 StrictAdd::strict_add(H::from(u32::MAX), H::from(1u8));
201 }
202
203 #[test]
204 #[should_panic(expected = "strict_shl shift exceeds")]
205 fn strict_shl_over_width_panics() {
206 StrictShl::strict_shl(H::from(1u8).widened(4), 32);
207 }
208
209 #[test]
210 fn byref_matches_value() {
211 let a = H::from(10u8).widened(4);
212 let b = H::from(20u8);
213 assert_eq!(StrictAdd::strict_add(&a, &b), StrictAdd::strict_add(a, b));
214 }
215}