#![allow(non_snake_case)]
use super::{
extended_edwards::ExtendedPoint, field::field_element::FieldElement,
projective_niels::ProjectiveNielsPoint,
};
use fiat_crypto::p448_solinas_64::fiat_p448_tight_field_element;
use zeroize::{Zeroize, ZeroizeOnDrop};
pub const TWO_TIMES_TWISTED_D: FieldElement = FieldElement(fiat_p448_tight_field_element([
144115188075777706,
144115188075855870,
144115188075855870,
144115188075855870,
144115188075855868,
144115188075855870,
144115188075855870,
144115188075855870,
]));
pub const TWISTED_D: FieldElement = FieldElement(fiat_p448_tight_field_element([
144115188075816788,
144115188075855870,
144115188075855870,
144115188075855870,
144115188075855868,
144115188075855870,
144115188075855870,
144115188075855870,
]));
#[derive(Zeroize, ZeroizeOnDrop)]
pub struct TwistedPoint {
pub X: FieldElement,
pub Y: FieldElement,
pub Z: FieldElement,
pub T1: FieldElement,
pub T2: FieldElement,
}
impl core::fmt::Debug for TwistedPoint {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "TwistedPoint(****)")
}
}
impl core::fmt::Display for TwistedPoint {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "TwistedPoint(REDACTED)")
}
}
impl TwistedPoint {
pub fn identity() -> TwistedPoint {
TwistedPoint {
X: FieldElement::zero(),
Y: FieldElement::one(),
Z: FieldElement::one(),
T1: FieldElement::zero(),
T2: FieldElement::one(),
}
}
pub fn to_projective_niels(&self) -> ProjectiveNielsPoint {
ProjectiveNielsPoint {
Y_plus_X: self.X + self.Y,
Y_minus_X: self.Y - self.X,
Z: self.Z + self.Z,
Td: self.T1 * self.T2 * TWO_TIMES_TWISTED_D,
}
}
pub fn to_extended(&self) -> ExtendedPoint {
ExtendedPoint {
X: self.X,
Y: self.Y,
Z: self.Z,
T: self.T1 * self.T2,
}
}
pub fn add_extensible(&self, other: &TwistedPoint) -> TwistedPoint {
self.add_extended(&other.to_extended())
}
pub fn add_projective_niels(&self, other: &ProjectiveNielsPoint) -> TwistedPoint {
let Z = self.Z * other.Z;
let A = (self.Y - self.X) * other.Y_minus_X;
let B = (self.Y + self.X) * other.Y_plus_X;
let C = other.Td * self.T1 * self.T2;
let D = B + A;
let E = B - A;
let F = Z - C;
let G = Z + C;
TwistedPoint {
X: E * F,
Y: G * D,
Z: F * G,
T1: E,
T2: D,
}
}
pub fn add_extended(&self, other: &ExtendedPoint) -> TwistedPoint {
let A = self.X * other.X;
let B = self.Y * other.Y;
let C = self.T1 * self.T2 * other.T * TWISTED_D;
let D = self.Z * other.Z;
let E = (self.X + self.Y) * (other.X + other.Y) - A - B;
let F = D - C;
let G = D + C;
let H = B + A;
TwistedPoint {
X: E * F,
Y: G * H,
T1: E,
T2: H,
Z: F * G,
}
}
pub fn double(&self) -> TwistedPoint {
let A = self.X.square();
let B = self.Y.square();
let C = self.Z.square() + self.Z.square();
let D = A.negate();
let E = (self.X + self.Y).square() - A - B;
let G = D + B;
let F = G - C;
let H = D - B;
TwistedPoint {
X: E * F,
Y: G * H,
Z: F * G,
T1: E,
T2: H,
}
}
pub fn sub_extended(&self, other: &ExtendedPoint) -> TwistedPoint {
let A = self.X * other.X;
let B = self.Y * other.Y;
let C = self.T1 * self.T2 * other.T * TWISTED_D;
let D = self.Z * other.Z;
let E = (self.X + self.Y) * (other.Y - other.X) + A - B;
let F = D + C;
let G = D - C;
let H = B - A;
TwistedPoint {
X: E * F,
Y: G * H,
T1: E,
T2: H,
Z: F * G,
}
}
}