1 #ifndef LAS_SIEVE_SHARED_DATA_HPP_
2 #define LAS_SIEVE_SHARED_DATA_HPP_
3 
4 #include <array>                       // for array
5 #include <map>                         // for map, swap
6 #include <memory>                      // for shared_ptr
7 #include <utility>                     // for pair
8 
9 #include "cado_poly.h"
10 #include "mpz_poly.h"
11 #include "ecm/facul.hpp"                   // for facul_strategies_t
12 #include "fb-types.h"                  // for fbprime_t
13 #include "fb.hpp"                      // for fb_factorbase, fb_factorbase::...
14 #include "las-siever-config.hpp"       // for siever_config, siever_config::...
15 #include "lock_guarded_container.hpp"  // for lock_guarded_container
16 #include "trialdiv.hpp"                // for trialdiv_data
17 #include "gmp_aux.h"
18 
19 struct j_divisibility_helper; // IWYU pragma: keep
20 struct unsieve_data; // IWYU pragma: keep
21 struct cxx_param_list;
22 
23 /*
24  * A sieve_shared_data struct is only a thin layer above the factor base. It
25  * provides the factor base, and the possibility to access some data
26  * structures that depend on the current configuration (e.g. on I).
27  *
28  * We have a singleton of this type, contained in the las_info structure.
29 
30  *
31  * It must be regarded as a (mostly) const repository from where we fetch
32  * data that is of interest to many special-q's.
33  *
34  * The data at the sieve_shared_data level should not be attached to a
35  * particular config, nor to particular q.
36  *
37  * In the multi-las context, sieve_shared_data is *shared* between the different
38  * sub-processes.
39  *
40  * TODO: at some point, the query mechanism for the cached entries will
41  * depend on the memory binding.
42  */
43 struct sieve_shared_data {
44     cxx_cado_poly cpoly;
45 
46     /* {{{ side_data */
47     struct side_data {
48         cxx_mpz_poly f;     /* handy. Alias to cpoly.pols[side] */
49 
50         /* fb depends on
51          *      cpoly
52          *      conf.sides[side].lim
53          *      conf.sides[side].powlim
54          *
55          */
56         fb_factorbase fb;
57 
no_fbsieve_shared_data::side_data58         inline bool no_fb() const { return fb.empty(); }
59 
get_factorbase_slicingsieve_shared_data::side_data60         fb_factorbase::slicing const * get_factorbase_slicing(fb_factorbase::key_type fbK) {
61             /* implemented in fb_factorbase::operator[] (fb.hpp), with
62              * locking.
63              */
64             return &fb[fbK];
65         }
66 
67 
68         /* trialdiv_data depends on
69          *      fbK.td_thresh
70          * and marginally on
71          *      fbK.thresholds[0]
72          */
73 
74         private:
75         struct equivalent_fbK_for_td {
operator ()sieve_shared_data::side_data::equivalent_fbK_for_td76             bool operator()(fb_factorbase::key_type const & a, fb_factorbase::key_type const & b) const {
77                 if (a.thresholds[0] < b.thresholds[0]) return true;
78                 if (a.thresholds[0] > b.thresholds[0]) return false;
79                 return a.td_thresh < b.td_thresh;
80             }
81         };
82         lock_guarded_container<
83             std::map<
84                 fb_factorbase::key_type,
85                 trialdiv_data,
86                 equivalent_fbK_for_td
87             >
88         > trialdiv_data_cache;
89         cxx_gmp_randstate rstate;       /* use is protected by trialdiv_data_cache.mutex() */
90         public:
91         /* in las-trialdiv.cpp */
92         trialdiv_data const * get_trialdiv_data(fb_factorbase::key_type fbK, fb_factorbase::slicing const * fbs);
93 
94         side_data(int side, cxx_cado_poly const & cpoly, cxx_param_list & pl, int nthreads = 1);
95         side_data() = default;
96         side_data(side_data &&) = default;
97         side_data& operator=(side_data &&) = default;
98     };
99 
100     /* }}} */
101 
102     side_data sides[2];
103 
104     /* Most of the member functions below which take a side argument
105      * should be members of the side_data structure instead.
106      *
107      * Note that have have only init_* functions below, no clear_*. In
108      * fact, it's mostly a misnomer, and I apologize for it. The
109      * automatic dtor will work fine for all these fields, hence there is
110      * no need for specific clear_* functions. The magic lies most of the
111      * time in the use of shared_ptr's. Maybe the init_* ones should have
112      * been named setup_* or something like this.
113      */
114 
115     /* in las-unsieve.cpp */
116     /* Data for unsieving locations where gcd(i,j) > 1 */
117     /* This gets initialized only when I is finally decided */
118     private:
119     lock_guarded_container<
120         std::map<
121             std::pair<int, int>,
122             unsieve_data
123         >
124     > us_cache;
125     public:
126     unsieve_data const * get_unsieve_data(siever_config const & conf);
127 
128     /* in las-unsieve.cpp */
129     /* Data for divisibility tests p|i in lines where p|j */
130     private:
131     lock_guarded_container<
132         std::map<
133             unsigned int,
134             j_divisibility_helper
135         >
136     > jdiv_cache;
137     public:
138     j_divisibility_helper const * get_j_divisibility_helper(int J);
139 
140     /* We use a shared_ptr only to provide the custom dtor.
141      *
142      * We have a cache because during the descent, several cofactoring
143      * strategies are possible.
144      */
145     private:
146     const char *cofactfilename;
147     lock_guarded_container<
148         std::map<
149             siever_config,
150             std::shared_ptr<facul_strategies_t>,
151             siever_config::has_same_cofactoring::comparison
152         >
153     > facul_strategies_cache;
154     public:
155     facul_strategies_t const * get_strategies(siever_config const & conf);
156 
157     ~sieve_shared_data();
158     sieve_shared_data(cxx_cado_poly const & cpoly, cxx_param_list & pl);
159     void load_factor_base(cxx_param_list & pl, int nthreads = 1);
160     // sieve_shared_data() = default;
161     sieve_shared_data(sieve_shared_data&&) = default;
162     sieve_shared_data& operator=(sieve_shared_data&&) = default;
163     static void declare_usage(cxx_param_list & pl);
164 };
165 
166 #endif	/* LAS_SIEVE_SHARED_DATA_HPP_ */
167