1use crate::Wheel;
4
5use core::ops::{Add, Sub, Mul, Div, Neg, Rem};
6use core::fmt::Debug;
7
8pub trait Ring: Add<Output=Self> + Mul<Output=Self> + Neg<Output=Self> + Copy + Clone + PartialEq + Eq + PartialOrd + Debug {
9 const ZERO: Self;
10 const ONE: Self;
11
12 fn compare_pairs(a: (Self, Self), b: (Self, Self)) -> bool {
13 let a0_is_zero = a.0 == Self::ZERO;
14 let b0_is_zero = b.0 == Self::ZERO;
15 let a1_is_zero = a.1 == Self::ZERO;
16 let b1_is_zero = b.1 == Self::ZERO;
17 match (a0_is_zero, b0_is_zero, a1_is_zero, b1_is_zero) {
18 (true, true, false, false) => true,
19 (false, false, true, true) => true,
20 (true, true, true, true) => true,
21 (false, false, false, false) => a.0 * b.1 == a.1 * b.0,
22 _ => false,
23 }
24 }
25
26 fn normalize_pair(pair: (Self, Self)) -> (Self, Self) {
27 let first_is_zero = pair.0 == Self::ZERO;
28 let second_is_zero = pair.1 == Self::ZERO;
29 match (first_is_zero, second_is_zero) {
30 (true, true) => (Self::ZERO, Self::ZERO),
31 (true, false) => (Self::ZERO, Self::ONE),
32 (false, true) => (Self::ONE, Self::ZERO),
33 (false, false) => {
34 (pair.0, pair.1)
35 }
36 }
37 }
38}
39
40trait Gcd: Ring + Rem<Output=Self> + Ord {
41 fn abs(&self) -> Self {
42 if *self < Self::ZERO {
43 -*self
44 } else {
45 *self
46 }
47 }
48
49 fn gcd(a: Self, b: Self) -> Self {
50 let mut a = a.abs();
51 let mut b = b.abs();
52 while b != Self::ZERO {
53 let t = b;
54 b = a % b;
55 a = t;
56 }
57 if a == Self::ZERO {
58 Self::ONE
59 } else {
60 a
61 }
62 }
63}
64
65impl Gcd for i8 {}
66impl Gcd for i16 {}
67impl Gcd for i32 {}
68impl Gcd for i64 {}
69impl Gcd for i128 {}
70
71impl Ring for i8 {
72 const ZERO: i8 = 0;
73 const ONE: i8 = 1;
74
75 fn normalize_pair((a, b): (Self, Self)) -> (Self, Self) {
76 let gcd = Self::gcd(a, b);
77 (a / gcd, b / gcd)
78 }
79}
80
81impl Ring for i16 {
82 const ZERO: i16 = 0;
83 const ONE: i16 = 1;
84
85 fn normalize_pair((a, b): (Self, Self)) -> (Self, Self) {
86 let gcd = Self::gcd(a, b);
87 (a / gcd, b / gcd)
88 }
89}
90
91impl Ring for i32 {
92 const ZERO: i32 = 0;
93 const ONE: i32 = 1;
94
95 fn normalize_pair((a, b): (Self, Self)) -> (Self, Self) {
96 let gcd = Self::gcd(a, b);
97 (a / gcd, b / gcd)
98 }
99}
100
101impl Ring for i64 {
102 const ZERO: i64 = 0;
103 const ONE: i64 = 1;
104
105 fn normalize_pair((a, b): (Self, Self)) -> (Self, Self) {
106 let gcd = Self::gcd(a, b);
107 (a / gcd, b / gcd)
108 }
109}
110
111impl Ring for i128 {
112 const ZERO: i128 = 0;
113 const ONE: i128 = 1;
114
115 fn normalize_pair((a, b): (Self, Self)) -> (Self, Self) {
116 let gcd = Self::gcd(a, b);
117 (a / gcd, b / gcd)
118 }
119}
120
121#[derive(Debug, Clone, Copy)]
122pub struct FractionWheel<T: Ring> (T, T);
123
124impl<T: Ring> FractionWheel<T> {
125 pub const ZERO: Self = FractionWheel(T::ZERO, T::ONE);
126 pub const ONE: Self = FractionWheel(T::ONE, T::ONE);
127
128 pub const INFINITY: Self = FractionWheel(T::ONE, T::ZERO);
130
131 pub const BOTTOM: Self = FractionWheel(T::ZERO, T::ZERO);
133
134 pub fn new(numerator: T, denominator: T) -> Self {
135 let value = FractionWheel(numerator, denominator);
136 value.normalize()
137 }
138
139 fn normalize(&self) -> Self {
140 let (numerator, denominator) = T::normalize_pair((self.0, self.1));
141 if denominator < T::ZERO {
142 FractionWheel(-numerator, -denominator)
143 } else if denominator == T::ZERO && numerator < T::ZERO {
144 FractionWheel(T::ONE, T::ZERO)
145 } else {
146 FractionWheel(numerator, denominator)
147 }
148 }
149
150 fn add(&self, other: Self) -> Self {
151 let a = self.0 * other.1;
152 let b = self.1 * other.0;
153 let c = self.1 * other.1;
154 FractionWheel(a + b, c).normalize()
155 }
156
157 fn neg(&self) -> Self {
158 FractionWheel(-self.0, self.1).normalize()
159 }
160
161 fn sub(&self, other: Self) -> Self {
164 self.add(other.neg())
165 }
166
167 fn mul(&self, other: Self) -> Self {
169 let a = self.0 * other.0;
170 let b = self.1 * other.1;
171 FractionWheel(a, b).normalize()
172 }
173
174 pub fn inv(&self) -> Self {
176 FractionWheel(self.1, self.0).normalize()
177 }
178
179 fn div(&self, other: Self) -> Self {
182 self.mul(other.inv())
183 }
184
185 fn eq(&self, other: Self) -> bool {
186 T::compare_pairs((self.0, self.1), (other.0, other.1))
187 }
188}
189
190impl<T: Ring> Wheel for FractionWheel<T> {
191 const ZERO: Self = FractionWheel::ZERO;
192 const ONE: Self = FractionWheel::ONE;
193 const INFINITY: Self = FractionWheel::INFINITY;
194 const BOTTOM: Self = FractionWheel::BOTTOM;
195
196 fn add(&self, other: &Self) -> Self {
197 FractionWheel::add(self, *other)
198 }
199
200 fn neg(&self) -> Self {
201 FractionWheel::neg(self)
202 }
203
204 fn mul(&self, other: &Self) -> Self {
205 FractionWheel::mul(self, *other)
206 }
207
208 fn inv(&self) -> Self {
209 FractionWheel::inv(self)
210 }
211}
212
213
214impl From<i8> for FractionWheel<i8> {
217 fn from(value: i8) -> Self {
218 FractionWheel(value, 1)
219 }
220}
221
222impl From<i16> for FractionWheel<i16> {
223 fn from(value: i16) -> Self {
224 FractionWheel(value, 1)
225 }
226}
227
228impl From<i32> for FractionWheel<i32> {
229 fn from(value: i32) -> Self {
230 FractionWheel(value, 1)
231 }
232}
233
234impl From<i64> for FractionWheel<i64> {
235 fn from(value: i64) -> Self {
236 FractionWheel(value, 1)
237 }
238}
239
240impl From<i128> for FractionWheel<i128> {
241 fn from(value: i128) -> Self {
242 FractionWheel(value, 1)
243 }
244}
245
246
247impl<T: Ring> Add for FractionWheel<T> {
252 type Output = Self;
253
254 fn add(self, other: Self) -> Self {
255 Self::add(&self, other)
256 }
257}
258
259impl<T: Ring> Add<&FractionWheel<T>> for FractionWheel<T> {
260 type Output = FractionWheel<T>;
261
262 fn add(self, other: &Self) -> Self {
263 Self::add(&self, *other)
264 }
265}
266
267impl<T: Ring> Add<FractionWheel<T>> for &FractionWheel<T> {
268 type Output = FractionWheel<T>;
269
270 fn add(self, other: FractionWheel<T>) -> FractionWheel<T> {
271 FractionWheel::add(self, other)
272 }
273}
274
275impl<T: Ring> Add<&FractionWheel<T>> for &FractionWheel<T> {
276 type Output = FractionWheel<T>;
277
278 fn add(self, other: &FractionWheel<T>) -> FractionWheel<T> {
279 FractionWheel::add(self, *other)
280 }
281}
282
283impl<T: Ring> Sub for FractionWheel<T> {
286 type Output = Self;
287
288 fn sub(self, other: Self) -> Self {
289 Self::sub(&self, other)
290 }
291}
292
293impl<T: Ring> Sub<&FractionWheel<T>> for FractionWheel<T> {
294 type Output = FractionWheel<T>;
295
296 fn sub(self, other: &Self) -> Self {
297 Self::sub(&self, *other)
298 }
299}
300
301impl<T: Ring> Sub<FractionWheel<T>> for &FractionWheel<T> {
302 type Output = FractionWheel<T>;
303
304 fn sub(self, other: FractionWheel<T>) -> FractionWheel<T> {
305 FractionWheel::sub(self, other)
306 }
307}
308
309impl<T: Ring> Sub<&FractionWheel<T>> for &FractionWheel<T> {
310 type Output = FractionWheel<T>;
311
312 fn sub(self, other: &FractionWheel<T>) -> FractionWheel<T> {
313 FractionWheel::sub(self, *other)
314 }
315}
316
317impl<T: Ring> Mul for FractionWheel<T> {
320 type Output = Self;
321
322 fn mul(self, other: Self) -> Self {
323 Self::mul(&self, other)
324 }
325}
326
327impl<T: Ring> Mul<&FractionWheel<T>> for FractionWheel<T> {
328 type Output = FractionWheel<T>;
329
330 fn mul(self, other: &Self) -> Self {
331 Self::mul(&self, *other)
332 }
333}
334
335impl<T: Ring> Mul<FractionWheel<T>> for &FractionWheel<T> {
336 type Output = FractionWheel<T>;
337
338 fn mul(self, other: FractionWheel<T>) -> FractionWheel<T> {
339 FractionWheel::mul(self, other)
340 }
341}
342
343impl<T: Ring> Mul<&FractionWheel<T>> for &FractionWheel<T> {
344 type Output = FractionWheel<T>;
345
346 fn mul(self, other: &FractionWheel<T>) -> FractionWheel<T> {
347 FractionWheel::mul(self, *other)
348 }
349}
350
351impl<T: Ring> Div for FractionWheel<T> {
354 type Output = Self;
355
356 fn div(self, other: Self) -> Self {
357 Self::div(&self, other)
358 }
359}
360
361impl<T: Ring> Div<&FractionWheel<T>> for FractionWheel<T> {
362 type Output = FractionWheel<T>;
363
364 fn div(self, other: &Self) -> Self {
365 Self::div(&self, *other)
366 }
367}
368
369impl<T: Ring> Div<FractionWheel<T>> for &FractionWheel<T> {
370 type Output = FractionWheel<T>;
371
372 fn div(self, other: FractionWheel<T>) -> FractionWheel<T> {
373 FractionWheel::div(self, other)
374 }
375}
376
377impl<T: Ring> Div<&FractionWheel<T>> for &FractionWheel<T> {
378 type Output = FractionWheel<T>;
379
380 fn div(self, other: &FractionWheel<T>) -> FractionWheel<T> {
381 FractionWheel::div(self, *other)
382 }
383}
384
385impl<T: Ring> Neg for FractionWheel<T> {
388 type Output = Self;
389
390 fn neg(self) -> Self {
391 Self::neg(&self)
392 }
393}
394
395impl<T: Ring> Neg for &FractionWheel<T> {
396 type Output = FractionWheel<T>;
397
398 fn neg(self) -> FractionWheel<T> {
399 FractionWheel::neg(self)
400 }
401}
402
403
404impl<T: Ring> PartialEq for FractionWheel<T> {
407 fn eq(&self, other: &Self) -> bool {
408 self.eq(*other)
409 }
410}
411
412impl<T: Ring> Eq for FractionWheel<T> {}
413
414pub type FractionWheel8 = FractionWheel<i8>;
415pub type FractionWheel16 = FractionWheel<i16>;
416pub type FractionWheel32 = FractionWheel<i32>;
417pub type FractionWheel64 = FractionWheel<i64>;
418pub type FractionWheel128 = FractionWheel<i128>;
419
420pub use FractionWheel8 as qw8;
421pub use FractionWheel16 as qw16;
422pub use FractionWheel32 as qw32;
423pub use FractionWheel64 as qw64;
424pub use FractionWheel128 as qw128;
425
426
427#[cfg(test)]
428mod test {
429 use super::*;
430 type MyWheel = FractionWheel<i32>;
431
432 const ZERO: MyWheel = MyWheel::ZERO;
433 const ONE: MyWheel = MyWheel::ONE;
434 const INFINITY: MyWheel = MyWheel::INFINITY;
435 const BOTTOM: MyWheel = MyWheel::BOTTOM;
436
437 #[inline]
438 fn negative_one() -> MyWheel {
439 -ONE
440 }
441
442 #[inline]
443 fn three() -> MyWheel {
444 ONE + ONE + ONE
445 }
446
447 #[inline]
448 fn negative_two() -> MyWheel {
449 -ONE - ONE
450 }
451
452 #[inline]
453 fn three_halves() -> MyWheel {
454 MyWheel::new(3, 2)
455 }
456
457 #[inline]
458 fn negative_two_fifths() -> MyWheel {
459 MyWheel::new(-2, 5)
460 }
461
462 #[inline]
463 fn any_numbers() -> [MyWheel; 9] {
464 [
465 ZERO, ONE, INFINITY, BOTTOM,
466 negative_one(), three(), negative_two(),
467 three_halves(), negative_two_fifths()
468 ]
469 }
470
471 #[test]
472 fn inv_is_involution() {
473 for &x in any_numbers().iter() {
474 println!("{:?} == {:?}", x.inv().inv(), x);
475 assert_eq!(x.inv().inv(), x);
476 }
477 }
478
479 #[test]
480 fn inv_is_multicative() {
481 for &x in any_numbers().iter() {
482 for &y in any_numbers().iter() {
483 println!("{:?} == {:?}", (x * y).inv(), y.inv() * x.inv());
484 assert_eq!((x * y).inv(), y.inv() * x.inv());
485 }
486 }
487 }
488
489 #[test]
491 fn add_is_distributive() {
492 for &x in any_numbers().iter() {
493 for &y in any_numbers().iter() {
494 for &z in any_numbers().iter() {
495 println!("{:?} == {:?}", (x + y) * z + ZERO * z, x * z + y * z);
496 assert_eq!((x + y) * z + ZERO * z, x * z + y * z);
497 }
498 }
499 }
500 }
501
502 #[test]
504 fn add_is_distributive_div() {
505 for &x in any_numbers().iter() {
506 for &y in any_numbers().iter() {
507 for &z in any_numbers().iter() {
508 println!("{:?} == {:?}", (x + y * z) / y, x / y + z + ZERO * y);
509 assert_eq!((x + y * z) / y, x / y + z + ZERO * y);
510 }
511 }
512 }
513 }
514
515 #[test]
517 fn zero_times_zero() {
518 assert_eq!(ZERO * ZERO, ZERO);
519 }
520
521 #[test]
523 fn zero_times_y() {
524 for &x in any_numbers().iter() {
525 for &y in any_numbers().iter() {
526 for &z in any_numbers().iter() {
527 println!("{:?} == {:?}", (x + ZERO * y) * z, x * z + ZERO * y);
528 assert_eq!((x + ZERO * y) * z, x * z + ZERO * y);
529 }
530 }
531 }
532 }
533
534 #[test]
536 fn zero_times_y_inv() {
537 for &x in any_numbers().iter() {
538 for &y in any_numbers().iter() {
539 println!("{:?} == {:?}", (x + ZERO * y).inv(), x.inv() + ZERO * y);
540 assert_eq!((x + ZERO * y).inv(), x.inv() + ZERO * y);
541 }
542 }
543 }
544
545 #[test]
547 fn bottom_addition() {
548 for &x in any_numbers().iter() {
549 println!("{:?} == {:?}", BOTTOM + x, BOTTOM);
550 assert_eq!(BOTTOM + x, BOTTOM);
551 }
552 }
553
554 #[test]
556 fn zero_times_x_plus_zero_times_y() {
557 for &x in any_numbers().iter() {
558 for &y in any_numbers().iter() {
559 println!("{:?} == {:?}", ZERO * x + ZERO * y, ZERO * x * y);
560 assert_eq!(ZERO * x + ZERO * y, ZERO * x * y);
561 }
562 }
563 }
564
565 #[test]
567 fn x_div_x() {
568 for &x in any_numbers().iter() {
569 println!("{:?} == {:?}", x / x, ONE + ZERO * x / x);
570 assert_eq!(x / x, ONE + ZERO * x / x);
571 }
572 }
573
574 #[test]
576 fn x_minus_x() {
577 for &x in any_numbers().iter() {
578 println!("{:?} == {:?}", x - x, ZERO * x * x);
579 assert_eq!(x - x, ZERO * x * x);
580 }
581 }
582}