sirius/solver/poly/
coef.rs1use std::cmp::{Ord, PartialOrd};
4use std::fmt;
5use std::ops::Neg;
6
7#[derive(Clone, Copy, PartialOrd, Ord, Hash, PartialEq, Eq)]
10pub struct Coef(i128);
11
12impl Coef {
13 pub fn new<T: Into<i128>>(v: T) -> Self {
14 Self(v.into())
15 }
16
17 pub fn from_size(v: usize) -> Self {
18 Self(v as i128)
19 }
20
21 pub fn get(&self) -> i128 {
22 self.0
23 }
24
25 pub fn vec(arr: &[i128]) -> Vec<Self> {
26 arr.iter().map(|a| Coef::new(*a)).collect()
27 }
28
29 pub fn is_zero(&self) -> bool {
30 self.0 == 0
31 }
32
33 pub fn is_positive(&self) -> bool {
34 self.0 > 0
35 }
36
37 pub fn gcd(&self, other: &Self) -> Self {
38 let (mut a, mut b) = (self.0, other.0);
39 while b != 0 {
40 (a, b) = (b, a % b);
41 }
42 Self(a)
43 }
44
45 pub fn lcm(&self, other: &Self) -> Self {
46 self * other / self.gcd(other)
47 }
48
49 pub fn abs(&self) -> Self {
50 Coef(self.0.checked_abs().unwrap())
51 }
52
53 pub fn divrem(&self, other: Coef) -> (Self, Self) {
54 (
55 Coef(self.0.checked_div(other.0).unwrap()),
56 Coef(self.0.checked_rem(other.0).unwrap()),
57 )
58 }
59
60 fn add_impl(&self, b: &Self) -> Coef {
61 Coef(self.0.checked_add(b.0).unwrap())
62 }
63
64 fn sub_impl(&self, b: &Self) -> Coef {
65 Coef(self.0.checked_sub(b.0).unwrap())
66 }
67
68 fn mul_impl(&self, b: &Self) -> Coef {
69 Coef(self.0.checked_mul(b.0).unwrap())
70 }
71
72 fn div_impl(&self, b: &Self) -> Coef {
73 Coef(self.0.checked_div(b.0).unwrap())
74 }
75}
76
77impl fmt::Debug for Coef {
78 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
79 write!(f, "{}", self.0)
80 }
81}
82
83impl<T: Into<i128>> From<T> for Coef {
84 fn from(val: T) -> Self {
85 Coef::new(val)
86 }
87}
88
89impl Neg for Coef {
90 type Output = Coef;
91
92 fn neg(self) -> Coef {
93 Coef(self.0.checked_neg().unwrap())
94 }
95}
96
97macro_rules! impl_binop {
98 ($T:ident, $Trait:ident, $method:ident, $impl_fn:ident) => {
99 impl std::ops::$Trait<&$T> for &$T {
100 type Output = $T;
101 fn $method(self, rhs: &$T) -> $T {
102 self.$impl_fn(rhs)
103 }
104 }
105 impl std::ops::$Trait<$T> for &$T {
106 type Output = $T;
107 fn $method(self, rhs: $T) -> $T {
108 self.$impl_fn(&rhs)
109 }
110 }
111 impl std::ops::$Trait<&$T> for $T {
112 type Output = $T;
113 fn $method(self, rhs: &$T) -> $T {
114 self.$impl_fn(rhs)
115 }
116 }
117 impl std::ops::$Trait<$T> for $T {
118 type Output = $T;
119 fn $method(self, rhs: $T) -> $T {
120 self.$impl_fn(&rhs)
121 }
122 }
123 };
124}
125
126impl_binop!(Coef, Add, add, add_impl);
127impl_binop!(Coef, Sub, sub, sub_impl);
128impl_binop!(Coef, Mul, mul, mul_impl);
129impl_binop!(Coef, Div, div, div_impl);
130
131#[cfg(test)]
132mod tests {
133 use super::Coef;
134 #[test]
135 fn gcd() {
136 let a = Coef(156);
137 let b = Coef(36);
138 assert_eq!(a.gcd(&b), Coef(12));
139 }
140}