1use super::field::{AsField, AsFieldBase};
2use super::poly::dense_poly::DensePolyRing;
3use super::poly::{PolyRing, PolyRingStore};
4use crate::algorithms::extension_ops;
5use crate::algorithms::linsolve::LinSolveRing;
6use crate::algorithms::poly_factor::FactorPolyField;
7use crate::divisibility::DivisibilityRing;
8use crate::field::*;
9use crate::homomorphism::*;
10use crate::pid::PrincipalIdealRing;
11use crate::ring::*;
12use crate::seq::*;
13use crate::wrapper::RingElementWrapper;
14
15pub mod extension_impl;
18
19pub mod galois_field;
21
22pub mod number_field;
24
25pub mod conway;
27
28pub trait FreeAlgebra: RingExtension {
80 type VectorRepresentation<'a>: VectorFn<El<Self::BaseRing>>
83 where
84 Self: 'a;
85
86 fn canonical_gen(&self) -> Self::Element;
88
89 fn rank(&self) -> usize;
91
92 fn wrt_canonical_basis<'a>(&'a self, el: &'a Self::Element) -> Self::VectorRepresentation<'a>;
98
99 fn from_canonical_basis<V>(&self, vec: V) -> Self::Element
105 where
106 V: IntoIterator<Item = El<Self::BaseRing>>,
107 V::IntoIter: DoubleEndedIterator,
108 {
109 let mut given_len = 0;
110 let x = self.canonical_gen();
111 let mut result = self.zero();
112 for c in vec.into_iter().rev() {
113 self.mul_assign_ref(&mut result, &x);
114 self.add_assign(&mut result, self.from(c));
115 given_len += 1;
116 }
117 assert_eq!(given_len, self.rank());
118 return result;
119 }
120
121 fn mul_assign_gen_power(&self, el: &mut Self::Element, power: usize) {
124 self.mul_assign(el, RingRef::new(self).pow(self.canonical_gen(), power));
125 }
126
127 fn from_canonical_basis_extended<V>(&self, vec: V) -> Self::Element
131 where
132 V: IntoIterator<Item = El<Self::BaseRing>>,
133 {
134 extension_ops::from_canonical_basis_extended(self, vec)
135 }
136
137 fn charpoly<P, H>(&self, el: &Self::Element, poly_ring: P, hom: H) -> El<P>
143 where
144 P: RingStore,
145 P::Type: PolyRing,
146 <<P::Type as RingExtension>::BaseRing as RingStore>::Type: LinSolveRing,
147 H: Homomorphism<<Self::BaseRing as RingStore>::Type, <<P::Type as RingExtension>::BaseRing as RingStore>::Type>,
148 {
149 extension_ops::charpoly(self, el, poly_ring, hom)
150 }
151
152 fn minpoly<P, H>(&self, el: &Self::Element, poly_ring: P, hom: H) -> El<P>
165 where
166 P: RingStore,
167 P::Type: PolyRing,
168 <<P::Type as RingExtension>::BaseRing as RingStore>::Type: LinSolveRing,
169 H: Homomorphism<<Self::BaseRing as RingStore>::Type, <<P::Type as RingExtension>::BaseRing as RingStore>::Type>,
170 {
171 extension_ops::minpoly(self, el, poly_ring, hom)
172 }
173
174 fn trace(&self, el: Self::Element) -> El<Self::BaseRing> {
182 let mut current = el;
183 let generator = self.canonical_gen();
184 return self.base_ring().sum((0..self.rank()).map(|i| {
185 let result = self.wrt_canonical_basis(¤t).at(i);
186 self.mul_assign_ref(&mut current, &generator);
187 return result;
188 }));
189 }
190
191 fn discriminant(&self) -> El<Self::BaseRing>
202 where
203 <Self::BaseRing as RingStore>::Type: PrincipalIdealRing,
204 {
205 extension_ops::discriminant(self)
206 }
207}
208
209pub trait FreeAlgebraStore: RingStore
211where
212 Self::Type: FreeAlgebra,
213{
214 delegate! { FreeAlgebra, fn canonical_gen(&self) -> El<Self> }
215 delegate! { FreeAlgebra, fn rank(&self) -> usize }
216 delegate! { FreeAlgebra, fn trace(&self, el: El<Self>) -> El<<Self::Type as RingExtension>::BaseRing> }
217 delegate! { FreeAlgebra, fn mul_assign_gen_power(&self, el: &mut El<Self>, power: usize) -> () }
218
219 fn wrt_canonical_basis<'a>(&'a self, el: &'a El<Self>) -> <Self::Type as FreeAlgebra>::VectorRepresentation<'a> {
221 self.get_ring().wrt_canonical_basis(el)
222 }
223
224 fn from_canonical_basis<V>(&self, vec: V) -> El<Self>
226 where
227 V: IntoIterator<Item = El<<Self::Type as RingExtension>::BaseRing>>,
228 V::IntoIter: DoubleEndedIterator,
229 {
230 self.get_ring().from_canonical_basis(vec)
231 }
232
233 fn from_canonical_basis_extended<V>(&self, vec: V) -> El<Self>
235 where
236 V: IntoIterator<Item = El<<Self::Type as RingExtension>::BaseRing>>,
237 {
238 self.get_ring().from_canonical_basis_extended(vec)
239 }
240
241 fn generating_poly<P, H>(&self, poly_ring: P, hom: H) -> El<P>
244 where
245 P: PolyRingStore,
246 P::Type: PolyRing,
247 H: Homomorphism<
248 <<Self::Type as RingExtension>::BaseRing as RingStore>::Type,
249 <<P::Type as RingExtension>::BaseRing as RingStore>::Type,
250 >,
251 {
252 assert!(hom.domain().get_ring() == self.base_ring().get_ring());
253 poly_ring.sub(
254 poly_ring.from_terms([(poly_ring.base_ring().one(), self.rank())]),
255 self.poly_repr(&poly_ring, &self.pow(self.canonical_gen(), self.rank()), hom),
256 )
257 }
258
259 fn as_field(self) -> Result<AsField<Self>, Self>
264 where
265 Self::Type: DivisibilityRing,
266 <<Self::Type as RingExtension>::BaseRing as RingStore>::Type: Field + FactorPolyField,
267 {
268 let poly_ring = DensePolyRing::new(self.base_ring(), "X");
269 if <_ as FactorPolyField>::factor_poly(
270 &poly_ring,
271 &self.generating_poly(&poly_ring, self.base_ring().identity()),
272 )
273 .0
274 .len()
275 > 1
276 {
277 return Err(self);
278 } else {
279 return Ok(RingValue::from(AsFieldBase::promise_is_perfect_field(self)));
280 }
281 }
282
283 fn poly_repr<P, H>(&self, to: P, el: &El<Self>, hom: H) -> El<P>
287 where
288 P: PolyRingStore,
289 P::Type: PolyRing,
290 H: Homomorphism<
291 <<Self::Type as RingExtension>::BaseRing as RingStore>::Type,
292 <<P::Type as RingExtension>::BaseRing as RingStore>::Type,
293 >,
294 {
295 let coeff_vec = self.wrt_canonical_basis(el);
296 to.from_terms(
297 (0..self.rank())
298 .map(|i| coeff_vec.at(i))
299 .enumerate()
300 .filter(|(_, x)| !self.base_ring().is_zero(x))
301 .map(|(j, x)| (hom.map(x), j)),
302 )
303 }
304
305 fn discriminant(&self) -> El<<Self::Type as RingExtension>::BaseRing>
311 where
312 <<Self::Type as RingExtension>::BaseRing as RingStore>::Type: PrincipalIdealRing,
313 {
314 self.get_ring().discriminant()
315 }
316
317 fn charpoly<P, H>(&self, el: &El<Self>, poly_ring: P, hom: H) -> El<P>
319 where
320 P: RingStore,
321 P::Type: PolyRing,
322 <<P::Type as RingExtension>::BaseRing as RingStore>::Type: LinSolveRing,
323 H: Homomorphism<
324 <<Self::Type as RingExtension>::BaseRing as RingStore>::Type,
325 <<P::Type as RingExtension>::BaseRing as RingStore>::Type,
326 >,
327 {
328 self.get_ring().charpoly(el, poly_ring, hom)
329 }
330
331 #[stability::unstable(feature = "enable")]
334 fn with_wrapped_generator<'a, F, const M: usize>(&'a self, f: F) -> [El<Self>; M]
335 where
336 F: FnOnce(&RingElementWrapper<&'a Self>) -> [RingElementWrapper<&'a Self>; M],
337 {
338 let wrapped_indet = RingElementWrapper::new(self, self.canonical_gen());
339 let mut result_it = f(&wrapped_indet).into_iter();
340 return std::array::from_fn(|_| result_it.next().unwrap().unwrap());
341 }
342}
343
344impl<R: RingStore> FreeAlgebraStore for R where R::Type: FreeAlgebra {}
345
346#[stability::unstable(feature = "enable")]
347pub struct FreeAlgebraHom<R, S>
348where
349 R: RingStore,
350 R::Type: FreeAlgebra,
351 S: RingStore,
352 S::Type: FreeAlgebra,
353 <S::Type as RingExtension>::BaseRing: RingStore<Type = <<R::Type as RingExtension>::BaseRing as RingStore>::Type>,
354{
355 from: R,
356 to: S,
357 image_of_generator: El<S>,
358}
359
360impl<R> FreeAlgebraHom<R, R>
361where
362 R: RingStore + Clone,
363 R::Type: FreeAlgebra,
364{
365 #[stability::unstable(feature = "enable")]
366 pub fn identity(ring: R) -> Self {
367 Self {
368 image_of_generator: ring.canonical_gen(),
369 from: ring.clone(),
370 to: ring,
371 }
372 }
373}
374
375impl<R, S> FreeAlgebraHom<R, S>
376where
377 R: RingStore,
378 R::Type: FreeAlgebra,
379 S: RingStore,
380 S::Type: FreeAlgebra,
381 <S::Type as RingExtension>::BaseRing: RingStore<Type = <<R::Type as RingExtension>::BaseRing as RingStore>::Type>,
382{
383 #[stability::unstable(feature = "enable")]
390 pub fn promise_is_well_defined(from: R, to: S, image_of_generator: El<S>) -> Self {
391 assert!(from.base_ring().get_ring() == to.base_ring().get_ring());
392 Self {
393 from,
394 to,
395 image_of_generator,
396 }
397 }
398
399 #[stability::unstable(feature = "enable")]
405 pub fn new(from: R, to: S, image_of_generator: El<S>) -> Self {
406 assert!(from.base_ring().get_ring() == to.base_ring().get_ring());
407 let poly_ring = DensePolyRing::new(to.base_ring(), "X");
408 assert!(to.is_zero(&poly_ring.evaluate(
409 &from.generating_poly(&poly_ring, poly_ring.base_ring().identity()),
410 &image_of_generator,
411 to.inclusion()
412 )));
413 Self {
414 from,
415 to,
416 image_of_generator,
417 }
418 }
419
420 #[stability::unstable(feature = "enable")]
423 pub fn destruct(self) -> (R, S, El<S>) { (self.from, self.to, self.image_of_generator) }
424}
425
426impl<R, S> Homomorphism<R::Type, S::Type> for FreeAlgebraHom<R, S>
427where
428 R: RingStore,
429 R::Type: FreeAlgebra,
430 S: RingStore,
431 S::Type: FreeAlgebra,
432 <S::Type as RingExtension>::BaseRing: RingStore<Type = <<R::Type as RingExtension>::BaseRing as RingStore>::Type>,
433{
434 type DomainStore = R;
435 type CodomainStore = S;
436
437 fn domain(&self) -> &Self::DomainStore { &self.from }
438
439 fn codomain(&self) -> &Self::CodomainStore { &self.to }
440
441 fn map(&self, x: El<R>) -> El<S> { self.map_ref(&x) }
442
443 fn map_ref(&self, x: &El<R>) -> El<S> {
444 let poly_ring = DensePolyRing::new(self.to.base_ring(), "X");
445 return poly_ring.evaluate(
446 &self.from.poly_repr(&poly_ring, x, self.to.base_ring().identity()),
447 &self.image_of_generator,
448 self.to.inclusion(),
449 );
450 }
451}
452
453#[cfg(any(test, feature = "generic_tests"))]
454pub mod generic_tests {
455 use super::*;
456
457 pub fn test_free_algebra_axioms<R: FreeAlgebraStore>(ring: R)
458 where
459 R::Type: FreeAlgebra,
460 {
461 let x = ring.canonical_gen();
462 let n = ring.rank();
463
464 let xn_original = ring.pow(ring.clone_el(&x), n);
465 let xn_vec = ring.wrt_canonical_basis(&xn_original);
466 let xn = ring.sum(Iterator::map(0..n, |i| {
467 ring.mul(ring.inclusion().map(xn_vec.at(i)), ring.pow(ring.clone_el(&x), i))
468 }));
469 assert_el_eq!(ring, xn_original, xn);
470
471 let x_n_1_vec_expected = (0..n).map_fn(|i| {
472 if i > 0 {
473 ring.base_ring()
474 .add(ring.base_ring().mul(xn_vec.at(n - 1), xn_vec.at(i)), xn_vec.at(i - 1))
475 } else {
476 ring.base_ring().mul(xn_vec.at(n - 1), xn_vec.at(0))
477 }
478 });
479 let x_n_1 = ring.pow(ring.clone_el(&x), n + 1);
480 let x_n_1_vec_actual = ring.wrt_canonical_basis(&x_n_1);
481 for i in 0..n {
482 assert_el_eq!(ring.base_ring(), x_n_1_vec_expected.at(i), x_n_1_vec_actual.at(i));
483 }
484
485 for i in (0..ring.rank()).step_by(3) {
488 for j in (1..ring.rank()).step_by(5) {
489 if i == j {
490 continue;
491 }
492 let element = ring.from_canonical_basis((0..n).map(|k| {
493 if k == i {
494 ring.base_ring().one()
495 } else if k == j {
496 ring.base_ring().int_hom().map(2)
497 } else {
498 ring.base_ring().zero()
499 }
500 }));
501 let expected = ring.add(
502 ring.pow(ring.clone_el(&x), i),
503 ring.int_hom().mul_map(ring.pow(ring.clone_el(&x), j), 2),
504 );
505 assert_el_eq!(ring, expected, element);
506 let element_vec = ring.wrt_canonical_basis(&expected);
507 for k in 0..ring.rank() {
508 if k == i {
509 assert_el_eq!(ring.base_ring(), ring.base_ring().one(), element_vec.at(k));
510 } else if k == j {
511 assert_el_eq!(ring.base_ring(), ring.base_ring().int_hom().map(2), element_vec.at(k));
512 } else {
513 assert_el_eq!(ring.base_ring(), ring.base_ring().zero(), element_vec.at(k));
514 }
515 }
516 }
517 }
518
519 for i in (0..ring.rank()).step_by(3) {
521 for j in (0..ring.rank()).step_by(5) {
522 let element = ring.add(ring.pow(ring.canonical_gen(), i), ring.one());
523 let mut actual = ring.clone_el(&element);
524 ring.mul_assign_gen_power(&mut actual, j);
525 assert_el_eq!(ring, ring.mul(element, ring.pow(ring.canonical_gen(), j)), actual);
526 }
527 }
528 }
529}