1use super::curve::Curve;
4use super::field::limbs_of;
5use super::group::Table;
6use crate::math::numbers::Number;
7use core::fmt;
8use core::hash::{Hash, Hasher};
9use core::ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign};
10
11pub struct Point<'c, C: Curve> {
43 curve: &'c C,
45 pub(super) limbs: Vec<u64>,
47}
48
49impl<'c, C: Curve> Point<'c, C> {
50 #[inline]
52 pub(super) fn from_limbs(curve: &'c C, limbs: Vec<u64>) -> Self {
53 Point { curve, limbs }
54 }
55
56 #[inline(always)]
58 pub(super) fn belongs_to(&self, curve: &C) -> bool {
59 core::ptr::eq(self.curve, curve) || self.curve.same_curve(curve)
60 }
61
62 #[inline(always)]
64 #[track_caller]
65 pub(super) fn check_curve(&self, curve: &C) {
66 if !self.belongs_to(curve) {
67 different_curves();
68 }
69 }
70
71 #[inline]
73 pub fn curve(&self) -> &'c C {
74 self.curve
75 }
76
77 pub fn is_identity(&self) -> bool {
79 self.curve.is_identity_limbs(&self.limbs)
80 }
81
82 pub fn coordinates(&self) -> Option<(Number, Number)> {
88 self.curve
89 .coordinates_limbs(&[&self.limbs])
90 .pop()
91 .unwrap_or(None)
92 }
93
94 pub fn coordinates_of(points: &[Point<'c, C>]) -> Vec<Option<(Number, Number)>> {
102 let Some(first) = points.first() else {
103 return Vec::new();
104 };
105 let stored: Vec<&[u64]> = points
106 .iter()
107 .map(|p| {
108 p.check_curve(first.curve);
109 &p.limbs[..]
110 })
111 .collect();
112 first.curve.coordinates_limbs(&stored)
113 }
114
115 pub fn double(&self) -> Self {
117 let mut r = self.clone();
118 self.curve.double_limbs(&mut r.limbs);
119 r
120 }
121
122 pub fn compress(&self) -> Vec<u8> {
127 let xy = self.coordinates();
128 self.curve.encode(xy.as_ref().map(|(x, y)| (x, y)), true)
129 }
130
131 pub fn to_bytes(&self) -> Vec<u8> {
135 let xy = self.coordinates();
136 self.curve.encode(xy.as_ref().map(|(x, y)| (x, y)), false)
137 }
138
139 pub fn prepare(&self, bits: usize) -> Prepared<'c, C> {
144 Prepared {
145 curve: self.curve,
146 table: self.curve.prepare_limbs(&self.limbs, bits),
147 point: self.limbs.clone(),
148 }
149 }
150}
151
152#[cold]
154#[inline(never)]
155#[track_caller]
156fn different_curves() -> ! {
157 panic!("the points are on different curves")
158}
159
160pub struct Prepared<'c, C: Curve> {
162 curve: &'c C,
164 table: Table,
166 point: Vec<u64>,
168}
169
170impl<'c, C: Curve> Prepared<'c, C> {
171 pub fn mul(&self, k: &Number) -> Point<'c, C> {
173 let scalar = limbs_of(k);
174 let mut limbs = self.point.clone();
175 if k.bits() as usize <= self.table.bits {
176 self.curve
177 .prepared_limbs(&mut limbs, &self.table, &scalar, k.is_negative());
178 } else {
179 self.curve.mul_limbs(&mut limbs, &scalar, k.is_negative());
180 }
181 Point::from_limbs(self.curve, limbs)
182 }
183}
184
185impl<C: Curve> Clone for Point<'_, C> {
186 fn clone(&self) -> Self {
187 Point {
188 curve: self.curve,
189 limbs: self.limbs.clone(),
190 }
191 }
192
193 fn clone_from(&mut self, source: &Self) {
194 self.curve = source.curve;
195 self.limbs.clone_from(&source.limbs);
196 }
197}
198
199impl<C: Curve> PartialEq for Point<'_, C> {
202 #[track_caller]
203 fn eq(&self, other: &Self) -> bool {
204 other.check_curve(self.curve);
205 self.curve.equal_limbs(&self.limbs, &other.limbs)
206 }
207}
208
209impl<C: Curve> Eq for Point<'_, C> {}
210
211impl<C: Curve> Hash for Point<'_, C> {
213 fn hash<H: Hasher>(&self, state: &mut H) {
214 self.coordinates().hash(state);
215 }
216}
217
218impl<C: Curve> fmt::Debug for Point<'_, C> {
219 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
220 fmt::Display::fmt(self, f)
221 }
222}
223
224impl<C: Curve> fmt::Display for Point<'_, C> {
226 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
227 match self.coordinates() {
228 Some((x, y)) => write!(f, "({x}, {y})"),
229 None => f.write_str("infinity"),
230 }
231 }
232}
233
234impl<'c, C: Curve> Neg for &Point<'c, C> {
235 type Output = Point<'c, C>;
236
237 fn neg(self) -> Point<'c, C> {
238 -self.clone()
239 }
240}
241
242impl<'c, C: Curve> Neg for Point<'c, C> {
243 type Output = Point<'c, C>;
244
245 fn neg(mut self) -> Point<'c, C> {
246 self.curve.neg_limbs(&mut self.limbs);
247 self
248 }
249}
250
251macro_rules! operators {
254 ($trait:ident, $method:ident, $assign:ident, $assign_method:ident, $limbs:ident) => {
255 impl<'c, C: Curve> $assign<&Point<'c, C>> for Point<'c, C> {
256 #[track_caller]
257 fn $assign_method(&mut self, rhs: &Point<'c, C>) {
258 rhs.check_curve(self.curve);
259 self.curve.$limbs(&mut self.limbs, &rhs.limbs);
260 }
261 }
262
263 impl<'c, C: Curve> $assign<Point<'c, C>> for Point<'c, C> {
264 #[track_caller]
265 fn $assign_method(&mut self, rhs: Point<'c, C>) {
266 self.$assign_method(&rhs);
267 }
268 }
269
270 impl<'c, C: Curve> $trait<&Point<'c, C>> for Point<'c, C> {
271 type Output = Point<'c, C>;
272
273 #[track_caller]
274 fn $method(mut self, rhs: &Point<'c, C>) -> Point<'c, C> {
275 self.$assign_method(rhs);
276 self
277 }
278 }
279
280 impl<'c, C: Curve> $trait<Point<'c, C>> for Point<'c, C> {
281 type Output = Point<'c, C>;
282
283 #[track_caller]
284 fn $method(self, rhs: Point<'c, C>) -> Point<'c, C> {
285 self.$method(&rhs)
286 }
287 }
288
289 impl<'c, C: Curve> $trait<&Point<'c, C>> for &Point<'c, C> {
290 type Output = Point<'c, C>;
291
292 #[track_caller]
293 fn $method(self, rhs: &Point<'c, C>) -> Point<'c, C> {
294 self.clone().$method(rhs)
295 }
296 }
297
298 impl<'c, C: Curve> $trait<Point<'c, C>> for &Point<'c, C> {
299 type Output = Point<'c, C>;
300
301 #[track_caller]
302 fn $method(self, rhs: Point<'c, C>) -> Point<'c, C> {
303 self.clone().$method(&rhs)
304 }
305 }
306 };
307}
308operators!(Add, add, AddAssign, add_assign, add_limbs);
309operators!(Sub, sub, SubAssign, sub_assign, sub_limbs);
310
311impl<C: Curve> MulAssign<&Number> for Point<'_, C> {
312 fn mul_assign(&mut self, k: &Number) {
313 self.curve
314 .mul_limbs(&mut self.limbs, &limbs_of(k), k.is_negative());
315 }
316}
317
318impl<C: Curve> MulAssign<Number> for Point<'_, C> {
319 fn mul_assign(&mut self, k: Number) {
320 *self *= &k;
321 }
322}
323
324impl<'c, C: Curve> Mul<&Number> for Point<'c, C> {
325 type Output = Point<'c, C>;
326
327 fn mul(mut self, k: &Number) -> Point<'c, C> {
328 self *= k;
329 self
330 }
331}
332
333impl<'c, C: Curve> Mul<Number> for Point<'c, C> {
334 type Output = Point<'c, C>;
335
336 fn mul(self, k: Number) -> Point<'c, C> {
337 self * &k
338 }
339}
340
341impl<'c, C: Curve> Mul<&Number> for &Point<'c, C> {
342 type Output = Point<'c, C>;
343
344 fn mul(self, k: &Number) -> Point<'c, C> {
345 self.clone() * k
346 }
347}
348
349impl<'c, C: Curve> Mul<Number> for &Point<'c, C> {
350 type Output = Point<'c, C>;
351
352 fn mul(self, k: Number) -> Point<'c, C> {
353 self.clone() * &k
354 }
355}
356
357impl<'c, C: Curve> Mul<&Point<'c, C>> for &Number {
358 type Output = Point<'c, C>;
359
360 fn mul(self, p: &Point<'c, C>) -> Point<'c, C> {
361 p * self
362 }
363}
364
365impl<'c, C: Curve> Mul<Point<'c, C>> for &Number {
366 type Output = Point<'c, C>;
367
368 fn mul(self, p: Point<'c, C>) -> Point<'c, C> {
369 p * self
370 }
371}
372
373impl<'c, C: Curve> Mul<&Point<'c, C>> for Number {
374 type Output = Point<'c, C>;
375
376 fn mul(self, p: &Point<'c, C>) -> Point<'c, C> {
377 p * &self
378 }
379}
380
381impl<'c, C: Curve> Mul<Point<'c, C>> for Number {
382 type Output = Point<'c, C>;
383
384 fn mul(self, p: Point<'c, C>) -> Point<'c, C> {
385 p * &self
386 }
387}