1use core::marker::PhantomData;
16
17use p3_field::{Algebra, Field, InjectiveMonomial};
18use p3_symmetric::Permutation;
19
20use crate::external::{
21 FullRoundConstants, FullRoundLayer, FullRoundLayerConstructor,
22 full_round_initial_permute_state, full_round_terminal_permute_state, mds_multiply,
23};
24use crate::internal::{
25 PartialRoundConstants, PartialRoundLayer, PartialRoundLayerConstructor, cheap_matmul,
26 partial_permute_state, textbook_partial_permute_state,
27};
28
29#[inline(always)]
31pub fn add_rc_and_sbox_generic<F: Field, A: Algebra<F> + InjectiveMonomial<D>, const D: u64>(
32 val: &mut A,
33 rc: F,
34) {
35 *val += rc;
36 *val = val.injective_exp_n();
37}
38
39pub trait GenericPoseidon1LinearLayers<F: Field, const WIDTH: usize>: Sync {
44 fn mds_multiply<R: Algebra<F>>(state: &mut [R; WIDTH], mds: &[[F; WIDTH]; WIDTH]) {
48 mds_multiply(state, mds);
49 }
50
51 fn mds_permute<R: Algebra<F>>(state: &mut [R; WIDTH], mds: &impl Permutation<[R; WIDTH]>) {
56 mds.permute_mut(state);
57 }
58
59 fn cheap_matmul<R: Algebra<F>>(state: &mut [R; WIDTH], first_row: &[F; WIDTH], v: &[F; WIDTH]) {
61 cheap_matmul(state, first_row, v);
62 }
63}
64
65#[derive(Debug, Clone)]
74pub struct Poseidon1ExternalLayerGeneric<F, Mds, const WIDTH: usize> {
75 constants: FullRoundConstants<F, WIDTH>,
76 _mds: PhantomData<Mds>,
77}
78
79impl<F: Field, Mds, const WIDTH: usize> FullRoundLayerConstructor<F, WIDTH>
80 for Poseidon1ExternalLayerGeneric<F, Mds, WIDTH>
81{
82 fn new_from_constants(constants: FullRoundConstants<F, WIDTH>) -> Self {
83 Self {
84 constants,
85 _mds: PhantomData,
86 }
87 }
88}
89
90impl<F, A, Mds, const WIDTH: usize, const D: u64> FullRoundLayer<A, WIDTH, D>
91 for Poseidon1ExternalLayerGeneric<F, Mds, WIDTH>
92where
93 F: Field + InjectiveMonomial<D>,
94 A: Algebra<F> + InjectiveMonomial<D>,
95 Mds: Permutation<[A; WIDTH]> + Default + Sync + Clone,
96{
97 fn permute_state_initial(&self, state: &mut [A; WIDTH]) {
98 let mds = Mds::default();
99 full_round_initial_permute_state::<F, A, _, WIDTH, D>(state, &self.constants, &mds);
100 }
101
102 fn permute_state_terminal(&self, state: &mut [A; WIDTH]) {
103 let mds = Mds::default();
104 full_round_terminal_permute_state::<F, A, _, WIDTH, D>(state, &self.constants, &mds);
105 }
106}
107
108#[derive(Debug, Clone)]
114pub struct Poseidon1InternalLayerGeneric<F, const WIDTH: usize> {
115 constants: PartialRoundConstants<F, WIDTH>,
116}
117
118impl<F: Field, const WIDTH: usize> PartialRoundLayerConstructor<F, WIDTH>
119 for Poseidon1InternalLayerGeneric<F, WIDTH>
120{
121 fn new_from_constants(constants: PartialRoundConstants<F, WIDTH>) -> Self {
122 Self { constants }
123 }
124}
125
126impl<F, A, const WIDTH: usize, const D: u64> PartialRoundLayer<A, WIDTH, D>
127 for Poseidon1InternalLayerGeneric<F, WIDTH>
128where
129 F: Field + InjectiveMonomial<D>,
130 A: Algebra<F> + InjectiveMonomial<D>,
131{
132 fn permute_state(&self, state: &mut [A; WIDTH]) {
133 partial_permute_state::<F, A, WIDTH, D>(state, &self.constants);
134 }
135}
136
137#[derive(Debug, Clone)]
146pub struct Poseidon1InternalLayerTextbook<F, Mds, const WIDTH: usize> {
147 constants: PartialRoundConstants<F, WIDTH>,
148 _mds: PhantomData<Mds>,
149}
150
151impl<F: Field, Mds, const WIDTH: usize> PartialRoundLayerConstructor<F, WIDTH>
152 for Poseidon1InternalLayerTextbook<F, Mds, WIDTH>
153{
154 fn new_from_constants(constants: PartialRoundConstants<F, WIDTH>) -> Self {
155 Self {
156 constants,
157 _mds: PhantomData,
158 }
159 }
160}
161
162impl<F, A, Mds, const WIDTH: usize, const D: u64> PartialRoundLayer<A, WIDTH, D>
163 for Poseidon1InternalLayerTextbook<F, Mds, WIDTH>
164where
165 F: Field + InjectiveMonomial<D>,
166 A: Algebra<F> + InjectiveMonomial<D>,
167 Mds: Permutation<[A; WIDTH]> + Default + Sync + Clone,
168{
169 fn permute_state(&self, state: &mut [A; WIDTH]) {
170 let mds = Mds::default();
171 textbook_partial_permute_state::<F, A, _, WIDTH, D>(state, &self.constants, &mds);
172 }
173}