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