competitive/algebra/
ring.rs1use super::*;
2use std::{
3 marker::PhantomData,
4 num::Wrapping,
5 ops::{Add, Mul},
6};
7
8pub trait SemiRing {
9 type T: Clone;
10 type Additive: AbelianMonoid<T = Self::T>;
11 type Multiplicative: Monoid<T = Self::T>;
12 fn zero() -> Self::T {
14 <Self::Additive as Unital>::unit()
15 }
16 fn is_zero(x: &Self::T) -> bool
17 where
18 Self::T: PartialEq,
19 {
20 *x == Self::zero()
21 }
22 fn one() -> Self::T {
24 <Self::Multiplicative as Unital>::unit()
25 }
26 fn is_one(x: &Self::T) -> bool
27 where
28 Self::T: PartialEq,
29 {
30 *x == Self::one()
31 }
32 fn add(x: &Self::T, y: &Self::T) -> Self::T {
34 <Self::Additive as Magma>::operate(x, y)
35 }
36 fn mul(x: &Self::T, y: &Self::T) -> Self::T {
38 <Self::Multiplicative as Magma>::operate(x, y)
39 }
40
41 fn try_matrix_product(_a: &[Vec<Self::T>], _b: &[Vec<Self::T>]) -> Option<Vec<Vec<Self::T>>> {
42 None
43 }
44
45 fn dot_product(x: &[Self::T], y: &[Self::T]) -> Self::T {
46 assert_eq!(x.len(), y.len());
47 x.iter().zip(y).fold(Self::zero(), |mut sum, (x, y)| {
48 Self::add_assign(&mut sum, &Self::mul(x, y));
49 sum
50 })
51 }
52
53 fn add_scaled_assign(x: &mut [Self::T], y: &[Self::T], a: &Self::T) {
54 assert_eq!(x.len(), y.len());
55 for (x, y) in x.iter_mut().zip(y) {
56 Self::add_assign(x, &Self::mul(a, y));
57 }
58 }
59
60 fn add_assign(x: &mut Self::T, y: &Self::T) {
61 <Self::Additive as Magma>::operate_assign(x, y);
62 }
63
64 fn mul_assign(x: &mut Self::T, y: &Self::T) {
65 <Self::Multiplicative as Magma>::operate_assign(x, y);
66 }
67}
68
69pub trait Ring: SemiRing<Additive: Invertible> {
70 fn neg(x: &Self::T) -> Self::T {
72 <Self::Additive as Invertible>::inverse(x)
73 }
74 fn sub(x: &Self::T, y: &Self::T) -> Self::T {
76 <Self::Additive as Invertible>::rinv_operate(x, y)
77 }
78
79 fn sub_assign(x: &mut Self::T, y: &Self::T) {
80 <Self::Additive as Invertible>::rinv_operate_assign(x, y);
81 }
82}
83
84impl<R> Ring for R where R: SemiRing<Additive: Invertible> {}
85
86pub trait Field: Ring<Multiplicative: Invertible> {
87 fn inv(x: &Self::T) -> Self::T {
89 <Self::Multiplicative as Invertible>::inverse(x)
90 }
91 fn div(x: &Self::T, y: &Self::T) -> Self::T {
93 <Self::Multiplicative as Invertible>::rinv_operate(x, y)
94 }
95
96 fn div_assign(x: &mut Self::T, y: &Self::T) {
97 <Self::Multiplicative as Invertible>::rinv_operate_assign(x, y);
98 }
99}
100
101impl<F> Field for F where F: Ring<Multiplicative: Invertible> {}
102
103pub trait DotProduct: Sized + Clone + Zero + Add<Output = Self> + Mul<Output = Self> {
104 fn try_matrix_product(_a: &[Vec<Self>], _b: &[Vec<Self>]) -> Option<Vec<Vec<Self>>> {
105 None
106 }
107
108 fn add_scaled_assign(x: &mut [Self], y: &[Self], a: &Self) {
109 assert_eq!(x.len(), y.len());
110 for (x, y) in x.iter_mut().zip(y) {
111 *x = x.clone() + a.clone() * y.clone();
112 }
113 }
114
115 fn dot_product(x: &[Self], y: &[Self]) -> Self {
116 assert_eq!(x.len(), y.len());
117 x.iter()
118 .zip(y)
119 .fold(Self::zero(), |sum, (x, y)| sum + x.clone() * y.clone())
120 }
121}
122
123macro_rules! impl_dot_product {
124 ($($t:ty)*) => {
125 $(impl DotProduct for $t {})*
126 };
127}
128impl_dot_product!(u8 u16 u32 u64 usize u128 i8 i16 i32 i64 isize i128 f32 f64);
129
130impl<T> DotProduct for Wrapping<T> where
131 Wrapping<T>: Clone + Zero + Add<Output = Wrapping<T>> + Mul<Output = Wrapping<T>>
132{
133}
134
135pub struct AddMulOperation<T>
137where
138 T: DotProduct + One,
139{
140 _marker: PhantomData<fn() -> T>,
141}
142impl<T> SemiRing for AddMulOperation<T>
143where
144 T: DotProduct + One,
145{
146 type T = T;
147 type Additive = AdditiveOperation<T>;
148 type Multiplicative = MultiplicativeOperation<T>;
149
150 #[inline]
151 fn try_matrix_product(a: &[Vec<T>], b: &[Vec<T>]) -> Option<Vec<Vec<T>>> {
152 T::try_matrix_product(a, b)
153 }
154
155 #[inline]
156 fn dot_product(x: &[Self::T], y: &[Self::T]) -> Self::T {
157 T::dot_product(x, y)
158 }
159
160 #[inline]
161 fn add_scaled_assign(x: &mut [Self::T], y: &[Self::T], a: &Self::T) {
162 T::add_scaled_assign(x, y, a);
163 }
164}