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