1 #include "cado.h" // IWYU pragma: keep
2 #include <cinttypes>               // for PRId64
3 #include <cstdio>              // IWYU pragma: keep
4 #include <cstdarg>             // IWYU pragma: keep
5 #include <gmp.h>                   // for mpz_srcptr, gmp_vfprintf
6 #include "cado_poly.h"   // cxx_cado_poly
7 #include "cxx_mpz.hpp"   // for cxx_mpz
8 #include "fb-types.h"              // for sublat_t
9 #include "las-auxiliary-data.hpp"  // for nfs_aux, report_and_timer
10 #include "las-choose-sieve-area.hpp"
11 #include "las-info.hpp"            // for las_info, HILIGHT_END, HILIGHT_START
12 #include "las-multiobj-globals.hpp"
13 #include "las-norms.hpp"           // for sieve_range_adjust
14 #include "las-qlattice.hpp"        // for qlattice_basis, qlattice_basis::to...
15 #include "las-siever-config.hpp"   // for siever_config, siever_config_pool
16 #include "las-todo-entry.hpp"      // for las_todo_entry
17 #include "macros.h"                // for MAYBE_UNUSED
18 #include "tdict.hpp"               // for timetree_t
19 #include "verbose.h"    // verbose_output_vfprint
20 
21 int never_discard = 0;      /* only enabled for las_descent */
22 
choose_sieve_area(las_info const & las,timetree_t * ptimer MAYBE_UNUSED,las_todo_entry const & doing,siever_config & conf,qlattice_basis & Q,uint32_t & J)23 static bool choose_sieve_area(las_info const & las,
24         timetree_t * ptimer MAYBE_UNUSED,
25         las_todo_entry const & doing,
26         siever_config & conf,
27         qlattice_basis & Q,
28         uint32_t & J)
29 {
30     sieve_range_adjust Adj;
31 
32     int adjust_strategy = las.adjust_strategy;
33     {
34 
35     /* Our business: find an appropriate siever_config, that is
36      * appropriate for this special-q. Different special-q's may lead to
37      * different siever_config's, it is allowed.
38      *
39      * This process completes when we also set conf.logI.
40      */
41     conf = las.config_pool.get_config_for_q(doing);
42 
43     /* The whole business about sieve_range_adjust is to compute the
44      * optimal logI and J for this special-q. We have several
45      * strategies for that.
46      */
47     try {
48         Adj = sieve_range_adjust(doing, las.cpoly, conf);
49     } catch (qlattice_basis::too_skewed const & x) {
50         verbose_output_vfprint(0, 1, gmp_vfprintf,
51                 "# "
52                 HILIGHT_START
53                 "Discarding side-%d q=%Zd; rho=%Zd (q-lattice basis does not fit)\n"
54                 HILIGHT_END,
55                 doing.side,
56                 (mpz_srcptr) doing.p,
57                 (mpz_srcptr) doing.r);
58         return false;
59     }
60 
61     if (!support_large_q && !Adj.Q.fits_31bits()) { // for fb_root_in_qlattice_31bits
62         verbose_output_print(2, 1,
63                 "# Warning, special-q basis is too skewed,"
64                 " skipping this special-q."
65                 " Define SUPPORT_LARGE_Q to proceed anyway.\n");
66         return false;
67     }
68 
69     }
70 
71     /* Must be done before any sort of lognorm computation, even before the
72      * adjustment. (only sublat_bound matters, here -- which actual
73      * sublattice we will sieve is irrelevant at this point, as what we
74      * do will be shared for all sublattices).
75      */
76     Adj.Q.sublat.m = conf.sublat_bound;
77 
78     {
79 
80     /* Try strategies for adopting the sieving range */
81 
82     int should_discard = !Adj.sieve_info_adjust_IJ();
83 
84     if (should_discard) {
85         if (never_discard) {
86             Adj.set_minimum_J_anyway();
87         } else {
88             verbose_output_vfprint(0, 1, gmp_vfprintf,
89                     "# "
90                     HILIGHT_START
91                     "Discarding side-%d q=%Zd; rho=%Zd;"
92                     HILIGHT_END
93                     " a0=%" PRId64
94                     "; b0=%" PRId64
95                     "; a1=%" PRId64
96                     "; b1=%" PRId64
97                     "; raw_J=%u;\n",
98                     doing.side,
99                     (mpz_srcptr) doing.p,
100                     (mpz_srcptr) doing.r,
101                     Adj.Q.a0, Adj.Q.b0, Adj.Q.a1, Adj.Q.b1, Adj.J);
102             return false;
103         }
104     }
105 
106     /* With adjust_strategy == 2, we want to display the other
107      * values, too. Also, strategy 0 wants strategy 1 to run first.
108      */
109     if (adjust_strategy != 1)
110         Adj.sieve_info_update_norm_data_Jmax();
111 
112     if (adjust_strategy >= 2)
113         Adj.adjust_with_estimated_yield();
114 
115     if (adjust_strategy >= 3) {
116         /* Let's change that again. We tell the code to keep logI as
117          * it is currently. */
118         Adj.sieve_info_update_norm_data_Jmax(true);
119     }
120 
121     /* check whether J is too small after the adjustments */
122     if (Adj.J < Adj.get_minimum_J())
123     {
124         if (never_discard) {
125             Adj.set_minimum_J_anyway();
126         } else {
127             verbose_output_vfprint(0, 1, gmp_vfprintf,
128                     "# "
129                     HILIGHT_START
130                     "Discarding side-%d q=%Zd; rho=%Zd;"
131                     HILIGHT_END,
132                     doing.side,
133                     (mpz_srcptr) doing.p,
134                     (mpz_srcptr) doing.r);
135             verbose_output_print(0, 1,
136                     " a0=%" PRId64
137                     "; b0=%" PRId64
138                     "; a1=%" PRId64
139                     "; b1=%" PRId64
140                     "; raw_J=%u;\n",
141                     Adj.Q.a0, Adj.Q.b0, Adj.Q.a1, Adj.Q.b1, Adj.J);
142             return false;
143         }
144     }
145 
146     /* At this point we've decided on a new configuration for the
147      * siever.
148      */
149     conf.logI = Adj.logI;
150     Q = Adj.Q;
151     J = Adj.J;
152 
153     }
154 
155     return true;
156 }
157 
choose_sieve_area(las_info const & las,std::shared_ptr<nfs_aux> aux_p,las_todo_entry const & doing,siever_config & conf,qlattice_basis & Q,uint32_t & J)158 bool choose_sieve_area(las_info const & las,
159         std::shared_ptr<nfs_aux> aux_p,
160         las_todo_entry const & doing,
161         siever_config & conf,
162         qlattice_basis & Q,
163         uint32_t & J)
164 {
165     timetree_t & timer(aux_p->rt.timer);
166     return choose_sieve_area(las, &timer, doing, conf, Q, J);
167 }
168 
choose_sieve_area(las_info const & las,las_todo_entry const & doing,siever_config & conf,qlattice_basis & Q,uint32_t & J)169 bool choose_sieve_area(las_info const & las,
170         las_todo_entry const & doing,
171         siever_config & conf,
172         qlattice_basis & Q,
173         uint32_t & J)
174 {
175     return choose_sieve_area(las, nullptr, doing, conf, Q, J);
176 }
177 
178