elliptic_curve/hash2curve/
isogeny.rs1use core::ops::{AddAssign, Mul};
6use ff::Field;
7use generic_array::{typenum::Unsigned, ArrayLength, GenericArray};
8
9pub struct IsogenyCoefficients<F: Field + AddAssign + Mul<Output = F>> {
11 pub xnum: &'static [F],
13 pub xden: &'static [F],
15 pub ynum: &'static [F],
17 pub yden: &'static [F],
19}
20
21pub trait Isogeny: Field + AddAssign + Mul<Output = Self> {
23 type Degree: ArrayLength<Self>;
25 const COEFFICIENTS: IsogenyCoefficients<Self>;
27
28 fn isogeny(x: Self, y: Self) -> (Self, Self) {
30 let mut xs = GenericArray::<Self, Self::Degree>::default();
31 xs[0] = Self::ONE;
32 xs[1] = x;
33 xs[2] = x.square();
34 for i in 3..Self::Degree::to_usize() {
35 xs[i] = xs[i - 1] * x;
36 }
37 let x_num = Self::compute_iso(&xs, Self::COEFFICIENTS.xnum);
38 let x_den = Self::compute_iso(&xs, Self::COEFFICIENTS.xden)
39 .invert()
40 .unwrap();
41 let y_num = Self::compute_iso(&xs, Self::COEFFICIENTS.ynum) * y;
42 let y_den = Self::compute_iso(&xs, Self::COEFFICIENTS.yden)
43 .invert()
44 .unwrap();
45
46 (x_num * x_den, y_num * y_den)
47 }
48
49 fn compute_iso(xxs: &[Self], k: &[Self]) -> Self {
51 let mut xx = Self::ZERO;
52 for (xi, ki) in xxs.iter().zip(k.iter()) {
53 xx += *xi * ki;
54 }
55 xx
56 }
57}