-
Notifications
You must be signed in to change notification settings - Fork 4
/
headers.h
369 lines (335 loc) · 10.7 KB
/
headers.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
#ifndef FAC_HEADERS
#define FAC_HEADERS
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include <stdint.h>
#include <inttypes.h>
#include <assert.h>
#include <unistd.h>
#include <sys/time.h>
// Quadratic sieve integers.
typedef uint32_t qs_sm; // small size, like a factor base prime number (32-bit)
typedef uint64_t qs_md; // medium size, like a factor base prime number squared (64-bit)
typedef int64_t qs_tmp; // signed type to perform intermediates computations
// 64-bit factorization integers.
typedef unsigned long long int u64;
// 64-bit factorization structure
typedef struct {
qs_md prime;
int power;
} fac64_row;
// Factorization manager's structure
typedef struct {
struct {
int verbose;
qs_md force;
qs_md help;
struct {
qs_md custom;
qs_md seed;
} rand;
qs_md generate[3];
qs_md timeout;
char *input_file;
char *output_file;
char output_format;
qs_md qs_multiplier;
qs_md qs_base_size;
qs_md qs_sieve;
qs_md qs_error_bits;
qs_md qs_threshold;
qs_md qs_alloc_mb;
qs_md qs_large_prime;
qs_md qs_poly;
qs_md qs_laziness;
} params;
qs_md duration_ms ;
FILE *in;
FILE *out;
int code;
struct {
size_t row_idx;
size_t total_rows;
size_t max_factors;
size_t max_digits;
size_t max_bits;
} scale;
struct {
cint num;
cint tmp[10];
cint_sheet *sheet;
qs_md trial_start;
qs_md duration_ms;
int power;
char *input_string;
char *output_string;
struct {
cint num;
int power;
int prime;
} *res;
struct {
void *base;
void *now;
} mem;
} session;
} state;
// Quadratic sieve structures
struct qs_relation {
qs_sm id; // definitive relations have a non-zero id.
cint *X;
struct {
qs_sm *data;
qs_sm length;
} Y;
union {
struct {
qs_sm *data;
qs_sm length;
} Z;
struct qs_relation *next;
} axis;
// axis :
// - "Z" field is used by definitive relations.
// - "next" is used by data that wait to be paired, it uses a linked list instead of a "Z" field.
};
typedef struct {
// computation sheet
cint_sheet *sheet;
// numbers that are updated
struct {
cint N;
cint FACTOR;
cint X;
cint KEY;
cint VALUE;
cint CYCLE;
cint TEMP[5];
cint MY[5]; // available for developers
} vars;
// polynomial vars
struct {
cint A;
cint B;
cint C;
cint D;
qs_sm d_bits;
qs_sm offset;
struct {
qs_sm x_1;
qs_sm half ;
qs_sm x_2 ;
qs_sm x_3 ;
} span;
qs_sm gray_max;
qs_sm curves;
} poly;
// constants
struct {
cint kN;
cint ONE;
cint TOO_LARGE_PRIME;
cint MULTIPLIER;
cint M_HALF;
} constants;
// system
struct {
qs_sm bytes_allocated;
void *base;
void *now;
} mem;
// parameters and miscellaneous vars
struct{
qs_md start;
qs_md end;
qs_md now;
qs_sm tick;
char remaining[127];
} time;
qs_md seed;
qs_md adjustor;
qs_sm multiplier;
qs_sm n_bits;
qs_sm kn_bits;
struct {
uint8_t **positions[2];
uint8_t *sieve;
uint8_t *flags;
qs_sm length;
qs_sm length_half;
qs_sm cache_size;
} m;
qs_sm iterative_list[5];
qs_sm error_bits;
struct {
qs_sm value;
} threshold;
qs_sm sieve_again_perms;
// useful data sharing same length
struct {
struct {
qs_sm num;
qs_sm size;
qs_sm sqrt_kN_mod_prime;
qs_sm root[2];
} *data;
qs_sm largest;
qs_sm length;
} base;
// useful data sharing same length
struct {
qs_sm *A_indexes;
struct {
cint B_terms;
qs_sm *A_inv_double_value_B_terms;
qs_sm A_over_prime_mod_prime;
qs_sm prime_index;
qs_md prime_squared;
} *data;
struct {
qs_sm defined;
qs_sm subtract_one;
qs_sm double_value;
} values;
} s;
qs_sm *buffer[2]; // proportional to "length of factor base" (medium or large)
// uniqueness trees : [ relations, cycle finder, divisors of N, ]
struct avl_manager uniqueness[3];
// data collection made by algorithm
struct {
struct qs_relation **data;
struct {
qs_sm prev;
qs_sm now;
qs_sm peak;
qs_sm needs;
qs_sm capacity;
qs_sm by_partial;
} length;
qs_md too_large_prime;
} relations;
// pointers to the divisors of N are kept in a flat array
struct {
qs_sm processing_index;
qs_sm total_primes;
qs_sm length;
cint **data;
} divisors;
// Lanczos has its own struct
struct {
qs_sm safe_length;
struct {
struct qs_relation *relation;
qs_sm y_length;
} *snapshot;
} lanczos;
state *state;
} qs_sheet;
// Factorization manager and file i/o utilities.
static void print_help(const char *);
static inline int cli_param_match(const char *, const char *, const char *);
static inline qs_md get_num(char *);
static int read_key_value(char **, state *);
static int read_flags(char **, state *);
static void generate_input_file(state *state);
static void output_csv(state *, int, int);
static void output_default(state *, int, int);
static void output_json_compact(state *, int, int);
static void output_json_pretty_print(state *, int, int);
static inline void display_progress(const char *, double);
static inline void output(state *);
static int validate_input_file(state *state);
static size_t prepare_file_descriptors(state *);
static int validate_string_number(const char *, state *);
// Misc utilities (including the factorization manager).
static inline void simple_inline_cint(cint *, size_t, void **);
static inline void simple_dup_cint(cint *, const cint *, void **);
static inline void simple_int_to_cint(cint *, qs_md);
static inline qs_md simple_cint_to_int(const cint *);
static struct avl_node *avl_cint_inserter(void *, const void *);
static inline void *mem_aligned(void *);
static qs_md get_time_ms();
static void prepare_sessions(state *state);
static void erase_session(state *state);
static void clear_sessions(state *state);
static void manager_add_factor(state *state, cint *num, int pow, int is_prime);
static inline void manager_add_simple_factor(state *state, qs_md num, int pow, int is_prime);
static void factorization_64_bits(state *);
static int factorization_trial_division(state *, int, int);
static int factorization_any_root_checker(state *, const cint *, cint *, cint *);
static int factorization_perfect_power_checker(state *, int);
static int factorization_prime_number_checker(state *, int);
static int factorization_give_up(state *, int);
static void factor(state *);
static void process_single(state *);
static void process_multi(int, char **, state *);
// Math functions and system utilities.
static qs_md xor_random(qs_md *);
static inline qs_md xor_rand(qs_md *, qs_md, qs_md);
static int is_prime_4669913(qs_sm);
static double log_computation(double);
static inline qs_sm multiplication_modulo(qs_md, qs_md, qs_sm);
static inline qs_sm power_modulo(qs_md, qs_md, qs_sm);
static int kronecker_symbol(qs_sm, qs_sm);
static qs_sm tonelli_shanks(qs_sm, qs_sm);
static qs_sm modular_inverse(qs_sm, qs_sm);
// 64-bit factorization.
static u64 mul_mod(u64, u64, u64);
static u64 pow_mod(u64, u64, u64);
static int is_prime_64_bits(u64);
static u64 pollard_rho(u64, uint64_t *);
static u64 nth_root(u64, u64);
static inline u64 square_extraction(u64 *, int *);
static void fac_64_worker(state *, u64, fac64_row *);
// Quadratic sieve.
static int factorization_quadratic_sieve(state *, int);
static int inner_continuation_condition(qs_sheet *);
static int outer_continuation_condition(qs_sheet *);
static void qs_parametrize(qs_sheet *);
static qs_sm linear_param_resolution(const double [][2], qs_sm);
static void preparation_part_1(qs_sheet *, state *, int);
static void preparation_part_2(qs_sheet *);
static void preparation_part_3(qs_sheet *);
static void preparation_part_3_default_proposition(qs_sheet *qs, qs_sm *, size_t);
static void preparation_part_3_alternative_proposition(qs_sheet *qs, qs_sm *, size_t);
static void preparation_part_4(qs_sheet *);
static void preparation_part_5(qs_sheet *);
static void preparation_part_6(qs_sheet *);
static void get_started_iteration(qs_sheet *);
static void iteration_part_1(qs_sheet *, const cint *, cint *);
static void iteration_part_2(qs_sheet *, const cint *, cint *);
static void iteration_part_3(qs_sheet *, const cint *, const cint *);
static qs_sm iteration_part_4(const qs_sheet *, qs_sm, qs_sm **, cint *);
static void iteration_part_5(qs_sheet *, const cint *, const cint *);
static void iteration_part_6(qs_sheet *, const cint *, const cint *, const cint *, cint *);
static void iteration_part_7(qs_sheet *, qs_sm, const qs_sm *restrict);
static void iteration_part_8(qs_sheet *, qs_sm, const qs_sm *);
static int qs_register_divisor(qs_sheet *qs);
static void register_relations(qs_sheet *, const cint *, const cint *, const cint *);
static void register_regular_relation(qs_sheet *, const cint *, const qs_sm *const restrict[4]);
static void register_partial_relation(qs_sheet *, const cint *, const cint *, const qs_sm *const restrict[4]);
static void finalization_part_1(qs_sheet *, const uint64_t *restrict);
static int finalization_part_2(qs_sheet *);
// Linear algebra with Block Lanczos algorithm.
static void lanczos_mul_MxN_Nx64(const qs_sheet *, const uint64_t *, qs_sm, uint64_t *);
static void lanczos_mul_trans_MxN_Nx64(const qs_sheet *, const uint64_t *, uint64_t *);
static void lanczos_mul_64xN_Nx64(const qs_sheet *, const uint64_t *, const uint64_t *, uint64_t *, uint64_t *);
static uint64_t lanczos_find_non_singular_sub(const uint64_t *, const uint64_t *, uint64_t *, uint64_t, uint64_t *);
static void lanczos_mul_Nx64_64x64_acc(qs_sheet *, const uint64_t *, const uint64_t *, uint64_t *, uint64_t *);
static void lanczos_mul_64x64_64x64(const uint64_t *, const uint64_t *, uint64_t *);
static void lanczos_transpose_vector(qs_sheet *, const uint64_t *, uint64_t **);
static void lanczos_combine_cols(qs_sheet *, uint64_t *, uint64_t *, uint64_t *, uint64_t *);
static void lanczos_build_array(qs_sheet *, uint64_t **, size_t, size_t);
static uint64_t *lanczos_block_worker(qs_sheet *);
static void lanczos_reduce_matrix(qs_sheet *);
static uint64_t *lanczos_block(qs_sheet *);
// Verbose Level 0: Just need a factorization of N, no debug messages.
// Verbose Level 1: Also print the factorization progress in percentage.
// Verbose Level 2: Also show critical issues, should usually show nothing.
// Verbose Level 3: Also show detailed information, for in-depth analysis.
// Verbose Level 4: Also show intermediate mathematical values (divisors of N).
#define DEBUG_CRITICAL(fmt, ...) debug_print(qs->state, 1, fmt, __VA_ARGS__)
#define DEBUG_NORMAL(fmt, ...) debug_print(qs->state, 2, fmt, __VA_ARGS__)
#define DEBUG_MATH(fmt, ...) debug_print(qs->state, 3, fmt, __VA_ARGS__)
#endif //FAC_HEADERS