use super::{WnafBase, WnafScalar};
use crate::{ProjectivePoint, Scalar, arithmetic::scalar::WideScalar};
use elliptic_curve::scalar::IsHigh;
use primeorder::PrimeFieldExt;
const MINUS_LAMBDA: Scalar = Scalar::from_bytes_unchecked(&[
0xac, 0x9c, 0x52, 0xb3, 0x3f, 0xa3, 0xcf, 0x1f, 0x5a, 0xd9, 0xe3, 0xfd, 0x77, 0xed, 0x9b, 0xa4,
0xa8, 0x80, 0xb9, 0xfc, 0x8e, 0xc7, 0x39, 0xc2, 0xe0, 0xcf, 0xc8, 0x10, 0xb5, 0x12, 0x83, 0xcf,
]);
const MINUS_B1: Scalar = Scalar::from_bytes_unchecked(&[
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xe4, 0x43, 0x7e, 0xd6, 0x01, 0x0e, 0x88, 0x28, 0x6f, 0x54, 0x7f, 0xa9, 0x0a, 0xbf, 0xe4, 0xc3,
]);
const MINUS_B2: Scalar = Scalar::from_bytes_unchecked(&[
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe,
0x8a, 0x28, 0x0a, 0xc5, 0x07, 0x74, 0x34, 0x6d, 0xd7, 0x65, 0xcd, 0xa8, 0x3d, 0xb1, 0x56, 0x2c,
]);
const G1: Scalar = Scalar::from_bytes_unchecked(&[
0x30, 0x86, 0xd2, 0x21, 0xa7, 0xd4, 0x6b, 0xcd, 0xe8, 0x6c, 0x90, 0xe4, 0x92, 0x84, 0xeb, 0x15,
0x3d, 0xaa, 0x8a, 0x14, 0x71, 0xe8, 0xca, 0x7f, 0xe8, 0x93, 0x20, 0x9a, 0x45, 0xdb, 0xb0, 0x31,
]);
const G2: Scalar = Scalar::from_bytes_unchecked(&[
0xe4, 0x43, 0x7e, 0xd6, 0x01, 0x0e, 0x88, 0x28, 0x6f, 0x54, 0x7f, 0xa9, 0x0a, 0xbf, 0xe4, 0xc4,
0x22, 0x12, 0x08, 0xac, 0x9d, 0xf5, 0x06, 0xc6, 0x15, 0x71, 0xb4, 0xae, 0x8a, 0xc4, 0x7f, 0x71,
]);
const GLV_LE_BYTES: usize = 16;
pub(super) fn decompose_scalar(k: &Scalar) -> (Scalar, Scalar) {
let c1 = WideScalar::mul_shift_vartime(k, &G1, 384) * MINUS_B1;
let c2 = WideScalar::mul_shift_vartime(k, &G2, 384) * MINUS_B2;
let r2 = c1 + c2;
let r1 = k + r2 * MINUS_LAMBDA;
(r1, r2)
}
#[inline]
pub(super) fn decompose_wnaf(x: &ProjectivePoint, k: &Scalar) -> ([WnafBase; 2], [WnafScalar; 2]) {
let mut bases = [WnafBase::default(), WnafBase::default()];
let mut scalars = [WnafScalar::default(), WnafScalar::default()];
decompose_wnaf_into(x, k, &mut bases, &mut scalars);
(bases, scalars)
}
#[inline]
pub(super) fn decompose_wnaf_into(
x: &ProjectivePoint,
k: &Scalar,
bases: &mut [WnafBase; 2],
scalars: &mut [WnafScalar; 2],
) {
let (r1, r2) = decompose_scalar(k);
let r1_neg = bool::from(r1.is_high());
let r2_neg = bool::from(r2.is_high());
let r1 = if r1_neg { -r1 } else { r1 };
let r2 = if r2_neg { -r2 } else { r2 };
scalars[0].init_from_le_bytes(&r1.to_le_repr()[..GLV_LE_BYTES]);
scalars[1].init_from_le_bytes(&r2.to_le_repr()[..GLV_LE_BYTES]);
let p1 = if r1_neg { -*x } else { *x };
let p_beta = x.endomorphism();
let p2 = if r2_neg { -p_beta } else { p_beta };
bases[0].init_from_base(&p1);
bases[1].init_from_base(&p2);
}