algebra/module/homomorphism/
quotient_homomorphism.rs1use std::sync::Arc;
2
3use fp::vector::{FpSliceMut, FpVector};
4
5use crate::module::{Module, QuotientModule, homomorphism::ModuleHomomorphism};
6
7pub struct QuotientHomomorphism<F: ModuleHomomorphism> {
8 f: Arc<F>,
9 s: Arc<QuotientModule<F::Source>>,
10 t: Arc<QuotientModule<F::Target>>,
11}
12
13impl<F: ModuleHomomorphism> QuotientHomomorphism<F> {
14 pub fn new(
15 f: Arc<F>,
16 s: Arc<QuotientModule<F::Source>>,
17 t: Arc<QuotientModule<F::Target>>,
18 ) -> Self {
19 Self { f, s, t }
20 }
21}
22
23impl<F: ModuleHomomorphism> ModuleHomomorphism for QuotientHomomorphism<F> {
24 type Source = QuotientModule<F::Source>;
25 type Target = QuotientModule<F::Target>;
26
27 fn source(&self) -> Arc<Self::Source> {
28 Arc::clone(&self.s)
29 }
30
31 fn target(&self) -> Arc<Self::Target> {
32 Arc::clone(&self.t)
33 }
34
35 fn degree_shift(&self) -> i32 {
36 self.f.degree_shift()
37 }
38
39 fn apply_to_basis_element(
40 &self,
41 result: FpSliceMut,
42 coeff: u32,
43 input_degree: i32,
44 input_idx: usize,
45 ) {
46 let output_degree = input_degree - self.degree_shift();
47 let mut result_ = FpVector::new(self.prime(), self.t.module.dimension(output_degree));
48 self.f.apply_to_basis_element(
49 result_.as_slice_mut(),
50 coeff,
51 input_degree,
52 self.s.basis_list[input_degree][input_idx],
53 );
54
55 self.t.reduce(output_degree, result_.as_slice_mut());
56 self.t
57 .old_basis_to_new(output_degree, result, result_.as_slice());
58 }
59}
60
61pub struct QuotientHomomorphismSource<F: ModuleHomomorphism> {
62 f: Arc<F>,
63 s: Arc<QuotientModule<F::Source>>,
64}
65
66impl<F: ModuleHomomorphism> QuotientHomomorphismSource<F> {
67 pub fn new(f: Arc<F>, s: Arc<QuotientModule<F::Source>>) -> Self {
68 Self { f, s }
69 }
70}
71
72impl<F: ModuleHomomorphism> ModuleHomomorphism for QuotientHomomorphismSource<F> {
73 type Source = QuotientModule<F::Source>;
74 type Target = F::Target;
75
76 fn source(&self) -> Arc<Self::Source> {
77 Arc::clone(&self.s)
78 }
79
80 fn target(&self) -> Arc<Self::Target> {
81 self.f.target()
82 }
83
84 fn degree_shift(&self) -> i32 {
85 self.f.degree_shift()
86 }
87
88 fn apply_to_basis_element(
89 &self,
90 result: FpSliceMut,
91 coeff: u32,
92 input_degree: i32,
93 input_idx: usize,
94 ) {
95 self.f.apply_to_basis_element(
96 result,
97 coeff,
98 input_degree,
99 self.s.basis_list[input_degree][input_idx],
100 );
101 }
102}