2 * Example of a singular curve, similar to 19.c
3 * but the Tate pairing degenerates
5 * Consider the curve E: y^2 = x^3 + x^2 over F_19:
6 * E_ns(F_19) is a cyclic group of order 18.
10 #include "pbc_singular.h"
13 static void miller(element_t res
, element_t P
, element_t Q
, element_t R
, int n
)
23 const element_ptr Px
= curve_x_coord(P
);
24 const element_ptr Py
= curve_y_coord(P
);
25 const element_ptr numx
= curve_x_coord(Q
);
26 const element_ptr numy
= curve_y_coord(Q
);
27 const element_ptr denomx
= curve_x_coord(R
);
28 const element_ptr denomy
= curve_y_coord(R
);
30 #define do_vertical(e, edenom) { \
31 element_sub(e0, numx, Zx); \
32 element_mul((e), (e), e0); \
34 element_sub(e0, denomx, Zx); \
35 element_mul((edenom), (edenom), e0); \
38 #define do_tangent(e, edenom) { \
39 /*a = -slope_tangent(A.x, A.y); \
41 c = -(A.y + a * A.x); \
42 but we multiply by 2*A.y to avoid division \
44 a = -Ax * (Ax + Ax + Ax + twicea_2) - a_4; \
45 This curve is special: \
48 c = -(2 Ay^2 + a Ax); */ \
50 if (element_is0(Zy)) { \
51 do_vertical((e), (edenom)); \
53 element_square(a, Zx); \
54 element_mul_si(a, a, 3); \
55 element_add(a, a, Zx); \
56 element_add(a, a, Zx); \
59 element_add(b, Zy, Zy); \
61 element_mul(e0, b, Zy); \
62 element_mul(c, a, Zx); \
63 element_add(c, c, e0); \
66 element_mul(e0, a, numx); \
67 element_mul(e1, b, numy); \
68 element_add(e0, e0, e1); \
69 element_add(e0, e0, c); \
70 element_mul((e), (e), e0); \
72 element_mul(e0, a, denomx); \
73 element_mul(e1, b, denomy); \
74 element_add(e0, e0, e1); \
75 element_add(e0, e0, c); \
76 element_mul((edenom), (edenom), e0); \
80 #define do_line(e, edenom) { \
81 if (!element_cmp(Zx, Px)) { \
82 if (!element_cmp(Zy, Py)) { \
83 do_tangent((e), (edenom)); \
85 do_vertical((e), (edenom)); \
88 element_sub(b, Px, Zx); \
89 element_sub(a, Zy, Py); \
90 element_mul(c, Zx, Py); \
91 element_mul(e0, Zy, Px); \
92 element_sub(c, c, e0); \
94 element_mul(e0, a, numx); \
95 element_mul(e1, b, numy); \
96 element_add(e0, e0, e1); \
97 element_add(e0, e0, c); \
98 element_mul((e), (e), e0); \
100 element_mul(e0, a, denomx); \
101 element_mul(e1, b, denomy); \
102 element_add(e0, e0, e1); \
103 element_add(e0, e0, c); \
104 element_mul((edenom), (edenom), e0); \
108 element_init(a
, res
->field
);
109 element_init(b
, res
->field
);
110 element_init(c
, res
->field
);
111 element_init(e0
, res
->field
);
112 element_init(e1
, res
->field
);
114 element_init(v
, res
->field
);
115 element_init(vd
, res
->field
);
116 element_init(Z
, P
->field
);
119 Zx
= curve_x_coord(Z
);
120 Zy
= curve_y_coord(Z
);
127 m
= (mp_bitcnt_t
)mpz_sizeinbase(q
, 2);
128 m
= (m
> 2 ? m
- 2 : 0);
131 element_square(v
, v
);
132 element_square(vd
, vd
);
134 element_double(Z
, Z
);
137 if (mpz_tstbit(q
, m
)) {
139 element_add(Z
, Z
, P
);
150 element_invert(vd
, vd
);
151 element_mul(res
, v
, vd
);
166 static void tate_3(element_ptr out
, element_ptr P
, element_ptr Q
, element_ptr R
)
175 element_init(QR
, P
->field
);
176 element_init(e0
, out
->field
);
178 element_add(QR
, Q
, R
);
180 //for subgroup size 3, -2P = P, hence
181 //the tangent line at P has divisor 3(P) - 3(O)
183 miller(out
, P
, QR
, R
, 3);
185 element_pow_mpz(out
, out
, six
);
191 static void tate_9(element_ptr out
, element_ptr P
, element_ptr Q
, element_ptr R
)
194 element_init(QR
, P
->field
);
196 element_add(QR
, Q
, R
);
198 miller(out
, P
, QR
, R
, 9);
200 element_square(out
, out
);
219 field_init_fp(Z19
, q
);
220 element_init(a
, Z19
);
222 field_init_curve_singular_with_node(c
, Z19
);
228 //(3,+/-6) is a generator
229 //we have an isomorphism from E_ns to F_19^*
231 //(generally (x,y) --> (y+x)/(y-x)
233 curve_set_si(R
, 3, 6);
235 for (i
=1; i
<=18; i
++) {
237 element_mul_mpz(Q
, R
, z
);
238 element_printf("%dR = %B\n", i
, Q
);
242 element_mul_mpz(P
, R
, z
);
244 element_printf("P = %B\n", P
);
246 for (i
=1; i
<=3; i
++) {
248 element_mul_mpz(Q
, R
, z
);
250 element_printf("e_3(P,%dP) = %B\n", i
, a
);
253 element_double(P
, R
);
255 element_printf("P = %B\n", P
);
256 for (i
=1; i
<=9; i
++) {
258 element_mul_mpz(Q
, P
, z
);
260 element_printf("e_9(P,%dP) = %B\n", i
, a
);