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, GfElement, NoSimd, ShardsRefMut, GF_ORDER, SHARD_CHUNK_BYTES,
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            cpufeatures::new!(has_avx2, "avx2");
32            if has_avx2::get() {
33                return Self(Box::new(Avx2::new()));
34            }
35
36            cpufeatures::new!(has_ssse3, "ssse3");
37            if has_ssse3::get() {
38                return Self(Box::new(Ssse3::new()));
39            }
40        }
41
42        #[cfg(target_arch = "aarch64")]
43        {
44            cpufeatures::new!(has_neon, "neon");
45            if has_neon::get() {
46                return Self(Box::new(Neon::new()));
47            }
48        }
49
50        Self(Box::new(NoSimd::new()))
51    }
52}
53
54// ======================================================================
55// DefaultEngine - IMPL Default
56
57impl Default for DefaultEngine {
58    fn default() -> Self {
59        Self::new()
60    }
61}
62
63// ======================================================================
64// DefaultEngine - IMPL Engine
65
66impl Engine for DefaultEngine {
67    fn fft(
68        &self,
69        data: &mut ShardsRefMut<'_>,
70        pos: usize,
71        size: usize,
72        truncated_size: usize,
73        skew_delta: usize,
74    ) {
75        self.0.fft(data, pos, size, truncated_size, skew_delta);
76    }
77
78    fn ifft(
79        &self,
80        data: &mut ShardsRefMut<'_>,
81        pos: usize,
82        size: usize,
83        truncated_size: usize,
84        skew_delta: usize,
85    ) {
86        self.0.ifft(data, pos, size, truncated_size, skew_delta);
87    }
88
89    fn mul(&self, x: &mut [[u8; SHARD_CHUNK_BYTES]], log_m: GfElement) {
90        self.0.mul(x, log_m);
91    }
92
93    fn eval_poly(erasures: &mut [GfElement; GF_ORDER], truncated_size: usize) {
94        #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
95        {
96            cpufeatures::new!(has_avx2, "avx2");
97            if has_avx2::get() {
98                return Avx2::eval_poly(erasures, truncated_size);
99            }
100
101            cpufeatures::new!(has_ssse3, "ssse3");
102            if has_ssse3::get() {
103                return Ssse3::eval_poly(erasures, truncated_size);
104            }
105        }
106
107        #[cfg(target_arch = "aarch64")]
108        {
109            cpufeatures::new!(has_neon, "neon");
110            if has_neon::get() {
111                return Neon::eval_poly(erasures, truncated_size);
112            }
113        }
114
115        NoSimd::eval_poly(erasures, truncated_size);
116    }
117}