1 #include "cado.h" // IWYU pragma: keep
2 #include <cerrno>      // for errno
3 #include <cstdlib>     // for exit, free, strtoul, EXIT_FAILURE
4 #include <cstring>     // for strdup
5 #include <cctype>      // for isspace
6 #include <cstdint>     // for uint64_t
7 #include <cstdio>      // for fprintf, NULL, stderr, fclose, fgets, fopen, FILE
8 #include "las-dlog-base.hpp"
9 #include "las-multiobj-globals.hpp"
10 #include "macros.h"    // for ASSERT_ALWAYS
11 #include "typedefs.h"  // for index_t
12 #include "params.h"     // param_list_parse_*
13 #include "portability.h" // strdup // IWYU pragma: keep
14 #include "verbose.h"    // verbose_output_print
15 
declare_usage(cxx_param_list & pl)16 void las_dlog_base::declare_usage(cxx_param_list & pl)
17 {
18     if (!dlp_descent) return;
19     param_list_decl_usage(pl, "renumber", "renumber table (for the descent)");
20     param_list_decl_usage(pl, "log", "log table, as built by reconstructlog");
21     /* These belong to las-siever-config of course. But we do a lookup
22      * from here as well.
23      */
24     param_list_decl_usage(pl, "lpb0", "set large prime bound on side 0 to 2^lpb0");
25     param_list_decl_usage(pl, "lpb1", "set large prime bound on side 1 to 2^lpb1");
26 }
27 
las_dlog_base(cxx_cado_poly const & cpoly,cxx_param_list & pl)28 las_dlog_base::las_dlog_base(cxx_cado_poly const & cpoly, cxx_param_list & pl)
29     : cpoly(cpoly)
30     , renumber_table(cpoly)
31 {
32     if (!dlp_descent) return;
33     renumberfilename = NULL;
34     logfilename = NULL;
35     const char * tmp;
36     if ((tmp = param_list_lookup_string(pl, "renumber")) != NULL) {
37         renumberfilename = strdup(tmp);
38     }
39     if ((tmp = param_list_lookup_string(pl, "log")) != NULL) {
40         logfilename = strdup(tmp);
41     }
42     if (!logfilename != !renumberfilename) {
43         fprintf(stderr, "In descent mode, want either renumber+log, or none\n");
44         exit(EXIT_FAILURE);
45     }
46     if (!param_list_parse_ulong(pl, "lpb0", &(lpb[0]))) {
47         fprintf(stderr, "In descent mode, want lpb0 for the final descent\n");
48         exit(EXIT_FAILURE);
49     }
50     if (!param_list_parse_ulong(pl, "lpb1", &(lpb[1]))) {
51         fprintf(stderr, "In descent mode, want lpb1 for the final descent\n");
52         exit(EXIT_FAILURE);
53     }
54     read();
55 }
56 
~las_dlog_base()57 las_dlog_base::~las_dlog_base()
58 {
59     if (!dlp_descent) return;
60     free(renumberfilename);
61     free(logfilename);
62 }
63 
is_known(int side,p_r_values_t p,p_r_values_t r) const64 bool las_dlog_base::is_known(int side, p_r_values_t p, p_r_values_t r) const
65 {
66     ASSERT_ALWAYS(dlp_descent);
67     // if p is above large prime bound,  its log is not known.
68     if (lpb[side] >= 64)
69         return false;
70     if (p >> lpb[side]) {
71         return false;
72     }
73     if (renumberfilename) {
74         /* For now we assume that we know the log of all bad ideals */
75         /* If we want to be able to do a complete lookup for bad ideals,
76          * then we need to use
77          *      renumber_table.indices_from_p_a_b
78          * which needs a,b as well.
79          */
80         if (renumber_table.is_bad ({ p, r, side }))
81             return true;
82         index_t h = renumber_table.index_from_p_r({ p, r, side });
83         return known_logs[h];
84     }
85     return true;
86 }
87 
88 
read()89 void las_dlog_base::read()
90 {
91     ASSERT_ALWAYS(dlp_descent);
92     if (!renumberfilename) {
93         verbose_output_print(0, 1, "# Descent: no access to renumber table given, using lpb(%lu/%lu) to decide what are the supposedly known logs\n",
94                 lpb[0], lpb[1]);
95         return;
96     }
97 
98     verbose_output_print(0, 1, "# Descent: will get list of known logs from %s, using also %s for mapping\n", logfilename, renumberfilename);
99 
100     renumber_table.read_from_file(renumberfilename);
101 
102     for(int side = 0 ; side < 2 ; side++) {
103         if (lpb[side] != renumber_table.get_lpb(side)) {
104             fprintf(stderr, "lpb%d=%lu different from lpb%d=%u stored in renumber table, probably a bug\n", side, lpb[side], side, renumber_table.get_lpb(side));
105             exit(EXIT_FAILURE);
106         }
107     }
108 
109     uint64_t nprimes = renumber_table.get_size();
110     known_logs.assign(nprimes + 32, false);
111     /* 32 is because the SM columns are here, too ! We would like to
112      * avoid reallocation, so let's be generous (anyway we'll
113      * reallocate if needed)
114      */
115 
116     /* format of the log table: there are FIVE different line types.
117      *
118      * [index] added column [log]
119      * [index] bad ideals [log]
120      * [index] [p] [side] rat [log]
121      * [index] [p] [side] [r] [log]
122      * [index] SM col [i] [log]
123      * where by default side=0 means the rational side, side=1 the algebraic one
124      * r is the root of f(x) mod p, where f is the algebraic polynomial
125      * log is the virtual logarithm
126      * (see https://lists.gforge.inria.fr/pipermail/cado-nfs-discuss/2019-February/000998.html)
127      *
128      * Here we care only about the index anyway. By the way, this index
129      * is written in hex.
130      */
131     FILE * f = fopen(logfilename, "r");
132     ASSERT_ALWAYS(f != NULL);
133     size_t nlogs=0;
134     for(int lnum = 0 ; ; lnum++) {
135         char line[1024];
136         char * x = fgets(line, sizeof(line), f);
137         if (x == NULL) break;
138         for( ; *x && isspace(*x) ; x++) ;
139         if (*x == '#') continue;
140         if (!*x) continue;
141         errno=0;
142         unsigned long z = strtoul(x, &x, 16);
143         if (errno) {
144             fprintf(stderr, "Parse error at line %d in %s: %s\n", lnum, logfilename, line);
145             break;
146         }
147         if (z >= known_logs.size()) {
148             /* happens for SM columns: we have more than the size of the
149              * renumber table ! */
150             known_logs.resize(z + 1);
151         }
152 	nlogs+=!known_logs[z];
153         known_logs[z] = true;
154     }
155     fclose(f);
156     verbose_output_print(0, 1, "# Got %zu known logs from %s\n", nlogs, logfilename);
157 }
158 
159 
160