Skip to main content

rustfs_erasure_codec/galois_8/
mod.rs

1//! Implementation of GF(2^8): the finite field with 2^8 elements.
2
3include!(concat!(env!("OUT_DIR"), "/table.rs"));
4
5pub(crate) mod aarch64;
6mod aligned;
7mod backend;
8mod legacy;
9mod policy;
10mod ppc64;
11mod profile;
12mod scalar;
13pub(crate) mod x86;
14
15pub use aligned::{
16    AlignedShard, SHARD_ALIGNMENT, alloc_aligned_shards, alloc_shard_slots, mark_missing_slots,
17    shards_to_slots,
18};
19pub use backend::{BackendId, BackendKind};
20#[cfg(feature = "std")]
21pub use policy::OptionVecReconstructWorkspace;
22#[cfg(feature = "std")]
23pub(crate) use policy::resolve_runtime_parallel_policy_cache;
24#[cfg(feature = "std")]
25pub use profile::RustNeonProfileStats;
26#[cfg(feature = "std")]
27pub use profile::{reset_rust_neon_profile_stats, rust_neon_profile_stats};
28
29/// The field GF(2^8).
30#[derive(Debug, Default, Copy, Clone, PartialEq, Eq)]
31pub struct Field;
32
33impl crate::Field for Field {
34    const ORDER: usize = 256;
35    type Elem = u8;
36
37    fn add(a: u8, b: u8) -> u8 {
38        add(a, b)
39    }
40
41    fn mul(a: u8, b: u8) -> u8 {
42        mul(a, b)
43    }
44
45    fn div(a: u8, b: u8) -> u8 {
46        div(a, b)
47    }
48
49    fn exp(elem: u8, n: usize) -> u8 {
50        exp(elem, n)
51    }
52
53    fn zero() -> u8 {
54        0
55    }
56
57    fn one() -> u8 {
58        1
59    }
60
61    fn nth_internal(n: usize) -> u8 {
62        n as u8
63    }
64
65    fn mul_slice(c: u8, input: &[u8], out: &mut [u8]) {
66        mul_slice(c, input, out)
67    }
68
69    fn mul_slice_add(c: u8, input: &[u8], out: &mut [u8]) {
70        mul_slice_xor(c, input, out)
71    }
72}
73
74/// Type alias of ReedSolomon over GF(2^8).
75pub type ReedSolomon = crate::ReedSolomon<Field>;
76
77/// Type alias of ShardByShard over GF(2^8).
78pub type ShardByShard<'a> = crate::ShardByShard<'a, Field>;
79
80/// Add two elements.
81pub fn add(a: u8, b: u8) -> u8 {
82    a ^ b
83}
84
85/// Subtract `b` from `a`.
86#[cfg(test)]
87pub fn sub(a: u8, b: u8) -> u8 {
88    a ^ b
89}
90
91/// Multiply two elements.
92pub fn mul(a: u8, b: u8) -> u8 {
93    MUL_TABLE[a as usize][b as usize]
94}
95
96/// Divide one element by another. If `b` is `0`, this returns `0` instead of panicking.
97pub fn div(a: u8, b: u8) -> u8 {
98    if a == 0 || b == 0 {
99        return 0;
100    }
101    let log_a = LOG_TABLE[a as usize];
102    let log_b = LOG_TABLE[b as usize];
103    let mut log_result = log_a as isize - log_b as isize;
104    if log_result < 0 {
105        log_result += 255;
106    }
107    EXP_TABLE[log_result as usize]
108}
109
110/// Compute a^n.
111pub fn exp(a: u8, n: usize) -> u8 {
112    if n == 0 {
113        1
114    } else if a == 0 {
115        0
116    } else {
117        let log_a = LOG_TABLE[a as usize];
118        let mut log_result = log_a as usize * n;
119        while 255 <= log_result {
120            log_result -= 255;
121        }
122        EXP_TABLE[log_result]
123    }
124}
125
126/// Multiply each byte in `input` by `c` in GF(2^8), writing results to `out`.
127pub fn mul_slice(c: u8, input: &[u8], out: &mut [u8]) {
128    (backend::active_backend().mul_slice)(c, input, out);
129}
130
131/// XOR-multiply: `out[i] ^= gf_mul(c, input[i])` for each byte.
132pub fn mul_slice_xor(c: u8, input: &[u8], out: &mut [u8]) {
133    (backend::active_backend().mul_slice_xor)(c, input, out);
134}
135
136/// Returns the name of the currently active GF(2^8) backend.
137pub fn active_backend_name() -> &'static str {
138    backend::active_backend().name
139}
140
141/// Returns the kind (Scalar, SimdC, RustSimd) of the active backend.
142pub fn active_backend_kind() -> BackendKind {
143    backend::active_backend().kind
144}
145
146/// Returns the identifier of the active backend.
147pub fn active_backend_id() -> BackendId {
148    backend::active_backend().id
149}
150
151#[cfg(test)]
152fn mul_slice_scalar_for_test(c: u8, input: &[u8], out: &mut [u8]) {
153    scalar::mul_slice_pure_rust(c, input, out);
154}
155
156#[cfg(test)]
157fn mul_slice_xor_scalar_for_test(c: u8, input: &[u8], out: &mut [u8]) {
158    scalar::mul_slice_xor_pure_rust(c, input, out);
159}
160
161#[cfg(test)]
162mod tests;