Skip to main content

commonware_cryptography/reed_solomon/engine/
engine_default.rs

1#[cfg(target_arch = "aarch64")]
2use crate::reed_solomon::engine::Neon;
3#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
4use crate::reed_solomon::engine::{Avx2, Ssse3};
5use crate::reed_solomon::engine::{
6    Engine, GF_ORDER, GfElement, NoSimd, SHARD_CHUNK_BYTES, ShardsRefMut,
7};
8#[cfg(not(feature = "std"))]
9use alloc::boxed::Box;
10
11// ======================================================================
12// DefaultEngine - PUBLIC
13
14/// [`Engine`] that at runtime selects the best Engine.
15pub struct DefaultEngine(Box<dyn Engine + Send + Sync>);
16
17impl DefaultEngine {
18    /// Creates new [`DefaultEngine`] by chosing and initializing the underlying engine.
19    ///
20    /// On x86(-64) the engine is chosen in the following order of preference:
21    /// 1. `Avx2`
22    /// 2. `Ssse3`
23    /// 3. [`NoSimd`]
24    ///
25    /// On `AArch64` the engine is chosen in the following order of preference:
26    /// 1. `Neon`
27    /// 2. [`NoSimd`]
28    pub fn new() -> Self {
29        #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
30        {
31            if super::cpu_features::avx2() {
32                return Self(Box::new(Avx2::new()));
33            }
34
35            if super::cpu_features::ssse3() {
36                return Self(Box::new(Ssse3::new()));
37            }
38        }
39
40        #[cfg(target_arch = "aarch64")]
41        {
42            if super::cpu_features::neon() {
43                return Self(Box::new(Neon::new()));
44            }
45        }
46
47        Self(Box::new(NoSimd::new()))
48    }
49}
50
51// ======================================================================
52// DefaultEngine - IMPL Default
53
54impl Default for DefaultEngine {
55    fn default() -> Self {
56        Self::new()
57    }
58}
59
60// ======================================================================
61// DefaultEngine - IMPL Engine
62
63impl Engine for DefaultEngine {
64    fn fft(
65        &self,
66        data: &mut ShardsRefMut<'_>,
67        pos: usize,
68        size: usize,
69        truncated_size: usize,
70        skew_delta: usize,
71    ) {
72        self.0.fft(data, pos, size, truncated_size, skew_delta);
73    }
74
75    fn ifft(
76        &self,
77        data: &mut ShardsRefMut<'_>,
78        pos: usize,
79        size: usize,
80        truncated_size: usize,
81        skew_delta: usize,
82    ) {
83        self.0.ifft(data, pos, size, truncated_size, skew_delta);
84    }
85
86    fn mul(&self, x: &mut [[u8; SHARD_CHUNK_BYTES]], log_m: GfElement) {
87        self.0.mul(x, log_m);
88    }
89
90    fn eval_poly(erasures: &mut [GfElement; GF_ORDER], truncated_size: usize) {
91        #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
92        {
93            if super::cpu_features::avx2() {
94                return Avx2::eval_poly(erasures, truncated_size);
95            }
96
97            if super::cpu_features::ssse3() {
98                return Ssse3::eval_poly(erasures, truncated_size);
99            }
100        }
101
102        #[cfg(target_arch = "aarch64")]
103        {
104            if super::cpu_features::neon() {
105                return Neon::eval_poly(erasures, truncated_size);
106            }
107        }
108
109        NoSimd::eval_poly(erasures, truncated_size);
110    }
111}