abstalg/
vector_algebra.rs

1// Copyright (C) 2020 Miklos Maroti
2// Licensed under the MIT license (see LICENSE)
3
4use crate::*;
5
6/// The direct power of the given algebra where the elements are fixed sized
7/// vectors. The algebraic operations are always acting coordinate-wise.
8#[derive(Clone, Debug)]
9pub struct VectorAlgebra<A>
10where
11    A: Domain,
12{
13    base: A,
14    len: usize,
15}
16
17#[allow(clippy::len_without_is_empty)]
18impl<A> VectorAlgebra<A>
19where
20    A: Domain,
21{
22    /// Creates a new vector algebra for the given base and length.
23    pub fn new(base: A, len: usize) -> Self {
24        Self { base, len }
25    }
26
27    /// Returns the base algebra from which this vector algebra was created.
28    pub fn base(&self) -> &A {
29        &self.base
30    }
31
32    /// Returns the common length of vectors that are the elements of this
33    /// algebra (the exponent of the power algebra).
34    pub fn len(&self) -> usize {
35        self.len
36    }
37
38    /// Returns the constant vector containing the given element.
39    pub fn diagonal(&self, elem: A::Elem) -> Vec<A::Elem> {
40        vec![elem; self.len]
41    }
42}
43
44impl<A> Domain for VectorAlgebra<A>
45where
46    A: Domain,
47{
48    type Elem = Vec<A::Elem>;
49
50    fn contains(&self, elem: &Self::Elem) -> bool {
51        if elem.len() != self.len {
52            false
53        } else {
54            elem.iter().all(|a| self.base.contains(a))
55        }
56    }
57
58    fn equals(&self, elem1: &Self::Elem, elem2: &Self::Elem) -> bool {
59        assert!(elem1.len() == self.len && elem2.len() == self.len);
60        elem1
61            .iter()
62            .zip(elem2.iter())
63            .all(|(x, y)| self.base.equals(x, y))
64    }
65}
66
67impl<A> Semigroup for VectorAlgebra<A>
68where
69    A: Semigroup,
70{
71    fn mul(&self, elem1: &Self::Elem, elem2: &Self::Elem) -> Self::Elem {
72        assert!(elem1.len() == self.len && elem2.len() == self.len);
73        elem1
74            .iter()
75            .zip(elem2.iter())
76            .map(|(x, y)| self.base.mul(x, y))
77            .collect()
78    }
79
80    fn mul_assign(&self, elem1: &mut Self::Elem, elem2: &Self::Elem) {
81        assert!(elem1.len() == self.len && elem2.len() == self.len);
82        elem1
83            .iter_mut()
84            .zip(elem2.iter())
85            .for_each(|(x, y)| self.base.mul_assign(x, y));
86    }
87
88    fn square(&self, elem: &mut Self::Elem) {
89        assert!(elem.len() == self.len);
90        elem.iter_mut().for_each(|x| self.base.square(x));
91    }
92}
93
94impl<A> Monoid for VectorAlgebra<A>
95where
96    A: Monoid,
97{
98    fn one(&self) -> Self::Elem {
99        self.diagonal(self.base.one())
100    }
101
102    fn is_one(&self, elem: &Self::Elem) -> bool {
103        assert!(elem.len() == self.len);
104        elem.iter().all(|x| self.base.is_one(x))
105    }
106
107    fn try_inv(&self, elem: &Self::Elem) -> Option<Self::Elem> {
108        assert!(elem.len() == self.len);
109        let mut v = Vec::with_capacity(self.len);
110        for x in elem.iter() {
111            if let Some(y) = self.base.try_inv(x) {
112                v.push(y)
113            } else {
114                return None;
115            }
116        }
117        Some(v)
118    }
119
120    fn invertible(&self, elem: &Self::Elem) -> bool {
121        assert!(elem.len() == self.len);
122        elem.iter().all(|x| self.base.invertible(x))
123    }
124}
125
126impl<A> Group for VectorAlgebra<A>
127where
128    A: Group,
129{
130    fn inv(&self, elem: &Self::Elem) -> Self::Elem {
131        assert!(elem.len() == self.len);
132        elem.iter().map(|x| self.base.inv(x)).collect()
133    }
134}
135
136impl<A> CommuntativeMonoid for VectorAlgebra<A>
137where
138    A: CommuntativeMonoid,
139{
140    fn zero(&self) -> Self::Elem {
141        self.diagonal(self.base.zero())
142    }
143
144    fn is_zero(&self, elem: &Self::Elem) -> bool {
145        assert!(elem.len() == self.len);
146        elem.iter().all(|x| self.base.is_zero(x))
147    }
148
149    fn add(&self, elem1: &Self::Elem, elem2: &Self::Elem) -> Self::Elem {
150        assert!(elem1.len() == self.len && elem2.len() == self.len);
151        elem1
152            .iter()
153            .zip(elem2.iter())
154            .map(|(x, y)| self.base.add(x, y))
155            .collect()
156    }
157
158    fn add_assign(&self, elem1: &mut Self::Elem, elem2: &Self::Elem) {
159        assert!(elem1.len() == self.len && elem2.len() == self.len);
160        elem1
161            .iter_mut()
162            .zip(elem2.iter())
163            .for_each(|(x, y)| self.base.add_assign(x, y));
164    }
165
166    fn double(&self, elem: &mut Self::Elem) {
167        assert!(elem.len() == self.len);
168        elem.iter_mut().for_each(|x| self.base.double(x))
169    }
170}
171
172impl<A> AbelianGroup for VectorAlgebra<A>
173where
174    A: AbelianGroup,
175{
176    fn neg(&self, elem: &Self::Elem) -> Self::Elem {
177        assert!(elem.len() == self.len);
178        elem.iter().map(|x| self.base.neg(x)).collect()
179    }
180
181    fn neg_assign(&self, elem: &mut Self::Elem) {
182        assert!(elem.len() == self.len);
183        elem.iter_mut().for_each(|x| self.base.neg_assign(x))
184    }
185
186    fn sub(&self, elem1: &Self::Elem, elem2: &Self::Elem) -> Self::Elem {
187        assert!(elem1.len() == self.len && elem2.len() == self.len);
188        elem1
189            .iter()
190            .zip(elem2.iter())
191            .map(|(x, y)| self.base.sub(x, y))
192            .collect()
193    }
194
195    fn sub_assign(&self, elem1: &mut Self::Elem, elem2: &Self::Elem) {
196        assert!(elem1.len() == self.len && elem2.len() == self.len);
197        elem1
198            .iter_mut()
199            .zip(elem2.iter())
200            .for_each(|(x, y)| self.base.sub_assign(x, y));
201    }
202}
203
204impl<A> SemiRing for VectorAlgebra<A> where A: SemiRing {}
205
206impl<A> UnitaryRing for VectorAlgebra<A>
207where
208    A: UnitaryRing,
209{
210    fn int(&self, elem: isize) -> Self::Elem {
211        self.diagonal(self.base.int(elem))
212    }
213}
214
215impl<A> PartialOrder for VectorAlgebra<A>
216where
217    A: PartialOrder,
218{
219    fn leq(&self, elem1: &Self::Elem, elem2: &Self::Elem) -> bool {
220        assert!(elem1.len() == self.len && elem2.len() == self.len);
221        elem1
222            .iter()
223            .zip(elem2.iter())
224            .all(|(x, y)| self.base.leq(x, y))
225    }
226}
227
228impl<A> BoundedOrder for VectorAlgebra<A>
229where
230    A: BoundedOrder,
231{
232    fn max(&self) -> Self::Elem {
233        self.diagonal(self.base.max())
234    }
235
236    fn min(&self) -> Self::Elem {
237        self.diagonal(self.base.min())
238    }
239}
240
241impl<A> Lattice for VectorAlgebra<A>
242where
243    A: Lattice,
244{
245    fn meet(&self, elem1: &Self::Elem, elem2: &Self::Elem) -> Self::Elem {
246        assert!(elem1.len() == self.len && elem2.len() == self.len);
247        elem1
248            .iter()
249            .zip(elem2.iter())
250            .map(|(x, y)| self.base.meet(x, y))
251            .collect()
252    }
253
254    fn join(&self, elem1: &Self::Elem, elem2: &Self::Elem) -> Self::Elem {
255        assert!(elem1.len() == self.len && elem2.len() == self.len);
256        elem1
257            .iter()
258            .zip(elem2.iter())
259            .map(|(x, y)| self.base.join(x, y))
260            .collect()
261    }
262}
263
264impl<A> DistributiveLattice for VectorAlgebra<A> where A: DistributiveLattice {}
265
266impl<A> BooleanAlgebra for VectorAlgebra<A>
267where
268    A: BooleanAlgebra,
269{
270    fn not(&self, elem: &Self::Elem) -> Self::Elem {
271        assert!(elem.len() == self.len);
272        elem.iter().map(|x| self.base.not(x)).collect()
273    }
274}