use crate::prelude::*;
elliptic_curve_model! {
[attributes]
name = TwistedEdwards
coordinates = (x, y, z, t)
constants = (a, d)
[functions]
#[inline(always)]
add: (P: Point, Q: Point) -> Point
xx <- P.x * Q.x yy <- P.y * Q.y tt <- P.t * Q.t * d zz <- P.z * Q.z
xyxy <- (P.x + P.y) * (Q.x + Q.y) - xx - yy zzd <- zz - tt zzp <- zz + tt yahx <- yy - a * xx x <- xyxy * zzd
y <- zzp * yahx
t <- xyxy * yahx
z <- zzd * zzp
Point::new(x, y, z, t)
#[inline(always)]
dbl: (P: Point) -> Point
xx <- P.x.sqr() yy <- P.y.sqr() zz <- P.z.sqr().dbl() d <- a * xx xyxy <- (P.x + P.y).sqr() - xx - yy g <- d + yy f <- g - zz h <- d - yy x <- xyxy * f
y <- g * h
t <- xyxy * h
z <- f * g
Point::new(x, y, z, t)
#[inline(always)]
montgomery_u: (P: Point) -> Element
u <- P.z + P.y
w <- P.z - P.y
u * w.inv()
#[inline(always)]
serialize: (P: Point) -> Bytes
z_inv <- P.z.inv()
x <- P.x * z_inv
y <- P.y * z_inv
flag <- x.is_even() ? 0 : 1
Bytes::from(y.serialize_with_flags(flag))
#[inline(always)]
deserialize: (bytes: Bytes) -> Point
(y, flags) <- Element::deserialize_with_flags(bytes)
flag <- flags.get(0)
y2 <- y.sqr()
u <- 1 - y2
v <- a - d * y2
x2 <- u * v.inv()
x <- x2.sqrt()
x <- flag ? x.neg() : x
Point::new(x, y, Element::from(1), x * y)
#[inline(always)]
equal: (P: Point, Q: Point) -> Bool
x_equal <- P.x * Q.z = Q.x * P.z
y_equal <- P.y * Q.z = Q.y * P.z
x_equal & y_equal
#[inline(always)]
neg: (P: Point) -> Point
Point::new(-(P.x), P.y, P.z, -(P.t))
}