1use crate::groups::{AdditiveAbelianGroup, MultiplicativeMonoid};
6use crate::operations::{ClosedAdd, ClosedMul, Distributive};
7use crate::CommutativeMultiplication;
8use num_traits::Euclid;
9
10pub trait Ring: AdditiveAbelianGroup + MultiplicativeMonoid + Distributive {}
31
32pub trait CommutativeRing: Ring + CommutativeMultiplication {}
43
44pub trait IntegralDomain: CommutativeRing {}
58
59pub trait UniqueFactorizationDomain: IntegralDomain {}
75
76pub trait PrincipalIdealDomain: UniqueFactorizationDomain {}
86
87pub trait Polynomial: Clone + PartialEq + ClosedAdd + ClosedMul + Euclid {
94 type Coefficient: Ring;
96
97 fn degree(&self) -> usize;
99
100 fn coefficient(&self, degree: usize) -> Self::Coefficient;
102}
103
104impl<T: AdditiveAbelianGroup + MultiplicativeMonoid + Distributive> Ring for T {}
106impl<T: Ring + CommutativeMultiplication> CommutativeRing for T {}
107impl<T: CommutativeRing> IntegralDomain for T {}
108impl<T: IntegralDomain> UniqueFactorizationDomain for T {}
109impl<T: UniqueFactorizationDomain> PrincipalIdealDomain for T {}
110
111#[cfg(test)]
112mod tests {
113 use super::*;
114 use crate::operations::{
115 AssociativeAddition, AssociativeMultiplication, CommutativeAddition,
116 CommutativeMultiplication, Distributive,
117 };
118 use num_traits::{One, Zero};
119 use std::ops::{Add, Mul};
120
121 #[derive(Debug, Clone, Copy, PartialEq)]
123 struct TestRing(i32);
124
125 impl Add for TestRing {
126 type Output = Self;
127
128 fn add(self, rhs: Self) -> Self::Output {
129 TestRing(self.0 + rhs.0)
130 }
131 }
132
133 impl std::ops::AddAssign for TestRing {
134 fn add_assign(&mut self, rhs: Self) {
135 self.0 += rhs.0;
136 }
137 }
138
139 impl std::ops::Sub for TestRing {
140 type Output = Self;
141
142 fn sub(self, rhs: Self) -> Self::Output {
143 TestRing(self.0 - rhs.0)
144 }
145 }
146
147 impl std::ops::SubAssign for TestRing {
148 fn sub_assign(&mut self, rhs: Self) {
149 self.0 -= rhs.0;
150 }
151 }
152
153 impl Mul for TestRing {
154 type Output = Self;
155
156 fn mul(self, rhs: Self) -> Self::Output {
157 TestRing(self.0 * rhs.0)
158 }
159 }
160
161 impl std::ops::MulAssign for TestRing {
162 fn mul_assign(&mut self, rhs: Self) {
163 self.0 *= rhs.0;
164 }
165 }
166
167 impl std::ops::Div for TestRing {
168 type Output = Self;
169
170 fn div(self, rhs: Self) -> Self::Output {
171 TestRing(self.0 / rhs.0)
172 }
173 }
174
175 impl std::ops::DivAssign for TestRing {
176 fn div_assign(&mut self, rhs: Self) {
177 self.0 /= rhs.0;
178 }
179 }
180
181 impl std::ops::Rem for TestRing {
182 type Output = Self;
183
184 fn rem(self, rhs: Self) -> Self::Output {
185 TestRing(self.0 % rhs.0)
186 }
187 }
188
189 impl std::ops::RemAssign for TestRing {
190 fn rem_assign(&mut self, rhs: Self) {
191 self.0 %= rhs.0;
192 }
193 }
194
195 impl Zero for TestRing {
196 fn zero() -> Self {
197 TestRing(0)
198 }
199
200 fn is_zero(&self) -> bool {
201 self.0 == 0
202 }
203 }
204
205 impl One for TestRing {
206 fn one() -> Self {
207 TestRing(1)
208 }
209 }
210
211 impl std::ops::Neg for TestRing {
212 type Output = Self;
213
214 fn neg(self) -> Self::Output {
215 TestRing(-self.0)
216 }
217 }
218
219 impl num_traits::Inv for TestRing {
220 type Output = Self;
221
222 fn inv(self) -> Self::Output {
223 if self.0 == 0 {
224 panic!("Cannot invert zero");
225 }
226 if self.0 == 1 || self.0 == -1 {
227 self
228 } else {
229 panic!("Only 1 and -1 have multiplicative inverses in integer ring");
230 }
231 }
232 }
233
234 impl num_traits::Euclid for TestRing {
235 fn div_euclid(&self, v: &Self) -> Self {
236 TestRing(self.0.div_euclid(v.0))
237 }
238
239 fn rem_euclid(&self, v: &Self) -> Self {
240 TestRing(self.0.rem_euclid(v.0))
241 }
242 }
243
244 impl CommutativeAddition for TestRing {}
246 impl AssociativeAddition for TestRing {}
247 impl CommutativeMultiplication for TestRing {}
248 impl AssociativeMultiplication for TestRing {}
249 impl Distributive for TestRing {}
250
251 #[derive(Debug, Clone, PartialEq)]
253 struct SimplePolynomial {
254 coefficients: Vec<i32>, }
256
257 impl SimplePolynomial {
258 fn new(coefficients: Vec<i32>) -> Self {
259 let mut coeffs = coefficients;
261 while coeffs.len() > 1 && *coeffs.last().unwrap() == 0 {
262 coeffs.pop();
263 }
264 Self {
265 coefficients: coeffs,
266 }
267 }
268
269 fn degree(&self) -> usize {
270 if self.coefficients.is_empty()
271 || (self.coefficients.len() == 1 && self.coefficients[0] == 0)
272 {
273 0
274 } else {
275 self.coefficients.len() - 1
276 }
277 }
278
279 fn coefficient(&self, degree: usize) -> i32 {
280 if degree < self.coefficients.len() {
281 self.coefficients[degree]
282 } else {
283 0
284 }
285 }
286 }
287
288 impl Add for SimplePolynomial {
289 type Output = Self;
290
291 fn add(self, rhs: Self) -> Self::Output {
292 let max_len = self.coefficients.len().max(rhs.coefficients.len());
293 let mut result = vec![0; max_len];
294
295 for (i, &coeff) in self.coefficients.iter().enumerate() {
296 result[i] += coeff;
297 }
298
299 for (i, &coeff) in rhs.coefficients.iter().enumerate() {
300 result[i] += coeff;
301 }
302
303 Self::new(result)
304 }
305 }
306
307 impl Mul for SimplePolynomial {
308 type Output = Self;
309
310 fn mul(self, rhs: Self) -> Self::Output {
311 if self.coefficients.is_empty() || rhs.coefficients.is_empty() {
312 return Self::new(vec![0]);
313 }
314
315 let result_degree = self.degree() + rhs.degree();
316 let mut result = vec![0; result_degree + 1];
317
318 for (i, &a) in self.coefficients.iter().enumerate() {
319 for (j, &b) in rhs.coefficients.iter().enumerate() {
320 result[i + j] += a * b;
321 }
322 }
323
324 Self::new(result)
325 }
326 }
327
328 impl Zero for SimplePolynomial {
329 fn zero() -> Self {
330 Self::new(vec![0])
331 }
332
333 fn is_zero(&self) -> bool {
334 self.coefficients.len() == 1 && self.coefficients[0] == 0
335 }
336 }
337
338 impl One for SimplePolynomial {
339 fn one() -> Self {
340 Self::new(vec![1])
341 }
342 }
343
344 impl CommutativeAddition for SimplePolynomial {}
346 impl AssociativeAddition for SimplePolynomial {}
347 impl CommutativeMultiplication for SimplePolynomial {}
348 impl AssociativeMultiplication for SimplePolynomial {}
349 impl Distributive for SimplePolynomial {}
350
351 #[test]
352 fn test_ring_trait() {
353 fn assert_is_ring<T: Ring>(_: &T) {}
355
356 assert_is_ring(&5i32);
357 assert_is_ring(&10i64);
358 assert_is_ring(&TestRing(42));
359 }
360
361 #[test]
362 fn test_commutative_ring_trait() {
363 fn assert_is_commutative_ring<T: CommutativeRing>(_: &T) {}
365
366 assert_is_commutative_ring(&5i32);
367 assert_is_commutative_ring(&10i64);
368 assert_is_commutative_ring(&TestRing(42));
369 }
370
371 #[test]
372 fn test_integral_domain_trait() {
373 fn assert_is_integral_domain<T: IntegralDomain>(_: &T) {}
375
376 assert_is_integral_domain(&5i32);
377 assert_is_integral_domain(&10i64);
378 assert_is_integral_domain(&TestRing(42));
379 }
380
381 #[test]
382 fn test_ufd_trait() {
383 fn assert_is_ufd<T: UniqueFactorizationDomain>(_: &T) {}
385
386 assert_is_ufd(&5i32);
387 assert_is_ufd(&10i64);
388 assert_is_ufd(&TestRing(42));
389 }
390
391 #[test]
392 fn test_pid_trait() {
393 fn assert_is_pid<T: PrincipalIdealDomain>(_: &T) {}
395
396 assert_is_pid(&5i32);
397 assert_is_pid(&10i64);
398 assert_is_pid(&TestRing(42));
399 }
400
401 #[test]
402 fn test_simple_polynomial() {
403 let p1 = SimplePolynomial::new(vec![1, 2, 3]);
406 let p2 = SimplePolynomial::new(vec![4, 5]);
408
409 let sum = p1.clone() + p2.clone();
412 assert_eq!(sum, SimplePolynomial::new(vec![5, 7, 3]));
413
414 let product = p1.clone() * p2.clone();
417 assert_eq!(product, SimplePolynomial::new(vec![4, 13, 22, 15]));
418
419 assert_eq!(p1.degree(), 2);
421 assert_eq!(p2.degree(), 1);
422 assert_eq!(product.degree(), 3);
423
424 assert_eq!(p1.coefficient(0), 1);
426 assert_eq!(p1.coefficient(1), 2);
427 assert_eq!(p1.coefficient(2), 3);
428 assert_eq!(p1.coefficient(3), 0); let zero = SimplePolynomial::zero();
432 assert_eq!(zero, SimplePolynomial::new(vec![0]));
433 assert!(zero.is_zero());
434 assert_eq!(zero.degree(), 0);
435
436 let one = SimplePolynomial::one();
438 assert_eq!(one, SimplePolynomial::new(vec![1]));
439 assert_eq!(one.degree(), 0);
440 }
441
442 #[test]
443 fn test_ring_axioms() {
444 let a = TestRing(5);
449 let b = TestRing(7);
450 let c = TestRing(10);
451 assert_eq!((a + b) + c, a + (b + c));
452
453 assert_eq!(a + b, b + a);
455
456 assert_eq!(a + TestRing::zero(), a);
458
459 assert_eq!(a + (-a), TestRing::zero());
461
462 assert_eq!((a * b) * c, a * (b * c));
465
466 assert_eq!(a * TestRing::one(), a);
468
469 assert_eq!(a * (b + c), (a * b) + (a * c));
472
473 assert_eq!((a + b) * c, (a * c) + (b * c));
475 }
476
477 #[test]
478 fn test_polynomial_ring_structure() {
479 let p = SimplePolynomial::new(vec![1, 2, 3]); let q = SimplePolynomial::new(vec![4, 5]); let r = SimplePolynomial::new(vec![6, 7, 8]); assert_eq!(
488 (p.clone() + q.clone()) + r.clone(),
489 p.clone() + (q.clone() + r.clone())
490 );
491
492 assert_eq!(p.clone() + q.clone(), q.clone() + p.clone());
494
495 let zero = SimplePolynomial::zero();
497 assert_eq!(p.clone() + zero.clone(), p.clone());
498
499 assert_eq!(
501 (p.clone() * q.clone()) * r.clone(),
502 p.clone() * (q.clone() * r.clone())
503 );
504
505 let one = SimplePolynomial::one();
507 assert_eq!(p.clone() * one.clone(), p.clone());
508
509 assert_eq!(
511 p.clone() * (q.clone() + r.clone()),
512 (p.clone() * q.clone()) + (p.clone() * r.clone())
513 );
514 }
515}