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