1
2use crate::algorithms::miller_rabin::prev_prime;
3use crate::divisibility::{DivisibilityRing, Domain};
4use crate::homomorphism::*;
5use crate::integer::{IntegerRing, IntegerRingStore};
6use crate::pid::PrincipalIdealRing;
7use crate::primitive_int::StaticRing;
8use crate::ring::*;
9use crate::rings::field::{AsField, AsFieldBase};
10use crate::rings::zn::{zn_64, zn_rns, ZnRingStore};
11use crate::seq::VectorView;
12
13#[stability::unstable(feature = "enable")]
22pub trait InterpolationBaseRing: DivisibilityRing {
23
24 type ExtendedRingBase<'a>: ?Sized + DivisibilityRing + PrincipalIdealRing + Domain
30 where Self: 'a;
31
32 type ExtendedRing<'a>: RingStore<Type = Self::ExtendedRingBase<'a>> + Clone
33 where Self: 'a;
34
35 fn in_base<'a, S>(&self, ext_ring: S, el: El<S>) -> Option<Self::Element>
36 where Self: 'a, S: RingStore<Type = Self::ExtendedRingBase<'a>>;
37
38 fn in_extension<'a, S>(&self, ext_ring: S, el: Self::Element) -> El<S>
39 where Self: 'a, S: RingStore<Type = Self::ExtendedRingBase<'a>>;
40
41 fn interpolation_points<'a>(&'a self, count: usize) -> (Self::ExtendedRing<'a>, Vec<El<Self::ExtendedRing<'a>>>);
48}
49
50#[stability::unstable(feature = "enable")]
54pub trait InterpolationBaseRingStore: RingStore
55 where Self::Type: InterpolationBaseRing
56{}
57
58impl<R> InterpolationBaseRingStore for R
59 where R: RingStore, R::Type: InterpolationBaseRing
60{}
61
62#[stability::unstable(feature = "enable")]
67pub struct ToExtRingMap<'a, R>
68 where R: ?Sized + InterpolationBaseRing
69{
70 ring: RingRef<'a, R>,
71 ext_ring: R::ExtendedRing<'a>
72}
73
74impl<'a, R> ToExtRingMap<'a, R>
75 where R: ?Sized + InterpolationBaseRing
76{
77 #[stability::unstable(feature = "enable")]
78 pub fn for_interpolation(ring: &'a R, point_count: usize) -> (Self, Vec<El<R::ExtendedRing<'a>>>) {
79 let (ext_ring, points) = ring.interpolation_points(point_count);
80 return (Self { ring: RingRef::new(ring), ext_ring: ext_ring }, points);
81 }
82
83 #[stability::unstable(feature = "enable")]
84 pub fn as_base_ring_el(&self, el: El<R::ExtendedRing<'a>>) -> R::Element {
85 self.ring.get_ring().in_base(&self.ext_ring, el).unwrap()
86 }
87}
88
89impl<'a, R> Homomorphism<R, R::ExtendedRingBase<'a>> for ToExtRingMap<'a, R>
90 where R: ?Sized + InterpolationBaseRing
91{
92 type CodomainStore = R::ExtendedRing<'a>;
93 type DomainStore = RingRef<'a, R>;
94
95 fn codomain<'b>(&'b self) -> &'b Self::CodomainStore {
96 &self.ext_ring
97 }
98
99 fn domain<'b>(&'b self) -> &'b Self::DomainStore {
100 &self.ring
101 }
102
103 fn map(&self, x: <R as RingBase>::Element) -> <R::ExtendedRingBase<'a> as RingBase>::Element {
104 self.ring.get_ring().in_extension(&self.ext_ring, x)
105 }
106}
107
108#[stability::unstable(feature = "enable")]
141pub trait EvaluatePolyLocallyRing: RingBase {
142
143 type LocalRingBase<'ring>: ?Sized + PrincipalIdealRing + Domain
154 where Self: 'ring;
155
156 type LocalRing<'ring>: RingStore<Type = Self::LocalRingBase<'ring>>
157 where Self: 'ring;
158
159 type LocalComputationData<'ring>
160 where Self: 'ring;
161
162 fn ln_pseudo_norm(&self, el: &Self::Element) -> f64;
172
173 fn local_computation<'ring>(&'ring self, ln_pseudo_norm_bound: f64) -> Self::LocalComputationData<'ring>;
178
179 fn local_ring_count<'ring>(&self, computation: &Self::LocalComputationData<'ring>) -> usize
184 where Self: 'ring;
185
186 fn local_ring_at<'ring>(&self, computation: &Self::LocalComputationData<'ring>, i: usize) -> Self::LocalRing<'ring>
190 where Self: 'ring;
191
192 fn reduce<'ring>(&self, computation: &Self::LocalComputationData<'ring>, el: &Self::Element) -> Vec<<Self::LocalRingBase<'ring> as RingBase>::Element>
197 where Self: 'ring;
198
199 fn lift_combine<'ring>(&self, computation: &Self::LocalComputationData<'ring>, el: &[<Self::LocalRingBase<'ring> as RingBase>::Element]) -> Self::Element
207 where Self: 'ring;
208}
209
210impl<I> EvaluatePolyLocallyRing for I
211 where I: IntegerRing
212{
213 type LocalComputationData<'ring> = zn_rns::Zn<AsField<zn_64::Zn>, RingRef<'ring, Self>>
214 where Self: 'ring;
215
216 type LocalRing<'ring> = AsField<zn_64::Zn>
217 where Self: 'ring;
218
219 type LocalRingBase<'ring> = AsFieldBase<zn_64::Zn>
220 where Self: 'ring;
221
222 fn ln_pseudo_norm(&self, el: &Self::Element) -> f64 {
223 RingRef::new(self).abs_log2_ceil(el).unwrap_or(0) as f64 * 2f64.ln()
224 }
225
226 fn local_computation<'ring>(&'ring self, ln_pseudo_norm_bound: f64) -> Self::LocalComputationData<'ring> {
227 let mut primes = Vec::new();
228 let mut ln_current = 0.;
229 let mut current_value = (1 << 62) / 9;
230 while ln_current < ln_pseudo_norm_bound + 1. {
231 current_value = prev_prime(StaticRing::<i64>::RING, current_value).unwrap();
232 if current_value < (1 << 32) {
233 panic!("not enough primes");
234 }
235 primes.push(current_value);
236 ln_current += (current_value as f64).ln();
237 }
238 return zn_rns::Zn::new(
239 primes.into_iter().map(|p| AsField::from(AsFieldBase::promise_is_perfect_field(zn_64::Zn::new(p as u64)))).collect(),
240 RingRef::new(self)
241 );
242 }
243
244 fn local_ring_at<'ring>(&self, computation: &Self::LocalComputationData<'ring>, i: usize) -> Self::LocalRing<'ring>
245 where Self: 'ring
246 {
247 computation.at(i).clone()
248 }
249
250 fn local_ring_count<'ring>(&self, computation: &Self::LocalComputationData<'ring>) -> usize
251 where Self: 'ring
252 {
253 computation.len()
254 }
255
256 fn reduce<'ring>(&self, computation: &Self::LocalComputationData<'ring>, el: &Self::Element) -> Vec<<Self::LocalRingBase<'ring> as RingBase>::Element>
257 where Self: 'ring
258 {
259 computation.get_congruence(&computation.coerce(RingValue::from_ref(self), self.clone_el(el))).as_iter().map(|x| *x).collect()
260 }
261
262 fn lift_combine<'ring>(&self, computation: &Self::LocalComputationData<'ring>, el: &[<Self::LocalRingBase<'ring> as RingBase>::Element]) -> Self::Element
263 where Self: 'ring
264 {
265 computation.smallest_lift(computation.from_congruence(el.iter().copied()))
266 }
267}
268
269#[stability::unstable(feature = "enable")]
274pub struct EvaluatePolyLocallyReductionMap<'ring, 'data, R>
275 where R: 'ring + ?Sized + EvaluatePolyLocallyRing, 'ring: 'data
276{
277 ring: RingRef<'data, R>,
278 data: &'data R::LocalComputationData<'ring>,
279 local_ring: R::LocalRing<'ring>,
280 index: usize
281}
282
283impl<'ring, 'data, R> EvaluatePolyLocallyReductionMap<'ring, 'data, R>
284 where R: 'ring +?Sized + EvaluatePolyLocallyRing, 'ring: 'data
285{
286 #[stability::unstable(feature = "enable")]
287 pub fn new(ring: &'data R, data: &'data R::LocalComputationData<'ring>, index: usize) -> Self {
288 Self { ring: RingRef::new(ring), data: data, local_ring: ring.local_ring_at(data, index), index: index }
289 }
290}
291
292impl<'ring, 'data, R> Homomorphism<R, R::LocalRingBase<'ring>> for EvaluatePolyLocallyReductionMap<'ring, 'data, R>
293 where R: 'ring +?Sized + EvaluatePolyLocallyRing, 'ring: 'data
294{
295 type CodomainStore = R::LocalRing<'ring>;
296 type DomainStore = RingRef<'data, R>;
297
298 fn codomain<'b>(&'b self) -> &'b Self::CodomainStore {
299 &self.local_ring
300 }
301
302 fn domain<'b>(&'b self) -> &'b Self::DomainStore {
303 &self.ring
304 }
305
306 fn map(&self, x: <R as RingBase>::Element) -> <R::LocalRingBase<'ring> as RingBase>::Element {
307 let ring_ref: &'data R = self.ring.into();
308 let mut reductions: Vec<<R::LocalRingBase<'ring> as RingBase>::Element> = ring_ref.reduce(self.data, &x);
309 return reductions.swap_remove(self.index);
310 }
311}
312
313#[macro_export]
314macro_rules! impl_interpolation_base_ring_char_zero {
315 (<{$($gen_args:tt)*}> InterpolationBaseRing for $self_type:ty where $($constraints:tt)*) => {
316 impl<$($gen_args)*> $crate::compute_locally::InterpolationBaseRing for $self_type where $($constraints)* {
317
318 type ExtendedRing<'a> = RingRef<'a, Self>
319 where Self: 'a;
320
321 type ExtendedRingBase<'a> = Self
322 where Self: 'a;
323
324 fn in_base<'a, S>(&self, _ext_ring: S, el: El<S>) -> Option<Self::Element>
325 where Self: 'a, S: RingStore<Type = Self::ExtendedRingBase<'a>>
326 {
327 Some(el)
328 }
329
330 fn in_extension<'a, S>(&self, _ext_ring: S, el: Self::Element) -> El<S>
331 where Self: 'a, S: RingStore<Type = Self::ExtendedRingBase<'a>>
332 {
333 el
334 }
335
336 fn interpolation_points<'a>(&'a self, count: usize) -> (Self::ExtendedRing<'a>, Vec<El<Self::ExtendedRing<'a>>>) {
337 let ZZbig = $crate::integer::BigIntRing::RING;
338 assert!(ZZbig.is_zero(&self.characteristic(&ZZbig).unwrap()));
339 let ring = $crate::ring::RingRef::new(self);
340 (ring, (0..count).map(|n| <_ as $crate::homomorphism::Homomorphism<_, _>>::map(&ring.int_hom(), n as i32)).collect())
341 }
342 }
343 };
344}