use crate::{
constants::Eta, helper::cloop, ntt::ntt, polynomial::PolynomialRingElement,
simd::traits::Operations,
};
#[inline(always)]
pub(crate) fn serialize<SIMDUnit: Operations>(
eta: Eta,
re: &PolynomialRingElement<SIMDUnit>,
serialized: &mut [u8], ) {
let output_bytes_per_simd_unit = chunk_size(eta);
cloop! {
for (i, simd_unit) in re.simd_units.iter().enumerate() {
SIMDUnit::error_serialize(eta,
simd_unit,
&mut serialized[i * output_bytes_per_simd_unit..(i + 1) * output_bytes_per_simd_unit]
);
}
}
}
#[inline(always)]
fn chunk_size(eta: Eta) -> usize {
match eta {
Eta::Two => 3,
Eta::Four => 4,
}
}
#[inline(always)]
fn deserialize<SIMDUnit: Operations>(
eta: Eta,
serialized: &[u8],
result: &mut PolynomialRingElement<SIMDUnit>,
) {
let chunk_size = chunk_size(eta);
for i in 0..result.simd_units.len() {
SIMDUnit::error_deserialize(
eta,
&serialized[i * chunk_size..(i + 1) * chunk_size],
&mut result.simd_units[i],
);
}
}
#[inline(always)]
pub(crate) fn deserialize_to_vector_then_ntt<SIMDUnit: Operations>(
eta: Eta,
ring_element_size: usize,
serialized: &[u8],
ring_elements: &mut [PolynomialRingElement<SIMDUnit>],
) {
cloop! {
for (i, bytes) in serialized.chunks_exact(ring_element_size).enumerate() {
deserialize::<SIMDUnit>(eta, bytes, &mut ring_elements[i]);
ntt(&mut ring_elements[i]);
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::simd::{self, traits::Operations};
fn test_deserialize_generic<SIMDUnit: Operations>() {
let serialized = [
220, 24, 44, 136, 134, 36, 11, 195, 72, 82, 34, 144, 36, 33, 9, 196, 22, 70, 100, 148,
65, 32, 163, 1, 210, 40, 14, 224, 38, 72, 33, 41, 136, 156, 146, 80, 25, 37, 50, 92,
66, 140, 227, 144, 96, 9, 64, 141, 193, 50, 1, 140, 20, 141, 92, 32, 97, 2, 25, 42, 34,
66, 50, 193, 72, 113, 202, 8, 16, 209, 54, 44, 129, 194, 48, 144, 20, 141, 228, 166,
141, 228, 20, 144, 146, 54, 12, 99, 4, 140, 226, 18, 12, 194, 38, 97,
];
let expected_coefficients = [
-2, -1, -1, -2, 1, 2, -1, 1, 2, 1, 0, -1, 2, 1, 1, 1, -1, 1, -2, 1, -2, 1, 0, 0, 0, 0,
1, 1, 0, 2, -2, -2, -2, -2, -2, 2, 0, 0, 0, 2, -2, 2, -1, -1, 1, -2, 1, 0, -2, -2, 1,
0, 1, -1, 2, 0, 2, -2, -2, 1, 0, -1, 2, 2, 0, 0, -1, -2, 0, -2, -1, 2, 2, -2, -1, -1,
0, 2, 0, 0, 1, -2, -2, -2, 0, 2, 0, -2, -2, -1, 0, 1, 1, 1, -2, 0, 1, -1, -2, 0, 0, -2,
-2, 1, -2, -1, 1, 1, -2, 2, -1, -2, -1, -2, -1, 2, 1, 1, 2, -1, 1, 1, 2, 2, -2, 0, -1,
-2, 1, 2, -1, 1, -1, 0, 2, 2, -2, 1, 0, 0, 1, 0, -1, -2, -2, -1, 1, 2, 0, 0, 2, -1, 0,
2, -2, -2, 1, -2, 0, 1, 0, -2, 2, 1, -2, -2, -2, 1, 1, 2, -1, -2, -2, 0, -2, -1, 0, 1,
-1, -2, 2, 2, -2, 2, 1, 0, -1, -1, -1, 2, -1, 1, 1, 2, 0, 1, -2, 1, -2, 1, 2, 0, 0, 0,
1, 0, -1, -2, -2, -2, -1, -1, 0, -1, -1, -2, -2, -2, -1, 0, 1, 2, -2, -2, 0, 0, 0, -1,
-1, 2, -1, 2, -1, -2, 1, 0, 2, 2, -1, -2, 0, -2, -1, 1, 1, 2, -1, 2, 0, 2, -1, -1, 0,
0, 2, -1,
];
let mut deserialized = PolynomialRingElement::<SIMDUnit>::zero();
deserialize::<SIMDUnit>(Eta::Two, &serialized, &mut deserialized);
assert_eq!(deserialized.to_i32_array(), expected_coefficients);
let serialized = [
22, 103, 55, 49, 34, 65, 50, 129, 52, 65, 21, 85, 82, 69, 3, 55, 52, 101, 80, 64, 114,
136, 53, 8, 135, 67, 64, 71, 131, 21, 117, 81, 23, 99, 17, 84, 51, 23, 117, 56, 52, 85,
131, 17, 22, 117, 85, 68, 34, 113, 87, 24, 65, 81, 2, 80, 118, 53, 34, 8, 32, 51, 51,
82, 24, 2, 69, 0, 80, 68, 129, 133, 134, 17, 134, 82, 18, 21, 37, 114, 55, 87, 83, 8,
80, 52, 103, 1, 84, 82, 99, 16, 86, 48, 16, 133, 17, 2, 67, 51, 120, 71, 19, 5, 72, 19,
21, 103, 114, 115, 69, 36, 97, 68, 115, 56, 18, 83, 99, 32, 83, 88, 37, 71, 35, 82, 24,
19,
];
let expected_coefficients = [
-2, 3, -3, -2, -3, 1, 3, 1, 2, 2, 3, 0, 2, 1, 3, -4, 0, 1, 3, 0, -1, 3, -1, -1, 2, -1,
-1, 0, 1, 4, -3, 1, 0, 1, -1, -2, 4, -1, 4, 0, 2, -3, -4, -4, -1, 1, -4, 4, -3, -4, 1,
0, 4, 0, -3, 0, 1, -4, -1, 3, -1, -3, 3, -1, -3, 3, 1, -2, 3, 3, 0, -1, 1, 1, -3, 3,
-1, -3, -4, 1, 0, 1, -1, -1, 1, -4, 3, 3, -2, 3, -1, -3, -1, -1, 0, 0, 2, 2, 3, -3, -3,
-1, -4, 3, 3, 0, 3, -1, 2, 4, 4, -1, -2, -3, -1, 1, 2, 2, -4, 4, 4, 2, 1, 1, 1, 1, 2,
-1, -4, 3, 2, 4, -1, 0, 4, 4, 4, -1, 0, 0, 3, -4, -1, -4, -2, -4, 3, 3, -2, -4, 2, -1,
2, 3, -1, 3, -1, 2, 2, -3, -3, 1, -3, -1, 1, -1, -4, 4, 4, -1, 0, 1, -3, -2, 3, 4, 0,
-1, 2, -1, 1, -2, 4, 3, -2, -1, 4, 1, 4, 3, -1, -4, 3, 3, 2, 4, 1, 0, 1, 1, -4, -3, -3,
0, 1, 3, -1, 4, -4, 0, 1, 3, -1, 3, -3, -2, 2, -3, 1, -3, -1, 0, 0, 2, 3, -2, 0, 0, 1,
-3, -4, 1, 2, 3, 1, -1, 1, -2, 4, 2, 1, -1, -4, -1, -1, 2, -3, 0, 1, 2, 2, -1, -4, 3,
1, 3,
];
let mut deserialized = PolynomialRingElement::<SIMDUnit>::zero();
deserialize::<SIMDUnit>(Eta::Four, &serialized, &mut deserialized);
assert_eq!(deserialized.to_i32_array(), expected_coefficients);
}
#[test]
fn test_deserialize_portable() {
test_deserialize_generic::<simd::portable::PortableSIMDUnit>();
}
#[cfg(feature = "simd256")]
#[test]
fn test_deserialize_simd256() {
test_deserialize_generic::<simd::avx2::AVX2SIMDUnit>();
}
}