1use std::fmt::Debug;
2use std::fmt::Display;
3
4use crate::algorithms::linsolve::LinSolveRing;
5use crate::algorithms::miller_rabin::is_prime;
6use crate::computation::no_error;
7use crate::delegate::*;
8use crate::divisibility::*;
9use crate::homomorphism::*;
10use crate::integer::*;
11use crate::ordered::OrderedRing;
12use crate::ring::*;
13use crate::rings::zn::*;
14use crate::seq::*;
15use crate::specialization::FiniteRingSpecializable;
16use crate::algorithms::poly_factor::FactorPolyField;
17use crate::algorithms::poly_gcd::PolyTFracGCDRing;
18use crate::rings::field::{AsField, AsFieldBase};
19use crate::field::Field;
20use crate::rings::finite::FiniteRing;
21
22#[stability::unstable(feature = "enable")]
88pub trait PolyGCDLocallyDomain: Domain + DivisibilityRing + FiniteRingSpecializable {
89
90 type LocalRingBase<'ring>: ?Sized + LinSolveRing
94 where Self: 'ring;
95
96 type LocalRing<'ring>: RingStore<Type = Self::LocalRingBase<'ring>> + Clone
97 where Self: 'ring;
98
99 type LocalFieldBase<'ring>: ?Sized + PolyTFracGCDRing + FactorPolyField + Field + SelfIso + FiniteRingSpecializable
106 where Self: 'ring;
107
108 type LocalField<'ring>: RingStore<Type = Self::LocalFieldBase<'ring>> + Clone
109 where Self: 'ring;
110
111 type SuitableIdeal<'ring>
116 where Self: 'ring;
117
118 fn heuristic_exponent<'ring, 'a, I>(&self, _ideal: &Self::SuitableIdeal<'ring>, _poly_deg: usize, _coefficients: I) -> usize
126 where I: Iterator<Item = &'a Self::Element>,
127 Self: 'a,
128 Self: 'ring;
129
130 fn random_suitable_ideal<'ring, F>(&'ring self, rng: F) -> Self::SuitableIdeal<'ring>
134 where F: FnMut() -> u64;
135
136 fn maximal_ideal_factor_count<'ring>(&self, ideal: &Self::SuitableIdeal<'ring>) -> usize
140 where Self: 'ring;
141
142 fn local_field_at<'ring>(&self, ideal: &Self::SuitableIdeal<'ring>, max_ideal_idx: usize) -> Self::LocalField<'ring>
148 where Self: 'ring;
149
150 fn local_ring_at<'ring>(&self, ideal: &Self::SuitableIdeal<'ring>, e: usize, max_ideal_idx: usize) -> Self::LocalRing<'ring>
154 where Self: 'ring;
155
156 fn reduce_ring_el<'ring>(&self, ideal: &Self::SuitableIdeal<'ring>, to: (&Self::LocalRingBase<'ring>, usize), max_ideal_idx: usize, x: Self::Element) -> El<Self::LocalRing<'ring>>
164 where Self: 'ring;
165
166 fn reduce_partial<'ring>(&self, ideal: &Self::SuitableIdeal<'ring>, from: (&Self::LocalRingBase<'ring>, usize), to: (&Self::LocalRingBase<'ring>, usize), max_ideal_idx: usize, x: El<Self::LocalRing<'ring>>) -> El<Self::LocalRing<'ring>>
174 where Self: 'ring;
175
176 fn base_ring_to_field<'ring>(&self, ideal: &Self::SuitableIdeal<'ring>, from: &Self::LocalRingBase<'ring>, to: &Self::LocalFieldBase<'ring>, max_ideal_idx: usize, x: El<Self::LocalRing<'ring>>) -> El<Self::LocalField<'ring>>
180 where Self: 'ring;
181
182 fn field_to_base_ring<'ring>(&self, ideal: &Self::SuitableIdeal<'ring>, from: &Self::LocalFieldBase<'ring>, to: &Self::LocalRingBase<'ring>, max_ideal_idx: usize, x: El<Self::LocalField<'ring>>) -> El<Self::LocalRing<'ring>>
186 where Self: 'ring;
187
188 fn lift_partial<'ring>(&self, ideal: &Self::SuitableIdeal<'ring>, from: (&Self::LocalRingBase<'ring>, usize), to: (&Self::LocalRingBase<'ring>, usize), max_ideal_idx: usize, x: El<Self::LocalRing<'ring>>) -> El<Self::LocalRing<'ring>>
194 where Self: 'ring;
195
196 fn reconstruct_ring_el<'local, 'element, 'ring, V1, V2>(&self, ideal: &Self::SuitableIdeal<'ring>, from: V1, e: usize, x: V2) -> Self::Element
203 where Self: 'ring,
204 V1: VectorFn<&'local Self::LocalRing<'ring>>,
205 V2: VectorFn<&'element El<Self::LocalRing<'ring>>>,
206 Self::LocalRing<'ring>: 'local,
207 El<Self::LocalRing<'ring>>: 'element,
208 'ring: 'local + 'element;
209
210 fn dbg_ideal<'ring>(&self, ideal: &Self::SuitableIdeal<'ring>, out: &mut std::fmt::Formatter) -> std::fmt::Result
211 where Self: 'ring;
212}
213
214#[stability::unstable(feature = "enable")]
219pub trait IntegerPolyGCDRing: PolyGCDLocallyDomain {
220
221 type LocalRingAsZnBase<'ring>: ?Sized + CanIsoFromTo<Self::LocalRingBase<'ring>> + ZnRing + SelfIso
226 where Self: 'ring;
227
228 type LocalRingAsZn<'ring>: RingStore<Type = Self::LocalRingAsZnBase<'ring>> + Clone
229 where Self: 'ring;
230
231 fn local_ring_as_zn<'a, 'ring>(&self, local_field: &'a Self::LocalRing<'ring>) -> &'a Self::LocalRingAsZn<'ring>;
232
233 fn local_ring_into_zn<'ring>(&self, local_field: Self::LocalRing<'ring>) -> Self::LocalRingAsZn<'ring>;
234
235 fn principal_ideal_generator<'ring>(&self, p: &Self::SuitableIdeal<'ring>) -> El<BigIntRing>
236 where Self: 'ring
237 {
238 assert_eq!(1, self.maximal_ideal_factor_count(p));
239 let Fp = self.local_ring_at(p, 1, 0);
240 let Fp = self.local_ring_as_zn(&Fp);
241 return int_cast(Fp.integer_ring().clone_el(Fp.modulus()), BigIntRing::RING, Fp.integer_ring());
242 }
243}
244
245#[stability::unstable(feature = "enable")]
246pub struct IdealDisplayWrapper<'a, 'ring, R: 'ring + ?Sized + PolyGCDLocallyDomain> {
247 ring: &'a R,
248 ideal: &'a R::SuitableIdeal<'ring>
249}
250
251impl<'a, 'ring, R: 'ring + ?Sized + PolyGCDLocallyDomain> IdealDisplayWrapper<'a, 'ring, R> {
252
253 #[stability::unstable(feature = "enable")]
254 pub fn new(ring: &'a R, ideal: &'a R::SuitableIdeal<'ring>) -> Self {
255 Self {
256 ring: ring,
257 ideal: ideal
258 }
259 }
260}
261
262impl<'a, 'ring, R: 'ring + ?Sized + PolyGCDLocallyDomain> Display for IdealDisplayWrapper<'a, 'ring, R> {
263
264 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
265 self.ring.dbg_ideal(self.ideal, f)
266 }
267}
268
269#[stability::unstable(feature = "enable")]
274pub struct PolyGCDLocallyReductionMap<'ring, 'data, 'local, R>
275 where R: 'ring + ?Sized + PolyGCDLocallyDomain, 'ring: 'data
276{
277 ring: RingRef<'data, R>,
278 ideal: &'data R::SuitableIdeal<'ring>,
279 to: (&'local R::LocalRing<'ring>, usize),
280 max_ideal_idx: usize
281}
282
283impl<'ring, 'data, 'local, R> PolyGCDLocallyReductionMap<'ring, 'data, 'local, R>
284 where R: 'ring +?Sized + PolyGCDLocallyDomain, 'ring: 'data
285{
286 #[stability::unstable(feature = "enable")]
287 pub fn new(ring: &'data R, ideal: &'data R::SuitableIdeal<'ring>, to: &'local R::LocalRing<'ring>, to_e: usize, max_ideal_idx: usize) -> Self {
288 assert!(to.get_ring() == ring.local_ring_at(ideal, to_e, max_ideal_idx).get_ring());
289 Self {
290 ring: RingRef::new(ring),
291 ideal: ideal,
292 to: (to, to_e),
293 max_ideal_idx: max_ideal_idx
294 }
295 }
296}
297
298impl<'ring, 'data, 'local, R> Homomorphism<R, R::LocalRingBase<'ring>> for PolyGCDLocallyReductionMap<'ring, 'data, 'local, R>
299 where R: 'ring +?Sized + PolyGCDLocallyDomain, 'ring: 'data
300{
301 type CodomainStore = &'local R::LocalRing<'ring>;
302 type DomainStore = RingRef<'data, R>;
303
304 fn codomain<'b>(&'b self) -> &'b Self::CodomainStore {
305 &self.to.0
306 }
307
308 fn domain<'b>(&'b self) -> &'b Self::DomainStore {
309 &self.ring
310 }
311
312 fn map(&self, x: <R as RingBase>::Element) -> <R::LocalRingBase<'ring> as RingBase>::Element {
313 self.ring.get_ring().reduce_ring_el(self.ideal, (self.to.0.get_ring(), self.to.1), self.max_ideal_idx, x)
314 }
315}
316
317#[stability::unstable(feature = "enable")]
322pub struct PolyGCDLocallyIntermediateReductionMap<'ring, 'data, 'local, R>
323 where R: 'ring + ?Sized + PolyGCDLocallyDomain, 'ring: 'data
324{
325 ring: RingRef<'data, R>,
326 ideal: &'data R::SuitableIdeal<'ring>,
327 from: (&'local R::LocalRing<'ring>, usize),
328 to: (&'local R::LocalRing<'ring>, usize),
329 max_ideal_idx: usize
330}
331
332impl<'ring, 'data, 'local, R> PolyGCDLocallyIntermediateReductionMap<'ring, 'data, 'local, R>
333 where R: 'ring + ?Sized + PolyGCDLocallyDomain, 'ring: 'data
334{
335 #[stability::unstable(feature = "enable")]
336 pub fn new(ring: &'data R, ideal: &'data R::SuitableIdeal<'ring>, from: &'local R::LocalRing<'ring>, from_e: usize, to: &'local R::LocalRing<'ring>, to_e: usize, max_ideal_idx: usize) -> Self {
337 assert!(ring.local_ring_at(ideal, from_e, max_ideal_idx).get_ring() == from.get_ring());
338 assert!(ring.local_ring_at(ideal, to_e, max_ideal_idx).get_ring() == to.get_ring());
339 Self {
340 ring: RingRef::new(ring),
341 ideal: ideal,
342 from: (from, from_e),
343 to: (to, to_e),
344 max_ideal_idx: max_ideal_idx
345 }
346 }
347
348 #[stability::unstable(feature = "enable")]
349 pub fn parent_ring<'a>(&'a self) -> RingRef<'a, R> {
350 RingRef::new(self.ring.get_ring())
351 }
352
353 #[stability::unstable(feature = "enable")]
354 pub fn from_e(&self) -> usize {
355 self.from.1
356 }
357
358 #[stability::unstable(feature = "enable")]
359 pub fn to_e(&self) -> usize {
360 self.to.1
361 }
362
363 #[stability::unstable(feature = "enable")]
364 pub fn ideal<'a>(&'a self) -> &'a R::SuitableIdeal<'ring> {
365 &self.ideal
366 }
367
368 #[stability::unstable(feature = "enable")]
369 pub fn max_ideal_idx(&self) -> usize {
370 self.max_ideal_idx
371 }
372}
373
374impl<'ring, 'data, 'local, R> Homomorphism<R::LocalRingBase<'ring>, R::LocalRingBase<'ring>> for PolyGCDLocallyIntermediateReductionMap<'ring, 'data, 'local, R>
375 where R: 'ring + ?Sized + PolyGCDLocallyDomain, 'ring: 'data
376{
377 type CodomainStore = &'local R::LocalRing<'ring>;
378 type DomainStore = &'local R::LocalRing<'ring>;
379
380 fn codomain<'b>(&'b self) -> &'b Self::CodomainStore {
381 &self.to.0
382 }
383
384 fn domain<'b>(&'b self) -> &'b Self::DomainStore {
385 &self.from.0
386 }
387
388 fn map(&self, x: <R::LocalRingBase<'ring> as RingBase>::Element) -> <R::LocalRingBase<'ring> as RingBase>::Element {
389 self.ring.get_ring().reduce_partial(self.ideal, (self.from.0.get_ring(), self.from.1), (self.to.0.get_ring(), self.to.1), self.max_ideal_idx, x)
390 }
391}
392
393#[stability::unstable(feature = "enable")]
399pub struct PolyGCDLocallyBaseRingToFieldIso<'ring, 'data, 'local, R>
400 where R: 'ring + ?Sized + PolyGCDLocallyDomain, 'ring: 'data
401{
402 ring: RingRef<'data, R>,
403 ideal: &'data R::SuitableIdeal<'ring>,
404 from: RingRef<'local, R::LocalRingBase<'ring>>,
405 to: RingRef<'local, R::LocalFieldBase<'ring>>,
406 max_ideal_idx: usize
407}
408
409impl<'ring, 'data, 'local, R> PolyGCDLocallyBaseRingToFieldIso<'ring, 'data, 'local, R>
410 where R: 'ring + ?Sized + PolyGCDLocallyDomain, 'ring: 'data
411{
412 #[stability::unstable(feature = "enable")]
413 pub fn new(ring: &'data R, ideal: &'data R::SuitableIdeal<'ring>, from: &'local R::LocalRingBase<'ring>, to: &'local R::LocalFieldBase<'ring>, max_ideal_idx: usize) -> Self {
414 assert!(ring.local_ring_at(ideal, 1, max_ideal_idx).get_ring() == from);
415 assert!(ring.local_field_at(ideal, max_ideal_idx).get_ring() == to);
416 Self {
417 ring: RingRef::new(ring),
418 ideal: ideal,
419 from: RingRef::new(from),
420 to: RingRef::new(to),
421 max_ideal_idx: max_ideal_idx
422 }
423 }
424
425 #[stability::unstable(feature = "enable")]
426 pub fn inv(&self) -> PolyGCDLocallyFieldToBaseRingIso<'ring, 'data, 'local, R> {
427 PolyGCDLocallyFieldToBaseRingIso {
428 ring: self.ring,
429 ideal: self.ideal,
430 from: self.to,
431 to: self.from,
432 max_ideal_idx: self.max_ideal_idx
433 }
434 }
435}
436
437impl<'ring, 'data, 'local, R> Homomorphism<R::LocalRingBase<'ring>, R::LocalFieldBase<'ring>> for PolyGCDLocallyBaseRingToFieldIso<'ring, 'data, 'local, R>
438 where R: 'ring + ?Sized + PolyGCDLocallyDomain, 'ring: 'data
439{
440 type DomainStore = RingRef<'local, R::LocalRingBase<'ring>>;
441 type CodomainStore = RingRef<'local, R::LocalFieldBase<'ring>>;
442
443 fn codomain<'b>(&'b self) -> &'b Self::CodomainStore {
444 &self.to
445 }
446
447 fn domain<'b>(&'b self) -> &'b Self::DomainStore {
448 &self.from
449 }
450
451 fn map(&self, x: <R::LocalRingBase<'ring> as RingBase>::Element) -> <R::LocalFieldBase<'ring> as RingBase>::Element {
452 self.ring.get_ring().base_ring_to_field(self.ideal, self.from.get_ring(), self.to.get_ring(), self.max_ideal_idx, x)
453 }
454}
455
456#[stability::unstable(feature = "enable")]
462pub struct PolyGCDLocallyFieldToBaseRingIso<'ring, 'data, 'local, R>
463 where R: 'ring + ?Sized + PolyGCDLocallyDomain, 'ring: 'data
464{
465 ring: RingRef<'data, R>,
466 ideal: &'data R::SuitableIdeal<'ring>,
467 to: RingRef<'local, R::LocalRingBase<'ring>>,
468 from: RingRef<'local, R::LocalFieldBase<'ring>>,
469 max_ideal_idx: usize
470}
471
472impl<'ring, 'data, 'local, R> PolyGCDLocallyFieldToBaseRingIso<'ring, 'data, 'local, R>
473 where R: 'ring + ?Sized + PolyGCDLocallyDomain, 'ring: 'data
474{
475 #[stability::unstable(feature = "enable")]
476 pub fn inv(&self) -> PolyGCDLocallyBaseRingToFieldIso<'ring, 'data, 'local, R> {
477 PolyGCDLocallyBaseRingToFieldIso {
478 ring: self.ring,
479 ideal: self.ideal,
480 from: self.to,
481 to: self.from,
482 max_ideal_idx: self.max_ideal_idx
483 }
484 }
485}
486
487impl<'ring, 'data, 'local, R> Homomorphism<R::LocalFieldBase<'ring>, R::LocalRingBase<'ring>> for PolyGCDLocallyFieldToBaseRingIso<'ring, 'data, 'local, R>
488 where R: 'ring + ?Sized + PolyGCDLocallyDomain, 'ring: 'data
489{
490 type DomainStore = RingRef<'local, R::LocalFieldBase<'ring>>;
491 type CodomainStore = RingRef<'local, R::LocalRingBase<'ring>>;
492
493 fn codomain<'b>(&'b self) -> &'b Self::CodomainStore {
494 &self.to
495 }
496
497 fn domain<'b>(&'b self) -> &'b Self::DomainStore {
498 &self.from
499 }
500
501 fn map(&self, x: <R::LocalFieldBase<'ring> as RingBase>::Element) -> <R::LocalRingBase<'ring> as RingBase>::Element {
502 self.ring.get_ring().field_to_base_ring(self.ideal, self.from.get_ring(), self.to.get_ring(), self.max_ideal_idx, x)
503 }
504}
505
506#[stability::unstable(feature = "enable")]
515pub struct ReductionContext<'ring, 'data, R>
516 where R: 'ring + ?Sized + PolyGCDLocallyDomain, 'ring: 'data
517{
518 ring: RingRef<'data, R>,
519 ideal: &'data R::SuitableIdeal<'ring>,
520 from_e: usize,
521 from: Vec<R::LocalRing<'ring>>,
522 to: Vec<R::LocalRing<'ring>>,
523 to_fields: Vec<R::LocalField<'ring>>
524}
525
526impl<'ring, 'data, R> ReductionContext<'ring, 'data, R>
527 where R: 'ring + ?Sized + PolyGCDLocallyDomain, 'ring: 'data
528{
529 #[stability::unstable(feature = "enable")]
530 pub fn new(ring: &'data R, ideal: &'data R::SuitableIdeal<'ring>, e: usize) -> Self {
531 assert!(e >= 1);
532 let maximal_ideal_factor_count = ring.maximal_ideal_factor_count(ideal);
533 Self {
534 ring: RingRef::new(ring),
535 ideal: ideal,
536 from_e: e,
537 from: (0..maximal_ideal_factor_count).map(|idx| ring.local_ring_at(ideal, e, idx)).collect::<Vec<_>>(),
538 to: (0..maximal_ideal_factor_count).map(|idx| ring.local_ring_at(ideal, 1, idx)).collect::<Vec<_>>(),
539 to_fields: (0..maximal_ideal_factor_count).map(|idx| ring.local_field_at(ideal, idx)).collect::<Vec<_>>(),
540 }
541 }
542
543 #[stability::unstable(feature = "enable")]
544 pub fn ideal(&self) -> &'data R::SuitableIdeal<'ring> {
545 self.ideal
546 }
547
548 #[stability::unstable(feature = "enable")]
549 pub fn main_ring_to_field_reduction<'local>(&'local self, max_ideal_idx: usize) -> PolyGCDLocallyReductionMap<'ring, 'data, 'local, R> {
550 PolyGCDLocallyReductionMap {
551 ideal: self.ideal,
552 ring: self.ring,
553 to: (self.to.at(max_ideal_idx), 1),
554 max_ideal_idx: max_ideal_idx
555 }
556 }
557
558 #[stability::unstable(feature = "enable")]
559 pub fn main_ring_to_intermediate_ring_reduction<'local>(&'local self, max_ideal_idx: usize) -> PolyGCDLocallyReductionMap<'ring, 'data, 'local, R> {
560 PolyGCDLocallyReductionMap {
561 ideal: self.ideal,
562 ring: self.ring,
563 to: (self.from.at(max_ideal_idx), self.from_e),
564 max_ideal_idx: max_ideal_idx
565 }
566 }
567
568 #[stability::unstable(feature = "enable")]
569 pub fn intermediate_ring_to_field_reduction<'local>(&'local self, max_ideal_idx: usize) -> PolyGCDLocallyIntermediateReductionMap<'ring, 'data, 'local, R> {
570 PolyGCDLocallyIntermediateReductionMap {
571 from: (&self.from[max_ideal_idx], self.from_e),
572 to: (&self.to[max_ideal_idx], 1),
573 max_ideal_idx: max_ideal_idx,
574 ring: self.ring,
575 ideal: self.ideal
576 }
577 }
578
579 #[stability::unstable(feature = "enable")]
580 pub fn base_ring_to_field_iso<'local>(&'local self, max_ideal_idx: usize) -> PolyGCDLocallyBaseRingToFieldIso<'ring, 'data, 'local, R> {
581 PolyGCDLocallyBaseRingToFieldIso {
582 ring: self.ring,
583 ideal: self.ideal,
584 from: RingRef::new(self.to[max_ideal_idx].get_ring()),
585 to: RingRef::new(self.to_fields[max_ideal_idx].get_ring()),
586 max_ideal_idx: max_ideal_idx
587 }
588 }
589
590 #[stability::unstable(feature = "enable")]
591 pub fn len(&self) -> usize {
592 self.from.len()
593 }
594
595 #[stability::unstable(feature = "enable")]
596 pub fn reconstruct_ring_el<'local, V>(&self, els: V) -> R::Element
597 where V: VectorFn<&'local El<R::LocalRing<'ring>>>,
598 El<R::LocalRing<'ring>>: 'local,
599 'ring: 'local
600 {
601 fn do_reconstruction<'ring, 'local, R, V>(ring: &R, ideal: &R::SuitableIdeal<'ring>, local_rings: &[R::LocalRing<'ring>], e: usize, els: V) -> R::Element
602 where R: 'ring + ?Sized + PolyGCDLocallyDomain,
603 V: VectorFn<&'local El<R::LocalRing<'ring>>>,
604 El<R::LocalRing<'ring>>: 'local,
605 'ring: 'local
606 {
607 ring.reconstruct_ring_el(ideal, local_rings.as_fn(), e, els)
608 }
609 do_reconstruction(self.ring.get_ring(), self.ideal, &self.from[..], self.from_e, els)
610 }
611}
612
613#[stability::unstable(feature = "enable")]
614pub const INTRING_HEURISTIC_FACTOR_SIZE_OVER_POLY_SIZE_FACTOR: f64 = 0.25;
615
616#[macro_export]
626macro_rules! impl_poly_gcd_locally_for_ZZ {
627 (IntegerPolyGCDRing for $int_ring_type:ty) => {
628 impl_poly_gcd_locally_for_ZZ!{ <{}> IntegerPolyGCDRing for $int_ring_type where }
629 };
630 (<{$($gen_args:tt)*}> IntegerPolyGCDRing for $int_ring_type:ty where $($constraints:tt)*) => {
631
632 impl<$($gen_args)*> $crate::reduce_lift::poly_factor_gcd::PolyGCDLocallyDomain for $int_ring_type
633 where $($constraints)*
634 {
635 type LocalRing<'ring> = $crate::rings::zn::zn_big::Zn<BigIntRing>
636 where Self: 'ring;
637 type LocalRingBase<'ring> = $crate::rings::zn::zn_big::ZnBase<BigIntRing>
638 where Self: 'ring;
639 type LocalFieldBase<'ring> = $crate::rings::field::AsFieldBase<$crate::rings::zn::zn_64::Zn>
640 where Self: 'ring;
641 type LocalField<'ring> = $crate::rings::field::AsField<$crate::rings::zn::zn_64::Zn>
642 where Self: 'ring;
643 type SuitableIdeal<'ring> = i64
644 where Self: 'ring;
645
646 fn reconstruct_ring_el<'local, 'element, 'ring, V1, V2>(&self, _p: &Self::SuitableIdeal<'ring>, from: V1, _e: usize, x: V2) -> Self::Element
647 where Self: 'ring,
648 V1: $crate::seq::VectorFn<&'local Self::LocalRing<'ring>>,
649 V2: $crate::seq::VectorFn<&'element El<Self::LocalRing<'ring>>>
650 {
651 use $crate::rings::zn::*;
652 #[allow(unused)]
653 use $crate::seq::*;
654 assert_eq!(1, from.len());
655 assert_eq!(1, x.len());
656 int_cast(from.at(0).smallest_lift(from.at(0).clone_el(x.at(0))), RingRef::new(self), BigIntRing::RING)
657 }
658
659 fn maximal_ideal_factor_count<'ring>(&self, _p: &Self::SuitableIdeal<'ring>) -> usize
660 where Self: 'ring
661 {
662 1
663 }
664
665 fn lift_partial<'ring>(&self, _p: &Self::SuitableIdeal<'ring>, from: (&Self::LocalRingBase<'ring>, usize), to: (&Self::LocalRingBase<'ring>, usize), max_ideal_idx: usize, x: El<Self::LocalRing<'ring>>) -> El<Self::LocalRing<'ring>>
666 where Self: 'ring
667 {
668 use $crate::rings::zn::*;
669 use $crate::homomorphism::*;
670
671 assert_eq!(0, max_ideal_idx);
672 assert!(from.1 <= to.1);
673 let hom = RingRef::new(to.0).into_can_hom(to.0.integer_ring()).ok().unwrap();
674 return hom.map(from.0.any_lift(x));
675 }
676
677 fn local_field_at<'ring>(&self, p: &Self::SuitableIdeal<'ring>, max_ideal_idx: usize) -> Self::LocalField<'ring>
678 where Self: 'ring
679 {
680 use $crate::rings::zn::*;
681
682 assert_eq!(0, max_ideal_idx);
683 $crate::rings::zn::zn_64::Zn::new(*p as u64).as_field().ok().unwrap()
684 }
685
686 fn local_ring_at<'ring>(&self, p: &Self::SuitableIdeal<'ring>, e: usize, max_ideal_idx: usize) -> Self::LocalRing<'ring>
687 where Self: 'ring
688 {
689 assert_eq!(0, max_ideal_idx);
690 $crate::rings::zn::zn_big::Zn::new(BigIntRing::RING, BigIntRing::RING.pow(int_cast(*p, BigIntRing::RING, StaticRing::<i64>::RING), e))
691 }
692
693 fn random_suitable_ideal<'ring, F>(&'ring self, rng: F) -> Self::SuitableIdeal<'ring>
694 where F: FnMut() -> u64
695 {
696 let lower_bound = StaticRing::<i64>::RING.get_ring().get_uniformly_random_bits(24, rng);
697 return $crate::algorithms::miller_rabin::next_prime(StaticRing::<i64>::RING, lower_bound);
698 }
699
700 fn base_ring_to_field<'ring>(&self, _ideal: &Self::SuitableIdeal<'ring>, from: &Self::LocalRingBase<'ring>, to: &Self::LocalFieldBase<'ring>, max_ideal_idx: usize, x: El<Self::LocalRing<'ring>>) -> El<Self::LocalField<'ring>>
701 where Self: 'ring
702 {
703 assert_eq!(0, max_ideal_idx);
704 assert_eq!(from.characteristic(StaticRing::<i64>::RING).unwrap(), to.characteristic(StaticRing::<i64>::RING).unwrap());
705 <_ as $crate::rings::zn::ZnRing>::from_int_promise_reduced(to, $crate::integer::int_cast(
706 <_ as $crate::rings::zn::ZnRing>::smallest_positive_lift(from, x),
707 <_ as $crate::rings::zn::ZnRing>::integer_ring(to),
708 <_ as $crate::rings::zn::ZnRing>::integer_ring(from),
709 ))
710 }
711
712 fn field_to_base_ring<'ring>(&self, _ideal: &Self::SuitableIdeal<'ring>, from: &Self::LocalFieldBase<'ring>, to: &Self::LocalRingBase<'ring>, max_ideal_idx: usize, x: El<Self::LocalField<'ring>>) -> El<Self::LocalRing<'ring>>
713 where Self: 'ring
714 {
715
716 assert_eq!(0, max_ideal_idx);
717 assert_eq!(from.characteristic(StaticRing::<i64>::RING).unwrap(), to.characteristic(StaticRing::<i64>::RING).unwrap());
718 <_ as $crate::rings::zn::ZnRing>::from_int_promise_reduced(to, $crate::integer::int_cast(
719 <_ as $crate::rings::zn::ZnRing>::smallest_positive_lift(from, x),
720 <_ as $crate::rings::zn::ZnRing>::integer_ring(to),
721 <_ as $crate::rings::zn::ZnRing>::integer_ring(from),
722 ))
723 }
724
725 fn reduce_ring_el<'ring>(&self, _p: &Self::SuitableIdeal<'ring>, to: (&Self::LocalRingBase<'ring>, usize), max_ideal_idx: usize, x: Self::Element) -> El<Self::LocalRing<'ring>>
726 where Self: 'ring
727 {
728 use $crate::homomorphism::*;
729
730 assert_eq!(0, max_ideal_idx);
731 let self_ref = RingRef::new(self);
732 let hom = RingRef::new(to.0).into_can_hom(&self_ref).ok().unwrap();
733 return hom.map(x);
734 }
735
736 fn reduce_partial<'ring>(&self, _p: &Self::SuitableIdeal<'ring>, from: (&Self::LocalRingBase<'ring>, usize), to: (&Self::LocalRingBase<'ring>, usize), max_ideal_idx: usize, x: El<Self::LocalRing<'ring>>) -> El<Self::LocalRing<'ring>>
737 where Self: 'ring
738 {
739 use $crate::rings::zn::*;
740 use $crate::homomorphism::*;
741
742 assert_eq!(0, max_ideal_idx);
743 assert!(from.1 >= to.1);
744 let hom = RingRef::new(to.0).into_can_hom(to.0.integer_ring()).ok().unwrap();
745 return hom.map(from.0.smallest_lift(x));
746 }
747
748 fn heuristic_exponent<'ring, 'a, I>(&self, p: &i64, poly_deg: usize, coefficients: I) -> usize
749 where I: Iterator<Item = &'a Self::Element>,
750 Self: 'a,
751 Self: 'ring
752 {
753 let log2_max_coeff = coefficients.map(|c| RingRef::new(self).abs_log2_ceil(c).unwrap_or(0)).max().unwrap_or(0);
754 return ((log2_max_coeff as f64 + poly_deg as f64) / (*p as f64).log2() * $crate::reduce_lift::poly_factor_gcd::INTRING_HEURISTIC_FACTOR_SIZE_OVER_POLY_SIZE_FACTOR).ceil() as usize + 1;
756 }
757
758 fn dbg_ideal<'ring>(&self, p: &Self::SuitableIdeal<'ring>, out: &mut std::fmt::Formatter) -> std::fmt::Result
759 where Self: 'ring
760 {
761 write!(out, "({})", p)
762 }
763 }
764
765 impl<$($gen_args)*> $crate::reduce_lift::poly_factor_gcd::IntegerPolyGCDRing for $int_ring_type
766 where $($constraints)*
767 {
768 type LocalRingAsZnBase<'ring> = Self::LocalRingBase<'ring>
769 where Self: 'ring;
770
771 type LocalRingAsZn<'ring> = Self::LocalRing<'ring>
772 where Self: 'ring;
773
774 fn local_ring_as_zn<'a, 'ring>(&self, local_field: &'a Self::LocalRing<'ring>) -> &'a Self::LocalRingAsZn<'ring>
775 where Self: 'ring
776 {
777 local_field
778 }
779
780 fn local_ring_into_zn<'ring>(&self, local_field: Self::LocalRing<'ring>) -> Self::LocalRingAsZn<'ring>
781 where Self: 'ring
782 {
783 local_field
784 }
785 }
786 };
787}
788
789#[allow(unused)]
800impl<R> PolyGCDLocallyDomain for R
801 where R: ?Sized + FiniteRing + FactorPolyField + Field + SelfIso
802{
803 type LocalRingBase<'ring> = Self
804 where Self: 'ring;
805 type LocalRing<'ring> = RingRef<'ring, Self>
806 where Self: 'ring;
807
808 type LocalFieldBase<'ring> = Self
809 where Self: 'ring;
810 type LocalField<'ring> = RingRef<'ring, Self>
811 where Self: 'ring;
812 type SuitableIdeal<'ring> = RingRef<'ring, Self>
813 where Self: 'ring;
814
815 fn heuristic_exponent<'ring, 'element, IteratorType>(&self, _maximal_ideal: &Self::SuitableIdeal<'ring>, _poly_deg: usize, _coefficients: IteratorType) -> usize
816 where IteratorType: Iterator<Item = &'element Self::Element>,
817 Self: 'element,
818 Self: 'ring
819 {
820 unreachable!("this should never be called for finite fields, since specialized functions are available in this case")
821 }
822
823 fn maximal_ideal_factor_count<'ring>(&self,ideal: &Self::SuitableIdeal<'ring>) -> usize where Self:'ring {
824 unreachable!("this should never be called for finite fields, since specialized functions are available in this case")
825 }
826
827 fn random_suitable_ideal<'ring, RandomNumberFunction>(&'ring self, rng: RandomNumberFunction) -> Self::SuitableIdeal<'ring>
828 where RandomNumberFunction: FnMut() -> u64
829 {
830 unreachable!("this should never be called for finite fields, since specialized functions are available in this case")
831 }
832
833 fn local_field_at<'ring>(&self, p: &Self::SuitableIdeal<'ring>, max_ideal_idx: usize) -> Self::LocalField<'ring>
834 where Self: 'ring
835 {
836 unreachable!("this should never be called for finite fields, since specialized functions are available in this case")
837 }
838
839 fn local_ring_at<'ring>(&self, p: &Self::SuitableIdeal<'ring>, e: usize, max_ideal_idx: usize) -> Self::LocalRing<'ring>
840 where Self: 'ring
841 {
842 unreachable!("this should never be called for finite fields, since specialized functions are available in this case")
843 }
844
845 fn reduce_ring_el<'ring>(&self, p: &Self::SuitableIdeal<'ring>, to: (&Self::LocalRingBase<'ring>, usize), max_ideal_idx: usize, x: Self::Element) -> El<Self::LocalRing<'ring>>
846 where Self: 'ring
847 {
848 unreachable!("this should never be called for finite fields, since specialized functions are available in this case")
849 }
850
851 fn base_ring_to_field<'ring>(&self, _ideal: &Self::SuitableIdeal<'ring>, from: &Self::LocalRingBase<'ring>, to: &Self::LocalFieldBase<'ring>, max_ideal_idx: usize, x: El<Self::LocalRing<'ring>>) -> El<Self::LocalField<'ring>>
852 where Self: 'ring
853 {
854 unreachable!("this should never be called for finite fields, since specialized functions are available in this case")
855 }
856
857 fn field_to_base_ring<'ring>(&self, _ideal: &Self::SuitableIdeal<'ring>, from: &Self::LocalFieldBase<'ring>, to: &Self::LocalRingBase<'ring>, max_ideal_idx: usize, x: El<Self::LocalField<'ring>>) -> El<Self::LocalRing<'ring>>
858 where Self: 'ring
859 {
860 unreachable!("this should never be called for finite fields, since specialized functions are available in this case")
861 }
862
863 fn reduce_partial<'ring>(&self, p: &Self::SuitableIdeal<'ring>, from: (&Self::LocalRingBase<'ring>, usize), to: (&Self::LocalRingBase<'ring>, usize), max_ideal_idx: usize, x: El<Self::LocalRing<'ring>>) -> El<Self::LocalRing<'ring>>
864 where Self: 'ring
865 {
866 unreachable!("this should never be called for finite fields, since specialized functions are available in this case")
867 }
868
869 fn lift_partial<'ring>(&self, p: &Self::SuitableIdeal<'ring>, from: (&Self::LocalRingBase<'ring>, usize), to: (&Self::LocalRingBase<'ring>, usize), max_ideal_idx: usize, x: El<Self::LocalRing<'ring>>) -> El<Self::LocalRing<'ring>>
870 where Self: 'ring
871 {
872 unreachable!("this should never be called for finite fields, since specialized functions are available in this case")
873 }
874
875 fn reconstruct_ring_el<'local, 'element, 'ring, V1, V2>(&self, p: &Self::SuitableIdeal<'ring>, from: V1, e: usize, x: V2) -> Self::Element
876 where Self: 'ring,
877 V1: VectorFn<&'local Self::LocalRing<'ring>>,
878 V2: VectorFn<&'element El<Self::LocalRing<'ring>>>,
879 'ring: 'local + 'element,
880 Self::LocalRing<'ring>: 'local,
881 El<Self::LocalRing<'ring>>: 'element
882 {
883 unreachable!("this should never be called for finite fields, since specialized functions are available in this case")
884 }
885
886 fn dbg_ideal<'ring>(&self, p: &Self::SuitableIdeal<'ring>, out: &mut std::fmt::Formatter) -> std::fmt::Result
887 where Self: 'ring
888 {
889 unreachable!("this should never be called for finite fields, since specialized functions are available in this case")
890 }
891}
892
893#[stability::unstable(feature = "enable")]
894pub struct IntegersWithLocalZnQuotient<'a, R>
895 where R: Sized + SelfIso + ZnRing + FromModulusCreateableZnRing + LinSolveRing + Clone
896{
897 integers: &'a R::IntegerRing,
898 prime: El<R::IntegerRing>
899}
900
901impl<'a, R> IntegersWithLocalZnQuotient<'a, R>
902 where R: Sized + SelfIso + ZnRing + FromModulusCreateableZnRing + LinSolveRing + Clone
903{
904 #[stability::unstable(feature = "enable")]
905 pub fn new(integers: &'a R::IntegerRing, prime: El<R::IntegerRing>) -> Self {
906 assert!(is_prime(integers, &prime, 10));
907 return Self { integers, prime };
908 }
909
910 #[stability::unstable(feature = "enable")]
911 pub fn reduction_context<'b>(&'b self, from_e: usize) -> ReductionContext<'b, 'b, Self> {
912 ReductionContext {
913 ring: RingRef::new(self),
914 ideal: &self.prime,
915 from_e: from_e,
916 from: vec![self.local_ring_at(&self.prime, from_e, 0)],
917 to: vec![self.local_ring_at(&self.prime, 1, 0)],
918 to_fields: vec![self.local_field_at(&self.prime, 0)],
919 }
920 }
921}
922
923impl<'a, R> Debug for IntegersWithLocalZnQuotient<'a, R>
924 where R: ?Sized + SelfIso + ZnRing + FromModulusCreateableZnRing + LinSolveRing + Clone,
925 R::IntegerRingBase: Debug
926{
927 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
928 f.debug_struct("IntegersWithLocalZnQuotient")
929 .field("integers", &self.integers.get_ring())
930 .finish()
931 }
932}
933
934impl<'a, R> PartialEq for IntegersWithLocalZnQuotient<'a, R>
935 where R: ?Sized + SelfIso + ZnRing + FromModulusCreateableZnRing + LinSolveRing + Clone
936{
937 fn eq(&self, other: &Self) -> bool {
938 self.integers.get_ring() == other.integers.get_ring()
939 }
940}
941
942impl<'a, R> DelegateRing for IntegersWithLocalZnQuotient<'a, R>
943 where R: Sized + SelfIso + ZnRing + FromModulusCreateableZnRing + LinSolveRing + Clone
944{
945 type Base = <R as ZnRing>::IntegerRingBase;
946 type Element = El<<R as ZnRing>::IntegerRing>;
947
948 fn get_delegate(&self) -> &Self::Base {
949 self.integers.get_ring()
950 }
951
952 fn delegate(&self, el: Self::Element) -> <Self::Base as RingBase>::Element { el }
953 fn delegate_mut<'b>(&self, el: &'b mut Self::Element) -> &'b mut <Self::Base as RingBase>::Element { el }
954 fn delegate_ref<'b>(&self, el: &'b Self::Element) -> &'b <Self::Base as RingBase>::Element { el }
955 fn rev_delegate(&self, el: <Self::Base as RingBase>::Element) -> Self::Element { el }
956}
957
958impl<'a, R> OrderedRing for IntegersWithLocalZnQuotient<'a, R>
959 where R: Sized + SelfIso + ZnRing + FromModulusCreateableZnRing + Clone
960{
961 fn cmp(&self, lhs: &Self::Element, rhs: &Self::Element) -> std::cmp::Ordering { self.get_delegate().cmp(self.delegate_ref(lhs), self.delegate_ref(rhs)) }
962 fn abs_cmp(&self, lhs: &Self::Element, rhs: &Self::Element) -> std::cmp::Ordering { self.get_delegate().abs_cmp(self.delegate_ref(lhs), self.delegate_ref(rhs)) }
963}
964
965impl<'a, R> Domain for IntegersWithLocalZnQuotient<'a, R>
966 where R: Sized + SelfIso + ZnRing + FromModulusCreateableZnRing + Clone
967{}
968
969impl<'a, R> DelegateRingImplFiniteRing for IntegersWithLocalZnQuotient<'a, R>
970 where R: Sized + SelfIso + ZnRing + FromModulusCreateableZnRing + Clone
971{}
972
973impl<'a, R> DelegateRingImplEuclideanRing for IntegersWithLocalZnQuotient<'a, R>
974 where R: Sized + SelfIso + ZnRing + FromModulusCreateableZnRing + Clone
975{}
976
977impl<'a, R> crate::reduce_lift::poly_eval::EvalPolyLocallyRing for IntegersWithLocalZnQuotient<'a, R>
978 where R: Sized + SelfIso + ZnRing + FromModulusCreateableZnRing + Clone
979{
980 type LocalRingBase<'ring> = <<Self as DelegateRing>::Base as crate::reduce_lift::poly_eval::EvalPolyLocallyRing>::LocalRingBase<'ring>
981 where Self: 'ring;
982 type LocalRing<'ring> = <<Self as DelegateRing>::Base as crate::reduce_lift::poly_eval::EvalPolyLocallyRing>::LocalRing<'ring>
983 where Self: 'ring;
984 type LocalComputationData<'ring> = <<Self as DelegateRing>::Base as crate::reduce_lift::poly_eval::EvalPolyLocallyRing>::LocalComputationData<'ring>
985 where Self:'ring;
986
987 fn ln_pseudo_norm(&self, el: &Self::Element) -> f64 {
988 self.get_delegate().ln_pseudo_norm(self.delegate_ref(el))
989 }
990
991 fn reduce<'ring>(&self, computation: &Self::LocalComputationData<'ring>, el: &Self::Element) -> Vec<<Self::LocalRingBase<'ring> as RingBase>::Element>
992 where Self: 'ring
993 {
994 self.get_delegate().reduce(computation, self.delegate_ref(el))
995 }
996
997 fn local_ring_count<'ring>(&self, computation: &Self::LocalComputationData<'ring>) -> usize
998 where Self: 'ring
999 {
1000 self.get_delegate().local_ring_count(computation)
1001 }
1002
1003 fn local_ring_at<'ring>(&self, computation: &Self::LocalComputationData<'ring>, i: usize) -> Self::LocalRing<'ring>
1004 where Self: 'ring
1005 {
1006 crate::reduce_lift::poly_eval::EvalPolyLocallyRing::local_ring_at(self.get_delegate(), computation, i)
1007 }
1008
1009 fn local_computation<'ring>(&'ring self, ln_pseudo_norm_bound: f64) -> Self::LocalComputationData<'ring> {
1010 self.get_delegate().local_computation(ln_pseudo_norm_bound)
1011 }
1012
1013 fn lift_combine<'ring>(&self, computation: &Self::LocalComputationData<'ring>, el: &[<Self::LocalRingBase<'ring> as RingBase>::Element]) -> Self::Element
1014 where Self: 'ring
1015 {
1016 self.rev_delegate(self.get_delegate().lift_combine(computation, el))
1017 }
1018}
1019
1020impl<'a, R> IntegerRing for IntegersWithLocalZnQuotient<'a, R>
1021 where R: Sized + SelfIso + ZnRing + FromModulusCreateableZnRing + Clone
1022{
1023 fn to_float_approx(&self, value: &Self::Element) -> f64 { self.get_delegate().to_float_approx(self.delegate_ref(self.rev_element_cast_ref(value))) }
1024 fn from_float_approx(&self, value: f64) -> Option<Self::Element> { self.get_delegate().from_float_approx(value).map(|x| self.element_cast(self.rev_delegate(x))) }
1025 fn abs_is_bit_set(&self, value: &Self::Element, i: usize) -> bool { self.get_delegate().abs_is_bit_set(self.delegate_ref(self.rev_element_cast_ref(value)), i) }
1026 fn abs_highest_set_bit(&self, value: &Self::Element) -> Option<usize> { self.get_delegate().abs_highest_set_bit(self.delegate_ref(self.rev_element_cast_ref(value))) }
1027 fn abs_lowest_set_bit(&self, value: &Self::Element) -> Option<usize> { self.get_delegate().abs_lowest_set_bit(self.delegate_ref(self.rev_element_cast_ref(value))) }
1028 fn get_uniformly_random_bits<G: FnMut() -> u64>(&self, log2_bound_exclusive: usize, rng: G) -> Self::Element { self.element_cast(self.rev_delegate(self.get_delegate().get_uniformly_random_bits(log2_bound_exclusive, rng))) }
1029 fn rounded_div(&self, lhs: Self::Element, rhs: &Self::Element) -> Self::Element { self.element_cast(self.rev_delegate(self.get_delegate().rounded_div(self.delegate(self.rev_element_cast(lhs)), self.delegate_ref(self.rev_element_cast_ref(rhs))))) }
1030 fn ceil_div(&self, lhs: Self::Element, rhs: &Self::Element) -> Self::Element { self.element_cast(self.rev_delegate(self.get_delegate().ceil_div(self.delegate(self.rev_element_cast(lhs)), self.delegate_ref(self.rev_element_cast_ref(rhs))))) }
1031 fn floor_div(&self, lhs: Self::Element, rhs: &Self::Element) -> Self::Element { self.element_cast(self.rev_delegate(self.get_delegate().floor_div(self.delegate(self.rev_element_cast(lhs)), self.delegate_ref(self.rev_element_cast_ref(rhs))))) }
1032 fn power_of_two(&self, power: usize) -> Self::Element { self.element_cast(self.rev_delegate(self.get_delegate().power_of_two(power))) }
1033 fn representable_bits(&self) -> Option<usize> { self.get_delegate().representable_bits() }
1034 fn parse(&self, string: &str, base: u32) -> Result<Self::Element, ()> { self.get_delegate().parse(string, base).map(|x| self.element_cast(self.rev_delegate(x))) }
1035
1036 fn euclidean_div_pow_2(&self, value: &mut Self::Element, power: usize) {
1037 self.get_delegate().euclidean_div_pow_2(self.delegate_mut(self.rev_element_cast_mut(value)), power);
1038 self.postprocess_delegate_mut(self.rev_element_cast_mut(value));
1039 }
1040
1041 fn mul_pow_2(&self, value: &mut Self::Element, power: usize) {
1042 self.get_delegate().mul_pow_2(self.delegate_mut(self.rev_element_cast_mut(value)), power);
1043 self.postprocess_delegate_mut(self.rev_element_cast_mut(value));
1044 }
1045}
1046
1047impl<'a, R> PolyGCDLocallyDomain for IntegersWithLocalZnQuotient<'a, R>
1048 where R: Sized + SelfIso + ZnRing + FromModulusCreateableZnRing + LinSolveRing + Clone
1049{
1050 type LocalRingBase<'ring> = R
1051 where Self: 'ring;
1052
1053 type LocalRing<'ring> = RingValue<R>
1054 where Self: 'ring;
1055
1056 type LocalFieldBase<'ring> = AsFieldBase<RingValue<R>>
1057 where Self: 'ring;
1058
1059 type LocalField<'ring> = AsField<RingValue<R>>
1060 where Self: 'ring;
1061
1062 type SuitableIdeal<'ring> = Self::Element
1063 where Self: 'ring;
1064
1065 fn heuristic_exponent<'ring, 'el, I>(&self, ideal: &Self::SuitableIdeal<'ring>, poly_deg: usize, coefficients: I) -> usize
1066 where I: Iterator<Item = &'el Self::Element>,
1067 Self: 'el + 'ring
1068 {
1069 let log2_max_coeff = coefficients.map(|c| self.integers.abs_log2_ceil(c).unwrap_or(0)).max().unwrap_or(0);
1070 return ((log2_max_coeff as f64 + poly_deg as f64) / self.integers.abs_log2_floor(ideal).unwrap_or(1) as f64 * crate::reduce_lift::poly_factor_gcd::INTRING_HEURISTIC_FACTOR_SIZE_OVER_POLY_SIZE_FACTOR).ceil() as usize + 1;
1072 }
1073
1074 fn random_suitable_ideal<'ring, F>(&'ring self, _rng: F) -> Self::SuitableIdeal<'ring>
1075 where F: FnMut() -> u64
1076 {
1077 self.integers.clone_el(&self.prime)
1078 }
1079
1080 fn maximal_ideal_factor_count<'ring>(&self, ideal: &Self::SuitableIdeal<'ring>) -> usize
1081 where Self: 'ring
1082 {
1083 debug_assert!(self.integers.eq_el(ideal, &self.prime));
1084 1
1085 }
1086
1087 fn local_field_at<'ring>(&self, ideal: &Self::SuitableIdeal<'ring>, max_ideal_idx: usize) -> Self::LocalField<'ring>
1088 where Self: 'ring
1089 {
1090 assert_eq!(0, max_ideal_idx);
1091 self.local_ring_at(ideal, 1, 0).as_field().ok().unwrap()
1092 }
1093
1094 fn local_ring_at<'ring>(&self, ideal: &Self::SuitableIdeal<'ring>, e: usize, max_ideal_idx: usize) -> Self::LocalRing<'ring>
1095 where Self: 'ring
1096 {
1097 assert_eq!(0, max_ideal_idx);
1098 assert!(self.integers.eq_el(ideal, &self.prime));
1099 RingValue::from(R::from_modulus(|ZZ| Ok(RingRef::new(ZZ).pow(int_cast(self.integers.clone_el(&self.prime), RingRef::new(ZZ), &self.integers), e))).unwrap_or_else(no_error))
1100 }
1101
1102 fn reduce_ring_el<'ring>(&self, ideal: &Self::SuitableIdeal<'ring>, to: (&Self::LocalRingBase<'ring>, usize), max_ideal_idx: usize, x: Self::Element) -> El<Self::LocalRing<'ring>>
1103 where Self: 'ring
1104 {
1105 debug_assert_eq!(0, max_ideal_idx);
1106 debug_assert!(self.integers.eq_el(ideal, &self.prime));
1107 debug_assert!(self.integers.eq_el(&self.integers.pow(self.integers.clone_el(&self.prime), to.1), to.0.modulus()));
1108 RingRef::new(to.0).coerce(&self.integers, x)
1109 }
1110
1111 fn reduce_partial<'ring>(&self, ideal: &Self::SuitableIdeal<'ring>, from: (&Self::LocalRingBase<'ring>, usize), to: (&Self::LocalRingBase<'ring>, usize), max_ideal_idx: usize, x: El<Self::LocalRing<'ring>>) -> El<Self::LocalRing<'ring>>
1112 where Self: 'ring
1113 {
1114 debug_assert_eq!(0, max_ideal_idx);
1115 debug_assert!(self.integers.eq_el(ideal, &self.prime));
1116 debug_assert!(self.integers.eq_el(&self.integers.pow(self.integers.clone_el(&self.prime), to.1), to.0.modulus()));
1117 debug_assert!(self.integers.eq_el(&self.integers.pow(self.integers.clone_el(&self.prime), from.1), from.0.modulus()));
1118 RingRef::new(to.0).coerce(&self.integers, from.0.smallest_positive_lift(x))
1119 }
1120
1121 fn lift_partial<'ring>(&self, ideal: &Self::SuitableIdeal<'ring>, from: (&Self::LocalRingBase<'ring>, usize), to: (&Self::LocalRingBase<'ring>, usize), max_ideal_idx: usize, x: El<Self::LocalRing<'ring>>) -> El<Self::LocalRing<'ring>>
1122 where Self: 'ring
1123 {
1124 debug_assert_eq!(0, max_ideal_idx);
1125 debug_assert!(self.integers.eq_el(ideal, &self.prime));
1126 debug_assert!(self.integers.eq_el(&self.integers.pow(self.integers.clone_el(&self.prime), to.1), to.0.modulus()));
1127 debug_assert!(self.integers.eq_el(&self.integers.pow(self.integers.clone_el(&self.prime), from.1), from.0.modulus()));
1128 RingRef::new(to.0).coerce(&self.integers, from.0.smallest_positive_lift(x))
1129 }
1130
1131 fn base_ring_to_field<'ring>(&self, _ideal: &Self::SuitableIdeal<'ring>, from: &Self::LocalRingBase<'ring>, to: &Self::LocalFieldBase<'ring>, max_ideal_idx: usize, x: El<Self::LocalRing<'ring>>) -> El<Self::LocalField<'ring>>
1132 where Self: 'ring
1133 {
1134 debug_assert_eq!(0, max_ideal_idx);
1135 assert!(from == to.get_delegate());
1136 to.element_cast(to.rev_delegate(x))
1137 }
1138
1139 fn field_to_base_ring<'ring>(&self, _ideal: &Self::SuitableIdeal<'ring>, from: &Self::LocalFieldBase<'ring>, to: &Self::LocalRingBase<'ring>, max_ideal_idx: usize, x: El<Self::LocalField<'ring>>) -> El<Self::LocalRing<'ring>>
1140 where Self: 'ring
1141 {
1142 debug_assert_eq!(0, max_ideal_idx);
1143 assert!(to == from.get_delegate());
1144 from.delegate(from.rev_element_cast(x))
1145 }
1146
1147 fn reconstruct_ring_el<'local, 'element, 'ring, V1, V2>(&self, ideal: &Self::SuitableIdeal<'ring>, from: V1, e: usize, x: V2) -> Self::Element
1148 where Self: 'ring,
1149 V1: VectorFn<&'local Self::LocalRing<'ring>>,
1150 V2: VectorFn<&'element El<Self::LocalRing<'ring>>>,
1151 Self::LocalRing<'ring>: 'local,
1152 El<Self::LocalRing<'ring>>: 'element,
1153 'ring: 'local + 'element
1154 {
1155 assert_eq!(1, x.len());
1156 assert_eq!(1, from.len());
1157 debug_assert!(self.integers.eq_el(ideal, &self.prime));
1158 debug_assert!(self.integers.eq_el(&self.integers.pow(self.integers.clone_el(&self.prime), e), from.at(0).modulus()));
1159 from.at(0).smallest_lift(from.at(0).clone_el(x.at(0)))
1160 }
1161
1162 fn dbg_ideal<'ring>(&self, ideal: &Self::SuitableIdeal<'ring>, out: &mut std::fmt::Formatter) -> std::fmt::Result
1163 where Self: 'ring
1164 {
1165 self.dbg(ideal, out)
1166 }
1167}
1168
1169impl<'a, R> IntegerPolyGCDRing for IntegersWithLocalZnQuotient<'a, R>
1170 where R: Sized + SelfIso + ZnRing + FromModulusCreateableZnRing + LinSolveRing + Clone
1171{
1172 type LocalRingAsZn<'ring> = Self::LocalRing<'ring>
1173 where Self:'ring;
1174 type LocalRingAsZnBase<'ring> = Self::LocalRingBase<'ring>
1175 where Self:'ring;
1176
1177 fn local_ring_as_zn<'b, 'ring>(&self, local_field: &'b Self::LocalRing<'ring>) -> &'b Self::LocalRingAsZn<'ring>
1178 where Self: 'ring
1179 {
1180 local_field
1181 }
1182
1183 fn local_ring_into_zn<'ring>(&self, local_field: Self::LocalRing<'ring>) -> Self::LocalRingAsZn<'ring>
1184 where Self: 'ring
1185 {
1186 local_field
1187 }
1188}