1use crate::{Absorb, Rational8, Rational16, Rational32, Rational64, Rational128, RationalUsize};
11use crate::fixed::{Binary, One, SignedOne, Zero};
12
13macro_rules! absorb_small {
14 ($name:ty; $($int:ty),* $(,)?) => {
15 impl Absorb<$name> for $name {
17 #[inline]
18 fn from_narrow(narrow: &$name) -> Self { *narrow }
19 #[inline]
20 fn add_narrow(&mut self, narrow: &$name) { *self += narrow }
21 #[inline]
22 fn sub_narrow(&mut self, narrow: &$name) { *self -= narrow }
23 #[inline]
24 fn mul_narrow(&self, narrow: &$name) -> Self { let mut r = *self; r *= narrow; r }
25 #[inline]
26 fn add_mul_narrow(&mut self, narrow: &$name, other: &Self) {
27 let mut product = *other;
28 product *= narrow;
29 *self += product;
30 }
31 }
32
33 impl Absorb<One> for $name {
34 #[inline]
35 fn from_narrow(_: &One) -> Self { <Self as num_traits::One>::one() }
36 #[inline]
37 fn add_narrow(&mut self, _: &One) { *self += One }
38 #[inline]
39 fn sub_narrow(&mut self, _: &One) { *self -= One }
40 #[inline]
41 fn mul_narrow(&self, _: &One) -> Self { *self }
42 #[inline]
43 fn add_mul_narrow(&mut self, _: &One, other: &Self) { *self += other }
44 }
45
46 impl Absorb<Zero> for $name {
47 #[inline]
48 fn from_narrow(_: &Zero) -> Self { <Self as num_traits::Zero>::zero() }
49 #[inline]
50 fn add_narrow(&mut self, _: &Zero) {}
51 #[inline]
52 fn sub_narrow(&mut self, _: &Zero) {}
53 #[inline]
54 fn mul_narrow(&self, _: &Zero) -> Self { <Self as num_traits::Zero>::zero() }
55 #[inline]
56 fn add_mul_narrow(&mut self, _: &Zero, _: &Self) {}
57 }
58
59 impl Absorb<Binary> for $name {
60 #[inline]
61 fn from_narrow(narrow: &Binary) -> Self {
62 match narrow {
63 Binary::Zero => <Self as num_traits::Zero>::zero(),
64 Binary::One => <Self as num_traits::One>::one(),
65 }
66 }
67 #[inline]
68 fn add_narrow(&mut self, narrow: &Binary) {
69 match narrow { Binary::Zero => {}, Binary::One => *self += One }
70 }
71 #[inline]
72 fn sub_narrow(&mut self, narrow: &Binary) {
73 match narrow { Binary::Zero => {}, Binary::One => *self -= One }
74 }
75 #[inline]
76 fn mul_narrow(&self, narrow: &Binary) -> Self {
77 match narrow {
78 Binary::Zero => <Self as num_traits::Zero>::zero(),
79 Binary::One => *self,
80 }
81 }
82 #[inline]
83 fn add_mul_narrow(&mut self, narrow: &Binary, other: &Self) {
84 match narrow { Binary::Zero => {}, Binary::One => *self += other }
85 }
86 }
87
88 impl Absorb<SignedOne> for $name {
89 #[inline]
90 fn from_narrow(narrow: &SignedOne) -> Self {
91 match narrow {
92 SignedOne::PlusOne => <Self as num_traits::One>::one(),
93 SignedOne::MinusOne => -<Self as num_traits::One>::one(),
94 }
95 }
96 #[inline]
97 fn add_narrow(&mut self, narrow: &SignedOne) {
98 match narrow {
99 SignedOne::PlusOne => *self += One,
100 SignedOne::MinusOne => *self -= One,
101 }
102 }
103 #[inline]
104 fn sub_narrow(&mut self, narrow: &SignedOne) {
105 match narrow {
106 SignedOne::PlusOne => *self -= One,
107 SignedOne::MinusOne => *self += One,
108 }
109 }
110 #[inline]
111 fn mul_narrow(&self, narrow: &SignedOne) -> Self {
112 match narrow {
113 SignedOne::PlusOne => *self,
114 SignedOne::MinusOne => -*self,
115 }
116 }
117 #[inline]
118 fn add_mul_narrow(&mut self, narrow: &SignedOne, other: &Self) {
119 match narrow {
120 SignedOne::PlusOne => *self += other,
121 SignedOne::MinusOne => *self -= other,
122 }
123 }
124 }
125
126 $(
127 impl Absorb<$int> for $name {
128 #[inline]
129 fn from_narrow(narrow: &$int) -> Self { Self::from(*narrow) }
130 #[inline]
131 fn add_narrow(&mut self, narrow: &$int) { *self += *narrow }
132 #[inline]
133 fn sub_narrow(&mut self, narrow: &$int) { *self -= *narrow }
134 #[inline]
135 fn mul_narrow(&self, narrow: &$int) -> Self { let mut r = *self; r *= *narrow; r }
136 #[inline]
137 fn add_mul_narrow(&mut self, narrow: &$int, other: &Self) {
138 let mut product = *other;
139 product *= *narrow;
140 *self += product;
141 }
142 }
143 )*
144
145 impl<N> Absorb<Option<N>> for $name where $name: Absorb<N> {
147 #[inline]
148 fn from_narrow(narrow: &Option<N>) -> Self {
149 match narrow {
150 None => <Self as num_traits::Zero>::zero(),
151 Some(value) => <$name as Absorb<N>>::from_narrow(value),
152 }
153 }
154 #[inline]
155 fn add_narrow(&mut self, narrow: &Option<N>) {
156 if let Some(value) = narrow { self.add_narrow(value) }
157 }
158 #[inline]
159 fn sub_narrow(&mut self, narrow: &Option<N>) {
160 if let Some(value) = narrow { self.sub_narrow(value) }
161 }
162 #[inline]
163 fn mul_narrow(&self, narrow: &Option<N>) -> Self {
164 match narrow {
165 None => <Self as num_traits::Zero>::zero(),
166 Some(value) => self.mul_narrow(value),
167 }
168 }
169 #[inline]
170 fn add_mul_narrow(&mut self, narrow: &Option<N>, other: &Self) {
171 if let Some(value) = narrow { self.add_mul_narrow(value, other) }
172 }
173 }
174
175 impl<N> Absorb<&N> for $name where $name: Absorb<N> {
177 #[inline]
178 fn from_narrow(narrow: &&N) -> Self { <$name as Absorb<N>>::from_narrow(narrow) }
179 #[inline]
180 fn add_narrow(&mut self, narrow: &&N) { self.add_narrow(*narrow) }
181 #[inline]
182 fn sub_narrow(&mut self, narrow: &&N) { self.sub_narrow(*narrow) }
183 #[inline]
184 fn mul_narrow(&self, narrow: &&N) -> Self { self.mul_narrow(*narrow) }
185 #[inline]
186 fn add_mul_narrow(&mut self, narrow: &&N, other: &Self) {
187 self.add_mul_narrow(*narrow, other)
188 }
189 }
190 }
191}
192
193absorb_small!(Rational8; u8, i8);
194absorb_small!(Rational16; u8, u16, i8, i16);
195absorb_small!(Rational32; u8, u16, u32, i8, i16, i32);
196absorb_small!(Rational64; u8, u16, u32, u64, i8, i16, i32, i64);
197absorb_small!(Rational128; u8, u16, u32, u64, u128, i8, i16, i32, i64, i128);
198
199macro_rules! absorb_by_identity {
204 ($name:ty) => {
205 impl Absorb<$name> for $name {
206 #[inline]
207 fn from_narrow(narrow: &$name) -> Self { *narrow }
208 #[inline]
209 fn add_narrow(&mut self, narrow: &$name) { *self += narrow }
210 #[inline]
211 fn sub_narrow(&mut self, narrow: &$name) { *self -= narrow }
212 #[inline]
213 fn mul_narrow(&self, narrow: &$name) -> Self { let mut r = *self; r *= narrow; r }
214 #[inline]
215 fn add_mul_narrow(&mut self, narrow: &$name, other: &Self) {
216 let mut product = *other;
217 product *= narrow;
218 *self += product;
219 }
220 }
221
222 impl Absorb<One> for $name {
223 #[inline]
224 fn from_narrow(_: &One) -> Self { <Self as num_traits::One>::one() }
225 #[inline]
226 fn add_narrow(&mut self, _: &One) { *self += <Self as num_traits::One>::one() }
227 #[inline]
228 fn sub_narrow(&mut self, _: &One) { *self -= <Self as num_traits::One>::one() }
229 #[inline]
230 fn mul_narrow(&self, _: &One) -> Self { *self }
231 #[inline]
232 fn add_mul_narrow(&mut self, _: &One, other: &Self) { *self += other }
233 }
234
235 impl Absorb<Zero> for $name {
236 #[inline]
237 fn from_narrow(_: &Zero) -> Self { <Self as num_traits::Zero>::zero() }
238 #[inline]
239 fn add_narrow(&mut self, _: &Zero) {}
240 #[inline]
241 fn sub_narrow(&mut self, _: &Zero) {}
242 #[inline]
243 fn mul_narrow(&self, _: &Zero) -> Self { <Self as num_traits::Zero>::zero() }
244 #[inline]
245 fn add_mul_narrow(&mut self, _: &Zero, _: &Self) {}
246 }
247
248 impl<N> Absorb<Option<N>> for $name where $name: Absorb<N> {
249 #[inline]
250 fn from_narrow(narrow: &Option<N>) -> Self {
251 match narrow {
252 None => <Self as num_traits::Zero>::zero(),
253 Some(value) => <$name as Absorb<N>>::from_narrow(value),
254 }
255 }
256 #[inline]
257 fn add_narrow(&mut self, narrow: &Option<N>) {
258 if let Some(value) = narrow { self.add_narrow(value) }
259 }
260 #[inline]
261 fn sub_narrow(&mut self, narrow: &Option<N>) {
262 if let Some(value) = narrow { self.sub_narrow(value) }
263 }
264 #[inline]
265 fn mul_narrow(&self, narrow: &Option<N>) -> Self {
266 match narrow {
267 None => <Self as num_traits::Zero>::zero(),
268 Some(value) => self.mul_narrow(value),
269 }
270 }
271 #[inline]
272 fn add_mul_narrow(&mut self, narrow: &Option<N>, other: &Self) {
273 if let Some(value) = narrow { self.add_mul_narrow(value, other) }
274 }
275 }
276
277 impl<N> Absorb<&N> for $name where $name: Absorb<N> {
278 #[inline]
279 fn from_narrow(narrow: &&N) -> Self { <$name as Absorb<N>>::from_narrow(narrow) }
280 #[inline]
281 fn add_narrow(&mut self, narrow: &&N) { self.add_narrow(*narrow) }
282 #[inline]
283 fn sub_narrow(&mut self, narrow: &&N) { self.sub_narrow(*narrow) }
284 #[inline]
285 fn mul_narrow(&self, narrow: &&N) -> Self { self.mul_narrow(*narrow) }
286 #[inline]
287 fn add_mul_narrow(&mut self, narrow: &&N, other: &Self) {
288 self.add_mul_narrow(*narrow, other)
289 }
290 }
291 }
292}
293
294absorb_by_identity!(RationalUsize);
295
296#[cfg(test)]
297mod test {
298 use crate::{Absorb, Rational64, RationalUsize, R32, R64, R8};
299 use crate::fixed::{Binary, One, SignedOne, Zero};
300
301 fn check<T>(value: &T, wide: Rational64)
304 where
305 Rational64: Absorb<T>,
306 {
307 assert_eq!(Rational64::from_narrow(value), wide, "from_narrow");
308
309 let start = R64!(5, 3);
310
311 let mut by_override = start;
312 by_override.add_narrow(value);
313 assert_eq!(by_override, start + wide, "add_narrow");
314
315 let mut by_override = start;
316 by_override.sub_narrow(value);
317 assert_eq!(by_override, start - wide, "sub_narrow");
318
319 assert_eq!(start.mul_narrow(value), wide * start, "mul_narrow");
320
321 for other in [R64!(0), R64!(1), R64!(-7, 5), start] {
322 let mut fused = start;
323 fused.add_mul_narrow(value, &other);
324 assert_eq!(fused, start + wide * other, "add_mul_narrow by {other}");
325 }
326 }
327
328 #[test]
329 fn markers() {
330 check(&One, R64!(1));
331 check(&Zero, R64!(0));
332 check(&Binary::Zero, R64!(0));
333 check(&Binary::One, R64!(1));
334 check(&SignedOne::PlusOne, R64!(1));
335 check(&SignedOne::MinusOne, R64!(-1));
336 }
337
338 #[test]
339 fn integers_and_self() {
340 check(&7_i32, R64!(7));
341 check(&-7_i64, R64!(-7));
342 check(&0_u8, R64!(0));
343 check(&R64!(-9, 4), R64!(-9, 4));
344 }
345
346 #[test]
347 fn options_and_references() {
348 check(&Some(One), R64!(1));
349 check(&None::<One>, R64!(0));
350 check(&&SignedOne::MinusOne, R64!(-1));
351 check(&Some(&7_i32), R64!(7));
352 }
353
354 #[test]
356 fn every_width_is_an_accumulator() {
357 let mut small = R8!(1, 2);
358 small.add_narrow(&One);
359 assert_eq!(small, R8!(3, 2));
360 assert_eq!(small.mul_narrow(&SignedOne::MinusOne), R8!(-3, 2));
361
362 let mut medium = R32!(1, 4);
363 medium.add_mul_narrow(&3_i32, &R32!(1, 2));
364 assert_eq!(medium, R32!(7, 4));
365
366 let mut pointer_width = RationalUsize::new(1, 2).unwrap();
369 pointer_width.add_narrow(&One);
370 assert_eq!(pointer_width, RationalUsize::new(3, 2).unwrap());
371 assert_eq!(
372 pointer_width.mul_narrow(&Zero),
373 RationalUsize::new(0, 1).unwrap(),
374 );
375 }
376}