commonware_cryptography/reed_solomon/engine/
engine_naive.rs1use crate::reed_solomon::engine::{
2 Engine, GF_MODULUS, GfElement, SHARD_CHUNK_BYTES, ShardsRefMut,
3 tables::{self, Exp, Log, Skew},
4 utils,
5};
6
7#[derive(Clone, Copy)]
14pub struct Naive {
15 exp: &'static Exp,
16 log: &'static Log,
17 skew: &'static Skew,
18}
19
20impl Naive {
21 pub fn new() -> Self {
25 let exp_log = tables::get_exp_log();
26 let skew = tables::get_skew();
27
28 Self {
29 exp: &exp_log.exp,
30 log: &exp_log.log,
31 skew,
32 }
33 }
34}
35
36impl Engine for Naive {
37 fn fft(
38 &self,
39 data: &mut ShardsRefMut<'_>,
40 pos: usize,
41 size: usize,
42 truncated_size: usize,
43 skew_delta: usize,
44 ) {
45 super::validate_transform(data, pos, size, truncated_size, skew_delta);
46
47 let mut dist = size / 2;
48 while dist > 0 {
49 let mut r = 0;
50 while r < truncated_size {
51 let log_m = self.skew[r + dist + skew_delta - 1];
52 for i in r..r + dist {
53 let (a, b) = data.dist2_mut(pos + i, dist);
54
55 if log_m != GF_MODULUS {
57 self.mul_add(a, b, log_m);
58 }
59 utils::xor(b, a);
60 }
61 r += dist * 2;
62 }
63 dist /= 2;
64 }
65 }
66
67 fn ifft(
68 &self,
69 data: &mut ShardsRefMut<'_>,
70 pos: usize,
71 size: usize,
72 truncated_size: usize,
73 skew_delta: usize,
74 ) {
75 super::validate_transform(data, pos, size, truncated_size, skew_delta);
76
77 let mut dist = 1;
78 while dist < size {
79 let mut r = 0;
80 while r < truncated_size {
81 let log_m = self.skew[r + dist + skew_delta - 1];
82 for i in r..r + dist {
83 let (a, b) = data.dist2_mut(pos + i, dist);
84
85 utils::xor(b, a);
87 if log_m != GF_MODULUS {
88 self.mul_add(a, b, log_m);
89 }
90 }
91 r += dist * 2;
92 }
93 dist *= 2;
94 }
95 }
96
97 fn mul(&self, x: &mut [[u8; SHARD_CHUNK_BYTES]], log_m: GfElement) {
98 for chunk in x.iter_mut() {
99 for i in 0..SHARD_CHUNK_BYTES / 2 {
100 let lo = GfElement::from(chunk[i]);
101 let hi = GfElement::from(chunk[i + SHARD_CHUNK_BYTES / 2]);
102 let prod = tables::mul(lo | (hi << 8), log_m, self.exp, self.log);
103 chunk[i] = prod as u8;
104 chunk[i + SHARD_CHUNK_BYTES / 2] = (prod >> 8) as u8;
105 }
106 }
107 }
108}
109
110impl Default for Naive {
111 fn default() -> Self {
112 Self::new()
113 }
114}
115
116impl Naive {
117 fn mul_add(
124 &self,
125 x: &mut [[u8; SHARD_CHUNK_BYTES]],
126 y: &[[u8; SHARD_CHUNK_BYTES]],
127 log_m: GfElement,
128 ) {
129 assert_eq!(x.len(), y.len());
130
131 for (x_chunk, y_chunk) in core::iter::zip(x.iter_mut(), y.iter()) {
132 for i in 0..SHARD_CHUNK_BYTES / 2 {
133 let lo = GfElement::from(y_chunk[i]);
134 let hi = GfElement::from(y_chunk[i + SHARD_CHUNK_BYTES / 2]);
135 let prod = tables::mul(lo | (hi << 8), log_m, self.exp, self.log);
136 x_chunk[i] ^= prod as u8;
137 x_chunk[i + SHARD_CHUNK_BYTES / 2] ^= (prod >> 8) as u8;
138 }
139 }
140 }
141}