use crate::bignum::Uint;
#[cfg(any(feature = "hazmat-edwards25519", feature = "ristretto255"))]
use crate::ct::{Choice, ConditionallySelectable};
use super::field::Fe;
fn join(lo: &Fe, hi: &Fe) -> Uint<8> {
let a = lo.as_limbs();
let b = hi.as_limbs();
Uint::from_limbs([a[0], a[1], a[2], a[3], b[0], b[1], b[2], b[3]])
}
fn widen(a: &Fe) -> Uint<8> {
let l = a.as_limbs();
Uint::from_limbs([l[0], l[1], l[2], l[3], 0, 0, 0, 0])
}
fn narrow(a: &Uint<8>) -> Fe {
let l = a.as_limbs();
Uint::from_limbs([l[0], l[1], l[2], l[3]])
}
pub(crate) fn scalar_reduce_wide(bytes: &[u8; 64], l8: &Uint<8>) -> Fe {
narrow(&Uint::<8>::from_le_bytes(bytes).reduce(l8))
}
pub(crate) fn scalar_muladd(r: &Fe, k: &Fe, a: &Fe, l8: &Uint<8>) -> Fe {
let (lo, hi) = k.mul_wide(a);
let (sum, _) = join(&lo, &hi).adc(&widen(r), 0);
narrow(&sum.reduce(l8))
}
#[cfg(any(feature = "hazmat-edwards25519", feature = "ristretto255"))]
pub(crate) fn scalar_mul(a: &Fe, b: &Fe, l8: &Uint<8>) -> Fe {
let (lo, hi) = a.mul_wide(b);
narrow(&join(&lo, &hi).reduce(l8))
}
#[cfg(any(feature = "hazmat-edwards25519", feature = "ristretto255"))]
pub(crate) fn scalar_add(a: &Fe, b: &Fe, l: &Fe) -> Fe {
let (sum, _) = a.adc(b, 0);
let (reduced, borrow) = sum.sbb(l, 0);
Fe::conditional_select(&reduced, &sum, Choice::from((borrow ^ 1) as u8))
}
#[cfg(any(feature = "hazmat-edwards25519", feature = "ristretto255"))]
pub(crate) fn scalar_sub(a: &Fe, b: &Fe, l: &Fe) -> Fe {
let (diff, borrow) = a.sbb(b, 0);
let (wrapped, _) = diff.adc(l, 0);
Fe::conditional_select(&wrapped, &diff, Choice::from(borrow as u8))
}
#[cfg(any(feature = "hazmat-edwards25519", feature = "ristretto255"))]
pub(crate) fn scalar_negate(a: &Fe, l: &Fe) -> Fe {
scalar_sub(&Fe::ZERO, a, l)
}
#[cfg(any(feature = "hazmat-edwards25519", feature = "ristretto255"))]
pub(crate) fn scalar_invert(a: &Fe, l: &Fe, l8: &Uint<8>) -> Fe {
let exp = l.wrapping_sub(&Fe::from_u64(2));
let mut r = Fe::ONE;
let limbs = exp.as_limbs();
let mut i = 256;
while i > 0 {
i -= 1;
r = scalar_mul(&r, &r, l8);
let bit = ((limbs[i / 64] >> (i % 64)) & 1) as u8;
let prod = scalar_mul(&r, a, l8);
r = Fe::conditional_select(&prod, &r, Choice::from(bit));
}
r
}
pub(crate) fn clamp(b: &mut [u8; 32]) {
b[0] &= 248;
b[31] &= 127;
b[31] |= 64;
}