1use core::{marker::PhantomData, ops::Mul};
2
3use crate::{boundable::*, Predicate, Refinement};
4
5use super::*;
6
7impl<
8 const A: usize,
9 Type: unsigned::UnsignedBoundable + Mul<Output = Type>,
10 B: UnsignedMax<Type> + Predicate<Type>,
11 > Mul<Refinement<Type, B>> for Refinement<Type, unsigned::LessThan<A>>
12where
13 Refinement<Type, unsigned::LessThan<{ (A - 1) * B::UMAX + 1 }>>: Sized,
14{
15 type Output = Refinement<Type, unsigned::LessThan<{ (A - 1) * B::UMAX + 1 }>>;
16
17 fn mul(self, rhs: Refinement<Type, B>) -> Self::Output {
18 Refinement(self.0 * rhs.0, PhantomData)
19 }
20}
21
22impl<
23 const A: usize,
24 Type: unsigned::UnsignedBoundable + Mul<Output = Type>,
25 B: UnsignedMax<Type> + Predicate<Type>,
26 > Mul<Refinement<Type, B>> for Refinement<Type, unsigned::LessThanEqual<A>>
27where
28 Refinement<Type, unsigned::LessThanEqual<{ A * B::UMAX }>>: Sized,
29{
30 type Output = Refinement<Type, unsigned::LessThanEqual<{ A * B::UMAX }>>;
31
32 fn mul(self, rhs: Refinement<Type, B>) -> Self::Output {
33 Refinement(self.0 * rhs.0, PhantomData)
34 }
35}
36
37impl<
38 const A: usize,
39 Type: unsigned::UnsignedBoundable + Mul<Output = Type>,
40 B: UnsignedMin<Type> + Predicate<Type>,
41 > Mul<Refinement<Type, B>> for Refinement<Type, unsigned::GreaterThan<A>>
42where
43 Refinement<Type, unsigned::GreaterThan<{ (A + 1) * B::UMIN - 1 }>>: Sized,
44{
45 type Output = Refinement<Type, unsigned::GreaterThan<{ (A + 1) * B::UMIN - 1 }>>;
46
47 fn mul(self, rhs: Refinement<Type, B>) -> Self::Output {
48 Refinement(self.0 * rhs.0, PhantomData)
49 }
50}
51
52impl<
53 const A: usize,
54 Type: unsigned::UnsignedBoundable + Mul<Output = Type>,
55 B: UnsignedMin<Type> + Predicate<Type>,
56 > Mul<Refinement<Type, B>> for Refinement<Type, unsigned::GreaterThanEqual<A>>
57where
58 Refinement<Type, unsigned::GreaterThanEqual<{ A * B::UMIN }>>: Sized,
59{
60 type Output = Refinement<Type, unsigned::GreaterThanEqual<{ A * B::UMIN }>>;
61
62 fn mul(self, rhs: Refinement<Type, B>) -> Self::Output {
63 Refinement(self.0 * rhs.0, PhantomData)
64 }
65}
66
67impl<
68 const MIN: usize,
69 const MAX: usize,
70 Type: unsigned::UnsignedBoundable + Mul<Output = Type>,
71 B: UnsignedMinMax<Type> + Predicate<Type>,
72 > Mul<Refinement<Type, B>> for Refinement<Type, unsigned::OpenInterval<MIN, MAX>>
73where
74 Refinement<
75 Type,
76 unsigned::OpenInterval<{ (MIN + 1) * B::UMIN - 1 }, { (MAX - 1) * B::UMAX + 1 }>,
77 >: Sized,
78{
79 type Output = Refinement<
80 Type,
81 unsigned::OpenInterval<{ (MIN + 1) * B::UMIN - 1 }, { (MAX - 1) * B::UMAX + 1 }>,
82 >;
83
84 fn mul(self, rhs: Refinement<Type, B>) -> Self::Output {
85 Refinement(self.0 * rhs.0, PhantomData)
86 }
87}
88
89impl<
90 const MIN: usize,
91 const MAX: usize,
92 Type: unsigned::UnsignedBoundable + Mul<Output = Type>,
93 B: UnsignedMinMax<Type> + Predicate<Type>,
94 > Mul<Refinement<Type, B>> for Refinement<Type, unsigned::ClosedInterval<MIN, MAX>>
95where
96 Refinement<Type, unsigned::ClosedInterval<{ MIN * B::UMIN }, { MAX * B::UMAX }>>: Sized,
97{
98 type Output = Refinement<Type, unsigned::ClosedInterval<{ MIN * B::UMIN }, { MAX * B::UMAX }>>;
99
100 fn mul(self, rhs: Refinement<Type, B>) -> Self::Output {
101 Refinement(self.0 * rhs.0, PhantomData)
102 }
103}
104
105impl<
106 const MIN: usize,
107 const MAX: usize,
108 Type: unsigned::UnsignedBoundable + Mul<Output = Type>,
109 B: UnsignedMinMax<Type> + Predicate<Type>,
110 > Mul<Refinement<Type, B>> for Refinement<Type, unsigned::OpenClosedInterval<MIN, MAX>>
111where
112 Refinement<Type, unsigned::OpenClosedInterval<{ (MIN + 1) * B::UMIN - 1 }, { MAX * B::UMAX }>>:
113 Sized,
114{
115 type Output = Refinement<
116 Type,
117 unsigned::OpenClosedInterval<{ (MIN + 1) * B::UMIN - 1 }, { MAX * B::UMAX }>,
118 >;
119
120 fn mul(self, rhs: Refinement<Type, B>) -> Self::Output {
121 Refinement(self.0 * rhs.0, PhantomData)
122 }
123}
124
125impl<
126 const MIN: usize,
127 const MAX: usize,
128 Type: unsigned::UnsignedBoundable + Mul<Output = Type>,
129 B: UnsignedMinMax<Type> + Predicate<Type>,
130 > Mul<Refinement<Type, B>> for Refinement<Type, unsigned::ClosedOpenInterval<MIN, MAX>>
131where
132 Refinement<Type, unsigned::ClosedOpenInterval<{ MIN * B::UMIN }, { (MAX - 1) * B::UMAX + 1 }>>:
133 Sized,
134{
135 type Output = Refinement<
136 Type,
137 unsigned::ClosedOpenInterval<{ MIN * B::UMIN }, { (MAX - 1) * B::UMAX + 1 }>,
138 >;
139
140 fn mul(self, rhs: Refinement<Type, B>) -> Self::Output {
141 Refinement(self.0 * rhs.0, PhantomData)
142 }
143}
144
145#[cfg(test)]
146mod unsigned_tests {
147 use super::*;
148 use crate::prelude::*;
149
150 #[test]
151 fn test_lt_mul_lt() {
152 let a = Refinement::<u8, unsigned::LessThan<10>>::refine(9).unwrap();
153 let b = Refinement::<u8, unsigned::LessThan<10>>::refine(9).unwrap();
154 let c: Refinement<u8, unsigned::LessThan<82>> = a * b;
155 assert_eq!(*c, 81);
156 }
157
158 #[test]
159 fn test_lte_mul_lte() {
160 let a = Refinement::<u8, unsigned::LessThanEqual<10>>::refine(6).unwrap();
161 let b = Refinement::<u8, unsigned::LessThanEqual<10>>::refine(3).unwrap();
162 let c: Refinement<u8, unsigned::LessThanEqual<100>> = a * b;
163 assert_eq!(*c, 18);
164 }
165
166 #[test]
167 fn test_lte_mul_lt() {
168 let a = Refinement::<u8, unsigned::LessThanEqual<10>>::refine(6).unwrap();
169 let b = Refinement::<u8, unsigned::LessThan<11>>::refine(3).unwrap();
170 let c: Refinement<u8, unsigned::LessThanEqual<100>> = a * b;
171 assert_eq!(*c, 18);
172 }
173
174 #[test]
175 fn test_gt_mul_gt() {
176 let a = Refinement::<u8, unsigned::GreaterThan<10>>::refine(11).unwrap();
177 let b = Refinement::<u8, unsigned::GreaterThan<10>>::refine(11).unwrap();
178 let c: Refinement<u8, unsigned::GreaterThan<120>> = a * b;
179 assert_eq!(*c, 121);
180 }
181
182 #[test]
183 fn test_gt_mul_gte() {
184 let a = Refinement::<u8, unsigned::GreaterThan<10>>::refine(11).unwrap();
185 let b = Refinement::<u8, unsigned::GreaterThanEqual<3>>::refine(3).unwrap();
186 let c: Refinement<u8, unsigned::GreaterThan<32>> = a * b;
187 assert_eq!(*c, 33);
188 }
189
190 #[test]
191 fn test_gte_mul_gte() {
192 let a = Refinement::<u8, unsigned::GreaterThanEqual<10>>::refine(12).unwrap();
193 let b = Refinement::<u8, unsigned::GreaterThanEqual<3>>::refine(3).unwrap();
194 let c: Refinement<u8, unsigned::GreaterThanEqual<30>> = a * b;
195 assert_eq!(*c, 36);
196 }
197
198 #[test]
199 fn test_gte_mul_gt() {
200 let a = Refinement::<u8, unsigned::GreaterThanEqual<12>>::refine(15).unwrap();
201 let b = Refinement::<u8, unsigned::GreaterThan<3>>::refine(4).unwrap();
202 let c: Refinement<u8, unsigned::GreaterThanEqual<48>> = a * b;
203 assert_eq!(*c, 60);
204 }
205
206 #[test]
207 fn test_open_closed_interval_mul() {
208 let a = Refinement::<u8, unsigned::OpenClosedInterval<15, 20>>::refine(18).unwrap();
209 let b = Refinement::<u8, unsigned::OpenClosedInterval<3, 6>>::refine(6).unwrap();
210 let c: Refinement<u8, unsigned::OpenClosedInterval<63, 120>> = a * b;
211 assert_eq!(*c, 108);
212 }
213
214 #[test]
215 fn test_closed_open_interval_mul() {
216 let a = Refinement::<u16, unsigned::ClosedOpenInterval<50, 100>>::refine(99).unwrap();
217 let b = Refinement::<u16, unsigned::ClosedOpenInterval<5, 10>>::refine(9).unwrap();
218 let c: Refinement<u16, unsigned::ClosedOpenInterval<250, 892>> = a * b;
219 assert_eq!(*c, 891);
220 }
221
222 #[test]
223 fn test_open_interval_mul() {
224 let a = Refinement::<u8, unsigned::OpenInterval<15, 30>>::refine(18).unwrap();
225 let b = Refinement::<u8, unsigned::OpenInterval<3, 6>>::refine(5).unwrap();
226 let c: Refinement<u8, unsigned::OpenInterval<63, 146>> = a * b;
227 assert_eq!(*c, 90);
228 }
229
230 #[test]
231 fn test_closed_interval_mul() {
232 let a = Refinement::<u8, unsigned::ClosedInterval<15, 50>>::refine(30).unwrap();
233 let b = Refinement::<u8, unsigned::ClosedInterval<3, 6>>::refine(6).unwrap();
234 let c: Refinement<u8, unsigned::ClosedInterval<45, 300>> = a * b;
235 assert_eq!(*c, 180);
236 }
237}
238
239impl<
240 const MIN: isize,
241 const MAX: isize,
242 Type: signed::SignedBoundable + Mul<Output = Type>,
243 B: SignedMinMax<Type> + Predicate<Type>,
244 > Mul<Refinement<Type, B>> for Refinement<Type, signed::OpenInterval<MIN, MAX>>
245where
246 Refinement<
247 Type,
248 signed::OpenInterval<
249 { min_mul(MIN + 1, MAX - 1, B::UMIN, B::UMAX) - 1 },
250 { max_mul(MIN + 1, MAX - 1, B::UMIN, B::UMAX) + 1 },
251 >,
252 >: Sized,
253{
254 type Output = Refinement<
255 Type,
256 signed::OpenInterval<
257 { min_mul(MIN + 1, MAX - 1, B::UMIN, B::UMAX) - 1 },
258 { max_mul(MIN + 1, MAX - 1, B::UMIN, B::UMAX) + 1 },
259 >,
260 >;
261
262 fn mul(self, rhs: Refinement<Type, B>) -> Self::Output {
263 Refinement(self.0 * rhs.0, PhantomData)
264 }
265}
266
267impl<
268 const MIN: isize,
269 const MAX: isize,
270 Type: signed::SignedBoundable + Mul<Output = Type>,
271 B: SignedMinMax<Type> + Predicate<Type>,
272 > Mul<Refinement<Type, B>> for Refinement<Type, signed::ClosedInterval<MIN, MAX>>
273where
274 Refinement<
275 Type,
276 signed::ClosedInterval<
277 { min_mul(MIN, MAX, B::UMIN, B::UMAX) },
278 { max_mul(MIN, MAX, B::UMIN, B::UMAX) },
279 >,
280 >: Sized,
281{
282 type Output = Refinement<
283 Type,
284 signed::ClosedInterval<
285 { min_mul(MIN, MAX, B::UMIN, B::UMAX) },
286 { max_mul(MIN, MAX, B::UMIN, B::UMAX) },
287 >,
288 >;
289
290 fn mul(self, rhs: Refinement<Type, B>) -> Self::Output {
291 Refinement(self.0 * rhs.0, PhantomData)
292 }
293}
294
295impl<
296 const MIN: isize,
297 const MAX: isize,
298 Type: signed::SignedBoundable + Mul<Output = Type>,
299 B: SignedMinMax<Type> + Predicate<Type>,
300 > Mul<Refinement<Type, B>> for Refinement<Type, signed::OpenClosedInterval<MIN, MAX>>
301where
302 Refinement<
303 Type,
304 signed::OpenClosedInterval<
305 { min_mul(MIN + 1, MAX, B::UMIN, B::UMAX) - 1 },
306 { max_mul(MIN + 1, MAX, B::UMIN, B::UMAX) },
307 >,
308 >: Sized,
309{
310 type Output = Refinement<
311 Type,
312 signed::OpenClosedInterval<
313 { min_mul(MIN + 1, MAX, B::UMIN, B::UMAX) - 1 },
314 { max_mul(MIN + 1, MAX, B::UMIN, B::UMAX) },
315 >,
316 >;
317
318 fn mul(self, rhs: Refinement<Type, B>) -> Self::Output {
319 Refinement(self.0 * rhs.0, PhantomData)
320 }
321}
322
323impl<
324 const MIN: isize,
325 const MAX: isize,
326 Type: signed::SignedBoundable + Mul<Output = Type>,
327 B: SignedMinMax<Type> + Predicate<Type>,
328 > Mul<Refinement<Type, B>> for Refinement<Type, signed::ClosedOpenInterval<MIN, MAX>>
329where
330 Refinement<
331 Type,
332 signed::ClosedOpenInterval<
333 { min_mul(MIN, MAX - 1, B::UMIN, B::UMAX) },
334 { max_mul(MIN, MAX - 1, B::UMIN, B::UMAX) + 1 },
335 >,
336 >: Sized,
337{
338 type Output = Refinement<
339 Type,
340 signed::ClosedOpenInterval<
341 { min_mul(MIN, MAX - 1, B::UMIN, B::UMAX) },
342 { max_mul(MIN, MAX - 1, B::UMIN, B::UMAX) + 1 },
343 >,
344 >;
345
346 fn mul(self, rhs: Refinement<Type, B>) -> Self::Output {
347 Refinement(self.0 * rhs.0, PhantomData)
348 }
349}
350
351#[cfg(test)]
352mod signed_tests {
353 use super::*;
354 use crate::prelude::*;
355
356 #[test]
357 fn test_open_closed_interval_mul() {
358 let a = Refinement::<i8, signed::OpenClosedInterval<15, 20>>::refine(20).unwrap();
359 let b = Refinement::<i8, signed::OpenClosedInterval<-6, -3>>::refine(-5).unwrap();
360 let c: Refinement<i8, signed::OpenClosedInterval<-101, -48>> = a * b;
361 assert_eq!(*c, -100);
362 }
363
364 #[test]
365 fn test_closed_open_interval_mul() {
366 let a = Refinement::<i16, signed::ClosedOpenInterval<-50, 100>>::refine(99).unwrap();
367 let b = Refinement::<i16, signed::ClosedOpenInterval<5, 10>>::refine(9).unwrap();
368 let c: Refinement<i16, signed::ClosedOpenInterval<-450, 892>> = a * b;
369 assert_eq!(*c, 891);
370 }
371
372 #[test]
373 fn test_open_interval_mul() {
374 let a = Refinement::<i8, signed::OpenInterval<15, 30>>::refine(16).unwrap();
375 let b = Refinement::<i8, signed::OpenInterval<-13, -6>>::refine(-7).unwrap();
376 let c: Refinement<i8, signed::OpenInterval<-349, -111>> = a * b;
377 assert_eq!(*c, -112);
378 }
379
380 #[test]
381 fn test_closed_interval_mul() {
382 let a = Refinement::<i16, signed::ClosedInterval<15, 50>>::refine(30).unwrap();
383 let b = Refinement::<i16, signed::ClosedInterval<3, 6>>::refine(6).unwrap();
384 let c: Refinement<i16, signed::ClosedInterval<45, 300>> = a * b;
385 assert_eq!(*c, 180);
386 }
387}