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 = "unstable_avx512", nightly))]
50 Avx512,
51 Serial,
52}
53
54#[inline]
55fn get_selected_backend() -> BackendKind {
56 #[cfg(all(curve25519_dalek_backend = "unstable_avx512", 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 = "unstable_avx512", 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 = "unstable_avx512", 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 = "unstable_avx512", 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 len(&self) -> usize {
133 use crate::traits::VartimePrecomputedMultiscalarMul;
134
135 match self {
136 #[cfg(curve25519_dalek_backend = "simd")]
137 VartimePrecomputedStraus::Avx2(inner) => inner.len(),
138 #[cfg(all(curve25519_dalek_backend = "unstable_avx512", nightly))]
139 VartimePrecomputedStraus::Avx512ifma(inner) => inner.len(),
140 VartimePrecomputedStraus::Scalar(inner) => inner.len(),
141 }
142 }
143
144 pub fn is_empty(&self) -> bool {
146 use crate::traits::VartimePrecomputedMultiscalarMul;
147
148 match self {
149 #[cfg(curve25519_dalek_backend = "simd")]
150 VartimePrecomputedStraus::Avx2(inner) => inner.is_empty(),
151 #[cfg(all(curve25519_dalek_backend = "unstable_avx512", nightly))]
152 VartimePrecomputedStraus::Avx512ifma(inner) => inner.is_empty(),
153 VartimePrecomputedStraus::Scalar(inner) => inner.is_empty(),
154 }
155 }
156
157 pub fn optional_mixed_multiscalar_mul<I, J, K>(
158 &self,
159 static_scalars: I,
160 dynamic_scalars: J,
161 dynamic_points: K,
162 ) -> Option<EdwardsPoint>
163 where
164 I: IntoIterator,
165 I::Item: core::borrow::Borrow<Scalar>,
166 J: IntoIterator,
167 J::Item: core::borrow::Borrow<Scalar>,
168 K: IntoIterator<Item = Option<EdwardsPoint>>,
169 {
170 use crate::traits::VartimePrecomputedMultiscalarMul;
171
172 match self {
173 #[cfg(curve25519_dalek_backend = "simd")]
174 VartimePrecomputedStraus::Avx2(inner) => inner.optional_mixed_multiscalar_mul(
175 static_scalars,
176 dynamic_scalars,
177 dynamic_points,
178 ),
179 #[cfg(all(curve25519_dalek_backend = "unstable_avx512", nightly))]
180 VartimePrecomputedStraus::Avx512ifma(inner) => inner.optional_mixed_multiscalar_mul(
181 static_scalars,
182 dynamic_scalars,
183 dynamic_points,
184 ),
185 VartimePrecomputedStraus::Scalar(inner) => inner.optional_mixed_multiscalar_mul(
186 static_scalars,
187 dynamic_scalars,
188 dynamic_points,
189 ),
190 }
191 }
192}
193
194#[allow(missing_docs)]
195#[cfg(feature = "alloc")]
196pub fn straus_multiscalar_mul<I, J>(scalars: I, points: J) -> EdwardsPoint
197where
198 I: IntoIterator,
199 I::Item: core::borrow::Borrow<Scalar>,
200 J: IntoIterator,
201 J::Item: core::borrow::Borrow<EdwardsPoint>,
202{
203 use crate::traits::MultiscalarMul;
204
205 match get_selected_backend() {
206 #[cfg(curve25519_dalek_backend = "simd")]
207 BackendKind::Avx2 => {
208 vector::scalar_mul::straus::spec_avx2::Straus::multiscalar_mul::<I, J>(scalars, points)
209 }
210 #[cfg(all(curve25519_dalek_backend = "unstable_avx512", nightly))]
211 BackendKind::Avx512 => {
212 vector::scalar_mul::straus::spec_avx512ifma_avx512vl::Straus::multiscalar_mul::<I, J>(
213 scalars, points,
214 )
215 }
216 BackendKind::Serial => {
217 serial::scalar_mul::straus::Straus::multiscalar_mul::<I, J>(scalars, points)
218 }
219 }
220}
221
222#[allow(missing_docs)]
223#[cfg(feature = "alloc")]
224pub fn straus_optional_multiscalar_mul<I, J>(scalars: I, points: J) -> Option<EdwardsPoint>
225where
226 I: IntoIterator,
227 I::Item: core::borrow::Borrow<Scalar>,
228 J: IntoIterator<Item = Option<EdwardsPoint>>,
229{
230 use crate::traits::VartimeMultiscalarMul;
231
232 match get_selected_backend() {
233 #[cfg(curve25519_dalek_backend = "simd")]
234 BackendKind::Avx2 => {
235 vector::scalar_mul::straus::spec_avx2::Straus::optional_multiscalar_mul::<I, J>(
236 scalars, points,
237 )
238 }
239 #[cfg(all(curve25519_dalek_backend = "unstable_avx512", nightly))]
240 BackendKind::Avx512 => {
241 vector::scalar_mul::straus::spec_avx512ifma_avx512vl::Straus::optional_multiscalar_mul::<
242 I,
243 J,
244 >(scalars, points)
245 }
246 BackendKind::Serial => {
247 serial::scalar_mul::straus::Straus::optional_multiscalar_mul::<I, J>(scalars, points)
248 }
249 }
250}
251
252pub fn variable_base_mul(point: &EdwardsPoint, scalar: &Scalar) -> EdwardsPoint {
254 match get_selected_backend() {
255 #[cfg(curve25519_dalek_backend = "simd")]
256 BackendKind::Avx2 => vector::scalar_mul::variable_base::spec_avx2::mul(point, scalar),
257 #[cfg(all(curve25519_dalek_backend = "unstable_avx512", nightly))]
258 BackendKind::Avx512 => {
259 vector::scalar_mul::variable_base::spec_avx512ifma_avx512vl::mul(point, scalar)
260 }
261 BackendKind::Serial => serial::scalar_mul::variable_base::mul(point, scalar),
262 }
263}
264
265#[allow(non_snake_case)]
267pub fn vartime_double_base_mul(a: &Scalar, A: &EdwardsPoint, b: &Scalar) -> EdwardsPoint {
268 match get_selected_backend() {
269 #[cfg(curve25519_dalek_backend = "simd")]
270 BackendKind::Avx2 => vector::scalar_mul::vartime_double_base::spec_avx2::mul(a, A, b),
271 #[cfg(all(curve25519_dalek_backend = "unstable_avx512", nightly))]
272 BackendKind::Avx512 => {
273 vector::scalar_mul::vartime_double_base::spec_avx512ifma_avx512vl::mul(a, A, b)
274 }
275 BackendKind::Serial => serial::scalar_mul::vartime_double_base::mul(a, A, b),
276 }
277}