This doesn't (yet) give any speedup over the non-precomputed multiscalar
multiplication, and it's not clear that it's a good idea to commit to
supporting it in the future. Removing it means that it's not committed-to as
part of the public API, but the source is still there in the tree if we want to
revisit it later.
Since computation of the 0 term in reduction requires a multiplication with a
4-cycle latency, this ensures that the rest of the computation can start before
the 0 term is finished
This splits the `FieldElement51x4` type into two types:
- `F51x4Reduced` (with reduced limbs)
- `F51x4Unreduced` (with unreduced limbs)
The reduction is implemented as a `From` impl to convert one type to the other.
The output of a multiplication is now a `F51x4Unreduced`. The reason is that
the inputs to IFMA operations must be at most 52 bits, so it's not possible to
perform an addition of (51+epsilon)-bit values and still be small enough to be
used as an input to multiplication. So, it doesn't make sense to perform a
reduction at the end of a multiplication, because the reduced values will be
fed into an addition or subtraction, which then needs to be re-reduced.
This begins to attempt to restructure the source tree so that the common parts
are common and the different parts are different.
The backend is now split into two parts:
- serial (containing the implementation using serial formulas and mixed-model arithmetic).
- vector (containing the implementation using parallel formulas and single-model arithmetic).
The serial scalar_mul tree is now under backend::serial::scalar_mul.
The avx2 scalar_mul tree is now under backend::avx2::scalar_mul.
`FieldElement32` -> `FieldElement2625`
`FieldElement64` -> `FieldElement51`
`Scalar32` -> `Scalar29`
`Scalar64` -> `Scalar52`
This naming is more accurate and would let us add an ADX backend later.