1 /*
2
3 modclass.c - code for evaluating modular functions in quadratic arguments
4
5 Copyright (C) 2009, 2010, 2011, 2015, 2016, 2018 Andreas Enge
6
7 This file is part of CM.
8
9 CM is free software; you can redistribute it and/or modify it under
10 the terms of the GNU General Public License as published by the
11 Free Software Foundation; either version 3 of the license, or (at your
12 option) any later version.
13
14 CM is distributed in the hope that it will be useful, but WITHOUT ANY
15 WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17 for more details.
18
19 You should have received a copy of the GNU General Public License along
20 with CM; see the file COPYING. If not, write to the Free Software
21 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 */
23
24 #include "cm_class-impl.h"
25
26 #define mpz_sub_si(c, a, b) \
27 (b >= 0) ? mpz_sub_ui (c, a, (unsigned long int) b) \
28 : mpz_add_ui (c, a, (unsigned long int) (-b))
29
30 static void cm_modclass_cset_quadratic (ctype rop,
31 int_cl_t a, int_cl_t b, ftype root);
32 static int cm_modclass_eta_transform_eval_quad (ctype rop, long int *e,
33 ctype czplusd, cm_modular_t m, cm_classgroup_t cl,
34 ctype *eta, int_cl_t a, int_cl_t b, ftype root);
35 static void write_q24eta (ctype *q24eta, cm_classgroup_t cl,
36 fprec_t prec, char *type);
37 static bool read_q24eta (ctype *q24eta, cm_classgroup_t cl, fprec_t prec,
38 char *type);
39 static void compute_q24 (cm_modular_t m, cm_classgroup_t cl, ftype root,
40 ctype *q24, bool verbose);
41 static void compute_eta (cm_modular_t m, cm_classgroup_t cl, ftype root,
42 ctype *eta, bool fem, bool checkpoints, bool verbose);
43 static void multieta_eval_quad_rec (cm_modclass_t mc, ctype rop_num,
44 ctype rop_den, int_cl_t a, int_cl_t b, int *p);
45
46 /*****************************************************************************/
47 /* */
48 /* creating and freeing variables */
49 /* */
50 /*****************************************************************************/
51
52 #define CM_FEM false
cm_modclass_init(cm_modclass_t * mc,cm_classgroup_t cl,cm_classgroup_t cl2,fprec_t prec,bool checkpoints,bool verbose)53 void cm_modclass_init (cm_modclass_t *mc, cm_classgroup_t cl,
54 cm_classgroup_t cl2, fprec_t prec, bool checkpoints, bool verbose)
55 /* cl2.d may be 0, in which case mc->eta2 is not computed */
56
57 {
58 int i;
59 mpz_t tmp_z;
60
61 mpz_init (tmp_z);
62
63 cm_modular_init (&(mc->m), prec);
64 mc->cl = cl;
65 mc->cl2 = cl2;
66
67 finit (mc->root, prec);
68 cm_classgroup_mpz_set_icl (tmp_z, -cl.d);
69 fset_z (mc->root, tmp_z);
70 fsqrt (mc->root, mc->root);
71 finit (mc->sqrt2_over2, prec);
72 fsqrt_ui (mc->sqrt2_over2, 2ul);
73 fdiv_2ui (mc->sqrt2_over2, mc->sqrt2_over2, 1ul);
74 finit (mc->sqrt2_over4, prec);
75 fdiv_2ui (mc->sqrt2_over4, mc->sqrt2_over2, 1ul);
76
77 mc->eta = (ctype *) malloc (mc->cl.h * sizeof (ctype));
78 /* Initialise only one out of two eta conjugates for inverse forms. */
79 for (i = 0; i < mc->cl.h; i++)
80 if (cl.conj [i] >= i)
81 cinit (mc->eta [i], prec);
82 if (!checkpoints || !read_q24eta (mc->eta, mc->cl, prec, "eta"))
83 compute_eta (mc->m, mc->cl, mc->root, mc->eta, CM_FEM, checkpoints, verbose);
84
85 if (cl2.d != 0) {
86 finit (mc->root2, prec);
87 cm_classgroup_mpz_set_icl (tmp_z, -cl2.d);
88 fset_z (mc->root2, tmp_z);
89 fsqrt (mc->root2, mc->root2);
90 mc->eta2 = (ctype *) malloc (mc->cl2.h * sizeof (ctype));
91 for (i = 0; i < mc->cl2.h; i++)
92 if (cl2.conj [i] >= i)
93 cinit (mc->eta2 [i], prec);
94 if (!checkpoints || !read_q24eta (mc->eta2, mc->cl2, prec, "eta"))
95 compute_eta (mc->m, mc->cl2, mc->root2, mc->eta2, CM_FEM, checkpoints,
96 verbose);
97 }
98
99 mpz_clear (tmp_z);
100 }
101
102 /*****************************************************************************/
103
cm_modclass_clear(cm_modclass_t * mc)104 void cm_modclass_clear (cm_modclass_t *mc)
105
106 {
107 int i;
108
109 fclear (mc->root);
110 fclear (mc->sqrt2_over2);
111 fclear (mc->sqrt2_over4);
112 for (i = 0; i < mc->cl.h; i++)
113 if (mc->cl.conj [i] >= i)
114 cclear (mc->eta [i]);
115 free (mc->eta);
116 if (mc->cl2.d != 0) {
117 fclear (mc->root2);
118 for (i = 0; i < mc->cl2.h; i++)
119 if (mc->cl2.conj [i] >= i)
120 cclear (mc->eta2 [i]);
121 free (mc->eta2);
122 }
123
124 cm_modular_clear (&(mc->m));
125 }
126
127 /*****************************************************************************/
128 /* */
129 /* file handling functions */
130 /* */
131 /*****************************************************************************/
132
write_q24eta(ctype * q24eta,cm_classgroup_t cl,fprec_t prec,char * type)133 static void write_q24eta (ctype *q24eta, cm_classgroup_t cl,
134 fprec_t prec, char *type)
135 /* writes the values of q24eta to the file */
136 /* CLASS_TMPDIR + "/tmp_" + -cl.d + "_" + prec + "_" + type + ".dat" */
137 /* type should be one of "q24" or "eta" */
138
139 {
140 char filename [255];
141 FILE *f;
142 int i;
143
144 sprintf (filename, "%s/tmp_%"PRIicl"_%d_%s.dat", CM_CLASS_TMPDIR, -cl.d,
145 (int) prec, type);
146
147 if (!cm_file_open_write (&f, filename))
148 exit (1);
149
150 for (i = 0; i < cl.h; i++)
151 if (cl.conj [i] >= i) {
152 cout_str (f, 16, 0, q24eta [i]);
153 fprintf (f, "\n");
154 }
155
156 cm_file_close (f);
157 }
158
159 /*****************************************************************************/
160
read_q24eta(ctype * q24eta,cm_classgroup_t cl,fprec_t prec,char * type)161 static bool read_q24eta (ctype *q24eta, cm_classgroup_t cl, fprec_t prec,
162 char *type)
163 /* reads the values of q24eta from the file */
164 /* CLASS_TMPDIR + "/tmp_" + -cl.d + "_" + prec + "_" + type + ".dat" */
165 /* type should be one of "q24" or "eta" */
166
167 {
168 char filename [255];
169 FILE *f;
170 int i;
171
172 sprintf (filename, "%s/tmp_%"PRIicl"_%d_%s.dat", CM_CLASS_TMPDIR, -cl.d,
173 (int) prec, type);
174
175 if (!cm_file_open_read (&f, filename))
176 return false;
177
178 for (i = 0; i < cl.h; i++)
179 if (cl.conj [i] >= i)
180 cinp_str (q24eta [i], f, NULL, 16);
181
182 cm_file_close (f);
183
184 return true;
185 }
186
187 /*****************************************************************************/
188 /* */
189 /* functions for precomputations */
190 /* */
191 /*****************************************************************************/
192
compute_q24(cm_modular_t m,cm_classgroup_t cl,ftype root,ctype * q24,bool verbose)193 static void compute_q24 (cm_modular_t m, cm_classgroup_t cl, ftype root,
194 ctype *q24, bool verbose)
195 /* Computes the q^(1/24) for all forms of cl with non-negative b;
196 root contains sqrt(-d). */
197 {
198 int i, j, tmp_int;
199 int_cl_t tmp_cli;
200 ftype Pi24, Pi24_root, tmp;
201 ftype *q_real;
202 int_cl_t *A_red, *B_red;
203 int *order;
204 cm_timer clock2, clock3;
205 int counter1, counter2;
206
207 finit (Pi24, m.prec);
208 finit (Pi24_root, m.prec);
209 finit (tmp, m.prec);
210
211 fdiv_ui (Pi24, m.pi, 24ul);
212 fmul (Pi24_root, root, Pi24);
213
214 A_red = (int_cl_t *) malloc (cl.h * sizeof (int_cl_t));
215 B_red = (int_cl_t *) malloc (cl.h * sizeof (int_cl_t));
216 order = (int *) malloc (cl.h * sizeof (int));
217 q_real = (ftype *) malloc (cl.h * sizeof (ftype));
218
219 for (i = 0; i < cl.h; i++)
220 if (cl.conj [i] >= i)
221 finit (q_real [i], m.prec);
222
223 cm_timer_start (clock2);
224 /* precompute the absolute values of q^{1/24}, i.e. the */
225 /* exp (- pi/24 * \sqrt (|d|) / A) for the occurring A */
226 cm_timer_start (clock3);
227 counter1 = 0;
228 counter2 = 0;
229
230 /* Sort the forms by insertion by decreasing A, then by increasing B;
231 the variable order keeps track of the permutation: So order [0] = j
232 means that the A in form j has the largest A, and so on. */
233 for (i = 0; i < cl.h; i++)
234 order [i] = i;
235 for (i = 0; i < cl.h - 1; i++) {
236 /* Look for the form with the largest A, and among these for the
237 one with the smallest B. */
238 tmp_int = i;
239 for (j = tmp_int + 1; j < cl.h; j++)
240 if (cl.form [order [j]].a > cl.form [order [tmp_int]].a
241 || ( cl.form [order [j]].a == cl.form [order [tmp_int]].a
242 && cl.form [order [j]].b < cl.form [order [tmp_int]].b))
243 tmp_int = j;
244 /* Swap the element with the found one. */
245 j = order [i];
246 order [i] = order [tmp_int];
247 order [tmp_int] = j;
248 }
249
250 for (i = 0; i < cl.h; i++) {
251 /* Compute q_real only for the first form in each pair of
252 inverse forms. */
253 if (cl.conj [order [i]] >= order [i]) {
254 /* Check whether the current A is a divisor of a previous one;
255 if yes, choose the closest one. Since the B are ordered
256 increasingly, we find a non-negative one, corresponding to an
257 element that has been computed. */
258 for (j = i-1;
259 j >= 0 &&
260 (cl.conj [order [j]] < order [j]
261 || cl.form [order [j]].a % cl.form [order [i]].a != 0);
262 j--);
263 if (j >= 0) {
264 if (cl.form [order [i]].a == cl.form [order [j]].a)
265 fset (q_real [order [i]], q_real [order [j]]);
266 else {
267 counter1++;
268 fpow_ui (q_real [order [i]], q_real [order [j]],
269 cl.form [order [j]].a / cl.form [order [i]].a);
270 }
271 }
272 else {
273 counter1++;
274 counter2++;
275 fdiv_ui (q_real [order [i]], Pi24_root, cl.form [order [i]].a);
276 fneg (q_real [order [i]], q_real [order [i]]);
277 fexp (q_real [order [i]], q_real [order [i]]);
278 }
279 }
280 if (verbose && i % 200 == 0) {
281 printf (".");
282 fflush (stdout);
283 }
284 }
285 cm_timer_stop (clock3);
286 if (verbose) {
287 printf ("\n- Number of distinct A: %d\n", counter1);
288 printf ("- Number of exp: %d\n", counter2);
289 printf ("- Time for exp: %.1f\n", cm_timer_get (clock3));
290 }
291
292 /* precompute the arguments of q^{1/24}, i.e. the
293 exp (- i pi/24 * B / A) for the occurring A, B
294 Write B / A = B_red / A_red with coprime (B_red, A_red).
295 Then order the forms with respect to increasing A_red, and for the
296 same A_red with respect to decreasing B_red: This ensures that forms
297 with a positive B come before their inverse. */
298 cm_timer_start (clock3);
299 counter1 = 0;
300 counter2 = 0;
301 for (i = 0; i < cl.h; i++) {
302 tmp_cli = cm_classgroup_gcd (cl.form [i].a, cl.form [i].b);
303 A_red [i] = cl.form [i].a / tmp_cli;
304 B_red [i] = cl.form [i].b / tmp_cli;
305 order [i] = i;
306 }
307
308 /* sort by insertion */
309 for (i = 0; i < cl.h - 1; i++) {
310 /* Look for the form with the smallest A, and among these for the
311 one with the largest B. */
312 tmp_int = i;
313 for (j = tmp_int + 1; j < cl.h; j++)
314 if (A_red [order [j]] < A_red [order [tmp_int]]
315 || ( A_red [order [j]] == A_red [order [tmp_int]]
316 && B_red [order [j]] > B_red [order [tmp_int]]))
317 tmp_int = j;
318 /* Swap the element with the found one. */
319 j = order [i];
320 order [i] = order [tmp_int];
321 order [tmp_int] = j;
322 }
323
324 /* put q24 [] = exp (- pi/24 i / A_red), i.e. the primitive root */
325 /* of unity */
326 for (i = cl.h - 1; i >= 0; i--) {
327 if (cl.conj [order [i]] >= order [i]) {
328 /* Check whether the current A is a divisor of a higher one;
329 if so, take the higher one which is closest and thus yields
330 the lowest quotient.
331 Notice that the A's are in increasing order and the B's
332 decreasing: So if there is a form with a non-negative B,
333 this one is chosen; otherwise we need to exclude it. */
334 for (j = i+1;
335 j < cl.h &&
336 (cl.conj [order [j]] < order [j]
337 || A_red [order [j]] % A_red [order [i]] != 0);
338 j++);
339 if (j < cl.h) {
340 if (A_red [order [i]] == A_red [order [j]])
341 cset (q24 [order [i]], q24 [order [j]]);
342 else {
343 counter1++;
344 cpow_ui (q24 [order [i]], q24 [order [j]],
345 (unsigned long int) (A_red [order [j]] / A_red [order [i]]));
346 }
347 }
348 else {
349 counter1++;
350 counter2++;
351 fdiv_ui (tmp, Pi24, A_red [order [i]]);
352 fsin_cos (q24 [order [i]]->im, q24 [order [i]]->re,
353 tmp);
354 }
355 }
356 if (verbose && i % 200 == 0) {
357 printf (".");
358 fflush (stdout);
359 }
360 }
361 cm_timer_stop (clock3);
362 if (verbose) {
363 printf ("\n- Number of distinct A_red: %d\n", counter1);
364 printf ("- Number of sin/cos: %d\n", counter2);
365 printf ("- Time for sin/cos: %.1f\n", cm_timer_get (clock3));
366 }
367
368 /* now raise to the power B_red */
369 cm_timer_start (clock3);
370 counter1 = 0;
371 counter2 = 0;
372 for (i = cl.h - 1; i >= 0; i--)
373 if (cl.conj [order [i]] >= order [i]) {
374 if (B_red [order [i]] == 0)
375 cset_ui_ui (q24 [order [i]], 1ul, 0ul);
376 else if (B_red [order [i]] > 1) {
377 /* Check whether the current B is a multiple of a previous one with */
378 /* the same A; if so, take the previous one which is closest. */
379 for (j = i+1;
380 j < cl.h && A_red [order [j]] == A_red [order [i]]
381 && B_red [order [j]] > 0
382 && B_red [order [i]] % B_red [order [j]] != 0;
383 j++);
384 if (j < cl.h && A_red [order [j]] == A_red [order [i]]
385 && B_red [order [j]] > 0) {
386 if (B_red [order [i]] == B_red [order [j]])
387 cset (q24 [order [i]], q24 [order [j]]);
388 else {
389 counter1++;
390 cpow_ui (q24 [order [i]], q24 [order [j]],
391 B_red [order [i]] / B_red [order [j]]);
392 }
393 }
394 else {
395 counter2++;
396 cpow_ui (q24 [order[i]], q24 [order [i]],
397 B_red [order [i]]);
398 }
399 }
400 }
401 cm_timer_stop (clock3);
402 if (verbose) {
403 printf ("- Number of partial powers: %d\n", counter1);
404 printf ("- Number of total powers: %d\n", counter2);
405 printf ("- Time for powers: %.1f\n", cm_timer_get (clock3));
406 }
407
408 /* Compute the q^(1/24) in q24 */
409 for (i = 0; i < cl.h; i++)
410 if (cl.conj [i] >= i)
411 cmul_fr (q24 [i], q24 [i], q_real [i]);
412 cm_timer_stop (clock2);
413 if (verbose)
414 printf ("- Time for q^(1/24): %.1f\n", cm_timer_get (clock2));
415
416 for (i = 0; i < cl.h; i++)
417 if (cl.conj [i] >= i)
418 fclear (q_real [i]);
419
420 free (A_red);
421 free (B_red);
422 free (order);
423 free (q_real);
424
425 fclear (Pi24);
426 fclear (Pi24_root);
427 fclear (tmp);
428 }
429
430 /*****************************************************************************/
431
compute_eta(cm_modular_t m,cm_classgroup_t cl,ftype root,ctype * eta,bool fem,bool checkpoints,bool verbose)432 static void compute_eta (cm_modular_t m, cm_classgroup_t cl, ftype root,
433 ctype *eta, bool fem, bool checkpoints, bool verbose)
434 /* computes the values of the Dedekind eta function for all reduced forms */
435 /* of the class group cl and stores them in eta; the precision is taken */
436 /* from eta [0], and root contains sqrt(-d). */
437 /* If fem is true, then evaluation via the AGM is activated. */
438
439 {
440 int i;
441 cm_timer clock1;
442 fprec_t prec = cget_prec (eta [0]);
443 cm_timer_start (clock1);
444
445 if (!fem) {
446 ctype *q24;
447 cm_timer clock2;
448
449 q24 = (ctype *) malloc (cl.h * sizeof (ctype));
450 for (i = 0; i < cl.h; i++)
451 if (cl.conj [i] >= i)
452 cinit (q24 [i], prec);
453
454 if (!checkpoints || !read_q24eta (q24, cl, prec, "q24")) {
455 compute_q24 (m, cl, root, q24, verbose);
456 if (checkpoints)
457 write_q24eta (q24, cl, prec, "q24");
458 }
459
460 cm_timer_start (clock2);
461 for (i = 0; i < cl.h; i++) {
462 if (cl.conj [i] >= i)
463 cm_modular_eta_series (m, eta [i], q24 [i]);
464 if (verbose && i % 200 == 0) {
465 printf (".");
466 fflush (stdout);
467 }
468 }
469 cm_timer_stop (clock2);
470 if (verbose)
471 printf ("\n- Time for series: %.1f",
472 cm_timer_get (clock2));
473 cm_timer_stop (clock2);
474 if (checkpoints)
475 write_q24eta (eta, cl, prec, "eta");
476
477 for (i = 0; i < cl.h; i++)
478 if (cl.conj [i] >= i)
479 cclear (q24 [i]);
480 free (q24);
481 }
482 else {
483 ctype tau;
484
485 cinit (tau, prec);
486
487 for (i = 0; i < cl.h; i++) {
488 if (cl.conj [i] >= i) {
489 cm_modclass_cset_quadratic (tau, cl.form [i].a, cl.form [i].b,
490 root);
491 cm_fem_eta_eval (m, eta [i], tau);
492 }
493 if (verbose && i % 200 == 0) {
494 printf (".");
495 fflush (stdout);
496 }
497 }
498
499 cclear (tau);
500 }
501
502 cm_timer_stop (clock1);
503 if (verbose)
504 printf ("\n- Time for eta: %.1f\n",
505 cm_timer_get (clock1));
506 }
507
508 /*****************************************************************************/
509 /* */
510 /* other internal functions */
511 /* */
512 /*****************************************************************************/
513
cm_modclass_cset_quadratic(ctype rop,int_cl_t a,int_cl_t b,ftype root)514 static void cm_modclass_cset_quadratic (ctype rop,
515 int_cl_t a, int_cl_t b, ftype root)
516 /* sets rop to (b + i*root) / (2a) */
517
518 {
519 fset_si (rop->re, b);
520 fset (rop->im, root);
521 cdiv_ui (rop, rop, 2*a);
522 }
523
524 /*****************************************************************************/
525
cm_modclass_fundamental_domain_quad(int_cl_t d,int_cl_t * a,int_cl_t * b,cm_matrix_t * M)526 static void cm_modclass_fundamental_domain_quad (int_cl_t d, int_cl_t *a,
527 int_cl_t *b, cm_matrix_t *M)
528 /* transforms (b + sqrt (d)) / (2a) into the fundamental domain and */
529 /* returns the inverse transformation matrix M */
530 /* Unfortunately we have to compute internally with multiprecision; */
531 /* although the final result fits into a long, intermediate results */
532 /* can be quite large. */
533 {
534 bool reduced = false;
535 static mpz_t a_local, b_local, b_minus_a, two_a, offset, c;
536 static bool first_time = true;
537 int_cl_t tmp_int;
538
539 if (first_time)
540 {
541 mpz_init (a_local);
542 mpz_init (b_local);
543 mpz_init (b_minus_a);
544 mpz_init (two_a);
545 mpz_init (offset);
546 mpz_init (c);
547 first_time = false;
548 }
549
550 M->a = 1;
551 M->b = 0;
552 M->c = 0;
553 M->d = 1;
554 cm_classgroup_mpz_set_icl (a_local, *a);
555 cm_classgroup_mpz_set_icl (b_local, *b);
556
557 while (!reduced) {
558 /* obtain -a < b <= a */
559 /* basically, compute offset as b / (2a) rounded towards the closest */
560 /* integer. If the quotient is exactly between two integers, round down */
561 mpz_sub (b_minus_a, b_local, a_local);
562 mpz_mul_2exp (two_a, a_local, 1);
563 mpz_cdiv_q (offset, b_minus_a, two_a);
564
565 tmp_int = mpz_get_si (offset);
566 /* multiply M from the right by T^{tmp_int} */
567 M->b += M->a * tmp_int;
568 M->d += M->c * tmp_int;
569
570 mpz_mul (offset, offset, two_a);
571 mpz_sub (b_local, b_local, offset);
572
573 /* compute c */
574 mpz_mul (c, b_local, b_local);
575 mpz_sub_si (c, c, d);
576 mpz_fdiv_q_2exp (c, c, 2);
577 mpz_divexact (c, c, a_local);
578 /* if not reduced, invert */
579 if (mpz_cmp (a_local, c) < 0 ||
580 (mpz_cmp (a_local, c) == 0 && mpz_sgn (b_local) >= 0))
581 reduced = true;
582 else {
583 mpz_set (a_local, c);
584 mpz_neg (b_local, b_local);
585 tmp_int = M->a;
586 M->a = M->b;
587 M->b = -tmp_int;
588 tmp_int = M->c;
589 M->c = M->d;
590 M->d = -tmp_int;
591 reduced = false;
592 }
593 }
594
595 *a = mpz_get_si (a_local);
596 *b = mpz_get_si (b_local);
597 /* normalise the matrix */
598 if (M->c < 0 || (M->c == 0 && M->d < 0)) {
599 M->a = -M->a;
600 M->b = -M->b;
601 M->c = -M->c;
602 M->d = -M->d;
603 }
604 }
605
606 /*****************************************************************************/
607
cm_modclass_eta_transform_eval_quad(ctype rop,long int * e,ctype czplusd,cm_modular_t m,cm_classgroup_t cl,ctype * eta,int_cl_t a,int_cl_t b,ftype root)608 static int cm_modclass_eta_transform_eval_quad (ctype rop, long int *e,
609 ctype czplusd, cm_modular_t m, cm_classgroup_t cl,
610 ctype *eta, int_cl_t a, int_cl_t b, ftype root)
611 /* Transform the quadratic integer op = (b + sqrt (cl.d)) / (2a) into the
612 element op1 in the fundamental domain.
613 Returns eta (op1) in rop and e and czplusd such that
614 eta (op) = zeta_24^e * sqrt (czplusd) * rop.
615 This can be used to decide at a higher level what to do with the
616 transformation data (for instance, if an even exponent is to be
617 applied, the square root can be saved).
618 Returns 0 if op itself is already in the fundamental domain,
619 1 otherwise.
620 root needs to be set to sqrt (|d|).
621 eta is a list of precomputed values, indexed in the same way as the
622 list of reduced quadratic forms in cl. */
623
624 {
625 int_cl_t a_local, b_local;
626 int transformed, i, sign;
627 cm_matrix_t M;
628
629 a_local = a;
630 b_local = b;
631 cm_modclass_fundamental_domain_quad (cl.d, &a_local, &b_local, &M);
632 cm_modclass_cset_quadratic (czplusd, a_local, b_local, root);
633 transformed = cm_modular_eta_transform (e, czplusd, czplusd, M);
634
635 /* look up the eta value */
636 if (b_local < 0) {
637 b_local = -b_local;
638 sign = -1;
639 }
640 else
641 sign = 1;
642 for (i = 0;
643 i < cl.h && (cl.form [i].a != a_local || cl.form [i].b != b_local);
644 i++);
645 if (i == cl.h) {
646 /* eta value not found, compute it. May happen when the level of the */
647 /* modular function and the conductor have a common factor. This case */
648 /* is rare, and the following computations are not optimised. */
649 printf ("Q");
650 if (sign == 1)
651 cm_modclass_cset_quadratic (rop, a_local, b_local, root);
652 else
653 cm_modclass_cset_quadratic (rop, a_local, -b_local, root);
654 cm_modular_eta_eval (m, rop, rop);
655 }
656 else {
657 if (sign == 1)
658 cset (rop, eta [i]);
659 else
660 cconj (rop, eta [i]);
661 }
662
663 return (transformed);
664 }
665
666 /*****************************************************************************/
667 /* */
668 /* external functions */
669 /* */
670 /*****************************************************************************/
671
cm_modclass_eta_eval_quad(ctype rop,cm_modular_t m,cm_classgroup_t cl,ctype * eta,int_cl_t a,int_cl_t b,ftype root)672 void cm_modclass_eta_eval_quad (ctype rop, cm_modular_t m, cm_classgroup_t cl,
673 ctype *eta, int_cl_t a, int_cl_t b, ftype root)
674 /* Evaluate the eta function at the quadratic integer
675 (b + sqrt (cl.d)) / (2a)
676 root needs to be set to sqrt (|d|).
677 eta is a list of precomputed values, indexed in the same way as the
678 list of reduced quadratic forms in cl. */
679
680 {
681 ctype czplusd;
682 long int e;
683 int transformed;
684
685 cinit (czplusd, cget_prec (rop));
686 transformed = cm_modclass_eta_transform_eval_quad (rop, &e, czplusd, m, cl,
687 eta, a, b, root);
688 if (transformed) {
689 csqrt (czplusd, czplusd);
690 cmul (rop, rop, czplusd);
691 cmul (rop, rop, m.zeta24 [e]);
692 }
693 }
694
695 /*****************************************************************************/
696
cm_modclass_f_eval_quad(cm_modclass_t mc,ctype rop,int_cl_t a,int_cl_t b,int e)697 void cm_modclass_f_eval_quad (cm_modclass_t mc, ctype rop,
698 int_cl_t a, int_cl_t b, int e)
699 /* Evaluate the Weber f-function, raised to the power e, at the quadratic
700 integer (b + sqrt (d)) / (2*a).
701 e may be 1 or 2. */
702
703 {
704 ctype rop1, czplusd1, czplusd2;
705 long int e1, e2;
706 int_cl_t c;
707
708 cinit (rop1, cget_prec (rop));
709 cinit (czplusd1, cget_prec (rop));
710 cinit (czplusd2, cget_prec (rop));
711
712 cm_modclass_eta_transform_eval_quad (rop1, &e1, czplusd1, mc.m, mc.cl,
713 mc.eta, a, b, mc.root);
714
715 /* The argument (z+1)/2 of the numerator corresponds to the quadratic */
716 /* form [2*a, b+2*a, (a+b+c)/2]. Here, (a+b+c)/2 need not be integral; */
717 /* if it is, the form need not be primitive any more, but may have a */
718 /* common divisor 2. */
719 c = a + b + cm_classgroup_compute_c (a, b, mc.cl.d);
720 if (c % 2 == 0)
721 if (b % 2 != 0 || c % 4 != 0)
722 cm_modclass_eta_transform_eval_quad (rop, &e2, czplusd2, mc.m, mc.cl,
723 mc.eta, 2*a, b + 2*a, mc.root);
724 else {
725 assert (mc.cl2.d == mc.cl.d / 4);
726 cm_modclass_eta_transform_eval_quad (rop, &e2, czplusd2, mc.m, mc.cl2,
727 mc.eta2, a, b/2 + a, mc.root2);
728 }
729 else {
730 ctype z;
731 cinit (z, cget_prec (rop));
732 cm_modclass_cset_quadratic (z, a, b, mc.root);
733 cadd_ui (rop, z, 1ul);
734 cdiv_ui (rop, rop, 2ul);
735 cm_modular_eta_eval (mc.m, rop, rop);
736 cclear (z);
737 e2 = 0;
738 cset_ui (czplusd2, 1ul);
739 }
740
741 if (e == 2) {
742 csqr (rop1, rop1);
743 csqr (rop, rop);
744 e2 = (2 * (e2 + (24 - e1)) + 23) % 24;
745 /* Force a positive result; 23 stands for the -1 coming from the
746 square of zeta48inv. */
747 }
748 else /* e == 1 */ {
749 cmul (rop, rop, mc.m.zeta48inv);
750 csqrt (czplusd1, czplusd1);
751 csqrt (czplusd2, czplusd2);
752 e2 = (e2 + (24 - e1)) % 24;
753 }
754 cmul (rop1, rop1, czplusd1);
755 cmul (rop, rop, czplusd2);
756 if (e2 != 0)
757 cmul (rop, rop, mc.m.zeta24 [e2]);
758
759 cdiv (rop, rop, rop1);
760
761 cclear (rop1);
762 cclear (czplusd1);
763 cclear (czplusd2);
764 }
765
766 /*****************************************************************************/
767
cm_modclass_f1_eval_quad(cm_modclass_t mc,ctype rop,int_cl_t a,int_cl_t b,int e)768 void cm_modclass_f1_eval_quad (cm_modclass_t mc, ctype rop,
769 int_cl_t a, int_cl_t b, int e)
770 /* Evaluate the Weber f-function, raised to the power e, at the quadratic
771 integer (b + sqrt (d)) / (2*a).
772 e may be 1 or 2. */
773
774 {
775 ctype rop1, czplusd1, czplusd2;
776 long int e1, e2;
777 int_cl_t c;
778
779 cinit (rop1, cget_prec (rop));
780 cinit (czplusd1, cget_prec (rop));
781 cinit (czplusd2, cget_prec (rop));
782
783 cm_modclass_eta_transform_eval_quad (rop1, &e1, czplusd1, mc.m, mc.cl,
784 mc.eta, a, b, mc.root);
785
786 /* The argument z/2 of the numerator corresponds to the quadratic form */
787 /* [2*a, b, c/2]. Here, c/2 need not be integral; if it is, the form need */
788 /* not be primitive any more, but may have a common divisor 2. */
789 c = cm_classgroup_compute_c (a, b, mc.cl.d);
790 if (c % 2 == 0)
791 if (b % 2 != 0 || c % 4 != 0)
792 cm_modclass_eta_transform_eval_quad (rop, &e2, czplusd2, mc.m,
793 mc.cl, mc.eta, 2*a, b, mc.root);
794 else {
795 assert (mc.cl2.d == mc.cl.d / 4);
796 cm_modclass_eta_transform_eval_quad (rop, &e2, czplusd2, mc.m,
797 mc.cl2, mc.eta2, a, b/2, mc.root2);
798 }
799 else {
800 ctype z;
801 cinit (z, cget_prec (rop));
802 cm_modclass_cset_quadratic (z, a, b, mc.root);
803 cdiv_ui (rop, z, 2ul);
804 cm_modular_eta_eval (mc.m, rop, rop);
805 cclear (z);
806 e2 = 0;
807 cset_ui (czplusd2, 1ul);
808 }
809
810 if (e == 2) {
811 csqr (rop1, rop1);
812 csqr (rop, rop);
813 e2 = (2 * (e2 + (24 - e1))) % 24;
814 }
815 else /* e == 1 */ {
816 csqrt (czplusd1, czplusd1);
817 csqrt (czplusd2, czplusd2);
818 e2 = (e2 + (24 - e1)) % 24;
819 }
820 cmul (rop1, rop1, czplusd1);
821 cmul (rop, rop, czplusd2);
822 if (e2 != 0)
823 cmul (rop, rop, mc.m.zeta24 [e2]);
824
825 cdiv (rop, rop, rop1);
826
827 cclear (rop1);
828 cclear (czplusd1);
829 cclear (czplusd2);
830 }
831
832 /*****************************************************************************/
833
cm_modclass_gamma2_eval_quad(cm_modclass_t mc,ctype rop,int_cl_t a,int_cl_t b)834 void cm_modclass_gamma2_eval_quad (cm_modclass_t mc, ctype rop,
835 int_cl_t a, int_cl_t b)
836
837 {
838 ctype f;
839
840 cinit (f, cget_prec (rop));
841
842 cm_modclass_f1_eval_quad (mc, f, a, b, 2);
843 cpow_ui (f, f, 4ul);
844 csqr (rop, f);
845 cui_div (f, 16ul, f);
846 cadd (rop, rop, f);
847
848 cclear (f);
849 }
850
851 /*****************************************************************************/
852
cm_modclass_gamma3_eval_quad(cm_modclass_t mc,ctype rop,int_cl_t a,int_cl_t b)853 void cm_modclass_gamma3_eval_quad (cm_modclass_t mc, ctype rop,
854 int_cl_t a, int_cl_t b)
855 /* evaluates sqrt (d) * gamma3 */
856
857 {
858 ctype f, tmp;
859 ftype tmp_fr;
860
861 cinit (f, cget_prec (rop));
862 cinit (tmp, cget_prec (rop));
863
864 cm_modclass_f_eval_quad (mc, f, a, b, 2);
865 cpow_ui (f, f, 4ul);
866 cm_modclass_f1_eval_quad (mc, rop, a, b, 2);
867 cpow_ui (rop, rop, 4ul);
868
869 cmul_ui (rop, rop, 2ul);
870 csub (rop, rop, f);
871 cpow_ui (tmp, f, 3ul);
872 cadd_ui (tmp, tmp, 8ul);
873 cmul (rop, rop, tmp);
874 cdiv (rop, rop, f);
875 cmul_fr (rop, rop, mc.root);
876 /* multiply by i */
877 tmp_fr [0] = rop->im [0];
878 rop->im [0] = rop->re [0];
879 rop->re [0] = tmp_fr [0];
880 fneg (rop->re, rop->re);
881
882 cclear (f);
883 cclear (tmp);
884 }
885
886 /*****************************************************************************/
887
cm_modclass_j_eval_quad(cm_modclass_t mc,ctype rop,int_cl_t a,int_cl_t b)888 void cm_modclass_j_eval_quad (cm_modclass_t mc, ctype rop,
889 int_cl_t a, int_cl_t b)
890
891 {
892 cm_modclass_gamma2_eval_quad (mc, rop, a, b);
893 cpow_ui (rop, rop, 3ul);
894 }
895
896 /*****************************************************************************/
897
multieta_eval_quad_rec(cm_modclass_t mc,ctype rop_num,ctype rop_den,int_cl_t a,int_cl_t b,int * p)898 static void multieta_eval_quad_rec (cm_modclass_t mc, ctype rop_num,
899 ctype rop_den, int_cl_t a, int_cl_t b, int *p)
900 /* Evaluates a multiple eta quotient, whose transformation degress are */
901 /* given by the numbers in p, which is an array terminated by 0; the */
902 /* result is given by rop_num / rop_den. This approach replaces complex */
903 /* divisions by faster multiplications. */
904 /* Assumes that p contains at least one number. */
905
906 {
907 if (p [1] == 0) {
908 /* simple eta quotient */
909 cm_modclass_eta_eval_quad (rop_num, mc.m, mc.cl, mc.eta, a * p [0], b,
910 mc.root);
911 cm_modclass_eta_eval_quad (rop_den, mc.m, mc.cl, mc.eta, a, b, mc.root);
912 }
913 else if (p [2] == 0 && p [0] == p [1]) {
914 /* special, faster code for double eta quotients with twice the same */
915 /* transformation degree */
916 cm_modclass_eta_eval_quad (rop_den, mc.m, mc.cl, mc.eta, a, b, mc.root);
917 cm_modclass_eta_eval_quad (rop_num, mc.m, mc.cl, mc.eta,
918 a * p [0] * p [0], b, mc.root);
919 cmul (rop_den, rop_den, rop_num);
920 cm_modclass_eta_eval_quad (rop_num, mc.m, mc.cl, mc.eta, a * p [0], b,
921 mc.root);
922 csqr (rop_num, rop_num);
923 }
924 else {
925 ctype tmp1, tmp2;
926 fprec_t prec = cget_prec (rop_num);
927
928 cinit (tmp1, prec);
929 cinit (tmp2, prec);
930
931 multieta_eval_quad_rec (mc, rop_num, tmp1, a, b, p+1);
932 multieta_eval_quad_rec (mc, rop_den, tmp2, a * p [0], b, p+1);
933 cmul (rop_num, rop_num, tmp2);
934 cmul (rop_den, rop_den, tmp1);
935
936 cclear (tmp1);
937 cclear (tmp2);
938 }
939 }
940
941 /*****************************************************************************/
942
cm_modclass_multieta_eval_quad(cm_modclass_t mc,ctype rop,int_cl_t a,int_cl_t b,int * p,int e)943 void cm_modclass_multieta_eval_quad (cm_modclass_t mc, ctype rop,
944 int_cl_t a, int_cl_t b, int *p, int e)
945 /* Evaluates a multiple eta quotient, whose transformation degress are */
946 /* given by the numbers in p, which is an array terminated by 0; the */
947 /* quotient is additionally raised to the power e. */
948 /* Assumes that p contains at least one number. */
949
950 {
951 ctype tmp;
952
953 cinit (tmp, cget_prec (rop));
954
955 multieta_eval_quad_rec (mc, rop, tmp, a, b, p);
956 cdiv (rop, rop, tmp);
957 if (e != 1)
958 cpow_ui (rop, rop, e);
959
960 cclear (tmp);
961 }
962
963 /*****************************************************************************/
964
cm_modclass_atkinhecke_level_eval_quad(cm_modclass_t mc,ctype rop,int_cl_t a,int_cl_t b,unsigned long int l)965 void cm_modclass_atkinhecke_level_eval_quad (cm_modclass_t mc, ctype rop,
966 int_cl_t a, int_cl_t b, unsigned long int l)
967
968 {
969 ctype z;
970
971 cinit (z, cget_prec (rop));
972
973 cm_modclass_cset_quadratic (z, a, b, mc.root);
974 cm_modular_atkinhecke_level_eval (mc.m, rop, z, l);
975
976 cclear (z);
977 }
978
979 /*****************************************************************************/
980