1use crate::algorithms::convolution::KaratsubaHint;
2use crate::algorithms::matmul::{ComputeInnerProduct, StrassenHint};
3use crate::reduce_lift::poly_eval::{InterpolationBaseRing, InterpolationBaseRingStore};
4use crate::delegate::*;
5use crate::divisibility::*;
6use crate::local::PrincipalLocalRing;
7use crate::pid::{EuclideanRing, PrincipalIdealRing};
8use crate::field::*;
9use crate::integer::IntegerRing;
10use crate::ring::*;
11use crate::homomorphism::*;
12use crate::rings::zn::FromModulusCreateableZnRing;
13use crate::rings::zn::*;
14use crate::specialization::FiniteRingSpecializable;
15use super::local::AsLocalPIRBase;
16use crate::primitive_int::*;
17
18use std::marker::PhantomData;
19use std::fmt::Debug;
20
21use feanor_serde::newtype_struct::{DeserializeSeedNewtypeStruct, SerializableNewtypeStruct};
22use serde::{Deserialize, Serialize, Deserializer, Serializer};
23use serde::de::DeserializeSeed;
24
25pub struct AsFieldBase<R: RingStore>
78 where R::Type: DivisibilityRing
79{
80 base: R,
81 zero: FieldEl<R>
82}
83
84impl<R> PerfectField for AsFieldBase<R>
85 where R: RingStore,
86 R::Type: DivisibilityRing
87{}
88
89impl<R> Clone for AsFieldBase<R>
90 where R: RingStore + Clone,
91 R::Type: DivisibilityRing
92{
93 fn clone(&self) -> Self {
94 Self { zero: FieldEl(self.base.zero()), base: self.base.clone() }
95 }
96}
97
98impl<R> Copy for AsFieldBase<R>
99 where R: RingStore + Copy,
100 R::Type: DivisibilityRing,
101 El<R>: Copy
102{}
103
104impl<R> Debug for AsFieldBase<R>
105 where R: RingStore,
106 R::Type: DivisibilityRing + Debug
107{
108 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
109 f.debug_tuple("AsField")
110 .field(&self.base.get_ring())
111 .finish()
112 }
113}
114
115impl<R> PartialEq for AsFieldBase<R>
116 where R: RingStore,
117 R::Type: DivisibilityRing
118{
119 fn eq(&self, other: &Self) -> bool {
120 self.base.get_ring() == other.base.get_ring()
121 }
122}
123
124#[allow(type_alias_bounds)]
128pub type AsField<R: RingStore> = RingValue<AsFieldBase<R>>;
129
130pub struct FieldEl<R: RingStore>(El<R>)
134 where R::Type: DivisibilityRing;
135
136impl<R: RingStore> Debug for FieldEl<R>
137 where El<R>: Debug,
138 R::Type: DivisibilityRing
139{
140 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
141 f.debug_tuple("FieldEl")
142 .field(&self.0)
143 .finish()
144 }
145}
146
147impl<R: RingStore> Clone for FieldEl<R>
148 where El<R>: Clone,
149 R::Type: DivisibilityRing
150{
151 fn clone(&self) -> Self {
152 FieldEl(self.0.clone())
153 }
154}
155
156impl<R: RingStore> Copy for FieldEl<R>
157 where El<R>: Copy,
158 R::Type: DivisibilityRing
159{}
160
161impl<R: RingStore> AsFieldBase<R>
162 where R::Type: DivisibilityRing
163{
164 pub fn promise_is_perfect_field(base: R) -> Self {
172 Self { zero: FieldEl(base.zero()), base }
173 }
174
175 #[stability::unstable(feature = "enable")]
189 pub fn promise_is_field(base: R) -> Result<Self, R>
190 where R::Type: FiniteRingSpecializable
191 {
192 let characteristic = base.characteristic(&StaticRing::<i64>::RING);
193 if characteristic.is_some() && characteristic.unwrap() == 0 {
194 return Ok(Self::promise_is_perfect_field(base));
195 } else if <R::Type as FiniteRingSpecializable>::is_finite_ring() {
196 return Ok(Self::promise_is_perfect_field(base));
197 } else {
198 return Err(base);
199 }
200 }
201
202 pub fn unwrap_element(&self, el: <Self as RingBase>::Element) -> El<R> {
203 el.0
204 }
205
206 pub fn unwrap_self(self) -> R {
210 self.base
211 }
212}
213
214impl<R: RingStore> AsFieldBase<R>
215 where R::Type: PerfectField
216{
217 pub fn from_field(base: R) -> Self {
222 Self::promise_is_perfect_field(base)
223 }
224}
225
226impl<R: RingStore> DelegateRing for AsFieldBase<R>
227 where R::Type: DivisibilityRing
228{
229 type Element = FieldEl<R>;
230 type Base = R::Type;
231
232 fn get_delegate(&self) -> &Self::Base {
233 self.base.get_ring()
234 }
235
236 fn delegate(&self, el: Self::Element) -> <Self::Base as RingBase>::Element {
237 el.0
238 }
239
240 fn delegate_mut<'a>(&self, el: &'a mut Self::Element) -> &'a mut <Self::Base as RingBase>::Element {
241 &mut el.0
242 }
243
244 fn delegate_ref<'a>(&self, el: &'a Self::Element) -> &'a <Self::Base as RingBase>::Element {
245 &el.0
246 }
247
248 fn rev_delegate(&self, el: <Self::Base as RingBase>::Element) -> Self::Element {
249 FieldEl(el)
250 }
251}
252
253impl<R: RingStore> DelegateRingImplFiniteRing for AsFieldBase<R>
254 where R::Type: DivisibilityRing
255{}
256
257impl<R: RingStore, S: RingStore> CanHomFrom<AsFieldBase<S>> for AsFieldBase<R>
258 where R::Type: DivisibilityRing + CanHomFrom<S::Type>,
259 S::Type: DivisibilityRing
260{
261 type Homomorphism = <R::Type as CanHomFrom<S::Type>>::Homomorphism;
262
263 fn has_canonical_hom(&self, from: &AsFieldBase<S>) -> Option<Self::Homomorphism> {
264 <R::Type as CanHomFrom<S::Type>>::has_canonical_hom(self.get_delegate(), from.get_delegate())
265 }
266
267 fn map_in(&self, from: &AsFieldBase<S>, el: FieldEl<S>, hom: &Self::Homomorphism) -> Self::Element {
268 FieldEl(<R::Type as CanHomFrom<S::Type>>::map_in(self.get_delegate(), from.get_delegate(), el.0, hom))
269 }
270}
271
272impl<R: RingStore, S: RingStore> CanIsoFromTo<AsFieldBase<S>> for AsFieldBase<R>
273 where R::Type: DivisibilityRing + CanIsoFromTo<S::Type>,
274 S::Type: DivisibilityRing
275{
276 type Isomorphism = <R::Type as CanIsoFromTo<S::Type>>::Isomorphism;
277
278 fn has_canonical_iso(&self, from: &AsFieldBase<S>) -> Option<Self::Isomorphism> {
279 <R::Type as CanIsoFromTo<S::Type>>::has_canonical_iso(self.get_delegate(), from.get_delegate())
280 }
281
282 fn map_out(&self, from: &AsFieldBase<S>, el: Self::Element, iso: &Self::Isomorphism) -> FieldEl<S> {
283 FieldEl(<R::Type as CanIsoFromTo<S::Type>>::map_out(self.get_delegate(), from.get_delegate(), el.0, iso))
284 }
285}
286
287impl<R: RingStore, S: IntegerRing + ?Sized> CanHomFrom<S> for AsFieldBase<R>
291 where R::Type: DivisibilityRing + CanHomFrom<S>
292{
293 type Homomorphism = <R::Type as CanHomFrom<S>>::Homomorphism;
294
295 fn has_canonical_hom(&self, from: &S) -> Option<Self::Homomorphism> {
296 self.get_delegate().has_canonical_hom(from)
297 }
298
299 fn map_in(&self, from: &S, el: S::Element, hom: &Self::Homomorphism) -> Self::Element {
300 FieldEl(<R::Type as CanHomFrom<S>>::map_in(self.get_delegate(), from, el, hom))
301 }
302}
303
304impl<R1, R2> CanHomFrom<AsLocalPIRBase<R1>> for AsFieldBase<R2>
305 where R1: RingStore, R2: RingStore,
306 R2::Type: CanHomFrom<R1::Type>,
307 R1::Type: DivisibilityRing,
308 R2::Type: DivisibilityRing
309{
310 type Homomorphism = <R2::Type as CanHomFrom<R1::Type>>::Homomorphism;
311
312 fn has_canonical_hom(&self, from: &AsLocalPIRBase<R1>) -> Option<Self::Homomorphism> {
313 self.get_delegate().has_canonical_hom(from.get_delegate())
314 }
315
316 fn map_in(&self, from: &AsLocalPIRBase<R1>, el: <AsLocalPIRBase<R1> as RingBase>::Element, hom: &Self::Homomorphism) -> Self::Element {
317 self.rev_delegate(self.get_delegate().map_in(from.get_delegate(), from.delegate(el), hom))
318 }
319}
320
321impl<R1, R2> CanIsoFromTo<AsLocalPIRBase<R1>> for AsFieldBase<R2>
322 where R1: RingStore, R2: RingStore,
323 R2::Type: CanIsoFromTo<R1::Type>,
324 R1::Type: DivisibilityRing,
325 R2::Type: DivisibilityRing
326{
327 type Isomorphism = <R2::Type as CanIsoFromTo<R1::Type>>::Isomorphism;
328
329 fn has_canonical_iso(&self, from: &AsLocalPIRBase<R1>) -> Option<Self::Isomorphism> {
330 self.get_delegate().has_canonical_iso(from.get_delegate())
331 }
332
333 fn map_out(&self, from: &AsLocalPIRBase<R1>, el: Self::Element, iso: &Self::Isomorphism) -> <AsLocalPIRBase<R1> as RingBase>::Element {
334 from.rev_delegate(self.get_delegate().map_out(from.get_delegate(), self.delegate(el), iso))
335 }
336}
337
338impl<R: RingStore> PrincipalIdealRing for AsFieldBase<R>
339 where R::Type: DivisibilityRing
340{
341 fn checked_div_min(&self, lhs: &Self::Element, rhs: &Self::Element) -> Option<Self::Element> {
342 if self.is_zero(lhs) && self.is_zero(rhs) {
343 Some(self.one())
344 } else {
345 self.checked_left_div(lhs, rhs)
346 }
347 }
348
349 fn extended_ideal_gen(&self, lhs: &Self::Element, rhs: &Self::Element) -> (Self::Element, Self::Element, Self::Element) {
350 if self.is_zero(lhs) {
351 (self.zero(), self.one(), self.clone_el(rhs))
352 } else {
353 (self.one(), self.zero(), self.clone_el(lhs))
354 }
355 }
356}
357
358impl<R: RingStore> PrincipalLocalRing for AsFieldBase<R>
359 where R::Type: DivisibilityRing
360{
361 fn max_ideal_gen(&self) -> &Self::Element {
362 &self.zero
363 }
364
365 fn nilpotent_power(&self) -> Option<usize> {
366 Some(1)
367 }
368
369 fn valuation(&self, x: &Self::Element) -> Option<usize> {
370 if self.is_zero(x) {
371 return None;
372 } else {
373 return Some(0);
374 }
375 }
376}
377
378impl<R> InterpolationBaseRing for AsFieldBase<R>
379 where R: InterpolationBaseRingStore,
380 R::Type: InterpolationBaseRing
381{
382 type ExtendedRingBase<'a> = <R::Type as InterpolationBaseRing>::ExtendedRingBase<'a>
383 where Self: 'a;
384
385 type ExtendedRing<'a> = <R::Type as InterpolationBaseRing>::ExtendedRing<'a>
386 where Self: 'a;
387
388 fn in_base<'a, S>(&self, ext_ring: S, el: El<S>) -> Option<Self::Element>
389 where Self: 'a, S: RingStore<Type = Self::ExtendedRingBase<'a>>
390 {
391 self.get_delegate().in_base(ext_ring, el).map(|x| self.rev_delegate(x))
392 }
393
394 fn in_extension<'a, S>(&self, ext_ring: S, el: Self::Element) -> El<S>
395 where Self: 'a, S: RingStore<Type = Self::ExtendedRingBase<'a>>
396 {
397 self.get_delegate().in_extension(ext_ring, self.delegate(el))
398 }
399
400 fn interpolation_points<'a>(&'a self, count: usize) -> (Self::ExtendedRing<'a>, Vec<El<Self::ExtendedRing<'a>>>) {
401 self.get_delegate().interpolation_points(count)
402 }
403}
404
405impl<R: RingStore> EuclideanRing for AsFieldBase<R>
406 where R::Type: DivisibilityRing
407{
408 fn euclidean_div_rem(&self, lhs: Self::Element, rhs: &Self::Element) -> (Self::Element, Self::Element) {
409 assert!(!self.is_zero(rhs));
410 (self.checked_left_div(&lhs, rhs).unwrap(), self.zero())
411 }
412
413 fn euclidean_deg(&self, val: &Self::Element) -> Option<usize> {
414 if self.is_zero(val) {
415 Some(0)
416 } else {
417 Some(1)
418 }
419 }
420
421 fn euclidean_rem(&self, _: Self::Element, rhs: &Self::Element) -> Self::Element {
422 assert!(!self.is_zero(rhs));
423 self.zero()
424 }
425}
426
427impl<R: RingStore> Domain for AsFieldBase<R>
428 where R::Type: DivisibilityRing
429{}
430
431impl<R: RingStore> Field for AsFieldBase<R>
432 where R::Type: DivisibilityRing
433{
434 fn div(&self, lhs: &Self::Element, rhs: &Self::Element) -> Self::Element {
435 FieldEl(self.get_delegate().checked_left_div(&lhs.0, &rhs.0).unwrap())
436 }
437}
438
439impl<R: RingStore> KaratsubaHint for AsFieldBase<R>
440 where R::Type: DivisibilityRing
441{
442 fn karatsuba_threshold(&self) -> usize {
443 self.get_delegate().karatsuba_threshold()
444 }
445}
446
447impl<R: RingStore> ComputeInnerProduct for AsFieldBase<R>
448 where R::Type: DivisibilityRing
449{
450 fn inner_product<I: Iterator<Item = (Self::Element, Self::Element)>>(&self, els: I) -> Self::Element {
451 self.rev_delegate(self.get_delegate().inner_product(els.map(|(a, b)| (self.delegate(a), self.delegate(b)))))
452 }
453
454 fn inner_product_ref<'a, I: Iterator<Item = (&'a Self::Element, &'a Self::Element)>>(&self, els: I) -> Self::Element
455 where Self::Element: 'a,
456 Self: 'a
457 {
458 self.rev_delegate(self.get_delegate().inner_product_ref(els.map(|(a, b)| (self.delegate_ref(a), self.delegate_ref(b)))))
459 }
460
461 fn inner_product_ref_fst<'a, I: Iterator<Item = (&'a Self::Element, Self::Element)>>(&self, els: I) -> Self::Element
462 where Self::Element: 'a,
463 Self: 'a
464 {
465 self.rev_delegate(self.get_delegate().inner_product_ref_fst(els.map(|(a, b)| (self.delegate_ref(a), self.delegate(b)))))
466 }
467}
468
469impl<R: RingStore> StrassenHint for AsFieldBase<R>
470 where R::Type: DivisibilityRing
471{
472 fn strassen_threshold(&self) -> usize {
473 self.get_delegate().strassen_threshold()
474 }
475}
476
477impl<R> FromModulusCreateableZnRing for AsFieldBase<RingValue<R>>
478 where R: DivisibilityRing + ZnRing + FromModulusCreateableZnRing
479{
480 fn from_modulus<F, E>(create_modulus: F) -> Result<Self, E>
481 where F:FnOnce(&Self::IntegerRingBase) -> Result<El<Self::IntegerRing>, E>
482 {
483 <R as FromModulusCreateableZnRing>::from_modulus(create_modulus).map(|ring| RingValue::from(ring).as_field().ok().unwrap().into())
484 }
485}
486
487impl<R> Serialize for AsFieldBase<R>
488 where R: RingStore + Serialize,
489 R::Type: DivisibilityRing
490{
491 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
492 where S: Serializer
493 {
494 SerializableNewtypeStruct::new("AsField", &self.base).serialize(serializer)
495 }
496}
497
498impl<'de, R> Deserialize<'de> for AsFieldBase<R>
499 where R: RingStore + Deserialize<'de>,
500 R::Type: DivisibilityRing
501{
502 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
503 where D: Deserializer<'de>
504 {
505 DeserializeSeedNewtypeStruct::new("AsField", PhantomData::<R>).deserialize(deserializer).map(|base_ring| AsFieldBase { zero: FieldEl(base_ring.zero()), base: base_ring })
506 }
507}
508
509#[macro_export]
569macro_rules! impl_field_wrap_unwrap_homs {
570 (<{$($gen_args:tt)*}> $self_type_from:ty, $self_type_to:ty where $($constraints:tt)*) => {
571
572 impl<AsFieldRingStore, $($gen_args)*> CanHomFrom<$self_type_from> for $crate::rings::field::AsFieldBase<AsFieldRingStore>
573 where AsFieldRingStore: RingStore<Type = $self_type_to>, $($constraints)*
574 {
575 type Homomorphism = <$self_type_to as CanHomFrom<$self_type_from>>::Homomorphism;
576
577 fn has_canonical_hom(&self, from: &$self_type_from) -> Option<Self::Homomorphism> {
578 self.get_delegate().has_canonical_hom(from)
579 }
580
581 fn map_in(&self, from: &$self_type_from, el: <$self_type_from as $crate::ring::RingBase>::Element, hom: &Self::Homomorphism) -> <Self as $crate::ring::RingBase>::Element {
582 self.rev_delegate(self.get_delegate().map_in(from, el, hom))
583 }
584 }
585
586 impl<AsFieldRingStore, $($gen_args)*> CanHomFrom<$crate::rings::field::AsFieldBase<AsFieldRingStore>> for $self_type_to
587 where AsFieldRingStore: RingStore<Type = $self_type_from>, $($constraints)*
588 {
589 type Homomorphism = <$self_type_to as CanHomFrom<$self_type_from>>::Homomorphism;
590
591 fn has_canonical_hom(&self, from: &$crate::rings::field::AsFieldBase<AsFieldRingStore>) -> Option<Self::Homomorphism> {
592 self.has_canonical_hom(from.get_delegate())
593 }
594
595 fn map_in(&self, from: &$crate::rings::field::AsFieldBase<AsFieldRingStore>, el: $crate::rings::field::FieldEl<AsFieldRingStore>, hom: &Self::Homomorphism) -> <Self as $crate::ring::RingBase>::Element {
596 self.map_in(from.get_delegate(), from.delegate(el), hom)
597 }
598 }
599 };
600 ($self_type_from:ty, $self_type_to:ty) => {
601 impl_field_wrap_unwrap_homs!{ <{}> $self_type_from, $self_type_to where }
602 };
603}
604
605#[macro_export]
612macro_rules! impl_field_wrap_unwrap_isos {
613 (<{$($gen_args:tt)*}> $self_type_from:ty, $self_type_to:ty where $($constraints:tt)*) => {
614
615 impl<AsFieldRingStore, $($gen_args)*> CanIsoFromTo<$self_type_from> for $crate::rings::field::AsFieldBase<AsFieldRingStore>
616 where AsFieldRingStore: RingStore<Type = $self_type_to>, $($constraints)*
617 {
618 type Isomorphism = <$self_type_to as CanIsoFromTo<$self_type_from>>::Isomorphism;
619
620 fn has_canonical_iso(&self, from: &$self_type_from) -> Option<Self::Isomorphism> {
621 self.get_delegate().has_canonical_iso(from)
622 }
623
624 fn map_out(&self, from: &$self_type_from, el: <Self as RingBase>::Element, iso: &Self::Isomorphism) -> <$self_type_from as RingBase>::Element {
625 self.get_delegate().map_out(from, self.delegate(el), iso)
626 }
627 }
628
629 impl<AsFieldRingStore, $($gen_args)*> CanIsoFromTo<$crate::rings::field::AsFieldBase<AsFieldRingStore>> for $self_type_to
630 where AsFieldRingStore: RingStore<Type = $self_type_from>, $($constraints)*
631 {
632 type Isomorphism = <$self_type_to as CanIsoFromTo<$self_type_from>>::Isomorphism;
633
634 fn has_canonical_iso(&self, from: &$crate::rings::field::AsFieldBase<AsFieldRingStore>) -> Option<Self::Isomorphism> {
635 self.has_canonical_iso(from.get_delegate())
636 }
637
638 fn map_out(&self, from: &$crate::rings::field::AsFieldBase<AsFieldRingStore>, el: <Self as RingBase>::Element, hom: &Self::Isomorphism) -> $crate::rings::field::FieldEl<AsFieldRingStore> {
639 from.rev_delegate(self.map_out(from.get_delegate(), el, hom))
640 }
641 }
642 };
643 ($self_type_from:ty, $self_type_to:ty) => {
644 impl_field_wrap_unwrap_isos!{ <{}> $self_type_from, $self_type_to where }
645 };
646}
647
648#[cfg(test)]
649use crate::rings::zn::zn_big::Zn;
650#[cfg(test)]
651use crate::rings::finite::FiniteRingStore;
652
653#[test]
654fn test_canonical_hom_axioms_static_int() {
655 let R = Zn::new(StaticRing::<i64>::RING, 17).as_field().ok().unwrap();
656 crate::ring::generic_tests::test_hom_axioms(StaticRing::<i64>::RING, &R, 0..17);
657}
658
659#[test]
660fn test_divisibility_axioms() {
661 let R = Zn::new(StaticRing::<i64>::RING, 17).as_field().ok().unwrap();
662 crate::divisibility::generic_tests::test_divisibility_axioms(&R, R.elements());
663}
664
665#[test]
666fn test_canonical_hom_axioms_wrap_unwrap() {
667 let R = Zn::new(StaticRing::<i64>::RING, 17).as_field().ok().unwrap();
668 crate::ring::generic_tests::test_hom_axioms(RingRef::new(R.get_ring().get_delegate()), &R, RingRef::new(R.get_ring().get_delegate()).elements());
669 crate::ring::generic_tests::test_iso_axioms(RingRef::new(R.get_ring().get_delegate()), &R, RingRef::new(R.get_ring().get_delegate()).elements());
670}
671
672#[test]
673fn test_principal_ideal_ring_axioms() {
674 let R = Zn::new(StaticRing::<i64>::RING, 17).as_field().ok().unwrap();
675 crate::pid::generic_tests::test_principal_ideal_ring_axioms(&R, R.elements());
676 crate::pid::generic_tests::test_euclidean_ring_axioms(&R, R.elements());
677}
678
679#[test]
680fn test_field_axioms() {
681 let R = Zn::new(StaticRing::<i64>::RING, 17).as_field().ok().unwrap();
682 crate::field::generic_tests::test_field_axioms(&R, R.elements());
683}