competitive/algebra/
magma.rs1pub trait Magma {
5 type T: Clone;
7 fn operate(x: &Self::T, y: &Self::T) -> Self::T;
9 #[inline]
10 fn reverse_operate(x: &Self::T, y: &Self::T) -> Self::T {
11 Self::operate(y, x)
12 }
13 #[inline]
14 fn operate_assign(x: &mut Self::T, y: &Self::T) {
15 *x = Self::operate(x, y);
16 }
17}
18
19pub trait Associative {}
21
22pub trait SemiGroup: Magma + Associative {}
24
25impl<S> SemiGroup for S where S: Magma + Associative {}
26
27pub trait Unital: Magma {
29 fn unit() -> Self::T;
31 #[inline]
32 fn is_unit(x: &Self::T) -> bool
33 where
34 <Self as Magma>::T: PartialEq,
35 {
36 x == &Self::unit()
37 }
38 #[inline]
39 fn set_unit(x: &mut Self::T) {
40 *x = Self::unit();
41 }
42}
43
44pub trait ExpBits {
45 type Iter: Iterator<Item = bool>;
46 fn bits(self) -> Self::Iter;
47}
48
49pub trait SignedExpBits {
50 type T: ExpBits;
51
52 fn neg_and_bits(self) -> (bool, Self::T);
53}
54
55pub struct Bits<T> {
56 n: T,
57}
58
59macro_rules! impl_exp_bits_for_uint {
60 ($($t:ty)*) => {
61 $(
62 impl Iterator for Bits<$t> {
63 type Item = bool;
64 fn next(&mut self) -> Option<bool> {
65 if self.n == 0 {
66 None
67 } else {
68 let bit = (self.n & 1) == 1;
69 self.n >>= 1;
70 Some(bit)
71 }
72 }
73 }
74 impl ExpBits for $t {
75 type Iter = Bits<$t>;
76 fn bits(self) -> Self::Iter {
77 Bits { n: self }
78 }
79 }
80 impl SignedExpBits for $t {
81 type T = $t;
82 fn neg_and_bits(self) -> (bool, Self::T) {
83 (false, self)
84 }
85 }
86 )*
87 };
88}
89impl_exp_bits_for_uint!(u8 u16 u32 u64 u128 usize);
90
91macro_rules! impl_signed_exp_bits_for_sint {
92 ($($s:ty, $u:ty;)*) => {
93 $(
94 impl SignedExpBits for $s {
95 type T = $u;
96 fn neg_and_bits(self) -> (bool, Self::T) {
97 (self < 0, self.unsigned_abs())
98 }
99 }
100 )*
101 };
102}
103impl_signed_exp_bits_for_sint!(i8, u8; i16, u16; i32, u32; i64, u64; i128, u128; isize, usize;);
104
105pub trait Monoid: SemiGroup + Unital {
107 fn pow<E>(mut x: Self::T, exp: E) -> Self::T
109 where
110 E: ExpBits,
111 {
112 let mut res = Self::unit();
113 for bit in exp.bits() {
114 if bit {
115 res = Self::operate(&res, &x);
116 }
117 x = Self::operate(&x, &x);
118 }
119 res
120 }
121
122 fn fold<I>(iter: I) -> Self::T
123 where
124 I: IntoIterator<Item = Self::T>,
125 {
126 let mut iter = iter.into_iter();
127 if let Some(item) = iter.next() {
128 iter.fold(item, |acc, x| Self::operate(&acc, &x))
129 } else {
130 Self::unit()
131 }
132 }
133}
134
135impl<M> Monoid for M where M: SemiGroup + Unital {}
136
137pub trait Invertible: Magma {
139 fn inverse(x: &Self::T) -> Self::T;
141 #[inline]
142 fn rinv_operate(x: &Self::T, y: &Self::T) -> Self::T {
143 Self::operate(x, &Self::inverse(y))
144 }
145 #[inline]
146 fn rinv_operate_assign(x: &mut Self::T, y: &Self::T) {
147 *x = Self::rinv_operate(x, y);
148 }
149}
150
151pub trait Group: Monoid + Invertible {
153 fn signed_pow<E>(x: Self::T, exp: E) -> Self::T
154 where
155 E: SignedExpBits,
156 {
157 let (neg, exp) = E::neg_and_bits(exp);
158 let res = Self::pow(x, exp);
159 if neg { Self::inverse(&res) } else { res }
160 }
161}
162
163impl<G> Group for G where G: Monoid + Invertible {}
164
165pub trait Commutative {}
167
168pub trait AbelianMonoid: Monoid + Commutative {}
170
171impl<M> AbelianMonoid for M where M: Monoid + Commutative {}
172
173pub trait AbelianGroup: Group + Commutative {}
175
176impl<G> AbelianGroup for G where G: Group + Commutative {}
177
178pub trait Idempotent {}
180
181pub trait IdempotentMonoid: Monoid + Idempotent {}
183
184impl<M> IdempotentMonoid for M where M: Monoid + Idempotent {}
185
186#[macro_export]
187macro_rules! monoid_fold {
188 ($m:ty) => { <$m as Unital>::unit() };
189 ($m:ty,) => { <$m as Unital>::unit() };
190 ($m:ty, $f:expr) => { $f };
191 ($m:ty, $f:expr, $($ff:expr),*) => { <$m as Magma>::operate(&($f), &monoid_fold!($m, $($ff),*)) };
192}
193
194#[macro_export]
195macro_rules! define_monoid {
196 ($Name:ident, $t:ty, |$x:ident, $y:ident| $op:expr, $unit:expr) => {
197 struct $Name;
198 impl Magma for $Name {
199 type T = $t;
200 fn operate($x: &Self::T, $y: &Self::T) -> Self::T {
201 $op
202 }
203 }
204 impl Unital for $Name {
205 fn unit() -> Self::T {
206 $unit
207 }
208 }
209 impl Associative for $Name {}
210 };
211}
212
213#[cfg(test)]
214mod tests {
215 use super::*;
216 use crate::{
217 algebra::operations::{AdditiveOperation, MaxOperation},
218 monoid_fold,
219 };
220
221 #[test]
222 fn test_monoid_pow() {
223 assert_eq!(AdditiveOperation::pow(2, 0u32), 0);
224 assert_eq!(AdditiveOperation::pow(2, 1u32), 2);
225 assert_eq!(AdditiveOperation::pow(2, 3u32), 6);
226 assert_eq!(AdditiveOperation::pow(2, 4usize), 8);
227 }
228
229 #[test]
230 #[allow(clippy::eq_op)]
231 fn test_monoid_fold() {
232 assert_eq!(monoid_fold!(MaxOperation<u32>,), 0);
233 assert_eq!(monoid_fold!(MaxOperation<u32>, 1), 1);
234 assert_eq!(monoid_fold!(MaxOperation<u32>, 1, 2), 2);
235 assert_eq!(monoid_fold!(MaxOperation<u32>, 0, 1, 5, 2), 5);
236 }
237}