2017-11-17 01:34:28 +00:00
|
|
|
|
// -*- mode: rust; -*-
|
|
|
|
|
|
//
|
|
|
|
|
|
// This file is part of curve25519-dalek.
|
|
|
|
|
|
// Copyright (c) 2016-2017 Isis Lovecruft, Henry de Valence
|
|
|
|
|
|
// See LICENSE for licensing information.
|
|
|
|
|
|
//
|
|
|
|
|
|
// Authors:
|
|
|
|
|
|
// - Isis Agora Lovecruft <isis@patternsinthevoid.net>
|
|
|
|
|
|
// - Henry de Valence <hdevalence@hdevalence.ca>
|
|
|
|
|
|
|
|
|
|
|
|
//! This module contains internal curve representations which are not part
|
|
|
|
|
|
//! of the public API.
|
|
|
|
|
|
//!
|
|
|
|
|
|
//! # Curve representations
|
|
|
|
|
|
//!
|
|
|
|
|
|
//! Internally, we use several different models for the curve. Here
|
|
|
|
|
|
//! is a sketch of the relationship between the models, following [a
|
|
|
|
|
|
//! post](https://moderncrypto.org/mail-archive/curves/2016/000807.html)
|
|
|
|
|
|
//! by Ben Smith on the moderncrypto mailing list.
|
|
|
|
|
|
//!
|
|
|
|
|
|
//! Begin with the affine equation for the curve,
|
|
|
|
|
|
//!
|
|
|
|
|
|
//! -x² + y² = 1 + dx²y². <span style="float: right">(1)</span>
|
|
|
|
|
|
//!
|
|
|
|
|
|
//! Next, pass to the projective closure 𝗣^1 x 𝗣^1 by setting x=X/Z,
|
|
|
|
|
|
//! y=Y/T. Clearing denominators gives the model
|
|
|
|
|
|
//!
|
|
|
|
|
|
//! -X²T² + Y²Z² = Z²T² + dX²Y². <span style="float: right">(2)<span>
|
|
|
|
|
|
//!
|
|
|
|
|
|
//! To map from 𝗣^1 x 𝗣^1, a product of two lines, to 𝗣^3, we use the
|
|
|
|
|
|
//! Segre embedding,
|
|
|
|
|
|
//!
|
|
|
|
|
|
//! σ : ((X:Z),(Y:T)) ↦ (XY:XT:ZY:ZT). <span style="float: right">(3)</span>
|
|
|
|
|
|
//!
|
|
|
|
|
|
//! Using coordinates (W₀:W₁:W₂:W₃) for 𝗣^3, the image of σ(𝗣^1 x 𝗣^1)
|
|
|
|
|
|
//! is the surface defined by W₀W₃=W₁W₂, and under σ, equation (2)
|
|
|
|
|
|
//! becomes
|
|
|
|
|
|
//!
|
|
|
|
|
|
//! -W₁² + W₂² = W₃² + dW₀². <span style="float: right">(4)</span>
|
|
|
|
|
|
//!
|
|
|
|
|
|
//! Up to variable naming, this is exactly the curve model introduced
|
|
|
|
|
|
//! in ["Twisted Edwards Curves
|
|
|
|
|
|
//! Revisited"](https://www.iacr.org/archive/asiacrypt2008/53500329/53500329.pdf)
|
|
|
|
|
|
//! by Hisil, Wong, Carter, and Dawson. We can map from 𝗣^3 to 𝗣² by
|
|
|
|
|
|
//! sending (W₀:W₁:W₂:W₃) to (W₁:W₂:W₃). Notice that
|
|
|
|
|
|
//!
|
|
|
|
|
|
//! W₁/W₃ = XT/ZT = X/Z = x <span style="float: right">(5)</span>
|
|
|
|
|
|
//!
|
|
|
|
|
|
//! W₂/W₃ = ZY/ZT = Y/T = y, <span style="float: right">(6)</span>
|
|
|
|
|
|
//!
|
|
|
|
|
|
//! so this is the same as if we had started with the affine model (1)
|
|
|
|
|
|
//! and passed to 𝗣^2 by setting `x = W₁/W₃`, `y = W₂/W₃`. Up to
|
|
|
|
|
|
//! variable naming, this is the projective representation introduced
|
|
|
|
|
|
//! in ["Twisted Edwards Curves"](https://eprint.iacr.org/2008/013).
|
|
|
|
|
|
//!
|
|
|
|
|
|
//! Following the implementation strategy in the ref10 reference
|
|
|
|
|
|
//! implementation for [Ed25519](https://ed25519.cr.yp.to/ed25519-20110926.pdf),
|
|
|
|
|
|
//! we use several different models for curve points:
|
|
|
|
|
|
//!
|
|
|
|
|
|
//! * `CompletedPoint`: points in 𝗣^1 x 𝗣^1;
|
|
|
|
|
|
//! * `ExtendedPoint`: points in 𝗣^3;
|
|
|
|
|
|
//! * `ProjectivePoint`: points in 𝗣^2.
|
|
|
|
|
|
//!
|
|
|
|
|
|
//! Finally, to accelerate additions, we use two cached point formats,
|
|
|
|
|
|
//! one for the affine model and one for the 𝗣^3 model:
|
|
|
|
|
|
//!
|
|
|
|
|
|
//! * `AffineNielsPoint`: `(y+x, y-x, 2dxy)`
|
|
|
|
|
|
//! * `ProjectiveNielsPoint`: `(Y+X, Y-X, Z, 2dXY)`
|
|
|
|
|
|
//!
|
|
|
|
|
|
//! [1]: https://moderncrypto.org/mail-archive/curves/2016/000807.html
|
|
|
|
|
|
|
|
|
|
|
|
#![allow(non_snake_case)]
|
|
|
|
|
|
|
|
|
|
|
|
use core::fmt::Debug;
|
|
|
|
|
|
use core::ops::{Add, Sub, Neg};
|
|
|
|
|
|
|
|
|
|
|
|
use constants;
|
|
|
|
|
|
|
|
|
|
|
|
use field::FieldElement;
|
|
|
|
|
|
use edwards::ExtendedPoint;
|
|
|
|
|
|
use subtle::ConditionallyAssignable;
|
|
|
|
|
|
use traits::ValidityCheck;
|
|
|
|
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------
|
|
|
|
|
|
// Internal point representations
|
|
|
|
|
|
// ------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
|
|
/// A `ProjectivePoint` is a point on the curve in 𝗣²(𝔽ₚ).
|
|
|
|
|
|
/// A point (x,y) in the affine model corresponds to (x:y:1).
|
|
|
|
|
|
#[derive(Copy, Clone)]
|
|
|
|
|
|
pub struct ProjectivePoint {
|
|
|
|
|
|
pub X: FieldElement,
|
|
|
|
|
|
pub Y: FieldElement,
|
|
|
|
|
|
pub Z: FieldElement,
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// A `CompletedPoint` is a point ((X:Z), (Y:T)) in 𝗣¹(𝔽ₚ)×𝗣¹(𝔽ₚ).
|
|
|
|
|
|
/// A point (x,y) in the affine model corresponds to ((x:1),(y:1)).
|
|
|
|
|
|
#[derive(Copy, Clone)]
|
|
|
|
|
|
#[allow(missing_docs)]
|
|
|
|
|
|
pub struct CompletedPoint {
|
|
|
|
|
|
pub X: FieldElement,
|
|
|
|
|
|
pub Y: FieldElement,
|
|
|
|
|
|
pub Z: FieldElement,
|
|
|
|
|
|
pub T: FieldElement,
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// A pre-computed point in the affine model for the curve, represented as
|
|
|
|
|
|
/// (y+x, y-x, 2dxy). These precomputations accelerate addition and
|
|
|
|
|
|
/// subtraction, and were introduced by Niels Duif in the ed25519 paper
|
|
|
|
|
|
/// ["High-Speed High-Security Signatures"](https://ed25519.cr.yp.to/ed25519-20110926.pdf).
|
|
|
|
|
|
// Safe to derive Eq because affine coordinates.
|
|
|
|
|
|
#[derive(Copy, Clone, Eq, PartialEq)]
|
|
|
|
|
|
#[allow(missing_docs)]
|
|
|
|
|
|
pub struct AffineNielsPoint {
|
|
|
|
|
|
pub y_plus_x: FieldElement,
|
|
|
|
|
|
pub y_minus_x: FieldElement,
|
|
|
|
|
|
pub xy2d: FieldElement,
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// A pre-computed point in the P³(𝔽ₚ) model for the curve, represented as
|
|
|
|
|
|
/// (Y+X, Y-X, Z, 2dXY). These precomputations accelerate addition and
|
|
|
|
|
|
/// subtraction, and were introduced by Niels Duif in the ed25519 paper
|
|
|
|
|
|
/// ["High-Speed High-Security Signatures"](https://ed25519.cr.yp.to/ed25519-20110926.pdf).
|
|
|
|
|
|
#[derive(Copy, Clone)]
|
|
|
|
|
|
pub struct ProjectiveNielsPoint {
|
|
|
|
|
|
pub Y_plus_X: FieldElement,
|
|
|
|
|
|
pub Y_minus_X: FieldElement,
|
|
|
|
|
|
pub Z: FieldElement,
|
|
|
|
|
|
pub T2d: FieldElement,
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------
|
|
|
|
|
|
// Constructors
|
|
|
|
|
|
// ------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
|
|
use traits::Identity;
|
|
|
|
|
|
|
|
|
|
|
|
impl Identity for ProjectivePoint {
|
|
|
|
|
|
fn identity() -> ProjectivePoint {
|
2017-11-17 22:09:48 +00:00
|
|
|
|
ProjectivePoint{
|
|
|
|
|
|
X: FieldElement::zero(),
|
|
|
|
|
|
Y: FieldElement::one(),
|
|
|
|
|
|
Z: FieldElement::one(),
|
|
|
|
|
|
}
|
2017-11-17 01:34:28 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
impl Identity for ProjectiveNielsPoint {
|
|
|
|
|
|
fn identity() -> ProjectiveNielsPoint {
|
2017-11-17 22:09:48 +00:00
|
|
|
|
ProjectiveNielsPoint{
|
|
|
|
|
|
Y_plus_X: FieldElement::one(),
|
|
|
|
|
|
Y_minus_X: FieldElement::one(),
|
|
|
|
|
|
Z: FieldElement::one(),
|
|
|
|
|
|
T2d: FieldElement::zero(),
|
|
|
|
|
|
}
|
2017-11-17 01:34:28 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
impl Identity for AffineNielsPoint {
|
|
|
|
|
|
fn identity() -> AffineNielsPoint {
|
|
|
|
|
|
AffineNielsPoint{
|
|
|
|
|
|
y_plus_x: FieldElement::one(),
|
|
|
|
|
|
y_minus_x: FieldElement::one(),
|
|
|
|
|
|
xy2d: FieldElement::zero(),
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------
|
|
|
|
|
|
// Validity checks (for debugging, not CT)
|
|
|
|
|
|
// ------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
|
|
impl ValidityCheck for ProjectivePoint {
|
|
|
|
|
|
fn is_valid(&self) -> bool {
|
|
|
|
|
|
// Curve equation is -x^2 + y^2 = 1 + d*x^2*y^2,
|
|
|
|
|
|
// homogenized as (-X^2 + Y^2)*Z^2 = Z^4 + d*X^2*Y^2
|
|
|
|
|
|
let XX = self.X.square();
|
|
|
|
|
|
let YY = self.Y.square();
|
|
|
|
|
|
let ZZ = self.Z.square();
|
|
|
|
|
|
let ZZZZ = ZZ.square();
|
|
|
|
|
|
let lhs = &(&YY - &XX) * &ZZ;
|
|
|
|
|
|
let rhs = &ZZZZ + &(&constants::EDWARDS_D * &(&XX * &YY));
|
|
|
|
|
|
|
|
|
|
|
|
lhs == rhs
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------
|
|
|
|
|
|
// Constant-time assignment
|
|
|
|
|
|
// ------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
|
|
impl ConditionallyAssignable for ProjectiveNielsPoint {
|
|
|
|
|
|
fn conditional_assign(&mut self, other: &ProjectiveNielsPoint, choice: u8) {
|
|
|
|
|
|
self.Y_plus_X.conditional_assign(&other.Y_plus_X, choice);
|
|
|
|
|
|
self.Y_minus_X.conditional_assign(&other.Y_minus_X, choice);
|
|
|
|
|
|
self.Z.conditional_assign(&other.Z, choice);
|
|
|
|
|
|
self.T2d.conditional_assign(&other.T2d, choice);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
impl ConditionallyAssignable for AffineNielsPoint {
|
|
|
|
|
|
fn conditional_assign(&mut self, other: &AffineNielsPoint, choice: u8) {
|
|
|
|
|
|
// PreComputedGroupElementCMove()
|
|
|
|
|
|
self.y_plus_x.conditional_assign(&other.y_plus_x, choice);
|
|
|
|
|
|
self.y_minus_x.conditional_assign(&other.y_minus_x, choice);
|
|
|
|
|
|
self.xy2d.conditional_assign(&other.xy2d, choice);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------
|
|
|
|
|
|
// Point conversions
|
|
|
|
|
|
// ------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
|
|
impl ProjectivePoint {
|
|
|
|
|
|
/// Convert to the extended twisted Edwards representation of this
|
|
|
|
|
|
/// point.
|
|
|
|
|
|
///
|
|
|
|
|
|
/// From §3 in [0]:
|
|
|
|
|
|
///
|
|
|
|
|
|
/// Given (X:Y:Z) in Ɛ, passing to Ɛₑ can be performed in 3M+1S by
|
|
|
|
|
|
/// computing (XZ,YZ,XY,Z²). (Note that in that paper, points are
|
|
|
|
|
|
/// (X:Y:T:Z) so this really does match the code below).
|
|
|
|
|
|
pub fn to_extended(&self) -> ExtendedPoint {
|
|
|
|
|
|
ExtendedPoint{
|
|
|
|
|
|
X: &self.X * &self.Z,
|
|
|
|
|
|
Y: &self.Y * &self.Z,
|
|
|
|
|
|
Z: self.Z.square(),
|
|
|
|
|
|
T: &self.X * &self.Y,
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
impl CompletedPoint {
|
|
|
|
|
|
/// Convert to a ProjectivePoint
|
|
|
|
|
|
pub fn to_projective(&self) -> ProjectivePoint {
|
|
|
|
|
|
ProjectivePoint{
|
|
|
|
|
|
X: &self.X * &self.T,
|
|
|
|
|
|
Y: &self.Y * &self.Z,
|
|
|
|
|
|
Z: &self.Z * &self.T,
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// Convert to an ExtendedPoint
|
|
|
|
|
|
pub fn to_extended(&self) -> ExtendedPoint {
|
|
|
|
|
|
ExtendedPoint{
|
|
|
|
|
|
X: &self.X * &self.T,
|
|
|
|
|
|
Y: &self.Y * &self.Z,
|
|
|
|
|
|
Z: &self.Z * &self.T,
|
|
|
|
|
|
T: &self.X * &self.Y,
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------
|
|
|
|
|
|
// Doubling
|
|
|
|
|
|
// ------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
|
|
impl ProjectivePoint {
|
|
|
|
|
|
/// Double this point: return self + self
|
|
|
|
|
|
pub fn double(&self) -> CompletedPoint { // Double()
|
|
|
|
|
|
let XX = self.X.square();
|
|
|
|
|
|
let YY = self.Y.square();
|
|
|
|
|
|
let ZZ2 = self.Z.square2();
|
|
|
|
|
|
let X_plus_Y = &self.X + &self.Y;
|
|
|
|
|
|
let X_plus_Y_sq = X_plus_Y.square();
|
|
|
|
|
|
let YY_plus_XX = &YY + &XX;
|
|
|
|
|
|
let YY_minus_XX = &YY - &XX;
|
|
|
|
|
|
|
|
|
|
|
|
CompletedPoint{
|
|
|
|
|
|
X: &X_plus_Y_sq - &YY_plus_XX,
|
|
|
|
|
|
Y: YY_plus_XX,
|
|
|
|
|
|
Z: YY_minus_XX,
|
|
|
|
|
|
T: &ZZ2 - &YY_minus_XX
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------
|
|
|
|
|
|
// Addition and Subtraction
|
|
|
|
|
|
// ------------------------------------------------------------------------
|
|
|
|
|
|
|
2017-11-17 23:42:37 +00:00
|
|
|
|
// These are doc(hidden) so they don't appear in the public API docs.
|
|
|
|
|
|
#[doc(hidden)]
|
2017-11-17 01:34:28 +00:00
|
|
|
|
impl<'a, 'b> Add<&'b ProjectiveNielsPoint> for &'a ExtendedPoint {
|
|
|
|
|
|
type Output = CompletedPoint;
|
|
|
|
|
|
|
|
|
|
|
|
fn add(self, other: &'b ProjectiveNielsPoint) -> CompletedPoint {
|
|
|
|
|
|
let Y_plus_X = &self.Y + &self.X;
|
|
|
|
|
|
let Y_minus_X = &self.Y - &self.X;
|
|
|
|
|
|
let PP = &Y_plus_X * &other.Y_plus_X;
|
|
|
|
|
|
let MM = &Y_minus_X * &other.Y_minus_X;
|
|
|
|
|
|
let TT2d = &self.T * &other.T2d;
|
|
|
|
|
|
let ZZ = &self.Z * &other.Z;
|
|
|
|
|
|
let ZZ2 = &ZZ + &ZZ;
|
|
|
|
|
|
|
|
|
|
|
|
CompletedPoint{
|
|
|
|
|
|
X: &PP - &MM,
|
|
|
|
|
|
Y: &PP + &MM,
|
|
|
|
|
|
Z: &ZZ2 + &TT2d,
|
|
|
|
|
|
T: &ZZ2 - &TT2d
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2017-11-17 23:42:37 +00:00
|
|
|
|
#[doc(hidden)]
|
2017-11-17 01:34:28 +00:00
|
|
|
|
impl<'a, 'b> Sub<&'b ProjectiveNielsPoint> for &'a ExtendedPoint {
|
|
|
|
|
|
type Output = CompletedPoint;
|
|
|
|
|
|
|
|
|
|
|
|
fn sub(self, other: &'b ProjectiveNielsPoint) -> CompletedPoint {
|
|
|
|
|
|
let Y_plus_X = &self.Y + &self.X;
|
|
|
|
|
|
let Y_minus_X = &self.Y - &self.X;
|
|
|
|
|
|
let PM = &Y_plus_X * &other.Y_minus_X;
|
|
|
|
|
|
let MP = &Y_minus_X * &other.Y_plus_X;
|
|
|
|
|
|
let TT2d = &self.T * &other.T2d;
|
|
|
|
|
|
let ZZ = &self.Z * &other.Z;
|
|
|
|
|
|
let ZZ2 = &ZZ + &ZZ;
|
|
|
|
|
|
|
|
|
|
|
|
CompletedPoint{
|
|
|
|
|
|
X: &PM - &MP,
|
|
|
|
|
|
Y: &PM + &MP,
|
|
|
|
|
|
Z: &ZZ2 - &TT2d,
|
|
|
|
|
|
T: &ZZ2 + &TT2d
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2017-11-17 23:42:37 +00:00
|
|
|
|
#[doc(hidden)]
|
2017-11-17 01:34:28 +00:00
|
|
|
|
impl<'a, 'b> Add<&'b AffineNielsPoint> for &'a ExtendedPoint {
|
|
|
|
|
|
type Output = CompletedPoint;
|
|
|
|
|
|
|
|
|
|
|
|
fn add(self, other: &'b AffineNielsPoint) -> CompletedPoint {
|
|
|
|
|
|
let Y_plus_X = &self.Y + &self.X;
|
|
|
|
|
|
let Y_minus_X = &self.Y - &self.X;
|
|
|
|
|
|
let PP = &Y_plus_X * &other.y_plus_x;
|
|
|
|
|
|
let MM = &Y_minus_X * &other.y_minus_x;
|
|
|
|
|
|
let Txy2d = &self.T * &other.xy2d;
|
|
|
|
|
|
let Z2 = &self.Z + &self.Z;
|
|
|
|
|
|
|
|
|
|
|
|
CompletedPoint{
|
|
|
|
|
|
X: &PP - &MM,
|
|
|
|
|
|
Y: &PP + &MM,
|
|
|
|
|
|
Z: &Z2 + &Txy2d,
|
|
|
|
|
|
T: &Z2 - &Txy2d
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2017-11-17 23:42:37 +00:00
|
|
|
|
#[doc(hidden)]
|
2017-11-17 01:34:28 +00:00
|
|
|
|
impl<'a, 'b> Sub<&'b AffineNielsPoint> for &'a ExtendedPoint {
|
|
|
|
|
|
type Output = CompletedPoint;
|
|
|
|
|
|
|
|
|
|
|
|
fn sub(self, other: &'b AffineNielsPoint) -> CompletedPoint {
|
|
|
|
|
|
let Y_plus_X = &self.Y + &self.X;
|
|
|
|
|
|
let Y_minus_X = &self.Y - &self.X;
|
|
|
|
|
|
let PM = &Y_plus_X * &other.y_minus_x;
|
|
|
|
|
|
let MP = &Y_minus_X * &other.y_plus_x;
|
|
|
|
|
|
let Txy2d = &self.T * &other.xy2d;
|
|
|
|
|
|
let Z2 = &self.Z + &self.Z;
|
|
|
|
|
|
|
|
|
|
|
|
CompletedPoint{
|
|
|
|
|
|
X: &PM - &MP,
|
|
|
|
|
|
Y: &PM + &MP,
|
|
|
|
|
|
Z: &Z2 - &Txy2d,
|
|
|
|
|
|
T: &Z2 + &Txy2d
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------
|
|
|
|
|
|
// Negation
|
|
|
|
|
|
// ------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
|
|
impl<'a> Neg for &'a ProjectiveNielsPoint {
|
|
|
|
|
|
type Output = ProjectiveNielsPoint;
|
|
|
|
|
|
|
|
|
|
|
|
fn neg(self) -> ProjectiveNielsPoint {
|
|
|
|
|
|
ProjectiveNielsPoint{
|
|
|
|
|
|
Y_plus_X: self.Y_minus_X,
|
|
|
|
|
|
Y_minus_X: self.Y_plus_X,
|
|
|
|
|
|
Z: self.Z,
|
|
|
|
|
|
T2d: -(&self.T2d),
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
impl<'a> Neg for &'a AffineNielsPoint {
|
|
|
|
|
|
type Output = AffineNielsPoint;
|
|
|
|
|
|
|
|
|
|
|
|
fn neg(self) -> AffineNielsPoint {
|
|
|
|
|
|
AffineNielsPoint{
|
|
|
|
|
|
y_plus_x: self.y_minus_x,
|
|
|
|
|
|
y_minus_x: self.y_plus_x,
|
|
|
|
|
|
xy2d: -(&self.xy2d)
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------
|
|
|
|
|
|
// Debug traits
|
|
|
|
|
|
// ------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
|
|
impl Debug for ProjectivePoint {
|
|
|
|
|
|
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
|
|
|
|
|
|
write!(f, "ProjectivePoint{{\n\tX: {:?},\n\tY: {:?},\n\tZ: {:?}\n}}",
|
|
|
|
|
|
&self.X, &self.Y, &self.Z)
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
impl Debug for CompletedPoint {
|
|
|
|
|
|
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
|
|
|
|
|
|
write!(f, "CompletedPoint{{\n\tX: {:?},\n\tY: {:?},\n\tZ: {:?},\n\tT: {:?}\n}}",
|
|
|
|
|
|
&self.X, &self.Y, &self.Z, &self.T)
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
impl Debug for AffineNielsPoint {
|
|
|
|
|
|
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
|
|
|
|
|
|
write!(f, "AffineNielsPoint{{\n\ty_plus_x: {:?},\n\ty_minus_x: {:?},\n\txy2d: {:?}\n}}",
|
|
|
|
|
|
&self.y_plus_x, &self.y_minus_x, &self.xy2d)
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
impl Debug for ProjectiveNielsPoint {
|
|
|
|
|
|
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
|
|
|
|
|
|
write!(f, "ProjectiveNielsPoint{{\n\tY_plus_X: {:?},\n\tY_minus_X: {:?},\n\tZ: {:?},\n\tT2d: {:?}\n}}",
|
|
|
|
|
|
&self.Y_plus_X, &self.Y_minus_X, &self.Z, &self.T2d)
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|