use super::params::RescueParams;
use crate::common::{matrix::mmul_assign, sbox::sbox};
use crate::sponge::generic_hash;
use crate::traits::{HashFamily, HashParams};
use franklin_crypto::bellman::{Engine, Field};
pub fn rescue_hash<E: Engine, const L: usize>(input: &[E::Fr; L]) -> [E::Fr; 2] {
const WIDTH: usize = 3;
const RATE: usize = 2;
let params = RescueParams::<E, RATE, WIDTH>::default();
generic_hash(¶ms, input, None)
}
pub(crate) fn rescue_round_function<E: Engine, P: HashParams<E, RATE, WIDTH>, const RATE: usize, const WIDTH: usize>(params: &P, state: &mut [E::Fr; WIDTH]) {
assert_eq!(params.hash_family(), HashFamily::Rescue, "Incorrect hash family!");
state.iter_mut().zip(params.constants_of_round(0).iter()).for_each(|(s, c)| s.add_assign(c));
for round in 0..2 * params.number_of_full_rounds() {
if round & 1 == 0 {
sbox::<E>(params.alpha_inv(), state);
} else {
sbox::<E>(params.alpha(), state);
}
if params.allows_specialization() {
let constants = params.constants_of_round(round + 1);
params.specialized_affine_transformation_for_round(state, &constants);
} else {
mmul_assign::<E, WIDTH>(params.mds_matrix(), state);
state.iter_mut().zip(params.constants_of_round(round + 1).iter()).for_each(|(s, c)| s.add_assign(c));
}
}
}