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