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