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