feanor_math/
wrapper.rs

1use std::{ops::*, hash::Hash, fmt::{Display, Debug}};
2
3use crate::homomorphism::*;
4use crate::ring::*;
5use crate::field::*;
6
7///
8/// Stores a ring element together with its ring, so that ring operations do
9/// not require explicit mention of the ring object. This can be used both for
10/// convenience of notation (i.e. use `a + b` instead of `ring.add(a, b)`) and
11/// might also be necessary when e.g. storing elements in a set.
12/// 
13/// # Examples
14/// ```
15/// # use feanor_math::ring::*;
16/// # use feanor_math::rings::poly::*;
17/// # use feanor_math::rings::poly::dense_poly::*;
18/// # use feanor_math::wrapper::*;
19/// # use feanor_math::primitive_int::*;
20/// let ring = DensePolyRing::new(StaticRing::<i64>::RING, "X");
21/// let x = RingElementWrapper::new(&ring, ring.indeterminate());
22/// println!("The result is: {}", x.clone() + x.clone() * x);
23/// // instead of
24/// let x = ring.indeterminate();
25/// println!("The result is: {}", ring.format(&ring.add(ring.mul(ring.clone_el(&x), ring.clone_el(&x)), ring.clone_el(&x))));
26/// ```
27/// You can also retrieve the wrapped element
28/// ```
29/// # use feanor_math::assert_el_eq;
30/// # use feanor_math::ring::*;
31/// # use feanor_math::rings::poly::*;
32/// # use feanor_math::rings::poly::dense_poly::*;
33/// # use feanor_math::wrapper::*;
34/// # use feanor_math::primitive_int::*;
35/// let ring = DensePolyRing::new(StaticRing::<i64>::RING, "X");
36/// let x = RingElementWrapper::new(&ring, ring.indeterminate());
37/// assert_el_eq!(&ring, ring.add(ring.mul(ring.clone_el(&x), ring.clone_el(&x)), ring.clone_el(&x)), (x.clone() + x.clone() * x).unwrap());
38/// ```
39/// 
40pub struct RingElementWrapper<R>
41    where R: RingStore
42{
43    ring: R,
44    element: El<R>
45}
46
47impl<R: RingStore> RingElementWrapper<R> {
48
49    ///
50    /// Creates a new [`RingElementWrapper`] wrapping the given element of the given ring.
51    /// 
52    pub const fn new(ring: R, element: El<R>) -> Self {
53        Self { ring, element }
54    }
55
56    ///
57    /// Raises the stored element to the given power.
58    /// 
59    /// Consider using [`RingElementWrapper::pow_ref()`] if you don't want to 
60    /// move the element.
61    /// 
62    pub fn pow(self, power: usize) -> Self {
63        Self {
64            element: self.ring.pow(self.element, power),
65            ring: self.ring
66        }
67    }
68
69    ///
70    /// Raises the stored element to the given power.
71    /// 
72    pub fn pow_ref(&self, power: usize) -> Self
73        where R: Clone
74    {
75        Self {
76            element: self.ring.pow(self.ring.clone_el(&self.element), power),
77            ring: self.ring.clone()
78        }
79    }
80
81    ///
82    /// Returns the stored element.
83    /// 
84    pub fn unwrap(self) -> El<R> {
85        self.element
86    }
87
88    ///
89    /// Returns the stored element as reference.
90    /// 
91    pub fn unwrap_ref(&self) -> &El<R> {
92        &self.element
93    }
94
95    ///
96    /// Returns a reference to the ring that this element belongs to.
97    /// 
98    pub fn parent(&self) -> &R {
99        &self.ring
100    }
101}
102
103macro_rules! impl_xassign_trait {
104    ($trait_name:ident, $fn_name:ident, $fn_ref_name:ident) => {
105        
106        impl<R: RingStore> $trait_name for RingElementWrapper<R> {
107
108            fn $fn_name(&mut self, rhs: Self) {
109                debug_assert!(self.ring.get_ring() == rhs.ring.get_ring());
110                self.ring.$fn_name(&mut self.element, rhs.element);
111            }
112        }
113
114        impl<'a, R: RingStore> $trait_name<&'a Self> for RingElementWrapper<R> {
115
116            fn $fn_name(&mut self, rhs: &'a Self) {
117                debug_assert!(self.ring.get_ring() == rhs.ring.get_ring());
118                self.ring.$fn_ref_name(&mut self.element, &rhs.element);
119            }
120        }
121    };
122}
123
124macro_rules! impl_trait {
125    ($trait_name:ident, $fn_name:ident, $fn_name_ref_fst:ident, $fn_name_ref_snd:ident, $fn_name_ref:ident) => {
126        
127        impl<R: RingStore> $trait_name for RingElementWrapper<R> {
128            type Output = Self;
129
130            fn $fn_name(self, rhs: Self) -> Self::Output {
131                debug_assert!(self.ring.get_ring() == rhs.ring.get_ring());
132                Self { ring: self.ring, element: rhs.ring.$fn_name(self.element, rhs.element) }
133            }
134        }
135
136        impl<'a, R: RingStore> $trait_name<RingElementWrapper<R>> for &'a RingElementWrapper<R> {
137            type Output = RingElementWrapper<R>;
138
139            fn $fn_name(self, rhs: RingElementWrapper<R>) -> Self::Output {
140                debug_assert!(self.ring.get_ring() == rhs.ring.get_ring());
141                RingElementWrapper { ring: rhs.ring, element: self.ring.$fn_name_ref_fst(&self.element, rhs.element) }
142            }
143        }
144
145        impl<'a, R: RingStore> $trait_name<&'a RingElementWrapper<R>> for RingElementWrapper<R> {
146            type Output = RingElementWrapper<R>;
147
148            fn $fn_name(self, rhs: &'a RingElementWrapper<R>) -> Self::Output {
149                debug_assert!(self.ring.get_ring() == rhs.ring.get_ring());
150                RingElementWrapper { ring: self.ring, element: rhs.ring.$fn_name_ref_snd(self.element, &rhs.element) }
151            }
152        }
153
154        impl<'a, 'b, R: RingStore + Clone> $trait_name<&'a RingElementWrapper<R>> for &'b RingElementWrapper<R> {
155            type Output = RingElementWrapper<R>;
156
157            fn $fn_name(self, rhs: &'a RingElementWrapper<R>) -> Self::Output {
158                debug_assert!(self.ring.get_ring() == rhs.ring.get_ring());
159                RingElementWrapper { ring: self.ring.clone(), element: self.ring.$fn_name_ref(&self.element, &rhs.element) }
160            }
161        }
162    };
163}
164
165impl_xassign_trait!{ AddAssign, add_assign, add_assign_ref }
166impl_xassign_trait!{ MulAssign, mul_assign, mul_assign_ref }
167impl_xassign_trait!{ SubAssign, sub_assign, sub_assign_ref }
168impl_trait!{ Add, add, add_ref_fst, add_ref_snd, add_ref }
169impl_trait!{ Mul, mul, mul_ref_fst, mul_ref_snd, mul_ref }
170impl_trait!{ Sub, sub, sub_ref_fst, sub_ref_snd, sub_ref }
171
172impl<R: RingStore> Div<RingElementWrapper<R>> for RingElementWrapper<R>
173    where R::Type: Field
174{
175    type Output = Self;
176
177    fn div(self, rhs: RingElementWrapper<R>) -> Self::Output {
178        RingElementWrapper { element: self.ring.div(&self.element, &rhs.element), ring: self.ring }
179    }
180}
181
182impl<'a, 'b, R: RingStore + Clone> Div<&'a RingElementWrapper<R>> for &'b RingElementWrapper<R>
183    where R::Type: Field
184{
185    type Output = RingElementWrapper<R>;
186
187    fn div(self, rhs: &'a RingElementWrapper<R>) -> Self::Output {
188        RingElementWrapper { element: self.ring.div(&self.element, &rhs.element), ring: self.ring.clone() }
189    }
190}
191
192impl<'a, R: RingStore + Clone> Div<RingElementWrapper<R>> for &'a RingElementWrapper<R>
193    where R::Type: Field
194{
195    type Output = RingElementWrapper<R>;
196
197    fn div(self, rhs: RingElementWrapper<R>) -> Self::Output {
198        RingElementWrapper { element: self.ring.div(&self.element, &rhs.element), ring: rhs.ring }
199    }
200}
201
202impl<'a, R: RingStore + Clone> Div<&'a RingElementWrapper<R>> for RingElementWrapper<R>
203    where R::Type: Field
204{
205    type Output = RingElementWrapper<R>;
206
207    fn div(self, rhs: &'a RingElementWrapper<R>) -> Self::Output {
208        RingElementWrapper { element: rhs.ring.div(&self.element, &rhs.element), ring: self.ring }
209    }
210}
211
212macro_rules! impl_xassign_trait_int {
213    ($trait_name:ident, $fn_name:ident) => {
214        
215        impl<R: RingStore> $trait_name<i32> for RingElementWrapper<R> {
216
217            fn $fn_name(&mut self, rhs: i32) {
218                self.ring.$fn_name(&mut self.element, self.ring.int_hom().map(rhs));
219            }
220        }
221    };
222}
223
224macro_rules! impl_trait_int {
225    ($trait_name:ident, $fn_name:ident) => {
226        
227        impl<R: RingStore> $trait_name<i32> for RingElementWrapper<R> {
228            type Output = Self;
229
230            fn $fn_name(self, rhs: i32) -> Self::Output {
231                RingElementWrapper { element: self.ring.$fn_name(self.element, self.ring.int_hom().map(rhs)), ring: self.ring }
232            }
233        }
234
235        impl<R: RingStore> $trait_name<RingElementWrapper<R>> for i32 {
236            type Output = RingElementWrapper<R>;
237
238            fn $fn_name(self, rhs: RingElementWrapper<R>) -> Self::Output {
239                RingElementWrapper { element: rhs.ring.$fn_name(rhs.ring.int_hom().map(self), rhs.element), ring: rhs.ring }
240            }
241        }
242
243        impl<'a, R: RingStore + Clone> $trait_name<i32> for &'a RingElementWrapper<R> {
244            type Output = RingElementWrapper<R>;
245
246            fn $fn_name(self, rhs: i32) -> Self::Output {
247                RingElementWrapper { element: self.ring.$fn_name(self.ring.clone_el(&self.element), self.ring.int_hom().map(rhs)), ring: self.ring.clone() }
248            }
249        }
250
251        impl<'a, R: RingStore + Clone> $trait_name<&'a RingElementWrapper<R>> for i32 {
252            type Output = RingElementWrapper<R>;
253
254            fn $fn_name(self, rhs: &'a RingElementWrapper<R>) -> Self::Output {
255                RingElementWrapper { element: rhs.ring.$fn_name(rhs.ring.int_hom().map(self), rhs.ring.clone_el(&rhs.element)), ring: rhs.ring.clone() }
256            }
257        }
258    };
259}
260
261impl_xassign_trait_int!{ AddAssign, add_assign }
262impl_xassign_trait_int!{ MulAssign, mul_assign }
263impl_xassign_trait_int!{ SubAssign, sub_assign }
264impl_trait_int!{ Add, add }
265impl_trait_int!{ Mul, mul }
266impl_trait_int!{ Sub, sub }
267
268impl<R: RingStore> Div<i32> for RingElementWrapper<R>
269    where R::Type: Field
270{
271    type Output = Self;
272
273    fn div(self, rhs: i32) -> Self::Output {
274        RingElementWrapper { element: self.ring.div(&self.element, &self.ring.int_hom().map(rhs)), ring: self.ring }
275    }
276}
277
278impl<R: RingStore> Div<RingElementWrapper<R>> for i32
279    where R::Type: Field
280{
281    type Output = RingElementWrapper<R>;
282
283    fn div(self, rhs: RingElementWrapper<R>) -> Self::Output {
284        RingElementWrapper { element: rhs.ring.div(&rhs.ring.int_hom().map(self), &rhs.element), ring: rhs.ring }
285    }
286}
287
288impl<'a, R: RingStore + Clone> Div<i32> for &'a RingElementWrapper<R>
289    where R::Type: Field
290{
291    type Output = RingElementWrapper<R>;
292
293    fn div(self, rhs: i32) -> Self::Output {
294        RingElementWrapper { element: self.ring.div(&self.element, &self.ring.int_hom().map(rhs)), ring: self.ring.clone() }
295    }
296}
297
298impl<'a, R: RingStore + Clone> Div<&'a RingElementWrapper<R>> for i32
299    where R::Type: Field
300{
301    type Output = RingElementWrapper<R>;
302
303    fn div(self, rhs: &'a RingElementWrapper<R>) -> Self::Output {
304        RingElementWrapper { element: rhs.ring.div(&rhs.ring.int_hom().map(self), &rhs.element), ring: rhs.ring.clone() }
305    }
306}
307
308impl<R: RingStore + Copy> Copy for RingElementWrapper<R> 
309    where El<R>: Copy
310{}
311
312impl<R: RingStore + Clone> Clone for RingElementWrapper<R> {
313
314    fn clone(&self) -> Self {
315        Self { ring: self.ring.clone(), element: self.ring.clone_el(&self.element) }
316    }
317}
318
319impl<R: RingStore> PartialEq for RingElementWrapper<R> {
320
321    fn eq(&self, other: &Self) -> bool {
322        debug_assert!(self.ring.get_ring() == other.ring.get_ring());
323        self.ring.eq_el(&self.element, &other.element)
324    }
325}
326
327impl<R: RingStore> Eq for RingElementWrapper<R> {}
328
329impl<R: RingStore> Hash for RingElementWrapper<R> 
330    where R::Type: HashableElRing
331{
332    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
333        self.ring.hash(&self.element, state)
334    }
335}
336
337impl<R: RingStore> Display for RingElementWrapper<R> {
338
339    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
340        self.ring.get_ring().dbg(&self.element, f)
341    }
342}
343
344impl<R: RingStore> Debug for RingElementWrapper<R> {
345
346    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
347        self.ring.get_ring().dbg(&self.element, f)
348    }
349}
350
351impl<R: RingStore> Deref for RingElementWrapper<R> {
352    type Target = El<R>;
353
354    fn deref(&self) -> &Self::Target {
355        &self.element
356    }
357}
358
359#[cfg(test)]
360use crate::rings::finite::FiniteRingStore;
361#[cfg(test)]
362use crate::rings::zn::zn_64;
363
364#[test]
365fn test_arithmetic_expression() {
366    let ring = zn_64::Zn::new(17);
367
368    for x in ring.elements() {
369        for y in ring.elements() {
370            for z in ring.elements() {
371                let expected = ring.add(ring.mul(x, y), ring.mul(ring.add(x, z), ring.sub(y, z)));
372                let x = RingElementWrapper::new(&ring, x);
373                let y = RingElementWrapper::new(&ring, y);
374                let z = RingElementWrapper::new(&ring, z);
375                assert_el_eq!(ring, expected, (x * y + (x + z) * (y - z)).unwrap());
376            }
377        }
378    }
379}
380
381#[test]
382fn test_arithmetic_expression_int() {
383    let ring = zn_64::Zn::new(17);
384
385    for x in ring.elements() {
386        for y in ring.elements() {
387            for z in ring.elements() {
388                let expected = ring.add(ring.add(ring.int_hom().mul_map(ring.mul(x, y), 8), ring.mul(ring.add(ring.add(ring.one(), x), ring.int_hom().mul_map(z, 2)), ring.sub(y, ring.int_hom().mul_map(z, 2)))), ring.int_hom().map(5));
389                let x = RingElementWrapper::new(&ring, x);
390                let y = RingElementWrapper::new(&ring, y);
391                let z = RingElementWrapper::new(&ring, z);
392                assert_el_eq!(ring, expected, (x * 8 * y + (1 + x + 2 * z) * (y - z * 2) + 5).unwrap());
393            }
394        }
395    }
396}
397
398#[test]
399fn test_arithmetic_expression_ref() {
400    let ring = zn_64::Zn::new(17);
401
402    for x in ring.elements() {
403        for y in ring.elements() {
404            for z in ring.elements() {
405                let expected = ring.add(ring.mul(x, y), ring.mul(ring.add(x, z), ring.sub(y, z)));
406                let x = RingElementWrapper::new(&ring, x);
407                let y = RingElementWrapper::new(&ring, y);
408                let z = RingElementWrapper::new(&ring, z);
409                assert_el_eq!(ring, expected, (x * &y + (&x + &z) * (&y - z)).unwrap());
410            }
411        }
412    }
413}
414
415#[test]
416fn test_arithmetic_expression_int_ref() {
417    let ring = zn_64::Zn::new(17);
418
419    for x in ring.elements() {
420        for y in ring.elements() {
421            for z in ring.elements() {
422                let expected = ring.add(ring.add(ring.int_hom().mul_map(ring.mul(x, y), 8), ring.mul(ring.add(ring.add(ring.one(), x), ring.int_hom().mul_map(z, 2)), ring.sub(y, ring.int_hom().mul_map(z, 2)))), ring.int_hom().map(5));
423                let x = RingElementWrapper::new(&ring, x);
424                let y = RingElementWrapper::new(&ring, y);
425                let z = RingElementWrapper::new(&ring, z);
426                assert_el_eq!(ring, expected, (x * 8 * &y + (1 + &x + 2 * &z) * (&y - z * 2) + 5).unwrap());
427            }
428        }
429    }
430}