algebra/module/homomorphism/
mod.rs1use std::sync::Arc;
2
3use fp::{
4 matrix::{AugmentedMatrix, Matrix, MatrixSliceMut, QuasiInverse, Subspace},
5 prime::ValidPrime,
6 vector::{FpSlice, FpSliceMut},
7};
8
9use crate::module::Module;
10
11mod free_module_homomorphism;
12mod full_module_homomorphism;
13mod generic_zero_homomorphism;
14mod hom_pullback;
15mod quotient_homomorphism;
16
17pub use free_module_homomorphism::{
18 FreeModuleHomomorphism, MuFreeModuleHomomorphism, UnstableFreeModuleHomomorphism,
19};
20pub use full_module_homomorphism::FullModuleHomomorphism;
21pub use generic_zero_homomorphism::GenericZeroHomomorphism;
22pub use hom_pullback::HomPullback;
23#[allow(unused_imports)]
28use maybe_rayon::prelude::*;
29pub use quotient_homomorphism::{QuotientHomomorphism, QuotientHomomorphismSource};
30
31pub trait ModuleHomomorphism: Send + Sync {
43 type Source: Module;
44 type Target: Module<Algebra = <Self::Source as Module>::Algebra>;
45
46 fn source(&self) -> Arc<Self::Source>;
47 fn target(&self) -> Arc<Self::Target>;
48 fn degree_shift(&self) -> i32;
49
50 fn apply_to_basis_element(
54 &self,
55 result: FpSliceMut,
56 coeff: u32,
57 input_degree: i32,
58 input_idx: usize,
59 );
60
61 #[allow(unused_variables)]
62 fn kernel(&self, degree: i32) -> Option<&Subspace> {
63 None
64 }
65
66 #[allow(unused_variables)]
67 fn quasi_inverse(&self, degree: i32) -> Option<&QuasiInverse> {
68 None
69 }
70
71 #[allow(unused_variables)]
72 fn image(&self, degree: i32) -> Option<&Subspace> {
73 None
74 }
75
76 #[allow(unused_variables)]
77 fn compute_auxiliary_data_through_degree(&self, degree: i32) {}
78
79 fn apply(&self, mut result: FpSliceMut, coeff: u32, input_degree: i32, input: FpSlice) {
80 let p = self.prime();
81 for (i, v) in input.iter_nonzero() {
82 self.apply_to_basis_element(result.copy(), (coeff * v) % p, input_degree, i);
83 }
84 }
85
86 fn prime(&self) -> ValidPrime {
87 self.source().prime()
88 }
89
90 fn min_degree(&self) -> i32 {
91 self.source().min_degree()
92 }
93
94 fn auxiliary_data(&self, degree: i32) -> (Subspace, Subspace, QuasiInverse) {
97 let p = self.prime();
98 let output_degree = degree - self.degree_shift();
99 self.source().compute_basis(degree);
100 self.target().compute_basis(output_degree);
101 let source_dimension = self.source().dimension(degree);
102 let target_dimension = self.target().dimension(output_degree);
103 let mut matrix =
104 AugmentedMatrix::<2>::new(p, source_dimension, [target_dimension, source_dimension]);
105
106 self.get_matrix(matrix.segment(0, 0), degree);
107 matrix.segment(1, 1).add_identity();
108
109 matrix.row_reduce();
110
111 (
112 matrix.compute_image(),
113 matrix.compute_kernel(),
114 matrix.compute_quasi_inverse(),
115 )
116 }
117
118 fn get_matrix(&self, mut matrix: MatrixSliceMut, degree: i32) {
123 assert_eq!(self.source().dimension(degree), matrix.rows());
124 assert_eq!(
125 self.target().dimension(degree - self.degree_shift()),
126 matrix.columns()
127 );
128
129 if matrix.columns() == 0 {
130 return;
131 }
132
133 matrix
134 .maybe_par_iter_mut()
135 .enumerate()
136 .for_each(|(i, row)| self.apply_to_basis_element(row, 1, degree, i));
137 }
138
139 fn get_partial_matrix(&self, degree: i32, inputs: &[usize]) -> Matrix {
141 let mut matrix = Matrix::new(self.prime(), inputs.len(), self.target().dimension(degree));
142
143 if matrix.columns() == 0 {
144 return matrix;
145 }
146
147 matrix
148 .maybe_par_iter_mut()
149 .enumerate()
150 .for_each(|(i, row)| self.apply_to_basis_element(row, 1, degree, inputs[i]));
151
152 matrix
153 }
154
155 #[must_use]
158 fn apply_quasi_inverse(&self, result: FpSliceMut, degree: i32, input: FpSlice) -> bool {
159 if let Some(qi) = self.quasi_inverse(degree) {
160 qi.apply(result, 1, input);
161 true
162 } else {
163 false
164 }
165 }
166}
167
168pub trait ZeroHomomorphism<S: Module, T: Module<Algebra = S::Algebra>>:
169 ModuleHomomorphism<Source = S, Target = T>
170{
171 fn zero_homomorphism(s: Arc<S>, t: Arc<T>, degree_shift: i32) -> Self;
172}
173
174pub trait IdentityHomomorphism<S: Module>: ModuleHomomorphism<Source = S, Target = S> {
175 fn identity_homomorphism(s: Arc<S>) -> Self;
176}