This change provides a common convention for using allocator-dependent
features with:
#![cfg(feature = "alloc")]
When available, `Vec` is imported consistently as `prelude::Vec`, which
means modules that need access to `Vec` can simply do:
use prelude::*;
and if an allocator is available, `Vec` will be in the crate prelude.
This allows all `alloc` vs `std` gating to be handled in `lib.rs`,
`build.rs`, and `prelude.rs` so the rest of the codebase doesn't have to
do any gating whatsoever.
This changes the primary function for the `VartimeMultiscalarMul` trait
to an `optional_multiscalar_mul` trait that accepts
`Option<Self::Point>` (and returns `None` if any input points are
`None`).
The existing `vartime_multiscalar_mul` is changed to be a wrapper around
this function to avoid code duplication. This may result in an
extra copy of each input point, but that cost is probably not
significant compared to the cost of the multiscalar multiplication.
The motivation is to allow performing multiscalar multiplications with
inline decompression. Currently, API consumers have to allocate
temporary buffers for all of their points, decompress into those
buffers, then pass (iterators over) those buffers into the multiscalar
multiplication code, which then creates new buffers for lookup tables.
Change Scalar::non_adjacent_form() to take a width parameter.
This rewrite also makes it faster, although it's probably a ways off
from optimal. I don't know how much it matters.
TODO: write up description of why this computes the same thing.
Thanks to @oleganza for pointing out an error reading bits across words
in an earlier version of this code.
The serial (`u32`/`u64`) implementations use a multiple curve models, passing
between extended and projective coordinates when performing addition and
doubling (respectively). But the AVX2 backend doesn't, so in order to write a
single scalar mult implementation, we have to either abstract over the curve
models or have two implementations.
A generic solution is possible but extremely unreadable: the scalar mul
implementation would be parameterized over the point types used by the serial
implementations, with many where clauses describing how the types relate. The
AVX2 types could then be substituted in the appropriate places.
Instead we just duplicate the code into the `avx2` backend.
This should contain generic implementations of scalar multiplication algorithms
that can be used with multiple backends. The goal is to move the existing
scalar multiplication code into this submodule, then call it from the
user-facing API. This can also contain code for things we can't do now, like
multiscalar multiplication with precomputation.