use crate::p256_ecc::{Point, P256C_PARAMS};
pub(crate) fn add_1998_cmo(p1: &Point, p2: &Point) -> Point {
let x1 = &p1.x;
let y1 = &p1.y;
let z1 = &p1.z;
let x2 = &p2.x;
let y2 = &p2.y;
let z2 = &p2.z;
let z1z1 = z1.square();
let z2z2 = z2.square();
let u1 = x1 * &z2z2;
let u2 = x2 * &z1z1;
let s1 = y1 * z2 * &z2z2;
let s2 = y2 * z1 * &z1z1;
let h = &u2 - &u1;
let r = &s2 - &s1;
let hh = h.square();
let hhh = &h * &hh;
let v = &u1 * &hh;
let x3 = &r.square() - &hhh - &v.double();
let y3 = &r * (&v - &x3) - &s1 * &hhh;
let z3 = z1 * z2 * &h;
Point {
x: x3,
y: y3,
z: z3,
}
}
pub(crate) fn double_1998_cmo(p1: &Point) -> Point {
let ecc_a = &P256C_PARAMS.a;
let (x1, y1, z1) = (&p1.x, &p1.y, &p1.z);
let is_z1_one = z1.is_one();
let yy = y1.square();
let yyyy = &yy.square();
let xx = x1.square();
let s = x1.double().double() * &yy;
if !is_z1_one {
let zz = z1.square();
let m = &xx.double() + &xx + ecc_a * &zz.square();
let t = &m.square() - &s.double();
let y3 = &m * (&s - &t) - yyyy.double().double().double();
let x3 = t;
let z3 = (y1 + z1).square() - &yy - &zz;
Point {
x: x3,
y: y3,
z: z3,
}
} else {
let m = (xx.double() + xx) + ecc_a;
let t = &m.square() - &s.double();
let x3 = t;
let y3 = m * (s - &x3) - yyyy.double().double().double();
let z3 = y1.double();
Point {
x: x3,
y: y3,
z: z3,
}
}
}