File indexing completed on 2026-11-07 10:15:34
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013 #ifndef QSIEVE_H
0014 #define QSIEVE_H
0015
0016 #include <stdint.h>
0017 #include "fmpz_types.h"
0018
0019 #if FLINT_USES_PTHREAD
0020 # include <pthread.h>
0021 #endif
0022
0023 #ifdef __cplusplus
0024 extern "C" {
0025 #endif
0026
0027
0028 #undef small
0029
0030 #define QS_DEBUG 0
0031
0032 #define BITS_ADJUST 25
0033
0034 #define BLOCK_SIZE (4*65536)
0035
0036 typedef struct
0037 {
0038 ulong pinv;
0039 ulong pinv2;
0040 int p;
0041 char size;
0042 } prime_t;
0043
0044 typedef struct
0045 {
0046 slong ind;
0047 slong exp;
0048 } fac_t;
0049
0050 typedef struct
0051 {
0052 slong * data;
0053 slong weight;
0054 slong orig;
0055 } la_col_t;
0056
0057
0058 typedef struct
0059 {
0060 ulong prime;
0061 ulong next;
0062 ulong count;
0063 } hash_t;
0064
0065 typedef struct
0066 {
0067 ulong lp;
0068 slong num_factors;
0069 slong small_primes;
0070 slong * small;
0071 fac_t * factor;
0072 fmpz_t Y;
0073 } relation_t;
0074
0075 typedef struct
0076 {
0077 fmpz_t B;
0078 int * soln1;
0079 int * soln2;
0080 int * posn1;
0081 int * posn2;
0082 slong * small;
0083 fac_t * factor;
0084 slong num_factors;
0085 } qs_poly_s;
0086
0087 typedef qs_poly_s qs_poly_t[1];
0088
0089 typedef struct
0090 {
0091 volatile slong index_j;
0092 #if FLINT_USES_PTHREAD
0093 pthread_mutex_t mutex;
0094 #endif
0095 thread_pool_handle * handles;
0096 slong num_handles;
0097
0098 fmpz_t n;
0099
0100 flint_bitcnt_t bits;
0101
0102 ulong ks_primes;
0103
0104 slong fb_primes;
0105
0106 ulong k;
0107 fmpz_t kn;
0108
0109 slong num_primes;
0110
0111 prime_t * factor_base;
0112
0113 int * sqrts;
0114
0115 slong small_primes;
0116 slong second_prime;
0117 slong sieve_size;
0118
0119 unsigned char sieve_bits;
0120 unsigned char sieve_fill;
0121
0122
0123
0124
0125
0126 fmpz_t A;
0127 fmpz_t B;
0128
0129 ulong * A_ind;
0130
0131 fmpz_t * A_divp;
0132
0133 ulong * B0_terms;
0134
0135
0136
0137 fmpz_t * B_terms;
0138
0139 ulong * A_inv;
0140 ulong ** A_inv2B;
0141
0142
0143 int * soln1;
0144 int * soln2;
0145
0146 fmpz_t target_A;
0147
0148 fmpz_t upp_bound;
0149 fmpz_t low_bound;
0150
0151 slong s;
0152 slong low;
0153
0154 slong high;
0155
0156 slong span;
0157
0158
0159
0160
0161
0162 slong h;
0163 slong m;
0164 slong A_ind_diff;
0165 ulong * curr_subset;
0166 ulong * first_subset;
0167 ulong j;
0168
0169 #if QS_DEBUG
0170 slong poly_count;
0171 #endif
0172
0173 qs_poly_s * poly;
0174
0175
0176
0177
0178
0179 FLINT_FILE * siqs;
0180 char * fname;
0181
0182 slong full_relation;
0183 slong num_cycles;
0184
0185 slong vertices;
0186 slong components;
0187 slong edges;
0188
0189 slong table_size;
0190 hash_t * table;
0191 ulong * hash_table;
0192
0193 slong extra_rels;
0194 slong max_factors;
0195
0196 fmpz * Y_arr;
0197 slong * curr_rel;
0198 slong * relation;
0199
0200 slong buffer_size;
0201 slong num_relations;
0202
0203 ulong small_factor;
0204
0205
0206
0207
0208
0209 la_col_t * matrix;
0210 la_col_t ** qsort_arr;
0211
0212 slong columns;
0213
0214
0215
0216
0217
0218 slong * prime_count;
0219
0220 } qs_s;
0221
0222 typedef qs_s qs_t[1];
0223
0224
0225
0226
0227
0228
0229
0230
0231
0232
0233
0234
0235 static const ulong qsieve_tune[][6] =
0236 {
0237
0238 {10, 49, 84, 4, 4300, 25},
0239 {20, 10, 120, 5, 4800, 26},
0240 {30, 14, 25, 3, 4500, 19},
0241 {40, 28, 73, 9, 5700, 24},
0242 {50, 25, 85, 7, 5400, 28},
0243 {60, 27, 100, 14, 11000, 28},
0244 {65, 26, 110, 19, 13000, 28},
0245 {70, 26, 180, 3, 12000, 43},
0246 {75, 26, 190, 4, 12000, 45},
0247 {80, 27, 190, 5, 12000, 45},
0248 {85, 28, 150, 5, 10000, 45},
0249 {90, 34, 150, 5, 10000, 45},
0250 {100, 40, 210, 6, 14000, 48},
0251 {110, 46, 220, 7, 13000, 48},
0252 {120, 50, 250, 7, 13000, 50},
0253 {130, 47, 310, 9, 16000, 50},
0254 {135, 39, 450, 10, 20000, 53},
0255 {140, 47, 580, 8, 17000, 56},
0256 {145, 47, 610, 9, 16000, 56},
0257 {150, 45, 610, 8, 17000, 59},
0258 {155, 43, 860, 10, 21000, 59},
0259
0260 {160, 150, 2000, 11, 4 * 65536, 73},
0261 {170, 150, 2000, 12, 4 * 65536, 75},
0262 {180, 150, 3000, 12, 4 * 65536, 76},
0263 {190, 150, 3000, 13, 4 * 65536, 78},
0264 {200, 200, 4500, 14, 4 * 65536, 81},
0265 {210, 100, 8000, 14, 12 * 65536, 84},
0266 {220, 300, 10000, 15, 12 * 65536, 88},
0267 {230, 400, 20000, 17, 20 * 65536, 90},
0268 {240, 450, 20000, 19, 20 * 65536, 93},
0269 {250, 500, 22000, 22, 24 * 65536, 97},
0270 {260, 600, 25000, 25, 24 * 65536, 100},
0271 {270, 800, 35000, 27, 28 * 65536, 102},
0272 {280, 900, 40000, 29, 28 * 65536, 104},
0273 {290, 1000, 60000, 29, 32 * 65536, 106},
0274 {300, 1100, 140000, 30, 32 * 65536, 108}
0275 };
0276
0277
0278 #define QS_TUNE_SIZE (sizeof(qsieve_tune)/(6*sizeof(ulong)))
0279
0280 void qsieve_init(qs_t qs_inf, const fmpz_t n);
0281
0282
0283
0284
0285 void qsieve_init_with_tune(qs_t qs_inf, const fmpz_t n, ulong ks_primes,
0286 slong fb_primes, slong small_primes, slong sieve_size, ulong sieve_bits);
0287
0288 ulong qsieve_knuth_schroeppel(qs_t qs_inf);
0289
0290 void qsieve_clear(qs_t qs_inf);
0291
0292 void qsieve_factor(fmpz_factor_t factors, const fmpz_t n);
0293
0294
0295 void qsieve_factor_with_tune(fmpz_factor_t factors, const fmpz_t n,
0296 ulong ks_primes, slong fb_primes, slong small_primes,
0297 slong sieve_size, ulong sieve_bits);
0298
0299 prime_t * compute_factor_base(ulong * small_factor, qs_t qs_inf,
0300 slong num_primes);
0301
0302 ulong qsieve_primes_init(qs_t qs_inf);
0303
0304 ulong qsieve_primes_increment(qs_t qs_inf, ulong delta);
0305
0306 ulong qsieve_poly_init(qs_t qs_inf);
0307
0308 int qsieve_init_A(qs_t qs_inf);
0309
0310 void qsieve_reinit_A(qs_t qs_inf);
0311
0312 int qsieve_next_A(qs_t qs_inf);
0313
0314 void qsieve_init_poly_first(qs_t qs_inf);
0315
0316 void qsieve_init_poly_next(qs_t qs_inf, slong i);
0317
0318 void qsieve_compute_C(fmpz_t C, qs_t qs_inf, qs_poly_t poly);
0319
0320 void qsieve_poly_copy(qs_poly_t poly, qs_t qs_inf);
0321
0322 void qsieve_poly_clear(qs_t qs_inf);
0323
0324 void qsieve_do_sieving(qs_t qs_inf, unsigned char * sieve, qs_poly_t poly);
0325
0326 void qsieve_do_sieving2(qs_t qs_inf, unsigned char * sieve, qs_poly_t poly);
0327
0328 slong qsieve_evaluate_candidate(qs_t qs_inf, ulong i, unsigned char * sieve, qs_poly_t poly);
0329
0330 slong qsieve_evaluate_sieve(qs_t qs_inf, unsigned char * sieve, qs_poly_t poly);
0331
0332 slong qsieve_collect_relations(qs_t qs_inf, unsigned char * sieve);
0333
0334 void qsieve_linalg_init(qs_t qs_inf);
0335
0336 void qsieve_linalg_realloc(qs_t qs_inf);
0337
0338 void qsieve_linalg_clear(qs_t qs_inf);
0339
0340 int qsieve_relations_cmp(const void * a, const void * b);
0341
0342 slong qsieve_merge_relations(qs_t qs_inf);
0343
0344 void qsieve_write_to_file(qs_t qs_inf, ulong prime,
0345 const fmpz_t Y, const qs_poly_t poly);
0346
0347 hash_t * qsieve_get_table_entry(qs_t qs_inf, ulong prime);
0348
0349 void qsieve_add_to_hashtable(qs_t qs_inf, ulong prime);
0350
0351 relation_t qsieve_parse_relation(qs_t qs_inf);
0352
0353 relation_t qsieve_merge_relation(qs_t qs_inf, relation_t a, relation_t b);
0354
0355 int qsieve_compare_relation(const void * a, const void * b);
0356
0357 int qsieve_remove_duplicates(relation_t * rel_list, slong num_relations);
0358
0359 void qsieve_insert_relation(qs_t qs_inf, relation_t * rel_list,
0360 slong num_relations);
0361
0362 int qsieve_process_relation(qs_t qs_inf);
0363
0364 static inline void insert_col_entry(la_col_t * col, slong entry)
0365 {
0366 if (((col->weight >> 4) << 4) == col->weight)
0367 {
0368 if (col->weight != 0) col->data =
0369 (slong *) flint_realloc(col->data, (col->weight + 16)*sizeof(slong));
0370 else col->data = (slong *) flint_malloc(16*sizeof(slong));
0371 }
0372
0373 col->data[col->weight] = entry;
0374 col->weight++;
0375 }
0376
0377 static inline void swap_cols(la_col_t * col2, la_col_t * col1)
0378 {
0379 la_col_t temp;
0380
0381 temp.weight = col1->weight;
0382 temp.data = col1->data;
0383 temp.orig = col1->orig;
0384
0385 col1->weight = col2->weight;
0386 col1->data = col2->data;
0387 col1->orig = col2->orig;
0388
0389 col2->weight = temp.weight;
0390 col2->data = temp.data;
0391 col2->orig = temp.orig;
0392 }
0393
0394 static inline void clear_col(la_col_t * col)
0395 {
0396 col->weight = 0;
0397 }
0398
0399 static inline void free_col(la_col_t * col)
0400 {
0401 if (col->weight) flint_free(col->data);
0402 }
0403
0404 uint64_t get_null_entry(uint64_t * nullrows, slong i, slong l);
0405
0406 void reduce_matrix(qs_t qs_inf, slong *nrows, slong *ncols, la_col_t *cols);
0407
0408 uint64_t * block_lanczos(flint_rand_t state, slong nrows,
0409 slong dense_rows, slong ncols, la_col_t *B);
0410
0411 void qsieve_square_root(fmpz_t X, fmpz_t Y, qs_t qs_inf,
0412 uint64_t * nullrows, slong ncols, slong l, fmpz_t N);
0413
0414 #ifdef __cplusplus
0415 }
0416 #endif
0417
0418 #endif