Apply the optimized pow to dalek-ff-group

Saves ~40% from Monero hash_to_curve, assisting with #68.
This commit is contained in:
Luke Parker 2022-08-31 00:57:23 -04:00
parent c5256d9b06
commit cc0c6fb5ac
No known key found for this signature in database
GPG key ID: F9F1386DB1E119B6

View file

@ -8,7 +8,7 @@ use crypto_bigint::{Encoding, U256, U512};
use ff::{Field, PrimeField, FieldBits, PrimeFieldBits}; use ff::{Field, PrimeField, FieldBits, PrimeFieldBits};
use crate::{choice, constant_time, math, from_uint}; use crate::{constant_time, math, from_uint};
const FIELD_MODULUS: U256 = const FIELD_MODULUS: U256 =
U256::from_be_hex("7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffed"); U256::from_be_hex("7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffed");
@ -155,11 +155,29 @@ impl FieldElement {
} }
pub fn pow(&self, other: FieldElement) -> FieldElement { pub fn pow(&self, other: FieldElement) -> FieldElement {
let mut table = [FieldElement(U256::ONE); 16];
table[1] = *self;
for i in 2 .. 16 {
table[i] = table[i - 1] * self;
}
let mut res = FieldElement(U256::ONE); let mut res = FieldElement(U256::ONE);
let mut m = *self; let mut bits = 0;
for bit in other.to_le_bits() { for (i, bit) in other.to_le_bits().iter().rev().enumerate() {
res *= FieldElement::conditional_select(&FieldElement(U256::ONE), &m, choice(bit)); bits <<= 1;
m *= m; let bit = *bit as u8;
assert_eq!(bit | 1, 1);
bits |= bit;
if ((i + 1) % 4) == 0 {
if i != 3 {
for _ in 0 .. 4 {
res *= res;
}
}
res *= table[usize::from(bits)];
bits = 0;
}
} }
res res
} }