fixed_bigint/heapless/
multiple.rs1use super::HeaplessBigInt;
8use crate::MachineWord;
9use const_num_traits::{CarryingMul, CheckedAdd, MultipleOf, Nct, NextMultipleOf, Zero};
10
11impl<T, const CAP: usize> MultipleOf for HeaplessBigInt<T, CAP, Nct>
12where
13 T: MachineWord + CarryingMul<Unsigned = T, Output = T>,
14{
15 fn is_multiple_of(self, rhs: Self) -> bool {
16 if <Self as Zero>::is_zero(&rhs) {
17 false
18 } else {
19 <Self as Zero>::is_zero(&(self % rhs))
20 }
21 }
22}
23
24impl<T, const CAP: usize> NextMultipleOf for HeaplessBigInt<T, CAP, Nct>
25where
26 T: MachineWord + CarryingMul<Unsigned = T, Output = T>,
27{
28 type Output = Self;
29
30 fn next_multiple_of(self, rhs: Self) -> Self {
31 match self.checked_next_multiple_of(rhs) {
32 Some(v) => v,
33 None => panic!("HeaplessBigInt::next_multiple_of: rhs is zero or the result overflows"),
34 }
35 }
36
37 fn checked_next_multiple_of(self, rhs: Self) -> Option<Self> {
38 if <Self as Zero>::is_zero(&rhs) {
39 return None;
40 }
41 let rem = self % rhs;
42 if <Self as Zero>::is_zero(&rem) {
43 Some(self.widened(core::cmp::max(self.len(), rhs.len())))
47 } else {
48 CheckedAdd::checked_add(self, rhs - rem)
50 }
51 }
52}
53
54impl<T, const CAP: usize> MultipleOf for &HeaplessBigInt<T, CAP, Nct>
56where
57 T: MachineWord + CarryingMul<Unsigned = T, Output = T>,
58{
59 fn is_multiple_of(self, rhs: Self) -> bool {
60 <HeaplessBigInt<T, CAP, Nct> as MultipleOf>::is_multiple_of(*self, *rhs)
61 }
62}
63
64impl<T, const CAP: usize> NextMultipleOf for &HeaplessBigInt<T, CAP, Nct>
65where
66 T: MachineWord + CarryingMul<Unsigned = T, Output = T>,
67{
68 type Output = HeaplessBigInt<T, CAP, Nct>;
69
70 fn next_multiple_of(self, rhs: Self) -> Self::Output {
71 <HeaplessBigInt<T, CAP, Nct> as NextMultipleOf>::next_multiple_of(*self, *rhs)
72 }
73
74 fn checked_next_multiple_of(self, rhs: Self) -> Option<Self::Output> {
75 <HeaplessBigInt<T, CAP, Nct> as NextMultipleOf>::checked_next_multiple_of(*self, *rhs)
76 }
77}
78
79#[cfg(test)]
80mod tests {
81 use super::HeaplessBigInt;
82 use const_num_traits::NextMultipleOf;
83
84 type H = HeaplessBigInt<u8, 8>;
85
86 #[test]
90 fn already_multiple_preserves_wider_rhs_width() {
91 let self_narrow = H::from(10u8); let rhs_wide = H::from(5u8).widened(8); assert_eq!(self_narrow.len(), 1);
94 let out = NextMultipleOf::checked_next_multiple_of(self_narrow, rhs_wide).unwrap();
95 assert_eq!(out, H::from(10u8));
96 assert_eq!(out.len(), 8, "result must widen to max(self.len, rhs.len)");
97 }
98
99 #[test]
100 fn rhs_larger_than_self_is_rhs() {
101 let out = NextMultipleOf::next_multiple_of(H::from(3u8), H::from(10u8));
103 assert_eq!(out, H::from(10u8));
104 }
105
106 #[test]
107 fn byref_matches_value() {
108 use const_num_traits::MultipleOf;
109 let a = H::from(12u8);
110 let b = H::from(5u8);
111 assert_eq!(
112 MultipleOf::is_multiple_of(&a, &b),
113 MultipleOf::is_multiple_of(a, b)
114 );
115 assert_eq!(
116 NextMultipleOf::next_multiple_of(&a, &b),
117 NextMultipleOf::next_multiple_of(a, b)
118 );
119 assert_eq!(
120 NextMultipleOf::checked_next_multiple_of(&a, &b),
121 NextMultipleOf::checked_next_multiple_of(a, b)
122 );
123 }
124}