zip_plus/code/
raa_sign_flip.rs1use super::raa::*;
2use crate::{code::LinearCode, pcs::structs::ZipTypes, utils::shuffle_seeded};
3use crypto_primitives::{
4 BaseFieldConfig, FixedConfig, ProjectPrimitiveIntegersWithConfig, Ring, RingConfig,
5};
6use std::fmt::Debug;
7use zinc_utils::from_ref::FromRef;
8
9#[derive(Clone)]
13pub struct RaaSignFlippingCode<Zt: ZipTypes, Config: RaaConfig, const REP: usize> {
14 raa: RaaCode<Zt, Config, REP>,
15}
16
17impl<Zt: ZipTypes, Config: RaaConfig, const REP: usize> RaaSignFlippingCode<Zt, Config, REP>
18where
19 Zt::Cw: Ring,
20{
21 pub fn new(row_len: usize) -> Self {
22 Self {
23 raa: RaaCode::new(row_len),
24 }
25 }
26
27 fn encode_inner<In, C, Map>(&self, cfg: &C, row: &[In], map: Map) -> Vec<C::Element>
29 where
30 C: RingConfig,
31 Map: Fn(&In) -> C::Element + Clone,
32 {
33 debug_assert_eq!(
34 row.len(),
35 self.raa.row_len,
36 "Row length must match the code's row length"
37 );
38
39 let mut result: Vec<C::Element> = repeat(row, REP, map);
40 flip_even_signs(cfg, &mut result, Config::CHECK_FOR_OVERFLOWS);
41 if Config::PERMUTE_IN_PLACE {
42 shuffle_seeded(&mut result, self.raa.perm_1_seed);
43 } else {
44 result = clone_shuffled(&result, &self.raa.perm_1);
45 }
46 if Config::CHECK_FOR_OVERFLOWS {
47 accumulate(cfg, &mut result);
48 } else {
49 accumulate_unchecked(cfg, &mut result);
50 }
51 flip_even_signs(cfg, &mut result, Config::CHECK_FOR_OVERFLOWS);
52 if Config::PERMUTE_IN_PLACE {
53 shuffle_seeded(&mut result, self.raa.perm_2_seed);
54 } else {
55 result = clone_shuffled(&result, &self.raa.perm_2);
56 }
57 if Config::CHECK_FOR_OVERFLOWS {
58 accumulate(cfg, &mut result);
59 } else {
60 accumulate_unchecked(cfg, &mut result);
61 }
62 debug_assert_eq!(result.len(), self.codeword_len());
63 result
64 }
65}
66
67impl<Zt: ZipTypes, Config: RaaConfig, const REP: usize> LinearCode<Zt>
68 for RaaSignFlippingCode<Zt, Config, REP>
69where
70 Zt::Cw: Ring,
71{
72 const REPETITION_FACTOR: usize = REP;
73
74 fn row_len(&self) -> usize {
75 self.raa.row_len()
76 }
77
78 #[allow(clippy::arithmetic_side_effects)]
79 fn codeword_len(&self) -> usize {
80 self.raa.codeword_len()
81 }
82
83 fn params_string(&self) -> String {
84 self.raa.params_string()
85 }
86
87 fn encode(&self, row: &[Zt::Eval]) -> Vec<Zt::Cw> {
88 self.encode_inner(&FixedConfig::default(), row, Zt::Cw::from_ref)
89 }
90
91 fn encode_wide(&self, row: &[Zt::CombR]) -> Vec<Zt::CombR> {
92 self.encode_inner(&FixedConfig::default(), row, |v| v.clone())
93 }
94
95 fn encode_f<C>(&self, cfg: &C, row: &[C::Element]) -> Vec<C::Element>
96 where
97 C: BaseFieldConfig + ProjectPrimitiveIntegersWithConfig,
98 {
99 self.encode_inner(cfg, row, |v| v.clone())
100 }
101}
102
103impl<Zt: ZipTypes, Config: RaaConfig, const REP: usize> Debug
104 for RaaSignFlippingCode<Zt, Config, REP>
105{
106 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
107 f.debug_struct("SignFlipping")
108 .field("row_len", &self.raa.row_len)
109 .field("perm_1_seed", &self.raa.perm_1_seed)
110 .field("perm_2_seed", &self.raa.perm_2_seed)
111 .finish()
112 }
113}
114
115impl<Zt: ZipTypes, Config: RaaConfig, const REP: usize> PartialEq
116 for RaaSignFlippingCode<Zt, Config, REP>
117{
118 fn eq(&self, other: &Self) -> bool {
119 self.raa == other.raa
120 }
121}
122
123impl<Zt: ZipTypes, Config: RaaConfig, const REP: usize> Eq
124 for RaaSignFlippingCode<Zt, Config, REP>
125{
126}
127
128fn flip_even_signs<C: RingConfig>(cfg: &C, result: &mut [C::Element], check_for_overflows: bool) {
129 for i in (1..result.len()).step_by(2) {
131 if check_for_overflows {
132 result[i] = cfg.checked_neg(&result[i]).expect("Negation overflow");
133 } else {
134 cfg.neg_assign(&mut result[i]);
135 }
136 }
137}