curve25519_dalek/backend/
mod.rs1use crate::EdwardsPoint;
38use crate::Scalar;
39
40pub mod serial;
41
42#[cfg(curve25519_dalek_backend = "simd")]
43pub mod vector;
44
45#[derive(Copy, Clone)]
46enum BackendKind {
47 #[cfg(curve25519_dalek_backend = "simd")]
48 Avx2,
49 #[cfg(all(curve25519_dalek_backend = "simd", nightly))]
50 Avx512,
51 Serial,
52}
53
54#[inline]
55fn get_selected_backend() -> BackendKind {
56 #[cfg(all(curve25519_dalek_backend = "simd", nightly))]
57 {
58 cpufeatures::new!(cpuid_avx512, "avx512ifma", "avx512vl");
59 let token_avx512: cpuid_avx512::InitToken = cpuid_avx512::init();
60 if token_avx512.get() {
61 return BackendKind::Avx512;
62 }
63 }
64
65 #[cfg(curve25519_dalek_backend = "simd")]
66 {
67 cpufeatures::new!(cpuid_avx2, "avx2");
68 let token_avx2: cpuid_avx2::InitToken = cpuid_avx2::init();
69 if token_avx2.get() {
70 return BackendKind::Avx2;
71 }
72 }
73
74 BackendKind::Serial
75}
76
77#[allow(missing_docs)]
78#[cfg(feature = "alloc")]
79pub fn pippenger_optional_multiscalar_mul<I, J>(scalars: I, points: J) -> Option<EdwardsPoint>
80where
81 I: IntoIterator,
82 I::Item: core::borrow::Borrow<Scalar>,
83 J: IntoIterator<Item = Option<EdwardsPoint>>,
84{
85 use crate::traits::VartimeMultiscalarMul;
86
87 match get_selected_backend() {
88 #[cfg(curve25519_dalek_backend = "simd")]
89 BackendKind::Avx2 =>
90 vector::scalar_mul::pippenger::spec_avx2::Pippenger::optional_multiscalar_mul::<I, J>(scalars, points),
91 #[cfg(all(curve25519_dalek_backend = "simd", nightly))]
92 BackendKind::Avx512 =>
93 vector::scalar_mul::pippenger::spec_avx512ifma_avx512vl::Pippenger::optional_multiscalar_mul::<I, J>(scalars, points),
94 BackendKind::Serial =>
95 serial::scalar_mul::pippenger::Pippenger::optional_multiscalar_mul::<I, J>(scalars, points),
96 }
97}
98
99#[cfg(feature = "alloc")]
100pub(crate) enum VartimePrecomputedStraus {
101 #[cfg(curve25519_dalek_backend = "simd")]
102 Avx2(vector::scalar_mul::precomputed_straus::spec_avx2::VartimePrecomputedStraus),
103 #[cfg(all(curve25519_dalek_backend = "simd", nightly))]
104 Avx512ifma(
105 vector::scalar_mul::precomputed_straus::spec_avx512ifma_avx512vl::VartimePrecomputedStraus,
106 ),
107 Scalar(serial::scalar_mul::precomputed_straus::VartimePrecomputedStraus),
108}
109
110#[cfg(feature = "alloc")]
111impl VartimePrecomputedStraus {
112 pub fn new<I>(static_points: I) -> Self
113 where
114 I: IntoIterator,
115 I::Item: core::borrow::Borrow<EdwardsPoint>,
116 {
117 use crate::traits::VartimePrecomputedMultiscalarMul;
118
119 match get_selected_backend() {
120 #[cfg(curve25519_dalek_backend = "simd")]
121 BackendKind::Avx2 =>
122 VartimePrecomputedStraus::Avx2(vector::scalar_mul::precomputed_straus::spec_avx2::VartimePrecomputedStraus::new(static_points)),
123 #[cfg(all(curve25519_dalek_backend = "simd", nightly))]
124 BackendKind::Avx512 =>
125 VartimePrecomputedStraus::Avx512ifma(vector::scalar_mul::precomputed_straus::spec_avx512ifma_avx512vl::VartimePrecomputedStraus::new(static_points)),
126 BackendKind::Serial =>
127 VartimePrecomputedStraus::Scalar(serial::scalar_mul::precomputed_straus::VartimePrecomputedStraus::new(static_points))
128 }
129 }
130
131 pub fn optional_mixed_multiscalar_mul<I, J, K>(
132 &self,
133 static_scalars: I,
134 dynamic_scalars: J,
135 dynamic_points: K,
136 ) -> Option<EdwardsPoint>
137 where
138 I: IntoIterator,
139 I::Item: core::borrow::Borrow<Scalar>,
140 J: IntoIterator,
141 J::Item: core::borrow::Borrow<Scalar>,
142 K: IntoIterator<Item = Option<EdwardsPoint>>,
143 {
144 use crate::traits::VartimePrecomputedMultiscalarMul;
145
146 match self {
147 #[cfg(curve25519_dalek_backend = "simd")]
148 VartimePrecomputedStraus::Avx2(inner) => inner.optional_mixed_multiscalar_mul(
149 static_scalars,
150 dynamic_scalars,
151 dynamic_points,
152 ),
153 #[cfg(all(curve25519_dalek_backend = "simd", nightly))]
154 VartimePrecomputedStraus::Avx512ifma(inner) => inner.optional_mixed_multiscalar_mul(
155 static_scalars,
156 dynamic_scalars,
157 dynamic_points,
158 ),
159 VartimePrecomputedStraus::Scalar(inner) => inner.optional_mixed_multiscalar_mul(
160 static_scalars,
161 dynamic_scalars,
162 dynamic_points,
163 ),
164 }
165 }
166}
167
168#[allow(missing_docs)]
169#[cfg(feature = "alloc")]
170pub fn straus_multiscalar_mul<I, J>(scalars: I, points: J) -> EdwardsPoint
171where
172 I: IntoIterator,
173 I::Item: core::borrow::Borrow<Scalar>,
174 J: IntoIterator,
175 J::Item: core::borrow::Borrow<EdwardsPoint>,
176{
177 use crate::traits::MultiscalarMul;
178
179 match get_selected_backend() {
180 #[cfg(curve25519_dalek_backend = "simd")]
181 BackendKind::Avx2 => {
182 vector::scalar_mul::straus::spec_avx2::Straus::multiscalar_mul::<I, J>(scalars, points)
183 }
184 #[cfg(all(curve25519_dalek_backend = "simd", nightly))]
185 BackendKind::Avx512 => {
186 vector::scalar_mul::straus::spec_avx512ifma_avx512vl::Straus::multiscalar_mul::<I, J>(
187 scalars, points,
188 )
189 }
190 BackendKind::Serial => {
191 serial::scalar_mul::straus::Straus::multiscalar_mul::<I, J>(scalars, points)
192 }
193 }
194}
195
196#[allow(missing_docs)]
197#[cfg(feature = "alloc")]
198pub fn straus_optional_multiscalar_mul<I, J>(scalars: I, points: J) -> Option<EdwardsPoint>
199where
200 I: IntoIterator,
201 I::Item: core::borrow::Borrow<Scalar>,
202 J: IntoIterator<Item = Option<EdwardsPoint>>,
203{
204 use crate::traits::VartimeMultiscalarMul;
205
206 match get_selected_backend() {
207 #[cfg(curve25519_dalek_backend = "simd")]
208 BackendKind::Avx2 => {
209 vector::scalar_mul::straus::spec_avx2::Straus::optional_multiscalar_mul::<I, J>(
210 scalars, points,
211 )
212 }
213 #[cfg(all(curve25519_dalek_backend = "simd", nightly))]
214 BackendKind::Avx512 => {
215 vector::scalar_mul::straus::spec_avx512ifma_avx512vl::Straus::optional_multiscalar_mul::<
216 I,
217 J,
218 >(scalars, points)
219 }
220 BackendKind::Serial => {
221 serial::scalar_mul::straus::Straus::optional_multiscalar_mul::<I, J>(scalars, points)
222 }
223 }
224}
225
226pub fn variable_base_mul(point: &EdwardsPoint, scalar: &Scalar) -> EdwardsPoint {
228 match get_selected_backend() {
229 #[cfg(curve25519_dalek_backend = "simd")]
230 BackendKind::Avx2 => vector::scalar_mul::variable_base::spec_avx2::mul(point, scalar),
231 #[cfg(all(curve25519_dalek_backend = "simd", nightly))]
232 BackendKind::Avx512 => {
233 vector::scalar_mul::variable_base::spec_avx512ifma_avx512vl::mul(point, scalar)
234 }
235 BackendKind::Serial => serial::scalar_mul::variable_base::mul(point, scalar),
236 }
237}
238
239#[allow(non_snake_case)]
241pub fn vartime_double_base_mul(a: &Scalar, A: &EdwardsPoint, b: &Scalar) -> EdwardsPoint {
242 match get_selected_backend() {
243 #[cfg(curve25519_dalek_backend = "simd")]
244 BackendKind::Avx2 => vector::scalar_mul::vartime_double_base::spec_avx2::mul(a, A, b),
245 #[cfg(all(curve25519_dalek_backend = "simd", nightly))]
246 BackendKind::Avx512 => {
247 vector::scalar_mul::vartime_double_base::spec_avx512ifma_avx512vl::mul(a, A, b)
248 }
249 BackendKind::Serial => serial::scalar_mul::vartime_double_base::mul(a, A, b),
250 }
251}