competitive/num/
urational.rs1use super::{Bounded, One, Unsigned, Zero};
2use std::{
3 cmp::Ordering,
4 fmt::{self, Debug},
5 ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Sub, SubAssign},
6};
7
8#[derive(Clone, Copy)]
9pub struct URational<T>
10where
11 T: Unsigned,
12{
13 pub num: T,
14 pub den: T,
15}
16
17impl<T> PartialEq for URational<T>
18where
19 T: Unsigned,
20{
21 fn eq(&self, other: &Self) -> bool {
22 self.num == other.num && self.den == other.den
23 }
24}
25
26impl<T> Eq for URational<T> where T: Unsigned {}
27
28impl<T> PartialOrd for URational<T>
29where
30 T: Unsigned,
31{
32 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
33 Some(self.cmp(other))
34 }
35}
36
37impl<T> Ord for URational<T>
38where
39 T: Unsigned,
40{
41 fn cmp(&self, other: &Self) -> Ordering {
42 match (self.den.is_zero(), other.den.is_zero()) {
43 (true, true) => self.num.cmp(&other.num),
44 (true, false) => self.num.cmp(&T::zero()),
45 (false, true) => T::zero().cmp(&other.num),
46 (false, false) => (self.num * other.den).cmp(&(self.den * other.num)),
47 }
48 }
49}
50
51impl<T> Debug for URational<T>
52where
53 T: Unsigned + Debug,
54{
55 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
56 write!(f, "{:?}/{:?}", self.num, self.den)
57 }
58}
59
60impl<T> URational<T>
61where
62 T: Unsigned,
63{
64 pub fn new(num: T, den: T) -> Self {
65 let g = num.gcd(den);
66 Self::new_unchecked(num / g, den / g)
67 }
68 pub fn new_unchecked(num: T, den: T) -> Self {
69 Self { num, den }
70 }
71 pub fn eval(self) -> T {
72 self.num / self.den
73 }
74 pub fn map<U>(self, mut f: impl FnMut(T) -> U) -> URational<U>
75 where
76 U: Unsigned,
77 {
78 URational::new(f(self.num), f(self.den))
79 }
80 pub fn map_unchecked<U>(self, mut f: impl FnMut(T) -> U) -> URational<U>
81 where
82 U: Unsigned,
83 {
84 URational::new_unchecked(f(self.num), f(self.den))
85 }
86 pub fn map_eval<U>(self, mut f: impl FnMut(T) -> U) -> <U as Div>::Output
87 where
88 U: Div,
89 {
90 f(self.num) / f(self.den)
91 }
92}
93
94impl<T> Bounded for URational<T>
95where
96 T: Unsigned,
97{
98 fn maximum() -> Self {
99 Self::new_unchecked(T::one(), T::zero())
100 }
101 fn minimum() -> Self {
102 Self::zero()
103 }
104}
105
106impl<T> Zero for URational<T>
107where
108 T: Unsigned,
109{
110 fn zero() -> Self {
111 Self::new_unchecked(T::zero(), T::one())
112 }
113}
114impl<T> One for URational<T>
115where
116 T: Unsigned,
117{
118 fn one() -> Self {
119 Self::new_unchecked(T::one(), T::one())
120 }
121}
122
123impl<T> Add for URational<T>
124where
125 T: Unsigned,
126{
127 type Output = Self;
128 fn add(self, rhs: Self) -> Self::Output {
129 Self::new(self.num * rhs.den + self.den * rhs.num, self.den * rhs.den)
130 }
131}
132impl<T> Sub for URational<T>
133where
134 T: Unsigned,
135{
136 type Output = Self;
137 fn sub(self, rhs: Self) -> Self::Output {
138 Self::new(self.num * rhs.den - self.den * rhs.num, self.den * rhs.den)
139 }
140}
141impl<T> Mul for URational<T>
142where
143 T: Unsigned,
144{
145 type Output = Self;
146 fn mul(self, rhs: Self) -> Self::Output {
147 Self::new(self.num * rhs.num, self.den * rhs.den)
148 }
149}
150impl<T> Div for URational<T>
151where
152 T: Unsigned,
153{
154 type Output = Self;
155 fn div(self, rhs: Self) -> Self::Output {
156 Self::new(self.num * rhs.den, self.den * rhs.num)
157 }
158}
159impl<T> AddAssign for URational<T>
160where
161 T: Unsigned,
162{
163 fn add_assign(&mut self, rhs: Self) {
164 *self = *self + rhs;
165 }
166}
167impl<T> SubAssign for URational<T>
168where
169 T: Unsigned,
170{
171 fn sub_assign(&mut self, rhs: Self) {
172 *self = *self - rhs;
173 }
174}
175impl<T> MulAssign for URational<T>
176where
177 T: Unsigned,
178{
179 fn mul_assign(&mut self, rhs: Self) {
180 *self = *self * rhs;
181 }
182}
183impl<T> DivAssign for URational<T>
184where
185 T: Unsigned,
186{
187 fn div_assign(&mut self, rhs: Self) {
188 *self = *self / rhs;
189 }
190}