1#![allow(clippy::needless_range_loop, clippy::op_ref)]
4
5use crate::{
6 AffinePoint, ArraySize, Field, LookupTable, MulBackend, PrimeCurveParams, Radix16Decomposition,
7 Radix16Digits, point_arithmetic::PointArithmetic,
8};
9use core::{array, borrow::Borrow, iter::Sum, iter::zip};
10use elliptic_curve::{
11 BatchNormalize, CurveGroup, Error, Generate, PublicKey, Result, Scalar,
12 array::{sizes::U5, typenum::Unsigned},
13 ctutils,
14 group::{
15 Group, GroupEncoding,
16 cofactor::CofactorGroup,
17 prime::{PrimeCurve, PrimeGroup},
18 },
19 ops::{
20 Add, AddAssign, BatchInvert, Double, LinearCombination, Mul, MulAssign,
21 MulByGeneratorVartime, MulVartime, Neg, Sub, SubAssign,
22 },
23 point::NonIdentity,
24 rand_core::{TryCryptoRng, TryRng},
25 sec1::{CompressedPoint, FromSec1Point, Sec1Point, ToSec1Point},
26 subtle::{Choice, ConditionallySelectable, ConstantTimeEq, CtOption},
27 zeroize::DefaultIsZeroes,
28};
29use wnaf::WnafGroup;
30
31use crate::array::Array;
32#[cfg(feature = "alloc")]
33use alloc::vec::Vec;
34#[cfg(feature = "serde")]
35use serdect::serde::{Deserialize, Serialize, de, ser};
36
37type DefaultWnafWindowSize = U5;
40
41pub(crate) type WnafBase<C> = wnaf::WnafBase<ProjectivePoint<C>, DefaultWnafWindowSize>;
43
44pub(crate) type WnafScalar<C> = wnaf::WnafScalar<Scalar<C>, DefaultWnafWindowSize>;
46
47#[derive(Clone, Copy, Debug)]
49pub struct ProjectivePoint<C: PrimeCurveParams> {
50 pub(crate) x: C::FieldElement,
51 pub(crate) y: C::FieldElement,
52 pub(crate) z: C::FieldElement,
53}
54
55impl<C> ProjectivePoint<C>
56where
57 C: PrimeCurveParams,
58{
59 pub const IDENTITY: Self = Self {
61 x: C::FieldElement::ZERO,
62 y: C::FieldElement::ONE,
63 z: C::FieldElement::ZERO,
64 };
65
66 pub const GENERATOR: Self = Self {
68 x: C::GENERATOR.0,
69 y: C::GENERATOR.1,
70 z: C::FieldElement::ONE,
71 };
72
73 pub fn to_affine(&self) -> AffinePoint<C> {
75 <C::FieldElement as Field>::invert(&self.z)
76 .map(|zinv| self.to_affine_internal(zinv))
77 .unwrap_or(AffinePoint::IDENTITY)
78 }
79
80 pub(super) fn to_affine_internal(self, zinv: C::FieldElement) -> AffinePoint<C> {
81 AffinePoint {
82 x: self.x * &zinv,
83 y: self.y * &zinv,
84 infinity: 0,
85 }
86 }
87
88 #[must_use]
90 pub fn neg(&self) -> Self {
91 Self {
92 x: self.x,
93 y: -self.y,
94 z: self.z,
95 }
96 }
97
98 #[inline]
100 #[must_use]
101 pub fn add(&self, other: &Self) -> Self {
102 let mut lhs = *self;
103 C::PointArithmetic::add_assign(&mut lhs, other);
104 lhs
105 }
106
107 #[inline]
109 #[must_use]
110 fn add_mixed(&self, other: &AffinePoint<C>) -> Self {
111 let mut lhs = *self;
112 C::PointArithmetic::add_assign_mixed(&mut lhs, other);
113 lhs
114 }
115
116 #[inline]
118 #[must_use]
119 pub fn sub(&self, other: &Self) -> Self {
120 self.add(&other.neg())
121 }
122
123 #[inline]
125 #[must_use]
126 fn sub_mixed(&self, other: &AffinePoint<C>) -> Self {
127 self.add_mixed(&-other)
128 }
129
130 #[inline]
132 #[must_use]
133 pub fn mul(&self, k: &Scalar<C>) -> Self {
134 let table = LookupTable::new(*self);
135 let digits = Radix16Decomposition::new(k);
136 lincomb::<C>(&[table], &[digits])
137 }
138
139 #[inline]
141 #[must_use]
142 pub fn mul_vartime(&self, k: &Scalar<C>) -> Self {
143 WnafBase::<C>::new(self) * WnafScalar::<C>::new(k)
144 }
145}
146
147impl<C> ConditionallySelectable for ProjectivePoint<C>
148where
149 C: PrimeCurveParams,
150{
151 #[inline(always)]
152 fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self {
153 Self {
154 x: C::FieldElement::conditional_select(&a.x, &b.x, choice),
155 y: C::FieldElement::conditional_select(&a.y, &b.y, choice),
156 z: C::FieldElement::conditional_select(&a.z, &b.z, choice),
157 }
158 }
159}
160
161impl<C> ConstantTimeEq for ProjectivePoint<C>
162where
163 C: PrimeCurveParams,
164{
165 fn ct_eq(&self, other: &Self) -> Choice {
166 let x_eq = (self.x * other.z).ct_eq(&(other.x * self.z));
167 let y_eq = (self.y * other.z).ct_eq(&(other.y * self.z));
168
169 x_eq & y_eq
170 }
171}
172
173impl<C> ctutils::CtEq for ProjectivePoint<C>
174where
175 C: PrimeCurveParams,
176{
177 fn ct_eq(&self, other: &Self) -> ctutils::Choice {
178 ConstantTimeEq::ct_eq(self, other).into()
179 }
180}
181
182impl<C> ctutils::CtSelect for ProjectivePoint<C>
183where
184 C: PrimeCurveParams,
185{
186 fn ct_select(&self, other: &Self, choice: ctutils::Choice) -> Self {
187 ConditionallySelectable::conditional_select(self, other, choice.into())
188 }
189}
190
191impl<C> Default for ProjectivePoint<C>
192where
193 C: PrimeCurveParams,
194{
195 fn default() -> Self {
196 Self::IDENTITY
197 }
198}
199
200impl<C> DefaultIsZeroes for ProjectivePoint<C> where C: PrimeCurveParams {}
201
202impl<C: PrimeCurveParams> Double for ProjectivePoint<C> {
203 #[inline]
204 fn double(&self) -> Self {
205 let mut ret = *self;
206 C::PointArithmetic::double_in_place(&mut ret);
207 ret
208 }
209
210 #[inline]
211 fn double_in_place(&mut self) {
212 C::PointArithmetic::double_in_place(self);
213 }
214}
215
216impl<C> Eq for ProjectivePoint<C> where C: PrimeCurveParams {}
217
218impl<C> From<AffinePoint<C>> for ProjectivePoint<C>
219where
220 C: PrimeCurveParams,
221{
222 fn from(p: AffinePoint<C>) -> Self {
223 let projective = ProjectivePoint {
224 x: p.x,
225 y: p.y,
226 z: C::FieldElement::ONE,
227 };
228 Self::conditional_select(&projective, &Self::IDENTITY, p.is_identity())
229 }
230}
231
232impl<C> From<&AffinePoint<C>> for ProjectivePoint<C>
233where
234 C: PrimeCurveParams,
235{
236 fn from(p: &AffinePoint<C>) -> Self {
237 Self::from(*p)
238 }
239}
240
241impl<C> From<NonIdentity<ProjectivePoint<C>>> for ProjectivePoint<C>
242where
243 C: PrimeCurveParams,
244{
245 fn from(p: NonIdentity<ProjectivePoint<C>>) -> Self {
246 p.to_point()
247 }
248}
249
250impl<C> From<PublicKey<C>> for ProjectivePoint<C>
251where
252 C: PrimeCurveParams,
253{
254 fn from(public_key: PublicKey<C>) -> ProjectivePoint<C> {
255 AffinePoint::from(public_key).into()
256 }
257}
258
259impl<C> From<&PublicKey<C>> for ProjectivePoint<C>
260where
261 C: PrimeCurveParams,
262{
263 fn from(public_key: &PublicKey<C>) -> ProjectivePoint<C> {
264 AffinePoint::<C>::from(public_key).into()
265 }
266}
267
268impl<C> FromSec1Point<C> for ProjectivePoint<C>
269where
270 C: PrimeCurveParams,
271{
272 fn from_sec1_point(p: &Sec1Point<C>) -> ctutils::CtOption<Self> {
273 AffinePoint::<C>::from_sec1_point(p).map(Self::from)
274 }
275}
276
277impl<C> Generate for ProjectivePoint<C>
278where
279 C: PrimeCurveParams,
280{
281 fn try_generate_from_rng<R: TryCryptoRng + ?Sized>(
282 rng: &mut R,
283 ) -> core::result::Result<Self, R::Error> {
284 AffinePoint::try_generate_from_rng(rng).map(Self::from)
285 }
286}
287
288impl<C> CofactorGroup for ProjectivePoint<C>
294where
295 C: PrimeCurveParams,
296{
297 type Subgroup = ProjectivePoint<C>;
298
299 fn clear_cofactor(&self) -> Self::Subgroup {
300 *self
301 }
302
303 fn into_subgroup(self) -> CtOption<Self::Subgroup> {
304 CtOption::new(self, Choice::from(1))
305 }
306
307 fn is_torsion_free(&self) -> Choice {
308 Choice::from(1)
309 }
310}
311
312impl<C> CurveGroup for ProjectivePoint<C>
313where
314 C: PrimeCurveParams,
315{
316 type Affine = AffinePoint<C>;
317
318 fn to_affine(&self) -> AffinePoint<C> {
319 ProjectivePoint::to_affine(self)
320 }
321
322 #[cfg(feature = "alloc")]
323 #[inline]
324 fn batch_normalize(projective: &[Self], affine: &mut [Self::Affine]) {
325 assert_eq!(projective.len(), affine.len());
326 let mut zs = vec![C::FieldElement::ZERO; projective.len()];
327 let mut scratch = vec![C::FieldElement::ZERO; projective.len()];
328 batch_normalize_generic(projective, &mut zs, &mut scratch, affine);
329 }
330}
331
332impl<C> Group for ProjectivePoint<C>
333where
334 C: PrimeCurveParams,
335{
336 type Scalar = Scalar<C>;
337
338 fn try_random<R: TryRng + ?Sized>(rng: &mut R) -> core::result::Result<Self, R::Error> {
339 AffinePoint::try_random(rng).map(Self::from)
340 }
341
342 fn identity() -> Self {
343 Self::IDENTITY
344 }
345
346 fn generator() -> Self {
347 Self::GENERATOR
348 }
349
350 fn is_identity(&self) -> Choice {
351 self.ct_eq(&Self::IDENTITY)
352 }
353
354 #[inline]
355 fn double(&self) -> Self {
356 Double::double(self)
357 }
358
359 #[inline]
360 fn mul_by_generator(scalar: &Self::Scalar) -> Self {
361 C::Backend::mul_by_generator(scalar)
362 }
363}
364
365impl<C> GroupEncoding for ProjectivePoint<C>
366where
367 C: PrimeCurveParams,
368{
369 type Repr = CompressedPoint<C>;
370
371 fn from_bytes(bytes: &Self::Repr) -> CtOption<Self> {
372 <AffinePoint<C> as GroupEncoding>::from_bytes(bytes).map(Into::into)
373 }
374
375 fn from_bytes_unchecked(bytes: &Self::Repr) -> CtOption<Self> {
376 Self::from_bytes(bytes)
378 }
379
380 fn to_bytes(&self) -> Self::Repr {
381 self.to_affine().to_bytes()
382 }
383}
384
385impl<C> PrimeCurve for ProjectivePoint<C> where C: PrimeCurveParams {}
386impl<C> PrimeGroup for ProjectivePoint<C> where C: PrimeCurveParams {}
387
388impl<C> WnafGroup for ProjectivePoint<C>
389where
390 C: PrimeCurveParams,
391{
392 fn recommended_wnaf_for_num_scalars(_num_scalars: usize) -> usize {
393 5 }
395}
396
397impl<const N: usize, C> BatchNormalize<[ProjectivePoint<C>; N]> for ProjectivePoint<C>
402where
403 C: PrimeCurveParams,
404{
405 type Output = [<Self as CurveGroup>::Affine; N];
406
407 #[inline]
408 fn batch_normalize(points: &[Self; N]) -> [<Self as CurveGroup>::Affine; N] {
409 let mut zs = [C::FieldElement::ZERO; N];
410 let mut scratch = [C::FieldElement::ZERO; N];
411 let mut affine_points = [C::AffinePoint::IDENTITY; N];
412 batch_normalize_generic(points, &mut zs, &mut scratch, &mut affine_points);
413 affine_points
414 }
415}
416
417impl<C, U> BatchNormalize<Array<ProjectivePoint<C>, U>> for ProjectivePoint<C>
418where
419 C: PrimeCurveParams,
420 U: ArraySize,
421{
422 type Output = Array<AffinePoint<C>, U>;
423
424 #[inline]
425 fn batch_normalize(points: &Array<Self, U>) -> Array<AffinePoint<C>, U> {
426 let mut zs = Array::<C::FieldElement, U>::default();
427 let mut scratch = Array::<C::FieldElement, U>::default();
428 let mut affine_points = Array::<AffinePoint<C>, U>::default();
429 batch_normalize_generic(points, &mut zs, &mut scratch, &mut affine_points);
430 affine_points
431 }
432}
433
434#[cfg(feature = "alloc")]
435impl<C> BatchNormalize<[ProjectivePoint<C>]> for ProjectivePoint<C>
436where
437 C: PrimeCurveParams,
438{
439 type Output = Vec<<Self as CurveGroup>::Affine>;
440
441 #[inline]
442 fn batch_normalize(points: &[Self]) -> Vec<<Self as CurveGroup>::Affine> {
443 let mut zs = vec![C::FieldElement::ZERO; points.len()];
444 let mut scratch = vec![C::FieldElement::ZERO; points.len()];
445 let mut affine_points = vec![AffinePoint::IDENTITY; points.len()];
446 batch_normalize_generic(points, &mut zs, &mut scratch, &mut affine_points);
447 affine_points
448 }
449}
450
451fn batch_normalize_generic<C>(
453 points: &[ProjectivePoint<C>],
454 zs: &mut [C::FieldElement],
455 scratch: &mut [C::FieldElement],
456 out: &mut [AffinePoint<C>],
457) where
458 C: PrimeCurveParams,
459{
460 debug_assert_eq!(points.len(), zs.len());
461 debug_assert_eq!(points.len(), scratch.len());
462 debug_assert_eq!(points.len(), out.len());
463
464 for (z, point) in zs.iter_mut().zip(points) {
465 *z = point.z;
466 }
467
468 let _ = C::FieldElement::batch_invert_in_place(zs, scratch);
470
471 for i in 0..out.len() {
472 out[i] = C::AffinePoint::conditional_select(
473 &points[i].to_affine_internal(zs[i]),
474 &C::AffinePoint::IDENTITY,
475 points[i].z.ct_eq(&C::FieldElement::ZERO),
476 );
477 }
478}
479
480impl<C> LinearCombination<[(Self, Scalar<C>)]> for ProjectivePoint<C>
481where
482 C: PrimeCurveParams,
483{
484 #[cfg(feature = "alloc")]
485 fn lincomb(points_and_scalars: &[(Self, Scalar<C>)]) -> Self {
486 let tables: Vec<_> = points_and_scalars
487 .iter()
488 .map(|(point, _)| LookupTable::new(*point))
489 .collect();
490 let digits: Vec<_> = points_and_scalars
491 .iter()
492 .map(|(_, scalar)| Radix16Decomposition::new(scalar))
493 .collect();
494
495 lincomb::<C>(&tables, &digits)
496 }
497
498 #[cfg(feature = "alloc")]
499 fn lincomb_vartime(points_and_scalars: &[(Self, Scalar<C>)]) -> Self {
500 let bases: Vec<_> = points_and_scalars
501 .iter()
502 .map(|(point, _)| WnafBase::<C>::new(point))
503 .collect();
504 let scalars: Vec<_> = points_and_scalars
505 .iter()
506 .map(|(_, scalar)| WnafScalar::<C>::new(scalar))
507 .collect();
508
509 WnafBase::multiscalar_mul(bases.iter().zip(scalars.iter()))
510 }
511}
512
513impl<C, const N: usize> LinearCombination<[(Self, Scalar<C>); N]> for ProjectivePoint<C>
514where
515 C: PrimeCurveParams,
516{
517 fn lincomb(points_and_scalars: &[(Self, Scalar<C>); N]) -> Self {
518 let tables: [_; N] = array::from_fn(|index| LookupTable::new(points_and_scalars[index].0));
519 let digits: [_; N] =
520 array::from_fn(|index| Radix16Decomposition::new(&points_and_scalars[index].1));
521
522 lincomb::<C>(&tables, &digits)
523 }
524
525 fn lincomb_vartime(points_and_scalars: &[(Self, Scalar<C>); N]) -> Self {
526 let bases = points_and_scalars.map(|(point, _)| WnafBase::<C>::new(&point));
527 let scalars = points_and_scalars.map(|(_, scalar)| WnafScalar::<C>::new(&scalar));
528 WnafBase::multiscalar_mul(bases.iter().zip(scalars.iter()))
529 }
530}
531
532fn lincomb<C: PrimeCurveParams>(
533 tables: &[LookupTable<ProjectivePoint<C>>],
534 digits: &[Radix16Decomposition<Radix16Digits<C>>],
535) -> ProjectivePoint<C> {
536 debug_assert_eq!(tables.len(), digits.len());
537 debug_assert!(!digits.is_empty());
538
539 let d = Radix16Digits::<C>::USIZE;
540 let mut q = ProjectivePoint::IDENTITY;
541
542 for (table, digit) in zip(tables, digits) {
543 q = q.add(&table.select(digit[d - 1]));
544 }
545
546 for i in (0..d - 1).rev() {
547 for _ in 0..4 {
548 q.double_in_place();
549 }
550
551 for (table, digit) in zip(tables, digits) {
552 q = q.add(&table.select(digit[i]));
553 }
554 }
555
556 q
557}
558
559impl<C> PartialEq for ProjectivePoint<C>
560where
561 C: PrimeCurveParams,
562{
563 fn eq(&self, other: &Self) -> bool {
564 self.ct_eq(other).into()
565 }
566}
567
568impl<C> ToSec1Point<C> for ProjectivePoint<C>
569where
570 C: PrimeCurveParams,
571{
572 fn to_sec1_point(&self, compress: bool) -> Sec1Point<C> {
573 self.to_affine().to_sec1_point(compress)
574 }
575}
576
577impl<C> TryFrom<ProjectivePoint<C>> for NonIdentity<ProjectivePoint<C>>
579where
580 C: PrimeCurveParams,
581{
582 type Error = Error;
583
584 fn try_from(point: ProjectivePoint<C>) -> Result<Self> {
585 NonIdentity::new(point).into_option().ok_or(Error)
586 }
587}
588
589impl<C> TryFrom<ProjectivePoint<C>> for PublicKey<C>
590where
591 C: PrimeCurveParams,
592{
593 type Error = Error;
594
595 fn try_from(point: ProjectivePoint<C>) -> Result<PublicKey<C>> {
596 PublicKey::try_from(&point)
597 }
598}
599
600impl<C> TryFrom<&ProjectivePoint<C>> for PublicKey<C>
601where
602 C: PrimeCurveParams,
603{
604 type Error = Error;
605
606 fn try_from(point: &ProjectivePoint<C>) -> Result<PublicKey<C>> {
607 AffinePoint::<C>::from(point).try_into()
608 }
609}
610
611impl<C> Add<ProjectivePoint<C>> for ProjectivePoint<C>
616where
617 C: PrimeCurveParams,
618{
619 type Output = ProjectivePoint<C>;
620
621 fn add(self, other: ProjectivePoint<C>) -> ProjectivePoint<C> {
622 ProjectivePoint::add(&self, &other)
623 }
624}
625
626impl<C> Add<&ProjectivePoint<C>> for &ProjectivePoint<C>
627where
628 C: PrimeCurveParams,
629{
630 type Output = ProjectivePoint<C>;
631
632 fn add(self, other: &ProjectivePoint<C>) -> ProjectivePoint<C> {
633 ProjectivePoint::add(self, other)
634 }
635}
636
637impl<C> Add<&ProjectivePoint<C>> for ProjectivePoint<C>
638where
639 C: PrimeCurveParams,
640{
641 type Output = ProjectivePoint<C>;
642
643 fn add(self, other: &ProjectivePoint<C>) -> ProjectivePoint<C> {
644 ProjectivePoint::add(&self, other)
645 }
646}
647
648impl<C> AddAssign<ProjectivePoint<C>> for ProjectivePoint<C>
649where
650 C: PrimeCurveParams,
651{
652 #[inline]
653 fn add_assign(&mut self, rhs: ProjectivePoint<C>) {
654 C::PointArithmetic::add_assign(self, &rhs);
655 }
656}
657
658impl<C> AddAssign<&ProjectivePoint<C>> for ProjectivePoint<C>
659where
660 C: PrimeCurveParams,
661{
662 #[inline]
663 fn add_assign(&mut self, rhs: &ProjectivePoint<C>) {
664 C::PointArithmetic::add_assign(self, rhs);
665 }
666}
667
668impl<C> Add<AffinePoint<C>> for ProjectivePoint<C>
669where
670 C: PrimeCurveParams,
671{
672 type Output = ProjectivePoint<C>;
673
674 fn add(self, other: AffinePoint<C>) -> ProjectivePoint<C> {
675 ProjectivePoint::add_mixed(&self, &other)
676 }
677}
678
679impl<C> Add<&AffinePoint<C>> for &ProjectivePoint<C>
680where
681 C: PrimeCurveParams,
682{
683 type Output = ProjectivePoint<C>;
684
685 fn add(self, other: &AffinePoint<C>) -> ProjectivePoint<C> {
686 ProjectivePoint::add_mixed(self, other)
687 }
688}
689
690impl<C> Add<&AffinePoint<C>> for ProjectivePoint<C>
691where
692 C: PrimeCurveParams,
693{
694 type Output = ProjectivePoint<C>;
695
696 fn add(self, other: &AffinePoint<C>) -> ProjectivePoint<C> {
697 ProjectivePoint::add_mixed(&self, other)
698 }
699}
700
701impl<C> AddAssign<AffinePoint<C>> for ProjectivePoint<C>
702where
703 C: PrimeCurveParams,
704{
705 #[inline]
706 fn add_assign(&mut self, rhs: AffinePoint<C>) {
707 C::PointArithmetic::add_assign_mixed(self, &rhs);
708 }
709}
710
711impl<C> AddAssign<&AffinePoint<C>> for ProjectivePoint<C>
712where
713 C: PrimeCurveParams,
714{
715 #[inline]
716 fn add_assign(&mut self, rhs: &AffinePoint<C>) {
717 C::PointArithmetic::add_assign_mixed(self, rhs);
718 }
719}
720
721impl<C> Sum for ProjectivePoint<C>
722where
723 C: PrimeCurveParams,
724{
725 #[inline]
726 fn sum<I: Iterator<Item = Self>>(iter: I) -> Self {
727 iter.fold(ProjectivePoint::IDENTITY, |a, b| a + b)
728 }
729}
730
731impl<'a, C> Sum<&'a ProjectivePoint<C>> for ProjectivePoint<C>
732where
733 C: PrimeCurveParams,
734{
735 #[inline]
736 fn sum<I: Iterator<Item = &'a ProjectivePoint<C>>>(iter: I) -> Self {
737 iter.cloned().sum()
738 }
739}
740
741impl<C> Sub<ProjectivePoint<C>> for ProjectivePoint<C>
742where
743 C: PrimeCurveParams,
744{
745 type Output = ProjectivePoint<C>;
746
747 fn sub(self, other: ProjectivePoint<C>) -> ProjectivePoint<C> {
748 ProjectivePoint::sub(&self, &other)
749 }
750}
751
752impl<C> Sub<&ProjectivePoint<C>> for &ProjectivePoint<C>
753where
754 C: PrimeCurveParams,
755{
756 type Output = ProjectivePoint<C>;
757
758 fn sub(self, other: &ProjectivePoint<C>) -> ProjectivePoint<C> {
759 ProjectivePoint::sub(self, other)
760 }
761}
762
763impl<C> Sub<&ProjectivePoint<C>> for ProjectivePoint<C>
764where
765 C: PrimeCurveParams,
766{
767 type Output = ProjectivePoint<C>;
768
769 fn sub(self, other: &ProjectivePoint<C>) -> ProjectivePoint<C> {
770 ProjectivePoint::sub(&self, other)
771 }
772}
773
774impl<C> SubAssign<ProjectivePoint<C>> for ProjectivePoint<C>
775where
776 C: PrimeCurveParams,
777{
778 #[inline]
779 fn sub_assign(&mut self, rhs: ProjectivePoint<C>) {
780 C::PointArithmetic::add_assign(self, &-rhs);
781 }
782}
783
784impl<C> SubAssign<&ProjectivePoint<C>> for ProjectivePoint<C>
785where
786 C: PrimeCurveParams,
787{
788 #[inline]
789 fn sub_assign(&mut self, rhs: &ProjectivePoint<C>) {
790 *self -= *rhs;
791 }
792}
793
794impl<C> Sub<AffinePoint<C>> for ProjectivePoint<C>
795where
796 C: PrimeCurveParams,
797{
798 type Output = ProjectivePoint<C>;
799
800 fn sub(self, other: AffinePoint<C>) -> ProjectivePoint<C> {
801 ProjectivePoint::sub_mixed(&self, &other)
802 }
803}
804
805impl<C> Sub<&AffinePoint<C>> for &ProjectivePoint<C>
806where
807 C: PrimeCurveParams,
808{
809 type Output = ProjectivePoint<C>;
810
811 fn sub(self, other: &AffinePoint<C>) -> ProjectivePoint<C> {
812 ProjectivePoint::sub_mixed(self, other)
813 }
814}
815
816impl<C> Sub<&AffinePoint<C>> for ProjectivePoint<C>
817where
818 C: PrimeCurveParams,
819{
820 type Output = ProjectivePoint<C>;
821
822 fn sub(self, other: &AffinePoint<C>) -> ProjectivePoint<C> {
823 ProjectivePoint::sub_mixed(&self, other)
824 }
825}
826
827impl<C> SubAssign<AffinePoint<C>> for ProjectivePoint<C>
828where
829 C: PrimeCurveParams,
830{
831 #[inline]
832 fn sub_assign(&mut self, rhs: AffinePoint<C>) {
833 C::PointArithmetic::add_assign_mixed(self, &-rhs);
834 }
835}
836
837impl<C> SubAssign<&AffinePoint<C>> for ProjectivePoint<C>
838where
839 C: PrimeCurveParams,
840{
841 #[inline]
842 fn sub_assign(&mut self, rhs: &AffinePoint<C>) {
843 *self -= *rhs;
844 }
845}
846
847impl<C, S> Mul<S> for ProjectivePoint<C>
848where
849 Self: Double,
850 C: PrimeCurveParams,
851 S: Borrow<Scalar<C>>,
852{
853 type Output = Self;
854
855 #[inline]
856 fn mul(self, scalar: S) -> Self {
857 ProjectivePoint::mul(&self, scalar.borrow())
858 }
859}
860
861impl<C, S> Mul<S> for &ProjectivePoint<C>
862where
863 Self: Double,
864 C: PrimeCurveParams,
865 S: Borrow<Scalar<C>>,
866{
867 type Output = ProjectivePoint<C>;
868
869 #[inline]
870 fn mul(self, scalar: S) -> ProjectivePoint<C> {
871 ProjectivePoint::mul(self, scalar.borrow())
872 }
873}
874
875impl<C> Mul<&Scalar<C>> for &ProjectivePoint<C>
876where
877 C: PrimeCurveParams,
878 ProjectivePoint<C>: Double,
879{
880 type Output = ProjectivePoint<C>;
881
882 #[inline]
883 fn mul(self, scalar: &Scalar<C>) -> ProjectivePoint<C> {
884 ProjectivePoint::mul(self, scalar)
885 }
886}
887
888impl<C, S> MulVartime<S> for ProjectivePoint<C>
889where
890 Self: Double,
891 C: PrimeCurveParams,
892 S: Borrow<Scalar<C>>,
893{
894 #[inline]
895 fn mul_vartime(self, scalar: S) -> Self {
896 ProjectivePoint::mul_vartime(&self, scalar.borrow())
897 }
898}
899
900impl<C, S> MulVartime<S> for &ProjectivePoint<C>
901where
902 Self: Double,
903 C: PrimeCurveParams,
904 S: Borrow<Scalar<C>>,
905{
906 #[inline]
907 fn mul_vartime(self, scalar: S) -> ProjectivePoint<C> {
908 ProjectivePoint::mul_vartime(self, scalar.borrow())
909 }
910}
911
912impl<C> MulVartime<&Scalar<C>> for &ProjectivePoint<C>
913where
914 C: PrimeCurveParams,
915 ProjectivePoint<C>: Double,
916{
917 #[inline]
918 fn mul_vartime(self, scalar: &Scalar<C>) -> ProjectivePoint<C> {
919 ProjectivePoint::mul_vartime(self, scalar)
920 }
921}
922
923impl<C> MulByGeneratorVartime for ProjectivePoint<C>
924where
925 C: PrimeCurveParams,
926{
927 #[inline]
928 fn mul_by_generator_vartime(scalar: &Scalar<C>) -> Self {
929 C::Backend::mul_by_generator_vartime(scalar)
930 }
931
932 #[inline]
933 fn mul_by_generator_and_mul_add_vartime(
934 a: &Self::Scalar,
935 b_scalar: &Self::Scalar,
936 b_point: &Self,
937 ) -> Self {
938 C::Backend::mul_by_generator_and_mul_add_vartime(a, b_scalar, b_point)
939 }
940}
941
942impl<C, S> MulAssign<S> for ProjectivePoint<C>
943where
944 Self: Double,
945 C: PrimeCurveParams,
946 S: Borrow<Scalar<C>>,
947{
948 #[inline]
949 fn mul_assign(&mut self, scalar: S) {
950 *self = ProjectivePoint::mul(self, scalar.borrow());
951 }
952}
953
954impl<C> Neg for ProjectivePoint<C>
955where
956 C: PrimeCurveParams,
957{
958 type Output = ProjectivePoint<C>;
959
960 fn neg(self) -> ProjectivePoint<C> {
961 ProjectivePoint::neg(&self)
962 }
963}
964
965impl<C> Neg for &ProjectivePoint<C>
966where
967 C: PrimeCurveParams,
968{
969 type Output = ProjectivePoint<C>;
970
971 fn neg(self) -> ProjectivePoint<C> {
972 ProjectivePoint::neg(self)
973 }
974}
975
976#[cfg(feature = "serde")]
981impl<C> Serialize for ProjectivePoint<C>
982where
983 C: PrimeCurveParams,
984{
985 fn serialize<S>(&self, serializer: S) -> core::result::Result<S::Ok, S::Error>
986 where
987 S: ser::Serializer,
988 {
989 self.to_affine().serialize(serializer)
990 }
991}
992
993#[cfg(feature = "serde")]
994impl<'de, C> Deserialize<'de> for ProjectivePoint<C>
995where
996 C: PrimeCurveParams,
997{
998 fn deserialize<D>(deserializer: D) -> core::result::Result<Self, D::Error>
999 where
1000 D: de::Deserializer<'de>,
1001 {
1002 AffinePoint::<C>::deserialize(deserializer).map(Self::from)
1003 }
1004}