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