Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Download
241818 views
1
#ifndef _MPZUTIL_INCLUDE_
2
#define _MPZUTIL_INCLUDE_
3
4
/*
5
Copyright 2007 Andrew V. Sutherland
6
7
This file is part of smalljac.
8
9
smalljac is free software: you can redistribute it and/or modify
10
it under the terms of the GNU General Public License as published by
11
the Free Software Foundation, either version 2 of the License, or
12
(at your option) any later version.
13
14
smalljac is distributed in the hope that it will be useful,
15
but WITHOUT ANY WARRANTY; without even the implied warranty of
16
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17
GNU General Public License for more details.
18
19
You should have received a copy of the GNU General Public License
20
along with smalljac. If not, see <http://www.gnu.org/licenses/>.
21
*/
22
23
// This module is a grab-bag of stuff, a lot of which has nothing to do with
24
// GMP's multi-precision integer arithmetic (mpz). This module should be split up and refined
25
26
// Much of this code is not used by smalljac
27
28
#include "asm.h"
29
#include "gmp.h"
30
31
#define MPZ_E 2.7182818284590452353602874713527
32
#define MPZ_SQRT2 1.41421356237309504880168872421
33
#define MPZ_LN2 0.69314718055994530941723212145818
34
#define MPZ_PI 3.1415926535897932384626433832795
35
36
#define ULONG_BITS (8*sizeof(unsigned long))
37
#define ULONG_BITS_LOG2 (4+(sizeof(unsigned long)/4)) // this only works for 16, 32, and 64 bit word sizes
38
39
#define MPZ_SMALL_PRIMES 6542
40
#define MPZ_MAX_SMALL_PRIME 65521
41
#define MPZ_MAX_SMALL_INTEGER 0xFFFF
42
#define MPZ_MAX_SMALL_COMPOSITE (1<<20)
43
#define MPZ_MIN_CUBE 0x100000000000UL // lower bound on cube of a prime > MPZ_MAX_SMALL_PRIME
44
#define MPZ_MAX_ENUM_PRIME (0xFFFFFFFF)
45
#define MPZ_MAX_ENUM_PRIME_LOG2 31 // floor(log2(MPZ_MAX_ENUM_PRIME))
46
47
#define MPZ_MAX_PRIMORIAL_W 15
48
#define MPZ_SMALL_PRIMORIAL_W 6 // P_6 = 2*3*5*7*11*13 = 30030
49
#define MPZ_SMALL_PRIMORIAL (2*3*5*7*11*13) // must be less than MPZ_MAX_SMALL_INTEGER
50
#define MPZ_SIEVE_LIMIT (MPZ_MAX_SMALL_INTEGER*MPZ_MAX_SMALL_INTEGER)
51
#define MPZ_MAX_WHEEL_W 9 // needs 200 mb map to construct a wheel this large
52
53
#define MPZ_MAX_TREE_FACTORS 100
54
#define MPZ_MAX_INVERTS 200
55
#define MPZ_MAX_SMALL_FACTORS 256
56
57
#define MPZ_MAX_UI_PP_FACTORS 20
58
#define MAX_UI_PP_FACTORS MPZ_MAX_UI_PP_FACTORS // more sensible name
59
#define MPZ_MAX_FACTORS 64 // we could be a bit more generous here
60
61
#define log2(x) (log(x)/MPZ_LN2)
62
static inline int mod (int n, int m) { n %= m; return ( n<0 ? (m + n) : n ); }
63
static inline int modl (long n, long m) { n %= m; return ( n<0 ? (m + n) : n ); }
64
65
struct wheel_struct {
66
unsigned long n;
67
unsigned long phi;
68
unsigned char *gaps;
69
unsigned maxgap;
70
};
71
typedef struct wheel_struct wheel_t;
72
73
struct prime_enum_ctx_struct {
74
unsigned L;
75
unsigned r[MPZ_MAX_ENUM_PRIME_LOG2+1];
76
unsigned h;
77
unsigned w;
78
unsigned *wi;
79
unsigned *wv;
80
unsigned p;
81
unsigned pi;
82
unsigned j;
83
unsigned start;
84
wheel_t *wheel;
85
unsigned char *map;
86
unsigned char *mp;
87
int powers;
88
};
89
typedef struct prime_enum_ctx_struct prime_enum_ctx_t;
90
91
struct factor_tree_item_struct {
92
int w;
93
mpz_t factors[MPZ_MAX_TREE_FACTORS]; // list of prime power factors
94
struct factor_tree_item_struct *subtrees[MPZ_MAX_TREE_FACTORS]; // subtrees factor p_i - 1 where p_i is the base of the ith pp factor
95
};
96
97
typedef struct factor_tree_item_struct *mpz_ftree_t;
98
99
#define _ui_ceil_ratio(a,b) (((a)%(b)) ? (a)/(b)+1 : (a)/(b))
100
#define _ui_max(a,b) ((a)>(b)?(a):(b))
101
#define _ui_min(a,b) ((a)>(b)?(b):(a))
102
103
#define i_sgn_c(x) ((x)<0?'-':'+')
104
#define i_abs(x) ((x)<0?-(x):(x))
105
106
#define mpz_get_i(z) (((long)mpz_get_ui(z))*mpz_sgn(z))
107
#define mylround(x) ((long)floor((x)+0.5)) // assumes x is positive - workaround problem with builtin lround function
108
109
void mpz_util_init();
110
111
int mpz_eval_expr (mpz_t o, char *expr);
112
void mpz_mulm (mpz_t o, mpz_t a, mpz_t b, mpz_t m);
113
void mpz_powm_tiny (mpz_t o, mpz_t b, unsigned e, mpz_t m);
114
void mpz_powm_big (mpz_t o, mpz_t b, mpz_t e, mpz_t m);
115
void mpz_addm (mpz_t o, mpz_t a, mpz_t b, mpz_t m);
116
void mpz_subm (mpz_t o, mpz_t a, mpz_t b, mpz_t m);
117
void mpz_subm_ui (mpz_t o, mpz_t a, unsigned long b, mpz_t m);
118
void mpz_negm (mpz_t a, mpz_t m);
119
void mpz_set_i (mpz_t o, long n);
120
void mpq_set_i (mpq_t o, long n);
121
void mpz_parallel_invert (mpz_t o[], mpz_t a[], unsigned n, mpz_t p);
122
int mpz_eval_term_ui (mpz_t o, unsigned long numvars, unsigned long vars[], unsigned long exps[]);
123
char *ui_term_to_string (char *buf, unsigned long numvars, unsigned long vars[], unsigned long exps[]);
124
125
int mpz_sqrt_modprime (mpz_t o, mpz_t a, mpz_t p);
126
int mpz_factor_small (unsigned long p[], unsigned long h[], mpz_t bigp, mpz_t n, int max_factors, int max_hard_bits);
127
int mpz_remove_smallsquares (mpz_t o, mpz_t n);
128
int mpz_coarse_part (mpz_t o, mpz_t x, mpz_t y);
129
void mpz_mul_set (mpz_t o, mpz_t *a, unsigned long n); // note overwrites array specified by a
130
int mpz_prime_mult (mpz_t o, mpz_t p, mpz_t maxp, unsigned long maxbits);
131
void mpz_power_primorial (mpz_t o, unsigned long L);
132
int mpz_compatible (mpz_t a, mpz_t b);
133
134
wheel_t *primorial_wheel_alloc (int w);
135
void primorial_wheel_free (wheel_t *pwheel);
136
137
prime_enum_ctx_t *fast_prime_enum_start (unsigned start, unsigned L, int powers);
138
unsigned fast_prime_enum (prime_enum_ctx_t *ctx);
139
unsigned fast_prime_power_enum (prime_enum_ctx_t *ctx); // enumerates floor_p(L) by p
140
void fast_prime_enum_end (prime_enum_ctx_t *ctx);
141
142
unsigned long ui_randomm(unsigned long m);
143
unsigned long ui_randomb (unsigned long b);
144
145
unsigned long mpz_randomf (mpz_t o, mpz_t N, mpz_t factors[], unsigned long w);
146
unsigned long mpz_randomft (mpz_t o, mpz_t N, mpz_t factors[], mpz_ftree_t factor_trees[], unsigned long w);
147
mpz_ftree_t mpz_randomfp (mpz_t o, mpz_t N);
148
mpz_ftree_t mpz_randomfpp (mpz_t o, mpz_t N);
149
void mpz_clear_ftree (mpz_ftree_t t);
150
151
void mpz_randompp (mpz_t Q, mpz_t N);
152
unsigned long mpz_pp_base (mpz_t b, mpz_t q);
153
unsigned long ui_pp_base (unsigned long pp);
154
unsigned long ui_pp_div (unsigned long n, unsigned long p);
155
156
unsigned long ui_pdiff (unsigned long a, unsigned long b); // returns least p s.t. the power of p dividing a and b differ
157
int ui_factor (unsigned long p[], unsigned long h[], unsigned long n);
158
int ui_divisor_in_interval (unsigned long p[], unsigned long h[], int w, unsigned long min, unsigned long max);
159
160
int mpz_remove_small_primes (mpz_t o, mpz_t n, unsigned long exps[], unsigned long maxprimes); // returns # distinct primes removed
161
unsigned long mpz_nearprime (mpz_t n, unsigned long L);
162
163
int ui_is_small_prime (unsigned long p);
164
int ui_is_prime (unsigned long p);
165
unsigned long ui_small_prime (unsigned long n); // returns the nth prime for 0 < n <= MPZ_SMALL_PRIMES (2 is the 1st prime)
166
unsigned long ui_small_prime_index (unsigned long p); // returns pi(n) for n <= MPZ_MAX_SMALL_INTEGER
167
unsigned long ui_primorial (int w); // returns the P_w = the w_th primorial or 0 if P_w > ULONG_MAX
168
unsigned long ui_primorial_phi (int w); // returns the phi(P_w) or 0 if P_w > ULONG_MAX
169
unsigned long ui_pi_bound (unsigned long n); // returns a guaranteed upper bound on pi(n)
170
unsigned long ui_phi (unsigned long n); // returns \phi(n) = |Z/nZ|^*
171
int ui_sqrt(long n); // returns -1 for non square input
172
173
unsigned long mpz_get_bits_ui (mpz_t a, unsigned long i, unsigned long n); // gets bits i thru i+n-1 and returns as ui
174
unsigned long mpz_set_bits_ui (mpz_t a, unsigned long i, unsigned long n, unsigned long bits); // sets bits i thru i+n-1 and returns as ui
175
double mpz_log2 (mpz_t a); // approximation guarunteed to be between floor(lg(a)) and lg(a)
176
177
void mpz_reset_counters ();
178
void mpz_report_counters ();
179
180
void mpz_sort (mpz_t a[], unsigned long n);
181
182
unsigned long ui_inverse (unsigned long a, unsigned long m); // returns the multiplicative inverse of a mod m
183
unsigned long ui_gcd (unsigned long a, unsigned long b);
184
unsigned long ui_gcd_ext (unsigned long a, unsigned long b, long *x, long *y);
185
unsigned long ui_crt (unsigned long a, unsigned long M, unsigned long b, unsigned long N); // returns x cong a%M and cong b%N with 0<=x<M*N, assumes gcd(M,N)=1
186
unsigned long bach_gcd (long a, long b, unsigned long N);
187
int ui_compatible (unsigned long a, unsigned long b);
188
189
int ui_qsort_cmp (const void *a, const void *b);
190
unsigned long ui_wt (unsigned long x); // number of bits in binary rep of x
191
unsigned long ui_lg_ceil (unsigned long x); // ceil(lg(x))
192
#define ui_lg_floor(x) _asm_highbit(x) // floor(lg(x))
193
unsigned long ui_binexp_cost (unsigned long x);
194
unsigned long ui_get_bits (unsigned long x, unsigned long pos, unsigned long bits);
195
char *ui_bit_string (char *buf, unsigned long x);
196
197
unsigned long mpz_store_bytes (mpz_t a);
198
void mpz_store (char *s, mpz_t a);
199
void mpz_retrieve (mpz_t o, char *s);
200
201
// counts multiples of k in [Min,Max] - assumes that the least multiple of k greater than Max fits in an unsigned long (this will be true if k and Max are both less than U
202
static inline unsigned long ui_multiples_in_range (unsigned long k, unsigned long Min, unsigned long Max)
203
{
204
register unsigned long a, b;
205
206
a = _ui_ceil_ratio (Min, k)*k; // least multiple of k >= Min
207
b = (Max/k)*k; // greatest multiple of k <= Max
208
if ( b < a ) return 0; // we could avoid this using signed arithmetic (and probably should, but we could have overflow problems if Max won't fit in a long)
209
return (b-a)/k + 1;
210
}
211
212
static inline unsigned long ui_trim (unsigned long x) { while ( x & 0x1 ) x << 1; return x; }
213
static inline unsigned ui_len (unsigned long x) { register unsigned i; for ( i = 0 ; x ; i++ ) x >>= 1; return i; }
214
unsigned long ui_eval_expr (char *expr);
215
216
typedef struct NAF_entry_struct {
217
char digit;
218
char c;
219
} NAF_entry_t;
220
221
extern NAF_entry_t ui_NAF_table[2][4];
222
223
void ui_NAF (unsigned long *pbits, unsigned long *nbits, unsigned long n);
224
225
static inline int ui_NAF_byte (unsigned char *pbits, unsigned char *nbits, unsigned long n, int c)
226
{
227
register int i,j,k;
228
register unsigned char pb, nb;
229
230
pb=nb=0;
231
for ( i = 0 ; i < 8 ; i++ ) { j=n&3; k=ui_NAF_table[c][j].digit; if ( k>0 ) pb|=(1<<i); if ( k < 0 ) nb|=(1<<i); c = ui_NAF_table[c][j].c; n>>=1; }
232
*pbits = pb; *nbits=nb;
233
return c;
234
}
235
236
static inline long atol_expr(char *expr)
237
{
238
register char *s;
239
long i,b,n,N;
240
241
for ( s = expr ; *s && *s != 'e' && *s != 'E' ; s++ );
242
if ( *s ) { *s++; N = b = atol (expr); n = atol(s); for ( i = 1; i < n ; i++ ) N *= b; } else N = atol(expr);
243
return N;
244
}
245
246
#endif
247
248