Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagelib
Path: blob/master/sage/rings/fast_arith.pyx
4072 views
1
"""
2
Basic arithmetic with c-integers.
3
"""
4
5
#*****************************************************************************
6
# Copyright (C) 2004 William Stein <[email protected]>
7
#
8
# Distributed under the terms of the GNU General Public License (GPL)
9
#
10
# This code is distributed in the hope that it will be useful,
11
# but WITHOUT ANY WARRANTY; without even the implied warranty of
12
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
# General Public License for more details.
14
#
15
# The full text of the GPL is available at:
16
#
17
# http://www.gnu.org/licenses/
18
#*****************************************************************************
19
20
21
###################################################################
22
# We define the following functions in this file, both
23
# for int (up to bound = 2**31 - 1) and longlong (up to 2**63 - 1).
24
# The function definitions are identical except for the types.
25
# Some of their input can be at most sqrt(bound), since
26
# it is necessary to multiply numbers and reduce the product
27
# modulo n, where n is at most bound.
28
#
29
# * abs_int -- absolute value of integer
30
# * sign_int -- sign of integer
31
# * c_gcd_int -- gcd of two ints
32
# * gcd_int -- python export of c_gcd_int
33
# * c_xgcd_int -- extended gcd of two ints
34
# * c_inverse_mod_int -- inverse of an int modulo another int
35
# * c_rational_recon_int -- rational reconstruction of ints
36
# * rational_recon_int -- export of rational reconstruction for ints
37
#
38
# The long long functions are the same, except they end in _longlong.
39
#
40
###################################################################
41
42
# The int definitions
43
44
include "../ext/gmp.pxi"
45
include "../ext/stdsage.pxi"
46
include "../libs/pari/decl.pxi"
47
48
cdef extern from "pari/pari.h":
49
cdef long NEXT_PRIME_VIADIFF(long, unsigned char*)
50
51
from sage.rings.integer_ring import ZZ
52
from sage.libs.pari.gen import pari
53
from sage.libs.pari.gen cimport gen as pari_gen
54
from sage.rings.integer cimport Integer
55
56
cpdef prime_range(start, stop=None, algorithm="pari_primes", bint py_ints=False):
57
r"""
58
List of all primes between start and stop-1, inclusive. If the
59
second argument is omitted, returns the primes up to the first
60
argument.
61
62
This function is closely related to (and can use) the primes iterator.
63
Use algorithm "pari_primes" when both start and stop are not too large,
64
since in all cases this function makes a table of primes up to
65
stop. If both are large, use algorithm "pari_isprime" instead.
66
67
Algorithm "pari_primes" is faster for most input, but crashes for larger input.
68
Algorithm "pari_isprime" is slower but will work for much larger input.
69
70
INPUT:
71
72
- ``start`` -- lower bound
73
74
- ``stop`` -- upper bound
75
76
- ``algorithm`` -- string, one of:
77
78
- "pari_primes": Uses PARI's primes function. Generates all primes up to stop.
79
Depends on PARI's primepi function.
80
81
- "pari_isprime": Uses a mod 2 wheel and PARI's isprime function by calling
82
the primes iterator.
83
84
- ``py_ints`` -- boolean (default False), return Python ints rather than Sage Integers (faster)
85
86
87
EXAMPLES:
88
sage: prime_range(10)
89
[2, 3, 5, 7]
90
sage: prime_range(7)
91
[2, 3, 5]
92
sage: prime_range(2000,2020)
93
[2003, 2011, 2017]
94
sage: prime_range(2,2)
95
[]
96
sage: prime_range(2,3)
97
[2]
98
sage: prime_range(5,10)
99
[5, 7]
100
sage: prime_range(-100,10,"pari_isprime")
101
[2, 3, 5, 7]
102
sage: prime_range(2,2,algorithm="pari_isprime")
103
[]
104
sage: prime_range(10**16,10**16+100,"pari_isprime")
105
[10000000000000061, 10000000000000069, 10000000000000079, 10000000000000099]
106
sage: prime_range(10**30,10**30+100,"pari_isprime")
107
[1000000000000000000000000000057, 1000000000000000000000000000099]
108
sage: type(prime_range(8)[0])
109
<type 'sage.rings.integer.Integer'>
110
sage: type(prime_range(8,algorithm="pari_isprime")[0])
111
<type 'sage.rings.integer.Integer'>
112
113
TESTS:
114
sage: len(prime_range(25000,2500000))
115
180310
116
sage: prime_range(2500000)[-1].is_prime()
117
True
118
119
AUTHORS:
120
- William Stein (original version)
121
- Craig Citro (rewrote for massive speedup)
122
- Kevin Stueve (added primes iterator option) 2010-10-16
123
- Robert Bradshaw (speedup using Pari prime table, py_ints option)
124
"""
125
cdef Integer z
126
cdef long c_start, c_stop, p
127
cdef unsigned char* pari_prime_ptr
128
if algorithm == "pari_primes":
129
if stop is None:
130
# In this case, "start" is really stop
131
c_start = 1
132
c_stop = start
133
else:
134
c_start = start
135
c_stop = stop
136
if c_stop <= c_start:
137
return []
138
if c_start < 1:
139
c_start = 1
140
if maxprime() < c_stop:
141
pari.init_primes(c_stop)
142
pari_prime_ptr = <unsigned char*>diffptr
143
p = 0
144
res = []
145
while p < c_start:
146
NEXT_PRIME_VIADIFF(p, pari_prime_ptr)
147
while p < c_stop:
148
if py_ints:
149
res.append(p)
150
else:
151
z = <Integer>PY_NEW(Integer)
152
mpz_set_ui(z.value, p)
153
res.append(z)
154
NEXT_PRIME_VIADIFF(p, pari_prime_ptr)
155
156
elif algorithm == "pari_isprime":
157
from sage.rings.arith import primes
158
res = list(primes(start, stop))
159
else:
160
raise ValueError("algorithm argument must be either ``pari_primes`` or ``pari_isprime``")
161
return res
162
163
cdef class arith_int:
164
cdef public int abs_int(self, int x) except -1:
165
if x < 0:
166
return -x
167
return x
168
169
cdef public int sign_int(self, int n) except -2:
170
if n < 0:
171
return -1
172
return 1
173
174
cdef public int c_gcd_int(self, int a, int b) except -1:
175
cdef int c
176
if a==0:
177
return self.abs_int(b)
178
if b==0:
179
return self.abs_int(a)
180
if a<0: a=-a
181
if b<0: b=-b
182
while(b):
183
c = a % b
184
a = b
185
b = c
186
return a
187
188
189
def gcd_int(self, int a, int b):
190
return self.c_gcd_int(a,b)
191
192
193
cdef public int c_xgcd_int(self, int a, int b, int* ss, int* tt) except -1:
194
cdef int psign, qsign, p, q, r, s, c, quot, new_r, new_s
195
196
if a == 0:
197
ss[0] = 0
198
tt[0] = self.sign_int(b)
199
return self.abs_int(b)
200
201
if b == 0:
202
ss[0] = self.sign_int(a)
203
tt[0] = 0
204
return self.abs_int(a)
205
206
psign = 1; qsign = 1
207
208
if a<0: a = -a; psign = -1
209
if b<0: b = -b; qsign = -1
210
211
p = 1; q = 0; r = 0; s = 1
212
while (b):
213
c = a % b; quot = a/b
214
a = b; b = c
215
new_r = p - quot*r
216
new_s = q - quot*s
217
p = r; q = s
218
r = new_r; s = new_s
219
220
ss[0] = p*psign
221
tt[0] = q*qsign
222
223
return a
224
225
def xgcd_int(self, int a, int b):
226
cdef int g, s, t
227
g = self.c_xgcd_int(a,b, &s, &t)
228
return (g,s,t)
229
230
cdef public int c_inverse_mod_int(self, int a, int m) except -1:
231
if a == 1 or m<=1: return a%m # common special case
232
cdef int g, s, t
233
g = self.c_xgcd_int(a,m, &s, &t)
234
if g != 1:
235
raise ArithmeticError, "The inverse of %s modulo %s is not defined."%(a,m)
236
s = s % m
237
if s < 0:
238
s = s + m
239
return s
240
241
242
def inverse_mod_int(self, int a, int m):
243
return self.c_inverse_mod_int(a, m)
244
245
cdef int c_rational_recon_int(self, int a, int m, int* n, int* d) except -1:
246
cdef int u, v, u0, u1, u2, v0, v1, v2, q, t0, t1, t2, x, y
247
cdef float bnd
248
249
if m>46340:
250
raise OverflowError, "The modulus m(=%s) should be at most 46340"%m
251
return -1
252
253
a = a % m
254
255
if a==0 or m == 0:
256
n[0] = 0
257
d[0] = 1
258
return 0
259
260
if m<0: m = -m
261
if a<0: a = m - a
262
if a==1:
263
n[0] = 1
264
d[0] = 1
265
return 0
266
267
u = m
268
v = a
269
bnd = sqrt(m/2.0)
270
u0=1; u1=0; u2=u
271
v0=0; v1=1; v2=v
272
while self.abs_int(v2) > bnd:
273
q = u2/v2 # floor is implicit
274
t0=u0-q*v0; t1=u1-q*v1; t2=u2-q*v2
275
u0=v0; u1=v1; u2=v2
276
v0=t0; v1=t1; v2=t2;
277
278
x = self.abs_int(v1); y = v2
279
if v1<0: y = -1*y
280
if x<=bnd and self.c_gcd_int(x,y)==1:
281
n[0] = y
282
d[0] = x
283
return 0
284
285
n[0] = 0
286
d[0] = 0
287
return 0
288
289
def rational_recon_int(self, int a, int m):
290
"""
291
Rational reconstruction of a modulo m.
292
"""
293
cdef int n, d
294
self.c_rational_recon_int(a, m, &n, &d)
295
return (n,d)
296
297
298
# The long long versions are next.
299
cdef class arith_llong:
300
301
cdef public long long abs_longlong(self, long long x) except -1:
302
if x < 0:
303
return -x
304
return x
305
306
cdef public long long sign_longlong(self, long long n) except -2:
307
if n < 0:
308
return -1
309
return 1
310
311
cdef public long long c_gcd_longlong(self, long long a, long long b) except -1:
312
cdef long long c
313
if a==0:
314
return self.abs_longlong(b)
315
if b==0:
316
return self.abs_longlong(a)
317
if a<0: a=-a
318
if b<0: b=-b
319
while(b):
320
c = a % b
321
a = b
322
b = c
323
return a
324
325
326
def gcd_longlong(self, long long a, long long b):
327
return self.c_gcd_longlong(a,b)
328
329
330
cdef public long long c_xgcd_longlong(self, long long a, long long b,
331
long long *ss,
332
long long *tt) except -1:
333
cdef long long psign, qsign, p, q, r, s, c, quot, new_r, new_s
334
335
336
if a == 0:
337
ss[0] = 0
338
tt[0] = self.sign_longlong(b)
339
return self.abs_longlong(b)
340
341
if b == 0:
342
ss[0] = self.sign_longlong(a)
343
tt[0] = 0
344
return self.abs_longlong(a)
345
346
psign = 1; qsign = 1
347
348
if a<0: a = -a; psign = -1
349
if b<0: b = -b; qsign = -1
350
351
p = 1; q = 0; r = 0; s = 1
352
while (b):
353
c = a % b; quot = a/b
354
a = b; b = c
355
new_r = p - quot*r
356
new_s = q - quot*s
357
p = r; q = s
358
r = new_r; s = new_s
359
360
ss[0] = p*psign
361
tt[0] = q*qsign
362
363
364
return a
365
366
cdef public long long c_inverse_mod_longlong(self, long long a, long long m) except -1:
367
cdef long long g, s, t
368
g = self.c_xgcd_longlong(a,m, &s, &t)
369
if g != 1:
370
raise ArithmeticError("The inverse of %s modulo %s is not defined."%(a,m))
371
s = s % m
372
if s < 0:
373
s = s + m
374
return s
375
376
def inverse_mod_longlong(self, long long a, long long m):
377
return self.c_inverse_mod_longlong(a, m)
378
379
cdef long long c_rational_recon_longlong(self, long long a, long long m,
380
long long *n, long long *d) except -1:
381
cdef long long u, v, u0, u1, u2, v0, v1, v2, q, t0, t1, t2, x, y
382
cdef float bnd
383
384
if m > 2147483647:
385
raise OverflowError, "The modulus m(=%s) must be at most 2147483647"%m
386
return -1
387
388
a = a % m
389
390
if a==0 or m == 0:
391
n[0] = 0
392
d[0] = 1
393
return 0
394
395
if m<0: m = -m
396
if a<0: a = m - a
397
if a==1:
398
n[0] = 1
399
d[0] = 1
400
return 0
401
402
u = m
403
v = a
404
bnd = sqrt(m/2.0)
405
u0=1; u1=0; u2=u
406
v0=0; v1=1; v2=v
407
while self.abs_longlong(v2) > bnd:
408
q = u2/v2 # floor is implicit
409
t0=u0-q*v0; t1=u1-q*v1; t2=u2-q*v2
410
u0=v0; u1=v1; u2=v2
411
v0=t0; v1=t1; v2=t2;
412
413
x = self.abs_longlong(v1); y = v2
414
if v1<0: y = -1*y
415
if x<=bnd and self.gcd_longlong(x,y)==1:
416
n[0] = y
417
d[0] = x
418
return 0
419
420
n[0] = 0
421
d[0] = 0
422
return 0
423
424
def rational_recon_longlong(self, long long a, long long m):
425
"""
426
Rational reconstruction of a modulo m.
427
"""
428
cdef long long n, d
429
self.c_rational_recon_longlong(a, m, &n, &d)
430
return (n,d)
431
432
433
434
435
436