poseidon_primitives/poseidon/primitives/
p128pow5t3_compact.rs
1use std::marker::PhantomData;
2
3use ff::PrimeField;
4
5use super::p128pow5t3::P128Pow5T3Constants;
6use super::{Mds, Spec};
7
8#[derive(Debug)]
12pub struct P128Pow5T3Compact<Fp> {
13 _marker: PhantomData<Fp>,
14}
15
16impl<Fp: P128Pow5T3Constants> Spec<Fp, 3, 2> for P128Pow5T3Compact<Fp> {
17 fn full_rounds() -> usize {
18 8
19 }
20
21 fn partial_rounds() -> usize {
22 Fp::partial_rounds()
23 }
24
25 fn sbox(val: Fp) -> Fp {
26 val.pow_vartime([5])
27 }
28
29 fn secure_mds() -> usize {
30 unimplemented!()
31 }
32
33 fn constants() -> (Vec<[Fp; 3]>, Mds<Fp, 3>, Mds<Fp, 3>) {
34 let (mut rc, mds, inv) = (Fp::round_constants(), Fp::mds(), Fp::mds_inv());
35
36 let first_partial = Self::full_rounds() / 2;
37 let after_partials = first_partial + Self::partial_rounds();
38
39 for i in first_partial..after_partials {
41 let rc_tail = vec_remove_tail(&mut rc[i]);
45
46 let rc_carry = mat_mul(&mds, &rc_tail);
48
49 vec_accumulate(&mut rc[i + 1], &rc_carry);
51 }
52 (rc, mds, inv)
55 }
56}
57
58fn mat_mul<Fp: PrimeField, const T: usize>(mat: &Mds<Fp, T>, input: &[Fp; T]) -> [Fp; T] {
59 let mut out = [Fp::ZERO; T];
60 #[allow(clippy::needless_range_loop)]
61 for i in 0..T {
62 for j in 0..T {
63 out[i] += mat[i][j] * input[j];
64 }
65 }
66 out
67}
68
69fn vec_accumulate<Fp: PrimeField, const T: usize>(a: &mut [Fp; T], b: &[Fp; T]) {
70 for i in 0..T {
71 a[i] += b[i];
72 }
73}
74
75fn vec_remove_tail<Fp: PrimeField, const T: usize>(a: &mut [Fp; T]) -> [Fp; T] {
76 let mut tail = [Fp::ZERO; T];
77 for i in 1..T {
78 tail[i] = a[i];
79 a[i] = Fp::ZERO;
80 }
81 tail
82}