reed_solomon_simd/engine/
engine_default.rs

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