feanor_math/
specialization.rs1use std::alloc::Allocator;
2use std::marker::PhantomData;
3
4use crate::algorithms::convolution::ConvolutionAlgorithm;
5use crate::integer::*;
6use crate::primitive_int::PrimitiveInt;
7use crate::primitive_int::StaticRingBase;
8use crate::ring::*;
9use crate::rings::extension::extension_impl::*;
10use crate::rings::finite::*;
11use crate::rings::rational::*;
12use crate::rings::rust_bigint::RustBigintRingBase;
13use crate::seq::*;
14use crate::rings::zn::*;
15
16#[stability::unstable(feature = "enable")]
23pub trait FiniteRingOperation<R>
24 where R: ?Sized
25{
26 type Output;
27
28 fn execute(self) -> Self::Output
32 where R: FiniteRing;
33}
34
35#[stability::unstable(feature = "enable")]
42pub trait FiniteRingSpecializable: RingBase {
43
44 fn specialize<O: FiniteRingOperation<Self>>(op: O) -> Result<O::Output, ()>;
45
46 fn is_finite_ring() -> bool {
47 struct CheckIsFinite;
48 impl<R: ?Sized + RingBase> FiniteRingOperation<R> for CheckIsFinite {
49 type Output = ();
50 fn execute(self) -> Self::Output
51 where R: FiniteRing { () }
52 }
53 return Self::specialize(CheckIsFinite).is_ok();
54 }
55}
56
57impl<I> FiniteRingSpecializable for RationalFieldBase<I>
58 where I: RingStore,
59 I::Type: IntegerRing
60{
61 fn specialize<O: FiniteRingOperation<Self>>(_op: O) -> Result<O::Output, ()> {
62 Err(())
63 }
64}
65
66impl<A> FiniteRingSpecializable for RustBigintRingBase<A>
67 where A: Allocator + Clone
68{
69 fn specialize<O: FiniteRingOperation<Self>>(_op: O) -> Result<O::Output, ()> {
70 Err(())
71 }
72}
73
74impl<T> FiniteRingSpecializable for StaticRingBase<T>
75 where T: PrimitiveInt
76{
77 fn specialize<O: FiniteRingOperation<Self>>(_op: O) -> Result<O::Output, ()> {
78 Err(())
79 }
80}
81
82impl FiniteRingSpecializable for zn_64::ZnBase {
83 fn specialize<O: FiniteRingOperation<Self>>(op: O) -> Result<O::Output, ()> {
84 Ok(op.execute())
85 }
86}
87
88impl<R, V, A, C> FiniteRingSpecializable for FreeAlgebraImplBase<R, V, A, C>
89 where R: RingStore,
90 R::Type: FiniteRingSpecializable,
91 V: VectorView<El<R>>,
92 A: Allocator + Clone,
93 C: ConvolutionAlgorithm<R::Type>
94{
95 fn specialize<O: FiniteRingOperation<Self>>(op: O) -> Result<O::Output, ()> {
96 struct OpWrapper<R, V, A, C, O>
97 where R: RingStore,
98 R::Type: FiniteRingSpecializable,
99 V: VectorView<El<R>>,
100 A: Allocator + Clone,
101 C: ConvolutionAlgorithm<R::Type>,
102 O: FiniteRingOperation<FreeAlgebraImplBase<R, V, A, C>>
103 {
104 operation: O,
105 ring: PhantomData<FreeAlgebraImpl<R, V, A, C>>
106 }
107
108 impl<R, V, A, C, O> FiniteRingOperation<R::Type> for OpWrapper<R, V, A, C, O>
109 where R: RingStore,
110 R::Type: FiniteRingSpecializable,
111 V: VectorView<El<R>>,
112 A: Allocator + Clone,
113 C: ConvolutionAlgorithm<R::Type>,
114 O: FiniteRingOperation<FreeAlgebraImplBase<R, V, A, C>>
115 {
116 type Output = O::Output;
117 fn execute(self) -> Self::Output where R::Type:FiniteRing {
118 self.operation.execute()
119 }
120 }
121
122 <R::Type as FiniteRingSpecializable>::specialize(OpWrapper { operation: op, ring: PhantomData })
123 }
124}
125
126#[cfg(test)]
127use crate::homomorphism::*;
128#[cfg(test)]
129use crate::rings::field::*;
130#[cfg(test)]
131use crate::rings::extension::galois_field::*;
132#[cfg(test)]
133use crate::rings::extension::*;
134
135#[test]
136fn test_specialize_finite_field() {
137
138 struct Verify<'a, R>(&'a R, i32)
139 where R: ?Sized + RingBase;
140
141 impl<'a, R: ?Sized> FiniteRingOperation<R> for Verify<'a, R>
142 where R: RingBase
143 {
144 type Output = ();
145
146 fn execute(self)
147 where R: FiniteRing
148 {
149 assert_el_eq!(BigIntRing::RING, BigIntRing::RING.int_hom().map(self.1), self.0.size(&BigIntRing::RING).unwrap());
150 }
151 }
152
153 let ring = zn_64::Zn::new(7).as_field().ok().unwrap();
154 assert!(<AsFieldBase<zn_64::Zn>>::specialize(Verify(ring.get_ring(), 7)).is_ok());
155
156 let ring = GaloisField::new(3, 2);
157 assert!(GaloisFieldBase::specialize(Verify(ring.get_ring(), 9)).is_ok());
158
159 let ring = GaloisField::new(3, 2).into().unwrap_self();
160 assert!(<AsFieldBase<FreeAlgebraImpl<_, _, _, _>>>::specialize(Verify(ring.get_ring(), 9)).is_ok());
161
162 let ring = RationalField::new(BigIntRing::RING);
163 assert!(<RationalFieldBase<_>>::specialize(Verify(ring.get_ring(), 0)).is_err());
164
165 let QQ = RationalField::new(BigIntRing::RING);
166 let ring = FreeAlgebraImpl::new(&QQ, 2, [QQ.neg_one()]).as_field().ok().unwrap();
167 assert!(<AsFieldBase<FreeAlgebraImpl<_, _, _, _>>>::specialize(Verify(ring.get_ring(), 0)).is_err());
168
169 let base_ring = GaloisField::new(3, 2).into().unwrap_self();
170 let ring = FreeAlgebraImpl::new(&base_ring, 3, [base_ring.neg_one(), base_ring.one()]).as_field().ok().unwrap();
171 assert!(<AsFieldBase<FreeAlgebraImpl<_, _, _, _>>>::specialize(Verify(ring.get_ring(), 729)).is_ok());
172}