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