Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagelib
Path: blob/master/sage/rings/factorint.pyx
4072 views
1
r"""
2
Integer factorization functions
3
4
AUTHORS:
5
6
- Andre Apitzsch (2011-01-13): initial version
7
8
"""
9
10
#*****************************************************************************
11
# Copyright (C) 2010 AndrĂ© Apitzsch <[email protected]>
12
#
13
# Distributed under the terms of the GNU General Public License (GPL)
14
# as published by the Free Software Foundation; either version 2 of
15
# the License, or (at your option) any later version.
16
# http://www.gnu.org/licenses/
17
#*****************************************************************************
18
19
include "../libs/pari/decl.pxi"
20
include "../ext/gmp.pxi"
21
include "../ext/stdsage.pxi"
22
23
from sage.rings.integer cimport Integer
24
from sage.rings.fast_arith import prime_range
25
from sage.structure.factorization_integer import IntegerFactorization
26
from math import floor
27
28
cdef extern from "limits.h":
29
long LONG_MAX
30
31
cpdef aurifeuillian(n, m, F=None):
32
r"""
33
Return Aurifeuillian factors `F_n^\pm(m^2n)`
34
35
INPUT:
36
37
- ``n`` - integer
38
- ``m`` - integer
39
- ``F`` - integer (default: None)
40
41
OUTPUT:
42
43
List of factors
44
45
EXAMPLES:
46
47
sage: from sage.rings.factorint import aurifeuillian
48
sage: aurifeuillian(2,2)
49
[5, 13]
50
sage: aurifeuillian(2,2^5)
51
[1985, 2113]
52
sage: aurifeuillian(5,3)
53
[1471, 2851]
54
sage: aurifeuillian(15,1)
55
[19231, 142111]
56
sage: aurifeuillian(12,3)
57
Traceback (most recent call last):
58
...
59
ValueError: n has to be square-free
60
sage: aurifeuillian(1,2)
61
Traceback (most recent call last):
62
...
63
ValueError: n has to be greater than 1
64
sage: aurifeuillian(2,0)
65
Traceback (most recent call last):
66
...
67
ValueError: m has to be positive
68
69
.. NOTE::
70
71
There is no need to set `F`. It's only for increasing speed
72
of factor_aurifeuillian().
73
74
REFERENCES:
75
76
.. Brent, On computing factors of cyclotomic polynomials, Theorem 3
77
arXiv:1004.5466v1 [math.NT]
78
79
"""
80
from sage.rings.arith import euler_phi, kronecker_symbol
81
from sage.functions.log import exp
82
from sage.rings.real_mpfr import RealField
83
if not n.is_squarefree():
84
raise ValueError, "n has to be square-free"
85
if n < 2:
86
raise ValueError, "n has to be greater than 1"
87
if m < 1:
88
raise ValueError, "m has to be positive"
89
x = m**2*n
90
y = euler_phi(2*n)//2
91
if F == None:
92
from sage.misc.functional import cyclotomic_polynomial
93
if n%2:
94
if n%4 == 3:
95
s = -1
96
else:
97
s = 1
98
F = cyclotomic_polynomial(n)(s*x)
99
else:
100
F = (-1)**euler_phi(n//2)*cyclotomic_polynomial(n//2)(-x**2)
101
tmp = sum([kronecker_symbol(n,2*j+1)/((2*j+1)*x**j) for j in range(y)])
102
R = RealField(300)
103
Fm = R(F.sqrt()*R(-1/m*tmp).exp()).round()
104
return [Fm, Integer(round(F//Fm))]
105
106
cpdef base_exponent(n):
107
r"""
108
Returns base and prime exponent of `n` if `n` is power.
109
Otherwise return `n, 1`.
110
111
INPUT:
112
113
- ``n`` - integer
114
115
OUTPUT:
116
117
- ``base, exp`` - where ``n = base^exp`` and ``exp`` is prime or 1
118
119
EXAMPLES:
120
sage: from sage.rings.factorint import base_exponent
121
sage: base_exponent(101**29)
122
(101, 29)
123
sage: base_exponent(0)
124
(0, 1)
125
sage: base_exponent(-4)
126
(-4, 1)
127
sage: base_exponent(-27)
128
(-3, 3)
129
"""
130
if n != 0:
131
for p in prime_range(2 if n > 0 else 3,int(abs(n).log(2)+1)):
132
tmp = n.nth_root(p,truncate_mode=1)
133
if tmp[1]:
134
return tmp[0], p
135
return n,1
136
137
cpdef factor_aurifeuillian(n):
138
r"""
139
Return Aurifeuillian factors of `n` if `n = x^{(2k-1)x} \pw 1`
140
(where the sign is '-' if x = 1 mod 4, and '+' otherwise) else `n`
141
142
INPUT:
143
144
- ``n`` - integer
145
146
OUTPUT:
147
148
List of factors of `n` found by Aurifeuillian factorization.
149
150
EXAMPLES:
151
152
sage: from sage.rings.factorint import factor_aurifeuillian as fa
153
sage: fa(2^6+1)
154
[5, 13]
155
sage: fa(2^58+1)
156
[536838145, 536903681]
157
sage: fa(3^3+1)
158
[4, 1, 7]
159
sage: fa(5^5-1)
160
[4, 11, 71]
161
sage: prod(_) == 5^5-1
162
True
163
sage: fa(2^4+1)
164
[17]
165
166
REFERENCES:
167
168
.. http://mathworld.wolfram.com/AurifeuilleanFactorization.html
169
170
"""
171
if n in [-2, -1, 0, 1, 2]:
172
return [n]
173
cdef int exp = 1
174
for x in [-1, 1]:
175
b = n + x
176
while b.is_power():
177
tmp = base_exponent(b)
178
b = tmp[0]
179
exp *= tmp[1]
180
if exp > 1:
181
if not b.is_prime():
182
continue
183
m = b**((exp+b)/(2*b)-1)
184
if m != floor(m):
185
continue
186
if b == 2:
187
if x == -1:
188
return aurifeuillian(b, m, n)
189
else:
190
return [2**(exp/2)-1, 2**(exp/2)+1]
191
F = b**(exp/b)-x
192
result = [F] + aurifeuillian(b, m, n/F)
193
prod = 1
194
for a in result:
195
prod *= a
196
if prod == n:
197
return result
198
return [n]
199
200
def factor_cunningham(m, proof=None):
201
r"""
202
Return factorization of self obtained using trial division
203
for all primes in the so called Cunningham table. This is
204
efficient if self has some factors of type $b^n+1$ or $b^n-1$,
205
with $b$ in $\{2,3,5,6,7,10,11,12\}$.
206
207
You need to install an optional package to use this method,
208
this can be done with the following command line:
209
``sage -i cunningham_tables-1.0``
210
211
INPUT:
212
213
- ``proof`` - bool (default: None) whether or not to
214
prove primality of each factor, this is only for factors
215
not in the Cunningham table.
216
217
EXAMPLES::
218
219
sage: (2^257-1)._factor_cunningham() # optional - cunningham
220
535006138814359 * 1155685395246619182673033 * 374550598501810936581776630096313181393
221
sage: ((3^101+1)*(2^60).next_prime())._factor_cunningham(proof=False) # optional - cunningham
222
2^2 * 379963 * 1152921504606847009 * 1017291527198723292208309354658785077827527
223
224
"""
225
from sage.databases import cunningham_tables
226
cunningham_prime_factors = cunningham_tables.cunningham_prime_factors()
227
if m.nbits() < 100 or len(cunningham_prime_factors) == 0:
228
return m.factor(proof=proof)
229
n = Integer(m)
230
L = []
231
for p in cunningham_prime_factors:
232
if p > n:
233
break
234
if p.divides(n):
235
v,n = n.val_unit(p)
236
L.append( (p,v) )
237
if n.is_one():
238
return IntegerFactorization(L)
239
else:
240
return IntegerFactorization(L)*n.factor(proof=proof)
241
242
cpdef factor_trial_division(m, long limit=LONG_MAX):
243
r"""
244
Return partial factorization of self obtained using trial division
245
for all primes up to limit, where limit must fit in a C signed long.
246
247
INPUT:
248
249
- ``limit`` - integer (default: LONG_MAX) that fits in a C signed long
250
251
EXAMPLES::
252
253
sage: from sage.rings.factorint import factor_trial_division
254
sage: n = 920384092842390423848290348203948092384082349082
255
sage: factor_trial_division(n, 1000)
256
2 * 11 * 41835640583745019265831379463815822381094652231
257
sage: factor_trial_division(n, 2000)
258
2 * 11 * 1531 * 27325696005058797691594630609938486205809701
259
"""
260
cdef Integer n = PY_NEW(Integer), unit = PY_NEW(Integer), p
261
cdef unsigned long e
262
263
n = Integer(m)
264
if mpz_sgn(n.value) > 0:
265
mpz_set_si(unit.value, 1)
266
else:
267
mpz_neg(n.value,n.value)
268
mpz_set_si(unit.value, -1)
269
270
F = []
271
while mpz_cmpabs_ui(n.value, 1):
272
p = n.trial_division(bound=limit)
273
e = mpz_remove(n.value, n.value, p.value)
274
F.append((p,e))
275
276
return IntegerFactorization(F, unit=unit, unsafe=True,
277
sort=False, simplify=False)
278
279
cpdef factor_using_pari(n, int_=False, debug_level=0, proof=None):
280
r"""
281
Factors this (positive) integer using PARI.
282
283
This method returns a list of pairs, not a ``Factorization``
284
object. The first element of each pair is the factor, of type
285
``Integer`` if ``int_`` is ``False`` or ``int`` otherwise,
286
the second element is the positive exponent, of type ``int``.
287
288
INPUT:
289
290
- ``int_`` -- (default: ``False``), whether the factors are
291
of type ``int`` instead of ``Integer``
292
293
- ``debug_level`` -- (default: 0), debug level of the call
294
to PARI
295
296
- ``proof`` -- (default: ``None``), whether the factors are
297
required to be proven prime; if ``None``, the global default
298
is used
299
300
OUTPUT:
301
302
- a list of pairs
303
304
EXAMPLES::
305
306
sage: factor(-2**72 + 3, algorithm='pari') # indirect doctest
307
-1 * 83 * 131 * 294971519 * 1472414939
308
"""
309
from sage.libs.pari.gen import pari
310
311
if proof is None:
312
from sage.structure.proof.proof import get_flag
313
proof = get_flag(proof, "arithmetic")
314
315
prev = pari.get_debug_level()
316
317
if prev != debug_level:
318
pari.set_debug_level(debug_level)
319
320
F = pari(n).factor(proof=proof)
321
B, e = F
322
if int_:
323
v = [(int(B[i]), int(e[i])) for i in xrange(len(B))]
324
else:
325
v = [(Integer(B[i]), int(e[i])) for i in xrange(len(B))]
326
327
if prev != debug_level:
328
pari.set_debug_level(prev)
329
330
return v
331
332