feanor_math/
ring.rs

1use std::ops::Deref;
2
3use crate::homomorphism::*;
4use crate::ordered::OrderedRingStore;
5use crate::primitive_int::StaticRing;
6use crate::integer::*;
7use crate::algorithms;
8
9use serde::{Serialize, Deserialize};
10
11///
12/// Describes the context in which to print an algebraic expression.
13/// It is usually used to determine when to use parenthesis during printing.
14/// 
15/// # Example
16/// ```rust
17/// # use feanor_math::ring::*;
18/// # use feanor_math::rings::poly::*;
19/// # use feanor_math::primitive_int::*;
20/// # use feanor_math::rings::poly::dense_poly::*;
21/// struct CustomDisplay<'a>(&'a DensePolyRing<StaticRing<i64>>, &'a El<DensePolyRing<StaticRing<i64>>>, EnvBindingStrength);
22/// impl<'a> std::fmt::Display for CustomDisplay<'a> {
23///     fn fmt(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
24///         self.0.get_ring().dbg_within(self.1, formatter, self.2)
25///     }
26/// }
27/// let poly_ring = DensePolyRing::new(StaticRing::<i64>::RING, "X");
28/// let f = poly_ring.add(poly_ring.one(), poly_ring.indeterminate());
29/// assert_eq!("X + 1", format!("{}", CustomDisplay(&poly_ring, &f, EnvBindingStrength::Weakest)));
30/// assert_eq!("X + 1", format!("{}", CustomDisplay(&poly_ring, &f, EnvBindingStrength::Sum)));
31/// assert_eq!("(X + 1)", format!("{}", CustomDisplay(&poly_ring, &f, EnvBindingStrength::Product)));
32/// assert_eq!("(X + 1)", format!("{}", CustomDisplay(&poly_ring, &f, EnvBindingStrength::Power)));
33/// assert_eq!("(X + 1)", format!("{}", CustomDisplay(&poly_ring, &f, EnvBindingStrength::Strongest)));
34/// ```
35/// 
36#[derive(PartialEq, Eq, Debug, Clone, Copy, PartialOrd, Ord)]
37pub enum EnvBindingStrength {
38    /// 
39    /// The weakest possible binding strength, i.e. never add parenthesis.
40    /// 
41    Weakest,
42    /// 
43    /// Binding strength of addition (and subtraction), i.e. only add parenthesis
44    /// if the expression includes an operation that binds weaker than `+` (I cannot
45    /// think of any example, this seems to be a rare situation).
46    /// 
47    Sum, 
48    /// 
49    /// Binding strength of multiplication (and division), i.e. only add parenthesis if 
50    /// the expression includes an operation that binds weaker than `*` (Standard example 
51    /// would be `+`).
52    /// 
53    Product, 
54    /// 
55    /// Binding strength of powering, i.e. only add parenthesis if the expression
56    /// includes an operation that binds weaker than exponentiation (Standard examples would 
57    /// be `+` or `*`).
58    /// 
59    Power, 
60    ///
61    /// The strongest possible binding strength, i.e. always add parenthesis.
62    /// 
63    Strongest
64}
65
66///
67/// Basic trait for objects that have a ring structure. This trait is 
68/// implementor-facing, so designed to be used for implementing new
69/// rings.
70/// 
71/// Implementors of this trait should provide the basic ring operations,
72/// and additionally operators for displaying and equality testing. If
73/// a performance advantage can be achieved by accepting some arguments by
74/// reference instead of by value, the default-implemented functions for
75/// ring operations on references should be overwritten.
76/// 
77/// # Relationship with [`RingStore`]
78/// 
79/// Note that usually, this trait will not be used directly, but always
80/// through a [`RingStore`]. In more detail, while this trait
81/// defines the functionality, [`RingStore`] allows abstracting
82/// the storage - everything that allows access to a ring then is a 
83/// [`RingStore`], as for example, references or shared pointers
84/// to rings. If you want to use rings directly by value, some technical
85/// details make it necessary to use the no-op container [`RingStore`].
86/// For more detail, see the documentation of [`RingStore`].
87/// 
88/// # A note on equality
89/// 
90/// Generally speaking, the notion of being canonically isomorphic 
91/// (given by [`CanIsoFromTo`] is often more useful for rings than 
92/// equality (defined by [`PartialEq`]).
93/// 
94/// In particular, being canonically isomorphic means that that there
95/// is a bidirectional mapping of elements `a in Ring1 <-> b in Ring2`
96/// such that `a` and `b` behave exactly the same. This mapping is provided
97/// by the functions of [`CanIsoFromTo`]. Note that every ring is supposed
98/// to be canonically isomorphic to itself, via the identiy mapping.
99/// 
100/// The notion of equality is stronger than that. In particular, implementors
101/// of [`PartialEq`] must ensure that if rings `R` and `S` are equal, then
102/// they are canonically isomorphic and the canonical isomorphism is given
103/// by bitwise identity map. In particular, elements of `R` and `S` must have
104/// the same type.
105/// 
106/// Hence, be careful to not mix up elements of different rings, even if they
107/// have the same type. This can easily lead to nasty errors. For example, 
108/// consider the following code
109/// ```rust
110/// # use feanor_math::ring::*;
111/// # use feanor_math::homomorphism::*;
112/// # use feanor_math::primitive_int::*;
113/// # use feanor_math::rings::zn::*;
114/// let Z7 = zn_big::Zn::new(StaticRing::<i64>::RING, 7);
115/// let Z11 = zn_big::Zn::new(StaticRing::<i64>::RING, 11);
116/// assert!(Z11.get_ring() != Z7.get_ring());
117/// let neg_one = Z7.int_hom().map(-1);
118/// assert!(!Z11.is_neg_one(&neg_one));
119/// ```
120/// It is even allowed that both rings are isomorphic, and might be expected
121/// to be intuitively "the same", but still they are considered unequal, and
122/// swapping elements leads to incorrect results.
123/// 
124/// However, swapping elements between rings is well-defined and correct if they are "equal"
125/// as given by `PartialEq` (not just canonically isomorphic)
126/// ```rust
127/// # use feanor_math::ring::*;
128/// # use feanor_math::homomorphism::*;
129/// # use feanor_math::primitive_int::*;
130/// # use feanor_math::rings::zn::*;
131/// let Z11_fst = zn_big::Zn::new(StaticRing::<i64>::RING, 7);
132/// let Z11_snd = Z11_fst.clone();
133/// assert!(Z11_fst.get_ring() == Z11_snd.get_ring());
134/// let neg_one = Z11_fst.int_hom().map(-1);
135/// assert!(Z11_fst.is_neg_one(&neg_one));
136/// ```
137/// 
138/// # Example
139/// 
140/// An example implementation of a new, very useless ring type that represents
141/// 32-bit integers stored on the heap.
142/// ```rust
143/// # use feanor_math::ring::*;
144/// # use feanor_math::homomorphism::*;
145/// # use feanor_math::integer::*;
146/// 
147/// #[derive(PartialEq)]
148/// struct MyRingBase;
149/// 
150/// impl RingBase for MyRingBase {
151///     
152///     type Element = Box<i32>;
153/// 
154///     fn clone_el(&self, val: &Self::Element) -> Self::Element { val.clone() }
155///
156///     fn add_assign(&self, lhs: &mut Self::Element, rhs: Self::Element) { **lhs += *rhs; }
157/// 
158///     fn negate_inplace(&self, lhs: &mut Self::Element) { **lhs = -**lhs; }
159/// 
160///     fn mul_assign(&self, lhs: &mut Self::Element, rhs: Self::Element) { **lhs *= *rhs; }
161/// 
162///     fn from_int(&self, value: i32) -> Self::Element { Box::new(value) }
163/// 
164///     fn eq_el(&self, lhs: &Self::Element, rhs: &Self::Element) -> bool { **lhs == **rhs }
165/// 
166///     fn is_commutative(&self) -> bool { true }
167///     fn is_noetherian(&self) -> bool { true }
168///     fn is_approximate(&self) -> bool { false }
169/// 
170///     fn dbg_within<'a>(&self, value: &Self::Element, out: &mut std::fmt::Formatter<'a>, _: EnvBindingStrength) -> std::fmt::Result {
171///         write!(out, "{}", **value)
172///     }
173/// 
174///     fn characteristic<I>(&self, ZZ: I) -> Option<El<I>>
175///         where I: RingStore + Copy, I::Type: IntegerRing
176///     {
177///         Some(ZZ.zero())
178///     }
179/// }
180/// 
181/// // To use the ring through a RingStore, it is also required to implement CanHomFrom<Self>
182/// // and CanIsoFromTo<Self>.
183/// 
184/// impl CanHomFrom<MyRingBase> for MyRingBase {
185/// 
186///     type Homomorphism = ();
187/// 
188///     fn has_canonical_hom(&self, _from: &MyRingBase) -> Option<()> { Some(()) }
189/// 
190///     fn map_in(&self, _from: &MyRingBase, el: Self::Element, _: &()) -> Self::Element { el }
191/// }
192/// 
193/// impl CanIsoFromTo<MyRingBase> for MyRingBase {
194/// 
195///     type Isomorphism = ();
196/// 
197///     fn has_canonical_iso(&self, _from: &MyRingBase) -> Option<()> { Some(()) }
198/// 
199///     fn map_out(&self, _from: &MyRingBase, el: Self::Element, _: &()) -> Self::Element { el }
200/// }
201/// 
202/// // A type alias for the simple, by-value RingStore.
203/// pub type MyRing = RingValue<MyRingBase>;
204/// 
205/// impl MyRingBase {
206/// 
207///     pub const RING: MyRing = RingValue::from(MyRingBase);
208/// }
209/// 
210/// let ring = MyRingBase::RING;
211/// assert!(ring.eq_el(
212///     &ring.int_hom().map(6), 
213///     &ring.mul(ring.int_hom().map(3), ring.int_hom().map(2))
214/// ));
215/// ```
216/// 
217/// TODO: on next breaking release restrict with `: Debug`
218/// 
219#[allow(missing_docs)]
220pub trait RingBase: PartialEq {
221
222    ///
223    /// Type of elements of the ring
224    /// 
225    type Element: Sized;
226
227    fn clone_el(&self, val: &Self::Element) -> Self::Element;
228    fn add_assign_ref(&self, lhs: &mut Self::Element, rhs: &Self::Element) { self.add_assign(lhs, self.clone_el(rhs)) }
229    fn add_assign(&self, lhs: &mut Self::Element, rhs: Self::Element);
230    fn sub_assign_ref(&self, lhs: &mut Self::Element, rhs: &Self::Element) { self.sub_assign(lhs, self.clone_el(rhs)) }
231    fn negate_inplace(&self, lhs: &mut Self::Element);
232    fn mul_assign(&self, lhs: &mut Self::Element, rhs: Self::Element);
233    fn mul_assign_ref(&self, lhs: &mut Self::Element, rhs: &Self::Element) { self.mul_assign(lhs, self.clone_el(rhs)) }
234    fn zero(&self) -> Self::Element { self.from_int(0) }
235    fn one(&self) -> Self::Element { self.from_int(1) }
236    fn neg_one(&self) -> Self::Element { self.from_int(-1) }
237    fn from_int(&self, value: i32) -> Self::Element;
238    fn eq_el(&self, lhs: &Self::Element, rhs: &Self::Element) -> bool;
239    fn is_zero(&self, value: &Self::Element) -> bool { self.eq_el(value, &self.zero()) }
240    fn is_one(&self, value: &Self::Element) -> bool { self.eq_el(value, &self.one()) }
241    fn is_neg_one(&self, value: &Self::Element) -> bool { self.eq_el(value, &self.neg_one()) }
242
243    ///
244    /// Fused-multiply-add. This computes `summand + lhs * rhs`.
245    /// 
246    fn fma(&self, lhs: &Self::Element, rhs: &Self::Element, summand: Self::Element) -> Self::Element {
247        self.add(summand, self.mul_ref(lhs, rhs))
248    }
249
250    ///
251    /// Returns whether the ring is commutative, i.e. `a * b = b * a` for all elements `a, b`.
252    /// Note that addition is assumed to be always commutative.
253    /// 
254    fn is_commutative(&self) -> bool;
255
256    ///
257    /// Returns whether the ring is noetherian, i.e. every ideal is finitely generated.
258    /// 
259    /// Rings for which this is not the case are a exceptional situation in computer
260    /// algebra, since they are usually "very large" and hard to work with. Examples for
261    /// non-noetherian rings could be the polynomial ring in infinitely many variables
262    /// `Z[X1, X2, X3, ...]` or the ring of algebraic integers.
263    /// 
264    fn is_noetherian(&self) -> bool;
265
266    ///
267    /// Returns whether this ring computes with approximations to elements.
268    /// This would usually be the case for rings that are based on `f32` or
269    /// `f64`, to represent real or complex numbers.
270    /// 
271    /// Note that these rings cannot provide implementations for [`RingBase::eq_el()`], 
272    /// [`RingBase::is_zero()`] etc, and hence are of limited use in this crate.
273    /// Currently, the only way how approximate rings are used is a complex-valued
274    /// fast Fourier transform, via [`crate::rings::float_complex::Complex64`].
275    /// 
276    fn is_approximate(&self) -> bool;
277
278    ///
279    /// Writes a human-readable representation of `value` to `out`.
280    /// 
281    /// Used by [`RingStore::format()`], [`RingStore::println()`] and the implementations of [`std::fmt::Debug`] 
282    /// and [`std::fmt::Display`] of [`crate::wrapper::RingElementWrapper`].
283    /// 
284    fn dbg<'a>(&self, value: &Self::Element, out: &mut std::fmt::Formatter<'a>) -> std::fmt::Result {
285        self.dbg_within(value, out, EnvBindingStrength::Weakest)
286    }
287
288    ///
289    /// Writes a human-readable representation of `value` to `out`, taking into account the possible context
290    /// to place parenthesis as needed.
291    /// 
292    /// See also [`RingBase::dbg()`] and [`EnvBindingStrength`].
293    /// 
294    /// Used by [`RingStore::format()`], [`RingStore::println()`] and the implementations of [`std::fmt::Debug`] 
295    /// and [`std::fmt::Display`] of [`crate::wrapper::RingElementWrapper`].
296    /// 
297    fn dbg_within<'a>(&self, value: &Self::Element, out: &mut std::fmt::Formatter<'a>, _env: EnvBindingStrength) -> std::fmt::Result;
298
299    fn square(&self, value: &mut Self::Element) {
300        self.mul_assign(value, self.clone_el(value));
301    }
302
303    fn negate(&self, mut value: Self::Element) -> Self::Element {
304        self.negate_inplace(&mut value);
305        return value;
306    }
307    
308    fn sub_assign(&self, lhs: &mut Self::Element, mut rhs: Self::Element) {
309        self.negate_inplace(&mut rhs);
310        self.add_assign(lhs, rhs);
311    }
312
313    fn mul_assign_int(&self, lhs: &mut Self::Element, rhs: i32) {
314        self.mul_assign(lhs, self.from_int(rhs));
315    }
316
317    fn mul_int(&self, mut lhs: Self::Element, rhs: i32) -> Self::Element {
318        self.mul_assign_int(&mut lhs, rhs);
319        return lhs;
320    }
321
322    fn mul_int_ref(&self, lhs: &Self::Element, rhs: i32) -> Self::Element {
323        self.mul_int(self.clone_el(lhs), rhs)
324    }
325
326    ///
327    /// Fused-multiply-add with an integer. This computes `summand + lhs * rhs`.
328    /// 
329    fn fma_int(&self, lhs: &Self::Element, rhs: i32, summand: Self::Element) -> Self::Element {
330        self.add(summand, self.mul_int_ref(lhs, rhs))
331    }
332
333    ///
334    /// Computes `lhs := rhs - lhs`.
335    /// 
336    fn sub_self_assign(&self, lhs: &mut Self::Element, rhs: Self::Element) {
337        self.negate_inplace(lhs);
338        self.add_assign(lhs, rhs);
339    }
340
341    ///
342    /// Computes `lhs := rhs - lhs`.
343    /// 
344    fn sub_self_assign_ref(&self, lhs: &mut Self::Element, rhs: &Self::Element) {
345        self.negate_inplace(lhs);
346        self.add_assign_ref(lhs, rhs);
347    }
348
349    fn add_ref(&self, lhs: &Self::Element, rhs: &Self::Element) -> Self::Element {
350        let mut result = self.clone_el(lhs);
351        self.add_assign_ref(&mut result, rhs);
352        return result;
353    }
354
355    fn add_ref_fst(&self, lhs: &Self::Element, mut rhs: Self::Element) -> Self::Element {
356        self.add_assign_ref(&mut rhs, lhs);
357        return rhs;
358    }
359
360    fn add_ref_snd(&self, mut lhs: Self::Element, rhs: &Self::Element) -> Self::Element {
361        self.add_assign_ref(&mut lhs, rhs);
362        return lhs;
363    }
364
365    fn add(&self, mut lhs: Self::Element, rhs: Self::Element) -> Self::Element {
366        self.add_assign(&mut lhs, rhs);
367        return lhs;
368    }
369
370    fn sub_ref(&self, lhs: &Self::Element, rhs: &Self::Element) -> Self::Element {
371        let mut result = self.clone_el(lhs);
372        self.sub_assign_ref(&mut result, rhs);
373        return result;
374    }
375
376    fn sub_ref_fst(&self, lhs: &Self::Element, mut rhs: Self::Element) -> Self::Element {
377        self.sub_assign_ref(&mut rhs, lhs);
378        self.negate_inplace(&mut rhs);
379        return rhs;
380    }
381
382    fn sub_ref_snd(&self, mut lhs: Self::Element, rhs: &Self::Element) -> Self::Element {
383        self.sub_assign_ref(&mut lhs, rhs);
384        return lhs;
385    }
386
387    fn sub(&self, mut lhs: Self::Element, rhs: Self::Element) -> Self::Element {
388        self.sub_assign(&mut lhs, rhs);
389        return lhs;
390    }
391
392    fn mul_ref(&self, lhs: &Self::Element, rhs: &Self::Element) -> Self::Element {
393        let mut result = self.clone_el(lhs);
394        self.mul_assign_ref(&mut result, rhs);
395        return result;
396    }
397
398    fn mul_ref_fst(&self, lhs: &Self::Element, mut rhs: Self::Element) -> Self::Element {
399        if self.is_commutative() {
400            self.mul_assign_ref(&mut rhs, lhs);
401            return rhs;
402        } else {
403            let mut result = self.clone_el(lhs);
404            self.mul_assign(&mut result, rhs);
405            return result;
406        }
407    }
408
409    fn mul_ref_snd(&self, mut lhs: Self::Element, rhs: &Self::Element) -> Self::Element {
410        self.mul_assign_ref(&mut lhs, rhs);
411        return lhs;
412    }
413
414    fn mul(&self, mut lhs: Self::Element, rhs: Self::Element) -> Self::Element {
415        self.mul_assign(&mut lhs, rhs);
416        return lhs;
417    }
418    
419    ///
420    /// Raises `x` to the power of an arbitrary, nonnegative integer given by
421    /// a custom integer ring implementation.
422    /// 
423    /// Unless overriden by implementors, this uses a square-and-multiply approach
424    /// to achieve running time O(log(power)).
425    /// 
426    /// # Panic
427    /// 
428    /// This may panic if `power` is negative.
429    /// 
430    fn pow_gen<R: RingStore>(&self, x: Self::Element, power: &El<R>, integers: R) -> Self::Element 
431        where R::Type: IntegerRing
432    {
433        assert!(!integers.is_neg(power));
434        algorithms::sqr_mul::generic_pow_shortest_chain_table(
435            x, 
436            power, 
437            &integers,
438            |a| {
439                let mut a_copy = self.clone_el(a);
440                self.square(&mut a_copy);
441                Ok(a_copy)
442            },
443            |a, b| Ok(self.mul_ref(a, b)),
444            |a| self.clone_el(a),
445            self.one()
446        ).unwrap_or_else(|x| x)
447    }
448
449    ///
450    /// Sums the elements given by the iterator.
451    /// 
452    /// The implementation might be as simple as `els.fold(self.zero(), |a, b| self.add(a, b))`, but
453    /// can be more efficient than that in some cases.
454    /// 
455    fn sum<I>(&self, els: I) -> Self::Element 
456        where I: IntoIterator<Item = Self::Element>
457    {
458        els.into_iter().fold(self.zero(), |a, b| self.add(a, b))
459    }
460
461    ///
462    /// Computes the product of the elements given by the iterator.
463    /// 
464    /// The implementation might be as simple as `els.fold(self.one(), |a, b| self.mul(a, b))`, but
465    /// can be more efficient than that in some cases.
466    /// 
467    fn prod<I>(&self, els: I) -> Self::Element 
468        where I: IntoIterator<Item = Self::Element>
469    {
470        els.into_iter().fold(self.one(), |a, b| self.mul(a, b))
471    }
472    
473    ///
474    /// Returns the characteristic of this ring as an element of the given
475    /// implementation of `ZZ`. 
476    /// 
477    /// If `None` is returned, this means the given integer ring might not be able
478    /// to represent the characteristic. This must never happen if the given implementation
479    /// of `ZZ` allows for unbounded integers (like [`crate::integer::BigIntRing`]).
480    /// In other cases however, we allow to perform the size check heuristically only,
481    /// so this might return `None` even in some cases where the integer ring would in
482    /// fact be able to represent the characteristic.
483    /// 
484    /// # Example
485    /// ```rust
486    /// # use feanor_math::ring::*;
487    /// # use feanor_math::primitive_int::*;
488    /// # use feanor_math::rings::zn::*;
489    /// let ZZ = StaticRing::<i16>::RING;
490    /// assert_eq!(Some(0), StaticRing::<i64>::RING.characteristic(&ZZ));
491    /// assert_eq!(None, zn_64::Zn::new(i16::MAX as u64 + 1).characteristic(&ZZ));
492    /// assert_eq!(Some(i16::MAX), zn_64::Zn::new(i16::MAX as u64).characteristic(&ZZ));
493    /// ```
494    /// 
495    fn characteristic<I: RingStore + Copy>(&self, ZZ: I) -> Option<El<I>>
496        where I::Type: IntegerRing;
497}
498
499///
500/// Used to easily implement functions in the trait definition of
501/// [`RingStore`] and its subtraits to delegate the call to the same
502/// function of the underlying [`RingBase`].
503/// 
504/// # Example
505/// ```rust
506/// # use feanor_math::ring::*;
507/// # #[macro_use] use feanor_math::delegate;
508/// 
509/// trait WeirdRingBase: RingBase {
510///     fn foo(&self) -> Self::Element;
511/// }
512/// 
513/// trait WeirdRingStore: RingStore
514///     where Self::Type: WeirdRingBase
515/// {
516///     delegate!{ WeirdRingBase, fn foo(&self) -> El<Self> }
517/// }
518/// ```
519/// 
520/// # Limitations
521/// 
522/// This macro does not work if the function takes generic parameters.
523/// In this case, write the delegation manually.
524/// 
525#[macro_export]
526macro_rules! delegate {
527    ($base_trait:ty, fn $name:ident (&self, $($pname:ident: $ptype:ty),*) -> $rtype:ty) => {
528        #[doc = concat!(" See [`", stringify!($base_trait), "::", stringify!($name), "()`]")]
529        fn $name (&self, $($pname: $ptype),*) -> $rtype {
530            <Self::Type as $base_trait>::$name(self.get_ring(), $($pname),*)
531        }
532    };
533    ($base_trait:ty, fn $name:ident (&self) -> $rtype:ty) => {
534        #[doc = concat!(" See [`", stringify!($base_trait), "::", stringify!($name), "()`]")]
535        fn $name (&self) -> $rtype {
536            <Self::Type as $base_trait>::$name(self.get_ring())
537        }
538    };
539}
540
541///
542/// Variant of `assert_eq!` for ring elements, i.e. assert that two ring elements are equal.
543/// Frequently used in tests
544/// 
545/// # Example
546/// ```rust
547/// # use feanor_math::ring::*;
548/// # use feanor_math::primitive_int::*;
549/// # use feanor_math::assert_el_eq;
550/// 
551/// assert_el_eq!(StaticRing::<i32>::RING, 3, 3);
552/// // is equivalent to
553/// assert_eq!(3, 3);
554/// ```
555/// If the ring elements are not comparable on their own, this is really useful
556/// ```rust
557/// # use feanor_math::ring::*;
558/// # use feanor_math::homomorphism::*;
559/// # use feanor_math::integer::*;
560/// # use feanor_math::assert_el_eq;
561/// // this does not have an equivalent representation with assert_eq!
562/// assert_el_eq!(BigIntRing::RING, BigIntRing::RING.int_hom().map(3), BigIntRing::RING.int_hom().map(3));
563/// ```
564/// 
565#[macro_export]
566macro_rules! assert_el_eq {
567    ($ring:expr, $lhs:expr, $rhs:expr) => {
568        match (&$ring, &$lhs, &$rhs) {
569            (ring_val, lhs_val, rhs_val) => {
570                assert!(<_ as $crate::ring::RingStore>::eq_el(ring_val, lhs_val, rhs_val), "Assertion failed: {} != {}", <_ as $crate::ring::RingStore>::format(ring_val, lhs_val), <_ as $crate::ring::RingStore>::format(ring_val, rhs_val));
571            }
572        }
573    }
574}
575
576///
577/// Basic trait for objects that store (in some sense) a ring. It can also
578/// be considered the user-facing trait for rings, so rings are always supposed
579/// to be used through a `RingStore`-object.
580/// 
581/// This can be a ring-by-value, a reference to a ring, or really any object that
582/// provides access to a [`RingBase`] object.
583/// 
584/// As opposed to [`RingBase`], which is responsible for the
585/// functionality and ring operations, this trait is solely responsible for
586/// the storage. The two basic implementors are [`RingValue`] and [`RingRef`],
587/// which just wrap a value resp. reference to a [`RingBase`] object.
588/// Building on that, every object that wraps a [`RingStore`] object can implement
589/// again [`RingStore`]. This applies in particular to implementors of
590/// `Deref<Target: RingStore>`, for whom there is a blanket implementation.
591/// 
592/// # Example
593/// 
594/// ```rust
595/// # use feanor_math::assert_el_eq;
596/// # use feanor_math::ring::*;
597/// # use feanor_math::primitive_int::*;
598/// # use std::rc::Rc;
599/// fn add_in_ring<R: RingStore>(ring: R, a: El<R>, b: El<R>) -> El<R> {
600///     ring.add(a, b)
601/// }
602/// 
603/// let ring: RingValue<StaticRingBase<i64>> = StaticRing::<i64>::RING;
604/// assert_el_eq!(ring, 7, add_in_ring(ring, 3, 4));
605/// assert_el_eq!(ring, 7, add_in_ring(&ring, 3, 4));
606/// assert_el_eq!(ring, 7, add_in_ring(Rc::new(ring), 3, 4));
607/// ```
608/// 
609/// # What does this do?
610/// 
611/// We need a framework that allows nesting rings, e.g. to provide a polynomial ring
612/// over a finite field - say `PolyRing<FiniteRing + Field>`. However, the simplest
613/// implementation
614/// ```rust,ignore
615/// struct PolyRing<BaseRing: Ring> { /* omitted */ }
616/// ```
617/// would have the effect that `PolyRing<FiniteRing + Field>` and `PolyRing<&FiniteRing + Field>`
618/// are entirely different types. While implementing relationships between them
619/// is possible, the approach does not scale well when we consider many rings and
620/// multiple layers of nesting.
621/// 
622/// # Note for implementors
623/// 
624/// Generally speaking it is not recommended to overwrite any of the default-implementations
625/// of ring functionality, as this is against the spirit of this trait. Instead,
626/// just provide an implementation of `get_ring()` and put ring functionality in
627/// a custom implementation of [`RingBase`].
628/// 
629pub trait RingStore: Sized {
630    
631    ///
632    /// The type of the stored ring.
633    /// 
634    type Type: RingBase + ?Sized;
635
636    ///
637    /// Returns a reference to the stored ring.
638    /// 
639    fn get_ring<'a>(&'a self) -> &'a Self::Type;
640
641    delegate!{ RingBase, fn clone_el(&self, val: &El<Self>) -> El<Self> }
642    delegate!{ RingBase, fn add_assign_ref(&self, lhs: &mut El<Self>, rhs: &El<Self>) -> () }
643    delegate!{ RingBase, fn add_assign(&self, lhs: &mut El<Self>, rhs: El<Self>) -> () }
644    delegate!{ RingBase, fn sub_assign_ref(&self, lhs: &mut El<Self>, rhs: &El<Self>) -> () }
645    delegate!{ RingBase, fn sub_self_assign(&self, lhs: &mut El<Self>, rhs: El<Self>) -> () }
646    delegate!{ RingBase, fn sub_self_assign_ref(&self, lhs: &mut El<Self>, rhs: &El<Self>) -> () }
647    delegate!{ RingBase, fn negate_inplace(&self, lhs: &mut El<Self>) -> () }
648    delegate!{ RingBase, fn mul_assign(&self, lhs: &mut El<Self>, rhs: El<Self>) -> () }
649    delegate!{ RingBase, fn mul_assign_ref(&self, lhs: &mut El<Self>, rhs: &El<Self>) -> () }
650    delegate!{ RingBase, fn zero(&self) -> El<Self> }
651    delegate!{ RingBase, fn one(&self) -> El<Self> }
652    delegate!{ RingBase, fn neg_one(&self) -> El<Self> }
653    delegate!{ RingBase, fn eq_el(&self, lhs: &El<Self>, rhs: &El<Self>) -> bool }
654    delegate!{ RingBase, fn is_zero(&self, value: &El<Self>) -> bool }
655    delegate!{ RingBase, fn is_one(&self, value: &El<Self>) -> bool }
656    delegate!{ RingBase, fn is_neg_one(&self, value: &El<Self>) -> bool }
657    delegate!{ RingBase, fn is_commutative(&self) -> bool }
658    delegate!{ RingBase, fn is_noetherian(&self) -> bool }
659    delegate!{ RingBase, fn negate(&self, value: El<Self>) -> El<Self> }
660    delegate!{ RingBase, fn sub_assign(&self, lhs: &mut El<Self>, rhs: El<Self>) -> () }
661    delegate!{ RingBase, fn add_ref(&self, lhs: &El<Self>, rhs: &El<Self>) -> El<Self> }
662    delegate!{ RingBase, fn add_ref_fst(&self, lhs: &El<Self>, rhs: El<Self>) -> El<Self> }
663    delegate!{ RingBase, fn add_ref_snd(&self, lhs: El<Self>, rhs: &El<Self>) -> El<Self> }
664    delegate!{ RingBase, fn add(&self, lhs: El<Self>, rhs: El<Self>) -> El<Self> }
665    delegate!{ RingBase, fn sub_ref(&self, lhs: &El<Self>, rhs: &El<Self>) -> El<Self> }
666    delegate!{ RingBase, fn sub_ref_fst(&self, lhs: &El<Self>, rhs: El<Self>) -> El<Self> }
667    delegate!{ RingBase, fn sub_ref_snd(&self, lhs: El<Self>, rhs: &El<Self>) -> El<Self> }
668    delegate!{ RingBase, fn sub(&self, lhs: El<Self>, rhs: El<Self>) -> El<Self> }
669    delegate!{ RingBase, fn mul_ref(&self, lhs: &El<Self>, rhs: &El<Self>) -> El<Self> }
670    delegate!{ RingBase, fn mul_ref_fst(&self, lhs: &El<Self>, rhs: El<Self>) -> El<Self> }
671    delegate!{ RingBase, fn mul_ref_snd(&self, lhs: El<Self>, rhs: &El<Self>) -> El<Self> }
672    delegate!{ RingBase, fn mul(&self, lhs: El<Self>, rhs: El<Self>) -> El<Self> }
673    delegate!{ RingBase, fn square(&self, value: &mut El<Self>) -> () }
674    delegate!{ RingBase, fn fma(&self, lhs: &El<Self>, rhs: &El<Self>, summand: El<Self>) -> El<Self> }
675
676    ///
677    /// Tries to map the given element into this ring.
678    ///
679    /// This will internally construct a homomorphism between the rings, using
680    /// [`CanHomFrom`]. Note that if you want to map many elements between the
681    /// same rings, it may be faster to construct the homomorphism only once using
682    /// [`RingStore::can_hom()`].
683    /// 
684    fn coerce<S>(&self, from: &S, el: El<S>) -> El<Self>
685        where S: RingStore, Self::Type: CanHomFrom<S::Type> 
686    {
687        self.get_ring().map_in(from.get_ring(), el, &self.get_ring().has_canonical_hom(from.get_ring()).unwrap())
688    }
689
690    ///
691    /// Returns the identity map `self -> self`.
692    /// 
693    fn into_identity(self) -> Identity<Self> {
694        Identity::new(self)
695    }
696
697    ///
698    /// Returns the identity map `self -> self`.
699    /// 
700    fn identity<'a>(&'a self) -> Identity<&'a Self> {
701        self.into_identity()
702    }
703
704    ///
705    /// Returns the canonical homomorphism `from -> self`, if it exists,
706    /// moving both rings into the [`CanHom`] object.
707    /// 
708    fn into_can_hom<S>(self, from: S) -> Result<CanHom<S, Self>, (S, Self)>
709        where Self: Sized, S: RingStore, Self::Type: CanHomFrom<S::Type>
710    {
711        CanHom::new(from, self)
712    }
713
714    ///
715    /// Returns the canonical isomorphism `from -> self`, if it exists,
716    /// moving both rings into the [`CanHom`] object.
717    /// 
718    fn into_can_iso<S>(self, from: S) -> Result<CanIso<S, Self>, (S, Self)>
719        where Self: Sized, S: RingStore, Self::Type: CanIsoFromTo<S::Type>
720    {
721        CanIso::new(from, self)
722    }
723
724    ///
725    /// Returns the canonical homomorphism `from -> self`, if it exists.
726    /// 
727    fn can_hom<'a, S>(&'a self, from: &'a S) -> Option<CanHom<&'a S, &'a Self>>
728        where S: RingStore, Self::Type: CanHomFrom<S::Type>
729    {
730        self.into_can_hom(from).ok()
731    }
732
733    ///
734    /// Returns the canonical isomorphism `from -> self`, if it exists.
735    /// 
736    fn can_iso<'a, S>(&'a self, from: &'a S) -> Option<CanIso<&'a S, &'a Self>>
737        where S: RingStore, Self::Type: CanIsoFromTo<S::Type>
738    {
739        self.into_can_iso(from).ok()
740    }
741
742    ///
743    /// Returns the homomorphism `Z -> self` that exists for any ring.
744    /// 
745    fn into_int_hom(self) -> IntHom<Self> {
746        IntHom::new(self)
747    }
748
749    ///
750    /// Returns the homomorphism `Z -> self` that exists for any ring.
751    /// 
752    fn int_hom<'a>(&'a self) -> IntHom<&'a Self> {
753        self.into_int_hom()
754    }
755
756    ///
757    /// Computes the sum of all elements returned by the iterator.
758    /// 
759    /// This is equivalent to
760    /// ```rust
761    /// # use feanor_math::ring::*;
762    /// # use feanor_math::primitive_int::*;
763    /// # use feanor_math::assert_el_eq;
764    /// fn sum<R, I>(ring: R, els: I) -> El<R>
765    ///     where R: RingStore,
766    ///         I: IntoIterator<Item = El<R>>
767    /// {
768    ///     els.into_iter().fold(ring.zero(), |a, b| ring.add(a, b))
769    /// }
770    /// # assert_el_eq!(StaticRing::<i64>::RING, StaticRing::<i64>::RING.sum([1, 2, 5]), sum(StaticRing::<i64>::RING, [1, 2, 5]))
771    /// ```
772    /// but may be faster.
773    /// 
774    fn sum<I>(&self, els: I) -> El<Self> 
775        where I: IntoIterator<Item = El<Self>>
776    {
777        self.get_ring().sum(els)
778    }
779
780    ///
781    /// Equivalent of [`RingStore::sum()`] if the producer of the ring elements
782    /// can fail, in which case summation is aborted and the error returned.
783    /// 
784    #[stability::unstable(feature = "enable")]
785    fn try_sum<I, E>(&self, els: I) -> Result<El<Self>, E>
786        where I: IntoIterator<Item = Result<El<Self>, E>>
787    {
788        let mut error = None;
789        let result = self.get_ring().sum(els.into_iter().map_while(|el| match el {
790            Ok(el) => Some(el),
791            Err(err) => {
792                error = Some(err);
793                None
794            }
795        }));
796        if let Some(err) = error {
797            return Err(err);
798        } else {
799            return Ok(result);
800        }
801    }
802
803    ///
804    /// Computes the product of all elements returned by the iterator.
805    /// 
806    /// This is equivalent to
807    /// ```rust
808    /// # use feanor_math::ring::*;
809    /// # use feanor_math::primitive_int::*;
810    /// # use feanor_math::assert_el_eq;
811    /// fn prod<R, I>(ring: R, els: I) -> El<R>
812    ///     where R: RingStore,
813    ///         I: IntoIterator<Item = El<R>>
814    /// {
815    ///     els.into_iter().fold(ring.one(), |a, b| ring.mul(a, b))
816    /// }
817    /// # assert_el_eq!(StaticRing::<i64>::RING, StaticRing::<i64>::RING.prod([1, 2, 5]), prod(StaticRing::<i64>::RING, [1, 2, 5]))
818    /// ```
819    /// but may be faster.
820    /// 
821    fn prod<I>(&self, els: I) -> El<Self> 
822        where I: IntoIterator<Item = El<Self>>
823    {
824        self.get_ring().prod(els)
825    }
826
827    ///
828    /// Raises the given element to the given power.
829    /// 
830    fn pow(&self, mut x: El<Self>, power: usize) -> El<Self> {
831        // special cases to increase performance
832        if power == 0 {
833            return self.one();
834        } else if power == 1 {
835            return x;
836        } else if power == 2 {
837            self.square(&mut x);
838            return x;
839        }
840        self.pow_gen(x, &power.try_into().unwrap(), StaticRing::<i64>::RING)
841    }
842
843    ///
844    /// Raises the given element to the given power, which should be a positive integer
845    /// belonging to an arbitrary [`IntegerRing`]. 
846    /// 
847    /// This can in particular be used to compute exponentiation when the exponent does
848    /// not fit in a `usize`.
849    /// 
850    fn pow_gen<R: RingStore>(&self, x: El<Self>, power: &El<R>, integers: R) -> El<Self> 
851        where R::Type: IntegerRing
852    {
853        self.get_ring().pow_gen(x, power, integers)
854    }
855
856    ///
857    /// Returns an object that represents the given ring element and implements
858    /// [`std::fmt::Display`], to use as formatting parameter.
859    /// 
860    /// # Example
861    /// ```rust
862    /// # use feanor_math::ring::*;
863    /// # use feanor_math::homomorphism::*;
864    /// # use feanor_math::integer::*;
865    /// let ring = BigIntRing::RING;
866    /// let element = ring.int_hom().map(3);
867    /// assert_eq!("3", format!("{}", ring.format(&element)));
868    /// ```
869    /// 
870    fn format<'a>(&'a self, value: &'a El<Self>) -> RingElementDisplayWrapper<'a, Self> {
871        self.format_within(value, EnvBindingStrength::Weakest)
872    }
873
874    ///
875    /// Returns an object that represents the given ring element and implements
876    /// [`std::fmt::Display`], to use as formatting parameter. As opposed to
877    /// [`RingStore::format()`], this function takes an additional argument to
878    /// specify the context the result is printed in, which is used to determine
879    /// whether to put the value in parenthesis or not.
880    /// 
881    /// # Example
882    /// ```rust
883    /// # use feanor_math::ring::*;
884    /// # use feanor_math::homomorphism::*;
885    /// # use feanor_math::integer::*;
886    /// # use feanor_math::rings::poly::dense_poly::*;
887    /// # use feanor_math::primitive_int::*;
888    /// # use feanor_math::rings::poly::*;
889    /// let ring = DensePolyRing::new(StaticRing::<i64>::RING, "X");
890    /// let [f, g] = ring.with_wrapped_indeterminate(|X| [X.clone(), X + 1]);
891    /// assert_eq!("X", format!("{}", ring.format_within(&f, EnvBindingStrength::Sum)));
892    /// assert_eq!("X", format!("{}", ring.format_within(&f, EnvBindingStrength::Product)));
893    /// assert_eq!("X + 1", format!("{}", ring.format_within(&g, EnvBindingStrength::Sum)));
894    /// assert_eq!("(X + 1)", format!("{}", ring.format_within(&g, EnvBindingStrength::Product)));
895    /// ```
896    /// 
897    fn format_within<'a>(&'a self, value: &'a El<Self>, within: EnvBindingStrength) -> RingElementDisplayWrapper<'a, Self> {
898        RingElementDisplayWrapper { ring: self, element: value, within: within }
899    }
900
901    ///
902    /// Prints the given element. Use for quick & dirty debugging.
903    /// 
904    fn println(&self, value: &El<Self>) {
905        println!("{}", self.format(value));
906    }
907    
908    ///
909    /// See [`RingBase::characteristic()`].
910    /// 
911    fn characteristic<I: RingStore + Copy>(&self, ZZ: I) -> Option<El<I>>
912        where I::Type: IntegerRing
913    {
914        self.get_ring().characteristic(ZZ)
915    }
916}
917
918///
919/// [`RingStore`] for [`RingExtension`]s
920/// 
921pub trait RingExtensionStore: RingStore
922    where Self::Type: RingExtension
923{
924    delegate!{ RingExtension, fn base_ring(&self) -> &<Self::Type as RingExtension>::BaseRing }
925
926    ///
927    /// Returns the inclusion map of the base ring `R -> self`.
928    /// 
929    fn into_inclusion(self) -> Inclusion<Self> {
930        Inclusion::new(self)
931    }
932
933    ///
934    /// Returns the inclusion map of the base ring `R -> self`.
935    /// 
936    fn inclusion<'a>(&'a self) -> Inclusion<&'a Self> {
937        self.into_inclusion()
938    }
939
940}
941
942impl<R: RingStore> RingExtensionStore for R
943    where R::Type: RingExtension
944{}
945
946///
947/// Wrapper around a ring and one of its elements that implements [`std::fmt::Display`]
948/// and will print the element. Used by [`RingStore::format()`].
949/// 
950pub struct RingElementDisplayWrapper<'a, R: RingStore + ?Sized> {
951    ring: &'a R,
952    element: &'a El<R>,
953    within: EnvBindingStrength
954}
955
956impl<'a, R: RingStore + ?Sized> std::fmt::Display for RingElementDisplayWrapper<'a, R> {
957
958    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
959        self.ring.get_ring().dbg_within(self.element, f, self.within)
960    }
961}
962
963impl<'a, R: RingStore + ?Sized> std::fmt::Debug for RingElementDisplayWrapper<'a, R> {
964
965    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
966        self.ring.get_ring().dbg_within(self.element, f, self.within)
967    }
968}
969
970///
971/// Trait for rings that are an extension ring of a base ring.
972/// This does not have to be a proper extension in the mathematical
973/// sense, but is in some cases implemented for a wrapper of a ring
974/// object that represents the same ring.
975/// 
976/// Hence, this is technically just a ring `R` with an injective homomorphism
977/// `BaseRing -> R`, but unlike [`CanHomFrom`], implementors must provide
978/// a reference to `BaseRing` via [`RingExtension::base_ring()`].
979/// 
980/// # Overlap with [`CanHomFrom`]
981/// 
982/// There is a certain amount of functionality overlap with [`CanHomFrom`], and
983/// in a perfect world, this trait would also be a subtrait of `CanHomFrom<<Self::BaseRing as RingStore>::Type>`.
984/// However, due to the issue with multiple blanket implementations for [`CanHomFrom`] (see
985/// the docs), this is not the case and in fact there are ring extensions that do not implement
986/// `CanHomFrom<<Self::BaseRing as RingStore>::Type>`.
987/// 
988pub trait RingExtension: RingBase {
989    
990    ///
991    /// Type of the base ring;
992    /// 
993    /// This is bounded by [`RingStore`] to encourage implementations of [`RingExtension`]
994    /// to store their base ring as a [`RingStore`] ([`RingStore`] is designed exactly for
995    /// this use case). Additionally, it makes using the base ring easier.
996    /// 
997    type BaseRing: RingStore;
998
999    ///
1000    /// Returns a reference to the base ring.
1001    /// 
1002    fn base_ring<'a>(&'a self) -> &'a Self::BaseRing;
1003
1004    ///
1005    /// Maps an element of the base ring into this ring.
1006    /// 
1007    /// This should realize an injective ring homomorphism.
1008    /// Instead of calling it directly, consider using it through
1009    /// [`RingExtensionStore::inclusion()`].
1010    /// 
1011    fn from(&self, x: El<Self::BaseRing>) -> Self::Element;
1012    
1013    ///
1014    /// Maps an element of the base ring (given as reference) into this ring.
1015    /// 
1016    fn from_ref(&self, x: &El<Self::BaseRing>) -> Self::Element {
1017        self.from(self.base_ring().get_ring().clone_el(x))
1018    }
1019
1020    ///
1021    /// Computes `lhs := lhs * rhs`, where `rhs` is mapped into this
1022    /// ring via [`RingExtension::from_ref()`]. Note that this may be
1023    /// faster than `self.mul_assign(lhs, self.from_ref(rhs))`.
1024    /// 
1025    fn mul_assign_base(&self, lhs: &mut Self::Element, rhs: &El<Self::BaseRing>) {
1026        self.mul_assign(lhs, self.from_ref(rhs));
1027    }
1028
1029    fn fma_base(&self, lhs: &Self::Element, rhs: &El<Self::BaseRing>, summand: Self::Element) -> Self::Element {
1030        let mut tmp = self.clone_el(lhs);
1031        self.mul_assign_base(&mut tmp, rhs);
1032        return self.add(summand, tmp);
1033    }
1034
1035    ///
1036    /// Computes `lhs := lhs * rhs`, where `rhs` is mapped into this ring
1037    /// via the given homomorphism, followed by the inclusion (as specified by
1038    /// [`RingExtension::from_ref()`]).
1039    /// 
1040    /// This is designed for the case that an extension ring element is represented
1041    /// as a vector of base ring elements, in which case this function can make
1042    /// use of an optimized [`Homomorphism::mul_assign_map()`] implementation.
1043    /// 
1044    #[stability::unstable(feature = "enable")]
1045    fn mul_assign_base_through_hom<S: ?Sized + RingBase, H: Homomorphism<S, <Self::BaseRing as RingStore>::Type>>(&self, lhs: &mut Self::Element, rhs: &S::Element, hom: H) {
1046        self.mul_assign_base(lhs, &hom.map_ref(rhs));
1047    }
1048}
1049
1050///
1051/// Trait for rings that can compute hashes for their elements.
1052/// This should be compatible with [`RingBase::eq_el`] in the usual way.
1053/// 
1054pub trait HashableElRing: RingBase {
1055
1056    ///
1057    /// Hashes the given ring element.
1058    /// 
1059    fn hash<H: std::hash::Hasher>(&self, el: &Self::Element, h: &mut H);
1060}
1061
1062///
1063/// [`RingStore`] for [`HashableElRing`]s
1064/// 
1065pub trait HashableElRingStore: RingStore
1066    where Self::Type: HashableElRing
1067{
1068    ///
1069    /// See [`HashableElRing::hash()`].
1070    /// 
1071    fn hash<H: std::hash::Hasher>(&self, el: &El<Self>, h: &mut H) {
1072        self.get_ring().hash(el, h)
1073    }
1074
1075    ///
1076    /// Computes a hash of the given element using some default hasher.
1077    /// 
1078    /// This may not be the same in different versions of `feanor-math`.
1079    /// 
1080    fn default_hash(&self, el: &El<Self>) -> u64 {
1081        let mut hasher = std::collections::hash_map::DefaultHasher::new();
1082        self.hash(el, &mut hasher);
1083        return <std::collections::hash_map::DefaultHasher as std::hash::Hasher>::finish(&hasher);
1084    }
1085}
1086
1087impl<R> HashableElRingStore for R
1088    where R: RingStore,
1089        R::Type: HashableElRing
1090{}
1091
1092///
1093/// Alias for `<<Self as RingStore>::Type as RingBase>::Element`.
1094/// 
1095pub type El<R> = <<R as RingStore>::Type as RingBase>::Element;
1096
1097///
1098/// The most fundamental [`crate::ring::RingStore`]. It is basically
1099/// a no-op container, i.e. stores a [`crate::ring::RingBase`] object
1100/// by value, and allows accessing it.
1101/// 
1102/// # Why is this necessary?
1103/// 
1104/// In fact, that we need this trait is just the result of a technical
1105/// detail. We cannot implement
1106/// ```rust,ignore
1107/// impl<R: RingBase> RingStore for R {}
1108/// impl<'a, R: RingStore> RingStore for &'a R {}
1109/// ```
1110/// since this might cause conflicting implementations.
1111/// Instead, we implement
1112/// ```rust,ignore
1113/// impl<R: RingBase> RingStore for RingValue<R> {}
1114/// impl<'a, R: RingStore> RingStore for &'a R {}
1115/// ```
1116/// This causes some inconvenience, as now we cannot chain
1117/// [`crate::ring::RingStore`] in the case of [`crate::ring::RingValue`].
1118/// Furthermore, this trait will be necessary everywhere - 
1119/// to define a reference to a ring of type `A`, we now have to
1120/// write `&RingValue<A>`.
1121/// 
1122/// To simplify this, we propose to use the following simple pattern:
1123/// Create your ring type as
1124/// ```rust,ignore
1125/// struct ABase { ... }
1126/// impl RingBase for ABase { ... } 
1127/// ```
1128/// and then provide a type alias
1129/// ```rust,ignore
1130/// type A = RingValue<ABase>;
1131/// ```
1132/// 
1133#[repr(transparent)]
1134#[derive(Copy, Clone, Debug, Serialize, Deserialize)]
1135pub struct RingValue<R: RingBase> {
1136    ring: R
1137}
1138
1139impl<R: RingBase> RingValue<R> {
1140
1141    ///
1142    /// Wraps the given [`RingBase`] in a [`RingValue`].
1143    /// 
1144    /// This is a dedicated function instead of an implementation
1145    /// of [`std::convert::From`] so that we can declare it `const`.
1146    /// 
1147    pub const fn from(value: R) -> Self {
1148        RingValue { ring: value }
1149    }
1150
1151    ///
1152    /// Creates a reference to a [`RingValue`] from a reference
1153    /// to the [`RingBase`].
1154    /// 
1155    pub fn from_ref<'a>(value: &'a R) -> &'a Self {
1156        unsafe { std::mem::transmute(value) }
1157    }
1158
1159    ///
1160    /// Unwraps the [`RingBase`].
1161    /// 
1162    /// The more common case would be to get a reference, which can
1163    /// be done with [`RingStore::get_ring()`].
1164    /// 
1165    pub fn into(self) -> R {
1166        self.ring
1167    }
1168}
1169
1170impl<R: RingBase> RingStore for RingValue<R> {
1171
1172    type Type = R;
1173    
1174    fn get_ring(&self) -> &R {
1175        &self.ring
1176    }
1177}
1178
1179impl<R: RingBase + Default> Default for RingValue<R> {
1180    
1181    fn default() -> Self {
1182        Self::from(R::default())
1183    }
1184}
1185
1186///
1187/// The second most basic [`crate::ring::RingStore`]. Similarly to 
1188/// [`crate::ring::RingValue`] it is just a no-op container.
1189/// 
1190/// # Why do we need this in addition to [`crate::ring::RingValue`]?
1191/// 
1192/// Before [`RingValue::from_ref()`] was added, this was important to
1193/// allow using a reference to a [`RingBase`] as [`RingStore`]. Since then,
1194/// it indeed has only a marginal importance, but note that it is currently
1195/// the only way of working with unsized rings (an admittedly pretty exotic
1196/// case).
1197/// 
1198#[repr(transparent)]
1199#[derive(Debug)]
1200pub struct RingRef<'a, R: RingBase + ?Sized> {
1201    ring: &'a R
1202}
1203
1204impl<'a, R: RingBase + ?Sized> Clone for RingRef<'a, R> {
1205
1206    fn clone(&self) -> Self {
1207        *self
1208    }
1209}
1210
1211impl<'a, R: RingBase + ?Sized> Copy for RingRef<'a, R> {}
1212
1213impl<'a, R: RingBase + ?Sized> RingRef<'a, R> {
1214
1215    ///
1216    /// Creates a new [`RingRef`] from a reference to a [`RingBase`].
1217    /// 
1218    pub const fn new(value: &'a R) -> Self {
1219        RingRef { ring: value }
1220    }
1221
1222    ///
1223    /// Returns the stored reference to the [`RingBase`].
1224    /// 
1225    /// This is almost the same as [`RingStore::get_ring()`], except for
1226    /// that the lifetime of the returned reference is not bounded to the
1227    /// lifetime of the [`RingRef`].
1228    /// 
1229    pub fn into(self) -> &'a R {
1230        self.ring
1231    }
1232}
1233
1234impl<'a, R: RingBase + ?Sized> RingStore for RingRef<'a, R> {
1235
1236    type Type = R;
1237    
1238    fn get_ring(&self) -> &R {
1239        self.ring
1240    }
1241}
1242
1243impl<'a, S: Deref> RingStore for S
1244    where S::Target: RingStore
1245{    
1246    type Type = <<S as Deref>::Target as RingStore>::Type;
1247    
1248    fn get_ring<'b>(&'b self) -> &'b Self::Type {
1249        (**self).get_ring()
1250    }
1251}
1252
1253#[cfg(test)]
1254use std::rc::Rc;
1255#[cfg(test)]
1256use crate::impl_eq_based_self_iso;
1257
1258#[test]
1259fn test_ring_rc_lifetimes() {
1260    let ring = Rc::new(StaticRing::<i32>::RING);
1261    let mut ring_ref = None;
1262    assert!(ring_ref.is_none());
1263    {
1264        ring_ref = Some(ring.get_ring());
1265    }
1266    assert!(ring.get_ring().is_commutative());
1267    assert!(ring_ref.is_some());
1268}
1269
1270#[test]
1271fn test_internal_wrappings_dont_matter() {
1272    
1273    #[derive(Clone, PartialEq)]
1274    pub struct ABase;
1275
1276    #[allow(unused)]
1277    #[derive(Clone)]
1278    pub struct BBase<R: RingStore> {
1279        base: R
1280    }
1281
1282    impl<R: RingStore> PartialEq for BBase<R> {
1283        fn eq(&self, other: &Self) -> bool {
1284            self.base.get_ring() == other.base.get_ring()
1285        }
1286    }
1287
1288    impl RingBase for ABase {
1289        type Element = i32;
1290
1291        fn clone_el(&self, val: &Self::Element) -> Self::Element {
1292            *val
1293        }
1294
1295        fn add_assign(&self, lhs: &mut Self::Element, rhs: Self::Element) {
1296            *lhs += rhs;
1297        }
1298
1299        fn negate_inplace(&self, lhs: &mut Self::Element) {
1300            *lhs = -*lhs;
1301        }
1302
1303        fn eq_el(&self, lhs: &Self::Element, rhs: &Self::Element) -> bool {
1304            *lhs == *rhs
1305        }
1306
1307        fn is_commutative(&self) -> bool {
1308            true
1309        }
1310
1311        fn is_noetherian(&self) -> bool {
1312            true
1313        }
1314
1315        fn from_int(&self, value: i32) -> Self::Element {
1316            value
1317        }
1318
1319        fn mul_assign(&self, lhs: &mut Self::Element, rhs: Self::Element) {
1320            *lhs *= rhs;
1321        }
1322
1323        fn dbg_within<'a>(&self, _: &Self::Element, _: &mut std::fmt::Formatter<'a>, _: EnvBindingStrength) -> std::fmt::Result {
1324            Ok(())
1325        }
1326
1327        fn characteristic<I: RingStore + Copy>(&self, ZZ: I) -> Option<El<I>>
1328                where I::Type: IntegerRing
1329        {
1330            Some(ZZ.zero())
1331        }
1332
1333        fn is_approximate(&self) -> bool { false }
1334    }
1335
1336    impl_eq_based_self_iso!{ ABase }
1337
1338    impl<R: RingStore> RingBase for BBase<R> {
1339        type Element = i32;
1340
1341        fn clone_el(&self, val: &Self::Element) -> Self::Element {
1342            *val
1343        }
1344
1345        fn add_assign(&self, lhs: &mut Self::Element, rhs: Self::Element) {
1346            *lhs += rhs;
1347        }
1348        fn negate_inplace(&self, lhs: &mut Self::Element) {
1349            *lhs = -*lhs;
1350        }
1351
1352        fn eq_el(&self, lhs: &Self::Element, rhs: &Self::Element) -> bool {
1353            *lhs == *rhs
1354        }
1355
1356        fn is_commutative(&self) -> bool {
1357            true
1358        }
1359
1360        fn is_noetherian(&self) -> bool {
1361            true
1362        }
1363
1364        fn from_int(&self, value: i32) -> Self::Element {
1365            value
1366        }
1367
1368        fn mul_assign(&self, lhs: &mut Self::Element, rhs: Self::Element) {
1369            *lhs *= rhs;
1370        }
1371
1372        fn dbg_within<'a>(&self, _: &Self::Element, _: &mut std::fmt::Formatter<'a>, _: EnvBindingStrength) -> std::fmt::Result {
1373            Ok(())
1374        }
1375        
1376        fn characteristic<I: RingStore + Copy>(&self, ZZ: I) -> Option<El<I>>
1377                where I::Type: IntegerRing
1378        {
1379            Some(ZZ.zero())
1380        }
1381
1382        fn is_approximate(&self) -> bool { false }
1383    }
1384
1385    impl<R: RingStore> CanHomFrom<ABase> for BBase<R> {
1386
1387        type Homomorphism = ();
1388
1389        fn has_canonical_hom(&self, _: &ABase) -> Option<()> {
1390            Some(())
1391        }
1392
1393        fn map_in(&self, _: &ABase, el: <ABase as RingBase>::Element, _: &()) -> Self::Element {
1394            el
1395        }
1396    }
1397
1398    impl<R: RingStore, S: RingStore> CanHomFrom<BBase<S>> for BBase<R> 
1399        where R::Type: CanHomFrom<S::Type>
1400    {
1401        type Homomorphism = ();
1402
1403        fn has_canonical_hom(&self, _: &BBase<S>) -> Option<()> {
1404            Some(())
1405        }
1406
1407        fn map_in(&self, _: &BBase<S>, el: <BBase<S> as RingBase>::Element, _: &()) -> Self::Element {
1408            el
1409        }
1410    }
1411
1412    impl<R: RingStore> CanIsoFromTo<BBase<R>> for BBase<R> 
1413        where R::Type: CanHomFrom<R::Type>
1414    {
1415        type Isomorphism = ();
1416
1417        fn has_canonical_iso(&self, _: &BBase<R>) -> Option<()> {
1418            Some(())
1419        }
1420
1421        fn map_out(&self, _: &BBase<R>, el: <BBase<R> as RingBase>::Element, _: &()) -> Self::Element {
1422            el
1423        }
1424    }
1425
1426    type A = RingValue<ABase>;
1427    type B<R> = RingValue<BBase<R>>;
1428
1429    let a: A = RingValue { ring: ABase };
1430    let b1: B<A> = RingValue { ring: BBase { base: a.clone() } };
1431    let b2: B<&B<A>> = RingValue { ring: BBase { base: &b1 } };
1432    let b3: B<&A> = RingValue { ring: BBase { base: &a } };
1433    _ = b1.coerce(&a, 0);
1434    _ = b2.coerce(&a, 0);
1435    _ = b2.coerce(&b1, 0);
1436    _ = b2.coerce(&b3, 0);
1437    _ = (&b2).coerce(&b3, 0);
1438    _ = (&b2).coerce(&&&b3, 0);
1439}
1440
1441#[allow(missing_docs)]
1442#[cfg(any(test, feature = "generic_tests"))]
1443pub mod generic_tests {
1444
1445    use crate::integer::{int_cast, BigIntRing};
1446    use std::cmp::min;
1447
1448    use super::*;
1449
1450    pub fn test_hom_axioms<R: RingStore, S: RingStore, I: Iterator<Item = El<R>>>(from: R, to: S, edge_case_elements: I)
1451        where S::Type: CanHomFrom<R::Type>
1452    {
1453        let hom = to.can_hom(&from).unwrap();
1454        crate::homomorphism::generic_tests::test_homomorphism_axioms(hom, edge_case_elements);
1455    }
1456
1457    pub fn test_iso_axioms<R: RingStore, S: RingStore, I: Iterator<Item = El<R>>>(from: R, to: S, edge_case_elements: I)
1458        where S::Type: CanIsoFromTo<R::Type>
1459    {
1460        let hom = to.get_ring().has_canonical_hom(from.get_ring()).unwrap();
1461        let iso = to.get_ring().has_canonical_iso(from.get_ring()).unwrap();
1462        let elements = edge_case_elements.collect::<Vec<_>>();
1463
1464        for a in &elements {
1465            let map_in = to.get_ring().map_in_ref(from.get_ring(), a, &hom);
1466            let map_in_out = to.get_ring().map_out(from.get_ring(), to.clone_el(&map_in), &iso);
1467            assert!(from.eq_el(&map_in_out, &a), "Bijectivity failed: {} != {} = hom^-1({}) = hom^-1(hom({}))", from.format(a), from.format(&map_in_out), to.format(&map_in), from.format(a));
1468        }
1469    }
1470
1471    pub fn test_self_iso<R: RingStore, I: Iterator<Item = El<R>>>(ring: R, edge_case_elements: I)
1472        where R::Type: SelfIso
1473    {
1474        let hom = ring.get_ring().has_canonical_hom(ring.get_ring()).unwrap();
1475        let iso = ring.get_ring().has_canonical_iso(ring.get_ring()).unwrap();
1476        let elements = edge_case_elements.collect::<Vec<_>>();
1477
1478        test_hom_axioms(&ring, &ring, elements.iter().map(|x| ring.clone_el(x)));
1479        test_iso_axioms(&ring, &ring, elements.iter().map(|x| ring.clone_el(x)));
1480
1481        for a in &elements {
1482            assert_el_eq!(ring, a, ring.get_ring().map_in_ref(ring.get_ring(), a, &hom));
1483            assert_el_eq!(ring, a, ring.get_ring().map_out(ring.get_ring(), ring.clone_el(a), &iso));
1484        }
1485    }
1486
1487    pub fn test_hash_axioms<R: RingStore, I: Iterator<Item = El<R>>>(ring: R, edge_case_elements: I)
1488        where R::Type: HashableElRing
1489    {
1490        let elements = edge_case_elements.collect::<Vec<_>>();
1491
1492        // technically not required, but we should test hash inequality and this really should be true
1493        assert_ne!(ring.default_hash(&ring.one()), ring.default_hash(&ring.zero()));
1494
1495        for a in &elements {
1496            for b in &elements {
1497                assert!(!ring.eq_el(a, b) || ring.default_hash(a) == ring.default_hash(b));
1498            }
1499        }
1500
1501        for a in &elements {
1502            for b in &elements {
1503                let expr = ring.sub(ring.mul_ref_fst(a, ring.add_ref_fst(b, ring.one())), ring.mul_ref(a, b));
1504                assert!(ring.default_hash(a) == ring.default_hash(&expr));
1505            }
1506        }
1507    }
1508
1509    pub fn test_ring_axioms<R: RingStore, I: Iterator<Item = El<R>>>(ring: R, edge_case_elements: I) {
1510        let elements = edge_case_elements.collect::<Vec<_>>();
1511        let zero = ring.zero();
1512        let one = ring.one();
1513
1514        assert!(ring.is_zero(&zero));
1515        assert!(ring.is_one(&one));
1516        assert!(ring.is_neg_one(&ring.neg_one()));
1517        assert!(ring.eq_el(&ring.neg_one(), &ring.get_ring().from_int(-1)));
1518        assert!(ring.eq_el(&zero, &ring.get_ring().from_int(0)));
1519        assert!(ring.eq_el(&one, &ring.get_ring().from_int(1)));
1520
1521        // check self-subtraction
1522        for a in &elements {
1523            let a_minus_a = ring.sub(ring.clone_el(a), ring.clone_el(a));
1524            assert!(ring.eq_el(&zero, &a_minus_a), "Additive inverse failed: {} - {} = {} != {}", ring.format_within(a, EnvBindingStrength::Sum), ring.format_within(a, EnvBindingStrength::Product), ring.format(&a_minus_a), ring.format(&zero));
1525        }
1526
1527        // check identity elements
1528        for a in &elements {
1529            let a_plus_zero = ring.add(ring.clone_el(a), ring.clone_el(&zero));
1530            assert!(ring.eq_el(a, &a_plus_zero), "Additive neutral element failed: {} + {} = {} != {}", ring.format_within(a, EnvBindingStrength::Sum), ring.format(&zero), ring.format(&a_plus_zero), ring.format(a));
1531            
1532            let a_times_one = ring.mul(ring.clone_el(a), ring.clone_el(&one));
1533            assert!(ring.eq_el(a, &a_times_one), "Multiplicative neutral element failed: {} * {} = {} != {}", ring.format_within(a, EnvBindingStrength::Product), ring.format(&one), ring.format(&a_times_one), ring.format(a));
1534        }
1535
1536        // check commutativity
1537        for a in &elements {
1538            for b in &elements {
1539                {
1540                    let ab = ring.add_ref(a, b);
1541                    let ba = ring.add_ref(b, a);
1542                    assert!(ring.eq_el(&ab, &ba), "Additive commutativity failed: {} + {} = {} != {} = {} + {}", ring.format_within(a, EnvBindingStrength::Sum), ring.format_within(b, EnvBindingStrength::Sum), ring.format(&ab), ring.format(&ba), ring.format_within(b, EnvBindingStrength::Sum), ring.format_within(a, EnvBindingStrength::Sum));
1543                }
1544
1545                if ring.is_commutative() {
1546                    let ab = ring.mul_ref(a, b);
1547                    let ba = ring.mul_ref(b, a);
1548                    assert!(ring.eq_el(&ab, &ba), "Multiplicative commutativity failed: {} * {} = {} != {} = {} * {}", ring.format_within(a, EnvBindingStrength::Product), ring.format_within(b, EnvBindingStrength::Product), ring.format(&ab), ring.format(&ba), ring.format_within(b, EnvBindingStrength::Product), ring.format_within(a, EnvBindingStrength::Product));
1549                }
1550            }
1551        }
1552
1553        // check associativity
1554        for a in &elements {
1555            for b in &elements {
1556                for c in &elements {
1557                    {
1558                        let ab_c = ring.add_ref_snd(ring.add_ref(a, b), c);
1559                        let a_bc = ring.add_ref_fst(c, ring.add_ref(b, a));
1560                        assert!(ring.eq_el(&ab_c, &a_bc), "Additive associativity failed: ({} + {}) + {} = {} != {} = {} + ({} + {})", ring.format_within(a, EnvBindingStrength::Sum), ring.format_within(b, EnvBindingStrength::Sum), ring.format_within(c, EnvBindingStrength::Sum), ring.format(&ab_c), ring.format(&a_bc), ring.format_within(a, EnvBindingStrength::Sum), ring.format_within(b, EnvBindingStrength::Sum), ring.format_within(c, EnvBindingStrength::Sum));
1561                    }
1562                    {
1563                        let ab_c = ring.mul_ref_snd(ring.mul_ref(a, b), c);
1564                        let a_bc = ring.mul_ref_fst(c, ring.mul_ref(b, a));
1565                        assert!(ring.eq_el(&ab_c, &a_bc), "Multiplicative associativity failed: ({} * {}) * {} = {} != {} = {} * ({} * {})", ring.format_within(a, EnvBindingStrength::Sum), ring.format_within(b, EnvBindingStrength::Sum), ring.format_within(c, EnvBindingStrength::Sum), ring.format(&ab_c), ring.format(&a_bc), ring.format_within(a, EnvBindingStrength::Sum), ring.format_within(b, EnvBindingStrength::Sum), ring.format_within(c, EnvBindingStrength::Sum));
1566                    }
1567                }
1568            }
1569        }
1570        
1571        // check distributivity
1572        for a in &elements {
1573            for b in &elements {
1574                for c in &elements {
1575                    let ab_c = ring.mul_ref_snd(ring.add_ref(a, b), c);
1576                    let ac_bc = ring.add(ring.mul_ref(a, c), ring.mul_ref(b, c));
1577                    assert!(ring.eq_el(&ab_c, &ac_bc), "Distributivity failed: ({} + {}) * {} = {} != {} = {} * {} + {} * {}", ring.format_within(a, EnvBindingStrength::Product), ring.format_within(b, EnvBindingStrength::Sum), ring.format_within(c, EnvBindingStrength::Sum), ring.format(&ab_c), ring.format(&ac_bc), ring.format_within(a, EnvBindingStrength::Product), ring.format_within(c, EnvBindingStrength::Product), ring.format_within(b, EnvBindingStrength::Product), ring.format_within(c, EnvBindingStrength::Product));
1578
1579                    let a_bc = ring.mul_ref_fst(a, ring.add_ref(b, c));
1580                    let ab_ac = ring.add(ring.mul_ref(a, b), ring.mul_ref(a, c));
1581                    assert!(ring.eq_el(&a_bc, &ab_ac), "Distributivity failed: {} * ({} + {}) = {} != {} = {} * {} + {} * {}", ring.format_within(a, EnvBindingStrength::Product), ring.format_within(b, EnvBindingStrength::Sum), ring.format_within(c, EnvBindingStrength::Sum), ring.format(&a_bc), ring.format(&ab_ac), ring.format_within(a, EnvBindingStrength::Product), ring.format_within(b, EnvBindingStrength::Product), ring.format_within(a, EnvBindingStrength::Product), ring.format_within(c, EnvBindingStrength::Product));
1582                }
1583            }
1584        }
1585
1586        // check fma
1587        for a in &elements {
1588            for b in &elements {
1589                for c in &elements {
1590                    let actual = ring.fma(a, b, ring.clone_el(c));
1591                    let expected = ring.add(ring.mul_ref(a, b), ring.clone_el(c));
1592                    assert!(ring.eq_el(&expected, &actual), "FMA failed: fma({}, {}, {}) = {} != {} = ({} * {}) + {}", ring.format(a), ring.format(b), ring.format(c), ring.format(&actual), ring.format(&expected), ring.format_within(a, EnvBindingStrength::Product), ring.format_within(b, EnvBindingStrength::Product), ring.format_within(c, EnvBindingStrength::Sum));
1593                }
1594
1595                let actual = ring.get_ring().fma_int(a, 2, ring.clone_el(b));
1596                let expected = ring.get_ring().add(ring.get_ring().add_ref(a, a), ring.clone_el(b));
1597                assert!(ring.eq_el(&expected, &actual), "Int-FMA failed: int-fma({}, 2, {}) = {} != {} = ({} * 2) + {}", ring.format(a), ring.format(b), ring.format(&actual), ring.format(&expected), ring.format_within(a, EnvBindingStrength::Product), ring.format_within(b, EnvBindingStrength::Sum));
1598            }
1599        }
1600
1601        // check powering
1602        for a in &elements {
1603            for n in [0, 1, 2, 3, 7, 8] {
1604                let expected = (0..n).map(|_| a).fold(ring.one(), |x, y| ring.mul_ref_snd(x, y));
1605                let actual = ring.pow(ring.clone_el(a), n);
1606                assert!(ring.eq_el(&expected, &actual), "Powering failed: {} * ... * {} = {} != {} = {}^{}", ring.format_within(a, EnvBindingStrength::Product), ring.format_within(a, EnvBindingStrength::Product), ring.format(&expected), ring.format(&actual), ring.format_within(a, EnvBindingStrength::Power), n);
1607            }
1608        }
1609        
1610        // check characteristic
1611        let ZZbig = BigIntRing::RING;
1612        let char = ring.characteristic(&ZZbig).unwrap();
1613        
1614        if ZZbig.is_geq(&char, &ZZbig.power_of_two(7)) {
1615            assert_eq!(None, ring.characteristic(&StaticRing::<i8>::RING));
1616        }
1617        if ZZbig.is_geq(&char, &ZZbig.power_of_two(15)) {
1618            assert_eq!(None, ring.characteristic(&StaticRing::<i16>::RING));
1619        }
1620        if ZZbig.is_geq(&char, &ZZbig.power_of_two(31)) {
1621            assert_eq!(None, ring.characteristic(&StaticRing::<i32>::RING));
1622        }
1623        if ZZbig.is_geq(&char, &ZZbig.power_of_two(63)) {
1624            assert_eq!(None, ring.characteristic(&StaticRing::<i64>::RING));
1625        }
1626        if ZZbig.is_geq(&char, &ZZbig.power_of_two(127)) {
1627            assert_eq!(None, ring.characteristic(&StaticRing::<i128>::RING));
1628        }
1629        if ZZbig.is_lt(&char, &ZZbig.power_of_two(31)) {
1630            let char = int_cast(char, &StaticRing::<i32>::RING, &ZZbig);
1631
1632            assert_el_eq!(ring, ring.zero(), ring.get_ring().from_int(char));
1633            
1634            if char == 0 {
1635                for i in 1..(1 << 10) {
1636                    assert!(!ring.is_zero(&ring.get_ring().from_int(i)));
1637                }
1638            } else {
1639                for i in 1..min(1 << 10, char) {
1640                    assert!(!ring.is_zero(&ring.get_ring().from_int(i)));
1641                }
1642            }
1643        }
1644
1645    }
1646}
1647
1648#[test]
1649fn test_environment_binding() {
1650    assert!(EnvBindingStrength::Strongest > EnvBindingStrength::Power);
1651    assert!(EnvBindingStrength::Power > EnvBindingStrength::Product);
1652    assert!(EnvBindingStrength::Product > EnvBindingStrength::Sum);
1653    assert!(EnvBindingStrength::Sum > EnvBindingStrength::Weakest);
1654}