1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
//! Exposes information about point coordinates
//!
//! `Curve` by default does not require that points expose their coordinates.
//! Some curves implementations intentionally don't expose points coordinates,
//! and, generally, most of the EC algorithms don't need them. Each curve
//! implementation may optionally expose affine coordinates by implementing
//! trait from this module.
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};

use crate::Curve;

/// A point that has affine x coordinate
pub trait HasAffineX: Curve {
    /// Returns point affine x coordinate
    ///
    /// Returns `None` if it's point at infinity
    fn x(point: &Self::Point) -> Option<Self::CoordinateArray>;
}

/// A point that has affine x coordinate and parity of y coordinate
pub trait HasAffineXAndParity: Curve + HasAffineX {
    /// Returns point x coordinate and parity of y coordinate
    ///
    /// Returns `None` if it's point at infinity
    fn x_and_parity(point: &Self::Point) -> Option<(Self::CoordinateArray, Parity)>;
    /// Construct a point from x coordinate and parity of y coordinate
    ///
    /// Returns `None` if input does not correspond to a valid point (but you
    /// still need to check that the point is [on curve](super::OnCurve) and
    /// has [no small component](super::SmallFactor))
    fn from_x_and_parity(x: &Self::CoordinateArray, y_parity: Parity) -> Option<Self::Point>;
}

/// A point that has affine y coordinate
pub trait HasAffineY: Curve {
    /// Returns point affine y coordinate
    ///
    /// Returns `None` if it's point at infinity
    fn y(point: &Self::Point) -> Option<Self::CoordinateArray>;
}

/// A point that has affine x and y coordinates
pub trait HasAffineXY: Curve + HasAffineX + HasAffineY {
    /// Returns point affine x and y coordinates
    ///
    /// Returns `None` if it's point at infinity
    fn x_and_y(point: &Self::Point) -> Option<(Self::CoordinateArray, Self::CoordinateArray)>;
    /// Construct a point from x and y coordinates
    ///
    /// Returns `None` if input does not correspond to a valid point (but you
    /// still need to check that the point is [on curve](super::OnCurve) and
    /// has [no small component](super::SmallFactor))
    fn from_x_and_y(x: &Self::CoordinateArray, y: &Self::CoordinateArray) -> Option<Self::Point>;
}

/// A point that always has affine y coordinate
pub trait AlwaysHasAffineY: Curve {
    /// Returns point affine y coordinate
    fn y(point: &Self::Point) -> Self::CoordinateArray;
}

/// A point that always has affine y coordinate and sign of x coordinate
pub trait AlwaysHasAffineYAndSign: Curve + AlwaysHasAffineY {
    /// Returns y coordinate and sign of x coordinate
    fn y_and_sign(point: &Self::Point) -> (Sign, Self::CoordinateArray);
    /// Constructs a point from y coordinate and sign of x coordinate
    ///
    /// Returns `None` if input does not correspond to a valid point (but you
    /// still need to check that the point is [on curve](super::OnCurve) and
    /// has [no small component](super::SmallFactor))
    fn from_y_and_sign(x_sign: Sign, y: &Self::CoordinateArray) -> Option<Self::Point>;
}

/// Sign of coordinate
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[repr(u8)]
pub enum Sign {
    /// Coordinate has negative sign
    Negative = 0,
    /// Coordinate has non-negative sign
    NonNegative = 1,
}

impl Sign {
    /// Checks whether coordinate is negative
    pub fn is_negative(&self) -> bool {
        *self == Self::Negative
    }
}

/// Parity of coordinate
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[repr(u8)]
pub enum Parity {
    /// Coordinate is odd
    Odd = 0,
    /// Coordinate is even
    Even = 1,
}

impl Parity {
    /// Checks whether coordinate is odd
    pub fn is_odd(&self) -> bool {
        *self == Self::Odd
    }

    /// Checks whether coordinate is even
    pub fn is_even(&self) -> bool {
        *self == Self::Even
    }
}