1use super::{FixedUInt, MachineWord};
18use crate::machineword::ConstMachineWord;
19use const_num_traits::Nct;
20use const_num_traits::{CheckedAdd, MultipleOf, NextMultipleOf, Zero};
21
22c0nst::c0nst! {
23 c0nst impl<T: [c0nst] ConstMachineWord + MachineWord, const N: usize> MultipleOf for FixedUInt<T, N, Nct> {
24 fn is_multiple_of(self, rhs: Self) -> bool {
25 if <Self as Zero>::is_zero(&rhs) {
26 false
27 } else {
28 <Self as Zero>::is_zero(&(self % rhs))
29 }
30 }
31 }
32
33 c0nst impl<T: [c0nst] ConstMachineWord + MachineWord, const N: usize> NextMultipleOf for FixedUInt<T, N, Nct> {
34 type Output = FixedUInt<T, N, Nct>;
35 fn next_multiple_of(self, rhs: Self) -> Self {
36 match self.checked_next_multiple_of(rhs) {
37 Some(v) => v,
38 None => panic!("next_multiple_of: rhs is zero or result overflows"),
39 }
40 }
41
42 fn checked_next_multiple_of(self, rhs: Self) -> Option<Self> {
43 if rhs.is_zero() {
44 return None;
45 }
46 let rem = self % rhs;
47 if rem.is_zero() {
48 Some(self)
49 } else {
50 let add = rhs - rem;
52 CheckedAdd::checked_add(self, add)
53 }
54 }
55 }
56
57 c0nst impl<T: [c0nst] ConstMachineWord + MachineWord, const N: usize> MultipleOf for &FixedUInt<T, N, Nct> {
58 fn is_multiple_of(self, rhs: Self) -> bool {
59 <FixedUInt<T, N, Nct> as MultipleOf>::is_multiple_of(FixedUInt::from_array(self.array), FixedUInt::from_array(rhs.array))
60 }
61 }
62
63 c0nst impl<T: [c0nst] ConstMachineWord + MachineWord, const N: usize> NextMultipleOf for &FixedUInt<T, N, Nct> {
64 type Output = FixedUInt<T, N, Nct>;
65 fn next_multiple_of(self, rhs: Self) -> FixedUInt<T, N, Nct> {
66 <FixedUInt<T, N, Nct> as NextMultipleOf>::next_multiple_of(FixedUInt::from_array(self.array), FixedUInt::from_array(rhs.array))
67 }
68 fn checked_next_multiple_of(self, rhs: Self) -> Option<FixedUInt<T, N, Nct>> {
69 <FixedUInt<T, N, Nct> as NextMultipleOf>::checked_next_multiple_of(FixedUInt::from_array(self.array), FixedUInt::from_array(rhs.array))
70 }
71 }
72}
73
74#[cfg(test)]
75mod tests {
76 use super::*;
77
78 #[test]
79 fn test_is_multiple_of() {
80 type U16 = FixedUInt<u8, 2>;
81
82 assert!(MultipleOf::is_multiple_of(U16::from(0u8), U16::from(5u8)));
83 assert!(MultipleOf::is_multiple_of(U16::from(10u8), U16::from(5u8)));
84 assert!(MultipleOf::is_multiple_of(U16::from(15u8), U16::from(5u8)));
85 assert!(!MultipleOf::is_multiple_of(U16::from(11u8), U16::from(5u8)));
86 assert!(MultipleOf::is_multiple_of(
87 U16::from(100u8),
88 U16::from(10u8)
89 ));
90 assert!(!MultipleOf::is_multiple_of(
91 U16::from(101u8),
92 U16::from(10u8)
93 ));
94
95 assert!(!MultipleOf::is_multiple_of(U16::from(10u8), U16::from(0u8)));
97 }
98
99 #[test]
100 fn test_next_multiple_of() {
101 type U16 = FixedUInt<u8, 2>;
102
103 assert_eq!(
105 NextMultipleOf::next_multiple_of(U16::from(10u8), U16::from(5u8)),
106 U16::from(10u8)
107 );
108 assert_eq!(
109 NextMultipleOf::next_multiple_of(U16::from(0u8), U16::from(5u8)),
110 U16::from(0u8)
111 );
112
113 assert_eq!(
115 NextMultipleOf::next_multiple_of(U16::from(11u8), U16::from(5u8)),
116 U16::from(15u8)
117 );
118 assert_eq!(
119 NextMultipleOf::next_multiple_of(U16::from(12u8), U16::from(5u8)),
120 U16::from(15u8)
121 );
122 assert_eq!(
123 NextMultipleOf::next_multiple_of(U16::from(14u8), U16::from(5u8)),
124 U16::from(15u8)
125 );
126
127 assert_eq!(
129 NextMultipleOf::next_multiple_of(U16::from(101u8), U16::from(10u8)),
130 U16::from(110u8)
131 );
132 }
133
134 #[test]
135 fn test_checked_next_multiple_of() {
136 type U16 = FixedUInt<u8, 2>;
137
138 assert_eq!(
140 NextMultipleOf::checked_next_multiple_of(U16::from(11u8), U16::from(5u8)),
141 Some(U16::from(15u8))
142 );
143
144 assert_eq!(
146 NextMultipleOf::checked_next_multiple_of(U16::from(10u8), U16::from(0u8)),
147 None
148 );
149
150 let large = U16::from(65530u16);
152 assert_eq!(
153 NextMultipleOf::checked_next_multiple_of(large, U16::from(10u8)),
154 Some(large)
155 ); let large2 = U16::from(65531u16);
159 assert_eq!(
160 NextMultipleOf::checked_next_multiple_of(large2, U16::from(10u8)),
161 None
162 ); }
164
165 c0nst::c0nst! {
166 pub c0nst fn const_is_multiple_of<T: [c0nst] ConstMachineWord + MachineWord, const N: usize>(
167 a: &FixedUInt<T, N, Nct>,
168 b: &FixedUInt<T, N, Nct>,
169 ) -> bool {
170 MultipleOf::is_multiple_of(*a, *b)
171 }
172
173 pub c0nst fn const_next_multiple_of<T: [c0nst] ConstMachineWord + MachineWord, const N: usize>(
174 a: FixedUInt<T, N, Nct>,
175 b: FixedUInt<T, N, Nct>,
176 ) -> FixedUInt<T, N, Nct> {
177 NextMultipleOf::next_multiple_of(a, b)
178 }
179 }
180
181 #[test]
182 fn test_const_multiple() {
183 type U16 = FixedUInt<u8, 2>;
184
185 assert!(const_is_multiple_of(&U16::from(10u8), &U16::from(5u8)));
186 assert_eq!(
187 const_next_multiple_of(U16::from(11u8), U16::from(5u8)),
188 U16::from(15u8)
189 );
190
191 #[cfg(feature = "nightly")]
192 {
193 const TEN: U16 = FixedUInt::from_array([10, 0]);
194 const FIVE: U16 = FixedUInt::from_array([5, 0]);
195 const IS_MULT: bool = const_is_multiple_of(&TEN, &FIVE);
196 assert!(IS_MULT);
197
198 const ELEVEN: U16 = FixedUInt::from_array([11, 0]);
199 const NEXT: U16 = const_next_multiple_of(ELEVEN, FIVE);
200 assert_eq!(NEXT, FixedUInt::from_array([15, 0]));
201 }
202 }
203}