feanor_math::delegate

Trait DelegateRing

Source
pub trait DelegateRing: PartialEq {
    type Base: ?Sized + RingBase;
    type Element;

    // Required methods
    fn get_delegate(&self) -> &Self::Base;
    fn delegate_ref<'a>(
        &self,
        el: &'a Self::Element,
    ) -> &'a <Self::Base as RingBase>::Element;
    fn delegate_mut<'a>(
        &self,
        el: &'a mut Self::Element,
    ) -> &'a mut <Self::Base as RingBase>::Element;
    fn delegate(&self, el: Self::Element) -> <Self::Base as RingBase>::Element;
    fn rev_delegate(
        &self,
        el: <Self::Base as RingBase>::Element,
    ) -> Self::Element;

    // Provided methods
    fn postprocess_delegate_mut(&self, el: &mut Self::Element) { ... }
    fn element_cast(&self, el: Self::Element) -> <Self as RingBase>::Element { ... }
    fn rev_element_cast(&self, el: <Self as RingBase>::Element) -> Self::Element { ... }
    fn rev_element_cast_ref<'a>(
        &self,
        el: &'a <Self as RingBase>::Element,
    ) -> &'a Self::Element { ... }
}
Expand description

Trait to simplify implementing newtype-pattern for rings. When you want to create a ring that just wraps another ring, possibly adding some functionality, you can implement DelegateRing instead of RingBase, and just provide how to map elements in the new ring to the wrapped ring and vice versa.

§Conditional Implementations

Some special ring traits (e.g. DivisibilityRing) are immediately implemented for R: DelegateRing as soon as R::Base: SpecialRingTrait. However, this of course prevents any implementation fo DelegateRing to provide a custom implementation (except for specialization in some cases), due to conflicting trait impls. Hence, for other traits, we use marker traits to mark an implementation R of DelegateRing to also automatically implement a special ring trait as soon as R::Base: SpecialRingTrait. These cases are currently

§Example

 
#[derive(PartialEq, Clone)]
struct MyI32Ring;
struct MyI32RingEl(i32);
 
impl DelegateRing for MyI32Ring {
 
    type Base = StaticRingBase<i32>;
    type Element = MyI32RingEl;
 
    fn get_delegate(&self) -> &Self::Base {
        StaticRing::<i32>::RING.get_ring()
    }
 
    fn delegate_ref<'a>(&self, MyI32RingEl(el): &'a MyI32RingEl) -> &'a i32 {
        el
    }
 
    fn delegate_mut<'a>(&self, MyI32RingEl(el): &'a mut MyI32RingEl) -> &'a mut i32 {
        el
    }
 
    fn delegate(&self, MyI32RingEl(el): MyI32RingEl) -> i32 {
        el
    }
 
    fn postprocess_delegate_mut(&self, _: &mut MyI32RingEl) {
        // sometimes it might be necessary to fix some data of `Self::Element`
        // if the underlying `Self::Base::Element` was modified via `delegate_mut()`;
        // this is not the case here, so leave empty
    }
 
    fn rev_delegate(&self, el: i32) -> MyI32RingEl {
        MyI32RingEl(el)
    }
}
 
// you will have to implement `CanIsoFromTo<Self>`
impl_eq_based_self_iso!{ MyI32Ring }
 
let ring = RingValue::from(MyI32Ring);
assert_el_eq!(ring, ring.int_hom().map(1), ring.one());

An example when special ring traits are automatically implemented is given by the following.

 
struct BoringRingWrapper<R>(R);
 
impl<R> PartialEq for BoringRingWrapper<R>
    where R: RingStore
{
    fn eq(&self, other: &Self) -> bool {
        self.0.get_ring() == other.0.get_ring()
    }
}
 
impl<R> DelegateRing for BoringRingWrapper<R>
    where R: RingStore
{
    type Base = R::Type;
    type Element = El<R>;
 
    fn get_delegate(&self) -> &Self::Base {
        self.0.get_ring()
    }
 
    fn delegate(&self, el: Self::Element) -> <Self::Base as RingBase>::Element { el }
    fn delegate_mut<'a>(&self, el: &'a mut Self::Element) -> &'a mut <Self::Base as RingBase>::Element { el }
    fn delegate_ref<'a>(&self, el: &'a Self::Element) -> &'a <Self::Base as RingBase>::Element { el }
    fn rev_delegate(&self, el: <Self::Base as RingBase>::Element) -> Self::Element { el }
}

DivisibilityRing is automatically implemented (but can be specialized):

fn divide_in_wrapped_ring<R>(base_ring: R)
    where R: RingStore,
        R::Type: DivisibilityRing
{
    let wrapped_ring = BoringRingWrapper(base_ring);
    assert!(wrapped_ring.checked_div(&wrapped_ring.one(), &wrapped_ring.one()).is_some());
}

FiniteRing for example is not automatically implemented:

fn size_of_wrapped_ring<R>(base_ring: R)
    where R: RingStore,
        R::Type: FiniteRing
{
    let wrapped_ring = BoringRingWrapper(base_ring);
    assert!(wrapped_ring.size(BigIntRing::RING).is_some());
}

But we can add a delegate-implementation of FiniteRing by adding the marker trait DelegateRingImplFiniteRing:

impl<R> DelegateRingImplFiniteRing for BoringRingWrapper<R>
    where R: RingStore
{}
 
fn size_of_wrapped_ring<R>(base_ring: R)
    where R: RingStore,
        R::Type: FiniteRing
{
    let wrapped_ring = BoringRingWrapper(base_ring);
    assert!(wrapped_ring.size(BigIntRing::RING).is_some());
}

Required Associated Types§

Required Methods§

Source

fn get_delegate(&self) -> &Self::Base

Source

fn delegate_ref<'a>( &self, el: &'a Self::Element, ) -> &'a <Self::Base as RingBase>::Element

Source

fn delegate_mut<'a>( &self, el: &'a mut Self::Element, ) -> &'a mut <Self::Base as RingBase>::Element

Source

fn delegate(&self, el: Self::Element) -> <Self::Base as RingBase>::Element

Source

fn rev_delegate(&self, el: <Self::Base as RingBase>::Element) -> Self::Element

Provided Methods§

Source

fn postprocess_delegate_mut(&self, el: &mut Self::Element)

Source

fn element_cast(&self, el: Self::Element) -> <Self as RingBase>::Element

Necessary in some locations to satisfy the type system

Source

fn rev_element_cast(&self, el: <Self as RingBase>::Element) -> Self::Element

Necessary in some locations to satisfy the type system

Source

fn rev_element_cast_ref<'a>( &self, el: &'a <Self as RingBase>::Element, ) -> &'a Self::Element

Necessary in some locations to satisfy the type system

Dyn Compatibility§

This trait is not dyn compatible.

In older versions of Rust, dyn compatibility was called "object safety", so this trait is not object safe.

Implementors§