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