mirror of
https://github.com/saymrwulf/risc0-curve25519-dalek-source.git
synced 2026-09-08 20:40:32 +00:00
Rework backend selection code.
Each backend can now be selected by an individual feature: - `u32_backend` for `backend::u32`; - `u64_backend` for `backend::u64`; - `avx2_backend` for `backend::avx2`; The `u64_backend` is selected by default, since most people use X64 and we have no way to select based on target (see discussion in #126). However, these changes mean that it is possible to select the backend explicitly, and if we had the ability to select target-default features, we could do so easily.
This commit is contained in:
parent
9b6c932635
commit
34c43c20a9
10 changed files with 70 additions and 60 deletions
28
.travis.yml
28
.travis.yml
|
|
@ -2,34 +2,28 @@ language: rust
|
||||||
|
|
||||||
rust:
|
rust:
|
||||||
- stable
|
- stable
|
||||||
- beta
|
|
||||||
- nightly
|
- nightly
|
||||||
|
|
||||||
env:
|
env:
|
||||||
- TEST_COMMAND=test EXTRA_FLAGS='' FEATURES=''
|
# Tests the u32 backend
|
||||||
|
- TEST_COMMAND=test EXTRA_FLAGS='--no-default-features' FEATURES='std u32_backend'
|
||||||
|
# Tests the u64 backend
|
||||||
|
- TEST_COMMAND=test EXTRA_FLAGS='--no-default-features' FEATURES='std u64_backend'
|
||||||
|
# Tests the avx2 backend
|
||||||
|
- TEST_COMMAND=test EXTRA_FLAGS='--no-default-features' FEATURES='std avx2_backend yolocrypto'
|
||||||
|
# Tests serde support and default feature selection
|
||||||
- TEST_COMMAND=test EXTRA_FLAGS='' FEATURES='serde'
|
- TEST_COMMAND=test EXTRA_FLAGS='' FEATURES='serde'
|
||||||
- TEST_COMMAND=test EXTRA_FLAGS='' FEATURES='nightly'
|
# Tests building without std
|
||||||
- TEST_COMMAND=test EXTRA_FLAGS='' FEATURES='yolocrypto nightly'
|
|
||||||
- TEST_COMMAND=build EXTRA_FLAGS=--no-default-features FEATURES=''
|
- TEST_COMMAND=build EXTRA_FLAGS=--no-default-features FEATURES=''
|
||||||
|
|
||||||
matrix:
|
matrix:
|
||||||
exclude:
|
exclude:
|
||||||
# Test nightly features, such as radix_51, only on nightly.
|
# Test the avx2 backend only on nightly
|
||||||
- rust: stable
|
- rust: stable
|
||||||
env: TEST_COMMAND=test EXTRA_FLAGS='' FEATURES='nightly'
|
env: TEST_COMMAND=test EXTRA_FLAGS='--no-default-features' FEATURES='std avx2_backend yolocrypto'
|
||||||
- rust: beta
|
|
||||||
env: TEST_COMMAND=test EXTRA_FLAGS='' FEATURES='nightly'
|
|
||||||
- rust: stable
|
|
||||||
env: TEST_COMMAND=test EXTRA_FLAGS='' FEATURES='yolocrypto nightly'
|
|
||||||
- rust: beta
|
|
||||||
env: TEST_COMMAND=test EXTRA_FLAGS='' FEATURES='yolocrypto nightly'
|
|
||||||
# Test no_std only on nightly.
|
# Test no_std only on nightly.
|
||||||
- rust: stable
|
- rust: stable
|
||||||
env: TEST_COMMAND=build EXTRA_FLAGS=--no-default-features FEATURES=''
|
env: TEST_COMMAND=build EXTRA_FLAGS=--no-default-features FEATURES=''
|
||||||
- rust: beta
|
|
||||||
env: TEST_COMMAND=build EXTRA_FLAGS=--no-default-features FEATURES=''
|
|
||||||
- rust: nightly
|
|
||||||
env: TEST_COMMAND=build EXTRA_FLAGS=--no-default-features FEATURES='alloc'
|
|
||||||
|
|
||||||
script:
|
script:
|
||||||
- cargo $TEST_COMMAND --features="$FEATURES" $EXTRA_FLAGS
|
- cargo $TEST_COMMAND --features="$FEATURES" $EXTRA_FLAGS
|
||||||
|
|
|
||||||
19
Cargo.toml
19
Cargo.toml
|
|
@ -60,15 +60,20 @@ serde = { version = "1.0", optional = true }
|
||||||
rand = { version = "0.4", optional = false }
|
rand = { version = "0.4", optional = false }
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
nightly = ["radix_51", "subtle/nightly", "clear_on_drop/nightly"]
|
nightly = ["subtle/nightly", "clear_on_drop/nightly"]
|
||||||
default = ["std"]
|
default = ["std", "u64_backend"]
|
||||||
std = ["rand", "subtle/std"]
|
std = ["rand", "subtle/std"]
|
||||||
alloc = []
|
alloc = []
|
||||||
yolocrypto = ["avx2_backend"]
|
yolocrypto = []
|
||||||
# Radix-51 arithmetic using u128
|
|
||||||
radix_51 = []
|
# The u32 backend uses u32s with u64 products.
|
||||||
# experimental avx2 support
|
u32_backend = []
|
||||||
avx2_backend = ["nightly"]
|
# The u64 backend uses u64s with u128 products.
|
||||||
|
u64_backend = []
|
||||||
|
# The AVX2 backend uses u32x8s with u64x4 products.
|
||||||
|
# It uses the u64 code for serial operations.
|
||||||
|
avx2_backend = ["nightly", "u64_backend"]
|
||||||
|
|
||||||
# Signals that we're in the main build stage. This is off by default,
|
# Signals that we're in the main build stage. This is off by default,
|
||||||
# to signal stage 1 of the build, where build.rs loads the library
|
# to signal stage 1 of the build, where build.rs loads the library
|
||||||
# into the build script. Then, the build.rs emits the stage2_build
|
# into the build script. Then, the build.rs emits the stage2_build
|
||||||
|
|
|
||||||
29
README.md
29
README.md
|
|
@ -59,25 +59,38 @@ extern crate curve25519_dalek;
|
||||||
|
|
||||||
# Backends and Features
|
# Backends and Features
|
||||||
|
|
||||||
|
The `yolocrypto` feature enables experimental features. The name `yolocrypto`
|
||||||
|
is meant to indicate that it is not considered production-ready, and we do not
|
||||||
|
consider `yolocrypto` features to be covered by semver guarantees.
|
||||||
|
|
||||||
|
The `std` feature is enabled by default, but it can be disabled.
|
||||||
|
|
||||||
|
The `nightly` feature enables nightly-only features. **It is recommended for security**.
|
||||||
|
|
||||||
Curve arithmetic is implemented using one of the following backends:
|
Curve arithmetic is implemented using one of the following backends:
|
||||||
|
|
||||||
* a `u32` backend using `u64` products;
|
* a `u32` backend using `u64` products;
|
||||||
* a `u64` backend using `u128` products, available using the `nightly` feature;
|
* a `u64` backend using `u128` products;
|
||||||
* an experimental AVX2 backend, available using the `yolocrypto` feature when
|
* an experimental AVX2 backend, available using the `yolocrypto` feature when
|
||||||
compiling for a target with `target_feature=+avx2`.
|
compiling for a target with `target_feature=+avx2`.
|
||||||
|
|
||||||
|
By default the `u64` backend is selected. To select a specific backend, use:
|
||||||
|
```sh
|
||||||
|
cargo build --no-default-features --features "std u32_backend"
|
||||||
|
cargo build --no-default-features --features "std u64_backend"
|
||||||
|
cargo build --no-default-features --features "std avx2_backend yolocrypto"
|
||||||
|
```
|
||||||
|
|
||||||
Benchmarks are run using [`criterion.rs`][criterion]:
|
Benchmarks are run using [`criterion.rs`][criterion]:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
cargo bench # u32 backend
|
# You must set RUSTFLAGS to enable AVX2 support.
|
||||||
cargo bench --features="nightly" # u64 backend
|
export RUSTFLAGS="-C target_cpu=native"
|
||||||
cargo bench --features="nightly yolocrypto" # u64 or avx2 if available
|
cargo bench --no-default-features --features "std u32_backend"
|
||||||
|
cargo bench --no-default-features --features "std u64_backend"
|
||||||
|
cargo bench --no-default-features --features "std avx2_backend yolocrypto"
|
||||||
```
|
```
|
||||||
|
|
||||||
The `yolocrypto` feature enables experimental features. The name `yolocrypto`
|
|
||||||
is meant to indicate that it is not considered production-ready, and we do not
|
|
||||||
consider `yolocrypto` features to be covered by semver guarantees.
|
|
||||||
|
|
||||||
# Contributing
|
# Contributing
|
||||||
|
|
||||||
Please see [CONTRIBUTING.md][contributing].
|
Please see [CONTRIBUTING.md][contributing].
|
||||||
|
|
|
||||||
9
build.rs
9
build.rs
|
|
@ -1,4 +1,3 @@
|
||||||
#![cfg_attr(feature = "nightly", feature(i128_type))]
|
|
||||||
#![cfg_attr(feature = "nightly", feature(cfg_target_feature))]
|
#![cfg_attr(feature = "nightly", feature(cfg_target_feature))]
|
||||||
#![cfg_attr(all(feature = "nightly", feature = "yolocrypto"), feature(stdsimd))]
|
#![cfg_attr(all(feature = "nightly", feature = "yolocrypto"), feature(stdsimd))]
|
||||||
#![allow(unused_variables)]
|
#![allow(unused_variables)]
|
||||||
|
|
@ -75,12 +74,12 @@ fn main() {
|
||||||
f.write_all(
|
f.write_all(
|
||||||
format!(
|
format!(
|
||||||
"\n
|
"\n
|
||||||
#[cfg(feature=\"radix_51\")]
|
#[cfg(feature = \"u32_backend\")]
|
||||||
use backend::u64::field::FieldElement64;
|
|
||||||
|
|
||||||
#[cfg(not(feature=\"radix_51\"))]
|
|
||||||
use backend::u32::field::FieldElement32;
|
use backend::u32::field::FieldElement32;
|
||||||
|
|
||||||
|
#[cfg(feature = \"u64_backend\")]
|
||||||
|
use backend::u64::field::FieldElement64;
|
||||||
|
|
||||||
use edwards::EdwardsBasepointTable;
|
use edwards::EdwardsBasepointTable;
|
||||||
|
|
||||||
use curve_models::AffineNielsPoint;
|
use curve_models::AffineNielsPoint;
|
||||||
|
|
|
||||||
|
|
@ -21,12 +21,12 @@
|
||||||
//! `32bit` since identifiers can't start with letters, and the backends
|
//! `32bit` since identifiers can't start with letters, and the backends
|
||||||
//! do use `u32`/`u64`, so this seems like a least-bad option.
|
//! do use `u32`/`u64`, so this seems like a least-bad option.
|
||||||
|
|
||||||
#[cfg(not(feature="radix_51"))]
|
#[cfg(feature = "u32_backend")]
|
||||||
pub mod u32;
|
pub mod u32;
|
||||||
|
|
||||||
#[cfg(feature="radix_51")]
|
#[cfg(feature = "u64_backend")]
|
||||||
pub mod u64;
|
pub mod u64;
|
||||||
|
|
||||||
#[cfg(all(feature="nightly", all(feature="avx2_backend", target_feature="avx2")))]
|
#[cfg(all(feature = "avx2_backend", feature = "yolocrypto", target_feature = "avx2"))]
|
||||||
pub mod avx2;
|
pub mod avx2;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -33,9 +33,9 @@ use ristretto::CompressedRistretto;
|
||||||
use montgomery::MontgomeryPoint;
|
use montgomery::MontgomeryPoint;
|
||||||
use scalar::Scalar;
|
use scalar::Scalar;
|
||||||
|
|
||||||
#[cfg(feature="radix_51")]
|
#[cfg(feature = "u64_backend")]
|
||||||
pub use backend::u64::constants::*;
|
pub use backend::u64::constants::*;
|
||||||
#[cfg(not(feature="radix_51"))]
|
#[cfg(feature = "u32_backend")]
|
||||||
pub use backend::u32::constants::*;
|
pub use backend::u32::constants::*;
|
||||||
|
|
||||||
/// The Ed25519 basepoint, in `CompressedEdwardsY` format.
|
/// The Ed25519 basepoint, in `CompressedEdwardsY` format.
|
||||||
|
|
@ -149,8 +149,8 @@ mod test {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Test that d = -121665/121666
|
/// Test that d = -121665/121666
|
||||||
#[cfg(not(feature="radix_51"))]
|
|
||||||
#[test]
|
#[test]
|
||||||
|
#[cfg(feature = "u32_backend")]
|
||||||
fn test_d_vs_ratio() {
|
fn test_d_vs_ratio() {
|
||||||
use backend::u32::field::FieldElement32;
|
use backend::u32::field::FieldElement32;
|
||||||
let a = -&FieldElement32([121665,0,0,0,0,0,0,0,0,0]);
|
let a = -&FieldElement32([121665,0,0,0,0,0,0,0,0,0]);
|
||||||
|
|
@ -162,8 +162,8 @@ mod test {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Test that d = -121665/121666
|
/// Test that d = -121665/121666
|
||||||
#[cfg(feature="radix_51")]
|
|
||||||
#[test]
|
#[test]
|
||||||
|
#[cfg(feature = "u64_backend")]
|
||||||
fn test_d_vs_ratio() {
|
fn test_d_vs_ratio() {
|
||||||
use backend::u64::field::FieldElement64;
|
use backend::u64::field::FieldElement64;
|
||||||
let a = -&FieldElement64([121665,0,0,0,0]);
|
let a = -&FieldElement64([121665,0,0,0,0]);
|
||||||
|
|
|
||||||
|
|
@ -490,13 +490,13 @@ impl<'a, 'b> Mul<&'b Scalar> for &'a EdwardsPoint {
|
||||||
/// `EdwardsBasepointTable` is approximately 4x faster.
|
/// `EdwardsBasepointTable` is approximately 4x faster.
|
||||||
fn mul(self, scalar: &'b Scalar) -> EdwardsPoint {
|
fn mul(self, scalar: &'b Scalar) -> EdwardsPoint {
|
||||||
// If we built with AVX2, use the AVX2 backend.
|
// If we built with AVX2, use the AVX2 backend.
|
||||||
#[cfg(all(feature="nightly", all(feature="avx2_backend", target_feature="avx2")))]
|
#[cfg(all(feature="avx2_backend", target_feature="avx2"))]
|
||||||
{
|
{
|
||||||
use backend::avx2::scalar_mul::variable_base::mul;
|
use backend::avx2::scalar_mul::variable_base::mul;
|
||||||
mul(self, scalar)
|
mul(self, scalar)
|
||||||
}
|
}
|
||||||
// Otherwise, use the serial backend:
|
// Otherwise, use the serial backend:
|
||||||
#[cfg(not(all(feature="nightly", all(feature="avx2_backend", target_feature="avx2"))))]
|
#[cfg(not(all(feature="avx2_backend", target_feature="avx2")))]
|
||||||
{
|
{
|
||||||
use scalar_mul::variable_base::mul;
|
use scalar_mul::variable_base::mul;
|
||||||
mul(self, scalar)
|
mul(self, scalar)
|
||||||
|
|
@ -571,13 +571,13 @@ pub fn multiscalar_mul<I, J>(scalars: I, points: J) -> EdwardsPoint
|
||||||
// delegate based on the iter's size hint -- hdevalence
|
// delegate based on the iter's size hint -- hdevalence
|
||||||
|
|
||||||
// If we built with AVX2, use the AVX2 backend.
|
// If we built with AVX2, use the AVX2 backend.
|
||||||
#[cfg(all(feature="nightly", all(feature="avx2_backend", target_feature="avx2")))]
|
#[cfg(all(feature="avx2_backend", target_feature="avx2"))]
|
||||||
{
|
{
|
||||||
use backend::avx2::scalar_mul::straus::multiscalar_mul;
|
use backend::avx2::scalar_mul::straus::multiscalar_mul;
|
||||||
multiscalar_mul(scalars, points)
|
multiscalar_mul(scalars, points)
|
||||||
}
|
}
|
||||||
// Otherwise, proceed as normal:
|
// Otherwise, proceed as normal:
|
||||||
#[cfg(not(all(feature="nightly", all(feature="avx2_backend", target_feature="avx2"))))]
|
#[cfg(not(all(feature="avx2_backend", target_feature="avx2")))]
|
||||||
{
|
{
|
||||||
use scalar_mul::straus::multiscalar_mul;
|
use scalar_mul::straus::multiscalar_mul;
|
||||||
multiscalar_mul(scalars, points)
|
multiscalar_mul(scalars, points)
|
||||||
|
|
@ -844,13 +844,13 @@ pub mod vartime {
|
||||||
// XXX later when we do more fancy multiscalar mults, we can delegate
|
// XXX later when we do more fancy multiscalar mults, we can delegate
|
||||||
// based on the iter's size hint -- hdevalence
|
// based on the iter's size hint -- hdevalence
|
||||||
// If we built with AVX2, use the AVX2 backend.
|
// If we built with AVX2, use the AVX2 backend.
|
||||||
#[cfg(all(feature="nightly", all(feature="avx2_backend", target_feature="avx2")))]
|
#[cfg(all(feature="avx2_backend", target_feature="avx2"))]
|
||||||
{
|
{
|
||||||
use backend::avx2::scalar_mul::vartime_straus::multiscalar_mul;
|
use backend::avx2::scalar_mul::vartime_straus::multiscalar_mul;
|
||||||
multiscalar_mul(scalars, points)
|
multiscalar_mul(scalars, points)
|
||||||
}
|
}
|
||||||
// Otherwise, proceed as normal:
|
// Otherwise, proceed as normal:
|
||||||
#[cfg(not(all(feature="nightly", all(feature="avx2_backend", target_feature="avx2"))))]
|
#[cfg(not(all(feature="avx2_backend", target_feature="avx2")))]
|
||||||
{
|
{
|
||||||
use scalar_mul::vartime_straus::multiscalar_mul;
|
use scalar_mul::vartime_straus::multiscalar_mul;
|
||||||
multiscalar_mul(scalars, points)
|
multiscalar_mul(scalars, points)
|
||||||
|
|
@ -861,13 +861,13 @@ pub mod vartime {
|
||||||
#[cfg(feature="stage2_build")]
|
#[cfg(feature="stage2_build")]
|
||||||
pub fn double_scalar_mul_basepoint(a: &Scalar, A: &EdwardsPoint, b: &Scalar) -> EdwardsPoint {
|
pub fn double_scalar_mul_basepoint(a: &Scalar, A: &EdwardsPoint, b: &Scalar) -> EdwardsPoint {
|
||||||
// If we built with AVX2, use the AVX2 backend.
|
// If we built with AVX2, use the AVX2 backend.
|
||||||
#[cfg(all(feature="nightly", all(feature="avx2_backend", target_feature="avx2")))]
|
#[cfg(all(feature="avx2_backend", target_feature="avx2"))]
|
||||||
{
|
{
|
||||||
use backend::avx2::scalar_mul::vartime_double_base::mul;
|
use backend::avx2::scalar_mul::vartime_double_base::mul;
|
||||||
mul(a, A, b)
|
mul(a, A, b)
|
||||||
}
|
}
|
||||||
// Otherwise, proceed as normal:
|
// Otherwise, proceed as normal:
|
||||||
#[cfg(not(all(feature="nightly", all(feature="avx2_backend", target_feature="avx2"))))]
|
#[cfg(not(all(feature="avx2_backend", target_feature="avx2")))]
|
||||||
{
|
{
|
||||||
use scalar_mul::vartime_double_base::mul;
|
use scalar_mul::vartime_double_base::mul;
|
||||||
mul(a, A, b)
|
mul(a, A, b)
|
||||||
|
|
@ -1169,7 +1169,7 @@ mod test {
|
||||||
/// and enable `debug_assert!()`. This performs many scalar
|
/// and enable `debug_assert!()`. This performs many scalar
|
||||||
/// multiplications to attempt to trigger possible overflows etc.
|
/// multiplications to attempt to trigger possible overflows etc.
|
||||||
///
|
///
|
||||||
/// For instance, the `radix_51` `Mul` implementation for
|
/// For instance, the `u64` `Mul` implementation for
|
||||||
/// `FieldElements` requires the input `Limb`s to be bounded by
|
/// `FieldElements` requires the input `Limb`s to be bounded by
|
||||||
/// 2^54, but we cannot enforce this dynamically at runtime, or
|
/// 2^54, but we cannot enforce this dynamically at runtime, or
|
||||||
/// statically at compile time (until Rust gets type-level
|
/// statically at compile time (until Rust gets type-level
|
||||||
|
|
|
||||||
|
|
@ -32,24 +32,24 @@ use subtle::ConstantTimeEq;
|
||||||
use constants;
|
use constants;
|
||||||
use backend;
|
use backend;
|
||||||
|
|
||||||
#[cfg(feature="radix_51")]
|
#[cfg(feature = "u64_backend")]
|
||||||
pub use backend::u64::field::*;
|
pub use backend::u64::field::*;
|
||||||
/// A `FieldElement` represents an element of the field
|
/// A `FieldElement` represents an element of the field
|
||||||
/// \\( \mathbb Z / (2\^{255} - 19)\\).
|
/// \\( \mathbb Z / (2\^{255} - 19)\\).
|
||||||
///
|
///
|
||||||
/// The `FieldElement` type is an alias for one of the platform-specific
|
/// The `FieldElement` type is an alias for one of the platform-specific
|
||||||
/// implementations.
|
/// implementations.
|
||||||
#[cfg(feature="radix_51")]
|
#[cfg(feature = "u64_backend")]
|
||||||
pub type FieldElement = backend::u64::field::FieldElement64;
|
pub type FieldElement = backend::u64::field::FieldElement64;
|
||||||
|
|
||||||
#[cfg(not(feature="radix_51"))]
|
#[cfg(feature = "u32_backend")]
|
||||||
pub use backend::u32::field::*;
|
pub use backend::u32::field::*;
|
||||||
/// A `FieldElement` represents an element of the field
|
/// A `FieldElement` represents an element of the field
|
||||||
/// \\( \mathbb Z / (2\^{255} - 19)\\).
|
/// \\( \mathbb Z / (2\^{255} - 19)\\).
|
||||||
///
|
///
|
||||||
/// The `FieldElement` type is an alias for one of the platform-specific
|
/// The `FieldElement` type is an alias for one of the platform-specific
|
||||||
/// implementations.
|
/// implementations.
|
||||||
#[cfg(not(feature="radix_51"))]
|
#[cfg(feature = "u32_backend")]
|
||||||
pub type FieldElement = backend::u32::field::FieldElement32;
|
pub type FieldElement = backend::u32::field::FieldElement32;
|
||||||
|
|
||||||
impl Eq for FieldElement {}
|
impl Eq for FieldElement {}
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,6 @@
|
||||||
|
|
||||||
#![cfg_attr(feature = "alloc", feature(alloc))]
|
#![cfg_attr(feature = "alloc", feature(alloc))]
|
||||||
|
|
||||||
#![cfg_attr(feature = "nightly", feature(i128_type))]
|
|
||||||
#![cfg_attr(feature = "nightly", feature(cfg_target_feature))]
|
#![cfg_attr(feature = "nightly", feature(cfg_target_feature))]
|
||||||
#![cfg_attr(feature = "nightly", feature(external_doc))]
|
#![cfg_attr(feature = "nightly", feature(external_doc))]
|
||||||
#![cfg_attr(all(feature = "nightly", feature = "yolocrypto"), feature(stdsimd))]
|
#![cfg_attr(all(feature = "nightly", feature = "yolocrypto"), feature(stdsimd))]
|
||||||
|
|
|
||||||
|
|
@ -39,14 +39,14 @@ use constants;
|
||||||
///
|
///
|
||||||
/// This is a type alias for one of the scalar types in the `backend`
|
/// This is a type alias for one of the scalar types in the `backend`
|
||||||
/// module.
|
/// module.
|
||||||
#[cfg(feature="radix_51")]
|
#[cfg(feature = "u64_backend")]
|
||||||
type UnpackedScalar = backend::u64::scalar::Scalar64;
|
type UnpackedScalar = backend::u64::scalar::Scalar64;
|
||||||
|
|
||||||
/// An `UnpackedScalar` represents an element of the field GF(l), optimized for speed.
|
/// An `UnpackedScalar` represents an element of the field GF(l), optimized for speed.
|
||||||
///
|
///
|
||||||
/// This is a type alias for one of the scalar types in the `backend`
|
/// This is a type alias for one of the scalar types in the `backend`
|
||||||
/// module.
|
/// module.
|
||||||
#[cfg(not(feature="radix_51"))]
|
#[cfg(feature = "u32_backend")]
|
||||||
type UnpackedScalar = backend::u32::scalar::Scalar32;
|
type UnpackedScalar = backend::u32::scalar::Scalar32;
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue