ZhengyangZhang commited on
Commit
aa5c86b
·
verified ·
1 Parent(s): b260509

Add files using upload-large-folder tool

Browse files
Files changed (50) hide show
  1. lib/python3.12/site-packages/sympy/liealgebras/__pycache__/__init__.cpython-312.pyc +0 -0
  2. lib/python3.12/site-packages/sympy/liealgebras/__pycache__/cartan_matrix.cpython-312.pyc +0 -0
  3. lib/python3.12/site-packages/sympy/liealgebras/__pycache__/cartan_type.cpython-312.pyc +0 -0
  4. lib/python3.12/site-packages/sympy/liealgebras/__pycache__/dynkin_diagram.cpython-312.pyc +0 -0
  5. lib/python3.12/site-packages/sympy/liealgebras/__pycache__/root_system.cpython-312.pyc +0 -0
  6. lib/python3.12/site-packages/sympy/liealgebras/__pycache__/type_a.cpython-312.pyc +0 -0
  7. lib/python3.12/site-packages/sympy/liealgebras/__pycache__/type_b.cpython-312.pyc +0 -0
  8. lib/python3.12/site-packages/sympy/liealgebras/__pycache__/type_c.cpython-312.pyc +0 -0
  9. lib/python3.12/site-packages/sympy/liealgebras/__pycache__/type_d.cpython-312.pyc +0 -0
  10. lib/python3.12/site-packages/sympy/liealgebras/__pycache__/type_e.cpython-312.pyc +0 -0
  11. lib/python3.12/site-packages/sympy/liealgebras/__pycache__/type_f.cpython-312.pyc +0 -0
  12. lib/python3.12/site-packages/sympy/liealgebras/__pycache__/type_g.cpython-312.pyc +0 -0
  13. lib/python3.12/site-packages/sympy/liealgebras/__pycache__/weyl_group.cpython-312.pyc +0 -0
  14. lib/python3.12/site-packages/sympy/liealgebras/tests/__pycache__/__init__.cpython-312.pyc +0 -0
  15. lib/python3.12/site-packages/sympy/liealgebras/tests/__pycache__/test_cartan_matrix.cpython-312.pyc +0 -0
  16. lib/python3.12/site-packages/sympy/liealgebras/tests/__pycache__/test_cartan_type.cpython-312.pyc +0 -0
  17. lib/python3.12/site-packages/sympy/liealgebras/tests/__pycache__/test_dynkin_diagram.cpython-312.pyc +0 -0
  18. lib/python3.12/site-packages/sympy/liealgebras/tests/__pycache__/test_root_system.cpython-312.pyc +0 -0
  19. lib/python3.12/site-packages/sympy/liealgebras/tests/__pycache__/test_type_A.cpython-312.pyc +0 -0
  20. lib/python3.12/site-packages/sympy/liealgebras/tests/__pycache__/test_type_B.cpython-312.pyc +0 -0
  21. lib/python3.12/site-packages/sympy/liealgebras/tests/__pycache__/test_type_C.cpython-312.pyc +0 -0
  22. lib/python3.12/site-packages/sympy/liealgebras/tests/__pycache__/test_type_D.cpython-312.pyc +0 -0
  23. lib/python3.12/site-packages/sympy/liealgebras/tests/__pycache__/test_type_E.cpython-312.pyc +0 -0
  24. lib/python3.12/site-packages/sympy/liealgebras/tests/__pycache__/test_type_F.cpython-312.pyc +0 -0
  25. lib/python3.12/site-packages/sympy/liealgebras/tests/__pycache__/test_type_G.cpython-312.pyc +0 -0
  26. lib/python3.12/site-packages/sympy/ntheory/__init__.py +67 -0
  27. lib/python3.12/site-packages/sympy/ntheory/bbp_pi.py +190 -0
  28. lib/python3.12/site-packages/sympy/ntheory/continued_fraction.py +369 -0
  29. lib/python3.12/site-packages/sympy/ntheory/digits.py +150 -0
  30. lib/python3.12/site-packages/sympy/ntheory/ecm.py +345 -0
  31. lib/python3.12/site-packages/sympy/ntheory/egyptian_fraction.py +223 -0
  32. lib/python3.12/site-packages/sympy/ntheory/elliptic_curve.py +397 -0
  33. lib/python3.12/site-packages/sympy/ntheory/factor_.py +2668 -0
  34. lib/python3.12/site-packages/sympy/ntheory/generate.py +1147 -0
  35. lib/python3.12/site-packages/sympy/ntheory/modular.py +291 -0
  36. lib/python3.12/site-packages/sympy/ntheory/multinomial.py +188 -0
  37. lib/python3.12/site-packages/sympy/ntheory/partitions_.py +278 -0
  38. lib/python3.12/site-packages/sympy/ntheory/primetest.py +793 -0
  39. lib/python3.12/site-packages/sympy/ntheory/qs.py +511 -0
  40. lib/python3.12/site-packages/sympy/ntheory/residue_ntheory.py +1954 -0
  41. lib/python3.12/site-packages/sympy/ntheory/tests/__init__.py +0 -0
  42. lib/python3.12/site-packages/sympy/ntheory/tests/test_bbp_pi.py +134 -0
  43. lib/python3.12/site-packages/sympy/ntheory/tests/test_continued_fraction.py +77 -0
  44. lib/python3.12/site-packages/sympy/ntheory/tests/test_digits.py +55 -0
  45. lib/python3.12/site-packages/sympy/ntheory/tests/test_egyptian_fraction.py +49 -0
  46. lib/python3.12/site-packages/sympy/ntheory/tests/test_generate.py +285 -0
  47. lib/python3.12/site-packages/sympy/ntheory/tests/test_hypothesis.py +24 -0
  48. lib/python3.12/site-packages/sympy/ntheory/tests/test_partitions.py +27 -0
  49. lib/python3.12/site-packages/sympy/ntheory/tests/test_primetest.py +230 -0
  50. lib/python3.12/site-packages/sympy/ntheory/tests/test_qs.py +124 -0
lib/python3.12/site-packages/sympy/liealgebras/__pycache__/__init__.cpython-312.pyc ADDED
Binary file (290 Bytes). View file
 
lib/python3.12/site-packages/sympy/liealgebras/__pycache__/cartan_matrix.cpython-312.pyc ADDED
Binary file (857 Bytes). View file
 
lib/python3.12/site-packages/sympy/liealgebras/__pycache__/cartan_type.cpython-312.pyc ADDED
Binary file (2.96 kB). View file
 
lib/python3.12/site-packages/sympy/liealgebras/__pycache__/dynkin_diagram.cpython-312.pyc ADDED
Binary file (869 Bytes). View file
 
lib/python3.12/site-packages/sympy/liealgebras/__pycache__/root_system.cpython-312.pyc ADDED
Binary file (8.72 kB). View file
 
lib/python3.12/site-packages/sympy/liealgebras/__pycache__/type_a.cpython-312.pyc ADDED
Binary file (6.64 kB). View file
 
lib/python3.12/site-packages/sympy/liealgebras/__pycache__/type_b.cpython-312.pyc ADDED
Binary file (6.77 kB). View file
 
lib/python3.12/site-packages/sympy/liealgebras/__pycache__/type_c.cpython-312.pyc ADDED
Binary file (6.64 kB). View file
 
lib/python3.12/site-packages/sympy/liealgebras/__pycache__/type_d.cpython-312.pyc ADDED
Binary file (7.09 kB). View file
 
lib/python3.12/site-packages/sympy/liealgebras/__pycache__/type_e.cpython-312.pyc ADDED
Binary file (10.8 kB). View file
 
lib/python3.12/site-packages/sympy/liealgebras/__pycache__/type_f.cpython-312.pyc ADDED
Binary file (6.3 kB). View file
 
lib/python3.12/site-packages/sympy/liealgebras/__pycache__/type_g.cpython-312.pyc ADDED
Binary file (4.02 kB). View file
 
lib/python3.12/site-packages/sympy/liealgebras/__pycache__/weyl_group.cpython-312.pyc ADDED
Binary file (18.5 kB). View file
 
lib/python3.12/site-packages/sympy/liealgebras/tests/__pycache__/__init__.cpython-312.pyc ADDED
Binary file (202 Bytes). View file
 
lib/python3.12/site-packages/sympy/liealgebras/tests/__pycache__/test_cartan_matrix.cpython-312.pyc ADDED
Binary file (756 Bytes). View file
 
lib/python3.12/site-packages/sympy/liealgebras/tests/__pycache__/test_cartan_type.cpython-312.pyc ADDED
Binary file (905 Bytes). View file
 
lib/python3.12/site-packages/sympy/liealgebras/tests/__pycache__/test_dynkin_diagram.cpython-312.pyc ADDED
Binary file (613 Bytes). View file
 
lib/python3.12/site-packages/sympy/liealgebras/tests/__pycache__/test_root_system.cpython-312.pyc ADDED
Binary file (1.85 kB). View file
 
lib/python3.12/site-packages/sympy/liealgebras/tests/__pycache__/test_type_A.cpython-312.pyc ADDED
Binary file (1.55 kB). View file
 
lib/python3.12/site-packages/sympy/liealgebras/tests/__pycache__/test_type_B.cpython-312.pyc ADDED
Binary file (1.51 kB). View file
 
lib/python3.12/site-packages/sympy/liealgebras/tests/__pycache__/test_type_C.cpython-312.pyc ADDED
Binary file (2.15 kB). View file
 
lib/python3.12/site-packages/sympy/liealgebras/tests/__pycache__/test_type_D.cpython-312.pyc ADDED
Binary file (1.65 kB). View file
 
lib/python3.12/site-packages/sympy/liealgebras/tests/__pycache__/test_type_E.cpython-312.pyc ADDED
Binary file (2.06 kB). View file
 
lib/python3.12/site-packages/sympy/liealgebras/tests/__pycache__/test_type_F.cpython-312.pyc ADDED
Binary file (4.07 kB). View file
 
lib/python3.12/site-packages/sympy/liealgebras/tests/__pycache__/test_type_G.cpython-312.pyc ADDED
Binary file (1.32 kB). View file
 
lib/python3.12/site-packages/sympy/ntheory/__init__.py ADDED
@@ -0,0 +1,67 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Number theory module (primes, etc)
3
+ """
4
+
5
+ from .generate import nextprime, prevprime, prime, primepi, primerange, \
6
+ randprime, Sieve, sieve, primorial, cycle_length, composite, compositepi
7
+ from .primetest import isprime, is_gaussian_prime, is_mersenne_prime
8
+ from .factor_ import divisors, proper_divisors, factorint, multiplicity, \
9
+ multiplicity_in_factorial, perfect_power, pollard_pm1, pollard_rho, \
10
+ primefactors, totient, \
11
+ divisor_count, proper_divisor_count, divisor_sigma, factorrat, \
12
+ reduced_totient, primenu, primeomega, mersenne_prime_exponent, \
13
+ is_perfect, is_abundant, is_deficient, is_amicable, is_carmichael, \
14
+ abundance, dra, drm
15
+
16
+ from .partitions_ import npartitions
17
+ from .residue_ntheory import is_primitive_root, is_quad_residue, \
18
+ legendre_symbol, jacobi_symbol, n_order, sqrt_mod, quadratic_residues, \
19
+ primitive_root, nthroot_mod, is_nthpow_residue, sqrt_mod_iter, mobius, \
20
+ discrete_log, quadratic_congruence, polynomial_congruence
21
+ from .multinomial import binomial_coefficients, binomial_coefficients_list, \
22
+ multinomial_coefficients
23
+ from .continued_fraction import continued_fraction_periodic, \
24
+ continued_fraction_iterator, continued_fraction_reduce, \
25
+ continued_fraction_convergents, continued_fraction
26
+ from .digits import count_digits, digits, is_palindromic
27
+ from .egyptian_fraction import egyptian_fraction
28
+ from .ecm import ecm
29
+ from .qs import qs
30
+ __all__ = [
31
+ 'nextprime', 'prevprime', 'prime', 'primepi', 'primerange', 'randprime',
32
+ 'Sieve', 'sieve', 'primorial', 'cycle_length', 'composite', 'compositepi',
33
+
34
+ 'isprime', 'is_gaussian_prime', 'is_mersenne_prime',
35
+
36
+
37
+ 'divisors', 'proper_divisors', 'factorint', 'multiplicity', 'perfect_power',
38
+ 'pollard_pm1', 'pollard_rho', 'primefactors', 'totient',
39
+ 'divisor_count', 'proper_divisor_count', 'divisor_sigma', 'factorrat',
40
+ 'reduced_totient', 'primenu', 'primeomega', 'mersenne_prime_exponent',
41
+ 'is_perfect', 'is_abundant', 'is_deficient', 'is_amicable',
42
+ 'is_carmichael', 'abundance', 'dra', 'drm', 'multiplicity_in_factorial',
43
+
44
+ 'npartitions',
45
+
46
+ 'is_primitive_root', 'is_quad_residue', 'legendre_symbol',
47
+ 'jacobi_symbol', 'n_order', 'sqrt_mod', 'quadratic_residues',
48
+ 'primitive_root', 'nthroot_mod', 'is_nthpow_residue', 'sqrt_mod_iter',
49
+ 'mobius', 'discrete_log', 'quadratic_congruence', 'polynomial_congruence',
50
+
51
+ 'binomial_coefficients', 'binomial_coefficients_list',
52
+ 'multinomial_coefficients',
53
+
54
+ 'continued_fraction_periodic', 'continued_fraction_iterator',
55
+ 'continued_fraction_reduce', 'continued_fraction_convergents',
56
+ 'continued_fraction',
57
+
58
+ 'digits',
59
+ 'count_digits',
60
+ 'is_palindromic',
61
+
62
+ 'egyptian_fraction',
63
+
64
+ 'ecm',
65
+
66
+ 'qs',
67
+ ]
lib/python3.12/site-packages/sympy/ntheory/bbp_pi.py ADDED
@@ -0,0 +1,190 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ '''
2
+ This implementation is a heavily modified fixed point implementation of
3
+ BBP_formula for calculating the nth position of pi. The original hosted
4
+ at: https://web.archive.org/web/20151116045029/http://en.literateprograms.org/Pi_with_the_BBP_formula_(Python)
5
+
6
+ # Permission is hereby granted, free of charge, to any person obtaining
7
+ # a copy of this software and associated documentation files (the
8
+ # "Software"), to deal in the Software without restriction, including
9
+ # without limitation the rights to use, copy, modify, merge, publish,
10
+ # distribute, sub-license, and/or sell copies of the Software, and to
11
+ # permit persons to whom the Software is furnished to do so, subject to
12
+ # the following conditions:
13
+ #
14
+ # The above copyright notice and this permission notice shall be
15
+ # included in all copies or substantial portions of the Software.
16
+ #
17
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
20
+ # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
21
+ # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
22
+ # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
23
+ # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24
+
25
+ Modifications:
26
+
27
+ 1.Once the nth digit and desired number of digits is selected, the
28
+ number of digits of working precision is calculated to ensure that
29
+ the hexadecimal digits returned are accurate. This is calculated as
30
+
31
+ int(math.log(start + prec)/math.log(16) + prec + 3)
32
+ --------------------------------------- --------
33
+ / /
34
+ number of hex digits additional digits
35
+
36
+ This was checked by the following code which completed without
37
+ errors (and dig are the digits included in the test_bbp.py file):
38
+
39
+ for i in range(0,1000):
40
+ for j in range(1,1000):
41
+ a, b = pi_hex_digits(i, j), dig[i:i+j]
42
+ if a != b:
43
+ print('%s\n%s'%(a,b))
44
+
45
+ Deceasing the additional digits by 1 generated errors, so '3' is
46
+ the smallest additional precision needed to calculate the above
47
+ loop without errors. The following trailing 10 digits were also
48
+ checked to be accurate (and the times were slightly faster with
49
+ some of the constant modifications that were made):
50
+
51
+ >> from time import time
52
+ >> t=time();pi_hex_digits(10**2-10 + 1, 10), time()-t
53
+ ('e90c6cc0ac', 0.0)
54
+ >> t=time();pi_hex_digits(10**4-10 + 1, 10), time()-t
55
+ ('26aab49ec6', 0.17100000381469727)
56
+ >> t=time();pi_hex_digits(10**5-10 + 1, 10), time()-t
57
+ ('a22673c1a5', 4.7109999656677246)
58
+ >> t=time();pi_hex_digits(10**6-10 + 1, 10), time()-t
59
+ ('9ffd342362', 59.985999822616577)
60
+ >> t=time();pi_hex_digits(10**7-10 + 1, 10), time()-t
61
+ ('c1a42e06a1', 689.51800012588501)
62
+
63
+ 2. The while loop to evaluate whether the series has converged quits
64
+ when the addition amount `dt` has dropped to zero.
65
+
66
+ 3. the formatting string to convert the decimal to hexadecimal is
67
+ calculated for the given precision.
68
+
69
+ 4. pi_hex_digits(n) changed to have coefficient to the formula in an
70
+ array (perhaps just a matter of preference).
71
+
72
+ '''
73
+
74
+ from sympy.utilities.misc import as_int
75
+
76
+
77
+ def _series(j, n, prec=14):
78
+
79
+ # Left sum from the bbp algorithm
80
+ s = 0
81
+ D = _dn(n, prec)
82
+ D4 = 4 * D
83
+ d = j
84
+ for k in range(n + 1):
85
+ s += (pow(16, n - k, d) << D4) // d
86
+ d += 8
87
+
88
+ # Right sum iterates to infinity for full precision, but we
89
+ # stop at the point where one iteration is beyond the precision
90
+ # specified.
91
+
92
+ t = 0
93
+ k = n + 1
94
+ e = D4 - 4 # 4*(D + n - k)
95
+ d = 8 * k + j
96
+ while True:
97
+ dt = (1 << e) // d
98
+ if not dt:
99
+ break
100
+ t += dt
101
+ # k += 1
102
+ e -= 4
103
+ d += 8
104
+ total = s + t
105
+
106
+ return total
107
+
108
+
109
+ def pi_hex_digits(n, prec=14):
110
+ """Returns a string containing ``prec`` (default 14) digits
111
+ starting at the nth digit of pi in hex. Counting of digits
112
+ starts at 0 and the decimal is not counted, so for n = 0 the
113
+ returned value starts with 3; n = 1 corresponds to the first
114
+ digit past the decimal point (which in hex is 2).
115
+
116
+ Parameters
117
+ ==========
118
+
119
+ n : non-negative integer
120
+ prec : non-negative integer. default = 14
121
+
122
+ Returns
123
+ =======
124
+
125
+ str : Returns a string containing ``prec`` digits
126
+ starting at the nth digit of pi in hex.
127
+ If ``prec`` = 0, returns empty string.
128
+
129
+ Raises
130
+ ======
131
+
132
+ ValueError
133
+ If ``n`` < 0 or ``prec`` < 0.
134
+ Or ``n`` or ``prec`` is not an integer.
135
+
136
+ Examples
137
+ ========
138
+
139
+ >>> from sympy.ntheory.bbp_pi import pi_hex_digits
140
+ >>> pi_hex_digits(0)
141
+ '3243f6a8885a30'
142
+ >>> pi_hex_digits(0, 3)
143
+ '324'
144
+
145
+ These are consistent with the following results
146
+
147
+ >>> import math
148
+ >>> hex(int(math.pi * 2**((14-1)*4)))
149
+ '0x3243f6a8885a30'
150
+ >>> hex(int(math.pi * 2**((3-1)*4)))
151
+ '0x324'
152
+
153
+ References
154
+ ==========
155
+
156
+ .. [1] http://www.numberworld.org/digits/Pi/
157
+ """
158
+ n, prec = as_int(n), as_int(prec)
159
+ if n < 0:
160
+ raise ValueError('n cannot be negative')
161
+ if prec < 0:
162
+ raise ValueError('prec cannot be negative')
163
+ if prec == 0:
164
+ return ''
165
+
166
+ # main of implementation arrays holding formulae coefficients
167
+ n -= 1
168
+ a = [4, 2, 1, 1]
169
+ j = [1, 4, 5, 6]
170
+
171
+ #formulae
172
+ D = _dn(n, prec)
173
+ x = + (a[0]*_series(j[0], n, prec)
174
+ - a[1]*_series(j[1], n, prec)
175
+ - a[2]*_series(j[2], n, prec)
176
+ - a[3]*_series(j[3], n, prec)) & (16**D - 1)
177
+
178
+ s = ("%0" + "%ix" % prec) % (x // 16**(D - prec))
179
+ return s
180
+
181
+
182
+ def _dn(n, prec):
183
+ # controller for n dependence on precision
184
+ # n = starting digit index
185
+ # prec = the number of total digits to compute
186
+ n += 1 # because we subtract 1 for _series
187
+
188
+ # assert int(math.log(n + prec)/math.log(16)) ==\
189
+ # ((n + prec).bit_length() - 1) // 4
190
+ return ((n + prec).bit_length() - 1) // 4 + prec + 3
lib/python3.12/site-packages/sympy/ntheory/continued_fraction.py ADDED
@@ -0,0 +1,369 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from __future__ import annotations
2
+ import itertools
3
+ from sympy.core.exprtools import factor_terms
4
+ from sympy.core.numbers import Integer, Rational
5
+ from sympy.core.singleton import S
6
+ from sympy.core.symbol import Dummy
7
+ from sympy.core.sympify import _sympify
8
+ from sympy.utilities.misc import as_int
9
+
10
+
11
+ def continued_fraction(a) -> list:
12
+ """Return the continued fraction representation of a Rational or
13
+ quadratic irrational.
14
+
15
+ Examples
16
+ ========
17
+
18
+ >>> from sympy.ntheory.continued_fraction import continued_fraction
19
+ >>> from sympy import sqrt
20
+ >>> continued_fraction((1 + 2*sqrt(3))/5)
21
+ [0, 1, [8, 3, 34, 3]]
22
+
23
+ See Also
24
+ ========
25
+ continued_fraction_periodic, continued_fraction_reduce, continued_fraction_convergents
26
+ """
27
+ e = _sympify(a)
28
+ if all(i.is_Rational for i in e.atoms()):
29
+ if e.is_Integer:
30
+ return continued_fraction_periodic(e, 1, 0)
31
+ elif e.is_Rational:
32
+ return continued_fraction_periodic(e.p, e.q, 0)
33
+ elif e.is_Pow and e.exp is S.Half and e.base.is_Integer:
34
+ return continued_fraction_periodic(0, 1, e.base)
35
+ elif e.is_Mul and len(e.args) == 2 and (
36
+ e.args[0].is_Rational and
37
+ e.args[1].is_Pow and
38
+ e.args[1].base.is_Integer and
39
+ e.args[1].exp is S.Half):
40
+ a, b = e.args
41
+ return continued_fraction_periodic(0, a.q, b.base, a.p)
42
+ else:
43
+ # this should not have to work very hard- no
44
+ # simplification, cancel, etc... which should be
45
+ # done by the user. e.g. This is a fancy 1 but
46
+ # the user should simplify it first:
47
+ # sqrt(2)*(1 + sqrt(2))/(sqrt(2) + 2)
48
+ p, d = e.expand().as_numer_denom()
49
+ if d.is_Integer:
50
+ if p.is_Rational:
51
+ return continued_fraction_periodic(p, d)
52
+ # look for a + b*c
53
+ # with c = sqrt(s)
54
+ if p.is_Add and len(p.args) == 2:
55
+ a, bc = p.args
56
+ else:
57
+ a = S.Zero
58
+ bc = p
59
+ if a.is_Integer:
60
+ b = S.NaN
61
+ if bc.is_Mul and len(bc.args) == 2:
62
+ b, c = bc.args
63
+ elif bc.is_Pow:
64
+ b = Integer(1)
65
+ c = bc
66
+ if b.is_Integer and (
67
+ c.is_Pow and c.exp is S.Half and
68
+ c.base.is_Integer):
69
+ # (a + b*sqrt(c))/d
70
+ c = c.base
71
+ return continued_fraction_periodic(a, d, c, b)
72
+ raise ValueError(
73
+ 'expecting a rational or quadratic irrational, not %s' % e)
74
+
75
+
76
+ def continued_fraction_periodic(p, q, d=0, s=1) -> list:
77
+ r"""
78
+ Find the periodic continued fraction expansion of a quadratic irrational.
79
+
80
+ Compute the continued fraction expansion of a rational or a
81
+ quadratic irrational number, i.e. `\frac{p + s\sqrt{d}}{q}`, where
82
+ `p`, `q \ne 0` and `d \ge 0` are integers.
83
+
84
+ Returns the continued fraction representation (canonical form) as
85
+ a list of integers, optionally ending (for quadratic irrationals)
86
+ with list of integers representing the repeating digits.
87
+
88
+ Parameters
89
+ ==========
90
+
91
+ p : int
92
+ the rational part of the number's numerator
93
+ q : int
94
+ the denominator of the number
95
+ d : int, optional
96
+ the irrational part (discriminator) of the number's numerator
97
+ s : int, optional
98
+ the coefficient of the irrational part
99
+
100
+ Examples
101
+ ========
102
+
103
+ >>> from sympy.ntheory.continued_fraction import continued_fraction_periodic
104
+ >>> continued_fraction_periodic(3, 2, 7)
105
+ [2, [1, 4, 1, 1]]
106
+
107
+ Golden ratio has the simplest continued fraction expansion:
108
+
109
+ >>> continued_fraction_periodic(1, 2, 5)
110
+ [[1]]
111
+
112
+ If the discriminator is zero or a perfect square then the number will be a
113
+ rational number:
114
+
115
+ >>> continued_fraction_periodic(4, 3, 0)
116
+ [1, 3]
117
+ >>> continued_fraction_periodic(4, 3, 49)
118
+ [3, 1, 2]
119
+
120
+ See Also
121
+ ========
122
+
123
+ continued_fraction_iterator, continued_fraction_reduce
124
+
125
+ References
126
+ ==========
127
+
128
+ .. [1] https://en.wikipedia.org/wiki/Periodic_continued_fraction
129
+ .. [2] K. Rosen. Elementary Number theory and its applications.
130
+ Addison-Wesley, 3 Sub edition, pages 379-381, January 1992.
131
+
132
+ """
133
+ from sympy.functions import sqrt, floor
134
+
135
+ p, q, d, s = list(map(as_int, [p, q, d, s]))
136
+
137
+ if d < 0:
138
+ raise ValueError("expected non-negative for `d` but got %s" % d)
139
+
140
+ if q == 0:
141
+ raise ValueError("The denominator cannot be 0.")
142
+
143
+ if not s:
144
+ d = 0
145
+
146
+ # check for rational case
147
+ sd = sqrt(d)
148
+ if sd.is_Integer:
149
+ return list(continued_fraction_iterator(Rational(p + s*sd, q)))
150
+
151
+ # irrational case with sd != Integer
152
+ if q < 0:
153
+ p, q, s = -p, -q, -s
154
+
155
+ n = (p + s*sd)/q
156
+ if n < 0:
157
+ w = floor(-n)
158
+ f = -n - w
159
+ one_f = continued_fraction(1 - f) # 1-f < 1 so cf is [0 ... [...]]
160
+ one_f[0] -= w + 1
161
+ return one_f
162
+
163
+ d *= s**2
164
+ sd *= s
165
+
166
+ if (d - p**2)%q:
167
+ d *= q**2
168
+ sd *= q
169
+ p *= q
170
+ q *= q
171
+
172
+ terms: list[int] = []
173
+ pq = {}
174
+
175
+ while (p, q) not in pq:
176
+ pq[(p, q)] = len(terms)
177
+ terms.append((p + sd)//q)
178
+ p = terms[-1]*q - p
179
+ q = (d - p**2)//q
180
+
181
+ i = pq[(p, q)]
182
+ return terms[:i] + [terms[i:]] # type: ignore
183
+
184
+
185
+ def continued_fraction_reduce(cf):
186
+ """
187
+ Reduce a continued fraction to a rational or quadratic irrational.
188
+
189
+ Compute the rational or quadratic irrational number from its
190
+ terminating or periodic continued fraction expansion. The
191
+ continued fraction expansion (cf) should be supplied as a
192
+ terminating iterator supplying the terms of the expansion. For
193
+ terminating continued fractions, this is equivalent to
194
+ ``list(continued_fraction_convergents(cf))[-1]``, only a little more
195
+ efficient. If the expansion has a repeating part, a list of the
196
+ repeating terms should be returned as the last element from the
197
+ iterator. This is the format returned by
198
+ continued_fraction_periodic.
199
+
200
+ For quadratic irrationals, returns the largest solution found,
201
+ which is generally the one sought, if the fraction is in canonical
202
+ form (all terms positive except possibly the first).
203
+
204
+ Examples
205
+ ========
206
+
207
+ >>> from sympy.ntheory.continued_fraction import continued_fraction_reduce
208
+ >>> continued_fraction_reduce([1, 2, 3, 4, 5])
209
+ 225/157
210
+ >>> continued_fraction_reduce([-2, 1, 9, 7, 1, 2])
211
+ -256/233
212
+ >>> continued_fraction_reduce([2, 1, 2, 1, 1, 4, 1, 1, 6, 1, 1, 8]).n(10)
213
+ 2.718281835
214
+ >>> continued_fraction_reduce([1, 4, 2, [3, 1]])
215
+ (sqrt(21) + 287)/238
216
+ >>> continued_fraction_reduce([[1]])
217
+ (1 + sqrt(5))/2
218
+ >>> from sympy.ntheory.continued_fraction import continued_fraction_periodic
219
+ >>> continued_fraction_reduce(continued_fraction_periodic(8, 5, 13))
220
+ (sqrt(13) + 8)/5
221
+
222
+ See Also
223
+ ========
224
+
225
+ continued_fraction_periodic
226
+
227
+ """
228
+ from sympy.solvers import solve
229
+
230
+ period = []
231
+ x = Dummy('x')
232
+
233
+ def untillist(cf):
234
+ for nxt in cf:
235
+ if isinstance(nxt, list):
236
+ period.extend(nxt)
237
+ yield x
238
+ break
239
+ yield nxt
240
+
241
+ a = S.Zero
242
+ for a in continued_fraction_convergents(untillist(cf)):
243
+ pass
244
+
245
+ if period:
246
+ y = Dummy('y')
247
+ solns = solve(continued_fraction_reduce(period + [y]) - y, y)
248
+ solns.sort()
249
+ pure = solns[-1]
250
+ rv = a.subs(x, pure).radsimp()
251
+ else:
252
+ rv = a
253
+ if rv.is_Add:
254
+ rv = factor_terms(rv)
255
+ if rv.is_Mul and rv.args[0] == -1:
256
+ rv = rv.func(*rv.args)
257
+ return rv
258
+
259
+
260
+ def continued_fraction_iterator(x):
261
+ """
262
+ Return continued fraction expansion of x as iterator.
263
+
264
+ Examples
265
+ ========
266
+
267
+ >>> from sympy import Rational, pi
268
+ >>> from sympy.ntheory.continued_fraction import continued_fraction_iterator
269
+
270
+ >>> list(continued_fraction_iterator(Rational(3, 8)))
271
+ [0, 2, 1, 2]
272
+ >>> list(continued_fraction_iterator(Rational(-3, 8)))
273
+ [-1, 1, 1, 1, 2]
274
+
275
+ >>> for i, v in enumerate(continued_fraction_iterator(pi)):
276
+ ... if i > 7:
277
+ ... break
278
+ ... print(v)
279
+ 3
280
+ 7
281
+ 15
282
+ 1
283
+ 292
284
+ 1
285
+ 1
286
+ 1
287
+
288
+ References
289
+ ==========
290
+
291
+ .. [1] https://en.wikipedia.org/wiki/Continued_fraction
292
+
293
+ """
294
+ from sympy.functions import floor
295
+ while True:
296
+ i = floor(x)
297
+ yield i
298
+ x -= i
299
+ if not x:
300
+ break
301
+ x = 1/x
302
+
303
+
304
+ def continued_fraction_convergents(cf):
305
+ """
306
+ Return an iterator over the convergents of a continued fraction (cf).
307
+
308
+ The parameter should be in either of the following to forms:
309
+ - A list of partial quotients, possibly with the last element being a list
310
+ of repeating partial quotients, such as might be returned by
311
+ continued_fraction and continued_fraction_periodic.
312
+ - An iterable returning successive partial quotients of the continued
313
+ fraction, such as might be returned by continued_fraction_iterator.
314
+
315
+ In computing the convergents, the continued fraction need not be strictly
316
+ in canonical form (all integers, all but the first positive).
317
+ Rational and negative elements may be present in the expansion.
318
+
319
+ Examples
320
+ ========
321
+
322
+ >>> from sympy.core import pi
323
+ >>> from sympy import S
324
+ >>> from sympy.ntheory.continued_fraction import \
325
+ continued_fraction_convergents, continued_fraction_iterator
326
+
327
+ >>> list(continued_fraction_convergents([0, 2, 1, 2]))
328
+ [0, 1/2, 1/3, 3/8]
329
+
330
+ >>> list(continued_fraction_convergents([1, S('1/2'), -7, S('1/4')]))
331
+ [1, 3, 19/5, 7]
332
+
333
+ >>> it = continued_fraction_convergents(continued_fraction_iterator(pi))
334
+ >>> for n in range(7):
335
+ ... print(next(it))
336
+ 3
337
+ 22/7
338
+ 333/106
339
+ 355/113
340
+ 103993/33102
341
+ 104348/33215
342
+ 208341/66317
343
+
344
+ >>> it = continued_fraction_convergents([1, [1, 2]]) # sqrt(3)
345
+ >>> for n in range(7):
346
+ ... print(next(it))
347
+ 1
348
+ 2
349
+ 5/3
350
+ 7/4
351
+ 19/11
352
+ 26/15
353
+ 71/41
354
+
355
+ See Also
356
+ ========
357
+
358
+ continued_fraction_iterator, continued_fraction, continued_fraction_periodic
359
+
360
+ """
361
+ if isinstance(cf, list) and isinstance(cf[-1], list):
362
+ cf = itertools.chain(cf[:-1], itertools.cycle(cf[-1]))
363
+ p_2, q_2 = S.Zero, S.One
364
+ p_1, q_1 = S.One, S.Zero
365
+ for a in cf:
366
+ p, q = a*p_1 + p_2, a*q_1 + q_2
367
+ p_2, q_2 = p_1, q_1
368
+ p_1, q_1 = p, q
369
+ yield p/q
lib/python3.12/site-packages/sympy/ntheory/digits.py ADDED
@@ -0,0 +1,150 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from collections import defaultdict
2
+
3
+ from sympy.utilities.iterables import multiset, is_palindromic as _palindromic
4
+ from sympy.utilities.misc import as_int
5
+
6
+
7
+ def digits(n, b=10, digits=None):
8
+ """
9
+ Return a list of the digits of ``n`` in base ``b``. The first
10
+ element in the list is ``b`` (or ``-b`` if ``n`` is negative).
11
+
12
+ Examples
13
+ ========
14
+
15
+ >>> from sympy.ntheory.digits import digits
16
+ >>> digits(35)
17
+ [10, 3, 5]
18
+
19
+ If the number is negative, the negative sign will be placed on the
20
+ base (which is the first element in the returned list):
21
+
22
+ >>> digits(-35)
23
+ [-10, 3, 5]
24
+
25
+ Bases other than 10 (and greater than 1) can be selected with ``b``:
26
+
27
+ >>> digits(27, b=2)
28
+ [2, 1, 1, 0, 1, 1]
29
+
30
+ Use the ``digits`` keyword if a certain number of digits is desired:
31
+
32
+ >>> digits(35, digits=4)
33
+ [10, 0, 0, 3, 5]
34
+
35
+ Parameters
36
+ ==========
37
+
38
+ n: integer
39
+ The number whose digits are returned.
40
+
41
+ b: integer
42
+ The base in which digits are computed.
43
+
44
+ digits: integer (or None for all digits)
45
+ The number of digits to be returned (padded with zeros, if
46
+ necessary).
47
+
48
+ See Also
49
+ ========
50
+ sympy.core.intfunc.num_digits, count_digits
51
+ """
52
+
53
+ b = as_int(b)
54
+ n = as_int(n)
55
+ if b < 2:
56
+ raise ValueError("b must be greater than 1")
57
+ else:
58
+ x, y = abs(n), []
59
+ while x >= b:
60
+ x, r = divmod(x, b)
61
+ y.append(r)
62
+ y.append(x)
63
+ y.append(-b if n < 0 else b)
64
+ y.reverse()
65
+ ndig = len(y) - 1
66
+ if digits is not None:
67
+ if ndig > digits:
68
+ raise ValueError(
69
+ "For %s, at least %s digits are needed." % (n, ndig))
70
+ elif ndig < digits:
71
+ y[1:1] = [0]*(digits - ndig)
72
+ return y
73
+
74
+
75
+ def count_digits(n, b=10):
76
+ """
77
+ Return a dictionary whose keys are the digits of ``n`` in the
78
+ given base, ``b``, with keys indicating the digits appearing in the
79
+ number and values indicating how many times that digit appeared.
80
+
81
+ Examples
82
+ ========
83
+
84
+ >>> from sympy.ntheory import count_digits
85
+
86
+ >>> count_digits(1111339)
87
+ {1: 4, 3: 2, 9: 1}
88
+
89
+ The digits returned are always represented in base-10
90
+ but the number itself can be entered in any format that is
91
+ understood by Python; the base of the number can also be
92
+ given if it is different than 10:
93
+
94
+ >>> n = 0xFA; n
95
+ 250
96
+ >>> count_digits(_)
97
+ {0: 1, 2: 1, 5: 1}
98
+ >>> count_digits(n, 16)
99
+ {10: 1, 15: 1}
100
+
101
+ The default dictionary will return a 0 for any digit that did
102
+ not appear in the number. For example, which digits appear 7
103
+ times in ``77!``:
104
+
105
+ >>> from sympy import factorial
106
+ >>> c77 = count_digits(factorial(77))
107
+ >>> [i for i in range(10) if c77[i] == 7]
108
+ [1, 3, 7, 9]
109
+
110
+ See Also
111
+ ========
112
+ sympy.core.intfunc.num_digits, digits
113
+ """
114
+ rv = defaultdict(int, multiset(digits(n, b)).items())
115
+ rv.pop(b) if b in rv else rv.pop(-b) # b or -b is there
116
+ return rv
117
+
118
+
119
+ def is_palindromic(n, b=10):
120
+ """return True if ``n`` is the same when read from left to right
121
+ or right to left in the given base, ``b``.
122
+
123
+ Examples
124
+ ========
125
+
126
+ >>> from sympy.ntheory import is_palindromic
127
+
128
+ >>> all(is_palindromic(i) for i in (-11, 1, 22, 121))
129
+ True
130
+
131
+ The second argument allows you to test numbers in other
132
+ bases. For example, 88 is palindromic in base-10 but not
133
+ in base-8:
134
+
135
+ >>> is_palindromic(88, 8)
136
+ False
137
+
138
+ On the other hand, a number can be palindromic in base-8 but
139
+ not in base-10:
140
+
141
+ >>> 0o121, is_palindromic(0o121)
142
+ (81, False)
143
+
144
+ Or it might be palindromic in both bases:
145
+
146
+ >>> oct(121), is_palindromic(121, 8) and is_palindromic(121)
147
+ ('0o171', True)
148
+
149
+ """
150
+ return _palindromic(digits(n, b), 1)
lib/python3.12/site-packages/sympy/ntheory/ecm.py ADDED
@@ -0,0 +1,345 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from math import log
2
+
3
+ from sympy.core.random import _randint
4
+ from sympy.external.gmpy import gcd, invert, sqrt
5
+ from sympy.utilities.misc import as_int
6
+ from .generate import sieve, primerange
7
+ from .primetest import isprime
8
+
9
+
10
+ #----------------------------------------------------------------------------#
11
+ # #
12
+ # Lenstra's Elliptic Curve Factorization #
13
+ # #
14
+ #----------------------------------------------------------------------------#
15
+
16
+
17
+ class Point:
18
+ """Montgomery form of Points in an elliptic curve.
19
+ In this form, the addition and doubling of points
20
+ does not need any y-coordinate information thus
21
+ decreasing the number of operations.
22
+ Using Montgomery form we try to perform point addition
23
+ and doubling in least amount of multiplications.
24
+
25
+ The elliptic curve used here is of the form
26
+ (E : b*y**2*z = x**3 + a*x**2*z + x*z**2).
27
+ The a_24 parameter is equal to (a + 2)/4.
28
+
29
+ References
30
+ ==========
31
+
32
+ .. [1] Kris Gaj, Soonhak Kwon, Patrick Baier, Paul Kohlbrenner, Hoang Le, Mohammed Khaleeluddin, Ramakrishna Bachimanchi,
33
+ Implementing the Elliptic Curve Method of Factoring in Reconfigurable Hardware,
34
+ Cryptographic Hardware and Embedded Systems - CHES 2006 (2006), pp. 119-133,
35
+ https://doi.org/10.1007/11894063_10
36
+ https://www.hyperelliptic.org/tanja/SHARCS/talks06/Gaj.pdf
37
+
38
+ """
39
+
40
+ def __init__(self, x_cord, z_cord, a_24, mod):
41
+ """
42
+ Initial parameters for the Point class.
43
+
44
+ Parameters
45
+ ==========
46
+
47
+ x_cord : X coordinate of the Point
48
+ z_cord : Z coordinate of the Point
49
+ a_24 : Parameter of the elliptic curve in Montgomery form
50
+ mod : modulus
51
+ """
52
+ self.x_cord = x_cord
53
+ self.z_cord = z_cord
54
+ self.a_24 = a_24
55
+ self.mod = mod
56
+
57
+ def __eq__(self, other):
58
+ """Two points are equal if X/Z of both points are equal
59
+ """
60
+ if self.a_24 != other.a_24 or self.mod != other.mod:
61
+ return False
62
+ return self.x_cord * other.z_cord % self.mod ==\
63
+ other.x_cord * self.z_cord % self.mod
64
+
65
+ def add(self, Q, diff):
66
+ """
67
+ Add two points self and Q where diff = self - Q. Moreover the assumption
68
+ is self.x_cord*Q.x_cord*(self.x_cord - Q.x_cord) != 0. This algorithm
69
+ requires 6 multiplications. Here the difference between the points
70
+ is already known and using this algorithm speeds up the addition
71
+ by reducing the number of multiplication required. Also in the
72
+ mont_ladder algorithm is constructed in a way so that the difference
73
+ between intermediate points is always equal to the initial point.
74
+ So, we always know what the difference between the point is.
75
+
76
+
77
+ Parameters
78
+ ==========
79
+
80
+ Q : point on the curve in Montgomery form
81
+ diff : self - Q
82
+
83
+ Examples
84
+ ========
85
+
86
+ >>> from sympy.ntheory.ecm import Point
87
+ >>> p1 = Point(11, 16, 7, 29)
88
+ >>> p2 = Point(13, 10, 7, 29)
89
+ >>> p3 = p2.add(p1, p1)
90
+ >>> p3.x_cord
91
+ 23
92
+ >>> p3.z_cord
93
+ 17
94
+ """
95
+ u = (self.x_cord - self.z_cord)*(Q.x_cord + Q.z_cord)
96
+ v = (self.x_cord + self.z_cord)*(Q.x_cord - Q.z_cord)
97
+ add, subt = u + v, u - v
98
+ x_cord = diff.z_cord * add * add % self.mod
99
+ z_cord = diff.x_cord * subt * subt % self.mod
100
+ return Point(x_cord, z_cord, self.a_24, self.mod)
101
+
102
+ def double(self):
103
+ """
104
+ Doubles a point in an elliptic curve in Montgomery form.
105
+ This algorithm requires 5 multiplications.
106
+
107
+ Examples
108
+ ========
109
+
110
+ >>> from sympy.ntheory.ecm import Point
111
+ >>> p1 = Point(11, 16, 7, 29)
112
+ >>> p2 = p1.double()
113
+ >>> p2.x_cord
114
+ 13
115
+ >>> p2.z_cord
116
+ 10
117
+ """
118
+ u = pow(self.x_cord + self.z_cord, 2, self.mod)
119
+ v = pow(self.x_cord - self.z_cord, 2, self.mod)
120
+ diff = u - v
121
+ x_cord = u*v % self.mod
122
+ z_cord = diff*(v + self.a_24*diff) % self.mod
123
+ return Point(x_cord, z_cord, self.a_24, self.mod)
124
+
125
+ def mont_ladder(self, k):
126
+ """
127
+ Scalar multiplication of a point in Montgomery form
128
+ using Montgomery Ladder Algorithm.
129
+ A total of 11 multiplications are required in each step of this
130
+ algorithm.
131
+
132
+ Parameters
133
+ ==========
134
+
135
+ k : The positive integer multiplier
136
+
137
+ Examples
138
+ ========
139
+
140
+ >>> from sympy.ntheory.ecm import Point
141
+ >>> p1 = Point(11, 16, 7, 29)
142
+ >>> p3 = p1.mont_ladder(3)
143
+ >>> p3.x_cord
144
+ 23
145
+ >>> p3.z_cord
146
+ 17
147
+ """
148
+ Q = self
149
+ R = self.double()
150
+ for i in bin(k)[3:]:
151
+ if i == '1':
152
+ Q = R.add(Q, self)
153
+ R = R.double()
154
+ else:
155
+ R = Q.add(R, self)
156
+ Q = Q.double()
157
+ return Q
158
+
159
+
160
+ def _ecm_one_factor(n, B1=10000, B2=100000, max_curve=200, seed=None):
161
+ """Returns one factor of n using
162
+ Lenstra's 2 Stage Elliptic curve Factorization
163
+ with Suyama's Parameterization. Here Montgomery
164
+ arithmetic is used for fast computation of addition
165
+ and doubling of points in elliptic curve.
166
+
167
+ Explanation
168
+ ===========
169
+
170
+ This ECM method considers elliptic curves in Montgomery
171
+ form (E : b*y**2*z = x**3 + a*x**2*z + x*z**2) and involves
172
+ elliptic curve operations (mod N), where the elements in
173
+ Z are reduced (mod N). Since N is not a prime, E over FF(N)
174
+ is not really an elliptic curve but we can still do point additions
175
+ and doubling as if FF(N) was a field.
176
+
177
+ Stage 1 : The basic algorithm involves taking a random point (P) on an
178
+ elliptic curve in FF(N). The compute k*P using Montgomery ladder algorithm.
179
+ Let q be an unknown factor of N. Then the order of the curve E, |E(FF(q))|,
180
+ might be a smooth number that divides k. Then we have k = l * |E(FF(q))|
181
+ for some l. For any point belonging to the curve E, |E(FF(q))|*P = O,
182
+ hence k*P = l*|E(FF(q))|*P. Thus kP.z_cord = 0 (mod q), and the unknownn
183
+ factor of N (q) can be recovered by taking gcd(kP.z_cord, N).
184
+
185
+ Stage 2 : This is a continuation of Stage 1 if k*P != O. The idea utilize
186
+ the fact that even if kP != 0, the value of k might miss just one large
187
+ prime divisor of |E(FF(q))|. In this case we only need to compute the
188
+ scalar multiplication by p to get p*k*P = O. Here a second bound B2
189
+ restrict the size of possible values of p.
190
+
191
+ Parameters
192
+ ==========
193
+
194
+ n : Number to be Factored
195
+ B1 : Stage 1 Bound. Must be an even number.
196
+ B2 : Stage 2 Bound. Must be an even number.
197
+ max_curve : Maximum number of curves generated
198
+
199
+ Returns
200
+ =======
201
+
202
+ integer | None : ``n`` (if it is prime) else a non-trivial divisor of ``n``. ``None`` if not found
203
+
204
+ References
205
+ ==========
206
+
207
+ .. [1] Carl Pomerance, Richard Crandall, Prime Numbers: A Computational Perspective,
208
+ 2nd Edition (2005), page 344, ISBN:978-0387252827
209
+ """
210
+ randint = _randint(seed)
211
+ if isprime(n):
212
+ return n
213
+
214
+ # When calculating T, if (B1 - 2*D) is negative, it cannot be calculated.
215
+ D = min(sqrt(B2), B1 // 2 - 1)
216
+ sieve.extend(D)
217
+ beta = [0] * D
218
+ S = [0] * D
219
+ k = 1
220
+ for p in primerange(2, B1 + 1):
221
+ k *= pow(p, int(log(B1, p)))
222
+
223
+ # Pre-calculate the prime numbers to be used in stage 2.
224
+ # Using the fact that the x-coordinates of point P and its
225
+ # inverse -P coincide, the number of primes to be checked
226
+ # in stage 2 can be reduced.
227
+ deltas_list = []
228
+ for r in range(B1 + 2*D, B2 + 2*D, 4*D):
229
+ deltas = set()
230
+ deltas.update((abs(q - r) - 1) // 2 for q in primerange(r - 2*D, r + 2*D))
231
+ # d in deltas iff r+(2d+1) and/or r-(2d+1) is prime
232
+ deltas_list.append(list(deltas))
233
+
234
+ for _ in range(max_curve):
235
+ #Suyama's Parametrization
236
+ sigma = randint(6, n - 1)
237
+ u = (sigma**2 - 5) % n
238
+ v = (4*sigma) % n
239
+ u_3 = pow(u, 3, n)
240
+
241
+ try:
242
+ # We use the elliptic curve y**2 = x**3 + a*x**2 + x
243
+ # where a = pow(v - u, 3, n)*(3*u + v)*invert(4*u_3*v, n) - 2
244
+ # However, we do not declare a because it is more convenient
245
+ # to use a24 = (a + 2)*invert(4, n) in the calculation.
246
+ a24 = pow(v - u, 3, n)*(3*u + v)*invert(16*u_3*v, n) % n
247
+ except ZeroDivisionError:
248
+ #If the invert(16*u_3*v, n) doesn't exist (i.e., g != 1)
249
+ g = gcd(2*u_3*v, n)
250
+ #If g = n, try another curve
251
+ if g == n:
252
+ continue
253
+ return g
254
+
255
+ Q = Point(u_3, pow(v, 3, n), a24, n)
256
+ Q = Q.mont_ladder(k)
257
+ g = gcd(Q.z_cord, n)
258
+
259
+ #Stage 1 factor
260
+ if g != 1 and g != n:
261
+ return g
262
+ #Stage 1 failure. Q.z = 0, Try another curve
263
+ elif g == n:
264
+ continue
265
+
266
+ #Stage 2 - Improved Standard Continuation
267
+ S[0] = Q
268
+ Q2 = Q.double()
269
+ S[1] = Q2.add(Q, Q)
270
+ beta[0] = (S[0].x_cord*S[0].z_cord) % n
271
+ beta[1] = (S[1].x_cord*S[1].z_cord) % n
272
+ for d in range(2, D):
273
+ S[d] = S[d - 1].add(Q2, S[d - 2])
274
+ beta[d] = (S[d].x_cord*S[d].z_cord) % n
275
+ # i.e., S[i] = Q.mont_ladder(2*i + 1)
276
+
277
+ g = 1
278
+ W = Q.mont_ladder(4*D)
279
+ T = Q.mont_ladder(B1 - 2*D)
280
+ R = Q.mont_ladder(B1 + 2*D)
281
+ for deltas in deltas_list:
282
+ # R = Q.mont_ladder(r) where r in range(B1 + 2*D, B2 + 2*D, 4*D)
283
+ alpha = (R.x_cord*R.z_cord) % n
284
+ for delta in deltas:
285
+ # We want to calculate
286
+ # f = R.x_cord * S[delta].z_cord - S[delta].x_cord * R.z_cord
287
+ f = (R.x_cord - S[delta].x_cord)*\
288
+ (R.z_cord + S[delta].z_cord) - alpha + beta[delta]
289
+ g = (g*f) % n
290
+ T, R = R, R.add(W, T)
291
+ g = gcd(n, g)
292
+
293
+ #Stage 2 Factor found
294
+ if g != 1 and g != n:
295
+ return g
296
+
297
+
298
+ def ecm(n, B1=10000, B2=100000, max_curve=200, seed=1234):
299
+ """Performs factorization using Lenstra's Elliptic curve method.
300
+
301
+ This function repeatedly calls ``_ecm_one_factor`` to compute the factors
302
+ of n. First all the small factors are taken out using trial division.
303
+ Then ``_ecm_one_factor`` is used to compute one factor at a time.
304
+
305
+ Parameters
306
+ ==========
307
+
308
+ n : Number to be Factored
309
+ B1 : Stage 1 Bound. Must be an even number.
310
+ B2 : Stage 2 Bound. Must be an even number.
311
+ max_curve : Maximum number of curves generated
312
+ seed : Initialize pseudorandom generator
313
+
314
+ Examples
315
+ ========
316
+
317
+ >>> from sympy.ntheory import ecm
318
+ >>> ecm(25645121643901801)
319
+ {5394769, 4753701529}
320
+ >>> ecm(9804659461513846513)
321
+ {4641991, 2112166839943}
322
+ """
323
+ n = as_int(n)
324
+ if B1 % 2 != 0 or B2 % 2 != 0:
325
+ raise ValueError("both bounds must be even")
326
+ _factors = set()
327
+ for prime in sieve.primerange(1, 100000):
328
+ if n % prime == 0:
329
+ _factors.add(prime)
330
+ while(n % prime == 0):
331
+ n //= prime
332
+ while(n > 1):
333
+ factor = _ecm_one_factor(n, B1, B2, max_curve, seed)
334
+ if factor is None:
335
+ raise ValueError("Increase the bounds")
336
+ _factors.add(factor)
337
+ n //= factor
338
+
339
+ factors = set()
340
+ for factor in _factors:
341
+ if isprime(factor):
342
+ factors.add(factor)
343
+ continue
344
+ factors |= ecm(factor)
345
+ return factors
lib/python3.12/site-packages/sympy/ntheory/egyptian_fraction.py ADDED
@@ -0,0 +1,223 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from sympy.core.containers import Tuple
2
+ from sympy.core.numbers import (Integer, Rational)
3
+ from sympy.core.singleton import S
4
+ import sympy.polys
5
+
6
+ from math import gcd
7
+
8
+
9
+ def egyptian_fraction(r, algorithm="Greedy"):
10
+ """
11
+ Return the list of denominators of an Egyptian fraction
12
+ expansion [1]_ of the said rational `r`.
13
+
14
+ Parameters
15
+ ==========
16
+
17
+ r : Rational or (p, q)
18
+ a positive rational number, ``p/q``.
19
+ algorithm : { "Greedy", "Graham Jewett", "Takenouchi", "Golomb" }, optional
20
+ Denotes the algorithm to be used (the default is "Greedy").
21
+
22
+ Examples
23
+ ========
24
+
25
+ >>> from sympy import Rational
26
+ >>> from sympy.ntheory.egyptian_fraction import egyptian_fraction
27
+ >>> egyptian_fraction(Rational(3, 7))
28
+ [3, 11, 231]
29
+ >>> egyptian_fraction((3, 7), "Graham Jewett")
30
+ [7, 8, 9, 56, 57, 72, 3192]
31
+ >>> egyptian_fraction((3, 7), "Takenouchi")
32
+ [4, 7, 28]
33
+ >>> egyptian_fraction((3, 7), "Golomb")
34
+ [3, 15, 35]
35
+ >>> egyptian_fraction((11, 5), "Golomb")
36
+ [1, 2, 3, 4, 9, 234, 1118, 2580]
37
+
38
+ See Also
39
+ ========
40
+
41
+ sympy.core.numbers.Rational
42
+
43
+ Notes
44
+ =====
45
+
46
+ Currently the following algorithms are supported:
47
+
48
+ 1) Greedy Algorithm
49
+
50
+ Also called the Fibonacci-Sylvester algorithm [2]_.
51
+ At each step, extract the largest unit fraction less
52
+ than the target and replace the target with the remainder.
53
+
54
+ It has some distinct properties:
55
+
56
+ a) Given `p/q` in lowest terms, generates an expansion of maximum
57
+ length `p`. Even as the numerators get large, the number of
58
+ terms is seldom more than a handful.
59
+
60
+ b) Uses minimal memory.
61
+
62
+ c) The terms can blow up (standard examples of this are 5/121 and
63
+ 31/311). The denominator is at most squared at each step
64
+ (doubly-exponential growth) and typically exhibits
65
+ singly-exponential growth.
66
+
67
+ 2) Graham Jewett Algorithm
68
+
69
+ The algorithm suggested by the result of Graham and Jewett.
70
+ Note that this has a tendency to blow up: the length of the
71
+ resulting expansion is always ``2**(x/gcd(x, y)) - 1``. See [3]_.
72
+
73
+ 3) Takenouchi Algorithm
74
+
75
+ The algorithm suggested by Takenouchi (1921).
76
+ Differs from the Graham-Jewett algorithm only in the handling
77
+ of duplicates. See [3]_.
78
+
79
+ 4) Golomb's Algorithm
80
+
81
+ A method given by Golumb (1962), using modular arithmetic and
82
+ inverses. It yields the same results as a method using continued
83
+ fractions proposed by Bleicher (1972). See [4]_.
84
+
85
+ If the given rational is greater than or equal to 1, a greedy algorithm
86
+ of summing the harmonic sequence 1/1 + 1/2 + 1/3 + ... is used, taking
87
+ all the unit fractions of this sequence until adding one more would be
88
+ greater than the given number. This list of denominators is prefixed
89
+ to the result from the requested algorithm used on the remainder. For
90
+ example, if r is 8/3, using the Greedy algorithm, we get [1, 2, 3, 4,
91
+ 5, 6, 7, 14, 420], where the beginning of the sequence, [1, 2, 3, 4, 5,
92
+ 6, 7] is part of the harmonic sequence summing to 363/140, leaving a
93
+ remainder of 31/420, which yields [14, 420] by the Greedy algorithm.
94
+ The result of egyptian_fraction(Rational(8, 3), "Golomb") is [1, 2, 3,
95
+ 4, 5, 6, 7, 14, 574, 2788, 6460, 11590, 33062, 113820], and so on.
96
+
97
+ References
98
+ ==========
99
+
100
+ .. [1] https://en.wikipedia.org/wiki/Egyptian_fraction
101
+ .. [2] https://en.wikipedia.org/wiki/Greedy_algorithm_for_Egyptian_fractions
102
+ .. [3] https://www.ics.uci.edu/~eppstein/numth/egypt/conflict.html
103
+ .. [4] https://web.archive.org/web/20180413004012/https://ami.ektf.hu/uploads/papers/finalpdf/AMI_42_from129to134.pdf
104
+
105
+ """
106
+
107
+ if not isinstance(r, Rational):
108
+ if isinstance(r, (Tuple, tuple)) and len(r) == 2:
109
+ r = Rational(*r)
110
+ else:
111
+ raise ValueError("Value must be a Rational or tuple of ints")
112
+ if r <= 0:
113
+ raise ValueError("Value must be positive")
114
+
115
+ # common cases that all methods agree on
116
+ x, y = r.as_numer_denom()
117
+ if y == 1 and x == 2:
118
+ return [Integer(i) for i in [1, 2, 3, 6]]
119
+ if x == y + 1:
120
+ return [S.One, y]
121
+
122
+ prefix, rem = egypt_harmonic(r)
123
+ if rem == 0:
124
+ return prefix
125
+ # work in Python ints
126
+ x, y = rem.p, rem.q
127
+ # assert x < y and gcd(x, y) = 1
128
+
129
+ if algorithm == "Greedy":
130
+ postfix = egypt_greedy(x, y)
131
+ elif algorithm == "Graham Jewett":
132
+ postfix = egypt_graham_jewett(x, y)
133
+ elif algorithm == "Takenouchi":
134
+ postfix = egypt_takenouchi(x, y)
135
+ elif algorithm == "Golomb":
136
+ postfix = egypt_golomb(x, y)
137
+ else:
138
+ raise ValueError("Entered invalid algorithm")
139
+ return prefix + [Integer(i) for i in postfix]
140
+
141
+
142
+ def egypt_greedy(x, y):
143
+ # assumes gcd(x, y) == 1
144
+ if x == 1:
145
+ return [y]
146
+ else:
147
+ a = (-y) % x
148
+ b = y*(y//x + 1)
149
+ c = gcd(a, b)
150
+ if c > 1:
151
+ num, denom = a//c, b//c
152
+ else:
153
+ num, denom = a, b
154
+ return [y//x + 1] + egypt_greedy(num, denom)
155
+
156
+
157
+ def egypt_graham_jewett(x, y):
158
+ # assumes gcd(x, y) == 1
159
+ l = [y] * x
160
+
161
+ # l is now a list of integers whose reciprocals sum to x/y.
162
+ # we shall now proceed to manipulate the elements of l without
163
+ # changing the reciprocated sum until all elements are unique.
164
+
165
+ while len(l) != len(set(l)):
166
+ l.sort() # so the list has duplicates. find a smallest pair
167
+ for i in range(len(l) - 1):
168
+ if l[i] == l[i + 1]:
169
+ break
170
+ # we have now identified a pair of identical
171
+ # elements: l[i] and l[i + 1].
172
+ # now comes the application of the result of graham and jewett:
173
+ l[i + 1] = l[i] + 1
174
+ # and we just iterate that until the list has no duplicates.
175
+ l.append(l[i]*(l[i] + 1))
176
+ return sorted(l)
177
+
178
+
179
+ def egypt_takenouchi(x, y):
180
+ # assumes gcd(x, y) == 1
181
+ # special cases for 3/y
182
+ if x == 3:
183
+ if y % 2 == 0:
184
+ return [y//2, y]
185
+ i = (y - 1)//2
186
+ j = i + 1
187
+ k = j + i
188
+ return [j, k, j*k]
189
+ l = [y] * x
190
+ while len(l) != len(set(l)):
191
+ l.sort()
192
+ for i in range(len(l) - 1):
193
+ if l[i] == l[i + 1]:
194
+ break
195
+ k = l[i]
196
+ if k % 2 == 0:
197
+ l[i] = l[i] // 2
198
+ del l[i + 1]
199
+ else:
200
+ l[i], l[i + 1] = (k + 1)//2, k*(k + 1)//2
201
+ return sorted(l)
202
+
203
+
204
+ def egypt_golomb(x, y):
205
+ # assumes x < y and gcd(x, y) == 1
206
+ if x == 1:
207
+ return [y]
208
+ xp = sympy.polys.ZZ.invert(int(x), int(y))
209
+ rv = [xp*y]
210
+ rv.extend(egypt_golomb((x*xp - 1)//y, xp))
211
+ return sorted(rv)
212
+
213
+
214
+ def egypt_harmonic(r):
215
+ # assumes r is Rational
216
+ rv = []
217
+ d = S.One
218
+ acc = S.Zero
219
+ while acc + 1/d <= r:
220
+ acc += 1/d
221
+ rv.append(d)
222
+ d += 1
223
+ return (rv, r - acc)
lib/python3.12/site-packages/sympy/ntheory/elliptic_curve.py ADDED
@@ -0,0 +1,397 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from sympy.core.numbers import oo
2
+ from sympy.core.symbol import symbols
3
+ from sympy.polys.domains import FiniteField, QQ, RationalField, FF
4
+ from sympy.polys.polytools import Poly
5
+ from sympy.solvers.solvers import solve
6
+ from sympy.utilities.iterables import is_sequence
7
+ from sympy.utilities.misc import as_int
8
+ from .factor_ import divisors
9
+ from .residue_ntheory import polynomial_congruence
10
+
11
+
12
+ class EllipticCurve:
13
+ """
14
+ Create the following Elliptic Curve over domain.
15
+
16
+ `y^{2} + a_{1} x y + a_{3} y = x^{3} + a_{2} x^{2} + a_{4} x + a_{6}`
17
+
18
+ The default domain is ``QQ``. If no coefficient ``a1``, ``a2``, ``a3``,
19
+ is given then it creates a curve with the following form:
20
+
21
+ `y^{2} = x^{3} + a_{4} x + a_{6}`
22
+
23
+ Examples
24
+ ========
25
+
26
+ References
27
+ ==========
28
+
29
+ .. [1] J. Silverman "A Friendly Introduction to Number Theory" Third Edition
30
+ .. [2] https://mathworld.wolfram.com/EllipticDiscriminant.html
31
+ .. [3] G. Hardy, E. Wright "An Introduction to the Theory of Numbers" Sixth Edition
32
+
33
+ """
34
+
35
+ def __init__(self, a4, a6, a1=0, a2=0, a3=0, modulus=0):
36
+ if modulus == 0:
37
+ domain = QQ
38
+ else:
39
+ domain = FF(modulus)
40
+ a1, a2, a3, a4, a6 = map(domain.convert, (a1, a2, a3, a4, a6))
41
+ self._domain = domain
42
+ self.modulus = modulus
43
+ # Calculate discriminant
44
+ b2 = a1**2 + 4 * a2
45
+ b4 = 2 * a4 + a1 * a3
46
+ b6 = a3**2 + 4 * a6
47
+ b8 = a1**2 * a6 + 4 * a2 * a6 - a1 * a3 * a4 + a2 * a3**2 - a4**2
48
+ self._b2, self._b4, self._b6, self._b8 = b2, b4, b6, b8
49
+ self._discrim = -b2**2 * b8 - 8 * b4**3 - 27 * b6**2 + 9 * b2 * b4 * b6
50
+ self._a1 = a1
51
+ self._a2 = a2
52
+ self._a3 = a3
53
+ self._a4 = a4
54
+ self._a6 = a6
55
+ x, y, z = symbols('x y z')
56
+ self.x, self.y, self.z = x, y, z
57
+ self._poly = Poly(y**2*z + a1*x*y*z + a3*y*z**2 - x**3 - a2*x**2*z - a4*x*z**2 - a6*z**3, domain=domain)
58
+ if isinstance(self._domain, FiniteField):
59
+ self._rank = 0
60
+ elif isinstance(self._domain, RationalField):
61
+ self._rank = None
62
+
63
+ def __call__(self, x, y, z=1):
64
+ return EllipticCurvePoint(x, y, z, self)
65
+
66
+ def __contains__(self, point):
67
+ if is_sequence(point):
68
+ if len(point) == 2:
69
+ z1 = 1
70
+ else:
71
+ z1 = point[2]
72
+ x1, y1 = point[:2]
73
+ elif isinstance(point, EllipticCurvePoint):
74
+ x1, y1, z1 = point.x, point.y, point.z
75
+ else:
76
+ raise ValueError('Invalid point.')
77
+ if self.characteristic == 0 and z1 == 0:
78
+ return True
79
+ return self._poly.subs({self.x: x1, self.y: y1, self.z: z1}) == 0
80
+
81
+ def __repr__(self):
82
+ return self._poly.__repr__()
83
+
84
+ def minimal(self):
85
+ """
86
+ Return minimal Weierstrass equation.
87
+
88
+ Examples
89
+ ========
90
+
91
+ >>> from sympy.ntheory.elliptic_curve import EllipticCurve
92
+
93
+ >>> e1 = EllipticCurve(-10, -20, 0, -1, 1)
94
+ >>> e1.minimal()
95
+ Poly(-x**3 + 13392*x*z**2 + y**2*z + 1080432*z**3, x, y, z, domain='QQ')
96
+
97
+ """
98
+ char = self.characteristic
99
+ if char == 2:
100
+ return self
101
+ if char == 3:
102
+ return EllipticCurve(self._b4/2, self._b6/4, a2=self._b2/4, modulus=self.modulus)
103
+ c4 = self._b2**2 - 24*self._b4
104
+ c6 = -self._b2**3 + 36*self._b2*self._b4 - 216*self._b6
105
+ return EllipticCurve(-27*c4, -54*c6, modulus=self.modulus)
106
+
107
+ def points(self):
108
+ """
109
+ Return points of curve over Finite Field.
110
+
111
+ Examples
112
+ ========
113
+
114
+ >>> from sympy.ntheory.elliptic_curve import EllipticCurve
115
+ >>> e2 = EllipticCurve(1, 1, 1, 1, 1, modulus=5)
116
+ >>> e2.points()
117
+ {(0, 2), (1, 4), (2, 0), (2, 2), (3, 0), (3, 1), (4, 0)}
118
+
119
+ """
120
+
121
+ char = self.characteristic
122
+ all_pt = set()
123
+ if char >= 1:
124
+ for i in range(char):
125
+ congruence_eq = self._poly.subs({self.x: i, self.z: 1}).expr
126
+ sol = polynomial_congruence(congruence_eq, char)
127
+ all_pt.update((i, num) for num in sol)
128
+ return all_pt
129
+ else:
130
+ raise ValueError("Infinitely many points")
131
+
132
+ def points_x(self, x):
133
+ """Returns points on the curve for the given x-coordinate."""
134
+ pt = []
135
+ if self._domain == QQ:
136
+ for y in solve(self._poly.subs(self.x, x)):
137
+ pt.append((x, y))
138
+ else:
139
+ congruence_eq = self._poly.subs({self.x: x, self.z: 1}).expr
140
+ for y in polynomial_congruence(congruence_eq, self.characteristic):
141
+ pt.append((x, y))
142
+ return pt
143
+
144
+ def torsion_points(self):
145
+ """
146
+ Return torsion points of curve over Rational number.
147
+
148
+ Return point objects those are finite order.
149
+ According to Nagell-Lutz theorem, torsion point p(x, y)
150
+ x and y are integers, either y = 0 or y**2 is divisor
151
+ of discriminent. According to Mazur's theorem, there are
152
+ at most 15 points in torsion collection.
153
+
154
+ Examples
155
+ ========
156
+
157
+ >>> from sympy.ntheory.elliptic_curve import EllipticCurve
158
+ >>> e2 = EllipticCurve(-43, 166)
159
+ >>> sorted(e2.torsion_points())
160
+ [(-5, -16), (-5, 16), O, (3, -8), (3, 8), (11, -32), (11, 32)]
161
+
162
+ """
163
+ if self.characteristic > 0:
164
+ raise ValueError("No torsion point for Finite Field.")
165
+ l = [EllipticCurvePoint.point_at_infinity(self)]
166
+ for xx in solve(self._poly.subs({self.y: 0, self.z: 1})):
167
+ if xx.is_rational:
168
+ l.append(self(xx, 0))
169
+ for i in divisors(self.discriminant, generator=True):
170
+ j = int(i**.5)
171
+ if j**2 == i:
172
+ for xx in solve(self._poly.subs({self.y: j, self.z: 1})):
173
+ if not xx.is_rational:
174
+ continue
175
+ p = self(xx, j)
176
+ if p.order() != oo:
177
+ l.extend([p, -p])
178
+ return l
179
+
180
+ @property
181
+ def characteristic(self):
182
+ """
183
+ Return domain characteristic.
184
+
185
+ Examples
186
+ ========
187
+
188
+ >>> from sympy.ntheory.elliptic_curve import EllipticCurve
189
+ >>> e2 = EllipticCurve(-43, 166)
190
+ >>> e2.characteristic
191
+ 0
192
+
193
+ """
194
+ return self._domain.characteristic()
195
+
196
+ @property
197
+ def discriminant(self):
198
+ """
199
+ Return curve discriminant.
200
+
201
+ Examples
202
+ ========
203
+
204
+ >>> from sympy.ntheory.elliptic_curve import EllipticCurve
205
+ >>> e2 = EllipticCurve(0, 17)
206
+ >>> e2.discriminant
207
+ -124848
208
+
209
+ """
210
+ return int(self._discrim)
211
+
212
+ @property
213
+ def is_singular(self):
214
+ """
215
+ Return True if curve discriminant is equal to zero.
216
+ """
217
+ return self.discriminant == 0
218
+
219
+ @property
220
+ def j_invariant(self):
221
+ """
222
+ Return curve j-invariant.
223
+
224
+ Examples
225
+ ========
226
+
227
+ >>> from sympy.ntheory.elliptic_curve import EllipticCurve
228
+ >>> e1 = EllipticCurve(-2, 0, 0, 1, 1)
229
+ >>> e1.j_invariant
230
+ 1404928/389
231
+
232
+ """
233
+ c4 = self._b2**2 - 24*self._b4
234
+ return self._domain.to_sympy(c4**3 / self._discrim)
235
+
236
+ @property
237
+ def order(self):
238
+ """
239
+ Number of points in Finite field.
240
+
241
+ Examples
242
+ ========
243
+
244
+ >>> from sympy.ntheory.elliptic_curve import EllipticCurve
245
+ >>> e2 = EllipticCurve(1, 0, modulus=19)
246
+ >>> e2.order
247
+ 19
248
+
249
+ """
250
+ if self.characteristic == 0:
251
+ raise NotImplementedError("Still not implemented")
252
+ return len(self.points())
253
+
254
+ @property
255
+ def rank(self):
256
+ """
257
+ Number of independent points of infinite order.
258
+
259
+ For Finite field, it must be 0.
260
+ """
261
+ if self._rank is not None:
262
+ return self._rank
263
+ raise NotImplementedError("Still not implemented")
264
+
265
+
266
+ class EllipticCurvePoint:
267
+ """
268
+ Point of Elliptic Curve
269
+
270
+ Examples
271
+ ========
272
+
273
+ >>> from sympy.ntheory.elliptic_curve import EllipticCurve
274
+ >>> e1 = EllipticCurve(-17, 16)
275
+ >>> p1 = e1(0, -4, 1)
276
+ >>> p2 = e1(1, 0)
277
+ >>> p1 + p2
278
+ (15, -56)
279
+ >>> e3 = EllipticCurve(-1, 9)
280
+ >>> e3(1, -3) * 3
281
+ (664/169, 17811/2197)
282
+ >>> (e3(1, -3) * 3).order()
283
+ oo
284
+ >>> e2 = EllipticCurve(-2, 0, 0, 1, 1)
285
+ >>> p = e2(-1,1)
286
+ >>> q = e2(0, -1)
287
+ >>> p+q
288
+ (4, 8)
289
+ >>> p-q
290
+ (1, 0)
291
+ >>> 3*p-5*q
292
+ (328/361, -2800/6859)
293
+ """
294
+
295
+ @staticmethod
296
+ def point_at_infinity(curve):
297
+ return EllipticCurvePoint(0, 1, 0, curve)
298
+
299
+ def __init__(self, x, y, z, curve):
300
+ dom = curve._domain.convert
301
+ self.x = dom(x)
302
+ self.y = dom(y)
303
+ self.z = dom(z)
304
+ self._curve = curve
305
+ self._domain = self._curve._domain
306
+ if not self._curve.__contains__(self):
307
+ raise ValueError("The curve does not contain this point")
308
+
309
+ def __add__(self, p):
310
+ if self.z == 0:
311
+ return p
312
+ if p.z == 0:
313
+ return self
314
+ x1, y1 = self.x/self.z, self.y/self.z
315
+ x2, y2 = p.x/p.z, p.y/p.z
316
+ a1 = self._curve._a1
317
+ a2 = self._curve._a2
318
+ a3 = self._curve._a3
319
+ a4 = self._curve._a4
320
+ a6 = self._curve._a6
321
+ if x1 != x2:
322
+ slope = (y1 - y2) / (x1 - x2)
323
+ yint = (y1 * x2 - y2 * x1) / (x2 - x1)
324
+ else:
325
+ if (y1 + y2) == 0:
326
+ return self.point_at_infinity(self._curve)
327
+ slope = (3 * x1**2 + 2*a2*x1 + a4 - a1*y1) / (a1 * x1 + a3 + 2 * y1)
328
+ yint = (-x1**3 + a4*x1 + 2*a6 - a3*y1) / (a1*x1 + a3 + 2*y1)
329
+ x3 = slope**2 + a1*slope - a2 - x1 - x2
330
+ y3 = -(slope + a1) * x3 - yint - a3
331
+ return self._curve(x3, y3, 1)
332
+
333
+ def __lt__(self, other):
334
+ return (self.x, self.y, self.z) < (other.x, other.y, other.z)
335
+
336
+ def __mul__(self, n):
337
+ n = as_int(n)
338
+ r = self.point_at_infinity(self._curve)
339
+ if n == 0:
340
+ return r
341
+ if n < 0:
342
+ return -self * -n
343
+ p = self
344
+ while n:
345
+ if n & 1:
346
+ r = r + p
347
+ n >>= 1
348
+ p = p + p
349
+ return r
350
+
351
+ def __rmul__(self, n):
352
+ return self * n
353
+
354
+ def __neg__(self):
355
+ return EllipticCurvePoint(self.x, -self.y - self._curve._a1*self.x - self._curve._a3, self.z, self._curve)
356
+
357
+ def __repr__(self):
358
+ if self.z == 0:
359
+ return 'O'
360
+ dom = self._curve._domain
361
+ try:
362
+ return '({}, {})'.format(dom.to_sympy(self.x), dom.to_sympy(self.y))
363
+ except TypeError:
364
+ pass
365
+ return '({}, {})'.format(self.x, self.y)
366
+
367
+ def __sub__(self, other):
368
+ return self.__add__(-other)
369
+
370
+ def order(self):
371
+ """
372
+ Return point order n where nP = 0.
373
+
374
+ """
375
+ if self.z == 0:
376
+ return 1
377
+ if self.y == 0: # P = -P
378
+ return 2
379
+ p = self * 2
380
+ if p.y == -self.y: # 2P = -P
381
+ return 3
382
+ i = 2
383
+ if self._domain != QQ:
384
+ while int(p.x) == p.x and int(p.y) == p.y:
385
+ p = self + p
386
+ i += 1
387
+ if p.z == 0:
388
+ return i
389
+ return oo
390
+ while p.x.numerator == p.x and p.y.numerator == p.y:
391
+ p = self + p
392
+ i += 1
393
+ if i > 12:
394
+ return oo
395
+ if p.z == 0:
396
+ return i
397
+ return oo
lib/python3.12/site-packages/sympy/ntheory/factor_.py ADDED
@@ -0,0 +1,2668 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Integer factorization
3
+ """
4
+
5
+ from collections import defaultdict
6
+ import math
7
+
8
+ from sympy.core.containers import Dict
9
+ from sympy.core.mul import Mul
10
+ from sympy.core.numbers import Rational, Integer
11
+ from sympy.core.intfunc import num_digits
12
+ from sympy.core.power import Pow
13
+ from sympy.core.random import _randint
14
+ from sympy.core.singleton import S
15
+ from sympy.external.gmpy import (SYMPY_INTS, gcd, sqrt as isqrt,
16
+ sqrtrem, iroot, bit_scan1, remove)
17
+ from .primetest import isprime, MERSENNE_PRIME_EXPONENTS, is_mersenne_prime
18
+ from .generate import sieve, primerange, nextprime
19
+ from .digits import digits
20
+ from sympy.utilities.decorator import deprecated
21
+ from sympy.utilities.iterables import flatten
22
+ from sympy.utilities.misc import as_int, filldedent
23
+ from .ecm import _ecm_one_factor
24
+
25
+
26
+ def smoothness(n):
27
+ """
28
+ Return the B-smooth and B-power smooth values of n.
29
+
30
+ The smoothness of n is the largest prime factor of n; the power-
31
+ smoothness is the largest divisor raised to its multiplicity.
32
+
33
+ Examples
34
+ ========
35
+
36
+ >>> from sympy.ntheory.factor_ import smoothness
37
+ >>> smoothness(2**7*3**2)
38
+ (3, 128)
39
+ >>> smoothness(2**4*13)
40
+ (13, 16)
41
+ >>> smoothness(2)
42
+ (2, 2)
43
+
44
+ See Also
45
+ ========
46
+
47
+ factorint, smoothness_p
48
+ """
49
+
50
+ if n == 1:
51
+ return (1, 1) # not prime, but otherwise this causes headaches
52
+ facs = factorint(n)
53
+ return max(facs), max(m**facs[m] for m in facs)
54
+
55
+
56
+ def smoothness_p(n, m=-1, power=0, visual=None):
57
+ """
58
+ Return a list of [m, (p, (M, sm(p + m), psm(p + m)))...]
59
+ where:
60
+
61
+ 1. p**M is the base-p divisor of n
62
+ 2. sm(p + m) is the smoothness of p + m (m = -1 by default)
63
+ 3. psm(p + m) is the power smoothness of p + m
64
+
65
+ The list is sorted according to smoothness (default) or by power smoothness
66
+ if power=1.
67
+
68
+ The smoothness of the numbers to the left (m = -1) or right (m = 1) of a
69
+ factor govern the results that are obtained from the p +/- 1 type factoring
70
+ methods.
71
+
72
+ >>> from sympy.ntheory.factor_ import smoothness_p, factorint
73
+ >>> smoothness_p(10431, m=1)
74
+ (1, [(3, (2, 2, 4)), (19, (1, 5, 5)), (61, (1, 31, 31))])
75
+ >>> smoothness_p(10431)
76
+ (-1, [(3, (2, 2, 2)), (19, (1, 3, 9)), (61, (1, 5, 5))])
77
+ >>> smoothness_p(10431, power=1)
78
+ (-1, [(3, (2, 2, 2)), (61, (1, 5, 5)), (19, (1, 3, 9))])
79
+
80
+ If visual=True then an annotated string will be returned:
81
+
82
+ >>> print(smoothness_p(21477639576571, visual=1))
83
+ p**i=4410317**1 has p-1 B=1787, B-pow=1787
84
+ p**i=4869863**1 has p-1 B=2434931, B-pow=2434931
85
+
86
+ This string can also be generated directly from a factorization dictionary
87
+ and vice versa:
88
+
89
+ >>> factorint(17*9)
90
+ {3: 2, 17: 1}
91
+ >>> smoothness_p(_)
92
+ 'p**i=3**2 has p-1 B=2, B-pow=2\\np**i=17**1 has p-1 B=2, B-pow=16'
93
+ >>> smoothness_p(_)
94
+ {3: 2, 17: 1}
95
+
96
+ The table of the output logic is:
97
+
98
+ ====== ====== ======= =======
99
+ | Visual
100
+ ------ ----------------------
101
+ Input True False other
102
+ ====== ====== ======= =======
103
+ dict str tuple str
104
+ str str tuple dict
105
+ tuple str tuple str
106
+ n str tuple tuple
107
+ mul str tuple tuple
108
+ ====== ====== ======= =======
109
+
110
+ See Also
111
+ ========
112
+
113
+ factorint, smoothness
114
+ """
115
+
116
+ # visual must be True, False or other (stored as None)
117
+ if visual in (1, 0):
118
+ visual = bool(visual)
119
+ elif visual not in (True, False):
120
+ visual = None
121
+
122
+ if isinstance(n, str):
123
+ if visual:
124
+ return n
125
+ d = {}
126
+ for li in n.splitlines():
127
+ k, v = [int(i) for i in
128
+ li.split('has')[0].split('=')[1].split('**')]
129
+ d[k] = v
130
+ if visual is not True and visual is not False:
131
+ return d
132
+ return smoothness_p(d, visual=False)
133
+ elif not isinstance(n, tuple):
134
+ facs = factorint(n, visual=False)
135
+
136
+ if power:
137
+ k = -1
138
+ else:
139
+ k = 1
140
+ if isinstance(n, tuple):
141
+ rv = n
142
+ else:
143
+ rv = (m, sorted([(f,
144
+ tuple([M] + list(smoothness(f + m))))
145
+ for f, M in list(facs.items())],
146
+ key=lambda x: (x[1][k], x[0])))
147
+
148
+ if visual is False or (visual is not True) and (type(n) in [int, Mul]):
149
+ return rv
150
+ lines = []
151
+ for dat in rv[1]:
152
+ dat = flatten(dat)
153
+ dat.insert(2, m)
154
+ lines.append('p**i=%i**%i has p%+i B=%i, B-pow=%i' % tuple(dat))
155
+ return '\n'.join(lines)
156
+
157
+
158
+ def multiplicity(p, n):
159
+ """
160
+ Find the greatest integer m such that p**m divides n.
161
+
162
+ Examples
163
+ ========
164
+
165
+ >>> from sympy import multiplicity, Rational
166
+ >>> [multiplicity(5, n) for n in [8, 5, 25, 125, 250]]
167
+ [0, 1, 2, 3, 3]
168
+ >>> multiplicity(3, Rational(1, 9))
169
+ -2
170
+
171
+ Note: when checking for the multiplicity of a number in a
172
+ large factorial it is most efficient to send it as an unevaluated
173
+ factorial or to call ``multiplicity_in_factorial`` directly:
174
+
175
+ >>> from sympy.ntheory import multiplicity_in_factorial
176
+ >>> from sympy import factorial
177
+ >>> p = factorial(25)
178
+ >>> n = 2**100
179
+ >>> nfac = factorial(n, evaluate=False)
180
+ >>> multiplicity(p, nfac)
181
+ 52818775009509558395695966887
182
+ >>> _ == multiplicity_in_factorial(p, n)
183
+ True
184
+
185
+ See Also
186
+ ========
187
+
188
+ trailing
189
+
190
+ """
191
+ try:
192
+ p, n = as_int(p), as_int(n)
193
+ except ValueError:
194
+ from sympy.functions.combinatorial.factorials import factorial
195
+ if all(isinstance(i, (SYMPY_INTS, Rational)) for i in (p, n)):
196
+ p = Rational(p)
197
+ n = Rational(n)
198
+ if p.q == 1:
199
+ if n.p == 1:
200
+ return -multiplicity(p.p, n.q)
201
+ return multiplicity(p.p, n.p) - multiplicity(p.p, n.q)
202
+ elif p.p == 1:
203
+ return multiplicity(p.q, n.q)
204
+ else:
205
+ like = min(
206
+ multiplicity(p.p, n.p),
207
+ multiplicity(p.q, n.q))
208
+ cross = min(
209
+ multiplicity(p.q, n.p),
210
+ multiplicity(p.p, n.q))
211
+ return like - cross
212
+ elif (isinstance(p, (SYMPY_INTS, Integer)) and
213
+ isinstance(n, factorial) and
214
+ isinstance(n.args[0], Integer) and
215
+ n.args[0] >= 0):
216
+ return multiplicity_in_factorial(p, n.args[0])
217
+ raise ValueError('expecting ints or fractions, got %s and %s' % (p, n))
218
+
219
+ if n == 0:
220
+ raise ValueError('no such integer exists: multiplicity of %s is not-defined' %(n))
221
+ return remove(n, p)[1]
222
+
223
+
224
+ def multiplicity_in_factorial(p, n):
225
+ """return the largest integer ``m`` such that ``p**m`` divides ``n!``
226
+ without calculating the factorial of ``n``.
227
+
228
+ Parameters
229
+ ==========
230
+
231
+ p : Integer
232
+ positive integer
233
+ n : Integer
234
+ non-negative integer
235
+
236
+ Examples
237
+ ========
238
+
239
+ >>> from sympy.ntheory import multiplicity_in_factorial
240
+ >>> from sympy import factorial
241
+
242
+ >>> multiplicity_in_factorial(2, 3)
243
+ 1
244
+
245
+ An instructive use of this is to tell how many trailing zeros
246
+ a given factorial has. For example, there are 6 in 25!:
247
+
248
+ >>> factorial(25)
249
+ 15511210043330985984000000
250
+ >>> multiplicity_in_factorial(10, 25)
251
+ 6
252
+
253
+ For large factorials, it is much faster/feasible to use
254
+ this function rather than computing the actual factorial:
255
+
256
+ >>> multiplicity_in_factorial(factorial(25), 2**100)
257
+ 52818775009509558395695966887
258
+
259
+ See Also
260
+ ========
261
+
262
+ multiplicity
263
+
264
+ """
265
+
266
+ p, n = as_int(p), as_int(n)
267
+
268
+ if p <= 0:
269
+ raise ValueError('expecting positive integer got %s' % p )
270
+
271
+ if n < 0:
272
+ raise ValueError('expecting non-negative integer got %s' % n )
273
+
274
+ # keep only the largest of a given multiplicity since those
275
+ # of a given multiplicity will be goverened by the behavior
276
+ # of the largest factor
277
+ f = defaultdict(int)
278
+ for k, v in factorint(p).items():
279
+ f[v] = max(k, f[v])
280
+ # multiplicity of p in n! depends on multiplicity
281
+ # of prime `k` in p, so we floor divide by `v`
282
+ # and keep it if smaller than the multiplicity of p
283
+ # seen so far
284
+ return min((n + k - sum(digits(n, k)))//(k - 1)//v for v, k in f.items())
285
+
286
+
287
+ def _perfect_power(n, next_p=2):
288
+ """ Return integers ``(b, e)`` such that ``n == b**e`` if ``n`` is a unique
289
+ perfect power with ``e > 1``, else ``False`` (e.g. 1 is not a perfect power).
290
+
291
+ Explanation
292
+ ===========
293
+
294
+ This is a low-level helper for ``perfect_power``, for internal use.
295
+
296
+ Parameters
297
+ ==========
298
+
299
+ n : int
300
+ assume that n is a nonnegative integer
301
+ next_p : int
302
+ Assume that n has no factor less than next_p.
303
+ i.e., all(n % p for p in range(2, next_p)) is True
304
+
305
+ Examples
306
+ ========
307
+ >>> from sympy.ntheory.factor_ import _perfect_power
308
+ >>> _perfect_power(16)
309
+ (2, 4)
310
+ >>> _perfect_power(17)
311
+ False
312
+
313
+ """
314
+ if n <= 3:
315
+ return False
316
+
317
+ factors = {}
318
+ g = 0
319
+ multi = 1
320
+
321
+ def done(n, factors, g, multi):
322
+ g = gcd(g, multi)
323
+ if g == 1:
324
+ return False
325
+ factors[n] = multi
326
+ return math.prod(p**(e//g) for p, e in factors.items()), g
327
+
328
+ # If n is small, only trial factoring is faster
329
+ if n <= 1_000_000:
330
+ n = _factorint_small(factors, n, 1_000, 1_000, next_p)[0]
331
+ if n > 1:
332
+ return False
333
+ g = gcd(*factors.values())
334
+ if g == 1:
335
+ return False
336
+ return math.prod(p**(e//g) for p, e in factors.items()), g
337
+
338
+ # divide by 2
339
+ if next_p < 3:
340
+ g = bit_scan1(n)
341
+ if g:
342
+ if g == 1:
343
+ return False
344
+ n >>= g
345
+ factors[2] = g
346
+ if n == 1:
347
+ return 2, g
348
+ else:
349
+ # If `m**g`, then we have found perfect power.
350
+ # Otherwise, there is no possibility of perfect power, especially if `g` is prime.
351
+ m, _exact = iroot(n, g)
352
+ if _exact:
353
+ return 2*m, g
354
+ elif isprime(g):
355
+ return False
356
+ next_p = 3
357
+
358
+ # square number?
359
+ while n & 7 == 1: # n % 8 == 1:
360
+ m, _exact = iroot(n, 2)
361
+ if _exact:
362
+ n = m
363
+ multi <<= 1
364
+ else:
365
+ break
366
+ if n < next_p**3:
367
+ return done(n, factors, g, multi)
368
+
369
+ # trial factoring
370
+ # Since the maximum value an exponent can take is `log_{next_p}(n)`,
371
+ # the number of exponents to be checked can be reduced by performing a trial factoring.
372
+ # The value of `tf_max` needs more consideration.
373
+ tf_max = n.bit_length()//27 + 24
374
+ if next_p < tf_max:
375
+ for p in primerange(next_p, tf_max):
376
+ m, t = remove(n, p)
377
+ if t:
378
+ n = m
379
+ t *= multi
380
+ _g = gcd(g, t)
381
+ if _g == 1:
382
+ return False
383
+ factors[p] = t
384
+ if n == 1:
385
+ return math.prod(p**(e//_g)
386
+ for p, e in factors.items()), _g
387
+ elif g == 0 or _g < g: # If g is updated
388
+ g = _g
389
+ m, _exact = iroot(n**multi, g)
390
+ if _exact:
391
+ return m * math.prod(p**(e//g)
392
+ for p, e in factors.items()), g
393
+ elif isprime(g):
394
+ return False
395
+ next_p = tf_max
396
+ if n < next_p**3:
397
+ return done(n, factors, g, multi)
398
+
399
+ # check iroot
400
+ if g:
401
+ # If g is non-zero, the exponent is a divisor of g.
402
+ # 2 can be omitted since it has already been checked.
403
+ prime_iter = sorted(factorint(g >> bit_scan1(g)).keys())
404
+ else:
405
+ # The maximum possible value of the exponent is `log_{next_p}(n)`.
406
+ # To compensate for the presence of computational error, 2 is added.
407
+ prime_iter = primerange(3, int(math.log(n, next_p)) + 2)
408
+ logn = math.log2(n)
409
+ threshold = logn / 40 # Threshold for direct calculation
410
+ for p in prime_iter:
411
+ if threshold < p:
412
+ # If p is large, find the power root p directly without `iroot`.
413
+ while True:
414
+ b = pow(2, logn / p)
415
+ rb = int(b + 0.5)
416
+ if abs(rb - b) < 0.01 and rb**p == n:
417
+ n = rb
418
+ multi *= p
419
+ logn = math.log2(n)
420
+ else:
421
+ break
422
+ else:
423
+ while True:
424
+ m, _exact = iroot(n, p)
425
+ if _exact:
426
+ n = m
427
+ multi *= p
428
+ logn = math.log2(n)
429
+ else:
430
+ break
431
+ if n < next_p**(p + 2):
432
+ break
433
+ return done(n, factors, g, multi)
434
+
435
+
436
+ def perfect_power(n, candidates=None, big=True, factor=True):
437
+ """
438
+ Return ``(b, e)`` such that ``n`` == ``b**e`` if ``n`` is a unique
439
+ perfect power with ``e > 1``, else ``False`` (e.g. 1 is not a
440
+ perfect power). A ValueError is raised if ``n`` is not Rational.
441
+
442
+ By default, the base is recursively decomposed and the exponents
443
+ collected so the largest possible ``e`` is sought. If ``big=False``
444
+ then the smallest possible ``e`` (thus prime) will be chosen.
445
+
446
+ If ``factor=True`` then simultaneous factorization of ``n`` is
447
+ attempted since finding a factor indicates the only possible root
448
+ for ``n``. This is True by default since only a few small factors will
449
+ be tested in the course of searching for the perfect power.
450
+
451
+ The use of ``candidates`` is primarily for internal use; if provided,
452
+ False will be returned if ``n`` cannot be written as a power with one
453
+ of the candidates as an exponent and factoring (beyond testing for
454
+ a factor of 2) will not be attempted.
455
+
456
+ Examples
457
+ ========
458
+
459
+ >>> from sympy import perfect_power, Rational
460
+ >>> perfect_power(16)
461
+ (2, 4)
462
+ >>> perfect_power(16, big=False)
463
+ (4, 2)
464
+
465
+ Negative numbers can only have odd perfect powers:
466
+
467
+ >>> perfect_power(-4)
468
+ False
469
+ >>> perfect_power(-8)
470
+ (-2, 3)
471
+
472
+ Rationals are also recognized:
473
+
474
+ >>> perfect_power(Rational(1, 2)**3)
475
+ (1/2, 3)
476
+ >>> perfect_power(Rational(-3, 2)**3)
477
+ (-3/2, 3)
478
+
479
+ Notes
480
+ =====
481
+
482
+ To know whether an integer is a perfect power of 2 use
483
+
484
+ >>> is2pow = lambda n: bool(n and not n & (n - 1))
485
+ >>> [(i, is2pow(i)) for i in range(5)]
486
+ [(0, False), (1, True), (2, True), (3, False), (4, True)]
487
+
488
+ It is not necessary to provide ``candidates``. When provided
489
+ it will be assumed that they are ints. The first one that is
490
+ larger than the computed maximum possible exponent will signal
491
+ failure for the routine.
492
+
493
+ >>> perfect_power(3**8, [9])
494
+ False
495
+ >>> perfect_power(3**8, [2, 4, 8])
496
+ (3, 8)
497
+ >>> perfect_power(3**8, [4, 8], big=False)
498
+ (9, 4)
499
+
500
+ See Also
501
+ ========
502
+ sympy.core.intfunc.integer_nthroot
503
+ sympy.ntheory.primetest.is_square
504
+ """
505
+ if isinstance(n, Rational) and not n.is_Integer:
506
+ p, q = n.as_numer_denom()
507
+ if p is S.One:
508
+ pp = perfect_power(q)
509
+ if pp:
510
+ pp = (n.func(1, pp[0]), pp[1])
511
+ else:
512
+ pp = perfect_power(p)
513
+ if pp:
514
+ num, e = pp
515
+ pq = perfect_power(q, [e])
516
+ if pq:
517
+ den, _ = pq
518
+ pp = n.func(num, den), e
519
+ return pp
520
+
521
+ n = as_int(n)
522
+ if n < 0:
523
+ pp = perfect_power(-n)
524
+ if pp:
525
+ b, e = pp
526
+ if e % 2:
527
+ return -b, e
528
+ return False
529
+
530
+ if candidates is None and big:
531
+ return _perfect_power(n)
532
+
533
+ if n <= 3:
534
+ # no unique exponent for 0, 1
535
+ # 2 and 3 have exponents of 1
536
+ return False
537
+ logn = math.log2(n)
538
+ max_possible = int(logn) + 2 # only check values less than this
539
+ not_square = n % 10 in [2, 3, 7, 8] # squares cannot end in 2, 3, 7, 8
540
+ min_possible = 2 + not_square
541
+ if not candidates:
542
+ candidates = primerange(min_possible, max_possible)
543
+ else:
544
+ candidates = sorted([i for i in candidates
545
+ if min_possible <= i < max_possible])
546
+ if n%2 == 0:
547
+ e = bit_scan1(n)
548
+ candidates = [i for i in candidates if e%i == 0]
549
+ if big:
550
+ candidates = reversed(candidates)
551
+ for e in candidates:
552
+ r, ok = iroot(n, e)
553
+ if ok:
554
+ return int(r), e
555
+ return False
556
+
557
+ def _factors():
558
+ rv = 2 + n % 2
559
+ while True:
560
+ yield rv
561
+ rv = nextprime(rv)
562
+
563
+ for fac, e in zip(_factors(), candidates):
564
+ # see if there is a factor present
565
+ if factor and n % fac == 0:
566
+ # find what the potential power is
567
+ e = remove(n, fac)[1]
568
+ # if it's a trivial power we are done
569
+ if e == 1:
570
+ return False
571
+
572
+ # maybe the e-th root of n is exact
573
+ r, exact = iroot(n, e)
574
+ if not exact:
575
+ # Having a factor, we know that e is the maximal
576
+ # possible value for a root of n.
577
+ # If n = fac**e*m can be written as a perfect
578
+ # power then see if m can be written as r**E where
579
+ # gcd(e, E) != 1 so n = (fac**(e//E)*r)**E
580
+ m = n//fac**e
581
+ rE = perfect_power(m, candidates=divisors(e, generator=True))
582
+ if not rE:
583
+ return False
584
+ else:
585
+ r, E = rE
586
+ r, e = fac**(e//E)*r, E
587
+ if not big:
588
+ e0 = primefactors(e)
589
+ if e0[0] != e:
590
+ r, e = r**(e//e0[0]), e0[0]
591
+ return int(r), e
592
+
593
+ # Weed out downright impossible candidates
594
+ if logn/e < 40:
595
+ b = 2.0**(logn/e)
596
+ if abs(int(b + 0.5) - b) > 0.01:
597
+ continue
598
+
599
+ # now see if the plausible e makes a perfect power
600
+ r, exact = iroot(n, e)
601
+ if exact:
602
+ if big:
603
+ m = perfect_power(r, big=big, factor=factor)
604
+ if m:
605
+ r, e = m[0], e*m[1]
606
+ return int(r), e
607
+
608
+ return False
609
+
610
+
611
+ def pollard_rho(n, s=2, a=1, retries=5, seed=1234, max_steps=None, F=None):
612
+ r"""
613
+ Use Pollard's rho method to try to extract a nontrivial factor
614
+ of ``n``. The returned factor may be a composite number. If no
615
+ factor is found, ``None`` is returned.
616
+
617
+ The algorithm generates pseudo-random values of x with a generator
618
+ function, replacing x with F(x). If F is not supplied then the
619
+ function x**2 + ``a`` is used. The first value supplied to F(x) is ``s``.
620
+ Upon failure (if ``retries`` is > 0) a new ``a`` and ``s`` will be
621
+ supplied; the ``a`` will be ignored if F was supplied.
622
+
623
+ The sequence of numbers generated by such functions generally have a
624
+ a lead-up to some number and then loop around back to that number and
625
+ begin to repeat the sequence, e.g. 1, 2, 3, 4, 5, 3, 4, 5 -- this leader
626
+ and loop look a bit like the Greek letter rho, and thus the name, 'rho'.
627
+
628
+ For a given function, very different leader-loop values can be obtained
629
+ so it is a good idea to allow for retries:
630
+
631
+ >>> from sympy.ntheory.generate import cycle_length
632
+ >>> n = 16843009
633
+ >>> F = lambda x:(2048*pow(x, 2, n) + 32767) % n
634
+ >>> for s in range(5):
635
+ ... print('loop length = %4i; leader length = %3i' % next(cycle_length(F, s)))
636
+ ...
637
+ loop length = 2489; leader length = 43
638
+ loop length = 78; leader length = 121
639
+ loop length = 1482; leader length = 100
640
+ loop length = 1482; leader length = 286
641
+ loop length = 1482; leader length = 101
642
+
643
+ Here is an explicit example where there is a three element leadup to
644
+ a sequence of 3 numbers (11, 14, 4) that then repeat:
645
+
646
+ >>> x=2
647
+ >>> for i in range(9):
648
+ ... print(x)
649
+ ... x=(x**2+12)%17
650
+ ...
651
+ 2
652
+ 16
653
+ 13
654
+ 11
655
+ 14
656
+ 4
657
+ 11
658
+ 14
659
+ 4
660
+ >>> next(cycle_length(lambda x: (x**2+12)%17, 2))
661
+ (3, 3)
662
+ >>> list(cycle_length(lambda x: (x**2+12)%17, 2, values=True))
663
+ [2, 16, 13, 11, 14, 4]
664
+
665
+ Instead of checking the differences of all generated values for a gcd
666
+ with n, only the kth and 2*kth numbers are checked, e.g. 1st and 2nd,
667
+ 2nd and 4th, 3rd and 6th until it has been detected that the loop has been
668
+ traversed. Loops may be many thousands of steps long before rho finds a
669
+ factor or reports failure. If ``max_steps`` is specified, the iteration
670
+ is cancelled with a failure after the specified number of steps.
671
+
672
+ Examples
673
+ ========
674
+
675
+ >>> from sympy import pollard_rho
676
+ >>> n=16843009
677
+ >>> F=lambda x:(2048*pow(x,2,n) + 32767) % n
678
+ >>> pollard_rho(n, F=F)
679
+ 257
680
+
681
+ Use the default setting with a bad value of ``a`` and no retries:
682
+
683
+ >>> pollard_rho(n, a=n-2, retries=0)
684
+
685
+ If retries is > 0 then perhaps the problem will correct itself when
686
+ new values are generated for a:
687
+
688
+ >>> pollard_rho(n, a=n-2, retries=1)
689
+ 257
690
+
691
+ References
692
+ ==========
693
+
694
+ .. [1] Richard Crandall & Carl Pomerance (2005), "Prime Numbers:
695
+ A Computational Perspective", Springer, 2nd edition, 229-231
696
+
697
+ """
698
+ n = int(n)
699
+ if n < 5:
700
+ raise ValueError('pollard_rho should receive n > 4')
701
+ randint = _randint(seed + retries)
702
+ V = s
703
+ for i in range(retries + 1):
704
+ U = V
705
+ if not F:
706
+ F = lambda x: (pow(x, 2, n) + a) % n
707
+ j = 0
708
+ while 1:
709
+ if max_steps and (j > max_steps):
710
+ break
711
+ j += 1
712
+ U = F(U)
713
+ V = F(F(V)) # V is 2x further along than U
714
+ g = gcd(U - V, n)
715
+ if g == 1:
716
+ continue
717
+ if g == n:
718
+ break
719
+ return int(g)
720
+ V = randint(0, n - 1)
721
+ a = randint(1, n - 3) # for x**2 + a, a%n should not be 0 or -2
722
+ F = None
723
+ return None
724
+
725
+
726
+ def pollard_pm1(n, B=10, a=2, retries=0, seed=1234):
727
+ """
728
+ Use Pollard's p-1 method to try to extract a nontrivial factor
729
+ of ``n``. Either a divisor (perhaps composite) or ``None`` is returned.
730
+
731
+ The value of ``a`` is the base that is used in the test gcd(a**M - 1, n).
732
+ The default is 2. If ``retries`` > 0 then if no factor is found after the
733
+ first attempt, a new ``a`` will be generated randomly (using the ``seed``)
734
+ and the process repeated.
735
+
736
+ Note: the value of M is lcm(1..B) = reduce(ilcm, range(2, B + 1)).
737
+
738
+ A search is made for factors next to even numbers having a power smoothness
739
+ less than ``B``. Choosing a larger B increases the likelihood of finding a
740
+ larger factor but takes longer. Whether a factor of n is found or not
741
+ depends on ``a`` and the power smoothness of the even number just less than
742
+ the factor p (hence the name p - 1).
743
+
744
+ Although some discussion of what constitutes a good ``a`` some
745
+ descriptions are hard to interpret. At the modular.math site referenced
746
+ below it is stated that if gcd(a**M - 1, n) = N then a**M % q**r is 1
747
+ for every prime power divisor of N. But consider the following:
748
+
749
+ >>> from sympy.ntheory.factor_ import smoothness_p, pollard_pm1
750
+ >>> n=257*1009
751
+ >>> smoothness_p(n)
752
+ (-1, [(257, (1, 2, 256)), (1009, (1, 7, 16))])
753
+
754
+ So we should (and can) find a root with B=16:
755
+
756
+ >>> pollard_pm1(n, B=16, a=3)
757
+ 1009
758
+
759
+ If we attempt to increase B to 256 we find that it does not work:
760
+
761
+ >>> pollard_pm1(n, B=256)
762
+ >>>
763
+
764
+ But if the value of ``a`` is changed we find that only multiples of
765
+ 257 work, e.g.:
766
+
767
+ >>> pollard_pm1(n, B=256, a=257)
768
+ 1009
769
+
770
+ Checking different ``a`` values shows that all the ones that did not
771
+ work had a gcd value not equal to ``n`` but equal to one of the
772
+ factors:
773
+
774
+ >>> from sympy import ilcm, igcd, factorint, Pow
775
+ >>> M = 1
776
+ >>> for i in range(2, 256):
777
+ ... M = ilcm(M, i)
778
+ ...
779
+ >>> set([igcd(pow(a, M, n) - 1, n) for a in range(2, 256) if
780
+ ... igcd(pow(a, M, n) - 1, n) != n])
781
+ {1009}
782
+
783
+ But does aM % d for every divisor of n give 1?
784
+
785
+ >>> aM = pow(255, M, n)
786
+ >>> [(d, aM%Pow(*d.args)) for d in factorint(n, visual=True).args]
787
+ [(257**1, 1), (1009**1, 1)]
788
+
789
+ No, only one of them. So perhaps the principle is that a root will
790
+ be found for a given value of B provided that:
791
+
792
+ 1) the power smoothness of the p - 1 value next to the root
793
+ does not exceed B
794
+ 2) a**M % p != 1 for any of the divisors of n.
795
+
796
+ By trying more than one ``a`` it is possible that one of them
797
+ will yield a factor.
798
+
799
+ Examples
800
+ ========
801
+
802
+ With the default smoothness bound, this number cannot be cracked:
803
+
804
+ >>> from sympy.ntheory import pollard_pm1
805
+ >>> pollard_pm1(21477639576571)
806
+
807
+ Increasing the smoothness bound helps:
808
+
809
+ >>> pollard_pm1(21477639576571, B=2000)
810
+ 4410317
811
+
812
+ Looking at the smoothness of the factors of this number we find:
813
+
814
+ >>> from sympy.ntheory.factor_ import smoothness_p, factorint
815
+ >>> print(smoothness_p(21477639576571, visual=1))
816
+ p**i=4410317**1 has p-1 B=1787, B-pow=1787
817
+ p**i=4869863**1 has p-1 B=2434931, B-pow=2434931
818
+
819
+ The B and B-pow are the same for the p - 1 factorizations of the divisors
820
+ because those factorizations had a very large prime factor:
821
+
822
+ >>> factorint(4410317 - 1)
823
+ {2: 2, 617: 1, 1787: 1}
824
+ >>> factorint(4869863-1)
825
+ {2: 1, 2434931: 1}
826
+
827
+ Note that until B reaches the B-pow value of 1787, the number is not cracked;
828
+
829
+ >>> pollard_pm1(21477639576571, B=1786)
830
+ >>> pollard_pm1(21477639576571, B=1787)
831
+ 4410317
832
+
833
+ The B value has to do with the factors of the number next to the divisor,
834
+ not the divisors themselves. A worst case scenario is that the number next
835
+ to the factor p has a large prime divisisor or is a perfect power. If these
836
+ conditions apply then the power-smoothness will be about p/2 or p. The more
837
+ realistic is that there will be a large prime factor next to p requiring
838
+ a B value on the order of p/2. Although primes may have been searched for
839
+ up to this level, the p/2 is a factor of p - 1, something that we do not
840
+ know. The modular.math reference below states that 15% of numbers in the
841
+ range of 10**15 to 15**15 + 10**4 are 10**6 power smooth so a B of 10**6
842
+ will fail 85% of the time in that range. From 10**8 to 10**8 + 10**3 the
843
+ percentages are nearly reversed...but in that range the simple trial
844
+ division is quite fast.
845
+
846
+ References
847
+ ==========
848
+
849
+ .. [1] Richard Crandall & Carl Pomerance (2005), "Prime Numbers:
850
+ A Computational Perspective", Springer, 2nd edition, 236-238
851
+ .. [2] https://web.archive.org/web/20150716201437/http://modular.math.washington.edu/edu/2007/spring/ent/ent-html/node81.html
852
+ .. [3] https://www.cs.toronto.edu/~yuvalf/Factorization.pdf
853
+ """
854
+
855
+ n = int(n)
856
+ if n < 4 or B < 3:
857
+ raise ValueError('pollard_pm1 should receive n > 3 and B > 2')
858
+ randint = _randint(seed + B)
859
+
860
+ # computing a**lcm(1,2,3,..B) % n for B > 2
861
+ # it looks weird, but it's right: primes run [2, B]
862
+ # and the answer's not right until the loop is done.
863
+ for i in range(retries + 1):
864
+ aM = a
865
+ for p in sieve.primerange(2, B + 1):
866
+ e = int(math.log(B, p))
867
+ aM = pow(aM, pow(p, e), n)
868
+ g = gcd(aM - 1, n)
869
+ if 1 < g < n:
870
+ return int(g)
871
+
872
+ # get a new a:
873
+ # since the exponent, lcm(1..B), is even, if we allow 'a' to be 'n-1'
874
+ # then (n - 1)**even % n will be 1 which will give a g of 0 and 1 will
875
+ # give a zero, too, so we set the range as [2, n-2]. Some references
876
+ # say 'a' should be coprime to n, but either will detect factors.
877
+ a = randint(2, n - 2)
878
+
879
+
880
+ def _trial(factors, n, candidates, verbose=False):
881
+ """
882
+ Helper function for integer factorization. Trial factors ``n`
883
+ against all integers given in the sequence ``candidates``
884
+ and updates the dict ``factors`` in-place. Returns the reduced
885
+ value of ``n`` and a flag indicating whether any factors were found.
886
+ """
887
+ if verbose:
888
+ factors0 = list(factors.keys())
889
+ nfactors = len(factors)
890
+ for d in candidates:
891
+ if n % d == 0:
892
+ n, m = remove(n // d, d)
893
+ factors[d] = m + 1
894
+ if verbose:
895
+ for k in sorted(set(factors).difference(set(factors0))):
896
+ print(factor_msg % (k, factors[k]))
897
+ return int(n), len(factors) != nfactors
898
+
899
+
900
+ def _check_termination(factors, n, limit, use_trial, use_rho, use_pm1,
901
+ verbose, next_p):
902
+ """
903
+ Helper function for integer factorization. Checks if ``n``
904
+ is a prime or a perfect power, and in those cases updates the factorization.
905
+ """
906
+ if verbose:
907
+ print('Check for termination')
908
+ if n == 1:
909
+ if verbose:
910
+ print(complete_msg)
911
+ return True
912
+ if n < next_p**2 or isprime(n):
913
+ factors[int(n)] = 1
914
+ if verbose:
915
+ print(complete_msg)
916
+ return True
917
+
918
+ # since we've already been factoring there is no need to do
919
+ # simultaneous factoring with the power check
920
+ p = _perfect_power(n, next_p)
921
+ if not p:
922
+ return False
923
+ base, exp = p
924
+ if base < next_p**2 or isprime(base):
925
+ factors[base] = exp
926
+ else:
927
+ facs = factorint(base, limit, use_trial, use_rho, use_pm1,
928
+ verbose=False)
929
+ for b, e in facs.items():
930
+ if verbose:
931
+ print(factor_msg % (b, e))
932
+ # int() can be removed when https://github.com/flintlib/python-flint/issues/92 is resolved
933
+ factors[b] = int(exp*e)
934
+ if verbose:
935
+ print(complete_msg)
936
+ return True
937
+
938
+
939
+ trial_int_msg = "Trial division with ints [%i ... %i] and fail_max=%i"
940
+ trial_msg = "Trial division with primes [%i ... %i]"
941
+ rho_msg = "Pollard's rho with retries %i, max_steps %i and seed %i"
942
+ pm1_msg = "Pollard's p-1 with smoothness bound %i and seed %i"
943
+ ecm_msg = "Elliptic Curve with B1 bound %i, B2 bound %i, num_curves %i"
944
+ factor_msg = '\t%i ** %i'
945
+ fermat_msg = 'Close factors satisying Fermat condition found.'
946
+ complete_msg = 'Factorization is complete.'
947
+
948
+
949
+ def _factorint_small(factors, n, limit, fail_max, next_p=2):
950
+ """
951
+ Return the value of n and either a 0 (indicating that factorization up
952
+ to the limit was complete) or else the next near-prime that would have
953
+ been tested.
954
+
955
+ Factoring stops if there are fail_max unsuccessful tests in a row.
956
+
957
+ If factors of n were found they will be in the factors dictionary as
958
+ {factor: multiplicity} and the returned value of n will have had those
959
+ factors removed. The factors dictionary is modified in-place.
960
+
961
+ """
962
+
963
+ def done(n, d):
964
+ """return n, d if the sqrt(n) was not reached yet, else
965
+ n, 0 indicating that factoring is done.
966
+ """
967
+ if d*d <= n:
968
+ return n, d
969
+ return n, 0
970
+
971
+ limit2 = limit**2
972
+ threshold2 = min(n, limit2)
973
+
974
+ if next_p < 3:
975
+ if not n & 1:
976
+ m = bit_scan1(n)
977
+ factors[2] = m
978
+ n >>= m
979
+ threshold2 = min(n, limit2)
980
+ next_p = 3
981
+ if threshold2 < 9: # next_p**2 = 9
982
+ return done(n, next_p)
983
+
984
+ if next_p < 5:
985
+ if not n % 3:
986
+ n //= 3
987
+ m = 1
988
+ while not n % 3:
989
+ n //= 3
990
+ m += 1
991
+ if m == 20:
992
+ n, mm = remove(n, 3)
993
+ m += mm
994
+ break
995
+ factors[3] = m
996
+ threshold2 = min(n, limit2)
997
+ next_p = 5
998
+ if threshold2 < 25: # next_p**2 = 25
999
+ return done(n, next_p)
1000
+
1001
+ # Because of the order of checks, starting from `min_p = 6k+5`,
1002
+ # useless checks are caused.
1003
+ # We want to calculate
1004
+ # next_p += [-1, -2, 3, 2, 1, 0][next_p % 6]
1005
+ p6 = next_p % 6
1006
+ next_p += (-1 if p6 < 2 else 5) - p6
1007
+
1008
+ fails = 0
1009
+ while fails < fail_max:
1010
+ # next_p % 6 == 5
1011
+ if n % next_p:
1012
+ fails += 1
1013
+ else:
1014
+ n //= next_p
1015
+ m = 1
1016
+ while not n % next_p:
1017
+ n //= next_p
1018
+ m += 1
1019
+ if m == 20:
1020
+ n, mm = remove(n, next_p)
1021
+ m += mm
1022
+ break
1023
+ factors[next_p] = m
1024
+ fails = 0
1025
+ threshold2 = min(n, limit2)
1026
+ next_p += 2
1027
+ if threshold2 < next_p**2:
1028
+ return done(n, next_p)
1029
+
1030
+ # next_p % 6 == 1
1031
+ if n % next_p:
1032
+ fails += 1
1033
+ else:
1034
+ n //= next_p
1035
+ m = 1
1036
+ while not n % next_p:
1037
+ n //= next_p
1038
+ m += 1
1039
+ if m == 20:
1040
+ n, mm = remove(n, next_p)
1041
+ m += mm
1042
+ break
1043
+ factors[next_p] = m
1044
+ fails = 0
1045
+ threshold2 = min(n, limit2)
1046
+ next_p += 4
1047
+ if threshold2 < next_p**2:
1048
+ return done(n, next_p)
1049
+ return done(n, next_p)
1050
+
1051
+
1052
+ def factorint(n, limit=None, use_trial=True, use_rho=True, use_pm1=True,
1053
+ use_ecm=True, verbose=False, visual=None, multiple=False):
1054
+ r"""
1055
+ Given a positive integer ``n``, ``factorint(n)`` returns a dict containing
1056
+ the prime factors of ``n`` as keys and their respective multiplicities
1057
+ as values. For example:
1058
+
1059
+ >>> from sympy.ntheory import factorint
1060
+ >>> factorint(2000) # 2000 = (2**4) * (5**3)
1061
+ {2: 4, 5: 3}
1062
+ >>> factorint(65537) # This number is prime
1063
+ {65537: 1}
1064
+
1065
+ For input less than 2, factorint behaves as follows:
1066
+
1067
+ - ``factorint(1)`` returns the empty factorization, ``{}``
1068
+ - ``factorint(0)`` returns ``{0:1}``
1069
+ - ``factorint(-n)`` adds ``-1:1`` to the factors and then factors ``n``
1070
+
1071
+ Partial Factorization:
1072
+
1073
+ If ``limit`` (> 3) is specified, the search is stopped after performing
1074
+ trial division up to (and including) the limit (or taking a
1075
+ corresponding number of rho/p-1 steps). This is useful if one has
1076
+ a large number and only is interested in finding small factors (if
1077
+ any). Note that setting a limit does not prevent larger factors
1078
+ from being found early; it simply means that the largest factor may
1079
+ be composite. Since checking for perfect power is relatively cheap, it is
1080
+ done regardless of the limit setting.
1081
+
1082
+ This number, for example, has two small factors and a huge
1083
+ semi-prime factor that cannot be reduced easily:
1084
+
1085
+ >>> from sympy.ntheory import isprime
1086
+ >>> a = 1407633717262338957430697921446883
1087
+ >>> f = factorint(a, limit=10000)
1088
+ >>> f == {991: 1, int(202916782076162456022877024859): 1, 7: 1}
1089
+ True
1090
+ >>> isprime(max(f))
1091
+ False
1092
+
1093
+ This number has a small factor and a residual perfect power whose
1094
+ base is greater than the limit:
1095
+
1096
+ >>> factorint(3*101**7, limit=5)
1097
+ {3: 1, 101: 7}
1098
+
1099
+ List of Factors:
1100
+
1101
+ If ``multiple`` is set to ``True`` then a list containing the
1102
+ prime factors including multiplicities is returned.
1103
+
1104
+ >>> factorint(24, multiple=True)
1105
+ [2, 2, 2, 3]
1106
+
1107
+ Visual Factorization:
1108
+
1109
+ If ``visual`` is set to ``True``, then it will return a visual
1110
+ factorization of the integer. For example:
1111
+
1112
+ >>> from sympy import pprint
1113
+ >>> pprint(factorint(4200, visual=True))
1114
+ 3 1 2 1
1115
+ 2 *3 *5 *7
1116
+
1117
+ Note that this is achieved by using the evaluate=False flag in Mul
1118
+ and Pow. If you do other manipulations with an expression where
1119
+ evaluate=False, it may evaluate. Therefore, you should use the
1120
+ visual option only for visualization, and use the normal dictionary
1121
+ returned by visual=False if you want to perform operations on the
1122
+ factors.
1123
+
1124
+ You can easily switch between the two forms by sending them back to
1125
+ factorint:
1126
+
1127
+ >>> from sympy import Mul
1128
+ >>> regular = factorint(1764); regular
1129
+ {2: 2, 3: 2, 7: 2}
1130
+ >>> pprint(factorint(regular))
1131
+ 2 2 2
1132
+ 2 *3 *7
1133
+
1134
+ >>> visual = factorint(1764, visual=True); pprint(visual)
1135
+ 2 2 2
1136
+ 2 *3 *7
1137
+ >>> print(factorint(visual))
1138
+ {2: 2, 3: 2, 7: 2}
1139
+
1140
+ If you want to send a number to be factored in a partially factored form
1141
+ you can do so with a dictionary or unevaluated expression:
1142
+
1143
+ >>> factorint(factorint({4: 2, 12: 3})) # twice to toggle to dict form
1144
+ {2: 10, 3: 3}
1145
+ >>> factorint(Mul(4, 12, evaluate=False))
1146
+ {2: 4, 3: 1}
1147
+
1148
+ The table of the output logic is:
1149
+
1150
+ ====== ====== ======= =======
1151
+ Visual
1152
+ ------ ----------------------
1153
+ Input True False other
1154
+ ====== ====== ======= =======
1155
+ dict mul dict mul
1156
+ n mul dict dict
1157
+ mul mul dict dict
1158
+ ====== ====== ======= =======
1159
+
1160
+ Notes
1161
+ =====
1162
+
1163
+ Algorithm:
1164
+
1165
+ The function switches between multiple algorithms. Trial division
1166
+ quickly finds small factors (of the order 1-5 digits), and finds
1167
+ all large factors if given enough time. The Pollard rho and p-1
1168
+ algorithms are used to find large factors ahead of time; they
1169
+ will often find factors of the order of 10 digits within a few
1170
+ seconds:
1171
+
1172
+ >>> factors = factorint(12345678910111213141516)
1173
+ >>> for base, exp in sorted(factors.items()):
1174
+ ... print('%s %s' % (base, exp))
1175
+ ...
1176
+ 2 2
1177
+ 2507191691 1
1178
+ 1231026625769 1
1179
+
1180
+ Any of these methods can optionally be disabled with the following
1181
+ boolean parameters:
1182
+
1183
+ - ``use_trial``: Toggle use of trial division
1184
+ - ``use_rho``: Toggle use of Pollard's rho method
1185
+ - ``use_pm1``: Toggle use of Pollard's p-1 method
1186
+
1187
+ ``factorint`` also periodically checks if the remaining part is
1188
+ a prime number or a perfect power, and in those cases stops.
1189
+
1190
+ For unevaluated factorial, it uses Legendre's formula(theorem).
1191
+
1192
+
1193
+ If ``verbose`` is set to ``True``, detailed progress is printed.
1194
+
1195
+ See Also
1196
+ ========
1197
+
1198
+ smoothness, smoothness_p, divisors
1199
+
1200
+ """
1201
+ if isinstance(n, Dict):
1202
+ n = dict(n)
1203
+ if multiple:
1204
+ fac = factorint(n, limit=limit, use_trial=use_trial,
1205
+ use_rho=use_rho, use_pm1=use_pm1,
1206
+ verbose=verbose, visual=False, multiple=False)
1207
+ factorlist = sum(([p] * fac[p] if fac[p] > 0 else [S.One/p]*(-fac[p])
1208
+ for p in sorted(fac)), [])
1209
+ return factorlist
1210
+
1211
+ factordict = {}
1212
+ if visual and not isinstance(n, (Mul, dict)):
1213
+ factordict = factorint(n, limit=limit, use_trial=use_trial,
1214
+ use_rho=use_rho, use_pm1=use_pm1,
1215
+ verbose=verbose, visual=False)
1216
+ elif isinstance(n, Mul):
1217
+ factordict = {int(k): int(v) for k, v in
1218
+ n.as_powers_dict().items()}
1219
+ elif isinstance(n, dict):
1220
+ factordict = n
1221
+ if factordict and isinstance(n, (Mul, dict)):
1222
+ # check it
1223
+ for key in list(factordict.keys()):
1224
+ if isprime(key):
1225
+ continue
1226
+ e = factordict.pop(key)
1227
+ d = factorint(key, limit=limit, use_trial=use_trial, use_rho=use_rho,
1228
+ use_pm1=use_pm1, verbose=verbose, visual=False)
1229
+ for k, v in d.items():
1230
+ if k in factordict:
1231
+ factordict[k] += v*e
1232
+ else:
1233
+ factordict[k] = v*e
1234
+ if visual or (type(n) is dict and
1235
+ visual is not True and
1236
+ visual is not False):
1237
+ if factordict == {}:
1238
+ return S.One
1239
+ if -1 in factordict:
1240
+ factordict.pop(-1)
1241
+ args = [S.NegativeOne]
1242
+ else:
1243
+ args = []
1244
+ args.extend([Pow(*i, evaluate=False)
1245
+ for i in sorted(factordict.items())])
1246
+ return Mul(*args, evaluate=False)
1247
+ elif isinstance(n, (dict, Mul)):
1248
+ return factordict
1249
+
1250
+ assert use_trial or use_rho or use_pm1 or use_ecm
1251
+
1252
+ from sympy.functions.combinatorial.factorials import factorial
1253
+ if isinstance(n, factorial):
1254
+ x = as_int(n.args[0])
1255
+ if x >= 20:
1256
+ factors = {}
1257
+ m = 2 # to initialize the if condition below
1258
+ for p in sieve.primerange(2, x + 1):
1259
+ if m > 1:
1260
+ m, q = 0, x // p
1261
+ while q != 0:
1262
+ m += q
1263
+ q //= p
1264
+ factors[p] = m
1265
+ if factors and verbose:
1266
+ for k in sorted(factors):
1267
+ print(factor_msg % (k, factors[k]))
1268
+ if verbose:
1269
+ print(complete_msg)
1270
+ return factors
1271
+ else:
1272
+ # if n < 20!, direct computation is faster
1273
+ # since it uses a lookup table
1274
+ n = n.func(x)
1275
+
1276
+ n = as_int(n)
1277
+ if limit:
1278
+ limit = int(limit)
1279
+ use_ecm = False
1280
+
1281
+ # special cases
1282
+ if n < 0:
1283
+ factors = factorint(
1284
+ -n, limit=limit, use_trial=use_trial, use_rho=use_rho,
1285
+ use_pm1=use_pm1, verbose=verbose, visual=False)
1286
+ factors[-1] = 1
1287
+ return factors
1288
+
1289
+ if limit and limit < 2:
1290
+ if n == 1:
1291
+ return {}
1292
+ return {n: 1}
1293
+ elif n < 10:
1294
+ # doing this we are assured of getting a limit > 2
1295
+ # when we have to compute it later
1296
+ return [{0: 1}, {}, {2: 1}, {3: 1}, {2: 2}, {5: 1},
1297
+ {2: 1, 3: 1}, {7: 1}, {2: 3}, {3: 2}][n]
1298
+
1299
+ factors = {}
1300
+
1301
+ # do simplistic factorization
1302
+ if verbose:
1303
+ sn = str(n)
1304
+ if len(sn) > 50:
1305
+ print('Factoring %s' % sn[:5] + \
1306
+ '..(%i other digits)..' % (len(sn) - 10) + sn[-5:])
1307
+ else:
1308
+ print('Factoring', n)
1309
+
1310
+ # this is the preliminary factorization for small factors
1311
+ # We want to guarantee that there are no small prime factors,
1312
+ # so we run even if `use_trial` is False.
1313
+ small = 2**15
1314
+ fail_max = 600
1315
+ small = min(small, limit or small)
1316
+ if verbose:
1317
+ print(trial_int_msg % (2, small, fail_max))
1318
+ n, next_p = _factorint_small(factors, n, small, fail_max)
1319
+ if factors and verbose:
1320
+ for k in sorted(factors):
1321
+ print(factor_msg % (k, factors[k]))
1322
+ if next_p == 0:
1323
+ if n > 1:
1324
+ factors[int(n)] = 1
1325
+ if verbose:
1326
+ print(complete_msg)
1327
+ return factors
1328
+ # first check if the simplistic run didn't finish
1329
+ # because of the limit and check for a perfect
1330
+ # power before exiting
1331
+ if limit and next_p > limit:
1332
+ if verbose:
1333
+ print('Exceeded limit:', limit)
1334
+ if _check_termination(factors, n, limit, use_trial,
1335
+ use_rho, use_pm1, verbose, next_p):
1336
+ return factors
1337
+ if n > 1:
1338
+ factors[int(n)] = 1
1339
+ return factors
1340
+ if _check_termination(factors, n, limit, use_trial,
1341
+ use_rho, use_pm1, verbose, next_p):
1342
+ return factors
1343
+
1344
+ # continue with more advanced factorization methods
1345
+ # ...do a Fermat test since it's so easy and we need the
1346
+ # square root anyway. Finding 2 factors is easy if they are
1347
+ # "close enough." This is the big root equivalent of dividing by
1348
+ # 2, 3, 5.
1349
+ sqrt_n = isqrt(n)
1350
+ a = sqrt_n + 1
1351
+ # If `n % 4 == 1`, `a` must be odd for `a**2 - n` to be a square number.
1352
+ if (n % 4 == 1) ^ (a & 1):
1353
+ a += 1
1354
+ a2 = a**2
1355
+ b2 = a2 - n
1356
+ for _ in range(3):
1357
+ b, fermat = sqrtrem(b2)
1358
+ if not fermat:
1359
+ if verbose:
1360
+ print(fermat_msg)
1361
+ for r in [a - b, a + b]:
1362
+ facs = factorint(r, limit=limit, use_trial=use_trial,
1363
+ use_rho=use_rho, use_pm1=use_pm1,
1364
+ verbose=verbose)
1365
+ for k, v in facs.items():
1366
+ factors[k] = factors.get(k, 0) + v
1367
+ if verbose:
1368
+ print(complete_msg)
1369
+ return factors
1370
+ b2 += (a + 1) << 2 # equiv to (a + 2)**2 - n
1371
+ a += 2
1372
+
1373
+ # these are the limits for trial division which will
1374
+ # be attempted in parallel with pollard methods
1375
+ low, high = next_p, 2*next_p
1376
+
1377
+ # add 1 to make sure limit is reached in primerange calls
1378
+ _limit = (limit or sqrt_n) + 1
1379
+ iteration = 0
1380
+ while 1:
1381
+ high_ = min(high, _limit)
1382
+
1383
+ # Trial division
1384
+ if use_trial:
1385
+ if verbose:
1386
+ print(trial_msg % (low, high_))
1387
+ ps = sieve.primerange(low, high_)
1388
+ n, found_trial = _trial(factors, n, ps, verbose)
1389
+ next_p = high_
1390
+ if found_trial and _check_termination(factors, n, limit, use_trial,
1391
+ use_rho, use_pm1, verbose, next_p):
1392
+ return factors
1393
+ else:
1394
+ found_trial = False
1395
+
1396
+ if high > _limit:
1397
+ if verbose:
1398
+ print('Exceeded limit:', _limit)
1399
+ if n > 1:
1400
+ factors[int(n)] = 1
1401
+ if verbose:
1402
+ print(complete_msg)
1403
+ return factors
1404
+
1405
+ # Only used advanced methods when no small factors were found
1406
+ if not found_trial:
1407
+ # Pollard p-1
1408
+ if use_pm1:
1409
+ if verbose:
1410
+ print(pm1_msg % (low, high_))
1411
+ c = pollard_pm1(n, B=low, seed=high_)
1412
+ if c:
1413
+ if c < next_p**2 or isprime(c):
1414
+ ps = [c]
1415
+ else:
1416
+ ps = factorint(c, limit=limit,
1417
+ use_trial=use_trial,
1418
+ use_rho=use_rho,
1419
+ use_pm1=use_pm1,
1420
+ use_ecm=use_ecm,
1421
+ verbose=verbose)
1422
+ n, _ = _trial(factors, n, ps, verbose=False)
1423
+ if _check_termination(factors, n, limit, use_trial,
1424
+ use_rho, use_pm1, verbose, next_p):
1425
+ return factors
1426
+
1427
+ # Pollard rho
1428
+ if use_rho:
1429
+ if verbose:
1430
+ print(rho_msg % (1, low, high_))
1431
+ c = pollard_rho(n, retries=1, max_steps=low, seed=high_)
1432
+ if c:
1433
+ if c < next_p**2 or isprime(c):
1434
+ ps = [c]
1435
+ else:
1436
+ ps = factorint(c, limit=limit,
1437
+ use_trial=use_trial,
1438
+ use_rho=use_rho,
1439
+ use_pm1=use_pm1,
1440
+ use_ecm=use_ecm,
1441
+ verbose=verbose)
1442
+ n, _ = _trial(factors, n, ps, verbose=False)
1443
+ if _check_termination(factors, n, limit, use_trial,
1444
+ use_rho, use_pm1, verbose, next_p):
1445
+ return factors
1446
+ # Use subexponential algorithms if use_ecm
1447
+ # Use pollard algorithms for finding small factors for 3 iterations
1448
+ # if after small factors the number of digits of n >= 25 then use ecm
1449
+ iteration += 1
1450
+ if use_ecm and iteration >= 3 and num_digits(n) >= 24:
1451
+ break
1452
+ low, high = high, high*2
1453
+
1454
+ B1 = 10000
1455
+ B2 = 100*B1
1456
+ num_curves = 50
1457
+ while(1):
1458
+ if verbose:
1459
+ print(ecm_msg % (B1, B2, num_curves))
1460
+ factor = _ecm_one_factor(n, B1, B2, num_curves, seed=B1)
1461
+ if factor:
1462
+ if factor < next_p**2 or isprime(factor):
1463
+ ps = [factor]
1464
+ else:
1465
+ ps = factorint(factor, limit=limit,
1466
+ use_trial=use_trial,
1467
+ use_rho=use_rho,
1468
+ use_pm1=use_pm1,
1469
+ use_ecm=use_ecm,
1470
+ verbose=verbose)
1471
+ n, _ = _trial(factors, n, ps, verbose=False)
1472
+ if _check_termination(factors, n, limit, use_trial,
1473
+ use_rho, use_pm1, verbose, next_p):
1474
+ return factors
1475
+ B1 *= 5
1476
+ B2 = 100*B1
1477
+ num_curves *= 4
1478
+
1479
+
1480
+ def factorrat(rat, limit=None, use_trial=True, use_rho=True, use_pm1=True,
1481
+ verbose=False, visual=None, multiple=False):
1482
+ r"""
1483
+ Given a Rational ``r``, ``factorrat(r)`` returns a dict containing
1484
+ the prime factors of ``r`` as keys and their respective multiplicities
1485
+ as values. For example:
1486
+
1487
+ >>> from sympy import factorrat, S
1488
+ >>> factorrat(S(8)/9) # 8/9 = (2**3) * (3**-2)
1489
+ {2: 3, 3: -2}
1490
+ >>> factorrat(S(-1)/987) # -1/789 = -1 * (3**-1) * (7**-1) * (47**-1)
1491
+ {-1: 1, 3: -1, 7: -1, 47: -1}
1492
+
1493
+ Please see the docstring for ``factorint`` for detailed explanations
1494
+ and examples of the following keywords:
1495
+
1496
+ - ``limit``: Integer limit up to which trial division is done
1497
+ - ``use_trial``: Toggle use of trial division
1498
+ - ``use_rho``: Toggle use of Pollard's rho method
1499
+ - ``use_pm1``: Toggle use of Pollard's p-1 method
1500
+ - ``verbose``: Toggle detailed printing of progress
1501
+ - ``multiple``: Toggle returning a list of factors or dict
1502
+ - ``visual``: Toggle product form of output
1503
+ """
1504
+ if multiple:
1505
+ fac = factorrat(rat, limit=limit, use_trial=use_trial,
1506
+ use_rho=use_rho, use_pm1=use_pm1,
1507
+ verbose=verbose, visual=False, multiple=False)
1508
+ factorlist = sum(([p] * fac[p] if fac[p] > 0 else [S.One/p]*(-fac[p])
1509
+ for p, _ in sorted(fac.items(),
1510
+ key=lambda elem: elem[0]
1511
+ if elem[1] > 0
1512
+ else 1/elem[0])), [])
1513
+ return factorlist
1514
+
1515
+ f = factorint(rat.p, limit=limit, use_trial=use_trial,
1516
+ use_rho=use_rho, use_pm1=use_pm1,
1517
+ verbose=verbose).copy()
1518
+ f = defaultdict(int, f)
1519
+ for p, e in factorint(rat.q, limit=limit,
1520
+ use_trial=use_trial,
1521
+ use_rho=use_rho,
1522
+ use_pm1=use_pm1,
1523
+ verbose=verbose).items():
1524
+ f[p] += -e
1525
+
1526
+ if len(f) > 1 and 1 in f:
1527
+ del f[1]
1528
+ if not visual:
1529
+ return dict(f)
1530
+ else:
1531
+ if -1 in f:
1532
+ f.pop(-1)
1533
+ args = [S.NegativeOne]
1534
+ else:
1535
+ args = []
1536
+ args.extend([Pow(*i, evaluate=False)
1537
+ for i in sorted(f.items())])
1538
+ return Mul(*args, evaluate=False)
1539
+
1540
+
1541
+ def primefactors(n, limit=None, verbose=False, **kwargs):
1542
+ """Return a sorted list of n's prime factors, ignoring multiplicity
1543
+ and any composite factor that remains if the limit was set too low
1544
+ for complete factorization. Unlike factorint(), primefactors() does
1545
+ not return -1 or 0.
1546
+
1547
+ Parameters
1548
+ ==========
1549
+
1550
+ n : integer
1551
+ limit, verbose, **kwargs :
1552
+ Additional keyword arguments to be passed to ``factorint``.
1553
+ Since ``kwargs`` is new in version 1.13,
1554
+ ``limit`` and ``verbose`` are retained for compatibility purposes.
1555
+
1556
+ Returns
1557
+ =======
1558
+
1559
+ list(int) : List of prime numbers dividing ``n``
1560
+
1561
+ Examples
1562
+ ========
1563
+
1564
+ >>> from sympy.ntheory import primefactors, factorint, isprime
1565
+ >>> primefactors(6)
1566
+ [2, 3]
1567
+ >>> primefactors(-5)
1568
+ [5]
1569
+
1570
+ >>> sorted(factorint(123456).items())
1571
+ [(2, 6), (3, 1), (643, 1)]
1572
+ >>> primefactors(123456)
1573
+ [2, 3, 643]
1574
+
1575
+ >>> sorted(factorint(10000000001, limit=200).items())
1576
+ [(101, 1), (99009901, 1)]
1577
+ >>> isprime(99009901)
1578
+ False
1579
+ >>> primefactors(10000000001, limit=300)
1580
+ [101]
1581
+
1582
+ See Also
1583
+ ========
1584
+
1585
+ factorint, divisors
1586
+
1587
+ """
1588
+ n = int(n)
1589
+ kwargs.update({"visual": None, "multiple": False,
1590
+ "limit": limit, "verbose": verbose})
1591
+ factors = sorted(factorint(n=n, **kwargs).keys())
1592
+ # We want to calculate
1593
+ # s = [f for f in factors if isprime(f)]
1594
+ s = [f for f in factors[:-1:] if f not in [-1, 0, 1]]
1595
+ if factors and isprime(factors[-1]):
1596
+ s += [factors[-1]]
1597
+ return s
1598
+
1599
+
1600
+ def _divisors(n, proper=False):
1601
+ """Helper function for divisors which generates the divisors.
1602
+
1603
+ Parameters
1604
+ ==========
1605
+
1606
+ n : int
1607
+ a nonnegative integer
1608
+ proper: bool
1609
+ If `True`, returns the generator that outputs only the proper divisor (i.e., excluding n).
1610
+
1611
+ """
1612
+ if n <= 1:
1613
+ if not proper and n:
1614
+ yield 1
1615
+ return
1616
+
1617
+ factordict = factorint(n)
1618
+ ps = sorted(factordict.keys())
1619
+
1620
+ def rec_gen(n=0):
1621
+ if n == len(ps):
1622
+ yield 1
1623
+ else:
1624
+ pows = [1]
1625
+ for _ in range(factordict[ps[n]]):
1626
+ pows.append(pows[-1] * ps[n])
1627
+ yield from (p * q for q in rec_gen(n + 1) for p in pows)
1628
+
1629
+ if proper:
1630
+ yield from (p for p in rec_gen() if p != n)
1631
+ else:
1632
+ yield from rec_gen()
1633
+
1634
+
1635
+ def divisors(n, generator=False, proper=False):
1636
+ r"""
1637
+ Return all divisors of n sorted from 1..n by default.
1638
+ If generator is ``True`` an unordered generator is returned.
1639
+
1640
+ The number of divisors of n can be quite large if there are many
1641
+ prime factors (counting repeated factors). If only the number of
1642
+ factors is desired use divisor_count(n).
1643
+
1644
+ Examples
1645
+ ========
1646
+
1647
+ >>> from sympy import divisors, divisor_count
1648
+ >>> divisors(24)
1649
+ [1, 2, 3, 4, 6, 8, 12, 24]
1650
+ >>> divisor_count(24)
1651
+ 8
1652
+
1653
+ >>> list(divisors(120, generator=True))
1654
+ [1, 2, 4, 8, 3, 6, 12, 24, 5, 10, 20, 40, 15, 30, 60, 120]
1655
+
1656
+ Notes
1657
+ =====
1658
+
1659
+ This is a slightly modified version of Tim Peters referenced at:
1660
+ https://stackoverflow.com/questions/1010381/python-factorization
1661
+
1662
+ See Also
1663
+ ========
1664
+
1665
+ primefactors, factorint, divisor_count
1666
+ """
1667
+ rv = _divisors(as_int(abs(n)), proper)
1668
+ return rv if generator else sorted(rv)
1669
+
1670
+
1671
+ def divisor_count(n, modulus=1, proper=False):
1672
+ """
1673
+ Return the number of divisors of ``n``. If ``modulus`` is not 1 then only
1674
+ those that are divisible by ``modulus`` are counted. If ``proper`` is True
1675
+ then the divisor of ``n`` will not be counted.
1676
+
1677
+ Examples
1678
+ ========
1679
+
1680
+ >>> from sympy import divisor_count
1681
+ >>> divisor_count(6)
1682
+ 4
1683
+ >>> divisor_count(6, 2)
1684
+ 2
1685
+ >>> divisor_count(6, proper=True)
1686
+ 3
1687
+
1688
+ See Also
1689
+ ========
1690
+
1691
+ factorint, divisors, totient, proper_divisor_count
1692
+
1693
+ """
1694
+
1695
+ if not modulus:
1696
+ return 0
1697
+ elif modulus != 1:
1698
+ n, r = divmod(n, modulus)
1699
+ if r:
1700
+ return 0
1701
+ if n == 0:
1702
+ return 0
1703
+ n = Mul(*[v + 1 for k, v in factorint(n).items() if k > 1])
1704
+ if n and proper:
1705
+ n -= 1
1706
+ return n
1707
+
1708
+
1709
+ def proper_divisors(n, generator=False):
1710
+ """
1711
+ Return all divisors of n except n, sorted by default.
1712
+ If generator is ``True`` an unordered generator is returned.
1713
+
1714
+ Examples
1715
+ ========
1716
+
1717
+ >>> from sympy import proper_divisors, proper_divisor_count
1718
+ >>> proper_divisors(24)
1719
+ [1, 2, 3, 4, 6, 8, 12]
1720
+ >>> proper_divisor_count(24)
1721
+ 7
1722
+ >>> list(proper_divisors(120, generator=True))
1723
+ [1, 2, 4, 8, 3, 6, 12, 24, 5, 10, 20, 40, 15, 30, 60]
1724
+
1725
+ See Also
1726
+ ========
1727
+
1728
+ factorint, divisors, proper_divisor_count
1729
+
1730
+ """
1731
+ return divisors(n, generator=generator, proper=True)
1732
+
1733
+
1734
+ def proper_divisor_count(n, modulus=1):
1735
+ """
1736
+ Return the number of proper divisors of ``n``.
1737
+
1738
+ Examples
1739
+ ========
1740
+
1741
+ >>> from sympy import proper_divisor_count
1742
+ >>> proper_divisor_count(6)
1743
+ 3
1744
+ >>> proper_divisor_count(6, modulus=2)
1745
+ 1
1746
+
1747
+ See Also
1748
+ ========
1749
+
1750
+ divisors, proper_divisors, divisor_count
1751
+
1752
+ """
1753
+ return divisor_count(n, modulus=modulus, proper=True)
1754
+
1755
+
1756
+ def _udivisors(n):
1757
+ """Helper function for udivisors which generates the unitary divisors.
1758
+
1759
+ Parameters
1760
+ ==========
1761
+
1762
+ n : int
1763
+ a nonnegative integer
1764
+
1765
+ """
1766
+ if n <= 1:
1767
+ if n == 1:
1768
+ yield 1
1769
+ return
1770
+
1771
+ factorpows = [p**e for p, e in factorint(n).items()]
1772
+ # We want to calculate
1773
+ # yield from (math.prod(s) for s in powersets(factorpows))
1774
+ for i in range(2**len(factorpows)):
1775
+ d = 1
1776
+ for k in range(i.bit_length()):
1777
+ if i & 1:
1778
+ d *= factorpows[k]
1779
+ i >>= 1
1780
+ yield d
1781
+
1782
+
1783
+ def udivisors(n, generator=False):
1784
+ r"""
1785
+ Return all unitary divisors of n sorted from 1..n by default.
1786
+ If generator is ``True`` an unordered generator is returned.
1787
+
1788
+ The number of unitary divisors of n can be quite large if there are many
1789
+ prime factors. If only the number of unitary divisors is desired use
1790
+ udivisor_count(n).
1791
+
1792
+ Examples
1793
+ ========
1794
+
1795
+ >>> from sympy.ntheory.factor_ import udivisors, udivisor_count
1796
+ >>> udivisors(15)
1797
+ [1, 3, 5, 15]
1798
+ >>> udivisor_count(15)
1799
+ 4
1800
+
1801
+ >>> sorted(udivisors(120, generator=True))
1802
+ [1, 3, 5, 8, 15, 24, 40, 120]
1803
+
1804
+ See Also
1805
+ ========
1806
+
1807
+ primefactors, factorint, divisors, divisor_count, udivisor_count
1808
+
1809
+ References
1810
+ ==========
1811
+
1812
+ .. [1] https://en.wikipedia.org/wiki/Unitary_divisor
1813
+ .. [2] https://mathworld.wolfram.com/UnitaryDivisor.html
1814
+
1815
+ """
1816
+ rv = _udivisors(as_int(abs(n)))
1817
+ return rv if generator else sorted(rv)
1818
+
1819
+
1820
+ def udivisor_count(n):
1821
+ """
1822
+ Return the number of unitary divisors of ``n``.
1823
+
1824
+ Parameters
1825
+ ==========
1826
+
1827
+ n : integer
1828
+
1829
+ Examples
1830
+ ========
1831
+
1832
+ >>> from sympy.ntheory.factor_ import udivisor_count
1833
+ >>> udivisor_count(120)
1834
+ 8
1835
+
1836
+ See Also
1837
+ ========
1838
+
1839
+ factorint, divisors, udivisors, divisor_count, totient
1840
+
1841
+ References
1842
+ ==========
1843
+
1844
+ .. [1] https://mathworld.wolfram.com/UnitaryDivisorFunction.html
1845
+
1846
+ """
1847
+
1848
+ if n == 0:
1849
+ return 0
1850
+ return 2**len([p for p in factorint(n) if p > 1])
1851
+
1852
+
1853
+ def _antidivisors(n):
1854
+ """Helper function for antidivisors which generates the antidivisors.
1855
+
1856
+ Parameters
1857
+ ==========
1858
+
1859
+ n : int
1860
+ a nonnegative integer
1861
+
1862
+ """
1863
+ if n <= 2:
1864
+ return
1865
+ for d in _divisors(n):
1866
+ y = 2*d
1867
+ if n > y and n % y:
1868
+ yield y
1869
+ for d in _divisors(2*n-1):
1870
+ if n > d >= 2 and n % d:
1871
+ yield d
1872
+ for d in _divisors(2*n+1):
1873
+ if n > d >= 2 and n % d:
1874
+ yield d
1875
+
1876
+
1877
+ def antidivisors(n, generator=False):
1878
+ r"""
1879
+ Return all antidivisors of n sorted from 1..n by default.
1880
+
1881
+ Antidivisors [1]_ of n are numbers that do not divide n by the largest
1882
+ possible margin. If generator is True an unordered generator is returned.
1883
+
1884
+ Examples
1885
+ ========
1886
+
1887
+ >>> from sympy.ntheory.factor_ import antidivisors
1888
+ >>> antidivisors(24)
1889
+ [7, 16]
1890
+
1891
+ >>> sorted(antidivisors(128, generator=True))
1892
+ [3, 5, 15, 17, 51, 85]
1893
+
1894
+ See Also
1895
+ ========
1896
+
1897
+ primefactors, factorint, divisors, divisor_count, antidivisor_count
1898
+
1899
+ References
1900
+ ==========
1901
+
1902
+ .. [1] definition is described in https://oeis.org/A066272/a066272a.html
1903
+
1904
+ """
1905
+ rv = _antidivisors(as_int(abs(n)))
1906
+ return rv if generator else sorted(rv)
1907
+
1908
+
1909
+ def antidivisor_count(n):
1910
+ """
1911
+ Return the number of antidivisors [1]_ of ``n``.
1912
+
1913
+ Parameters
1914
+ ==========
1915
+
1916
+ n : integer
1917
+
1918
+ Examples
1919
+ ========
1920
+
1921
+ >>> from sympy.ntheory.factor_ import antidivisor_count
1922
+ >>> antidivisor_count(13)
1923
+ 4
1924
+ >>> antidivisor_count(27)
1925
+ 5
1926
+
1927
+ See Also
1928
+ ========
1929
+
1930
+ factorint, divisors, antidivisors, divisor_count, totient
1931
+
1932
+ References
1933
+ ==========
1934
+
1935
+ .. [1] formula from https://oeis.org/A066272
1936
+
1937
+ """
1938
+
1939
+ n = as_int(abs(n))
1940
+ if n <= 2:
1941
+ return 0
1942
+ return divisor_count(2*n - 1) + divisor_count(2*n + 1) + \
1943
+ divisor_count(n) - divisor_count(n, 2) - 5
1944
+
1945
+ @deprecated("""\
1946
+ The `sympy.ntheory.factor_.totient` has been moved to `sympy.functions.combinatorial.numbers.totient`.""",
1947
+ deprecated_since_version="1.13",
1948
+ active_deprecations_target='deprecated-ntheory-symbolic-functions')
1949
+ def totient(n):
1950
+ r"""
1951
+ Calculate the Euler totient function phi(n)
1952
+
1953
+ .. deprecated:: 1.13
1954
+
1955
+ The ``totient`` function is deprecated. Use :class:`sympy.functions.combinatorial.numbers.totient`
1956
+ instead. See its documentation for more information. See
1957
+ :ref:`deprecated-ntheory-symbolic-functions` for details.
1958
+
1959
+ ``totient(n)`` or `\phi(n)` is the number of positive integers `\leq` n
1960
+ that are relatively prime to n.
1961
+
1962
+ Parameters
1963
+ ==========
1964
+
1965
+ n : integer
1966
+
1967
+ Examples
1968
+ ========
1969
+
1970
+ >>> from sympy.functions.combinatorial.numbers import totient
1971
+ >>> totient(1)
1972
+ 1
1973
+ >>> totient(25)
1974
+ 20
1975
+ >>> totient(45) == totient(5)*totient(9)
1976
+ True
1977
+
1978
+ See Also
1979
+ ========
1980
+
1981
+ divisor_count
1982
+
1983
+ References
1984
+ ==========
1985
+
1986
+ .. [1] https://en.wikipedia.org/wiki/Euler%27s_totient_function
1987
+ .. [2] https://mathworld.wolfram.com/TotientFunction.html
1988
+
1989
+ """
1990
+ from sympy.functions.combinatorial.numbers import totient as _totient
1991
+ return _totient(n)
1992
+
1993
+
1994
+ @deprecated("""\
1995
+ The `sympy.ntheory.factor_.reduced_totient` has been moved to `sympy.functions.combinatorial.numbers.reduced_totient`.""",
1996
+ deprecated_since_version="1.13",
1997
+ active_deprecations_target='deprecated-ntheory-symbolic-functions')
1998
+ def reduced_totient(n):
1999
+ r"""
2000
+ Calculate the Carmichael reduced totient function lambda(n)
2001
+
2002
+ .. deprecated:: 1.13
2003
+
2004
+ The ``reduced_totient`` function is deprecated. Use :class:`sympy.functions.combinatorial.numbers.reduced_totient`
2005
+ instead. See its documentation for more information. See
2006
+ :ref:`deprecated-ntheory-symbolic-functions` for details.
2007
+
2008
+ ``reduced_totient(n)`` or `\lambda(n)` is the smallest m > 0 such that
2009
+ `k^m \equiv 1 \mod n` for all k relatively prime to n.
2010
+
2011
+ Examples
2012
+ ========
2013
+
2014
+ >>> from sympy.functions.combinatorial.numbers import reduced_totient
2015
+ >>> reduced_totient(1)
2016
+ 1
2017
+ >>> reduced_totient(8)
2018
+ 2
2019
+ >>> reduced_totient(30)
2020
+ 4
2021
+
2022
+ See Also
2023
+ ========
2024
+
2025
+ totient
2026
+
2027
+ References
2028
+ ==========
2029
+
2030
+ .. [1] https://en.wikipedia.org/wiki/Carmichael_function
2031
+ .. [2] https://mathworld.wolfram.com/CarmichaelFunction.html
2032
+
2033
+ """
2034
+ from sympy.functions.combinatorial.numbers import reduced_totient as _reduced_totient
2035
+ return _reduced_totient(n)
2036
+
2037
+
2038
+ @deprecated("""\
2039
+ The `sympy.ntheory.factor_.divisor_sigma` has been moved to `sympy.functions.combinatorial.numbers.divisor_sigma`.""",
2040
+ deprecated_since_version="1.13",
2041
+ active_deprecations_target='deprecated-ntheory-symbolic-functions')
2042
+ def divisor_sigma(n, k=1):
2043
+ r"""
2044
+ Calculate the divisor function `\sigma_k(n)` for positive integer n
2045
+
2046
+ .. deprecated:: 1.13
2047
+
2048
+ The ``divisor_sigma`` function is deprecated. Use :class:`sympy.functions.combinatorial.numbers.divisor_sigma`
2049
+ instead. See its documentation for more information. See
2050
+ :ref:`deprecated-ntheory-symbolic-functions` for details.
2051
+
2052
+ ``divisor_sigma(n, k)`` is equal to ``sum([x**k for x in divisors(n)])``
2053
+
2054
+ If n's prime factorization is:
2055
+
2056
+ .. math ::
2057
+ n = \prod_{i=1}^\omega p_i^{m_i},
2058
+
2059
+ then
2060
+
2061
+ .. math ::
2062
+ \sigma_k(n) = \prod_{i=1}^\omega (1+p_i^k+p_i^{2k}+\cdots
2063
+ + p_i^{m_ik}).
2064
+
2065
+ Parameters
2066
+ ==========
2067
+
2068
+ n : integer
2069
+
2070
+ k : integer, optional
2071
+ power of divisors in the sum
2072
+
2073
+ for k = 0, 1:
2074
+ ``divisor_sigma(n, 0)`` is equal to ``divisor_count(n)``
2075
+ ``divisor_sigma(n, 1)`` is equal to ``sum(divisors(n))``
2076
+
2077
+ Default for k is 1.
2078
+
2079
+ Examples
2080
+ ========
2081
+
2082
+ >>> from sympy.functions.combinatorial.numbers import divisor_sigma
2083
+ >>> divisor_sigma(18, 0)
2084
+ 6
2085
+ >>> divisor_sigma(39, 1)
2086
+ 56
2087
+ >>> divisor_sigma(12, 2)
2088
+ 210
2089
+ >>> divisor_sigma(37)
2090
+ 38
2091
+
2092
+ See Also
2093
+ ========
2094
+
2095
+ divisor_count, totient, divisors, factorint
2096
+
2097
+ References
2098
+ ==========
2099
+
2100
+ .. [1] https://en.wikipedia.org/wiki/Divisor_function
2101
+
2102
+ """
2103
+ from sympy.functions.combinatorial.numbers import divisor_sigma as func_divisor_sigma
2104
+ return func_divisor_sigma(n, k)
2105
+
2106
+
2107
+ def _divisor_sigma(n:int, k:int=1) -> int:
2108
+ r""" Calculate the divisor function `\sigma_k(n)` for positive integer n
2109
+
2110
+ Parameters
2111
+ ==========
2112
+
2113
+ n : int
2114
+ positive integer
2115
+ k : int
2116
+ nonnegative integer
2117
+
2118
+ See Also
2119
+ ========
2120
+
2121
+ sympy.functions.combinatorial.numbers.divisor_sigma
2122
+
2123
+ """
2124
+ if k == 0:
2125
+ return math.prod(e + 1 for e in factorint(n).values())
2126
+ return math.prod((p**(k*(e + 1)) - 1)//(p**k - 1) for p, e in factorint(n).items())
2127
+
2128
+
2129
+ def core(n, t=2):
2130
+ r"""
2131
+ Calculate core(n, t) = `core_t(n)` of a positive integer n
2132
+
2133
+ ``core_2(n)`` is equal to the squarefree part of n
2134
+
2135
+ If n's prime factorization is:
2136
+
2137
+ .. math ::
2138
+ n = \prod_{i=1}^\omega p_i^{m_i},
2139
+
2140
+ then
2141
+
2142
+ .. math ::
2143
+ core_t(n) = \prod_{i=1}^\omega p_i^{m_i \mod t}.
2144
+
2145
+ Parameters
2146
+ ==========
2147
+
2148
+ n : integer
2149
+
2150
+ t : integer
2151
+ core(n, t) calculates the t-th power free part of n
2152
+
2153
+ ``core(n, 2)`` is the squarefree part of ``n``
2154
+ ``core(n, 3)`` is the cubefree part of ``n``
2155
+
2156
+ Default for t is 2.
2157
+
2158
+ Examples
2159
+ ========
2160
+
2161
+ >>> from sympy.ntheory.factor_ import core
2162
+ >>> core(24, 2)
2163
+ 6
2164
+ >>> core(9424, 3)
2165
+ 1178
2166
+ >>> core(379238)
2167
+ 379238
2168
+ >>> core(15**11, 10)
2169
+ 15
2170
+
2171
+ See Also
2172
+ ========
2173
+
2174
+ factorint, sympy.solvers.diophantine.diophantine.square_factor
2175
+
2176
+ References
2177
+ ==========
2178
+
2179
+ .. [1] https://en.wikipedia.org/wiki/Square-free_integer#Squarefree_core
2180
+
2181
+ """
2182
+
2183
+ n = as_int(n)
2184
+ t = as_int(t)
2185
+ if n <= 0:
2186
+ raise ValueError("n must be a positive integer")
2187
+ elif t <= 1:
2188
+ raise ValueError("t must be >= 2")
2189
+ else:
2190
+ y = 1
2191
+ for p, e in factorint(n).items():
2192
+ y *= p**(e % t)
2193
+ return y
2194
+
2195
+
2196
+ @deprecated("""\
2197
+ The `sympy.ntheory.factor_.udivisor_sigma` has been moved to `sympy.functions.combinatorial.numbers.udivisor_sigma`.""",
2198
+ deprecated_since_version="1.13",
2199
+ active_deprecations_target='deprecated-ntheory-symbolic-functions')
2200
+ def udivisor_sigma(n, k=1):
2201
+ r"""
2202
+ Calculate the unitary divisor function `\sigma_k^*(n)` for positive integer n
2203
+
2204
+ .. deprecated:: 1.13
2205
+
2206
+ The ``udivisor_sigma`` function is deprecated. Use :class:`sympy.functions.combinatorial.numbers.udivisor_sigma`
2207
+ instead. See its documentation for more information. See
2208
+ :ref:`deprecated-ntheory-symbolic-functions` for details.
2209
+
2210
+ ``udivisor_sigma(n, k)`` is equal to ``sum([x**k for x in udivisors(n)])``
2211
+
2212
+ If n's prime factorization is:
2213
+
2214
+ .. math ::
2215
+ n = \prod_{i=1}^\omega p_i^{m_i},
2216
+
2217
+ then
2218
+
2219
+ .. math ::
2220
+ \sigma_k^*(n) = \prod_{i=1}^\omega (1+ p_i^{m_ik}).
2221
+
2222
+ Parameters
2223
+ ==========
2224
+
2225
+ k : power of divisors in the sum
2226
+
2227
+ for k = 0, 1:
2228
+ ``udivisor_sigma(n, 0)`` is equal to ``udivisor_count(n)``
2229
+ ``udivisor_sigma(n, 1)`` is equal to ``sum(udivisors(n))``
2230
+
2231
+ Default for k is 1.
2232
+
2233
+ Examples
2234
+ ========
2235
+
2236
+ >>> from sympy.functions.combinatorial.numbers import udivisor_sigma
2237
+ >>> udivisor_sigma(18, 0)
2238
+ 4
2239
+ >>> udivisor_sigma(74, 1)
2240
+ 114
2241
+ >>> udivisor_sigma(36, 3)
2242
+ 47450
2243
+ >>> udivisor_sigma(111)
2244
+ 152
2245
+
2246
+ See Also
2247
+ ========
2248
+
2249
+ divisor_count, totient, divisors, udivisors, udivisor_count, divisor_sigma,
2250
+ factorint
2251
+
2252
+ References
2253
+ ==========
2254
+
2255
+ .. [1] https://mathworld.wolfram.com/UnitaryDivisorFunction.html
2256
+
2257
+ """
2258
+ from sympy.functions.combinatorial.numbers import udivisor_sigma as _udivisor_sigma
2259
+ return _udivisor_sigma(n, k)
2260
+
2261
+
2262
+ @deprecated("""\
2263
+ The `sympy.ntheory.factor_.primenu` has been moved to `sympy.functions.combinatorial.numbers.primenu`.""",
2264
+ deprecated_since_version="1.13",
2265
+ active_deprecations_target='deprecated-ntheory-symbolic-functions')
2266
+ def primenu(n):
2267
+ r"""
2268
+ Calculate the number of distinct prime factors for a positive integer n.
2269
+
2270
+ .. deprecated:: 1.13
2271
+
2272
+ The ``primenu`` function is deprecated. Use :class:`sympy.functions.combinatorial.numbers.primenu`
2273
+ instead. See its documentation for more information. See
2274
+ :ref:`deprecated-ntheory-symbolic-functions` for details.
2275
+
2276
+ If n's prime factorization is:
2277
+
2278
+ .. math ::
2279
+ n = \prod_{i=1}^k p_i^{m_i},
2280
+
2281
+ then ``primenu(n)`` or `\nu(n)` is:
2282
+
2283
+ .. math ::
2284
+ \nu(n) = k.
2285
+
2286
+ Examples
2287
+ ========
2288
+
2289
+ >>> from sympy.functions.combinatorial.numbers import primenu
2290
+ >>> primenu(1)
2291
+ 0
2292
+ >>> primenu(30)
2293
+ 3
2294
+
2295
+ See Also
2296
+ ========
2297
+
2298
+ factorint
2299
+
2300
+ References
2301
+ ==========
2302
+
2303
+ .. [1] https://mathworld.wolfram.com/PrimeFactor.html
2304
+
2305
+ """
2306
+ from sympy.functions.combinatorial.numbers import primenu as _primenu
2307
+ return _primenu(n)
2308
+
2309
+
2310
+ @deprecated("""\
2311
+ The `sympy.ntheory.factor_.primeomega` has been moved to `sympy.functions.combinatorial.numbers.primeomega`.""",
2312
+ deprecated_since_version="1.13",
2313
+ active_deprecations_target='deprecated-ntheory-symbolic-functions')
2314
+ def primeomega(n):
2315
+ r"""
2316
+ Calculate the number of prime factors counting multiplicities for a
2317
+ positive integer n.
2318
+
2319
+ .. deprecated:: 1.13
2320
+
2321
+ The ``primeomega`` function is deprecated. Use :class:`sympy.functions.combinatorial.numbers.primeomega`
2322
+ instead. See its documentation for more information. See
2323
+ :ref:`deprecated-ntheory-symbolic-functions` for details.
2324
+
2325
+ If n's prime factorization is:
2326
+
2327
+ .. math ::
2328
+ n = \prod_{i=1}^k p_i^{m_i},
2329
+
2330
+ then ``primeomega(n)`` or `\Omega(n)` is:
2331
+
2332
+ .. math ::
2333
+ \Omega(n) = \sum_{i=1}^k m_i.
2334
+
2335
+ Examples
2336
+ ========
2337
+
2338
+ >>> from sympy.functions.combinatorial.numbers import primeomega
2339
+ >>> primeomega(1)
2340
+ 0
2341
+ >>> primeomega(20)
2342
+ 3
2343
+
2344
+ See Also
2345
+ ========
2346
+
2347
+ factorint
2348
+
2349
+ References
2350
+ ==========
2351
+
2352
+ .. [1] https://mathworld.wolfram.com/PrimeFactor.html
2353
+
2354
+ """
2355
+ from sympy.functions.combinatorial.numbers import primeomega as _primeomega
2356
+ return _primeomega(n)
2357
+
2358
+
2359
+ def mersenne_prime_exponent(nth):
2360
+ """Returns the exponent ``i`` for the nth Mersenne prime (which
2361
+ has the form `2^i - 1`).
2362
+
2363
+ Examples
2364
+ ========
2365
+
2366
+ >>> from sympy.ntheory.factor_ import mersenne_prime_exponent
2367
+ >>> mersenne_prime_exponent(1)
2368
+ 2
2369
+ >>> mersenne_prime_exponent(20)
2370
+ 4423
2371
+ """
2372
+ n = as_int(nth)
2373
+ if n < 1:
2374
+ raise ValueError("nth must be a positive integer; mersenne_prime_exponent(1) == 2")
2375
+ if n > 51:
2376
+ raise ValueError("There are only 51 perfect numbers; nth must be less than or equal to 51")
2377
+ return MERSENNE_PRIME_EXPONENTS[n - 1]
2378
+
2379
+
2380
+ def is_perfect(n):
2381
+ """Returns True if ``n`` is a perfect number, else False.
2382
+
2383
+ A perfect number is equal to the sum of its positive, proper divisors.
2384
+
2385
+ Examples
2386
+ ========
2387
+
2388
+ >>> from sympy.functions.combinatorial.numbers import divisor_sigma
2389
+ >>> from sympy.ntheory.factor_ import is_perfect, divisors
2390
+ >>> is_perfect(20)
2391
+ False
2392
+ >>> is_perfect(6)
2393
+ True
2394
+ >>> 6 == divisor_sigma(6) - 6 == sum(divisors(6)[:-1])
2395
+ True
2396
+
2397
+ References
2398
+ ==========
2399
+
2400
+ .. [1] https://mathworld.wolfram.com/PerfectNumber.html
2401
+ .. [2] https://en.wikipedia.org/wiki/Perfect_number
2402
+
2403
+ """
2404
+ n = as_int(n)
2405
+ if n < 1:
2406
+ return False
2407
+ if n % 2 == 0:
2408
+ m = (n.bit_length() + 1) >> 1
2409
+ if (1 << (m - 1)) * ((1 << m) - 1) != n:
2410
+ # Even perfect numbers must be of the form `2^{m-1}(2^m-1)`
2411
+ return False
2412
+ return m in MERSENNE_PRIME_EXPONENTS or is_mersenne_prime(2**m - 1)
2413
+
2414
+ # n is an odd integer
2415
+ if n < 10**2000: # https://www.lirmm.fr/~ochem/opn/
2416
+ return False
2417
+ if n % 105 == 0: # not divis by 105
2418
+ return False
2419
+ if all(n % m != r for m, r in [(12, 1), (468, 117), (324, 81)]):
2420
+ return False
2421
+ # there are many criteria that the factor structure of n
2422
+ # must meet; since we will have to factor it to test the
2423
+ # structure we will have the factors and can then check
2424
+ # to see whether it is a perfect number or not. So we
2425
+ # skip the structure checks and go straight to the final
2426
+ # test below.
2427
+ result = abundance(n) == 0
2428
+ if result:
2429
+ raise ValueError(filldedent('''In 1888, Sylvester stated: "
2430
+ ...a prolonged meditation on the subject has satisfied
2431
+ me that the existence of any one such [odd perfect number]
2432
+ -- its escape, so to say, from the complex web of conditions
2433
+ which hem it in on all sides -- would be little short of a
2434
+ miracle." I guess SymPy just found that miracle and it
2435
+ factors like this: %s''' % factorint(n)))
2436
+ return result
2437
+
2438
+
2439
+ def abundance(n):
2440
+ """Returns the difference between the sum of the positive
2441
+ proper divisors of a number and the number.
2442
+
2443
+ Examples
2444
+ ========
2445
+
2446
+ >>> from sympy.ntheory import abundance, is_perfect, is_abundant
2447
+ >>> abundance(6)
2448
+ 0
2449
+ >>> is_perfect(6)
2450
+ True
2451
+ >>> abundance(10)
2452
+ -2
2453
+ >>> is_abundant(10)
2454
+ False
2455
+ """
2456
+ return _divisor_sigma(n) - 2 * n
2457
+
2458
+
2459
+ def is_abundant(n):
2460
+ """Returns True if ``n`` is an abundant number, else False.
2461
+
2462
+ A abundant number is smaller than the sum of its positive proper divisors.
2463
+
2464
+ Examples
2465
+ ========
2466
+
2467
+ >>> from sympy.ntheory.factor_ import is_abundant
2468
+ >>> is_abundant(20)
2469
+ True
2470
+ >>> is_abundant(15)
2471
+ False
2472
+
2473
+ References
2474
+ ==========
2475
+
2476
+ .. [1] https://mathworld.wolfram.com/AbundantNumber.html
2477
+
2478
+ """
2479
+ n = as_int(n)
2480
+ if is_perfect(n):
2481
+ return False
2482
+ return n % 6 == 0 or bool(abundance(n) > 0)
2483
+
2484
+
2485
+ def is_deficient(n):
2486
+ """Returns True if ``n`` is a deficient number, else False.
2487
+
2488
+ A deficient number is greater than the sum of its positive proper divisors.
2489
+
2490
+ Examples
2491
+ ========
2492
+
2493
+ >>> from sympy.ntheory.factor_ import is_deficient
2494
+ >>> is_deficient(20)
2495
+ False
2496
+ >>> is_deficient(15)
2497
+ True
2498
+
2499
+ References
2500
+ ==========
2501
+
2502
+ .. [1] https://mathworld.wolfram.com/DeficientNumber.html
2503
+
2504
+ """
2505
+ n = as_int(n)
2506
+ if is_perfect(n):
2507
+ return False
2508
+ return bool(abundance(n) < 0)
2509
+
2510
+
2511
+ def is_amicable(m, n):
2512
+ """Returns True if the numbers `m` and `n` are "amicable", else False.
2513
+
2514
+ Amicable numbers are two different numbers so related that the sum
2515
+ of the proper divisors of each is equal to that of the other.
2516
+
2517
+ Examples
2518
+ ========
2519
+
2520
+ >>> from sympy.functions.combinatorial.numbers import divisor_sigma
2521
+ >>> from sympy.ntheory.factor_ import is_amicable
2522
+ >>> is_amicable(220, 284)
2523
+ True
2524
+ >>> divisor_sigma(220) == divisor_sigma(284)
2525
+ True
2526
+
2527
+ References
2528
+ ==========
2529
+
2530
+ .. [1] https://en.wikipedia.org/wiki/Amicable_numbers
2531
+
2532
+ """
2533
+ return m != n and m + n == _divisor_sigma(m) == _divisor_sigma(n)
2534
+
2535
+
2536
+ def is_carmichael(n):
2537
+ """ Returns True if the numbers `n` is Carmichael number, else False.
2538
+
2539
+ Parameters
2540
+ ==========
2541
+
2542
+ n : Integer
2543
+
2544
+ References
2545
+ ==========
2546
+
2547
+ .. [1] https://en.wikipedia.org/wiki/Carmichael_number
2548
+ .. [2] https://oeis.org/A002997
2549
+
2550
+ """
2551
+ if n < 561:
2552
+ return False
2553
+ return n % 2 and not isprime(n) and \
2554
+ all(e == 1 and (n - 1) % (p - 1) == 0 for p, e in factorint(n).items())
2555
+
2556
+
2557
+ def find_carmichael_numbers_in_range(x, y):
2558
+ """ Returns a list of the number of Carmichael in the range
2559
+
2560
+ See Also
2561
+ ========
2562
+
2563
+ is_carmichael
2564
+
2565
+ """
2566
+ if 0 <= x <= y:
2567
+ if x % 2 == 0:
2568
+ return [i for i in range(x + 1, y, 2) if is_carmichael(i)]
2569
+ else:
2570
+ return [i for i in range(x, y, 2) if is_carmichael(i)]
2571
+ else:
2572
+ raise ValueError('The provided range is not valid. x and y must be non-negative integers and x <= y')
2573
+
2574
+
2575
+ def find_first_n_carmichaels(n):
2576
+ """ Returns the first n Carmichael numbers.
2577
+
2578
+ Parameters
2579
+ ==========
2580
+
2581
+ n : Integer
2582
+
2583
+ See Also
2584
+ ========
2585
+
2586
+ is_carmichael
2587
+
2588
+ """
2589
+ i = 561
2590
+ carmichaels = []
2591
+
2592
+ while len(carmichaels) < n:
2593
+ if is_carmichael(i):
2594
+ carmichaels.append(i)
2595
+ i += 2
2596
+
2597
+ return carmichaels
2598
+
2599
+
2600
+ def dra(n, b):
2601
+ """
2602
+ Returns the additive digital root of a natural number ``n`` in base ``b``
2603
+ which is a single digit value obtained by an iterative process of summing
2604
+ digits, on each iteration using the result from the previous iteration to
2605
+ compute a digit sum.
2606
+
2607
+ Examples
2608
+ ========
2609
+
2610
+ >>> from sympy.ntheory.factor_ import dra
2611
+ >>> dra(3110, 12)
2612
+ 8
2613
+
2614
+ References
2615
+ ==========
2616
+
2617
+ .. [1] https://en.wikipedia.org/wiki/Digital_root
2618
+
2619
+ """
2620
+
2621
+ num = abs(as_int(n))
2622
+ b = as_int(b)
2623
+ if b <= 1:
2624
+ raise ValueError("Base should be an integer greater than 1")
2625
+
2626
+ if num == 0:
2627
+ return 0
2628
+
2629
+ return (1 + (num - 1) % (b - 1))
2630
+
2631
+
2632
+ def drm(n, b):
2633
+ """
2634
+ Returns the multiplicative digital root of a natural number ``n`` in a given
2635
+ base ``b`` which is a single digit value obtained by an iterative process of
2636
+ multiplying digits, on each iteration using the result from the previous
2637
+ iteration to compute the digit multiplication.
2638
+
2639
+ Examples
2640
+ ========
2641
+
2642
+ >>> from sympy.ntheory.factor_ import drm
2643
+ >>> drm(9876, 10)
2644
+ 0
2645
+
2646
+ >>> drm(49, 10)
2647
+ 8
2648
+
2649
+ References
2650
+ ==========
2651
+
2652
+ .. [1] https://mathworld.wolfram.com/MultiplicativeDigitalRoot.html
2653
+
2654
+ """
2655
+
2656
+ n = abs(as_int(n))
2657
+ b = as_int(b)
2658
+ if b <= 1:
2659
+ raise ValueError("Base should be an integer greater than 1")
2660
+ while n > b:
2661
+ mul = 1
2662
+ while n > 1:
2663
+ n, r = divmod(n, b)
2664
+ if r == 0:
2665
+ return 0
2666
+ mul *= r
2667
+ n = mul
2668
+ return n
lib/python3.12/site-packages/sympy/ntheory/generate.py ADDED
@@ -0,0 +1,1147 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Generating and counting primes.
3
+
4
+ """
5
+
6
+ from bisect import bisect, bisect_left
7
+ from itertools import count
8
+ # Using arrays for sieving instead of lists greatly reduces
9
+ # memory consumption
10
+ from array import array as _array
11
+
12
+ from sympy.core.random import randint
13
+ from sympy.external.gmpy import sqrt
14
+ from .primetest import isprime
15
+ from sympy.utilities.decorator import deprecated
16
+ from sympy.utilities.misc import as_int
17
+
18
+
19
+ def _as_int_ceiling(a):
20
+ """ Wrapping ceiling in as_int will raise an error if there was a problem
21
+ determining whether the expression was exactly an integer or not."""
22
+ from sympy.functions.elementary.integers import ceiling
23
+ return as_int(ceiling(a))
24
+
25
+
26
+ class Sieve:
27
+ """A list of prime numbers, implemented as a dynamically
28
+ growing sieve of Eratosthenes. When a lookup is requested involving
29
+ an odd number that has not been sieved, the sieve is automatically
30
+ extended up to that number. Implementation details limit the number of
31
+ primes to ``2^32-1``.
32
+
33
+ Examples
34
+ ========
35
+
36
+ >>> from sympy import sieve
37
+ >>> sieve._reset() # this line for doctest only
38
+ >>> 25 in sieve
39
+ False
40
+ >>> sieve._list
41
+ array('L', [2, 3, 5, 7, 11, 13, 17, 19, 23])
42
+ """
43
+
44
+ # data shared (and updated) by all Sieve instances
45
+ def __init__(self, sieve_interval=1_000_000):
46
+ """ Initial parameters for the Sieve class.
47
+
48
+ Parameters
49
+ ==========
50
+
51
+ sieve_interval (int): Amount of memory to be used
52
+
53
+ Raises
54
+ ======
55
+
56
+ ValueError
57
+ If ``sieve_interval`` is not positive.
58
+
59
+ """
60
+ self._n = 6
61
+ self._list = _array('L', [2, 3, 5, 7, 11, 13]) # primes
62
+ self._tlist = _array('L', [0, 1, 1, 2, 2, 4]) # totient
63
+ self._mlist = _array('i', [0, 1, -1, -1, 0, -1]) # mobius
64
+ if sieve_interval <= 0:
65
+ raise ValueError("sieve_interval should be a positive integer")
66
+ self.sieve_interval = sieve_interval
67
+ assert all(len(i) == self._n for i in (self._list, self._tlist, self._mlist))
68
+
69
+ def __repr__(self):
70
+ return ("<%s sieve (%i): %i, %i, %i, ... %i, %i\n"
71
+ "%s sieve (%i): %i, %i, %i, ... %i, %i\n"
72
+ "%s sieve (%i): %i, %i, %i, ... %i, %i>") % (
73
+ 'prime', len(self._list),
74
+ self._list[0], self._list[1], self._list[2],
75
+ self._list[-2], self._list[-1],
76
+ 'totient', len(self._tlist),
77
+ self._tlist[0], self._tlist[1],
78
+ self._tlist[2], self._tlist[-2], self._tlist[-1],
79
+ 'mobius', len(self._mlist),
80
+ self._mlist[0], self._mlist[1],
81
+ self._mlist[2], self._mlist[-2], self._mlist[-1])
82
+
83
+ def _reset(self, prime=None, totient=None, mobius=None):
84
+ """Reset all caches (default). To reset one or more set the
85
+ desired keyword to True."""
86
+ if all(i is None for i in (prime, totient, mobius)):
87
+ prime = totient = mobius = True
88
+ if prime:
89
+ self._list = self._list[:self._n]
90
+ if totient:
91
+ self._tlist = self._tlist[:self._n]
92
+ if mobius:
93
+ self._mlist = self._mlist[:self._n]
94
+
95
+ def extend(self, n):
96
+ """Grow the sieve to cover all primes <= n.
97
+
98
+ Examples
99
+ ========
100
+
101
+ >>> from sympy import sieve
102
+ >>> sieve._reset() # this line for doctest only
103
+ >>> sieve.extend(30)
104
+ >>> sieve[10] == 29
105
+ True
106
+ """
107
+ n = int(n)
108
+ # `num` is even at any point in the function.
109
+ # This satisfies the condition required by `self._primerange`.
110
+ num = self._list[-1] + 1
111
+ if n < num:
112
+ return
113
+ num2 = num**2
114
+ while num2 <= n:
115
+ self._list += _array('L', self._primerange(num, num2))
116
+ num, num2 = num2, num2**2
117
+ # Merge the sieves
118
+ self._list += _array('L', self._primerange(num, n + 1))
119
+
120
+ def _primerange(self, a, b):
121
+ """ Generate all prime numbers in the range (a, b).
122
+
123
+ Parameters
124
+ ==========
125
+
126
+ a, b : positive integers assuming the following conditions
127
+ * a is an even number
128
+ * 2 < self._list[-1] < a < b < nextprime(self._list[-1])**2
129
+
130
+ Yields
131
+ ======
132
+
133
+ p (int): prime numbers such that ``a < p < b``
134
+
135
+ Examples
136
+ ========
137
+
138
+ >>> from sympy.ntheory.generate import Sieve
139
+ >>> s = Sieve()
140
+ >>> s._list[-1]
141
+ 13
142
+ >>> list(s._primerange(18, 31))
143
+ [19, 23, 29]
144
+
145
+ """
146
+ if b % 2:
147
+ b -= 1
148
+ while a < b:
149
+ block_size = min(self.sieve_interval, (b - a) // 2)
150
+ # Create the list such that block[x] iff (a + 2x + 1) is prime.
151
+ # Note that even numbers are not considered here.
152
+ block = [True] * block_size
153
+ for p in self._list[1:bisect(self._list, sqrt(a + 2 * block_size + 1))]:
154
+ for t in range((-(a + 1 + p) // 2) % p, block_size, p):
155
+ block[t] = False
156
+ for idx, p in enumerate(block):
157
+ if p:
158
+ yield a + 2 * idx + 1
159
+ a += 2 * block_size
160
+
161
+ def extend_to_no(self, i):
162
+ """Extend to include the ith prime number.
163
+
164
+ Parameters
165
+ ==========
166
+
167
+ i : integer
168
+
169
+ Examples
170
+ ========
171
+
172
+ >>> from sympy import sieve
173
+ >>> sieve._reset() # this line for doctest only
174
+ >>> sieve.extend_to_no(9)
175
+ >>> sieve._list
176
+ array('L', [2, 3, 5, 7, 11, 13, 17, 19, 23])
177
+
178
+ Notes
179
+ =====
180
+
181
+ The list is extended by 50% if it is too short, so it is
182
+ likely that it will be longer than requested.
183
+ """
184
+ i = as_int(i)
185
+ while len(self._list) < i:
186
+ self.extend(int(self._list[-1] * 1.5))
187
+
188
+ def primerange(self, a, b=None):
189
+ """Generate all prime numbers in the range [2, a) or [a, b).
190
+
191
+ Examples
192
+ ========
193
+
194
+ >>> from sympy import sieve, prime
195
+
196
+ All primes less than 19:
197
+
198
+ >>> print([i for i in sieve.primerange(19)])
199
+ [2, 3, 5, 7, 11, 13, 17]
200
+
201
+ All primes greater than or equal to 7 and less than 19:
202
+
203
+ >>> print([i for i in sieve.primerange(7, 19)])
204
+ [7, 11, 13, 17]
205
+
206
+ All primes through the 10th prime
207
+
208
+ >>> list(sieve.primerange(prime(10) + 1))
209
+ [2, 3, 5, 7, 11, 13, 17, 19, 23, 29]
210
+
211
+ """
212
+ if b is None:
213
+ b = _as_int_ceiling(a)
214
+ a = 2
215
+ else:
216
+ a = max(2, _as_int_ceiling(a))
217
+ b = _as_int_ceiling(b)
218
+ if a >= b:
219
+ return
220
+ self.extend(b)
221
+ yield from self._list[bisect_left(self._list, a):
222
+ bisect_left(self._list, b)]
223
+
224
+ def totientrange(self, a, b):
225
+ """Generate all totient numbers for the range [a, b).
226
+
227
+ Examples
228
+ ========
229
+
230
+ >>> from sympy import sieve
231
+ >>> print([i for i in sieve.totientrange(7, 18)])
232
+ [6, 4, 6, 4, 10, 4, 12, 6, 8, 8, 16]
233
+ """
234
+ a = max(1, _as_int_ceiling(a))
235
+ b = _as_int_ceiling(b)
236
+ n = len(self._tlist)
237
+ if a >= b:
238
+ return
239
+ elif b <= n:
240
+ for i in range(a, b):
241
+ yield self._tlist[i]
242
+ else:
243
+ self._tlist += _array('L', range(n, b))
244
+ for i in range(1, n):
245
+ ti = self._tlist[i]
246
+ if ti == i - 1:
247
+ startindex = (n + i - 1) // i * i
248
+ for j in range(startindex, b, i):
249
+ self._tlist[j] -= self._tlist[j] // i
250
+ if i >= a:
251
+ yield ti
252
+
253
+ for i in range(n, b):
254
+ ti = self._tlist[i]
255
+ if ti == i:
256
+ for j in range(i, b, i):
257
+ self._tlist[j] -= self._tlist[j] // i
258
+ if i >= a:
259
+ yield self._tlist[i]
260
+
261
+ def mobiusrange(self, a, b):
262
+ """Generate all mobius numbers for the range [a, b).
263
+
264
+ Parameters
265
+ ==========
266
+
267
+ a : integer
268
+ First number in range
269
+
270
+ b : integer
271
+ First number outside of range
272
+
273
+ Examples
274
+ ========
275
+
276
+ >>> from sympy import sieve
277
+ >>> print([i for i in sieve.mobiusrange(7, 18)])
278
+ [-1, 0, 0, 1, -1, 0, -1, 1, 1, 0, -1]
279
+ """
280
+ a = max(1, _as_int_ceiling(a))
281
+ b = _as_int_ceiling(b)
282
+ n = len(self._mlist)
283
+ if a >= b:
284
+ return
285
+ elif b <= n:
286
+ for i in range(a, b):
287
+ yield self._mlist[i]
288
+ else:
289
+ self._mlist += _array('i', [0]*(b - n))
290
+ for i in range(1, n):
291
+ mi = self._mlist[i]
292
+ startindex = (n + i - 1) // i * i
293
+ for j in range(startindex, b, i):
294
+ self._mlist[j] -= mi
295
+ if i >= a:
296
+ yield mi
297
+
298
+ for i in range(n, b):
299
+ mi = self._mlist[i]
300
+ for j in range(2 * i, b, i):
301
+ self._mlist[j] -= mi
302
+ if i >= a:
303
+ yield mi
304
+
305
+ def search(self, n):
306
+ """Return the indices i, j of the primes that bound n.
307
+
308
+ If n is prime then i == j.
309
+
310
+ Although n can be an expression, if ceiling cannot convert
311
+ it to an integer then an n error will be raised.
312
+
313
+ Examples
314
+ ========
315
+
316
+ >>> from sympy import sieve
317
+ >>> sieve.search(25)
318
+ (9, 10)
319
+ >>> sieve.search(23)
320
+ (9, 9)
321
+ """
322
+ test = _as_int_ceiling(n)
323
+ n = as_int(n)
324
+ if n < 2:
325
+ raise ValueError("n should be >= 2 but got: %s" % n)
326
+ if n > self._list[-1]:
327
+ self.extend(n)
328
+ b = bisect(self._list, n)
329
+ if self._list[b - 1] == test:
330
+ return b, b
331
+ else:
332
+ return b, b + 1
333
+
334
+ def __contains__(self, n):
335
+ try:
336
+ n = as_int(n)
337
+ assert n >= 2
338
+ except (ValueError, AssertionError):
339
+ return False
340
+ if n % 2 == 0:
341
+ return n == 2
342
+ a, b = self.search(n)
343
+ return a == b
344
+
345
+ def __iter__(self):
346
+ for n in count(1):
347
+ yield self[n]
348
+
349
+ def __getitem__(self, n):
350
+ """Return the nth prime number"""
351
+ if isinstance(n, slice):
352
+ self.extend_to_no(n.stop)
353
+ # Python 2.7 slices have 0 instead of None for start, so
354
+ # we can't default to 1.
355
+ start = n.start if n.start is not None else 0
356
+ if start < 1:
357
+ # sieve[:5] would be empty (starting at -1), let's
358
+ # just be explicit and raise.
359
+ raise IndexError("Sieve indices start at 1.")
360
+ return self._list[start - 1:n.stop - 1:n.step]
361
+ else:
362
+ if n < 1:
363
+ # offset is one, so forbid explicit access to sieve[0]
364
+ # (would surprisingly return the last one).
365
+ raise IndexError("Sieve indices start at 1.")
366
+ n = as_int(n)
367
+ self.extend_to_no(n)
368
+ return self._list[n - 1]
369
+
370
+ # Generate a global object for repeated use in trial division etc
371
+ sieve = Sieve()
372
+
373
+
374
+ def prime(nth):
375
+ r""" Return the nth prime, with the primes indexed as prime(1) = 2,
376
+ prime(2) = 3, etc.... The nth prime is approximately $n\log(n)$.
377
+
378
+ Logarithmic integral of $x$ is a pretty nice approximation for number of
379
+ primes $\le x$, i.e.
380
+ li(x) ~ pi(x)
381
+ In fact, for the numbers we are concerned about( x<1e11 ),
382
+ li(x) - pi(x) < 50000
383
+
384
+ Also,
385
+ li(x) > pi(x) can be safely assumed for the numbers which
386
+ can be evaluated by this function.
387
+
388
+ Here, we find the least integer m such that li(m) > n using binary search.
389
+ Now pi(m-1) < li(m-1) <= n,
390
+
391
+ We find pi(m - 1) using primepi function.
392
+
393
+ Starting from m, we have to find n - pi(m-1) more primes.
394
+
395
+ For the inputs this implementation can handle, we will have to test
396
+ primality for at max about 10**5 numbers, to get our answer.
397
+
398
+ Examples
399
+ ========
400
+
401
+ >>> from sympy import prime
402
+ >>> prime(10)
403
+ 29
404
+ >>> prime(1)
405
+ 2
406
+ >>> prime(100000)
407
+ 1299709
408
+
409
+ See Also
410
+ ========
411
+
412
+ sympy.ntheory.primetest.isprime : Test if n is prime
413
+ primerange : Generate all primes in a given range
414
+ primepi : Return the number of primes less than or equal to n
415
+
416
+ References
417
+ ==========
418
+
419
+ .. [1] https://en.wikipedia.org/wiki/Prime_number_theorem#Table_of_.CF.80.28x.29.2C_x_.2F_log_x.2C_and_li.28x.29
420
+ .. [2] https://en.wikipedia.org/wiki/Prime_number_theorem#Approximations_for_the_nth_prime_number
421
+ .. [3] https://en.wikipedia.org/wiki/Skewes%27_number
422
+ """
423
+ n = as_int(nth)
424
+ if n < 1:
425
+ raise ValueError("nth must be a positive integer; prime(1) == 2")
426
+ if n <= len(sieve._list):
427
+ return sieve[n]
428
+
429
+ from sympy.functions.elementary.exponential import log
430
+ from sympy.functions.special.error_functions import li
431
+ a = 2 # Lower bound for binary search
432
+ # leave n inside int since int(i*r) != i*int(r) is not a valid property
433
+ # e.g. int(2*.5) != 2*int(.5)
434
+ b = int(n*(log(n) + log(log(n)))) # Upper bound for the search.
435
+
436
+ while a < b:
437
+ mid = (a + b) >> 1
438
+ if li(mid) > n:
439
+ b = mid
440
+ else:
441
+ a = mid + 1
442
+ n_primes = _primepi(a - 1)
443
+ while n_primes < n:
444
+ if isprime(a):
445
+ n_primes += 1
446
+ a += 1
447
+ return a - 1
448
+
449
+ @deprecated("""\
450
+ The `sympy.ntheory.generate.primepi` has been moved to `sympy.functions.combinatorial.numbers.primepi`.""",
451
+ deprecated_since_version="1.13",
452
+ active_deprecations_target='deprecated-ntheory-symbolic-functions')
453
+ def primepi(n):
454
+ r""" Represents the prime counting function pi(n) = the number
455
+ of prime numbers less than or equal to n.
456
+
457
+ .. deprecated:: 1.13
458
+
459
+ The ``primepi`` function is deprecated. Use :class:`sympy.functions.combinatorial.numbers.primepi`
460
+ instead. See its documentation for more information. See
461
+ :ref:`deprecated-ntheory-symbolic-functions` for details.
462
+
463
+ Algorithm Description:
464
+
465
+ In sieve method, we remove all multiples of prime p
466
+ except p itself.
467
+
468
+ Let phi(i,j) be the number of integers 2 <= k <= i
469
+ which remain after sieving from primes less than
470
+ or equal to j.
471
+ Clearly, pi(n) = phi(n, sqrt(n))
472
+
473
+ If j is not a prime,
474
+ phi(i,j) = phi(i, j - 1)
475
+
476
+ if j is a prime,
477
+ We remove all numbers(except j) whose
478
+ smallest prime factor is j.
479
+
480
+ Let $x= j \times a$ be such a number, where $2 \le a \le i / j$
481
+ Now, after sieving from primes $\le j - 1$,
482
+ a must remain
483
+ (because x, and hence a has no prime factor $\le j - 1$)
484
+ Clearly, there are phi(i / j, j - 1) such a
485
+ which remain on sieving from primes $\le j - 1$
486
+
487
+ Now, if a is a prime less than equal to j - 1,
488
+ $x= j \times a$ has smallest prime factor = a, and
489
+ has already been removed(by sieving from a).
490
+ So, we do not need to remove it again.
491
+ (Note: there will be pi(j - 1) such x)
492
+
493
+ Thus, number of x, that will be removed are:
494
+ phi(i / j, j - 1) - phi(j - 1, j - 1)
495
+ (Note that pi(j - 1) = phi(j - 1, j - 1))
496
+
497
+ $\Rightarrow$ phi(i,j) = phi(i, j - 1) - phi(i / j, j - 1) + phi(j - 1, j - 1)
498
+
499
+ So,following recursion is used and implemented as dp:
500
+
501
+ phi(a, b) = phi(a, b - 1), if b is not a prime
502
+ phi(a, b) = phi(a, b-1)-phi(a / b, b-1) + phi(b-1, b-1), if b is prime
503
+
504
+ Clearly a is always of the form floor(n / k),
505
+ which can take at most $2\sqrt{n}$ values.
506
+ Two arrays arr1,arr2 are maintained
507
+ arr1[i] = phi(i, j),
508
+ arr2[i] = phi(n // i, j)
509
+
510
+ Finally the answer is arr2[1]
511
+
512
+ Examples
513
+ ========
514
+
515
+ >>> from sympy import primepi, prime, prevprime, isprime
516
+ >>> primepi(25)
517
+ 9
518
+
519
+ So there are 9 primes less than or equal to 25. Is 25 prime?
520
+
521
+ >>> isprime(25)
522
+ False
523
+
524
+ It is not. So the first prime less than 25 must be the
525
+ 9th prime:
526
+
527
+ >>> prevprime(25) == prime(9)
528
+ True
529
+
530
+ See Also
531
+ ========
532
+
533
+ sympy.ntheory.primetest.isprime : Test if n is prime
534
+ primerange : Generate all primes in a given range
535
+ prime : Return the nth prime
536
+ """
537
+ from sympy.functions.combinatorial.numbers import primepi as func_primepi
538
+ return func_primepi(n)
539
+
540
+
541
+ def _primepi(n:int) -> int:
542
+ r""" Represents the prime counting function pi(n) = the number
543
+ of prime numbers less than or equal to n.
544
+
545
+ Explanation
546
+ ===========
547
+
548
+ In sieve method, we remove all multiples of prime p
549
+ except p itself.
550
+
551
+ Let phi(i,j) be the number of integers 2 <= k <= i
552
+ which remain after sieving from primes less than
553
+ or equal to j.
554
+ Clearly, pi(n) = phi(n, sqrt(n))
555
+
556
+ If j is not a prime,
557
+ phi(i,j) = phi(i, j - 1)
558
+
559
+ if j is a prime,
560
+ We remove all numbers(except j) whose
561
+ smallest prime factor is j.
562
+
563
+ Let $x= j \times a$ be such a number, where $2 \le a \le i / j$
564
+ Now, after sieving from primes $\le j - 1$,
565
+ a must remain
566
+ (because x, and hence a has no prime factor $\le j - 1$)
567
+ Clearly, there are phi(i / j, j - 1) such a
568
+ which remain on sieving from primes $\le j - 1$
569
+
570
+ Now, if a is a prime less than equal to j - 1,
571
+ $x= j \times a$ has smallest prime factor = a, and
572
+ has already been removed(by sieving from a).
573
+ So, we do not need to remove it again.
574
+ (Note: there will be pi(j - 1) such x)
575
+
576
+ Thus, number of x, that will be removed are:
577
+ phi(i / j, j - 1) - phi(j - 1, j - 1)
578
+ (Note that pi(j - 1) = phi(j - 1, j - 1))
579
+
580
+ $\Rightarrow$ phi(i,j) = phi(i, j - 1) - phi(i / j, j - 1) + phi(j - 1, j - 1)
581
+
582
+ So,following recursion is used and implemented as dp:
583
+
584
+ phi(a, b) = phi(a, b - 1), if b is not a prime
585
+ phi(a, b) = phi(a, b-1)-phi(a / b, b-1) + phi(b-1, b-1), if b is prime
586
+
587
+ Clearly a is always of the form floor(n / k),
588
+ which can take at most $2\sqrt{n}$ values.
589
+ Two arrays arr1,arr2 are maintained
590
+ arr1[i] = phi(i, j),
591
+ arr2[i] = phi(n // i, j)
592
+
593
+ Finally the answer is arr2[1]
594
+
595
+ Parameters
596
+ ==========
597
+
598
+ n : int
599
+
600
+ """
601
+ if n < 2:
602
+ return 0
603
+ if n <= sieve._list[-1]:
604
+ return sieve.search(n)[0]
605
+ lim = sqrt(n)
606
+ arr1 = [0] * (lim + 1)
607
+ arr2 = [0] * (lim + 1)
608
+ for i in range(1, lim + 1):
609
+ arr1[i] = i - 1
610
+ arr2[i] = n // i - 1
611
+ for i in range(2, lim + 1):
612
+ # Presently, arr1[k]=phi(k,i - 1),
613
+ # arr2[k] = phi(n // k,i - 1)
614
+ if arr1[i] == arr1[i - 1]:
615
+ continue
616
+ p = arr1[i - 1]
617
+ for j in range(1, min(n // (i * i), lim) + 1):
618
+ st = i * j
619
+ if st <= lim:
620
+ arr2[j] -= arr2[st] - p
621
+ else:
622
+ arr2[j] -= arr1[n // st] - p
623
+ lim2 = min(lim, i * i - 1)
624
+ for j in range(lim, lim2, -1):
625
+ arr1[j] -= arr1[j // i] - p
626
+ return arr2[1]
627
+
628
+
629
+ def nextprime(n, ith=1):
630
+ """ Return the ith prime greater than n.
631
+
632
+ Parameters
633
+ ==========
634
+
635
+ n : integer
636
+ ith : positive integer
637
+
638
+ Returns
639
+ =======
640
+
641
+ int : Return the ith prime greater than n
642
+
643
+ Raises
644
+ ======
645
+
646
+ ValueError
647
+ If ``ith <= 0``.
648
+ If ``n`` or ``ith`` is not an integer.
649
+
650
+ Notes
651
+ =====
652
+
653
+ Potential primes are located at 6*j +/- 1. This
654
+ property is used during searching.
655
+
656
+ >>> from sympy import nextprime
657
+ >>> [(i, nextprime(i)) for i in range(10, 15)]
658
+ [(10, 11), (11, 13), (12, 13), (13, 17), (14, 17)]
659
+ >>> nextprime(2, ith=2) # the 2nd prime after 2
660
+ 5
661
+
662
+ See Also
663
+ ========
664
+
665
+ prevprime : Return the largest prime smaller than n
666
+ primerange : Generate all primes in a given range
667
+
668
+ """
669
+ n = int(n)
670
+ i = as_int(ith)
671
+ if i <= 0:
672
+ raise ValueError("ith should be positive")
673
+ if n < 2:
674
+ n = 2
675
+ i -= 1
676
+ if n <= sieve._list[-2]:
677
+ l, _ = sieve.search(n)
678
+ if l + i - 1 < len(sieve._list):
679
+ return sieve._list[l + i - 1]
680
+ return nextprime(sieve._list[-1], l + i - len(sieve._list))
681
+ if 1 < i:
682
+ for _ in range(i):
683
+ n = nextprime(n)
684
+ return n
685
+ nn = 6*(n//6)
686
+ if nn == n:
687
+ n += 1
688
+ if isprime(n):
689
+ return n
690
+ n += 4
691
+ elif n - nn == 5:
692
+ n += 2
693
+ if isprime(n):
694
+ return n
695
+ n += 4
696
+ else:
697
+ n = nn + 5
698
+ while 1:
699
+ if isprime(n):
700
+ return n
701
+ n += 2
702
+ if isprime(n):
703
+ return n
704
+ n += 4
705
+
706
+
707
+ def prevprime(n):
708
+ """ Return the largest prime smaller than n.
709
+
710
+ Notes
711
+ =====
712
+
713
+ Potential primes are located at 6*j +/- 1. This
714
+ property is used during searching.
715
+
716
+ >>> from sympy import prevprime
717
+ >>> [(i, prevprime(i)) for i in range(10, 15)]
718
+ [(10, 7), (11, 7), (12, 11), (13, 11), (14, 13)]
719
+
720
+ See Also
721
+ ========
722
+
723
+ nextprime : Return the ith prime greater than n
724
+ primerange : Generates all primes in a given range
725
+ """
726
+ n = _as_int_ceiling(n)
727
+ if n < 3:
728
+ raise ValueError("no preceding primes")
729
+ if n < 8:
730
+ return {3: 2, 4: 3, 5: 3, 6: 5, 7: 5}[n]
731
+ if n <= sieve._list[-1]:
732
+ l, u = sieve.search(n)
733
+ if l == u:
734
+ return sieve[l-1]
735
+ else:
736
+ return sieve[l]
737
+ nn = 6*(n//6)
738
+ if n - nn <= 1:
739
+ n = nn - 1
740
+ if isprime(n):
741
+ return n
742
+ n -= 4
743
+ else:
744
+ n = nn + 1
745
+ while 1:
746
+ if isprime(n):
747
+ return n
748
+ n -= 2
749
+ if isprime(n):
750
+ return n
751
+ n -= 4
752
+
753
+
754
+ def primerange(a, b=None):
755
+ """ Generate a list of all prime numbers in the range [2, a),
756
+ or [a, b).
757
+
758
+ If the range exists in the default sieve, the values will
759
+ be returned from there; otherwise values will be returned
760
+ but will not modify the sieve.
761
+
762
+ Examples
763
+ ========
764
+
765
+ >>> from sympy import primerange, prime
766
+
767
+ All primes less than 19:
768
+
769
+ >>> list(primerange(19))
770
+ [2, 3, 5, 7, 11, 13, 17]
771
+
772
+ All primes greater than or equal to 7 and less than 19:
773
+
774
+ >>> list(primerange(7, 19))
775
+ [7, 11, 13, 17]
776
+
777
+ All primes through the 10th prime
778
+
779
+ >>> list(primerange(prime(10) + 1))
780
+ [2, 3, 5, 7, 11, 13, 17, 19, 23, 29]
781
+
782
+ The Sieve method, primerange, is generally faster but it will
783
+ occupy more memory as the sieve stores values. The default
784
+ instance of Sieve, named sieve, can be used:
785
+
786
+ >>> from sympy import sieve
787
+ >>> list(sieve.primerange(1, 30))
788
+ [2, 3, 5, 7, 11, 13, 17, 19, 23, 29]
789
+
790
+ Notes
791
+ =====
792
+
793
+ Some famous conjectures about the occurrence of primes in a given
794
+ range are [1]:
795
+
796
+ - Twin primes: though often not, the following will give 2 primes
797
+ an infinite number of times:
798
+ primerange(6*n - 1, 6*n + 2)
799
+ - Legendre's: the following always yields at least one prime
800
+ primerange(n**2, (n+1)**2+1)
801
+ - Bertrand's (proven): there is always a prime in the range
802
+ primerange(n, 2*n)
803
+ - Brocard's: there are at least four primes in the range
804
+ primerange(prime(n)**2, prime(n+1)**2)
805
+
806
+ The average gap between primes is log(n) [2]; the gap between
807
+ primes can be arbitrarily large since sequences of composite
808
+ numbers are arbitrarily large, e.g. the numbers in the sequence
809
+ n! + 2, n! + 3 ... n! + n are all composite.
810
+
811
+ See Also
812
+ ========
813
+
814
+ prime : Return the nth prime
815
+ nextprime : Return the ith prime greater than n
816
+ prevprime : Return the largest prime smaller than n
817
+ randprime : Returns a random prime in a given range
818
+ primorial : Returns the product of primes based on condition
819
+ Sieve.primerange : return range from already computed primes
820
+ or extend the sieve to contain the requested
821
+ range.
822
+
823
+ References
824
+ ==========
825
+
826
+ .. [1] https://en.wikipedia.org/wiki/Prime_number
827
+ .. [2] https://primes.utm.edu/notes/gaps.html
828
+ """
829
+ if b is None:
830
+ a, b = 2, a
831
+ if a >= b:
832
+ return
833
+ # If we already have the range, return it.
834
+ largest_known_prime = sieve._list[-1]
835
+ if b <= largest_known_prime:
836
+ yield from sieve.primerange(a, b)
837
+ return
838
+ # If we know some of it, return it.
839
+ if a <= largest_known_prime:
840
+ yield from sieve._list[bisect_left(sieve._list, a):]
841
+ a = largest_known_prime + 1
842
+ elif a % 2:
843
+ a -= 1
844
+ tail = min(b, (largest_known_prime)**2)
845
+ if a < tail:
846
+ yield from sieve._primerange(a, tail)
847
+ a = tail
848
+ if b <= a:
849
+ return
850
+ # otherwise compute, without storing, the desired range.
851
+ while 1:
852
+ a = nextprime(a)
853
+ if a < b:
854
+ yield a
855
+ else:
856
+ return
857
+
858
+
859
+ def randprime(a, b):
860
+ """ Return a random prime number in the range [a, b).
861
+
862
+ Bertrand's postulate assures that
863
+ randprime(a, 2*a) will always succeed for a > 1.
864
+
865
+ Note that due to implementation difficulties,
866
+ the prime numbers chosen are not uniformly random.
867
+ For example, there are two primes in the range [112, 128),
868
+ ``113`` and ``127``, but ``randprime(112, 128)`` returns ``127``
869
+ with a probability of 15/17.
870
+
871
+ Examples
872
+ ========
873
+
874
+ >>> from sympy import randprime, isprime
875
+ >>> randprime(1, 30) #doctest: +SKIP
876
+ 13
877
+ >>> isprime(randprime(1, 30))
878
+ True
879
+
880
+ See Also
881
+ ========
882
+
883
+ primerange : Generate all primes in a given range
884
+
885
+ References
886
+ ==========
887
+
888
+ .. [1] https://en.wikipedia.org/wiki/Bertrand's_postulate
889
+
890
+ """
891
+ if a >= b:
892
+ return
893
+ a, b = map(int, (a, b))
894
+ n = randint(a - 1, b)
895
+ p = nextprime(n)
896
+ if p >= b:
897
+ p = prevprime(b)
898
+ if p < a:
899
+ raise ValueError("no primes exist in the specified range")
900
+ return p
901
+
902
+
903
+ def primorial(n, nth=True):
904
+ """
905
+ Returns the product of the first n primes (default) or
906
+ the primes less than or equal to n (when ``nth=False``).
907
+
908
+ Examples
909
+ ========
910
+
911
+ >>> from sympy.ntheory.generate import primorial, primerange
912
+ >>> from sympy import factorint, Mul, primefactors, sqrt
913
+ >>> primorial(4) # the first 4 primes are 2, 3, 5, 7
914
+ 210
915
+ >>> primorial(4, nth=False) # primes <= 4 are 2 and 3
916
+ 6
917
+ >>> primorial(1)
918
+ 2
919
+ >>> primorial(1, nth=False)
920
+ 1
921
+ >>> primorial(sqrt(101), nth=False)
922
+ 210
923
+
924
+ One can argue that the primes are infinite since if you take
925
+ a set of primes and multiply them together (e.g. the primorial) and
926
+ then add or subtract 1, the result cannot be divided by any of the
927
+ original factors, hence either 1 or more new primes must divide this
928
+ product of primes.
929
+
930
+ In this case, the number itself is a new prime:
931
+
932
+ >>> factorint(primorial(4) + 1)
933
+ {211: 1}
934
+
935
+ In this case two new primes are the factors:
936
+
937
+ >>> factorint(primorial(4) - 1)
938
+ {11: 1, 19: 1}
939
+
940
+ Here, some primes smaller and larger than the primes multiplied together
941
+ are obtained:
942
+
943
+ >>> p = list(primerange(10, 20))
944
+ >>> sorted(set(primefactors(Mul(*p) + 1)).difference(set(p)))
945
+ [2, 5, 31, 149]
946
+
947
+ See Also
948
+ ========
949
+
950
+ primerange : Generate all primes in a given range
951
+
952
+ """
953
+ if nth:
954
+ n = as_int(n)
955
+ else:
956
+ n = int(n)
957
+ if n < 1:
958
+ raise ValueError("primorial argument must be >= 1")
959
+ p = 1
960
+ if nth:
961
+ for i in range(1, n + 1):
962
+ p *= prime(i)
963
+ else:
964
+ for i in primerange(2, n + 1):
965
+ p *= i
966
+ return p
967
+
968
+
969
+ def cycle_length(f, x0, nmax=None, values=False):
970
+ """For a given iterated sequence, return a generator that gives
971
+ the length of the iterated cycle (lambda) and the length of terms
972
+ before the cycle begins (mu); if ``values`` is True then the
973
+ terms of the sequence will be returned instead. The sequence is
974
+ started with value ``x0``.
975
+
976
+ Note: more than the first lambda + mu terms may be returned and this
977
+ is the cost of cycle detection with Brent's method; there are, however,
978
+ generally less terms calculated than would have been calculated if the
979
+ proper ending point were determined, e.g. by using Floyd's method.
980
+
981
+ >>> from sympy.ntheory.generate import cycle_length
982
+
983
+ This will yield successive values of i <-- func(i):
984
+
985
+ >>> def gen(func, i):
986
+ ... while 1:
987
+ ... yield i
988
+ ... i = func(i)
989
+ ...
990
+
991
+ A function is defined:
992
+
993
+ >>> func = lambda i: (i**2 + 1) % 51
994
+
995
+ and given a seed of 4 and the mu and lambda terms calculated:
996
+
997
+ >>> next(cycle_length(func, 4))
998
+ (6, 3)
999
+
1000
+ We can see what is meant by looking at the output:
1001
+
1002
+ >>> iter = cycle_length(func, 4, values=True)
1003
+ >>> list(iter)
1004
+ [4, 17, 35, 2, 5, 26, 14, 44, 50, 2, 5, 26, 14]
1005
+
1006
+ There are 6 repeating values after the first 3.
1007
+
1008
+ If a sequence is suspected of being longer than you might wish, ``nmax``
1009
+ can be used to exit early (and mu will be returned as None):
1010
+
1011
+ >>> next(cycle_length(func, 4, nmax = 4))
1012
+ (4, None)
1013
+ >>> list(cycle_length(func, 4, nmax = 4, values=True))
1014
+ [4, 17, 35, 2]
1015
+
1016
+ Code modified from:
1017
+ https://en.wikipedia.org/wiki/Cycle_detection.
1018
+ """
1019
+
1020
+ nmax = int(nmax or 0)
1021
+
1022
+ # main phase: search successive powers of two
1023
+ power = lam = 1
1024
+ tortoise, hare = x0, f(x0) # f(x0) is the element/node next to x0.
1025
+ i = 1
1026
+ if values:
1027
+ yield tortoise
1028
+ while tortoise != hare and (not nmax or i < nmax):
1029
+ i += 1
1030
+ if power == lam: # time to start a new power of two?
1031
+ tortoise = hare
1032
+ power *= 2
1033
+ lam = 0
1034
+ if values:
1035
+ yield hare
1036
+ hare = f(hare)
1037
+ lam += 1
1038
+ if nmax and i == nmax:
1039
+ if values:
1040
+ return
1041
+ else:
1042
+ yield nmax, None
1043
+ return
1044
+ if not values:
1045
+ # Find the position of the first repetition of length lambda
1046
+ mu = 0
1047
+ tortoise = hare = x0
1048
+ for i in range(lam):
1049
+ hare = f(hare)
1050
+ while tortoise != hare:
1051
+ tortoise = f(tortoise)
1052
+ hare = f(hare)
1053
+ mu += 1
1054
+ yield lam, mu
1055
+
1056
+
1057
+ def composite(nth):
1058
+ """ Return the nth composite number, with the composite numbers indexed as
1059
+ composite(1) = 4, composite(2) = 6, etc....
1060
+
1061
+ Examples
1062
+ ========
1063
+
1064
+ >>> from sympy import composite
1065
+ >>> composite(36)
1066
+ 52
1067
+ >>> composite(1)
1068
+ 4
1069
+ >>> composite(17737)
1070
+ 20000
1071
+
1072
+ See Also
1073
+ ========
1074
+
1075
+ sympy.ntheory.primetest.isprime : Test if n is prime
1076
+ primerange : Generate all primes in a given range
1077
+ primepi : Return the number of primes less than or equal to n
1078
+ prime : Return the nth prime
1079
+ compositepi : Return the number of positive composite numbers less than or equal to n
1080
+ """
1081
+ n = as_int(nth)
1082
+ if n < 1:
1083
+ raise ValueError("nth must be a positive integer; composite(1) == 4")
1084
+ composite_arr = [4, 6, 8, 9, 10, 12, 14, 15, 16, 18]
1085
+ if n <= 10:
1086
+ return composite_arr[n - 1]
1087
+
1088
+ a, b = 4, sieve._list[-1]
1089
+ if n <= b - _primepi(b) - 1:
1090
+ while a < b - 1:
1091
+ mid = (a + b) >> 1
1092
+ if mid - _primepi(mid) - 1 > n:
1093
+ b = mid
1094
+ else:
1095
+ a = mid
1096
+ if isprime(a):
1097
+ a -= 1
1098
+ return a
1099
+
1100
+ from sympy.functions.elementary.exponential import log
1101
+ from sympy.functions.special.error_functions import li
1102
+ a = 4 # Lower bound for binary search
1103
+ b = int(n*(log(n) + log(log(n)))) # Upper bound for the search.
1104
+
1105
+ while a < b:
1106
+ mid = (a + b) >> 1
1107
+ if mid - li(mid) - 1 > n:
1108
+ b = mid
1109
+ else:
1110
+ a = mid + 1
1111
+
1112
+ n_composites = a - _primepi(a) - 1
1113
+ while n_composites > n:
1114
+ if not isprime(a):
1115
+ n_composites -= 1
1116
+ a -= 1
1117
+ if isprime(a):
1118
+ a -= 1
1119
+ return a
1120
+
1121
+
1122
+ def compositepi(n):
1123
+ """ Return the number of positive composite numbers less than or equal to n.
1124
+ The first positive composite is 4, i.e. compositepi(4) = 1.
1125
+
1126
+ Examples
1127
+ ========
1128
+
1129
+ >>> from sympy import compositepi
1130
+ >>> compositepi(25)
1131
+ 15
1132
+ >>> compositepi(1000)
1133
+ 831
1134
+
1135
+ See Also
1136
+ ========
1137
+
1138
+ sympy.ntheory.primetest.isprime : Test if n is prime
1139
+ primerange : Generate all primes in a given range
1140
+ prime : Return the nth prime
1141
+ primepi : Return the number of primes less than or equal to n
1142
+ composite : Return the nth composite number
1143
+ """
1144
+ n = int(n)
1145
+ if n < 4:
1146
+ return 0
1147
+ return n - _primepi(n) - 1
lib/python3.12/site-packages/sympy/ntheory/modular.py ADDED
@@ -0,0 +1,291 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from math import prod
2
+
3
+ from sympy.external.gmpy import gcd, gcdext
4
+ from sympy.ntheory.primetest import isprime
5
+ from sympy.polys.domains import ZZ
6
+ from sympy.polys.galoistools import gf_crt, gf_crt1, gf_crt2
7
+ from sympy.utilities.misc import as_int
8
+
9
+
10
+ def symmetric_residue(a, m):
11
+ """Return the residual mod m such that it is within half of the modulus.
12
+
13
+ >>> from sympy.ntheory.modular import symmetric_residue
14
+ >>> symmetric_residue(1, 6)
15
+ 1
16
+ >>> symmetric_residue(4, 6)
17
+ -2
18
+ """
19
+ if a <= m // 2:
20
+ return a
21
+ return a - m
22
+
23
+
24
+ def crt(m, v, symmetric=False, check=True):
25
+ r"""Chinese Remainder Theorem.
26
+
27
+ The moduli in m are assumed to be pairwise coprime. The output
28
+ is then an integer f, such that f = v_i mod m_i for each pair out
29
+ of v and m. If ``symmetric`` is False a positive integer will be
30
+ returned, else \|f\| will be less than or equal to the LCM of the
31
+ moduli, and thus f may be negative.
32
+
33
+ If the moduli are not co-prime the correct result will be returned
34
+ if/when the test of the result is found to be incorrect. This result
35
+ will be None if there is no solution.
36
+
37
+ The keyword ``check`` can be set to False if it is known that the moduli
38
+ are coprime.
39
+
40
+ Examples
41
+ ========
42
+
43
+ As an example consider a set of residues ``U = [49, 76, 65]``
44
+ and a set of moduli ``M = [99, 97, 95]``. Then we have::
45
+
46
+ >>> from sympy.ntheory.modular import crt
47
+
48
+ >>> crt([99, 97, 95], [49, 76, 65])
49
+ (639985, 912285)
50
+
51
+ This is the correct result because::
52
+
53
+ >>> [639985 % m for m in [99, 97, 95]]
54
+ [49, 76, 65]
55
+
56
+ If the moduli are not co-prime, you may receive an incorrect result
57
+ if you use ``check=False``:
58
+
59
+ >>> crt([12, 6, 17], [3, 4, 2], check=False)
60
+ (954, 1224)
61
+ >>> [954 % m for m in [12, 6, 17]]
62
+ [6, 0, 2]
63
+ >>> crt([12, 6, 17], [3, 4, 2]) is None
64
+ True
65
+ >>> crt([3, 6], [2, 5])
66
+ (5, 6)
67
+
68
+ Note: the order of gf_crt's arguments is reversed relative to crt,
69
+ and that solve_congruence takes residue, modulus pairs.
70
+
71
+ Programmer's note: rather than checking that all pairs of moduli share
72
+ no GCD (an O(n**2) test) and rather than factoring all moduli and seeing
73
+ that there is no factor in common, a check that the result gives the
74
+ indicated residuals is performed -- an O(n) operation.
75
+
76
+ See Also
77
+ ========
78
+
79
+ solve_congruence
80
+ sympy.polys.galoistools.gf_crt : low level crt routine used by this routine
81
+ """
82
+ if check:
83
+ m = list(map(as_int, m))
84
+ v = list(map(as_int, v))
85
+
86
+ result = gf_crt(v, m, ZZ)
87
+ mm = prod(m)
88
+
89
+ if check:
90
+ if not all(v % m == result % m for v, m in zip(v, m)):
91
+ result = solve_congruence(*list(zip(v, m)),
92
+ check=False, symmetric=symmetric)
93
+ if result is None:
94
+ return result
95
+ result, mm = result
96
+
97
+ if symmetric:
98
+ return int(symmetric_residue(result, mm)), int(mm)
99
+ return int(result), int(mm)
100
+
101
+
102
+ def crt1(m):
103
+ """First part of Chinese Remainder Theorem, for multiple application.
104
+
105
+ Examples
106
+ ========
107
+
108
+ >>> from sympy.ntheory.modular import crt, crt1, crt2
109
+ >>> m = [99, 97, 95]
110
+ >>> v = [49, 76, 65]
111
+
112
+ The following two codes have the same result.
113
+
114
+ >>> crt(m, v)
115
+ (639985, 912285)
116
+
117
+ >>> mm, e, s = crt1(m)
118
+ >>> crt2(m, v, mm, e, s)
119
+ (639985, 912285)
120
+
121
+ However, it is faster when we want to fix ``m`` and
122
+ compute for multiple ``v``, i.e. the following cases:
123
+
124
+ >>> mm, e, s = crt1(m)
125
+ >>> vs = [[52, 21, 37], [19, 46, 76]]
126
+ >>> for v in vs:
127
+ ... print(crt2(m, v, mm, e, s))
128
+ (397042, 912285)
129
+ (803206, 912285)
130
+
131
+ See Also
132
+ ========
133
+
134
+ sympy.polys.galoistools.gf_crt1 : low level crt routine used by this routine
135
+ sympy.ntheory.modular.crt
136
+ sympy.ntheory.modular.crt2
137
+
138
+ """
139
+
140
+ return gf_crt1(m, ZZ)
141
+
142
+
143
+ def crt2(m, v, mm, e, s, symmetric=False):
144
+ """Second part of Chinese Remainder Theorem, for multiple application.
145
+
146
+ See ``crt1`` for usage.
147
+
148
+ Examples
149
+ ========
150
+
151
+ >>> from sympy.ntheory.modular import crt1, crt2
152
+ >>> mm, e, s = crt1([18, 42, 6])
153
+ >>> crt2([18, 42, 6], [0, 0, 0], mm, e, s)
154
+ (0, 4536)
155
+
156
+ See Also
157
+ ========
158
+
159
+ sympy.polys.galoistools.gf_crt2 : low level crt routine used by this routine
160
+ sympy.ntheory.modular.crt
161
+ sympy.ntheory.modular.crt1
162
+
163
+ """
164
+
165
+ result = gf_crt2(v, m, mm, e, s, ZZ)
166
+
167
+ if symmetric:
168
+ return int(symmetric_residue(result, mm)), int(mm)
169
+ return int(result), int(mm)
170
+
171
+
172
+ def solve_congruence(*remainder_modulus_pairs, **hint):
173
+ """Compute the integer ``n`` that has the residual ``ai`` when it is
174
+ divided by ``mi`` where the ``ai`` and ``mi`` are given as pairs to
175
+ this function: ((a1, m1), (a2, m2), ...). If there is no solution,
176
+ return None. Otherwise return ``n`` and its modulus.
177
+
178
+ The ``mi`` values need not be co-prime. If it is known that the moduli are
179
+ not co-prime then the hint ``check`` can be set to False (default=True) and
180
+ the check for a quicker solution via crt() (valid when the moduli are
181
+ co-prime) will be skipped.
182
+
183
+ If the hint ``symmetric`` is True (default is False), the value of ``n``
184
+ will be within 1/2 of the modulus, possibly negative.
185
+
186
+ Examples
187
+ ========
188
+
189
+ >>> from sympy.ntheory.modular import solve_congruence
190
+
191
+ What number is 2 mod 3, 3 mod 5 and 2 mod 7?
192
+
193
+ >>> solve_congruence((2, 3), (3, 5), (2, 7))
194
+ (23, 105)
195
+ >>> [23 % m for m in [3, 5, 7]]
196
+ [2, 3, 2]
197
+
198
+ If you prefer to work with all remainder in one list and
199
+ all moduli in another, send the arguments like this:
200
+
201
+ >>> solve_congruence(*zip((2, 3, 2), (3, 5, 7)))
202
+ (23, 105)
203
+
204
+ The moduli need not be co-prime; in this case there may or
205
+ may not be a solution:
206
+
207
+ >>> solve_congruence((2, 3), (4, 6)) is None
208
+ True
209
+
210
+ >>> solve_congruence((2, 3), (5, 6))
211
+ (5, 6)
212
+
213
+ The symmetric flag will make the result be within 1/2 of the modulus:
214
+
215
+ >>> solve_congruence((2, 3), (5, 6), symmetric=True)
216
+ (-1, 6)
217
+
218
+ See Also
219
+ ========
220
+
221
+ crt : high level routine implementing the Chinese Remainder Theorem
222
+
223
+ """
224
+ def combine(c1, c2):
225
+ """Return the tuple (a, m) which satisfies the requirement
226
+ that n = a + i*m satisfy n = a1 + j*m1 and n = a2 = k*m2.
227
+
228
+ References
229
+ ==========
230
+
231
+ .. [1] https://en.wikipedia.org/wiki/Method_of_successive_substitution
232
+ """
233
+ a1, m1 = c1
234
+ a2, m2 = c2
235
+ a, b, c = m1, a2 - a1, m2
236
+ g = gcd(a, b, c)
237
+ a, b, c = [i//g for i in [a, b, c]]
238
+ if a != 1:
239
+ g, inv_a, _ = gcdext(a, c)
240
+ if g != 1:
241
+ return None
242
+ b *= inv_a
243
+ a, m = a1 + m1*b, m1*c
244
+ return a, m
245
+
246
+ rm = remainder_modulus_pairs
247
+ symmetric = hint.get('symmetric', False)
248
+
249
+ if hint.get('check', True):
250
+ rm = [(as_int(r), as_int(m)) for r, m in rm]
251
+
252
+ # ignore redundant pairs but raise an error otherwise; also
253
+ # make sure that a unique set of bases is sent to gf_crt if
254
+ # they are all prime.
255
+ #
256
+ # The routine will work out less-trivial violations and
257
+ # return None, e.g. for the pairs (1,3) and (14,42) there
258
+ # is no answer because 14 mod 42 (having a gcd of 14) implies
259
+ # (14/2) mod (42/2), (14/7) mod (42/7) and (14/14) mod (42/14)
260
+ # which, being 0 mod 3, is inconsistent with 1 mod 3. But to
261
+ # preprocess the input beyond checking of another pair with 42
262
+ # or 3 as the modulus (for this example) is not necessary.
263
+ uniq = {}
264
+ for r, m in rm:
265
+ r %= m
266
+ if m in uniq:
267
+ if r != uniq[m]:
268
+ return None
269
+ continue
270
+ uniq[m] = r
271
+ rm = [(r, m) for m, r in uniq.items()]
272
+ del uniq
273
+
274
+ # if the moduli are co-prime, the crt will be significantly faster;
275
+ # checking all pairs for being co-prime gets to be slow but a prime
276
+ # test is a good trade-off
277
+ if all(isprime(m) for r, m in rm):
278
+ r, m = list(zip(*rm))
279
+ return crt(m, r, symmetric=symmetric, check=False)
280
+
281
+ rv = (0, 1)
282
+ for rmi in rm:
283
+ rv = combine(rv, rmi)
284
+ if rv is None:
285
+ break
286
+ n, m = rv
287
+ n = n % m
288
+ else:
289
+ if symmetric:
290
+ return symmetric_residue(n, m), m
291
+ return n, m
lib/python3.12/site-packages/sympy/ntheory/multinomial.py ADDED
@@ -0,0 +1,188 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from sympy.utilities.misc import as_int
2
+
3
+
4
+ def binomial_coefficients(n):
5
+ """Return a dictionary containing pairs :math:`{(k1,k2) : C_kn}` where
6
+ :math:`C_kn` are binomial coefficients and :math:`n=k1+k2`.
7
+
8
+ Examples
9
+ ========
10
+
11
+ >>> from sympy.ntheory import binomial_coefficients
12
+ >>> binomial_coefficients(9)
13
+ {(0, 9): 1, (1, 8): 9, (2, 7): 36, (3, 6): 84,
14
+ (4, 5): 126, (5, 4): 126, (6, 3): 84, (7, 2): 36, (8, 1): 9, (9, 0): 1}
15
+
16
+ See Also
17
+ ========
18
+
19
+ binomial_coefficients_list, multinomial_coefficients
20
+ """
21
+ n = as_int(n)
22
+ d = {(0, n): 1, (n, 0): 1}
23
+ a = 1
24
+ for k in range(1, n//2 + 1):
25
+ a = (a * (n - k + 1))//k
26
+ d[k, n - k] = d[n - k, k] = a
27
+ return d
28
+
29
+
30
+ def binomial_coefficients_list(n):
31
+ """ Return a list of binomial coefficients as rows of the Pascal's
32
+ triangle.
33
+
34
+ Examples
35
+ ========
36
+
37
+ >>> from sympy.ntheory import binomial_coefficients_list
38
+ >>> binomial_coefficients_list(9)
39
+ [1, 9, 36, 84, 126, 126, 84, 36, 9, 1]
40
+
41
+ See Also
42
+ ========
43
+
44
+ binomial_coefficients, multinomial_coefficients
45
+ """
46
+ n = as_int(n)
47
+ d = [1] * (n + 1)
48
+ a = 1
49
+ for k in range(1, n//2 + 1):
50
+ a = (a * (n - k + 1))//k
51
+ d[k] = d[n - k] = a
52
+ return d
53
+
54
+
55
+ def multinomial_coefficients(m, n):
56
+ r"""Return a dictionary containing pairs ``{(k1,k2,..,km) : C_kn}``
57
+ where ``C_kn`` are multinomial coefficients such that
58
+ ``n=k1+k2+..+km``.
59
+
60
+ Examples
61
+ ========
62
+
63
+ >>> from sympy.ntheory import multinomial_coefficients
64
+ >>> multinomial_coefficients(2, 5) # indirect doctest
65
+ {(0, 5): 1, (1, 4): 5, (2, 3): 10, (3, 2): 10, (4, 1): 5, (5, 0): 1}
66
+
67
+ Notes
68
+ =====
69
+
70
+ The algorithm is based on the following result:
71
+
72
+ .. math::
73
+ \binom{n}{k_1, \ldots, k_m} =
74
+ \frac{k_1 + 1}{n - k_1} \sum_{i=2}^m \binom{n}{k_1 + 1, \ldots, k_i - 1, \ldots}
75
+
76
+ Code contributed to Sage by Yann Laigle-Chapuy, copied with permission
77
+ of the author.
78
+
79
+ See Also
80
+ ========
81
+
82
+ binomial_coefficients_list, binomial_coefficients
83
+ """
84
+ m = as_int(m)
85
+ n = as_int(n)
86
+ if not m:
87
+ if n:
88
+ return {}
89
+ return {(): 1}
90
+ if m == 2:
91
+ return binomial_coefficients(n)
92
+ if m >= 2*n and n > 1:
93
+ return dict(multinomial_coefficients_iterator(m, n))
94
+ t = [n] + [0] * (m - 1)
95
+ r = {tuple(t): 1}
96
+ if n:
97
+ j = 0 # j will be the leftmost nonzero position
98
+ else:
99
+ j = m
100
+ # enumerate tuples in co-lex order
101
+ while j < m - 1:
102
+ # compute next tuple
103
+ tj = t[j]
104
+ if j:
105
+ t[j] = 0
106
+ t[0] = tj
107
+ if tj > 1:
108
+ t[j + 1] += 1
109
+ j = 0
110
+ start = 1
111
+ v = 0
112
+ else:
113
+ j += 1
114
+ start = j + 1
115
+ v = r[tuple(t)]
116
+ t[j] += 1
117
+ # compute the value
118
+ # NB: the initialization of v was done above
119
+ for k in range(start, m):
120
+ if t[k]:
121
+ t[k] -= 1
122
+ v += r[tuple(t)]
123
+ t[k] += 1
124
+ t[0] -= 1
125
+ r[tuple(t)] = (v * tj) // (n - t[0])
126
+ return r
127
+
128
+
129
+ def multinomial_coefficients_iterator(m, n, _tuple=tuple):
130
+ """multinomial coefficient iterator
131
+
132
+ This routine has been optimized for `m` large with respect to `n` by taking
133
+ advantage of the fact that when the monomial tuples `t` are stripped of
134
+ zeros, their coefficient is the same as that of the monomial tuples from
135
+ ``multinomial_coefficients(n, n)``. Therefore, the latter coefficients are
136
+ precomputed to save memory and time.
137
+
138
+ >>> from sympy.ntheory.multinomial import multinomial_coefficients
139
+ >>> m53, m33 = multinomial_coefficients(5,3), multinomial_coefficients(3,3)
140
+ >>> m53[(0,0,0,1,2)] == m53[(0,0,1,0,2)] == m53[(1,0,2,0,0)] == m33[(0,1,2)]
141
+ True
142
+
143
+ Examples
144
+ ========
145
+
146
+ >>> from sympy.ntheory.multinomial import multinomial_coefficients_iterator
147
+ >>> it = multinomial_coefficients_iterator(20,3)
148
+ >>> next(it)
149
+ ((3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), 1)
150
+ """
151
+ m = as_int(m)
152
+ n = as_int(n)
153
+ if m < 2*n or n == 1:
154
+ mc = multinomial_coefficients(m, n)
155
+ yield from mc.items()
156
+ else:
157
+ mc = multinomial_coefficients(n, n)
158
+ mc1 = {}
159
+ for k, v in mc.items():
160
+ mc1[_tuple(filter(None, k))] = v
161
+ mc = mc1
162
+
163
+ t = [n] + [0] * (m - 1)
164
+ t1 = _tuple(t)
165
+ b = _tuple(filter(None, t1))
166
+ yield (t1, mc[b])
167
+ if n:
168
+ j = 0 # j will be the leftmost nonzero position
169
+ else:
170
+ j = m
171
+ # enumerate tuples in co-lex order
172
+ while j < m - 1:
173
+ # compute next tuple
174
+ tj = t[j]
175
+ if j:
176
+ t[j] = 0
177
+ t[0] = tj
178
+ if tj > 1:
179
+ t[j + 1] += 1
180
+ j = 0
181
+ else:
182
+ j += 1
183
+ t[j] += 1
184
+
185
+ t[0] -= 1
186
+ t1 = _tuple(t)
187
+ b = _tuple(filter(None, t1))
188
+ yield (t1, mc[b])
lib/python3.12/site-packages/sympy/ntheory/partitions_.py ADDED
@@ -0,0 +1,278 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from mpmath.libmp import (fzero, from_int, from_rational,
2
+ fone, fhalf, bitcount, to_int, mpf_mul, mpf_div, mpf_sub,
3
+ mpf_add, mpf_sqrt, mpf_pi, mpf_cosh_sinh, mpf_cos, mpf_sin)
4
+ from sympy.external.gmpy import gcd, legendre, jacobi
5
+ from .residue_ntheory import _sqrt_mod_prime_power, is_quad_residue
6
+ from sympy.utilities.decorator import deprecated
7
+ from sympy.utilities.memoization import recurrence_memo
8
+
9
+ import math
10
+ from itertools import count
11
+
12
+ def _pre():
13
+ maxn = 10**5
14
+ global _factor
15
+ global _totient
16
+ _factor = [0]*maxn
17
+ _totient = [1]*maxn
18
+ lim = int(maxn**0.5) + 5
19
+ for i in range(2, lim):
20
+ if _factor[i] == 0:
21
+ for j in range(i*i, maxn, i):
22
+ if _factor[j] == 0:
23
+ _factor[j] = i
24
+ for i in range(2, maxn):
25
+ if _factor[i] == 0:
26
+ _factor[i] = i
27
+ _totient[i] = i-1
28
+ continue
29
+ x = _factor[i]
30
+ y = i//x
31
+ if y % x == 0:
32
+ _totient[i] = _totient[y]*x
33
+ else:
34
+ _totient[i] = _totient[y]*(x - 1)
35
+
36
+ def _a(n, k, prec):
37
+ """ Compute the inner sum in HRR formula [1]_
38
+
39
+ References
40
+ ==========
41
+
42
+ .. [1] https://msp.org/pjm/1956/6-1/pjm-v6-n1-p18-p.pdf
43
+
44
+ """
45
+ if k == 1:
46
+ return fone
47
+
48
+ k1 = k
49
+ e = 0
50
+ p = _factor[k]
51
+ while k1 % p == 0:
52
+ k1 //= p
53
+ e += 1
54
+ k2 = k//k1 # k2 = p^e
55
+ v = 1 - 24*n
56
+ pi = mpf_pi(prec)
57
+
58
+ if k1 == 1:
59
+ # k = p^e
60
+ if p == 2:
61
+ mod = 8*k
62
+ v = mod + v % mod
63
+ v = (v*pow(9, k - 1, mod)) % mod
64
+ m = _sqrt_mod_prime_power(v, 2, e + 3)[0]
65
+ arg = mpf_div(mpf_mul(
66
+ from_int(4*m), pi, prec), from_int(mod), prec)
67
+ return mpf_mul(mpf_mul(
68
+ from_int((-1)**e*jacobi(m - 1, m)),
69
+ mpf_sqrt(from_int(k), prec), prec),
70
+ mpf_sin(arg, prec), prec)
71
+ if p == 3:
72
+ mod = 3*k
73
+ v = mod + v % mod
74
+ if e > 1:
75
+ v = (v*pow(64, k//3 - 1, mod)) % mod
76
+ m = _sqrt_mod_prime_power(v, 3, e + 1)[0]
77
+ arg = mpf_div(mpf_mul(from_int(4*m), pi, prec),
78
+ from_int(mod), prec)
79
+ return mpf_mul(mpf_mul(
80
+ from_int(2*(-1)**(e + 1)*legendre(m, 3)),
81
+ mpf_sqrt(from_int(k//3), prec), prec),
82
+ mpf_sin(arg, prec), prec)
83
+ v = k + v % k
84
+ if v % p == 0:
85
+ if e == 1:
86
+ return mpf_mul(
87
+ from_int(jacobi(3, k)),
88
+ mpf_sqrt(from_int(k), prec), prec)
89
+ return fzero
90
+ if not is_quad_residue(v, p):
91
+ return fzero
92
+ _phi = p**(e - 1)*(p - 1)
93
+ v = (v*pow(576, _phi - 1, k))
94
+ m = _sqrt_mod_prime_power(v, p, e)[0]
95
+ arg = mpf_div(
96
+ mpf_mul(from_int(4*m), pi, prec),
97
+ from_int(k), prec)
98
+ return mpf_mul(mpf_mul(
99
+ from_int(2*jacobi(3, k)),
100
+ mpf_sqrt(from_int(k), prec), prec),
101
+ mpf_cos(arg, prec), prec)
102
+
103
+ if p != 2 or e >= 3:
104
+ d1, d2 = gcd(k1, 24), gcd(k2, 24)
105
+ e = 24//(d1*d2)
106
+ n1 = ((d2*e*n + (k2**2 - 1)//d1)*
107
+ pow(e*k2*k2*d2, _totient[k1] - 1, k1)) % k1
108
+ n2 = ((d1*e*n + (k1**2 - 1)//d2)*
109
+ pow(e*k1*k1*d1, _totient[k2] - 1, k2)) % k2
110
+ return mpf_mul(_a(n1, k1, prec), _a(n2, k2, prec), prec)
111
+ if e == 2:
112
+ n1 = ((8*n + 5)*pow(128, _totient[k1] - 1, k1)) % k1
113
+ n2 = (4 + ((n - 2 - (k1**2 - 1)//8)*(k1**2)) % 4) % 4
114
+ return mpf_mul(mpf_mul(
115
+ from_int(-1),
116
+ _a(n1, k1, prec), prec),
117
+ _a(n2, k2, prec))
118
+ n1 = ((8*n + 1)*pow(32, _totient[k1] - 1, k1)) % k1
119
+ n2 = (2 + (n - (k1**2 - 1)//8) % 2) % 2
120
+ return mpf_mul(_a(n1, k1, prec), _a(n2, k2, prec), prec)
121
+
122
+ def _d(n, j, prec, sq23pi, sqrt8):
123
+ """
124
+ Compute the sinh term in the outer sum of the HRR formula.
125
+ The constants sqrt(2/3*pi) and sqrt(8) must be precomputed.
126
+ """
127
+ j = from_int(j)
128
+ pi = mpf_pi(prec)
129
+ a = mpf_div(sq23pi, j, prec)
130
+ b = mpf_sub(from_int(n), from_rational(1, 24, prec), prec)
131
+ c = mpf_sqrt(b, prec)
132
+ ch, sh = mpf_cosh_sinh(mpf_mul(a, c), prec)
133
+ D = mpf_div(
134
+ mpf_sqrt(j, prec),
135
+ mpf_mul(mpf_mul(sqrt8, b), pi), prec)
136
+ E = mpf_sub(mpf_mul(a, ch), mpf_div(sh, c, prec), prec)
137
+ return mpf_mul(D, E)
138
+
139
+
140
+ @recurrence_memo([1, 1])
141
+ def _partition_rec(n: int, prev) -> int:
142
+ """ Calculate the partition function P(n)
143
+
144
+ Parameters
145
+ ==========
146
+
147
+ n : int
148
+ nonnegative integer
149
+
150
+ """
151
+ v = 0
152
+ penta = 0 # pentagonal number: 1, 5, 12, ...
153
+ for i in count():
154
+ penta += 3*i + 1
155
+ np = n - penta
156
+ if np < 0:
157
+ break
158
+ s = prev[np]
159
+ np -= i + 1
160
+ # np = n - gp where gp = generalized pentagonal: 2, 7, 15, ...
161
+ if 0 <= np:
162
+ s += prev[np]
163
+ v += -s if i % 2 else s
164
+ return v
165
+
166
+
167
+ def _partition(n: int) -> int:
168
+ """ Calculate the partition function P(n)
169
+
170
+ Parameters
171
+ ==========
172
+
173
+ n : int
174
+
175
+ """
176
+ if n < 0:
177
+ return 0
178
+ if (n <= 200_000 and n - _partition_rec.cache_length() < 70 or
179
+ _partition_rec.cache_length() == 2 and n < 14_400):
180
+ # There will be 2*10**5 elements created here
181
+ # and n elements created by partition, so in case we
182
+ # are going to be working with small n, we just
183
+ # use partition to calculate (and cache) the values
184
+ # since lookup is used there while summation, using
185
+ # _factor and _totient, will be used below. But we
186
+ # only do so if n is relatively close to the length
187
+ # of the cache since doing 1 calculation here is about
188
+ # the same as adding 70 elements to the cache. In addition,
189
+ # the startup here costs about the same as calculating the first
190
+ # 14,400 values via partition, so we delay startup here unless n
191
+ # is smaller than that.
192
+ return _partition_rec(n)
193
+ if '_factor' not in globals():
194
+ _pre()
195
+ # Estimate number of bits in p(n). This formula could be tidied
196
+ pbits = int((
197
+ math.pi*(2*n/3.)**0.5 -
198
+ math.log(4*n))/math.log(10) + 1) * \
199
+ math.log2(10)
200
+ prec = p = int(pbits*1.1 + 100)
201
+
202
+ # find the number of terms needed so rounded sum will be accurate
203
+ # using Rademacher's bound M(n, N) for the remainder after a partial
204
+ # sum of N terms (https://arxiv.org/pdf/1205.5991.pdf, (1.8))
205
+ c1 = 44*math.pi**2/(225*math.sqrt(3))
206
+ c2 = math.pi*math.sqrt(2)/75
207
+ c3 = math.pi*math.sqrt(2/3)
208
+ def _M(n, N):
209
+ sqrt = math.sqrt
210
+ return c1/sqrt(N) + c2*sqrt(N/(n - 1))*math.sinh(c3*sqrt(n)/N)
211
+ big = max(9, math.ceil(n**0.5)) # should be too large (for n > 65, ceil should work)
212
+ assert _M(n, big) < 0.5 # else double big until too large
213
+ while big > 40 and _M(n, big) < 0.5:
214
+ big //= 2
215
+ small = big
216
+ big = small*2
217
+ while big - small > 1:
218
+ N = (big + small)//2
219
+ if (er := _M(n, N)) < 0.5:
220
+ big = N
221
+ elif er >= 0.5:
222
+ small = N
223
+ M = big # done with function M; now have value
224
+
225
+ # sanity check for expected size of answer
226
+ if M > 10**5: # i.e. M > maxn
227
+ raise ValueError("Input too big") # i.e. n > 149832547102
228
+
229
+ # calculate it
230
+ s = fzero
231
+ sq23pi = mpf_mul(mpf_sqrt(from_rational(2, 3, p), p), mpf_pi(p), p)
232
+ sqrt8 = mpf_sqrt(from_int(8), p)
233
+ for q in range(1, M):
234
+ a = _a(n, q, p)
235
+ d = _d(n, q, p, sq23pi, sqrt8)
236
+ s = mpf_add(s, mpf_mul(a, d), prec)
237
+ # On average, the terms decrease rapidly in magnitude.
238
+ # Dynamically reducing the precision greatly improves
239
+ # performance.
240
+ p = bitcount(abs(to_int(d))) + 50
241
+ return int(to_int(mpf_add(s, fhalf, prec)))
242
+
243
+
244
+ @deprecated("""\
245
+ The `sympy.ntheory.partitions_.npartitions` has been moved to `sympy.functions.combinatorial.numbers.partition`.""",
246
+ deprecated_since_version="1.13",
247
+ active_deprecations_target='deprecated-ntheory-symbolic-functions')
248
+ def npartitions(n, verbose=False):
249
+ """
250
+ Calculate the partition function P(n), i.e. the number of ways that
251
+ n can be written as a sum of positive integers.
252
+
253
+ .. deprecated:: 1.13
254
+
255
+ The ``npartitions`` function is deprecated. Use :class:`sympy.functions.combinatorial.numbers.partition`
256
+ instead. See its documentation for more information. See
257
+ :ref:`deprecated-ntheory-symbolic-functions` for details.
258
+
259
+ P(n) is computed using the Hardy-Ramanujan-Rademacher formula [1]_.
260
+
261
+
262
+ The correctness of this implementation has been tested through $10^{10}$.
263
+
264
+ Examples
265
+ ========
266
+
267
+ >>> from sympy.functions.combinatorial.numbers import partition
268
+ >>> partition(25)
269
+ 1958
270
+
271
+ References
272
+ ==========
273
+
274
+ .. [1] https://mathworld.wolfram.com/PartitionFunctionP.html
275
+
276
+ """
277
+ from sympy.functions.combinatorial.numbers import partition as func_partition
278
+ return func_partition(n)
lib/python3.12/site-packages/sympy/ntheory/primetest.py ADDED
@@ -0,0 +1,793 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Primality testing
3
+
4
+ """
5
+
6
+ from itertools import count
7
+
8
+ from sympy.core.sympify import sympify
9
+ from sympy.external.gmpy import (gmpy as _gmpy, gcd, jacobi,
10
+ is_square as gmpy_is_square,
11
+ bit_scan1, is_fermat_prp, is_euler_prp,
12
+ is_selfridge_prp, is_strong_selfridge_prp,
13
+ is_strong_bpsw_prp)
14
+ from sympy.external.ntheory import _lucas_sequence
15
+ from sympy.utilities.misc import as_int, filldedent
16
+
17
+ # Note: This list should be updated whenever new Mersenne primes are found.
18
+ # Refer: https://www.mersenne.org/
19
+ MERSENNE_PRIME_EXPONENTS = (2, 3, 5, 7, 13, 17, 19, 31, 61, 89, 107, 127, 521, 607, 1279, 2203,
20
+ 2281, 3217, 4253, 4423, 9689, 9941, 11213, 19937, 21701, 23209, 44497, 86243, 110503, 132049,
21
+ 216091, 756839, 859433, 1257787, 1398269, 2976221, 3021377, 6972593, 13466917, 20996011, 24036583,
22
+ 25964951, 30402457, 32582657, 37156667, 42643801, 43112609, 57885161, 74207281, 77232917, 82589933)
23
+
24
+
25
+ def is_fermat_pseudoprime(n, a):
26
+ r"""Returns True if ``n`` is prime or is an odd composite integer that
27
+ is coprime to ``a`` and satisfy the modular arithmetic congruence relation:
28
+
29
+ .. math ::
30
+ a^{n-1} \equiv 1 \pmod{n}
31
+
32
+ (where mod refers to the modulo operation).
33
+
34
+ Parameters
35
+ ==========
36
+
37
+ n : Integer
38
+ ``n`` is a positive integer.
39
+ a : Integer
40
+ ``a`` is a positive integer.
41
+ ``a`` and ``n`` should be relatively prime.
42
+
43
+ Returns
44
+ =======
45
+
46
+ bool : If ``n`` is prime, it always returns ``True``.
47
+ The composite number that returns ``True`` is called an Fermat pseudoprime.
48
+
49
+ Examples
50
+ ========
51
+
52
+ >>> from sympy.ntheory.primetest import is_fermat_pseudoprime
53
+ >>> from sympy.ntheory.factor_ import isprime
54
+ >>> for n in range(1, 1000):
55
+ ... if is_fermat_pseudoprime(n, 2) and not isprime(n):
56
+ ... print(n)
57
+ 341
58
+ 561
59
+ 645
60
+
61
+ References
62
+ ==========
63
+
64
+ .. [1] https://en.wikipedia.org/wiki/Fermat_pseudoprime
65
+ """
66
+ n, a = as_int(n), as_int(a)
67
+ if a == 1:
68
+ return n == 2 or bool(n % 2)
69
+ return is_fermat_prp(n, a)
70
+
71
+
72
+ def is_euler_pseudoprime(n, a):
73
+ r"""Returns True if ``n`` is prime or is an odd composite integer that
74
+ is coprime to ``a`` and satisfy the modular arithmetic congruence relation:
75
+
76
+ .. math ::
77
+ a^{(n-1)/2} \equiv \pm 1 \pmod{n}
78
+
79
+ (where mod refers to the modulo operation).
80
+
81
+ Parameters
82
+ ==========
83
+
84
+ n : Integer
85
+ ``n`` is a positive integer.
86
+ a : Integer
87
+ ``a`` is a positive integer.
88
+ ``a`` and ``n`` should be relatively prime.
89
+
90
+ Returns
91
+ =======
92
+
93
+ bool : If ``n`` is prime, it always returns ``True``.
94
+ The composite number that returns ``True`` is called an Euler pseudoprime.
95
+
96
+ Examples
97
+ ========
98
+
99
+ >>> from sympy.ntheory.primetest import is_euler_pseudoprime
100
+ >>> from sympy.ntheory.factor_ import isprime
101
+ >>> for n in range(1, 1000):
102
+ ... if is_euler_pseudoprime(n, 2) and not isprime(n):
103
+ ... print(n)
104
+ 341
105
+ 561
106
+
107
+ References
108
+ ==========
109
+
110
+ .. [1] https://en.wikipedia.org/wiki/Euler_pseudoprime
111
+ """
112
+ n, a = as_int(n), as_int(a)
113
+ if a < 1:
114
+ raise ValueError("a should be an integer greater than 0")
115
+ if n < 1:
116
+ raise ValueError("n should be an integer greater than 0")
117
+ if n == 1:
118
+ return False
119
+ if a == 1:
120
+ return n == 2 or bool(n % 2) # (prime or odd composite)
121
+ if n % 2 == 0:
122
+ return n == 2
123
+ if gcd(n, a) != 1:
124
+ raise ValueError("The two numbers should be relatively prime")
125
+ return pow(a, (n - 1) // 2, n) in [1, n - 1]
126
+
127
+
128
+ def is_euler_jacobi_pseudoprime(n, a):
129
+ r"""Returns True if ``n`` is prime or is an odd composite integer that
130
+ is coprime to ``a`` and satisfy the modular arithmetic congruence relation:
131
+
132
+ .. math ::
133
+ a^{(n-1)/2} \equiv \left(\frac{a}{n}\right) \pmod{n}
134
+
135
+ (where mod refers to the modulo operation).
136
+
137
+ Parameters
138
+ ==========
139
+
140
+ n : Integer
141
+ ``n`` is a positive integer.
142
+ a : Integer
143
+ ``a`` is a positive integer.
144
+ ``a`` and ``n`` should be relatively prime.
145
+
146
+ Returns
147
+ =======
148
+
149
+ bool : If ``n`` is prime, it always returns ``True``.
150
+ The composite number that returns ``True`` is called an Euler-Jacobi pseudoprime.
151
+
152
+ Examples
153
+ ========
154
+
155
+ >>> from sympy.ntheory.primetest import is_euler_jacobi_pseudoprime
156
+ >>> from sympy.ntheory.factor_ import isprime
157
+ >>> for n in range(1, 1000):
158
+ ... if is_euler_jacobi_pseudoprime(n, 2) and not isprime(n):
159
+ ... print(n)
160
+ 561
161
+
162
+ References
163
+ ==========
164
+
165
+ .. [1] https://en.wikipedia.org/wiki/Euler%E2%80%93Jacobi_pseudoprime
166
+ """
167
+ n, a = as_int(n), as_int(a)
168
+ if a == 1:
169
+ return n == 2 or bool(n % 2)
170
+ return is_euler_prp(n, a)
171
+
172
+
173
+ def is_square(n, prep=True):
174
+ """Return True if n == a * a for some integer a, else False.
175
+ If n is suspected of *not* being a square then this is a
176
+ quick method of confirming that it is not.
177
+
178
+ Examples
179
+ ========
180
+
181
+ >>> from sympy.ntheory.primetest import is_square
182
+ >>> is_square(25)
183
+ True
184
+ >>> is_square(2)
185
+ False
186
+
187
+ References
188
+ ==========
189
+
190
+ .. [1] https://mersenneforum.org/showpost.php?p=110896
191
+
192
+ See Also
193
+ ========
194
+ sympy.core.intfunc.isqrt
195
+ """
196
+ if prep:
197
+ n = as_int(n)
198
+ if n < 0:
199
+ return False
200
+ if n in (0, 1):
201
+ return True
202
+ return gmpy_is_square(n)
203
+
204
+
205
+ def _test(n, base, s, t):
206
+ """Miller-Rabin strong pseudoprime test for one base.
207
+ Return False if n is definitely composite, True if n is
208
+ probably prime, with a probability greater than 3/4.
209
+
210
+ """
211
+ # do the Fermat test
212
+ b = pow(base, t, n)
213
+ if b == 1 or b == n - 1:
214
+ return True
215
+ for _ in range(s - 1):
216
+ b = pow(b, 2, n)
217
+ if b == n - 1:
218
+ return True
219
+ # see I. Niven et al. "An Introduction to Theory of Numbers", page 78
220
+ if b == 1:
221
+ return False
222
+ return False
223
+
224
+
225
+ def mr(n, bases):
226
+ """Perform a Miller-Rabin strong pseudoprime test on n using a
227
+ given list of bases/witnesses.
228
+
229
+ References
230
+ ==========
231
+
232
+ .. [1] Richard Crandall & Carl Pomerance (2005), "Prime Numbers:
233
+ A Computational Perspective", Springer, 2nd edition, 135-138
234
+
235
+ A list of thresholds and the bases they require are here:
236
+ https://en.wikipedia.org/wiki/Miller%E2%80%93Rabin_primality_test#Deterministic_variants
237
+
238
+ Examples
239
+ ========
240
+
241
+ >>> from sympy.ntheory.primetest import mr
242
+ >>> mr(1373651, [2, 3])
243
+ False
244
+ >>> mr(479001599, [31, 73])
245
+ True
246
+
247
+ """
248
+ from sympy.polys.domains import ZZ
249
+
250
+ n = as_int(n)
251
+ if n < 2:
252
+ return False
253
+ # remove powers of 2 from n-1 (= t * 2**s)
254
+ s = bit_scan1(n - 1)
255
+ t = n >> s
256
+ for base in bases:
257
+ # Bases >= n are wrapped, bases < 2 are invalid
258
+ if base >= n:
259
+ base %= n
260
+ if base >= 2:
261
+ base = ZZ(base)
262
+ if not _test(n, base, s, t):
263
+ return False
264
+ return True
265
+
266
+
267
+ def _lucas_extrastrong_params(n):
268
+ """Calculates the "extra strong" parameters (D, P, Q) for n.
269
+
270
+ Parameters
271
+ ==========
272
+
273
+ n : int
274
+ positive odd integer
275
+
276
+ Returns
277
+ =======
278
+
279
+ D, P, Q: "extra strong" parameters.
280
+ ``(0, 0, 0)`` if we find a nontrivial divisor of ``n``.
281
+
282
+ Examples
283
+ ========
284
+
285
+ >>> from sympy.ntheory.primetest import _lucas_extrastrong_params
286
+ >>> _lucas_extrastrong_params(101)
287
+ (12, 4, 1)
288
+ >>> _lucas_extrastrong_params(15)
289
+ (0, 0, 0)
290
+
291
+ References
292
+ ==========
293
+ .. [1] OEIS A217719: Extra Strong Lucas Pseudoprimes
294
+ https://oeis.org/A217719
295
+ .. [2] https://en.wikipedia.org/wiki/Lucas_pseudoprime
296
+
297
+ """
298
+ for P in count(3):
299
+ D = P**2 - 4
300
+ j = jacobi(D, n)
301
+ if j == -1:
302
+ return (D, P, 1)
303
+ elif j == 0 and D % n:
304
+ return (0, 0, 0)
305
+
306
+
307
+ def is_lucas_prp(n):
308
+ """Standard Lucas compositeness test with Selfridge parameters. Returns
309
+ False if n is definitely composite, and True if n is a Lucas probable
310
+ prime.
311
+
312
+ This is typically used in combination with the Miller-Rabin test.
313
+
314
+ References
315
+ ==========
316
+ .. [1] Robert Baillie, Samuel S. Wagstaff, Lucas Pseudoprimes,
317
+ Math. Comp. Vol 35, Number 152 (1980), pp. 1391-1417,
318
+ https://doi.org/10.1090%2FS0025-5718-1980-0583518-6
319
+ http://mpqs.free.fr/LucasPseudoprimes.pdf
320
+ .. [2] OEIS A217120: Lucas Pseudoprimes
321
+ https://oeis.org/A217120
322
+ .. [3] https://en.wikipedia.org/wiki/Lucas_pseudoprime
323
+
324
+ Examples
325
+ ========
326
+
327
+ >>> from sympy.ntheory.primetest import isprime, is_lucas_prp
328
+ >>> for i in range(10000):
329
+ ... if is_lucas_prp(i) and not isprime(i):
330
+ ... print(i)
331
+ 323
332
+ 377
333
+ 1159
334
+ 1829
335
+ 3827
336
+ 5459
337
+ 5777
338
+ 9071
339
+ 9179
340
+ """
341
+ n = as_int(n)
342
+ if n < 2:
343
+ return False
344
+ return is_selfridge_prp(n)
345
+
346
+
347
+ def is_strong_lucas_prp(n):
348
+ """Strong Lucas compositeness test with Selfridge parameters. Returns
349
+ False if n is definitely composite, and True if n is a strong Lucas
350
+ probable prime.
351
+
352
+ This is often used in combination with the Miller-Rabin test, and
353
+ in particular, when combined with M-R base 2 creates the strong BPSW test.
354
+
355
+ References
356
+ ==========
357
+ .. [1] Robert Baillie, Samuel S. Wagstaff, Lucas Pseudoprimes,
358
+ Math. Comp. Vol 35, Number 152 (1980), pp. 1391-1417,
359
+ https://doi.org/10.1090%2FS0025-5718-1980-0583518-6
360
+ http://mpqs.free.fr/LucasPseudoprimes.pdf
361
+ .. [2] OEIS A217255: Strong Lucas Pseudoprimes
362
+ https://oeis.org/A217255
363
+ .. [3] https://en.wikipedia.org/wiki/Lucas_pseudoprime
364
+ .. [4] https://en.wikipedia.org/wiki/Baillie-PSW_primality_test
365
+
366
+ Examples
367
+ ========
368
+
369
+ >>> from sympy.ntheory.primetest import isprime, is_strong_lucas_prp
370
+ >>> for i in range(20000):
371
+ ... if is_strong_lucas_prp(i) and not isprime(i):
372
+ ... print(i)
373
+ 5459
374
+ 5777
375
+ 10877
376
+ 16109
377
+ 18971
378
+ """
379
+ n = as_int(n)
380
+ if n < 2:
381
+ return False
382
+ return is_strong_selfridge_prp(n)
383
+
384
+
385
+ def is_extra_strong_lucas_prp(n):
386
+ """Extra Strong Lucas compositeness test. Returns False if n is
387
+ definitely composite, and True if n is an "extra strong" Lucas probable
388
+ prime.
389
+
390
+ The parameters are selected using P = 3, Q = 1, then incrementing P until
391
+ (D|n) == -1. The test itself is as defined in [1]_, from the
392
+ Mo and Jones preprint. The parameter selection and test are the same as
393
+ used in OEIS A217719, Perl's Math::Prime::Util, and the Lucas pseudoprime
394
+ page on Wikipedia.
395
+
396
+ It is 20-50% faster than the strong test.
397
+
398
+ Because of the different parameters selected, there is no relationship
399
+ between the strong Lucas pseudoprimes and extra strong Lucas pseudoprimes.
400
+ In particular, one is not a subset of the other.
401
+
402
+ References
403
+ ==========
404
+ .. [1] Jon Grantham, Frobenius Pseudoprimes,
405
+ Math. Comp. Vol 70, Number 234 (2001), pp. 873-891,
406
+ https://doi.org/10.1090%2FS0025-5718-00-01197-2
407
+ .. [2] OEIS A217719: Extra Strong Lucas Pseudoprimes
408
+ https://oeis.org/A217719
409
+ .. [3] https://en.wikipedia.org/wiki/Lucas_pseudoprime
410
+
411
+ Examples
412
+ ========
413
+
414
+ >>> from sympy.ntheory.primetest import isprime, is_extra_strong_lucas_prp
415
+ >>> for i in range(20000):
416
+ ... if is_extra_strong_lucas_prp(i) and not isprime(i):
417
+ ... print(i)
418
+ 989
419
+ 3239
420
+ 5777
421
+ 10877
422
+ """
423
+ # Implementation notes:
424
+ # 1) the parameters differ from Thomas R. Nicely's. His parameter
425
+ # selection leads to pseudoprimes that overlap M-R tests, and
426
+ # contradict Baillie and Wagstaff's suggestion of (D|n) = -1.
427
+ # 2) The MathWorld page as of June 2013 specifies Q=-1. The Lucas
428
+ # sequence must have Q=1. See Grantham theorem 2.3, any of the
429
+ # references on the MathWorld page, or run it and see Q=-1 is wrong.
430
+ n = as_int(n)
431
+ if n == 2:
432
+ return True
433
+ if n < 2 or (n % 2) == 0:
434
+ return False
435
+ if gmpy_is_square(n):
436
+ return False
437
+
438
+ D, P, Q = _lucas_extrastrong_params(n)
439
+ if D == 0:
440
+ return False
441
+
442
+ # remove powers of 2 from n+1 (= k * 2**s)
443
+ s = bit_scan1(n + 1)
444
+ k = (n + 1) >> s
445
+
446
+ U, V, _ = _lucas_sequence(n, P, Q, k)
447
+
448
+ if U == 0 and (V == 2 or V == n - 2):
449
+ return True
450
+ for _ in range(1, s):
451
+ if V == 0:
452
+ return True
453
+ V = (V*V - 2) % n
454
+ return False
455
+
456
+
457
+ def proth_test(n):
458
+ r""" Test if the Proth number `n = k2^m + 1` is prime. where k is a positive odd number and `2^m > k`.
459
+
460
+ Parameters
461
+ ==========
462
+
463
+ n : Integer
464
+ ``n`` is Proth number
465
+
466
+ Returns
467
+ =======
468
+
469
+ bool : If ``True``, then ``n`` is the Proth prime
470
+
471
+ Raises
472
+ ======
473
+
474
+ ValueError
475
+ If ``n`` is not Proth number.
476
+
477
+ Examples
478
+ ========
479
+
480
+ >>> from sympy.ntheory.primetest import proth_test
481
+ >>> proth_test(41)
482
+ True
483
+ >>> proth_test(57)
484
+ False
485
+
486
+ References
487
+ ==========
488
+
489
+ .. [1] https://en.wikipedia.org/wiki/Proth_prime
490
+
491
+ """
492
+ n = as_int(n)
493
+ if n < 3:
494
+ raise ValueError("n is not Proth number")
495
+ m = bit_scan1(n - 1)
496
+ k = n >> m
497
+ if m < k.bit_length():
498
+ raise ValueError("n is not Proth number")
499
+ if n % 3 == 0:
500
+ return n == 3
501
+ if k % 3: # n % 12 == 5
502
+ return pow(3, n >> 1, n) == n - 1
503
+ # If `n` is a square number, then `jacobi(a, n) = 1` for any `a`
504
+ if gmpy_is_square(n):
505
+ return False
506
+ # `a` may be chosen at random.
507
+ # In any case, we want to find `a` such that `jacobi(a, n) = -1`.
508
+ for a in range(5, n):
509
+ j = jacobi(a, n)
510
+ if j == -1:
511
+ return pow(a, n >> 1, n) == n - 1
512
+ if j == 0:
513
+ return False
514
+
515
+
516
+ def _lucas_lehmer_primality_test(p):
517
+ r""" Test if the Mersenne number `M_p = 2^p-1` is prime.
518
+
519
+ Parameters
520
+ ==========
521
+
522
+ p : int
523
+ ``p`` is an odd prime number
524
+
525
+ Returns
526
+ =======
527
+
528
+ bool : If ``True``, then `M_p` is the Mersenne prime
529
+
530
+ Examples
531
+ ========
532
+
533
+ >>> from sympy.ntheory.primetest import _lucas_lehmer_primality_test
534
+ >>> _lucas_lehmer_primality_test(5) # 2**5 - 1 = 31 is prime
535
+ True
536
+ >>> _lucas_lehmer_primality_test(11) # 2**11 - 1 = 2047 is not prime
537
+ False
538
+
539
+ See Also
540
+ ========
541
+
542
+ is_mersenne_prime
543
+
544
+ References
545
+ ==========
546
+
547
+ .. [1] https://en.wikipedia.org/wiki/Lucas%E2%80%93Lehmer_primality_test
548
+
549
+ """
550
+ v = 4
551
+ m = 2**p - 1
552
+ for _ in range(p - 2):
553
+ v = pow(v, 2, m) - 2
554
+ return v == 0
555
+
556
+
557
+ def is_mersenne_prime(n):
558
+ """Returns True if ``n`` is a Mersenne prime, else False.
559
+
560
+ A Mersenne prime is a prime number having the form `2^i - 1`.
561
+
562
+ Examples
563
+ ========
564
+
565
+ >>> from sympy.ntheory.factor_ import is_mersenne_prime
566
+ >>> is_mersenne_prime(6)
567
+ False
568
+ >>> is_mersenne_prime(127)
569
+ True
570
+
571
+ References
572
+ ==========
573
+
574
+ .. [1] https://mathworld.wolfram.com/MersennePrime.html
575
+
576
+ """
577
+ n = as_int(n)
578
+ if n < 1:
579
+ return False
580
+ if n & (n + 1):
581
+ # n is not Mersenne number
582
+ return False
583
+ p = n.bit_length()
584
+ if p in MERSENNE_PRIME_EXPONENTS:
585
+ return True
586
+ if p < 65_000_000 or not isprime(p):
587
+ # According to GIMPS, verification was completed on September 19, 2023 for p less than 65 million.
588
+ # https://www.mersenne.org/report_milestones/
589
+ # If p is composite number, then n=2**p-1 is composite number.
590
+ return False
591
+ result = _lucas_lehmer_primality_test(p)
592
+ if result:
593
+ raise ValueError(filldedent('''
594
+ This Mersenne Prime, 2^%s - 1, should
595
+ be added to SymPy's known values.''' % p))
596
+ return result
597
+
598
+
599
+ def isprime(n):
600
+ """
601
+ Test if n is a prime number (True) or not (False). For n < 2^64 the
602
+ answer is definitive; larger n values have a small probability of actually
603
+ being pseudoprimes.
604
+
605
+ Negative numbers (e.g. -2) are not considered prime.
606
+
607
+ The first step is looking for trivial factors, which if found enables
608
+ a quick return. Next, if the sieve is large enough, use bisection search
609
+ on the sieve. For small numbers, a set of deterministic Miller-Rabin
610
+ tests are performed with bases that are known to have no counterexamples
611
+ in their range. Finally if the number is larger than 2^64, a strong
612
+ BPSW test is performed. While this is a probable prime test and we
613
+ believe counterexamples exist, there are no known counterexamples.
614
+
615
+ Examples
616
+ ========
617
+
618
+ >>> from sympy.ntheory import isprime
619
+ >>> isprime(13)
620
+ True
621
+ >>> isprime(15)
622
+ False
623
+
624
+ Notes
625
+ =====
626
+
627
+ This routine is intended only for integer input, not numerical
628
+ expressions which may represent numbers. Floats are also
629
+ rejected as input because they represent numbers of limited
630
+ precision. While it is tempting to permit 7.0 to represent an
631
+ integer there are errors that may "pass silently" if this is
632
+ allowed:
633
+
634
+ >>> from sympy import Float, S
635
+ >>> int(1e3) == 1e3 == 10**3
636
+ True
637
+ >>> int(1e23) == 1e23
638
+ True
639
+ >>> int(1e23) == 10**23
640
+ False
641
+
642
+ >>> near_int = 1 + S(1)/10**19
643
+ >>> near_int == int(near_int)
644
+ False
645
+ >>> n = Float(near_int, 10) # truncated by precision
646
+ >>> n % 1 == 0
647
+ True
648
+ >>> n = Float(near_int, 20)
649
+ >>> n % 1 == 0
650
+ False
651
+
652
+ See Also
653
+ ========
654
+
655
+ sympy.ntheory.generate.primerange : Generates all primes in a given range
656
+ sympy.functions.combinatorial.numbers.primepi : Return the number of primes less than or equal to n
657
+ sympy.ntheory.generate.prime : Return the nth prime
658
+
659
+ References
660
+ ==========
661
+ .. [1] https://en.wikipedia.org/wiki/Strong_pseudoprime
662
+ .. [2] Robert Baillie, Samuel S. Wagstaff, Lucas Pseudoprimes,
663
+ Math. Comp. Vol 35, Number 152 (1980), pp. 1391-1417,
664
+ https://doi.org/10.1090%2FS0025-5718-1980-0583518-6
665
+ http://mpqs.free.fr/LucasPseudoprimes.pdf
666
+ .. [3] https://en.wikipedia.org/wiki/Baillie-PSW_primality_test
667
+ """
668
+ n = as_int(n)
669
+
670
+ # Step 1, do quick composite testing via trial division. The individual
671
+ # modulo tests benchmark faster than one or two primorial igcds for me.
672
+ # The point here is just to speedily handle small numbers and many
673
+ # composites. Step 2 only requires that n <= 2 get handled here.
674
+ if n in [2, 3, 5]:
675
+ return True
676
+ if n < 2 or (n % 2) == 0 or (n % 3) == 0 or (n % 5) == 0:
677
+ return False
678
+ if n < 49:
679
+ return True
680
+ if (n % 7) == 0 or (n % 11) == 0 or (n % 13) == 0 or (n % 17) == 0 or \
681
+ (n % 19) == 0 or (n % 23) == 0 or (n % 29) == 0 or (n % 31) == 0 or \
682
+ (n % 37) == 0 or (n % 41) == 0 or (n % 43) == 0 or (n % 47) == 0:
683
+ return False
684
+ if n < 2809:
685
+ return True
686
+ if n < 65077:
687
+ # There are only five Euler pseudoprimes with a least prime factor greater than 47
688
+ return pow(2, n >> 1, n) in [1, n - 1] and n not in [8321, 31621, 42799, 49141, 49981]
689
+
690
+ # bisection search on the sieve if the sieve is large enough
691
+ from sympy.ntheory.generate import sieve as s
692
+ if n <= s._list[-1]:
693
+ l, u = s.search(n)
694
+ return l == u
695
+
696
+ # If we have GMPY2, skip straight to step 3 and do a strong BPSW test.
697
+ # This should be a bit faster than our step 2, and for large values will
698
+ # be a lot faster than our step 3 (C+GMP vs. Python).
699
+ if _gmpy is not None:
700
+ return is_strong_bpsw_prp(n)
701
+
702
+
703
+ # Step 2: deterministic Miller-Rabin testing for numbers < 2^64. See:
704
+ # https://miller-rabin.appspot.com/
705
+ # for lists. We have made sure the M-R routine will successfully handle
706
+ # bases larger than n, so we can use the minimal set.
707
+ # In September 2015 deterministic numbers were extended to over 2^81.
708
+ # https://arxiv.org/pdf/1509.00864.pdf
709
+ # https://oeis.org/A014233
710
+ if n < 341531:
711
+ return mr(n, [9345883071009581737])
712
+ if n < 885594169:
713
+ return mr(n, [725270293939359937, 3569819667048198375])
714
+ if n < 350269456337:
715
+ return mr(n, [4230279247111683200, 14694767155120705706, 16641139526367750375])
716
+ if n < 55245642489451:
717
+ return mr(n, [2, 141889084524735, 1199124725622454117, 11096072698276303650])
718
+ if n < 7999252175582851:
719
+ return mr(n, [2, 4130806001517, 149795463772692060, 186635894390467037, 3967304179347715805])
720
+ if n < 585226005592931977:
721
+ return mr(n, [2, 123635709730000, 9233062284813009, 43835965440333360, 761179012939631437, 1263739024124850375])
722
+ if n < 18446744073709551616:
723
+ return mr(n, [2, 325, 9375, 28178, 450775, 9780504, 1795265022])
724
+ if n < 318665857834031151167461:
725
+ return mr(n, [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37])
726
+ if n < 3317044064679887385961981:
727
+ return mr(n, [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41])
728
+
729
+ # We could do this instead at any point:
730
+ #if n < 18446744073709551616:
731
+ # return mr(n, [2]) and is_extra_strong_lucas_prp(n)
732
+
733
+ # Here are tests that are safe for MR routines that don't understand
734
+ # large bases.
735
+ #if n < 9080191:
736
+ # return mr(n, [31, 73])
737
+ #if n < 19471033:
738
+ # return mr(n, [2, 299417])
739
+ #if n < 38010307:
740
+ # return mr(n, [2, 9332593])
741
+ #if n < 316349281:
742
+ # return mr(n, [11000544, 31481107])
743
+ #if n < 4759123141:
744
+ # return mr(n, [2, 7, 61])
745
+ #if n < 105936894253:
746
+ # return mr(n, [2, 1005905886, 1340600841])
747
+ #if n < 31858317218647:
748
+ # return mr(n, [2, 642735, 553174392, 3046413974])
749
+ #if n < 3071837692357849:
750
+ # return mr(n, [2, 75088, 642735, 203659041, 3613982119])
751
+ #if n < 18446744073709551616:
752
+ # return mr(n, [2, 325, 9375, 28178, 450775, 9780504, 1795265022])
753
+
754
+ # Step 3: BPSW.
755
+ #
756
+ # Time for isprime(10**2000 + 4561), no gmpy or gmpy2 installed
757
+ # 44.0s old isprime using 46 bases
758
+ # 5.3s strong BPSW + one random base
759
+ # 4.3s extra strong BPSW + one random base
760
+ # 4.1s strong BPSW
761
+ # 3.2s extra strong BPSW
762
+
763
+ # Classic BPSW from page 1401 of the paper. See alternate ideas below.
764
+ return is_strong_bpsw_prp(n)
765
+
766
+ # Using extra strong test, which is somewhat faster
767
+ #return mr(n, [2]) and is_extra_strong_lucas_prp(n)
768
+
769
+ # Add a random M-R base
770
+ #import random
771
+ #return mr(n, [2, random.randint(3, n-1)]) and is_strong_lucas_prp(n)
772
+
773
+
774
+ def is_gaussian_prime(num):
775
+ r"""Test if num is a Gaussian prime number.
776
+
777
+ References
778
+ ==========
779
+
780
+ .. [1] https://oeis.org/wiki/Gaussian_primes
781
+ """
782
+
783
+ num = sympify(num)
784
+ a, b = num.as_real_imag()
785
+ a = as_int(a, strict=False)
786
+ b = as_int(b, strict=False)
787
+ if a == 0:
788
+ b = abs(b)
789
+ return isprime(b) and b % 4 == 3
790
+ elif b == 0:
791
+ a = abs(a)
792
+ return isprime(a) and a % 4 == 3
793
+ return isprime(a**2 + b**2)
lib/python3.12/site-packages/sympy/ntheory/qs.py ADDED
@@ -0,0 +1,511 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from sympy.core.random import _randint
2
+ from sympy.external.gmpy import gcd, invert, sqrt as isqrt
3
+ from sympy.ntheory.residue_ntheory import _sqrt_mod_prime_power
4
+ from sympy.ntheory import isprime
5
+ from math import log, sqrt
6
+
7
+
8
+ class SievePolynomial:
9
+ def __init__(self, modified_coeff=(), a=None, b=None):
10
+ """This class denotes the seive polynomial.
11
+ If ``g(x) = (a*x + b)**2 - N``. `g(x)` can be expanded
12
+ to ``a*x**2 + 2*a*b*x + b**2 - N``, so the coefficient
13
+ is stored in the form `[a**2, 2*a*b, b**2 - N]`. This
14
+ ensures faster `eval` method because we dont have to
15
+ perform `a**2, 2*a*b, b**2` every time we call the
16
+ `eval` method. As multiplication is more expensive
17
+ than addition, by using modified_coefficient we get
18
+ a faster seiving process.
19
+
20
+ Parameters
21
+ ==========
22
+
23
+ modified_coeff : modified_coefficient of sieve polynomial
24
+ a : parameter of the sieve polynomial
25
+ b : parameter of the sieve polynomial
26
+ """
27
+ self.modified_coeff = modified_coeff
28
+ self.a = a
29
+ self.b = b
30
+
31
+ def eval(self, x):
32
+ """
33
+ Compute the value of the sieve polynomial at point x.
34
+
35
+ Parameters
36
+ ==========
37
+
38
+ x : Integer parameter for sieve polynomial
39
+ """
40
+ ans = 0
41
+ for coeff in self.modified_coeff:
42
+ ans *= x
43
+ ans += coeff
44
+ return ans
45
+
46
+
47
+ class FactorBaseElem:
48
+ """This class stores an element of the `factor_base`.
49
+ """
50
+ def __init__(self, prime, tmem_p, log_p):
51
+ """
52
+ Initialization of factor_base_elem.
53
+
54
+ Parameters
55
+ ==========
56
+
57
+ prime : prime number of the factor_base
58
+ tmem_p : Integer square root of x**2 = n mod prime
59
+ log_p : Compute Natural Logarithm of the prime
60
+ """
61
+ self.prime = prime
62
+ self.tmem_p = tmem_p
63
+ self.log_p = log_p
64
+ self.soln1 = None
65
+ self.soln2 = None
66
+ self.a_inv = None
67
+ self.b_ainv = None
68
+
69
+
70
+ def _generate_factor_base(prime_bound, n):
71
+ """Generate `factor_base` for Quadratic Sieve. The `factor_base`
72
+ consists of all the points whose ``legendre_symbol(n, p) == 1``
73
+ and ``p < num_primes``. Along with the prime `factor_base` also stores
74
+ natural logarithm of prime and the residue n modulo p.
75
+ It also returns the of primes numbers in the `factor_base` which are
76
+ close to 1000 and 5000.
77
+
78
+ Parameters
79
+ ==========
80
+
81
+ prime_bound : upper prime bound of the factor_base
82
+ n : integer to be factored
83
+ """
84
+ from sympy.ntheory.generate import sieve
85
+ factor_base = []
86
+ idx_1000, idx_5000 = None, None
87
+ for prime in sieve.primerange(1, prime_bound):
88
+ if pow(n, (prime - 1) // 2, prime) == 1:
89
+ if prime > 1000 and idx_1000 is None:
90
+ idx_1000 = len(factor_base) - 1
91
+ if prime > 5000 and idx_5000 is None:
92
+ idx_5000 = len(factor_base) - 1
93
+ residue = _sqrt_mod_prime_power(n, prime, 1)[0]
94
+ log_p = round(log(prime)*2**10)
95
+ factor_base.append(FactorBaseElem(prime, residue, log_p))
96
+ return idx_1000, idx_5000, factor_base
97
+
98
+
99
+ def _initialize_first_polynomial(N, M, factor_base, idx_1000, idx_5000, seed=None):
100
+ """This step is the initialization of the 1st sieve polynomial.
101
+ Here `a` is selected as a product of several primes of the factor_base
102
+ such that `a` is about to ``sqrt(2*N) / M``. Other initial values of
103
+ factor_base elem are also initialized which includes a_inv, b_ainv, soln1,
104
+ soln2 which are used when the sieve polynomial is changed. The b_ainv
105
+ is required for fast polynomial change as we do not have to calculate
106
+ `2*b*invert(a, prime)` every time.
107
+ We also ensure that the `factor_base` primes which make `a` are between
108
+ 1000 and 5000.
109
+
110
+ Parameters
111
+ ==========
112
+
113
+ N : Number to be factored
114
+ M : sieve interval
115
+ factor_base : factor_base primes
116
+ idx_1000 : index of prime number in the factor_base near 1000
117
+ idx_5000 : index of prime number in the factor_base near to 5000
118
+ seed : Generate pseudoprime numbers
119
+ """
120
+ randint = _randint(seed)
121
+ approx_val = sqrt(2*N) / M
122
+ # `a` is a parameter of the sieve polynomial and `q` is the prime factors of `a`
123
+ # randomly search for a combination of primes whose multiplication is close to approx_val
124
+ # This multiplication of primes will be `a` and the primes will be `q`
125
+ # `best_a` denotes that `a` is close to approx_val in the random search of combination
126
+ best_a, best_q, best_ratio = None, None, None
127
+ start = 0 if idx_1000 is None else idx_1000
128
+ end = len(factor_base) - 1 if idx_5000 is None else idx_5000
129
+ for _ in range(50):
130
+ a = 1
131
+ q = []
132
+ while(a < approx_val):
133
+ rand_p = 0
134
+ while(rand_p == 0 or rand_p in q):
135
+ rand_p = randint(start, end)
136
+ p = factor_base[rand_p].prime
137
+ a *= p
138
+ q.append(rand_p)
139
+ ratio = a / approx_val
140
+ if best_ratio is None or abs(ratio - 1) < abs(best_ratio - 1):
141
+ best_q = q
142
+ best_a = a
143
+ best_ratio = ratio
144
+
145
+ a = best_a
146
+ q = best_q
147
+
148
+ B = []
149
+ for val in q:
150
+ q_l = factor_base[val].prime
151
+ gamma = factor_base[val].tmem_p * invert(a // q_l, q_l) % q_l
152
+ if gamma > q_l / 2:
153
+ gamma = q_l - gamma
154
+ B.append(a//q_l*gamma)
155
+
156
+ b = sum(B)
157
+ g = SievePolynomial([a*a, 2*a*b, b*b - N], a, b)
158
+
159
+ for fb in factor_base:
160
+ if a % fb.prime == 0:
161
+ continue
162
+ fb.a_inv = invert(a, fb.prime)
163
+ fb.b_ainv = [2*b_elem*fb.a_inv % fb.prime for b_elem in B]
164
+ fb.soln1 = (fb.a_inv*(fb.tmem_p - b)) % fb.prime
165
+ fb.soln2 = (fb.a_inv*(-fb.tmem_p - b)) % fb.prime
166
+ return g, B
167
+
168
+
169
+ def _initialize_ith_poly(N, factor_base, i, g, B):
170
+ """Initialization stage of ith poly. After we finish sieving 1`st polynomial
171
+ here we quickly change to the next polynomial from which we will again
172
+ start sieving. Suppose we generated ith sieve polynomial and now we
173
+ want to generate (i + 1)th polynomial, where ``1 <= i <= 2**(j - 1) - 1``
174
+ where `j` is the number of prime factors of the coefficient `a`
175
+ then this function can be used to go to the next polynomial. If
176
+ ``i = 2**(j - 1) - 1`` then go to _initialize_first_polynomial stage.
177
+
178
+ Parameters
179
+ ==========
180
+
181
+ N : number to be factored
182
+ factor_base : factor_base primes
183
+ i : integer denoting ith polynomial
184
+ g : (i - 1)th polynomial
185
+ B : array that stores a//q_l*gamma
186
+ """
187
+ from sympy.functions.elementary.integers import ceiling
188
+ v = 1
189
+ j = i
190
+ while(j % 2 == 0):
191
+ v += 1
192
+ j //= 2
193
+ if ceiling(i / (2**v)) % 2 == 1:
194
+ neg_pow = -1
195
+ else:
196
+ neg_pow = 1
197
+ b = g.b + 2*neg_pow*B[v - 1]
198
+ a = g.a
199
+ g = SievePolynomial([a*a, 2*a*b, b*b - N], a, b)
200
+ for fb in factor_base:
201
+ if a % fb.prime == 0:
202
+ continue
203
+ fb.soln1 = (fb.soln1 - neg_pow*fb.b_ainv[v - 1]) % fb.prime
204
+ fb.soln2 = (fb.soln2 - neg_pow*fb.b_ainv[v - 1]) % fb.prime
205
+
206
+ return g
207
+
208
+
209
+ def _gen_sieve_array(M, factor_base):
210
+ """Sieve Stage of the Quadratic Sieve. For every prime in the factor_base
211
+ that does not divide the coefficient `a` we add log_p over the sieve_array
212
+ such that ``-M <= soln1 + i*p <= M`` and ``-M <= soln2 + i*p <= M`` where `i`
213
+ is an integer. When p = 2 then log_p is only added using
214
+ ``-M <= soln1 + i*p <= M``.
215
+
216
+ Parameters
217
+ ==========
218
+
219
+ M : sieve interval
220
+ factor_base : factor_base primes
221
+ """
222
+ sieve_array = [0]*(2*M + 1)
223
+ for factor in factor_base:
224
+ if factor.soln1 is None: #The prime does not divides a
225
+ continue
226
+ for idx in range((M + factor.soln1) % factor.prime, 2*M, factor.prime):
227
+ sieve_array[idx] += factor.log_p
228
+ if factor.prime == 2:
229
+ continue
230
+ #if prime is 2 then sieve only with soln_1_p
231
+ for idx in range((M + factor.soln2) % factor.prime, 2*M, factor.prime):
232
+ sieve_array[idx] += factor.log_p
233
+ return sieve_array
234
+
235
+
236
+ def _check_smoothness(num, factor_base):
237
+ """Here we check that if `num` is a smooth number or not. If `a` is a smooth
238
+ number then it returns a vector of prime exponents modulo 2. For example
239
+ if a = 2 * 5**2 * 7**3 and the factor base contains {2, 3, 5, 7} then
240
+ `a` is a smooth number and this function returns ([1, 0, 0, 1], True). If
241
+ `a` is a partial relation which means that `a` a has one prime factor
242
+ greater than the `factor_base` then it returns `(a, False)` which denotes `a`
243
+ is a partial relation.
244
+
245
+ Parameters
246
+ ==========
247
+
248
+ a : integer whose smootheness is to be checked
249
+ factor_base : factor_base primes
250
+ """
251
+ vec = []
252
+ if num < 0:
253
+ vec.append(1)
254
+ num *= -1
255
+ else:
256
+ vec.append(0)
257
+ #-1 is not included in factor_base add -1 in vector
258
+ for factor in factor_base:
259
+ if num % factor.prime != 0:
260
+ vec.append(0)
261
+ continue
262
+ factor_exp = 0
263
+ while num % factor.prime == 0:
264
+ factor_exp += 1
265
+ num //= factor.prime
266
+ vec.append(factor_exp % 2)
267
+ if num == 1:
268
+ return vec, True
269
+ if isprime(num):
270
+ return num, False
271
+ return None, None
272
+
273
+
274
+ def _trial_division_stage(N, M, factor_base, sieve_array, sieve_poly, partial_relations, ERROR_TERM):
275
+ """Trial division stage. Here we trial divide the values generetated
276
+ by sieve_poly in the sieve interval and if it is a smooth number then
277
+ it is stored in `smooth_relations`. Moreover, if we find two partial relations
278
+ with same large prime then they are combined to form a smooth relation.
279
+ First we iterate over sieve array and look for values which are greater
280
+ than accumulated_val, as these values have a high chance of being smooth
281
+ number. Then using these values we find smooth relations.
282
+ In general, let ``t**2 = u*p modN`` and ``r**2 = v*p modN`` be two partial relations
283
+ with the same large prime p. Then they can be combined ``(t*r/p)**2 = u*v modN``
284
+ to form a smooth relation.
285
+
286
+ Parameters
287
+ ==========
288
+
289
+ N : Number to be factored
290
+ M : sieve interval
291
+ factor_base : factor_base primes
292
+ sieve_array : stores log_p values
293
+ sieve_poly : polynomial from which we find smooth relations
294
+ partial_relations : stores partial relations with one large prime
295
+ ERROR_TERM : error term for accumulated_val
296
+ """
297
+ sqrt_n = isqrt(N)
298
+ accumulated_val = log(M * sqrt_n)*2**10 - ERROR_TERM
299
+ smooth_relations = []
300
+ proper_factor = set()
301
+ partial_relation_upper_bound = 128*factor_base[-1].prime
302
+ for idx, val in enumerate(sieve_array):
303
+ if val < accumulated_val:
304
+ continue
305
+ x = idx - M
306
+ v = sieve_poly.eval(x)
307
+ vec, is_smooth = _check_smoothness(v, factor_base)
308
+ if is_smooth is None:#Neither smooth nor partial
309
+ continue
310
+ u = sieve_poly.a*x + sieve_poly.b
311
+ # Update the partial relation
312
+ # If 2 partial relation with same large prime is found then generate smooth relation
313
+ if is_smooth is False:#partial relation found
314
+ large_prime = vec
315
+ #Consider the large_primes under 128*F
316
+ if large_prime > partial_relation_upper_bound:
317
+ continue
318
+ if large_prime not in partial_relations:
319
+ partial_relations[large_prime] = (u, v)
320
+ continue
321
+ else:
322
+ u_prev, v_prev = partial_relations[large_prime]
323
+ partial_relations.pop(large_prime)
324
+ try:
325
+ large_prime_inv = invert(large_prime, N)
326
+ except ZeroDivisionError:#if large_prime divides N
327
+ proper_factor.add(large_prime)
328
+ continue
329
+ u = u*u_prev*large_prime_inv
330
+ v = v*v_prev // (large_prime*large_prime)
331
+ vec, is_smooth = _check_smoothness(v, factor_base)
332
+ #assert u*u % N == v % N
333
+ smooth_relations.append((u, v, vec))
334
+ return smooth_relations, proper_factor
335
+
336
+
337
+ #LINEAR ALGEBRA STAGE
338
+ def _build_matrix(smooth_relations):
339
+ """Build a 2D matrix from smooth relations.
340
+
341
+ Parameters
342
+ ==========
343
+
344
+ smooth_relations : Stores smooth relations
345
+ """
346
+ matrix = []
347
+ for s_relation in smooth_relations:
348
+ matrix.append(s_relation[2])
349
+ return matrix
350
+
351
+
352
+ def _gauss_mod_2(A):
353
+ """Fast gaussian reduction for modulo 2 matrix.
354
+
355
+ Parameters
356
+ ==========
357
+
358
+ A : Matrix
359
+
360
+ Examples
361
+ ========
362
+
363
+ >>> from sympy.ntheory.qs import _gauss_mod_2
364
+ >>> _gauss_mod_2([[0, 1, 1], [1, 0, 1], [0, 1, 0], [1, 1, 1]])
365
+ ([[[1, 0, 1], 3]],
366
+ [True, True, True, False],
367
+ [[0, 1, 0], [1, 0, 0], [0, 0, 1], [1, 0, 1]])
368
+
369
+ Reference
370
+ ==========
371
+
372
+ .. [1] A fast algorithm for gaussian elimination over GF(2) and
373
+ its implementation on the GAPP. Cetin K.Koc, Sarath N.Arachchige"""
374
+ import copy
375
+ matrix = copy.deepcopy(A)
376
+ row = len(matrix)
377
+ col = len(matrix[0])
378
+ mark = [False]*row
379
+ for c in range(col):
380
+ for r in range(row):
381
+ if matrix[r][c] == 1:
382
+ break
383
+ mark[r] = True
384
+ for c1 in range(col):
385
+ if c1 == c:
386
+ continue
387
+ if matrix[r][c1] == 1:
388
+ for r2 in range(row):
389
+ matrix[r2][c1] = (matrix[r2][c1] + matrix[r2][c]) % 2
390
+ dependent_row = []
391
+ for idx, val in enumerate(mark):
392
+ if val == False:
393
+ dependent_row.append([matrix[idx], idx])
394
+ return dependent_row, mark, matrix
395
+
396
+
397
+ def _find_factor(dependent_rows, mark, gauss_matrix, index, smooth_relations, N):
398
+ """Finds proper factor of N. Here, transform the dependent rows as a
399
+ combination of independent rows of the gauss_matrix to form the desired
400
+ relation of the form ``X**2 = Y**2 modN``. After obtaining the desired relation
401
+ we obtain a proper factor of N by `gcd(X - Y, N)`.
402
+
403
+ Parameters
404
+ ==========
405
+
406
+ dependent_rows : denoted dependent rows in the reduced matrix form
407
+ mark : boolean array to denoted dependent and independent rows
408
+ gauss_matrix : Reduced form of the smooth relations matrix
409
+ index : denoted the index of the dependent_rows
410
+ smooth_relations : Smooth relations vectors matrix
411
+ N : Number to be factored
412
+ """
413
+ idx_in_smooth = dependent_rows[index][1]
414
+ independent_u = [smooth_relations[idx_in_smooth][0]]
415
+ independent_v = [smooth_relations[idx_in_smooth][1]]
416
+ dept_row = dependent_rows[index][0]
417
+
418
+ for idx, val in enumerate(dept_row):
419
+ if val == 1:
420
+ for row in range(len(gauss_matrix)):
421
+ if gauss_matrix[row][idx] == 1 and mark[row] == True:
422
+ independent_u.append(smooth_relations[row][0])
423
+ independent_v.append(smooth_relations[row][1])
424
+ break
425
+
426
+ u = 1
427
+ v = 1
428
+ for i in independent_u:
429
+ u *= i
430
+ for i in independent_v:
431
+ v *= i
432
+ #assert u**2 % N == v % N
433
+ v = isqrt(v)
434
+ return gcd(u - v, N)
435
+
436
+
437
+ def qs(N, prime_bound, M, ERROR_TERM=25, seed=1234):
438
+ """Performs factorization using Self-Initializing Quadratic Sieve.
439
+ In SIQS, let N be a number to be factored, and this N should not be a
440
+ perfect power. If we find two integers such that ``X**2 = Y**2 modN`` and
441
+ ``X != +-Y modN``, then `gcd(X + Y, N)` will reveal a proper factor of N.
442
+ In order to find these integers X and Y we try to find relations of form
443
+ t**2 = u modN where u is a product of small primes. If we have enough of
444
+ these relations then we can form ``(t1*t2...ti)**2 = u1*u2...ui modN`` such that
445
+ the right hand side is a square, thus we found a relation of ``X**2 = Y**2 modN``.
446
+
447
+ Here, several optimizations are done like using multiple polynomials for
448
+ sieving, fast changing between polynomials and using partial relations.
449
+ The use of partial relations can speeds up the factoring by 2 times.
450
+
451
+ Parameters
452
+ ==========
453
+
454
+ N : Number to be Factored
455
+ prime_bound : upper bound for primes in the factor base
456
+ M : Sieve Interval
457
+ ERROR_TERM : Error term for checking smoothness
458
+ threshold : Extra smooth relations for factorization
459
+ seed : generate pseudo prime numbers
460
+
461
+ Examples
462
+ ========
463
+
464
+ >>> from sympy.ntheory import qs
465
+ >>> qs(25645121643901801, 2000, 10000)
466
+ {5394769, 4753701529}
467
+ >>> qs(9804659461513846513, 2000, 10000)
468
+ {4641991, 2112166839943}
469
+
470
+ References
471
+ ==========
472
+
473
+ .. [1] https://pdfs.semanticscholar.org/5c52/8a975c1405bd35c65993abf5a4edb667c1db.pdf
474
+ .. [2] https://www.rieselprime.de/ziki/Self-initializing_quadratic_sieve
475
+ """
476
+ ERROR_TERM*=2**10
477
+ idx_1000, idx_5000, factor_base = _generate_factor_base(prime_bound, N)
478
+ smooth_relations = []
479
+ ith_poly = 0
480
+ partial_relations = {}
481
+ proper_factor = set()
482
+ threshold = 5*len(factor_base) // 100
483
+ while True:
484
+ if ith_poly == 0:
485
+ ith_sieve_poly, B_array = _initialize_first_polynomial(N, M, factor_base, idx_1000, idx_5000)
486
+ else:
487
+ ith_sieve_poly = _initialize_ith_poly(N, factor_base, ith_poly, ith_sieve_poly, B_array)
488
+ ith_poly += 1
489
+ if ith_poly >= 2**(len(B_array) - 1): # time to start with a new sieve polynomial
490
+ ith_poly = 0
491
+ sieve_array = _gen_sieve_array(M, factor_base)
492
+ s_rel, p_f = _trial_division_stage(N, M, factor_base, sieve_array, ith_sieve_poly, partial_relations, ERROR_TERM)
493
+ smooth_relations += s_rel
494
+ proper_factor |= p_f
495
+ if len(smooth_relations) >= len(factor_base) + threshold:
496
+ break
497
+ matrix = _build_matrix(smooth_relations)
498
+ dependent_row, mark, gauss_matrix = _gauss_mod_2(matrix)
499
+ N_copy = N
500
+ for index in range(len(dependent_row)):
501
+ factor = _find_factor(dependent_row, mark, gauss_matrix, index, smooth_relations, N)
502
+ if factor > 1 and factor < N:
503
+ proper_factor.add(factor)
504
+ while(N_copy % factor == 0):
505
+ N_copy //= factor
506
+ if isprime(N_copy):
507
+ proper_factor.add(N_copy)
508
+ break
509
+ if(N_copy == 1):
510
+ break
511
+ return proper_factor
lib/python3.12/site-packages/sympy/ntheory/residue_ntheory.py ADDED
@@ -0,0 +1,1954 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from __future__ import annotations
2
+
3
+ from sympy.external.gmpy import (gcd, lcm, invert, sqrt, jacobi,
4
+ bit_scan1, remove)
5
+ from sympy.polys import Poly
6
+ from sympy.polys.domains import ZZ
7
+ from sympy.polys.galoistools import gf_crt1, gf_crt2, linear_congruence, gf_csolve
8
+ from .primetest import isprime
9
+ from .generate import primerange
10
+ from .factor_ import factorint, _perfect_power
11
+ from .modular import crt
12
+ from sympy.utilities.decorator import deprecated
13
+ from sympy.utilities.memoization import recurrence_memo
14
+ from sympy.utilities.misc import as_int
15
+ from sympy.utilities.iterables import iproduct
16
+ from sympy.core.random import _randint, randint
17
+
18
+ from itertools import product
19
+
20
+
21
+ def n_order(a, n):
22
+ r""" Returns the order of ``a`` modulo ``n``.
23
+
24
+ Explanation
25
+ ===========
26
+
27
+ The order of ``a`` modulo ``n`` is the smallest integer
28
+ ``k`` such that `a^k` leaves a remainder of 1 with ``n``.
29
+
30
+ Parameters
31
+ ==========
32
+
33
+ a : integer
34
+ n : integer, n > 1. a and n should be relatively prime
35
+
36
+ Returns
37
+ =======
38
+
39
+ int : the order of ``a`` modulo ``n``
40
+
41
+ Raises
42
+ ======
43
+
44
+ ValueError
45
+ If `n \le 1` or `\gcd(a, n) \neq 1`.
46
+ If ``a`` or ``n`` is not an integer.
47
+
48
+ Examples
49
+ ========
50
+
51
+ >>> from sympy.ntheory import n_order
52
+ >>> n_order(3, 7)
53
+ 6
54
+ >>> n_order(4, 7)
55
+ 3
56
+
57
+ See Also
58
+ ========
59
+
60
+ is_primitive_root
61
+ We say that ``a`` is a primitive root of ``n``
62
+ when the order of ``a`` modulo ``n`` equals ``totient(n)``
63
+
64
+ """
65
+ a, n = as_int(a), as_int(n)
66
+ if n <= 1:
67
+ raise ValueError("n should be an integer greater than 1")
68
+ a = a % n
69
+ # Trivial
70
+ if a == 1:
71
+ return 1
72
+ if gcd(a, n) != 1:
73
+ raise ValueError("The two numbers should be relatively prime")
74
+ a_order = 1
75
+ for p, e in factorint(n).items():
76
+ pe = p**e
77
+ pe_order = (p - 1) * p**(e - 1)
78
+ factors = factorint(p - 1)
79
+ if e > 1:
80
+ factors[p] = e - 1
81
+ order = 1
82
+ for px, ex in factors.items():
83
+ x = pow(a, pe_order // px**ex, pe)
84
+ while x != 1:
85
+ x = pow(x, px, pe)
86
+ order *= px
87
+ a_order = lcm(a_order, order)
88
+ return int(a_order)
89
+
90
+
91
+ def _primitive_root_prime_iter(p):
92
+ r""" Generates the primitive roots for a prime ``p``.
93
+
94
+ Explanation
95
+ ===========
96
+
97
+ The primitive roots generated are not necessarily sorted.
98
+ However, the first one is the smallest primitive root.
99
+
100
+ Find the element whose order is ``p-1`` from the smaller one.
101
+ If we can find the first primitive root ``g``, we can use the following theorem.
102
+
103
+ .. math ::
104
+ \operatorname{ord}(g^k) = \frac{\operatorname{ord}(g)}{\gcd(\operatorname{ord}(g), k)}
105
+
106
+ From the assumption that `\operatorname{ord}(g)=p-1`,
107
+ it is a necessary and sufficient condition for
108
+ `\operatorname{ord}(g^k)=p-1` that `\gcd(p-1, k)=1`.
109
+
110
+ Parameters
111
+ ==========
112
+
113
+ p : odd prime
114
+
115
+ Yields
116
+ ======
117
+
118
+ int
119
+ the primitive roots of ``p``
120
+
121
+ Examples
122
+ ========
123
+
124
+ >>> from sympy.ntheory.residue_ntheory import _primitive_root_prime_iter
125
+ >>> sorted(_primitive_root_prime_iter(19))
126
+ [2, 3, 10, 13, 14, 15]
127
+
128
+ References
129
+ ==========
130
+
131
+ .. [1] W. Stein "Elementary Number Theory" (2011), page 44
132
+
133
+ """
134
+ if p == 3:
135
+ yield 2
136
+ return
137
+ # Let p = +-1 (mod 4a). Legendre symbol (a/p) = 1, so `a` is not the primitive root.
138
+ # Corollary : If p = +-1 (mod 8), then 2 is not the primitive root of p.
139
+ g_min = 3 if p % 8 in [1, 7] else 2
140
+ if p < 41:
141
+ # small case
142
+ g = 5 if p == 23 else g_min
143
+ else:
144
+ v = [(p - 1) // i for i in factorint(p - 1).keys()]
145
+ for g in range(g_min, p):
146
+ if all(pow(g, pw, p) != 1 for pw in v):
147
+ break
148
+ yield g
149
+ # g**k is the primitive root of p iff gcd(p - 1, k) = 1
150
+ for k in range(3, p, 2):
151
+ if gcd(p - 1, k) == 1:
152
+ yield pow(g, k, p)
153
+
154
+
155
+ def _primitive_root_prime_power_iter(p, e):
156
+ r""" Generates the primitive roots of `p^e`.
157
+
158
+ Explanation
159
+ ===========
160
+
161
+ Let ``g`` be the primitive root of ``p``.
162
+ If `g^{p-1} \not\equiv 1 \pmod{p^2}`, then ``g`` is primitive root of `p^e`.
163
+ Thus, if we find a primitive root ``g`` of ``p``,
164
+ then `g, g+p, g+2p, \ldots, g+(p-1)p` are primitive roots of `p^2` except one.
165
+ That one satisfies `\hat{g}^{p-1} \equiv 1 \pmod{p^2}`.
166
+ If ``h`` is the primitive root of `p^2`,
167
+ then `h, h+p^2, h+2p^2, \ldots, h+(p^{e-2}-1)p^e` are primitive roots of `p^e`.
168
+
169
+ Parameters
170
+ ==========
171
+
172
+ p : odd prime
173
+ e : positive integer
174
+
175
+ Yields
176
+ ======
177
+
178
+ int
179
+ the primitive roots of `p^e`
180
+
181
+ Examples
182
+ ========
183
+
184
+ >>> from sympy.ntheory.residue_ntheory import _primitive_root_prime_power_iter
185
+ >>> sorted(_primitive_root_prime_power_iter(5, 2))
186
+ [2, 3, 8, 12, 13, 17, 22, 23]
187
+
188
+ """
189
+ if e == 1:
190
+ yield from _primitive_root_prime_iter(p)
191
+ else:
192
+ p2 = p**2
193
+ for g in _primitive_root_prime_iter(p):
194
+ t = (g - pow(g, 2 - p, p2)) % p2
195
+ for k in range(0, p2, p):
196
+ if k != t:
197
+ yield from (g + k + m for m in range(0, p**e, p2))
198
+
199
+
200
+ def _primitive_root_prime_power2_iter(p, e):
201
+ r""" Generates the primitive roots of `2p^e`.
202
+
203
+ Explanation
204
+ ===========
205
+
206
+ If ``g`` is the primitive root of ``p**e``,
207
+ then the odd one of ``g`` and ``g+p**e`` is the primitive root of ``2*p**e``.
208
+
209
+ Parameters
210
+ ==========
211
+
212
+ p : odd prime
213
+ e : positive integer
214
+
215
+ Yields
216
+ ======
217
+
218
+ int
219
+ the primitive roots of `2p^e`
220
+
221
+ Examples
222
+ ========
223
+
224
+ >>> from sympy.ntheory.residue_ntheory import _primitive_root_prime_power2_iter
225
+ >>> sorted(_primitive_root_prime_power2_iter(5, 2))
226
+ [3, 13, 17, 23, 27, 33, 37, 47]
227
+
228
+ """
229
+ for g in _primitive_root_prime_power_iter(p, e):
230
+ if g % 2 == 1:
231
+ yield g
232
+ else:
233
+ yield g + p**e
234
+
235
+
236
+ def primitive_root(p, smallest=True):
237
+ r""" Returns a primitive root of ``p`` or None.
238
+
239
+ Explanation
240
+ ===========
241
+
242
+ For the definition of primitive root,
243
+ see the explanation of ``is_primitive_root``.
244
+
245
+ The primitive root of ``p`` exist only for
246
+ `p = 2, 4, q^e, 2q^e` (``q`` is an odd prime).
247
+ Now, if we know the primitive root of ``q``,
248
+ we can calculate the primitive root of `q^e`,
249
+ and if we know the primitive root of `q^e`,
250
+ we can calculate the primitive root of `2q^e`.
251
+ When there is no need to find the smallest primitive root,
252
+ this property can be used to obtain a fast primitive root.
253
+ On the other hand, when we want the smallest primitive root,
254
+ we naively determine whether it is a primitive root or not.
255
+
256
+ Parameters
257
+ ==========
258
+
259
+ p : integer, p > 1
260
+ smallest : if True the smallest primitive root is returned or None
261
+
262
+ Returns
263
+ =======
264
+
265
+ int | None :
266
+ If the primitive root exists, return the primitive root of ``p``.
267
+ If not, return None.
268
+
269
+ Raises
270
+ ======
271
+
272
+ ValueError
273
+ If `p \le 1` or ``p`` is not an integer.
274
+
275
+ Examples
276
+ ========
277
+
278
+ >>> from sympy.ntheory.residue_ntheory import primitive_root
279
+ >>> primitive_root(19)
280
+ 2
281
+ >>> primitive_root(21) is None
282
+ True
283
+ >>> primitive_root(50, smallest=False)
284
+ 27
285
+
286
+ See Also
287
+ ========
288
+
289
+ is_primitive_root
290
+
291
+ References
292
+ ==========
293
+
294
+ .. [1] W. Stein "Elementary Number Theory" (2011), page 44
295
+ .. [2] P. Hackman "Elementary Number Theory" (2009), Chapter C
296
+
297
+ """
298
+ p = as_int(p)
299
+ if p <= 1:
300
+ raise ValueError("p should be an integer greater than 1")
301
+ if p <= 4:
302
+ return p - 1
303
+ p_even = p % 2 == 0
304
+ if not p_even:
305
+ q = p # p is odd
306
+ elif p % 4:
307
+ q = p//2 # p had 1 factor of 2
308
+ else:
309
+ return None # p had more than one factor of 2
310
+ if isprime(q):
311
+ e = 1
312
+ else:
313
+ m = _perfect_power(q, 3)
314
+ if not m:
315
+ return None
316
+ q, e = m
317
+ if not isprime(q):
318
+ return None
319
+ if not smallest:
320
+ if p_even:
321
+ return next(_primitive_root_prime_power2_iter(q, e))
322
+ return next(_primitive_root_prime_power_iter(q, e))
323
+ if p_even:
324
+ for i in range(3, p, 2):
325
+ if i % q and is_primitive_root(i, p):
326
+ return i
327
+ g = next(_primitive_root_prime_iter(q))
328
+ if e == 1 or pow(g, q - 1, q**2) != 1:
329
+ return g
330
+ for i in range(g + 1, p):
331
+ if i % q and is_primitive_root(i, p):
332
+ return i
333
+
334
+
335
+ def is_primitive_root(a, p):
336
+ r""" Returns True if ``a`` is a primitive root of ``p``.
337
+
338
+ Explanation
339
+ ===========
340
+
341
+ ``a`` is said to be the primitive root of ``p`` if `\gcd(a, p) = 1` and
342
+ `\phi(p)` is the smallest positive number s.t.
343
+
344
+ `a^{\phi(p)} \equiv 1 \pmod{p}`.
345
+
346
+ where `\phi(p)` is Euler's totient function.
347
+
348
+ The primitive root of ``p`` exist only for
349
+ `p = 2, 4, q^e, 2q^e` (``q`` is an odd prime).
350
+ Hence, if it is not such a ``p``, it returns False.
351
+ To determine the primitive root, we need to know
352
+ the prime factorization of ``q-1``.
353
+ The hardness of the determination depends on this complexity.
354
+
355
+ Parameters
356
+ ==========
357
+
358
+ a : integer
359
+ p : integer, ``p`` > 1. ``a`` and ``p`` should be relatively prime
360
+
361
+ Returns
362
+ =======
363
+
364
+ bool : If True, ``a`` is the primitive root of ``p``.
365
+
366
+ Raises
367
+ ======
368
+
369
+ ValueError
370
+ If `p \le 1` or `\gcd(a, p) \neq 1`.
371
+ If ``a`` or ``p`` is not an integer.
372
+
373
+ Examples
374
+ ========
375
+
376
+ >>> from sympy.functions.combinatorial.numbers import totient
377
+ >>> from sympy.ntheory import is_primitive_root, n_order
378
+ >>> is_primitive_root(3, 10)
379
+ True
380
+ >>> is_primitive_root(9, 10)
381
+ False
382
+ >>> n_order(3, 10) == totient(10)
383
+ True
384
+ >>> n_order(9, 10) == totient(10)
385
+ False
386
+
387
+ See Also
388
+ ========
389
+
390
+ primitive_root
391
+
392
+ """
393
+ a, p = as_int(a), as_int(p)
394
+ if p <= 1:
395
+ raise ValueError("p should be an integer greater than 1")
396
+ a = a % p
397
+ if gcd(a, p) != 1:
398
+ raise ValueError("The two numbers should be relatively prime")
399
+ # Primitive root of p exist only for
400
+ # p = 2, 4, q**e, 2*q**e (q is odd prime)
401
+ if p <= 4:
402
+ # The primitive root is only p-1.
403
+ return a == p - 1
404
+ if p % 2:
405
+ q = p # p is odd
406
+ elif p % 4:
407
+ q = p//2 # p had 1 factor of 2
408
+ else:
409
+ return False # p had more than one factor of 2
410
+ if isprime(q):
411
+ group_order = q - 1
412
+ factors = factorint(q - 1).keys()
413
+ else:
414
+ m = _perfect_power(q, 3)
415
+ if not m:
416
+ return False
417
+ q, e = m
418
+ if not isprime(q):
419
+ return False
420
+ group_order = q**(e - 1)*(q - 1)
421
+ factors = set(factorint(q - 1).keys())
422
+ factors.add(q)
423
+ return all(pow(a, group_order // prime, p) != 1 for prime in factors)
424
+
425
+
426
+ def _sqrt_mod_tonelli_shanks(a, p):
427
+ """
428
+ Returns the square root in the case of ``p`` prime with ``p == 1 (mod 8)``
429
+
430
+ Assume that the root exists.
431
+
432
+ Parameters
433
+ ==========
434
+
435
+ a : int
436
+ p : int
437
+ prime number. should be ``p % 8 == 1``
438
+
439
+ Returns
440
+ =======
441
+
442
+ int : Generally, there are two roots, but only one is returned.
443
+ Which one is returned is random.
444
+
445
+ Examples
446
+ ========
447
+
448
+ >>> from sympy.ntheory.residue_ntheory import _sqrt_mod_tonelli_shanks
449
+ >>> _sqrt_mod_tonelli_shanks(2, 17) in [6, 11]
450
+ True
451
+
452
+ References
453
+ ==========
454
+
455
+ .. [1] Carl Pomerance, Richard Crandall, Prime Numbers: A Computational Perspective,
456
+ 2nd Edition (2005), page 101, ISBN:978-0387252827
457
+
458
+ """
459
+ s = bit_scan1(p - 1)
460
+ t = p >> s
461
+ # find a non-quadratic residue
462
+ if p % 12 == 5:
463
+ # Legendre symbol (3/p) == -1 if p % 12 in [5, 7]
464
+ d = 3
465
+ elif p % 5 in [2, 3]:
466
+ # Legendre symbol (5/p) == -1 if p % 5 in [2, 3]
467
+ d = 5
468
+ else:
469
+ while 1:
470
+ d = randint(6, p - 1)
471
+ if jacobi(d, p) == -1:
472
+ break
473
+ #assert legendre_symbol(d, p) == -1
474
+ A = pow(a, t, p)
475
+ D = pow(d, t, p)
476
+ m = 0
477
+ for i in range(s):
478
+ adm = A*pow(D, m, p) % p
479
+ adm = pow(adm, 2**(s - 1 - i), p)
480
+ if adm % p == p - 1:
481
+ m += 2**i
482
+ #assert A*pow(D, m, p) % p == 1
483
+ x = pow(a, (t + 1)//2, p)*pow(D, m//2, p) % p
484
+ return x
485
+
486
+
487
+ def sqrt_mod(a, p, all_roots=False):
488
+ """
489
+ Find a root of ``x**2 = a mod p``.
490
+
491
+ Parameters
492
+ ==========
493
+
494
+ a : integer
495
+ p : positive integer
496
+ all_roots : if True the list of roots is returned or None
497
+
498
+ Notes
499
+ =====
500
+
501
+ If there is no root it is returned None; else the returned root
502
+ is less or equal to ``p // 2``; in general is not the smallest one.
503
+ It is returned ``p // 2`` only if it is the only root.
504
+
505
+ Use ``all_roots`` only when it is expected that all the roots fit
506
+ in memory; otherwise use ``sqrt_mod_iter``.
507
+
508
+ Examples
509
+ ========
510
+
511
+ >>> from sympy.ntheory import sqrt_mod
512
+ >>> sqrt_mod(11, 43)
513
+ 21
514
+ >>> sqrt_mod(17, 32, True)
515
+ [7, 9, 23, 25]
516
+ """
517
+ if all_roots:
518
+ return sorted(sqrt_mod_iter(a, p))
519
+ p = abs(as_int(p))
520
+ halfp = p // 2
521
+ x = None
522
+ for r in sqrt_mod_iter(a, p):
523
+ if r < halfp:
524
+ return r
525
+ elif r > halfp:
526
+ return p - r
527
+ else:
528
+ x = r
529
+ return x
530
+
531
+
532
+ def sqrt_mod_iter(a, p, domain=int):
533
+ """
534
+ Iterate over solutions to ``x**2 = a mod p``.
535
+
536
+ Parameters
537
+ ==========
538
+
539
+ a : integer
540
+ p : positive integer
541
+ domain : integer domain, ``int``, ``ZZ`` or ``Integer``
542
+
543
+ Examples
544
+ ========
545
+
546
+ >>> from sympy.ntheory.residue_ntheory import sqrt_mod_iter
547
+ >>> list(sqrt_mod_iter(11, 43))
548
+ [21, 22]
549
+
550
+ See Also
551
+ ========
552
+
553
+ sqrt_mod : Same functionality, but you want a sorted list or only one solution.
554
+
555
+ """
556
+ a, p = as_int(a), abs(as_int(p))
557
+ v = []
558
+ pv = []
559
+ _product = product
560
+ for px, ex in factorint(p).items():
561
+ if a % px:
562
+ # `len(rx)` is at most 4
563
+ rx = _sqrt_mod_prime_power(a, px, ex)
564
+ else:
565
+ # `len(list(rx))` can be assumed to be large.
566
+ # The `itertools.product` is disadvantageous in terms of memory usage.
567
+ # It is also inferior to iproduct in speed if not all Cartesian products are needed.
568
+ rx = _sqrt_mod1(a, px, ex)
569
+ _product = iproduct
570
+ if not rx:
571
+ return
572
+ v.append(rx)
573
+ pv.append(px**ex)
574
+ if len(v) == 1:
575
+ yield from map(domain, v[0])
576
+ else:
577
+ mm, e, s = gf_crt1(pv, ZZ)
578
+ for vx in _product(*v):
579
+ yield domain(gf_crt2(vx, pv, mm, e, s, ZZ))
580
+
581
+
582
+ def _sqrt_mod_prime_power(a, p, k):
583
+ """
584
+ Find the solutions to ``x**2 = a mod p**k`` when ``a % p != 0``.
585
+ If no solution exists, return ``None``.
586
+ Solutions are returned in an ascending list.
587
+
588
+ Parameters
589
+ ==========
590
+
591
+ a : integer
592
+ p : prime number
593
+ k : positive integer
594
+
595
+ Examples
596
+ ========
597
+
598
+ >>> from sympy.ntheory.residue_ntheory import _sqrt_mod_prime_power
599
+ >>> _sqrt_mod_prime_power(11, 43, 1)
600
+ [21, 22]
601
+
602
+ References
603
+ ==========
604
+
605
+ .. [1] P. Hackman "Elementary Number Theory" (2009), page 160
606
+ .. [2] http://www.numbertheory.org/php/squareroot.html
607
+ .. [3] [Gathen99]_
608
+ """
609
+ pk = p**k
610
+ a = a % pk
611
+
612
+ if p == 2:
613
+ # see Ref.[2]
614
+ if a % 8 != 1:
615
+ return None
616
+ # Trivial
617
+ if k <= 3:
618
+ return list(range(1, pk, 2))
619
+ r = 1
620
+ # r is one of the solutions to x**2 - a = 0 (mod 2**3).
621
+ # Hensel lift them to solutions of x**2 - a = 0 (mod 2**k)
622
+ # if r**2 - a = 0 mod 2**nx but not mod 2**(nx+1)
623
+ # then r + 2**(nx - 1) is a root mod 2**(nx+1)
624
+ for nx in range(3, k):
625
+ if ((r**2 - a) >> nx) % 2:
626
+ r += 1 << (nx - 1)
627
+ # r is a solution of x**2 - a = 0 (mod 2**k), and
628
+ # there exist other solutions -r, r+h, -(r+h), and these are all solutions.
629
+ h = 1 << (k - 1)
630
+ return sorted([r, pk - r, (r + h) % pk, -(r + h) % pk])
631
+
632
+ # If the Legendre symbol (a/p) is not 1, no solution exists.
633
+ if jacobi(a, p) != 1:
634
+ return None
635
+ if p % 4 == 3:
636
+ res = pow(a, (p + 1) // 4, p)
637
+ elif p % 8 == 5:
638
+ res = pow(a, (p + 3) // 8, p)
639
+ if pow(res, 2, p) != a % p:
640
+ res = res * pow(2, (p - 1) // 4, p) % p
641
+ else:
642
+ res = _sqrt_mod_tonelli_shanks(a, p)
643
+ if k > 1:
644
+ # Hensel lifting with Newton iteration, see Ref.[3] chapter 9
645
+ # with f(x) = x**2 - a; one has f'(a) != 0 (mod p) for p != 2
646
+ px = p
647
+ for _ in range(k.bit_length() - 1):
648
+ px = px**2
649
+ frinv = invert(2*res, px)
650
+ res = (res - (res**2 - a)*frinv) % px
651
+ if k & (k - 1): # If k is not a power of 2
652
+ frinv = invert(2*res, pk)
653
+ res = (res - (res**2 - a)*frinv) % pk
654
+ return sorted([res, pk - res])
655
+
656
+
657
+ def _sqrt_mod1(a, p, n):
658
+ """
659
+ Find solution to ``x**2 == a mod p**n`` when ``a % p == 0``.
660
+ If no solution exists, return ``None``.
661
+
662
+ Parameters
663
+ ==========
664
+
665
+ a : integer
666
+ p : prime number, p must divide a
667
+ n : positive integer
668
+
669
+ References
670
+ ==========
671
+
672
+ .. [1] http://www.numbertheory.org/php/squareroot.html
673
+ """
674
+ pn = p**n
675
+ a = a % pn
676
+ if a == 0:
677
+ # case gcd(a, p**k) = p**n
678
+ return range(0, pn, p**((n + 1) // 2))
679
+ # case gcd(a, p**k) = p**r, r < n
680
+ a, r = remove(a, p)
681
+ if r % 2 == 1:
682
+ return None
683
+ res = _sqrt_mod_prime_power(a, p, n - r)
684
+ if res is None:
685
+ return None
686
+ m = r // 2
687
+ return (x for rx in res for x in range(rx*p**m, pn, p**(n - m)))
688
+
689
+
690
+ def is_quad_residue(a, p):
691
+ """
692
+ Returns True if ``a`` (mod ``p``) is in the set of squares mod ``p``,
693
+ i.e a % p in set([i**2 % p for i in range(p)]).
694
+
695
+ Parameters
696
+ ==========
697
+
698
+ a : integer
699
+ p : positive integer
700
+
701
+ Returns
702
+ =======
703
+
704
+ bool : If True, ``x**2 == a (mod p)`` has solution.
705
+
706
+ Raises
707
+ ======
708
+
709
+ ValueError
710
+ If ``a``, ``p`` is not integer.
711
+ If ``p`` is not positive.
712
+
713
+ Examples
714
+ ========
715
+
716
+ >>> from sympy.ntheory import is_quad_residue
717
+ >>> is_quad_residue(21, 100)
718
+ True
719
+
720
+ Indeed, ``pow(39, 2, 100)`` would be 21.
721
+
722
+ >>> is_quad_residue(21, 120)
723
+ False
724
+
725
+ That is, for any integer ``x``, ``pow(x, 2, 120)`` is not 21.
726
+
727
+ If ``p`` is an odd
728
+ prime, an iterative method is used to make the determination:
729
+
730
+ >>> from sympy.ntheory import is_quad_residue
731
+ >>> sorted(set([i**2 % 7 for i in range(7)]))
732
+ [0, 1, 2, 4]
733
+ >>> [j for j in range(7) if is_quad_residue(j, 7)]
734
+ [0, 1, 2, 4]
735
+
736
+ See Also
737
+ ========
738
+
739
+ legendre_symbol, jacobi_symbol, sqrt_mod
740
+ """
741
+ a, p = as_int(a), as_int(p)
742
+ if p < 1:
743
+ raise ValueError('p must be > 0')
744
+ a %= p
745
+ if a < 2 or p < 3:
746
+ return True
747
+ # Since we want to compute the Jacobi symbol,
748
+ # we separate p into the odd part and the rest.
749
+ t = bit_scan1(p)
750
+ if t:
751
+ # The existence of a solution to a power of 2 is determined
752
+ # using the logic of `p==2` in `_sqrt_mod_prime_power` and `_sqrt_mod1`.
753
+ a_ = a % (1 << t)
754
+ if a_:
755
+ r = bit_scan1(a_)
756
+ if r % 2 or (a_ >> r) & 6:
757
+ return False
758
+ p >>= t
759
+ a %= p
760
+ if a < 2 or p < 3:
761
+ return True
762
+ # If Jacobi symbol is -1 or p is prime, can be determined by Jacobi symbol only
763
+ j = jacobi(a, p)
764
+ if j == -1 or isprime(p):
765
+ return j == 1
766
+ # Checks if `x**2 = a (mod p)` has a solution
767
+ for px, ex in factorint(p).items():
768
+ if a % px:
769
+ if jacobi(a, px) != 1:
770
+ return False
771
+ else:
772
+ a_ = a % px**ex
773
+ if a_ == 0:
774
+ continue
775
+ a_, r = remove(a_, px)
776
+ if r % 2 or jacobi(a_, px) != 1:
777
+ return False
778
+ return True
779
+
780
+
781
+ def is_nthpow_residue(a, n, m):
782
+ """
783
+ Returns True if ``x**n == a (mod m)`` has solutions.
784
+
785
+ References
786
+ ==========
787
+
788
+ .. [1] P. Hackman "Elementary Number Theory" (2009), page 76
789
+
790
+ """
791
+ a = a % m
792
+ a, n, m = as_int(a), as_int(n), as_int(m)
793
+ if m <= 0:
794
+ raise ValueError('m must be > 0')
795
+ if n < 0:
796
+ raise ValueError('n must be >= 0')
797
+ if n == 0:
798
+ if m == 1:
799
+ return False
800
+ return a == 1
801
+ if a == 0:
802
+ return True
803
+ if n == 1:
804
+ return True
805
+ if n == 2:
806
+ return is_quad_residue(a, m)
807
+ return all(_is_nthpow_residue_bign_prime_power(a, n, p, e)
808
+ for p, e in factorint(m).items())
809
+
810
+
811
+ def _is_nthpow_residue_bign_prime_power(a, n, p, k):
812
+ r"""
813
+ Returns True if `x^n = a \pmod{p^k}` has solutions for `n > 2`.
814
+
815
+ Parameters
816
+ ==========
817
+
818
+ a : positive integer
819
+ n : integer, n > 2
820
+ p : prime number
821
+ k : positive integer
822
+
823
+ """
824
+ while a % p == 0:
825
+ a %= pow(p, k)
826
+ if not a:
827
+ return True
828
+ a, mu = remove(a, p)
829
+ if mu % n:
830
+ return False
831
+ k -= mu
832
+ if p != 2:
833
+ f = p**(k - 1)*(p - 1) # f = totient(p**k)
834
+ return pow(a, f // gcd(f, n), pow(p, k)) == 1
835
+ if n & 1:
836
+ return True
837
+ c = min(bit_scan1(n) + 2, k)
838
+ return a % pow(2, c) == 1
839
+
840
+
841
+ def _nthroot_mod1(s, q, p, all_roots):
842
+ """
843
+ Root of ``x**q = s mod p``, ``p`` prime and ``q`` divides ``p - 1``.
844
+ Assume that the root exists.
845
+
846
+ Parameters
847
+ ==========
848
+
849
+ s : integer
850
+ q : integer, n > 2. ``q`` divides ``p - 1``.
851
+ p : prime number
852
+ all_roots : if False returns the smallest root, else the list of roots
853
+
854
+ Returns
855
+ =======
856
+
857
+ list[int] | int :
858
+ Root of ``x**q = s mod p``. If ``all_roots == True``,
859
+ returned ascending list. otherwise, returned an int.
860
+
861
+ Examples
862
+ ========
863
+
864
+ >>> from sympy.ntheory.residue_ntheory import _nthroot_mod1
865
+ >>> _nthroot_mod1(5, 3, 13, False)
866
+ 7
867
+ >>> _nthroot_mod1(13, 4, 17, True)
868
+ [3, 5, 12, 14]
869
+
870
+ References
871
+ ==========
872
+
873
+ .. [1] A. M. Johnston, A Generalized qth Root Algorithm,
874
+ ACM-SIAM Symposium on Discrete Algorithms (1999), pp. 929-930
875
+
876
+ """
877
+ g = next(_primitive_root_prime_iter(p))
878
+ r = s
879
+ for qx, ex in factorint(q).items():
880
+ f = (p - 1) // qx**ex
881
+ while f % qx == 0:
882
+ f //= qx
883
+ z = f*invert(-f, qx)
884
+ x = (1 + z) // qx
885
+ t = discrete_log(p, pow(r, f, p), pow(g, f*qx, p))
886
+ for _ in range(ex):
887
+ # assert t == discrete_log(p, pow(r, f, p), pow(g, f*qx, p))
888
+ r = pow(r, x, p)*pow(g, -z*t % (p - 1), p) % p
889
+ t //= qx
890
+ res = [r]
891
+ h = pow(g, (p - 1) // q, p)
892
+ #assert pow(h, q, p) == 1
893
+ hx = r
894
+ for _ in range(q - 1):
895
+ hx = (hx*h) % p
896
+ res.append(hx)
897
+ if all_roots:
898
+ res.sort()
899
+ return res
900
+ return min(res)
901
+
902
+
903
+ def _nthroot_mod_prime_power(a, n, p, k):
904
+ """ Root of ``x**n = a mod p**k``.
905
+
906
+ Parameters
907
+ ==========
908
+
909
+ a : integer
910
+ n : integer, n > 2
911
+ p : prime number
912
+ k : positive integer
913
+
914
+ Returns
915
+ =======
916
+
917
+ list[int] :
918
+ Ascending list of roots of ``x**n = a mod p**k``.
919
+ If no solution exists, return ``[]``.
920
+
921
+ """
922
+ if not _is_nthpow_residue_bign_prime_power(a, n, p, k):
923
+ return []
924
+ a_mod_p = a % p
925
+ if a_mod_p == 0:
926
+ base_roots = [0]
927
+ elif (p - 1) % n == 0:
928
+ base_roots = _nthroot_mod1(a_mod_p, n, p, all_roots=True)
929
+ else:
930
+ # The roots of ``x**n - a = 0 (mod p)`` are roots of
931
+ # ``gcd(x**n - a, x**(p - 1) - 1) = 0 (mod p)``
932
+ pa = n
933
+ pb = p - 1
934
+ b = 1
935
+ if pa < pb:
936
+ a_mod_p, pa, b, pb = b, pb, a_mod_p, pa
937
+ # gcd(x**pa - a, x**pb - b) = gcd(x**pb - b, x**pc - c)
938
+ # where pc = pa % pb; c = b**-q * a mod p
939
+ while pb:
940
+ q, pc = divmod(pa, pb)
941
+ c = pow(b, -q, p) * a_mod_p % p
942
+ pa, pb = pb, pc
943
+ a_mod_p, b = b, c
944
+ if pa == 1:
945
+ base_roots = [a_mod_p]
946
+ elif pa == 2:
947
+ base_roots = sqrt_mod(a_mod_p, p, all_roots=True)
948
+ else:
949
+ base_roots = _nthroot_mod1(a_mod_p, pa, p, all_roots=True)
950
+ if k == 1:
951
+ return base_roots
952
+ a %= p**k
953
+ tot_roots = set()
954
+ for root in base_roots:
955
+ diff = pow(root, n - 1, p)*n % p
956
+ new_base = p
957
+ if diff != 0:
958
+ m_inv = invert(diff, p)
959
+ for _ in range(k - 1):
960
+ new_base *= p
961
+ tmp = pow(root, n, new_base) - a
962
+ tmp *= m_inv
963
+ root = (root - tmp) % new_base
964
+ tot_roots.add(root)
965
+ else:
966
+ roots_in_base = {root}
967
+ for _ in range(k - 1):
968
+ new_base *= p
969
+ new_roots = set()
970
+ for k_ in roots_in_base:
971
+ if pow(k_, n, new_base) != a % new_base:
972
+ continue
973
+ while k_ not in new_roots:
974
+ new_roots.add(k_)
975
+ k_ = (k_ + (new_base // p)) % new_base
976
+ roots_in_base = new_roots
977
+ tot_roots = tot_roots | roots_in_base
978
+ return sorted(tot_roots)
979
+
980
+
981
+ def nthroot_mod(a, n, p, all_roots=False):
982
+ """
983
+ Find the solutions to ``x**n = a mod p``.
984
+
985
+ Parameters
986
+ ==========
987
+
988
+ a : integer
989
+ n : positive integer
990
+ p : positive integer
991
+ all_roots : if False returns the smallest root, else the list of roots
992
+
993
+ Returns
994
+ =======
995
+
996
+ list[int] | int | None :
997
+ solutions to ``x**n = a mod p``.
998
+ The table of the output type is:
999
+
1000
+ ========== ========== ==========
1001
+ all_roots has roots Returns
1002
+ ========== ========== ==========
1003
+ True Yes list[int]
1004
+ True No []
1005
+ False Yes int
1006
+ False No None
1007
+ ========== ========== ==========
1008
+
1009
+ Raises
1010
+ ======
1011
+
1012
+ ValueError
1013
+ If ``a``, ``n`` or ``p`` is not integer.
1014
+ If ``n`` or ``p`` is not positive.
1015
+
1016
+ Examples
1017
+ ========
1018
+
1019
+ >>> from sympy.ntheory.residue_ntheory import nthroot_mod
1020
+ >>> nthroot_mod(11, 4, 19)
1021
+ 8
1022
+ >>> nthroot_mod(11, 4, 19, True)
1023
+ [8, 11]
1024
+ >>> nthroot_mod(68, 3, 109)
1025
+ 23
1026
+
1027
+ References
1028
+ ==========
1029
+
1030
+ .. [1] P. Hackman "Elementary Number Theory" (2009), page 76
1031
+
1032
+ """
1033
+ a = a % p
1034
+ a, n, p = as_int(a), as_int(n), as_int(p)
1035
+
1036
+ if n < 1:
1037
+ raise ValueError("n should be positive")
1038
+ if p < 1:
1039
+ raise ValueError("p should be positive")
1040
+ if n == 1:
1041
+ return [a] if all_roots else a
1042
+ if n == 2:
1043
+ return sqrt_mod(a, p, all_roots)
1044
+ base = []
1045
+ prime_power = []
1046
+ for q, e in factorint(p).items():
1047
+ tot_roots = _nthroot_mod_prime_power(a, n, q, e)
1048
+ if not tot_roots:
1049
+ return [] if all_roots else None
1050
+ prime_power.append(q**e)
1051
+ base.append(sorted(tot_roots))
1052
+ P, E, S = gf_crt1(prime_power, ZZ)
1053
+ ret = sorted(map(int, {gf_crt2(c, prime_power, P, E, S, ZZ)
1054
+ for c in product(*base)}))
1055
+ if all_roots:
1056
+ return ret
1057
+ if ret:
1058
+ return ret[0]
1059
+
1060
+
1061
+ def quadratic_residues(p) -> list[int]:
1062
+ """
1063
+ Returns the list of quadratic residues.
1064
+
1065
+ Examples
1066
+ ========
1067
+
1068
+ >>> from sympy.ntheory.residue_ntheory import quadratic_residues
1069
+ >>> quadratic_residues(7)
1070
+ [0, 1, 2, 4]
1071
+ """
1072
+ p = as_int(p)
1073
+ r = {pow(i, 2, p) for i in range(p // 2 + 1)}
1074
+ return sorted(r)
1075
+
1076
+
1077
+ @deprecated("""\
1078
+ The `sympy.ntheory.residue_ntheory.legendre_symbol` has been moved to `sympy.functions.combinatorial.numbers.legendre_symbol`.""",
1079
+ deprecated_since_version="1.13",
1080
+ active_deprecations_target='deprecated-ntheory-symbolic-functions')
1081
+ def legendre_symbol(a, p):
1082
+ r"""
1083
+ Returns the Legendre symbol `(a / p)`.
1084
+
1085
+ .. deprecated:: 1.13
1086
+
1087
+ The ``legendre_symbol`` function is deprecated. Use :class:`sympy.functions.combinatorial.numbers.legendre_symbol`
1088
+ instead. See its documentation for more information. See
1089
+ :ref:`deprecated-ntheory-symbolic-functions` for details.
1090
+
1091
+ For an integer ``a`` and an odd prime ``p``, the Legendre symbol is
1092
+ defined as
1093
+
1094
+ .. math ::
1095
+ \genfrac(){}{}{a}{p} = \begin{cases}
1096
+ 0 & \text{if } p \text{ divides } a\\
1097
+ 1 & \text{if } a \text{ is a quadratic residue modulo } p\\
1098
+ -1 & \text{if } a \text{ is a quadratic nonresidue modulo } p
1099
+ \end{cases}
1100
+
1101
+ Parameters
1102
+ ==========
1103
+
1104
+ a : integer
1105
+ p : odd prime
1106
+
1107
+ Examples
1108
+ ========
1109
+
1110
+ >>> from sympy.functions.combinatorial.numbers import legendre_symbol
1111
+ >>> [legendre_symbol(i, 7) for i in range(7)]
1112
+ [0, 1, 1, -1, 1, -1, -1]
1113
+ >>> sorted(set([i**2 % 7 for i in range(7)]))
1114
+ [0, 1, 2, 4]
1115
+
1116
+ See Also
1117
+ ========
1118
+
1119
+ is_quad_residue, jacobi_symbol
1120
+
1121
+ """
1122
+ from sympy.functions.combinatorial.numbers import legendre_symbol as _legendre_symbol
1123
+ return _legendre_symbol(a, p)
1124
+
1125
+
1126
+ @deprecated("""\
1127
+ The `sympy.ntheory.residue_ntheory.jacobi_symbol` has been moved to `sympy.functions.combinatorial.numbers.jacobi_symbol`.""",
1128
+ deprecated_since_version="1.13",
1129
+ active_deprecations_target='deprecated-ntheory-symbolic-functions')
1130
+ def jacobi_symbol(m, n):
1131
+ r"""
1132
+ Returns the Jacobi symbol `(m / n)`.
1133
+
1134
+ .. deprecated:: 1.13
1135
+
1136
+ The ``jacobi_symbol`` function is deprecated. Use :class:`sympy.functions.combinatorial.numbers.jacobi_symbol`
1137
+ instead. See its documentation for more information. See
1138
+ :ref:`deprecated-ntheory-symbolic-functions` for details.
1139
+
1140
+ For any integer ``m`` and any positive odd integer ``n`` the Jacobi symbol
1141
+ is defined as the product of the Legendre symbols corresponding to the
1142
+ prime factors of ``n``:
1143
+
1144
+ .. math ::
1145
+ \genfrac(){}{}{m}{n} =
1146
+ \genfrac(){}{}{m}{p^{1}}^{\alpha_1}
1147
+ \genfrac(){}{}{m}{p^{2}}^{\alpha_2}
1148
+ ...
1149
+ \genfrac(){}{}{m}{p^{k}}^{\alpha_k}
1150
+ \text{ where } n =
1151
+ p_1^{\alpha_1}
1152
+ p_2^{\alpha_2}
1153
+ ...
1154
+ p_k^{\alpha_k}
1155
+
1156
+ Like the Legendre symbol, if the Jacobi symbol `\genfrac(){}{}{m}{n} = -1`
1157
+ then ``m`` is a quadratic nonresidue modulo ``n``.
1158
+
1159
+ But, unlike the Legendre symbol, if the Jacobi symbol
1160
+ `\genfrac(){}{}{m}{n} = 1` then ``m`` may or may not be a quadratic residue
1161
+ modulo ``n``.
1162
+
1163
+ Parameters
1164
+ ==========
1165
+
1166
+ m : integer
1167
+ n : odd positive integer
1168
+
1169
+ Examples
1170
+ ========
1171
+
1172
+ >>> from sympy.functions.combinatorial.numbers import jacobi_symbol, legendre_symbol
1173
+ >>> from sympy import S
1174
+ >>> jacobi_symbol(45, 77)
1175
+ -1
1176
+ >>> jacobi_symbol(60, 121)
1177
+ 1
1178
+
1179
+ The relationship between the ``jacobi_symbol`` and ``legendre_symbol`` can
1180
+ be demonstrated as follows:
1181
+
1182
+ >>> L = legendre_symbol
1183
+ >>> S(45).factors()
1184
+ {3: 2, 5: 1}
1185
+ >>> jacobi_symbol(7, 45) == L(7, 3)**2 * L(7, 5)**1
1186
+ True
1187
+
1188
+ See Also
1189
+ ========
1190
+
1191
+ is_quad_residue, legendre_symbol
1192
+ """
1193
+ from sympy.functions.combinatorial.numbers import jacobi_symbol as _jacobi_symbol
1194
+ return _jacobi_symbol(m, n)
1195
+
1196
+
1197
+ @deprecated("""\
1198
+ The `sympy.ntheory.residue_ntheory.mobius` has been moved to `sympy.functions.combinatorial.numbers.mobius`.""",
1199
+ deprecated_since_version="1.13",
1200
+ active_deprecations_target='deprecated-ntheory-symbolic-functions')
1201
+ def mobius(n):
1202
+ """
1203
+ Mobius function maps natural number to {-1, 0, 1}
1204
+
1205
+ .. deprecated:: 1.13
1206
+
1207
+ The ``mobius`` function is deprecated. Use :class:`sympy.functions.combinatorial.numbers.mobius`
1208
+ instead. See its documentation for more information. See
1209
+ :ref:`deprecated-ntheory-symbolic-functions` for details.
1210
+
1211
+ It is defined as follows:
1212
+ 1) `1` if `n = 1`.
1213
+ 2) `0` if `n` has a squared prime factor.
1214
+ 3) `(-1)^k` if `n` is a square-free positive integer with `k`
1215
+ number of prime factors.
1216
+
1217
+ It is an important multiplicative function in number theory
1218
+ and combinatorics. It has applications in mathematical series,
1219
+ algebraic number theory and also physics (Fermion operator has very
1220
+ concrete realization with Mobius Function model).
1221
+
1222
+ Parameters
1223
+ ==========
1224
+
1225
+ n : positive integer
1226
+
1227
+ Examples
1228
+ ========
1229
+
1230
+ >>> from sympy.functions.combinatorial.numbers import mobius
1231
+ >>> mobius(13*7)
1232
+ 1
1233
+ >>> mobius(1)
1234
+ 1
1235
+ >>> mobius(13*7*5)
1236
+ -1
1237
+ >>> mobius(13**2)
1238
+ 0
1239
+
1240
+ References
1241
+ ==========
1242
+
1243
+ .. [1] https://en.wikipedia.org/wiki/M%C3%B6bius_function
1244
+ .. [2] Thomas Koshy "Elementary Number Theory with Applications"
1245
+
1246
+ """
1247
+ from sympy.functions.combinatorial.numbers import mobius as _mobius
1248
+ return _mobius(n)
1249
+
1250
+
1251
+ def _discrete_log_trial_mul(n, a, b, order=None):
1252
+ """
1253
+ Trial multiplication algorithm for computing the discrete logarithm of
1254
+ ``a`` to the base ``b`` modulo ``n``.
1255
+
1256
+ The algorithm finds the discrete logarithm using exhaustive search. This
1257
+ naive method is used as fallback algorithm of ``discrete_log`` when the
1258
+ group order is very small.
1259
+
1260
+ Examples
1261
+ ========
1262
+
1263
+ >>> from sympy.ntheory.residue_ntheory import _discrete_log_trial_mul
1264
+ >>> _discrete_log_trial_mul(41, 15, 7)
1265
+ 3
1266
+
1267
+ See Also
1268
+ ========
1269
+
1270
+ discrete_log
1271
+
1272
+ References
1273
+ ==========
1274
+
1275
+ .. [1] "Handbook of applied cryptography", Menezes, A. J., Van, O. P. C., &
1276
+ Vanstone, S. A. (1997).
1277
+ """
1278
+ a %= n
1279
+ b %= n
1280
+ if order is None:
1281
+ order = n
1282
+ x = 1
1283
+ for i in range(order):
1284
+ if x == a:
1285
+ return i
1286
+ x = x * b % n
1287
+ raise ValueError("Log does not exist")
1288
+
1289
+
1290
+ def _discrete_log_shanks_steps(n, a, b, order=None):
1291
+ """
1292
+ Baby-step giant-step algorithm for computing the discrete logarithm of
1293
+ ``a`` to the base ``b`` modulo ``n``.
1294
+
1295
+ The algorithm is a time-memory trade-off of the method of exhaustive
1296
+ search. It uses `O(sqrt(m))` memory, where `m` is the group order.
1297
+
1298
+ Examples
1299
+ ========
1300
+
1301
+ >>> from sympy.ntheory.residue_ntheory import _discrete_log_shanks_steps
1302
+ >>> _discrete_log_shanks_steps(41, 15, 7)
1303
+ 3
1304
+
1305
+ See Also
1306
+ ========
1307
+
1308
+ discrete_log
1309
+
1310
+ References
1311
+ ==========
1312
+
1313
+ .. [1] "Handbook of applied cryptography", Menezes, A. J., Van, O. P. C., &
1314
+ Vanstone, S. A. (1997).
1315
+ """
1316
+ a %= n
1317
+ b %= n
1318
+ if order is None:
1319
+ order = n_order(b, n)
1320
+ m = sqrt(order) + 1
1321
+ T = {}
1322
+ x = 1
1323
+ for i in range(m):
1324
+ T[x] = i
1325
+ x = x * b % n
1326
+ z = pow(b, -m, n)
1327
+ x = a
1328
+ for i in range(m):
1329
+ if x in T:
1330
+ return i * m + T[x]
1331
+ x = x * z % n
1332
+ raise ValueError("Log does not exist")
1333
+
1334
+
1335
+ def _discrete_log_pollard_rho(n, a, b, order=None, retries=10, rseed=None):
1336
+ """
1337
+ Pollard's Rho algorithm for computing the discrete logarithm of ``a`` to
1338
+ the base ``b`` modulo ``n``.
1339
+
1340
+ It is a randomized algorithm with the same expected running time as
1341
+ ``_discrete_log_shanks_steps``, but requires a negligible amount of memory.
1342
+
1343
+ Examples
1344
+ ========
1345
+
1346
+ >>> from sympy.ntheory.residue_ntheory import _discrete_log_pollard_rho
1347
+ >>> _discrete_log_pollard_rho(227, 3**7, 3)
1348
+ 7
1349
+
1350
+ See Also
1351
+ ========
1352
+
1353
+ discrete_log
1354
+
1355
+ References
1356
+ ==========
1357
+
1358
+ .. [1] "Handbook of applied cryptography", Menezes, A. J., Van, O. P. C., &
1359
+ Vanstone, S. A. (1997).
1360
+ """
1361
+ a %= n
1362
+ b %= n
1363
+
1364
+ if order is None:
1365
+ order = n_order(b, n)
1366
+ randint = _randint(rseed)
1367
+
1368
+ for i in range(retries):
1369
+ aa = randint(1, order - 1)
1370
+ ba = randint(1, order - 1)
1371
+ xa = pow(b, aa, n) * pow(a, ba, n) % n
1372
+
1373
+ c = xa % 3
1374
+ if c == 0:
1375
+ xb = a * xa % n
1376
+ ab = aa
1377
+ bb = (ba + 1) % order
1378
+ elif c == 1:
1379
+ xb = xa * xa % n
1380
+ ab = (aa + aa) % order
1381
+ bb = (ba + ba) % order
1382
+ else:
1383
+ xb = b * xa % n
1384
+ ab = (aa + 1) % order
1385
+ bb = ba
1386
+
1387
+ for j in range(order):
1388
+ c = xa % 3
1389
+ if c == 0:
1390
+ xa = a * xa % n
1391
+ ba = (ba + 1) % order
1392
+ elif c == 1:
1393
+ xa = xa * xa % n
1394
+ aa = (aa + aa) % order
1395
+ ba = (ba + ba) % order
1396
+ else:
1397
+ xa = b * xa % n
1398
+ aa = (aa + 1) % order
1399
+
1400
+ c = xb % 3
1401
+ if c == 0:
1402
+ xb = a * xb % n
1403
+ bb = (bb + 1) % order
1404
+ elif c == 1:
1405
+ xb = xb * xb % n
1406
+ ab = (ab + ab) % order
1407
+ bb = (bb + bb) % order
1408
+ else:
1409
+ xb = b * xb % n
1410
+ ab = (ab + 1) % order
1411
+
1412
+ c = xb % 3
1413
+ if c == 0:
1414
+ xb = a * xb % n
1415
+ bb = (bb + 1) % order
1416
+ elif c == 1:
1417
+ xb = xb * xb % n
1418
+ ab = (ab + ab) % order
1419
+ bb = (bb + bb) % order
1420
+ else:
1421
+ xb = b * xb % n
1422
+ ab = (ab + 1) % order
1423
+
1424
+ if xa == xb:
1425
+ r = (ba - bb) % order
1426
+ try:
1427
+ e = invert(r, order) * (ab - aa) % order
1428
+ if (pow(b, e, n) - a) % n == 0:
1429
+ return e
1430
+ except ZeroDivisionError:
1431
+ pass
1432
+ break
1433
+ raise ValueError("Pollard's Rho failed to find logarithm")
1434
+
1435
+
1436
+ def _discrete_log_is_smooth(n: int, factorbase: list):
1437
+ """Try to factor n with respect to a given factorbase.
1438
+ Upon success a list of exponents with repect to the factorbase is returned.
1439
+ Otherwise None."""
1440
+ factors = [0]*len(factorbase)
1441
+ for i, p in enumerate(factorbase):
1442
+ while n % p == 0: # divide by p as many times as possible
1443
+ factors[i] += 1
1444
+ n = n // p
1445
+ if n != 1:
1446
+ return None # the number factors if at the end nothing is left
1447
+ return factors
1448
+
1449
+
1450
+ def _discrete_log_index_calculus(n, a, b, order, rseed=None):
1451
+ """
1452
+ Index Calculus algorithm for computing the discrete logarithm of ``a`` to
1453
+ the base ``b`` modulo ``n``.
1454
+
1455
+ The group order must be given and prime. It is not suitable for small orders
1456
+ and the algorithm might fail to find a solution in such situations.
1457
+
1458
+ Examples
1459
+ ========
1460
+
1461
+ >>> from sympy.ntheory.residue_ntheory import _discrete_log_index_calculus
1462
+ >>> _discrete_log_index_calculus(24570203447, 23859756228, 2, 12285101723)
1463
+ 4519867240
1464
+
1465
+ See Also
1466
+ ========
1467
+
1468
+ discrete_log
1469
+
1470
+ References
1471
+ ==========
1472
+
1473
+ .. [1] "Handbook of applied cryptography", Menezes, A. J., Van, O. P. C., &
1474
+ Vanstone, S. A. (1997).
1475
+ """
1476
+ randint = _randint(rseed)
1477
+ from math import sqrt, exp, log
1478
+ a %= n
1479
+ b %= n
1480
+ # assert isprime(order), "The order of the base must be prime."
1481
+ # First choose a heuristic the bound B for the factorbase.
1482
+ # We have added an extra term to the asymptotic value which
1483
+ # is closer to the theoretical optimum for n up to 2^70.
1484
+ B = int(exp(0.5 * sqrt( log(n) * log(log(n)) )*( 1 + 1/log(log(n)) )))
1485
+ max = 5 * B * B # expected number of trys to find a relation
1486
+ factorbase = list(primerange(B)) # compute the factorbase
1487
+ lf = len(factorbase) # length of the factorbase
1488
+ ordermo = order-1
1489
+ abx = a
1490
+ for x in range(order):
1491
+ if abx == 1:
1492
+ return (order - x) % order
1493
+ relationa = _discrete_log_is_smooth(abx, factorbase)
1494
+ if relationa:
1495
+ relationa = [r % order for r in relationa] + [x]
1496
+ break
1497
+ abx = abx * b % n # abx = a*pow(b, x, n) % n
1498
+
1499
+ else:
1500
+ raise ValueError("Index Calculus failed")
1501
+
1502
+ relations = [None] * lf
1503
+ k = 1 # number of relations found
1504
+ kk = 0
1505
+ while k < 3 * lf and kk < max: # find relations for all primes in our factor base
1506
+ x = randint(1,ordermo)
1507
+ relation = _discrete_log_is_smooth(pow(b,x,n), factorbase)
1508
+ if relation is None:
1509
+ kk += 1
1510
+ continue
1511
+ k += 1
1512
+ kk = 0
1513
+ relation += [ x ]
1514
+ index = lf # determine the index of the first nonzero entry
1515
+ for i in range(lf):
1516
+ ri = relation[i] % order
1517
+ if ri> 0 and relations[i] is not None: # make this entry zero if we can
1518
+ for j in range(lf+1):
1519
+ relation[j] = (relation[j] - ri*relations[i][j]) % order
1520
+ else:
1521
+ relation[i] = ri
1522
+ if relation[i] > 0 and index == lf: # is this the index of the first nonzero entry?
1523
+ index = i
1524
+ if index == lf or relations[index] is not None: # the relation contains no new information
1525
+ continue
1526
+ # the relation contains new information
1527
+ rinv = pow(relation[index],-1,order) # normalize the first nonzero entry
1528
+ for j in range(index,lf+1):
1529
+ relation[j] = rinv * relation[j] % order
1530
+ relations[index] = relation
1531
+ for i in range(lf): # subtract the new relation from the one for a
1532
+ if relationa[i] > 0 and relations[i] is not None:
1533
+ rbi = relationa[i]
1534
+ for j in range(lf+1):
1535
+ relationa[j] = (relationa[j] - rbi*relations[i][j]) % order
1536
+ if relationa[i] > 0: # the index of the first nonzero entry
1537
+ break # we do not need to reduce further at this point
1538
+ else: # all unkowns are gone
1539
+ #print(f"Success after {k} relations out of {lf}")
1540
+ x = (order -relationa[lf]) % order
1541
+ if pow(b,x,n) == a:
1542
+ return x
1543
+ raise ValueError("Index Calculus failed")
1544
+ raise ValueError("Index Calculus failed")
1545
+
1546
+
1547
+ def _discrete_log_pohlig_hellman(n, a, b, order=None, order_factors=None):
1548
+ """
1549
+ Pohlig-Hellman algorithm for computing the discrete logarithm of ``a`` to
1550
+ the base ``b`` modulo ``n``.
1551
+
1552
+ In order to compute the discrete logarithm, the algorithm takes advantage
1553
+ of the factorization of the group order. It is more efficient when the
1554
+ group order factors into many small primes.
1555
+
1556
+ Examples
1557
+ ========
1558
+
1559
+ >>> from sympy.ntheory.residue_ntheory import _discrete_log_pohlig_hellman
1560
+ >>> _discrete_log_pohlig_hellman(251, 210, 71)
1561
+ 197
1562
+
1563
+ See Also
1564
+ ========
1565
+
1566
+ discrete_log
1567
+
1568
+ References
1569
+ ==========
1570
+
1571
+ .. [1] "Handbook of applied cryptography", Menezes, A. J., Van, O. P. C., &
1572
+ Vanstone, S. A. (1997).
1573
+ """
1574
+ from .modular import crt
1575
+ a %= n
1576
+ b %= n
1577
+
1578
+ if order is None:
1579
+ order = n_order(b, n)
1580
+ if order_factors is None:
1581
+ order_factors = factorint(order)
1582
+ l = [0] * len(order_factors)
1583
+
1584
+ for i, (pi, ri) in enumerate(order_factors.items()):
1585
+ for j in range(ri):
1586
+ aj = pow(a * pow(b, -l[i], n), order // pi**(j + 1), n)
1587
+ bj = pow(b, order // pi, n)
1588
+ cj = discrete_log(n, aj, bj, pi, True)
1589
+ l[i] += cj * pi**j
1590
+
1591
+ d, _ = crt([pi**ri for pi, ri in order_factors.items()], l)
1592
+ return d
1593
+
1594
+
1595
+ def discrete_log(n, a, b, order=None, prime_order=None):
1596
+ """
1597
+ Compute the discrete logarithm of ``a`` to the base ``b`` modulo ``n``.
1598
+
1599
+ This is a recursive function to reduce the discrete logarithm problem in
1600
+ cyclic groups of composite order to the problem in cyclic groups of prime
1601
+ order.
1602
+
1603
+ It employs different algorithms depending on the problem (subgroup order
1604
+ size, prime order or not):
1605
+
1606
+ * Trial multiplication
1607
+ * Baby-step giant-step
1608
+ * Pollard's Rho
1609
+ * Index Calculus
1610
+ * Pohlig-Hellman
1611
+
1612
+ Examples
1613
+ ========
1614
+
1615
+ >>> from sympy.ntheory import discrete_log
1616
+ >>> discrete_log(41, 15, 7)
1617
+ 3
1618
+
1619
+ References
1620
+ ==========
1621
+
1622
+ .. [1] https://mathworld.wolfram.com/DiscreteLogarithm.html
1623
+ .. [2] "Handbook of applied cryptography", Menezes, A. J., Van, O. P. C., &
1624
+ Vanstone, S. A. (1997).
1625
+
1626
+ """
1627
+ from math import sqrt, log
1628
+ n, a, b = as_int(n), as_int(a), as_int(b)
1629
+ if order is None:
1630
+ # Compute the order and its factoring in one pass
1631
+ # order = totient(n), factors = factorint(order)
1632
+ factors = {}
1633
+ for px, kx in factorint(n).items():
1634
+ if kx > 1:
1635
+ if px in factors:
1636
+ factors[px] += kx - 1
1637
+ else:
1638
+ factors[px] = kx - 1
1639
+ for py, ky in factorint(px - 1).items():
1640
+ if py in factors:
1641
+ factors[py] += ky
1642
+ else:
1643
+ factors[py] = ky
1644
+ order = 1
1645
+ for px, kx in factors.items():
1646
+ order *= px**kx
1647
+ # Now the `order` is the order of the group and factors = factorint(order)
1648
+ # The order of `b` divides the order of the group.
1649
+ order_factors = {}
1650
+ for p, e in factors.items():
1651
+ i = 0
1652
+ for _ in range(e):
1653
+ if pow(b, order // p, n) == 1:
1654
+ order //= p
1655
+ i += 1
1656
+ else:
1657
+ break
1658
+ if i < e:
1659
+ order_factors[p] = e - i
1660
+
1661
+ if prime_order is None:
1662
+ prime_order = isprime(order)
1663
+
1664
+ if order < 1000:
1665
+ return _discrete_log_trial_mul(n, a, b, order)
1666
+ elif prime_order:
1667
+ # Shanks and Pollard rho are O(sqrt(order)) while index calculus is O(exp(2*sqrt(log(n)log(log(n)))))
1668
+ # we compare the expected running times to determine the algorithmus which is expected to be faster
1669
+ if 4*sqrt(log(n)*log(log(n))) < log(order) - 10: # the number 10 was determined experimental
1670
+ return _discrete_log_index_calculus(n, a, b, order)
1671
+ elif order < 1000000000000:
1672
+ # Shanks seems typically faster, but uses O(sqrt(order)) memory
1673
+ return _discrete_log_shanks_steps(n, a, b, order)
1674
+ return _discrete_log_pollard_rho(n, a, b, order)
1675
+
1676
+ return _discrete_log_pohlig_hellman(n, a, b, order, order_factors)
1677
+
1678
+
1679
+
1680
+ def quadratic_congruence(a, b, c, n):
1681
+ r"""
1682
+ Find the solutions to `a x^2 + b x + c \equiv 0 \pmod{n}`.
1683
+
1684
+ Parameters
1685
+ ==========
1686
+
1687
+ a : int
1688
+ b : int
1689
+ c : int
1690
+ n : int
1691
+ A positive integer.
1692
+
1693
+ Returns
1694
+ =======
1695
+
1696
+ list[int] :
1697
+ A sorted list of solutions. If no solution exists, ``[]``.
1698
+
1699
+ Examples
1700
+ ========
1701
+
1702
+ >>> from sympy.ntheory.residue_ntheory import quadratic_congruence
1703
+ >>> quadratic_congruence(2, 5, 3, 7) # 2x^2 + 5x + 3 = 0 (mod 7)
1704
+ [2, 6]
1705
+ >>> quadratic_congruence(8, 6, 4, 15) # No solution
1706
+ []
1707
+
1708
+ See Also
1709
+ ========
1710
+
1711
+ polynomial_congruence : Solve the polynomial congruence
1712
+
1713
+ """
1714
+ a = as_int(a)
1715
+ b = as_int(b)
1716
+ c = as_int(c)
1717
+ n = as_int(n)
1718
+ if n <= 1:
1719
+ raise ValueError("n should be an integer greater than 1")
1720
+ a %= n
1721
+ b %= n
1722
+ c %= n
1723
+
1724
+ if a == 0:
1725
+ return linear_congruence(b, -c, n)
1726
+ if n == 2:
1727
+ # assert a == 1
1728
+ roots = []
1729
+ if c == 0:
1730
+ roots.append(0)
1731
+ if (b + c) % 2:
1732
+ roots.append(1)
1733
+ return roots
1734
+ if gcd(2*a, n) == 1:
1735
+ inv_a = invert(a, n)
1736
+ b *= inv_a
1737
+ c *= inv_a
1738
+ if b % 2:
1739
+ b += n
1740
+ b >>= 1
1741
+ return sorted((i - b) % n for i in sqrt_mod_iter(b**2 - c, n))
1742
+ res = set()
1743
+ for i in sqrt_mod_iter(b**2 - 4*a*c, 4*a*n):
1744
+ res.update(j % n for j in linear_congruence(2*a, i - b, 4*a*n))
1745
+ return sorted(res)
1746
+
1747
+
1748
+ def _valid_expr(expr):
1749
+ """
1750
+ return coefficients of expr if it is a univariate polynomial
1751
+ with integer coefficients else raise a ValueError.
1752
+ """
1753
+
1754
+ if not expr.is_polynomial():
1755
+ raise ValueError("The expression should be a polynomial")
1756
+ polynomial = Poly(expr)
1757
+ if not polynomial.is_univariate:
1758
+ raise ValueError("The expression should be univariate")
1759
+ if not polynomial.domain == ZZ:
1760
+ raise ValueError("The expression should should have integer coefficients")
1761
+ return polynomial.all_coeffs()
1762
+
1763
+
1764
+ def polynomial_congruence(expr, m):
1765
+ """
1766
+ Find the solutions to a polynomial congruence equation modulo m.
1767
+
1768
+ Parameters
1769
+ ==========
1770
+
1771
+ expr : integer coefficient polynomial
1772
+ m : positive integer
1773
+
1774
+ Examples
1775
+ ========
1776
+
1777
+ >>> from sympy.ntheory import polynomial_congruence
1778
+ >>> from sympy.abc import x
1779
+ >>> expr = x**6 - 2*x**5 -35
1780
+ >>> polynomial_congruence(expr, 6125)
1781
+ [3257]
1782
+
1783
+ See Also
1784
+ ========
1785
+
1786
+ sympy.polys.galoistools.gf_csolve : low level solving routine used by this routine
1787
+
1788
+ """
1789
+ coefficients = _valid_expr(expr)
1790
+ coefficients = [num % m for num in coefficients]
1791
+ rank = len(coefficients)
1792
+ if rank == 3:
1793
+ return quadratic_congruence(*coefficients, m)
1794
+ if rank == 2:
1795
+ return quadratic_congruence(0, *coefficients, m)
1796
+ if coefficients[0] == 1 and 1 + coefficients[-1] == sum(coefficients):
1797
+ return nthroot_mod(-coefficients[-1], rank - 1, m, True)
1798
+ return gf_csolve(coefficients, m)
1799
+
1800
+
1801
+ def binomial_mod(n, m, k):
1802
+ """Compute ``binomial(n, m) % k``.
1803
+
1804
+ Explanation
1805
+ ===========
1806
+
1807
+ Returns ``binomial(n, m) % k`` using a generalization of Lucas'
1808
+ Theorem for prime powers given by Granville [1]_, in conjunction with
1809
+ the Chinese Remainder Theorem. The residue for each prime power
1810
+ is calculated in time O(log^2(n) + q^4*log(n)log(p) + q^4*p*log^3(p)).
1811
+
1812
+ Parameters
1813
+ ==========
1814
+
1815
+ n : an integer
1816
+ m : an integer
1817
+ k : a positive integer
1818
+
1819
+ Examples
1820
+ ========
1821
+
1822
+ >>> from sympy.ntheory.residue_ntheory import binomial_mod
1823
+ >>> binomial_mod(10, 2, 6) # binomial(10, 2) = 45
1824
+ 3
1825
+ >>> binomial_mod(17, 9, 10) # binomial(17, 9) = 24310
1826
+ 0
1827
+
1828
+ References
1829
+ ==========
1830
+
1831
+ .. [1] Binomial coefficients modulo prime powers, Andrew Granville,
1832
+ Available: https://web.archive.org/web/20170202003812/http://www.dms.umontreal.ca/~andrew/PDF/BinCoeff.pdf
1833
+ """
1834
+ if k < 1: raise ValueError('k is required to be positive')
1835
+ # We decompose q into a product of prime powers and apply
1836
+ # the generalization of Lucas' Theorem given by Granville
1837
+ # to obtain binomial(n, k) mod p^e, and then use the Chinese
1838
+ # Remainder Theorem to obtain the result mod q
1839
+ if n < 0 or m < 0 or m > n: return 0
1840
+ factorisation = factorint(k)
1841
+ residues = [_binomial_mod_prime_power(n, m, p, e) for p, e in factorisation.items()]
1842
+ return crt([p**pw for p, pw in factorisation.items()], residues, check=False)[0]
1843
+
1844
+
1845
+ def _binomial_mod_prime_power(n, m, p, q):
1846
+ """Compute ``binomial(n, m) % p**q`` for a prime ``p``.
1847
+
1848
+ Parameters
1849
+ ==========
1850
+
1851
+ n : positive integer
1852
+ m : a nonnegative integer
1853
+ p : a prime
1854
+ q : a positive integer (the prime exponent)
1855
+
1856
+ Examples
1857
+ ========
1858
+
1859
+ >>> from sympy.ntheory.residue_ntheory import _binomial_mod_prime_power
1860
+ >>> _binomial_mod_prime_power(10, 2, 3, 2) # binomial(10, 2) = 45
1861
+ 0
1862
+ >>> _binomial_mod_prime_power(17, 9, 2, 4) # binomial(17, 9) = 24310
1863
+ 6
1864
+
1865
+ References
1866
+ ==========
1867
+
1868
+ .. [1] Binomial coefficients modulo prime powers, Andrew Granville,
1869
+ Available: https://web.archive.org/web/20170202003812/http://www.dms.umontreal.ca/~andrew/PDF/BinCoeff.pdf
1870
+ """
1871
+ # Function/variable naming within this function follows Ref.[1]
1872
+ # n!_p will be used to denote the product of integers <= n not divisible by
1873
+ # p, with binomial(n, m)_p the same as binomial(n, m), but defined using
1874
+ # n!_p in place of n!
1875
+ modulo = pow(p, q)
1876
+
1877
+ def up_factorial(u):
1878
+ """Compute (u*p)!_p modulo p^q."""
1879
+ r = q // 2
1880
+ fac = prod = 1
1881
+ if r == 1 and p == 2 or 2*r + 1 in (p, p*p):
1882
+ if q % 2 == 1: r += 1
1883
+ modulo, div = pow(p, 2*r), pow(p, 2*r - q)
1884
+ else:
1885
+ modulo, div = pow(p, 2*r + 1), pow(p, (2*r + 1) - q)
1886
+ for j in range(1, r + 1):
1887
+ for mul in range((j - 1)*p + 1, j*p): # ignore jp itself
1888
+ fac *= mul
1889
+ fac %= modulo
1890
+ bj_ = bj(u, j, r)
1891
+ prod *= pow(fac, bj_, modulo)
1892
+ prod %= modulo
1893
+ if p == 2:
1894
+ sm = u // 2
1895
+ for j in range(1, r + 1): sm += j//2 * bj(u, j, r)
1896
+ if sm % 2 == 1: prod *= -1
1897
+ prod %= modulo//div
1898
+ return prod % modulo
1899
+
1900
+ def bj(u, j, r):
1901
+ """Compute the exponent of (j*p)!_p in the calculation of (u*p)!_p."""
1902
+ prod = u
1903
+ for i in range(1, r + 1):
1904
+ if i != j: prod *= u*u - i*i
1905
+ for i in range(1, r + 1):
1906
+ if i != j: prod //= j*j - i*i
1907
+ return prod // j
1908
+
1909
+ def up_plus_v_binom(u, v):
1910
+ """Compute binomial(u*p + v, v)_p modulo p^q."""
1911
+ prod = 1
1912
+ div = invert(factorial(v), modulo)
1913
+ for j in range(1, q):
1914
+ b = div
1915
+ for v_ in range(j*p + 1, j*p + v + 1):
1916
+ b *= v_
1917
+ b %= modulo
1918
+ aj = u
1919
+ for i in range(1, q):
1920
+ if i != j: aj *= u - i
1921
+ for i in range(1, q):
1922
+ if i != j: aj //= j - i
1923
+ aj //= j
1924
+ prod *= pow(b, aj, modulo)
1925
+ prod %= modulo
1926
+ return prod
1927
+
1928
+ @recurrence_memo([1])
1929
+ def factorial(v, prev):
1930
+ """Compute v! modulo p^q."""
1931
+ return v*prev[-1] % modulo
1932
+
1933
+ def factorial_p(n):
1934
+ """Compute n!_p modulo p^q."""
1935
+ u, v = divmod(n, p)
1936
+ return (factorial(v) * up_factorial(u) * up_plus_v_binom(u, v)) % modulo
1937
+
1938
+ prod = 1
1939
+ Nj, Mj, Rj = n, m, n - m
1940
+ # e0 will be the p-adic valuation of binomial(n, m) at p
1941
+ e0 = carry = eq_1 = j = 0
1942
+ while Nj:
1943
+ numerator = factorial_p(Nj % modulo)
1944
+ denominator = factorial_p(Mj % modulo) * factorial_p(Rj % modulo) % modulo
1945
+ Nj, (Mj, mj), (Rj, rj) = Nj//p, divmod(Mj, p), divmod(Rj, p)
1946
+ carry = (mj + rj + carry) // p
1947
+ e0 += carry
1948
+ if j >= q - 1: eq_1 += carry
1949
+ prod *= numerator * invert(denominator, modulo)
1950
+ prod %= modulo
1951
+ j += 1
1952
+
1953
+ mul = pow(1 if p == 2 and q >= 3 else -1, eq_1, modulo)
1954
+ return (pow(p, e0, modulo) * mul * prod) % modulo
lib/python3.12/site-packages/sympy/ntheory/tests/__init__.py ADDED
File without changes
lib/python3.12/site-packages/sympy/ntheory/tests/test_bbp_pi.py ADDED
@@ -0,0 +1,134 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from sympy.core.random import randint
2
+
3
+ from sympy.ntheory.bbp_pi import pi_hex_digits
4
+ from sympy.testing.pytest import raises
5
+
6
+
7
+ # http://www.herongyang.com/Cryptography/Blowfish-First-8366-Hex-Digits-of-PI.html
8
+ # There are actually 8336 listed there; with the prepended 3 there are 8337
9
+ # below
10
+ dig=''.join('''
11
+ 3243f6a8885a308d313198a2e03707344a4093822299f31d0082efa98ec4e6c89452821e638d013
12
+ 77be5466cf34e90c6cc0ac29b7c97c50dd3f84d5b5b54709179216d5d98979fb1bd1310ba698dfb5
13
+ ac2ffd72dbd01adfb7b8e1afed6a267e96ba7c9045f12c7f9924a19947b3916cf70801f2e2858efc
14
+ 16636920d871574e69a458fea3f4933d7e0d95748f728eb658718bcd5882154aee7b54a41dc25a59
15
+ b59c30d5392af26013c5d1b023286085f0ca417918b8db38ef8e79dcb0603a180e6c9e0e8bb01e8a
16
+ 3ed71577c1bd314b2778af2fda55605c60e65525f3aa55ab945748986263e8144055ca396a2aab10
17
+ b6b4cc5c341141e8cea15486af7c72e993b3ee1411636fbc2a2ba9c55d741831f6ce5c3e169b8793
18
+ 1eafd6ba336c24cf5c7a325381289586773b8f48986b4bb9afc4bfe81b6628219361d809ccfb21a9
19
+ 91487cac605dec8032ef845d5de98575b1dc262302eb651b8823893e81d396acc50f6d6ff383f442
20
+ 392e0b4482a484200469c8f04a9e1f9b5e21c66842f6e96c9a670c9c61abd388f06a51a0d2d8542f
21
+ 68960fa728ab5133a36eef0b6c137a3be4ba3bf0507efb2a98a1f1651d39af017666ca593e82430e
22
+ 888cee8619456f9fb47d84a5c33b8b5ebee06f75d885c12073401a449f56c16aa64ed3aa62363f77
23
+ 061bfedf72429b023d37d0d724d00a1248db0fead349f1c09b075372c980991b7b25d479d8f6e8de
24
+ f7e3fe501ab6794c3b976ce0bd04c006bac1a94fb6409f60c45e5c9ec2196a246368fb6faf3e6c53
25
+ b51339b2eb3b52ec6f6dfc511f9b30952ccc814544af5ebd09bee3d004de334afd660f2807192e4b
26
+ b3c0cba85745c8740fd20b5f39b9d3fbdb5579c0bd1a60320ad6a100c6402c7279679f25fefb1fa3
27
+ cc8ea5e9f8db3222f83c7516dffd616b152f501ec8ad0552ab323db5fafd23876053317b483e00df
28
+ 829e5c57bbca6f8ca01a87562edf1769dbd542a8f6287effc3ac6732c68c4f5573695b27b0bbca58
29
+ c8e1ffa35db8f011a010fa3d98fd2183b84afcb56c2dd1d35b9a53e479b6f84565d28e49bc4bfb97
30
+ 90e1ddf2daa4cb7e3362fb1341cee4c6e8ef20cada36774c01d07e9efe2bf11fb495dbda4dae9091
31
+ 98eaad8e716b93d5a0d08ed1d0afc725e08e3c5b2f8e7594b78ff6e2fbf2122b648888b812900df0
32
+ 1c4fad5ea0688fc31cd1cff191b3a8c1ad2f2f2218be0e1777ea752dfe8b021fa1e5a0cc0fb56f74
33
+ e818acf3d6ce89e299b4a84fe0fd13e0b77cc43b81d2ada8d9165fa2668095770593cc7314211a14
34
+ 77e6ad206577b5fa86c75442f5fb9d35cfebcdaf0c7b3e89a0d6411bd3ae1e7e4900250e2d2071b3
35
+ 5e226800bb57b8e0af2464369bf009b91e5563911d59dfa6aa78c14389d95a537f207d5ba202e5b9
36
+ c5832603766295cfa911c819684e734a41b3472dca7b14a94a1b5100529a532915d60f573fbc9bc6
37
+ e42b60a47681e6740008ba6fb5571be91ff296ec6b2a0dd915b6636521e7b9f9b6ff34052ec58556
38
+ 6453b02d5da99f8fa108ba47996e85076a4b7a70e9b5b32944db75092ec4192623ad6ea6b049a7df
39
+ 7d9cee60b88fedb266ecaa8c71699a17ff5664526cc2b19ee1193602a575094c29a0591340e4183a
40
+ 3e3f54989a5b429d656b8fe4d699f73fd6a1d29c07efe830f54d2d38e6f0255dc14cdd20868470eb
41
+ 266382e9c6021ecc5e09686b3f3ebaefc93c9718146b6a70a1687f358452a0e286b79c5305aa5007
42
+ 373e07841c7fdeae5c8e7d44ec5716f2b8b03ada37f0500c0df01c1f040200b3ffae0cf51a3cb574
43
+ b225837a58dc0921bdd19113f97ca92ff69432477322f547013ae5e58137c2dadcc8b576349af3dd
44
+ a7a94461460fd0030eecc8c73ea4751e41e238cd993bea0e2f3280bba1183eb3314e548b384f6db9
45
+ 086f420d03f60a04bf2cb8129024977c795679b072bcaf89afde9a771fd9930810b38bae12dccf3f
46
+ 2e5512721f2e6b7124501adde69f84cd877a5847187408da17bc9f9abce94b7d8cec7aec3adb851d
47
+ fa63094366c464c3d2ef1c18473215d908dd433b3724c2ba1612a14d432a65c45150940002133ae4
48
+ dd71dff89e10314e5581ac77d65f11199b043556f1d7a3c76b3c11183b5924a509f28fe6ed97f1fb
49
+ fa9ebabf2c1e153c6e86e34570eae96fb1860e5e0a5a3e2ab3771fe71c4e3d06fa2965dcb999e71d
50
+ 0f803e89d65266c8252e4cc9789c10b36ac6150eba94e2ea78a5fc3c531e0a2df4f2f74ea7361d2b
51
+ 3d1939260f19c279605223a708f71312b6ebadfe6eeac31f66e3bc4595a67bc883b17f37d1018cff
52
+ 28c332ddefbe6c5aa56558218568ab9802eecea50fdb2f953b2aef7dad5b6e2f841521b628290761
53
+ 70ecdd4775619f151013cca830eb61bd960334fe1eaa0363cfb5735c904c70a239d59e9e0bcbaade
54
+ 14eecc86bc60622ca79cab5cabb2f3846e648b1eaf19bdf0caa02369b9655abb5040685a323c2ab4
55
+ b3319ee9d5c021b8f79b540b19875fa09995f7997e623d7da8f837889a97e32d7711ed935f166812
56
+ 810e358829c7e61fd696dedfa17858ba9957f584a51b2272639b83c3ff1ac24696cdb30aeb532e30
57
+ 548fd948e46dbc312858ebf2ef34c6ffeafe28ed61ee7c3c735d4a14d9e864b7e342105d14203e13
58
+ e045eee2b6a3aaabeadb6c4f15facb4fd0c742f442ef6abbb5654f3b1d41cd2105d81e799e86854d
59
+ c7e44b476a3d816250cf62a1f25b8d2646fc8883a0c1c7b6a37f1524c369cb749247848a0b5692b2
60
+ 85095bbf00ad19489d1462b17423820e0058428d2a0c55f5ea1dadf43e233f70613372f0928d937e
61
+ 41d65fecf16c223bdb7cde3759cbee74604085f2a7ce77326ea607808419f8509ee8efd85561d997
62
+ 35a969a7aac50c06c25a04abfc800bcadc9e447a2ec3453484fdd567050e1e9ec9db73dbd3105588
63
+ cd675fda79e3674340c5c43465713e38d83d28f89ef16dff20153e21e78fb03d4ae6e39f2bdb83ad
64
+ f7e93d5a68948140f7f64c261c94692934411520f77602d4f7bcf46b2ed4a20068d40824713320f4
65
+ 6a43b7d4b7500061af1e39f62e9724454614214f74bf8b88404d95fc1d96b591af70f4ddd366a02f
66
+ 45bfbc09ec03bd97857fac6dd031cb850496eb27b355fd3941da2547e6abca0a9a28507825530429
67
+ f40a2c86dae9b66dfb68dc1462d7486900680ec0a427a18dee4f3ffea2e887ad8cb58ce0067af4d6
68
+ b6aace1e7cd3375fecce78a399406b2a4220fe9e35d9f385b9ee39d7ab3b124e8b1dc9faf74b6d18
69
+ 5626a36631eae397b23a6efa74dd5b43326841e7f7ca7820fbfb0af54ed8feb397454056acba4895
70
+ 2755533a3a20838d87fe6ba9b7d096954b55a867bca1159a58cca9296399e1db33a62a4a563f3125
71
+ f95ef47e1c9029317cfdf8e80204272f7080bb155c05282ce395c11548e4c66d2248c1133fc70f86
72
+ dc07f9c9ee41041f0f404779a45d886e17325f51ebd59bc0d1f2bcc18f41113564257b7834602a9c
73
+ 60dff8e8a31f636c1b0e12b4c202e1329eaf664fd1cad181156b2395e0333e92e13b240b62eebeb9
74
+ 2285b2a20ee6ba0d99de720c8c2da2f728d012784595b794fd647d0862e7ccf5f05449a36f877d48
75
+ fac39dfd27f33e8d1e0a476341992eff743a6f6eabf4f8fd37a812dc60a1ebddf8991be14cdb6e6b
76
+ 0dc67b55106d672c372765d43bdcd0e804f1290dc7cc00ffa3b5390f92690fed0b667b9ffbcedb7d
77
+ 9ca091cf0bd9155ea3bb132f88515bad247b9479bf763bd6eb37392eb3cc1159798026e297f42e31
78
+ 2d6842ada7c66a2b3b12754ccc782ef11c6a124237b79251e706a1bbe64bfb63501a6b101811caed
79
+ fa3d25bdd8e2e1c3c9444216590a121386d90cec6ed5abea2a64af674eda86a85fbebfe98864e4c3
80
+ fe9dbc8057f0f7c08660787bf86003604dd1fd8346f6381fb07745ae04d736fccc83426b33f01eab
81
+ 71b08041873c005e5f77a057bebde8ae2455464299bf582e614e58f48ff2ddfda2f474ef388789bd
82
+ c25366f9c3c8b38e74b475f25546fcd9b97aeb26618b1ddf84846a0e79915f95e2466e598e20b457
83
+ 708cd55591c902de4cb90bace1bb8205d011a862487574a99eb77f19b6e0a9dc09662d09a1c43246
84
+ 33e85a1f0209f0be8c4a99a0251d6efe101ab93d1d0ba5a4dfa186f20f2868f169dcb7da83573906
85
+ fea1e2ce9b4fcd7f5250115e01a70683faa002b5c40de6d0279af88c27773f8641c3604c0661a806
86
+ b5f0177a28c0f586e0006058aa30dc7d6211e69ed72338ea6353c2dd94c2c21634bbcbee5690bcb6
87
+ deebfc7da1ce591d766f05e4094b7c018839720a3d7c927c2486e3725f724d9db91ac15bb4d39eb8
88
+ fced54557808fca5b5d83d7cd34dad0fc41e50ef5eb161e6f8a28514d96c51133c6fd5c7e756e14e
89
+ c4362abfceddc6c837d79a323492638212670efa8e406000e03a39ce37d3faf5cfabc277375ac52d
90
+ 1b5cb0679e4fa33742d382274099bc9bbed5118e9dbf0f7315d62d1c7ec700c47bb78c1b6b21a190
91
+ 45b26eb1be6a366eb45748ab2fbc946e79c6a376d26549c2c8530ff8ee468dde7dd5730a1d4cd04d
92
+ c62939bbdba9ba4650ac9526e8be5ee304a1fad5f06a2d519a63ef8ce29a86ee22c089c2b843242e
93
+ f6a51e03aa9cf2d0a483c061ba9be96a4d8fe51550ba645bd62826a2f9a73a3ae14ba99586ef5562
94
+ e9c72fefd3f752f7da3f046f6977fa0a5980e4a91587b086019b09e6ad3b3ee593e990fd5a9e34d7
95
+ 972cf0b7d9022b8b5196d5ac3a017da67dd1cf3ed67c7d2d281f9f25cfadf2b89b5ad6b4725a88f5
96
+ 4ce029ac71e019a5e647b0acfded93fa9be8d3c48d283b57ccf8d5662979132e28785f0191ed7560
97
+ 55f7960e44e3d35e8c15056dd488f46dba03a161250564f0bdc3eb9e153c9057a297271aeca93a07
98
+ 2a1b3f6d9b1e6321f5f59c66fb26dcf3197533d928b155fdf5035634828aba3cbb28517711c20ad9
99
+ f8abcc5167ccad925f4de817513830dc8e379d58629320f991ea7a90c2fb3e7bce5121ce64774fbe
100
+ 32a8b6e37ec3293d4648de53696413e680a2ae0810dd6db22469852dfd09072166b39a460a6445c0
101
+ dd586cdecf1c20c8ae5bbef7dd1b588d40ccd2017f6bb4e3bbdda26a7e3a59ff453e350a44bcb4cd
102
+ d572eacea8fa6484bb8d6612aebf3c6f47d29be463542f5d9eaec2771bf64e6370740e0d8de75b13
103
+ 57f8721671af537d5d4040cb084eb4e2cc34d2466a0115af84e1b0042895983a1d06b89fb4ce6ea0
104
+ 486f3f3b823520ab82011a1d4b277227f8611560b1e7933fdcbb3a792b344525bda08839e151ce79
105
+ 4b2f32c9b7a01fbac9e01cc87ebcc7d1f6cf0111c3a1e8aac71a908749d44fbd9ad0dadecbd50ada
106
+ 380339c32ac69136678df9317ce0b12b4ff79e59b743f5bb3af2d519ff27d9459cbf97222c15e6fc
107
+ 2a0f91fc719b941525fae59361ceb69cebc2a8645912baa8d1b6c1075ee3056a0c10d25065cb03a4
108
+ 42e0ec6e0e1698db3b4c98a0be3278e9649f1f9532e0d392dfd3a0342b8971f21e1b0a74414ba334
109
+ 8cc5be7120c37632d8df359f8d9b992f2ee60b6f470fe3f11de54cda541edad891ce6279cfcd3e7e
110
+ 6f1618b166fd2c1d05848fd2c5f6fb2299f523f357a632762393a8353156cccd02acf081625a75eb
111
+ b56e16369788d273ccde96629281b949d04c50901b71c65614e6c6c7bd327a140a45e1d006c3f27b
112
+ 9ac9aa53fd62a80f00bb25bfe235bdd2f671126905b2040222b6cbcf7ccd769c2b53113ec01640e3
113
+ d338abbd602547adf0ba38209cf746ce7677afa1c52075606085cbfe4e8ae88dd87aaaf9b04cf9aa
114
+ 7e1948c25c02fb8a8c01c36ae4d6ebe1f990d4f869a65cdea03f09252dc208e69fb74e6132ce77e2
115
+ 5b578fdfe33ac372e6'''.split())
116
+
117
+
118
+ def test_hex_pi_nth_digits():
119
+ assert pi_hex_digits(0) == '3243f6a8885a30'
120
+ assert pi_hex_digits(1) == '243f6a8885a308'
121
+ assert pi_hex_digits(10000) == '68ac8fcfb8016c'
122
+ assert pi_hex_digits(13) == '08d313198a2e03'
123
+ assert pi_hex_digits(0, 3) == '324'
124
+ assert pi_hex_digits(0, 0) == ''
125
+ raises(ValueError, lambda: pi_hex_digits(-1))
126
+ raises(ValueError, lambda: pi_hex_digits(0, -1))
127
+ raises(ValueError, lambda: pi_hex_digits(3.14))
128
+
129
+ # this will pick a random segment to compute every time
130
+ # it is run. If it ever fails, there is an error in the
131
+ # computation.
132
+ n = randint(0, len(dig))
133
+ prec = randint(0, len(dig) - n)
134
+ assert pi_hex_digits(n, prec) == dig[n: n + prec]
lib/python3.12/site-packages/sympy/ntheory/tests/test_continued_fraction.py ADDED
@@ -0,0 +1,77 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import itertools
2
+ from sympy.core import GoldenRatio as phi
3
+ from sympy.core.numbers import (Rational, pi)
4
+ from sympy.core.singleton import S
5
+ from sympy.functions.elementary.miscellaneous import sqrt
6
+ from sympy.ntheory.continued_fraction import \
7
+ (continued_fraction_periodic as cf_p,
8
+ continued_fraction_iterator as cf_i,
9
+ continued_fraction_convergents as cf_c,
10
+ continued_fraction_reduce as cf_r,
11
+ continued_fraction as cf)
12
+ from sympy.testing.pytest import raises
13
+
14
+
15
+ def test_continued_fraction():
16
+ assert cf_p(1, 1, 10, 0) == cf_p(1, 1, 0, 1)
17
+ assert cf_p(1, -1, 10, 1) == cf_p(-1, 1, 10, -1)
18
+ t = sqrt(2)
19
+ assert cf((1 + t)*(1 - t)) == cf(-1)
20
+ for n in [0, 2, Rational(2, 3), sqrt(2), 3*sqrt(2), 1 + 2*sqrt(3)/5,
21
+ (2 - 3*sqrt(5))/7, 1 + sqrt(2), (-5 + sqrt(17))/4]:
22
+ assert (cf_r(cf(n)) - n).expand() == 0
23
+ assert (cf_r(cf(-n)) + n).expand() == 0
24
+ raises(ValueError, lambda: cf(sqrt(2 + sqrt(3))))
25
+ raises(ValueError, lambda: cf(sqrt(2) + sqrt(3)))
26
+ raises(ValueError, lambda: cf(pi))
27
+ raises(ValueError, lambda: cf(.1))
28
+
29
+ raises(ValueError, lambda: cf_p(1, 0, 0))
30
+ raises(ValueError, lambda: cf_p(1, 1, -1))
31
+ assert cf_p(4, 3, 0) == [1, 3]
32
+ assert cf_p(0, 3, 5) == [0, 1, [2, 1, 12, 1, 2, 2]]
33
+ assert cf_p(1, 1, 0) == [1]
34
+ assert cf_p(3, 4, 0) == [0, 1, 3]
35
+ assert cf_p(4, 5, 0) == [0, 1, 4]
36
+ assert cf_p(5, 6, 0) == [0, 1, 5]
37
+ assert cf_p(11, 13, 0) == [0, 1, 5, 2]
38
+ assert cf_p(16, 19, 0) == [0, 1, 5, 3]
39
+ assert cf_p(27, 32, 0) == [0, 1, 5, 2, 2]
40
+ assert cf_p(1, 2, 5) == [[1]]
41
+ assert cf_p(0, 1, 2) == [1, [2]]
42
+ assert cf_p(6, 7, 49) == [1, 1, 6]
43
+ assert cf_p(3796, 1387, 0) == [2, 1, 2, 1, 4]
44
+ assert cf_p(3245, 10000) == [0, 3, 12, 4, 13]
45
+ assert cf_p(1932, 2568) == [0, 1, 3, 26, 2]
46
+ assert cf_p(6589, 2569) == [2, 1, 1, 3, 2, 1, 3, 1, 23]
47
+
48
+ def take(iterator, n=7):
49
+ return list(itertools.islice(iterator, n))
50
+
51
+ assert take(cf_i(phi)) == [1, 1, 1, 1, 1, 1, 1]
52
+ assert take(cf_i(pi)) == [3, 7, 15, 1, 292, 1, 1]
53
+
54
+ assert list(cf_i(Rational(17, 12))) == [1, 2, 2, 2]
55
+ assert list(cf_i(Rational(-17, 12))) == [-2, 1, 1, 2, 2]
56
+
57
+ assert list(cf_c([1, 6, 1, 8])) == [S.One, Rational(7, 6), Rational(8, 7), Rational(71, 62)]
58
+ assert list(cf_c([2])) == [S(2)]
59
+ assert list(cf_c([1, 1, 1, 1, 1, 1, 1])) == [S.One, S(2), Rational(3, 2), Rational(5, 3),
60
+ Rational(8, 5), Rational(13, 8), Rational(21, 13)]
61
+ assert list(cf_c([1, 6, Rational(-1, 2), 4])) == [S.One, Rational(7, 6), Rational(5, 4), Rational(3, 2)]
62
+ assert take(cf_c([[1]])) == [S.One, S(2), Rational(3, 2), Rational(5, 3), Rational(8, 5),
63
+ Rational(13, 8), Rational(21, 13)]
64
+ assert take(cf_c([1, [1, 2]])) == [S.One, S(2), Rational(5, 3), Rational(7, 4), Rational(19, 11),
65
+ Rational(26, 15), Rational(71, 41)]
66
+
67
+ cf_iter_e = (2 if i == 1 else i // 3 * 2 if i % 3 == 0 else 1 for i in itertools.count(1))
68
+ assert take(cf_c(cf_iter_e)) == [S(2), S(3), Rational(8, 3), Rational(11, 4), Rational(19, 7),
69
+ Rational(87, 32), Rational(106, 39)]
70
+
71
+ assert cf_r([1, 6, 1, 8]) == Rational(71, 62)
72
+ assert cf_r([3]) == S(3)
73
+ assert cf_r([-1, 5, 1, 4]) == Rational(-24, 29)
74
+ assert (cf_r([0, 1, 1, 7, [24, 8]]) - (sqrt(3) + 2)/7).expand() == 0
75
+ assert cf_r([1, 5, 9]) == Rational(55, 46)
76
+ assert (cf_r([[1]]) - (sqrt(5) + 1)/2).expand() == 0
77
+ assert cf_r([-3, 1, 1, [2]]) == -1 - sqrt(2)
lib/python3.12/site-packages/sympy/ntheory/tests/test_digits.py ADDED
@@ -0,0 +1,55 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from sympy.ntheory import count_digits, digits, is_palindromic
2
+ from sympy.core.intfunc import num_digits
3
+
4
+ from sympy.testing.pytest import raises
5
+
6
+
7
+ def test_num_digits():
8
+ # depending on whether one rounds up or down or uses log or log10,
9
+ # one or more of these will fail if you don't check for the off-by
10
+ # one condition
11
+ assert num_digits(2, 2) == 2
12
+ assert num_digits(2**48 - 1, 2) == 48
13
+ assert num_digits(1000, 10) == 4
14
+ assert num_digits(125, 5) == 4
15
+ assert num_digits(100, 16) == 2
16
+ assert num_digits(-1000, 10) == 4
17
+ # if changes are made to the function, this structured test over
18
+ # this range will expose problems
19
+ for base in range(2, 100):
20
+ for e in range(1, 100):
21
+ n = base**e
22
+ assert num_digits(n, base) == e + 1
23
+ assert num_digits(n + 1, base) == e + 1
24
+ assert num_digits(n - 1, base) == e
25
+
26
+
27
+ def test_digits():
28
+ assert all(digits(n, 2)[1:] == [int(d) for d in format(n, 'b')]
29
+ for n in range(20))
30
+ assert all(digits(n, 8)[1:] == [int(d) for d in format(n, 'o')]
31
+ for n in range(20))
32
+ assert all(digits(n, 16)[1:] == [int(d, 16) for d in format(n, 'x')]
33
+ for n in range(20))
34
+ assert digits(2345, 34) == [34, 2, 0, 33]
35
+ assert digits(384753, 71) == [71, 1, 5, 23, 4]
36
+ assert digits(93409, 10) == [10, 9, 3, 4, 0, 9]
37
+ assert digits(-92838, 11) == [-11, 6, 3, 8, 2, 9]
38
+ assert digits(35, 10) == [10, 3, 5]
39
+ assert digits(35, 10, 3) == [10, 0, 3, 5]
40
+ assert digits(-35, 10, 4) == [-10, 0, 0, 3, 5]
41
+ raises(ValueError, lambda: digits(2, 2, 1))
42
+
43
+
44
+ def test_count_digits():
45
+ assert count_digits(55, 2) == {1: 5, 0: 1}
46
+ assert count_digits(55, 10) == {5: 2}
47
+ n = count_digits(123)
48
+ assert n[4] == 0 and type(n[4]) is int
49
+
50
+
51
+ def test_is_palindromic():
52
+ assert is_palindromic(-11)
53
+ assert is_palindromic(11)
54
+ assert is_palindromic(0o121, 8)
55
+ assert not is_palindromic(123)
lib/python3.12/site-packages/sympy/ntheory/tests/test_egyptian_fraction.py ADDED
@@ -0,0 +1,49 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from sympy.core.numbers import Rational
2
+ from sympy.ntheory.egyptian_fraction import egyptian_fraction
3
+ from sympy.core.add import Add
4
+ from sympy.testing.pytest import raises
5
+ from sympy.core.random import random_complex_number
6
+
7
+
8
+ def test_egyptian_fraction():
9
+ def test_equality(r, alg="Greedy"):
10
+ return r == Add(*[Rational(1, i) for i in egyptian_fraction(r, alg)])
11
+
12
+ r = random_complex_number(a=0, c=1, b=0, d=0, rational=True)
13
+ assert test_equality(r)
14
+
15
+ assert egyptian_fraction(Rational(4, 17)) == [5, 29, 1233, 3039345]
16
+ assert egyptian_fraction(Rational(7, 13), "Greedy") == [2, 26]
17
+ assert egyptian_fraction(Rational(23, 101), "Greedy") == \
18
+ [5, 37, 1438, 2985448, 40108045937720]
19
+ assert egyptian_fraction(Rational(18, 23), "Takenouchi") == \
20
+ [2, 6, 12, 35, 276, 2415]
21
+ assert egyptian_fraction(Rational(5, 6), "Graham Jewett") == \
22
+ [6, 7, 8, 9, 10, 42, 43, 44, 45, 56, 57, 58, 72, 73, 90, 1806, 1807,
23
+ 1808, 1892, 1893, 1980, 3192, 3193, 3306, 5256, 3263442, 3263443,
24
+ 3267056, 3581556, 10192056, 10650056950806]
25
+ assert egyptian_fraction(Rational(5, 6), "Golomb") == [2, 6, 12, 20, 30]
26
+ assert egyptian_fraction(Rational(5, 121), "Golomb") == [25, 1225, 3577, 7081, 11737]
27
+ raises(ValueError, lambda: egyptian_fraction(Rational(-4, 9)))
28
+ assert egyptian_fraction(Rational(8, 3), "Golomb") == [1, 2, 3, 4, 5, 6, 7,
29
+ 14, 574, 2788, 6460,
30
+ 11590, 33062, 113820]
31
+ assert egyptian_fraction(Rational(355, 113)) == [1, 2, 3, 4, 5, 6, 7, 8, 9,
32
+ 10, 11, 12, 27, 744, 893588,
33
+ 1251493536607,
34
+ 20361068938197002344405230]
35
+
36
+
37
+ def test_input():
38
+ r = (2,3), Rational(2, 3), (Rational(2), Rational(3))
39
+ for m in ["Greedy", "Graham Jewett", "Takenouchi", "Golomb"]:
40
+ for i in r:
41
+ d = egyptian_fraction(i, m)
42
+ assert all(i.is_Integer for i in d)
43
+ if m == "Graham Jewett":
44
+ assert d == [3, 4, 12]
45
+ else:
46
+ assert d == [2, 6]
47
+ # check prefix
48
+ d = egyptian_fraction(Rational(5, 3))
49
+ assert d == [1, 2, 6] and all(i.is_Integer for i in d)
lib/python3.12/site-packages/sympy/ntheory/tests/test_generate.py ADDED
@@ -0,0 +1,285 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from bisect import bisect, bisect_left
2
+
3
+ from sympy.functions.combinatorial.numbers import mobius, totient
4
+ from sympy.ntheory.generate import (sieve, Sieve)
5
+
6
+ from sympy.ntheory import isprime, randprime, nextprime, prevprime, \
7
+ primerange, primepi, prime, primorial, composite, compositepi
8
+ from sympy.ntheory.generate import cycle_length, _primepi
9
+ from sympy.ntheory.primetest import mr
10
+ from sympy.testing.pytest import raises
11
+
12
+ def test_prime():
13
+ assert prime(1) == 2
14
+ assert prime(2) == 3
15
+ assert prime(5) == 11
16
+ assert prime(11) == 31
17
+ assert prime(57) == 269
18
+ assert prime(296) == 1949
19
+ assert prime(559) == 4051
20
+ assert prime(3000) == 27449
21
+ assert prime(4096) == 38873
22
+ assert prime(9096) == 94321
23
+ assert prime(25023) == 287341
24
+ assert prime(10000000) == 179424673 # issue #20951
25
+ assert prime(99999999) == 2038074739
26
+ raises(ValueError, lambda: prime(0))
27
+ sieve.extend(3000)
28
+ assert prime(401) == 2749
29
+ raises(ValueError, lambda: prime(-1))
30
+
31
+
32
+ def test__primepi():
33
+ assert _primepi(-1) == 0
34
+ assert _primepi(1) == 0
35
+ assert _primepi(2) == 1
36
+ assert _primepi(5) == 3
37
+ assert _primepi(11) == 5
38
+ assert _primepi(57) == 16
39
+ assert _primepi(296) == 62
40
+ assert _primepi(559) == 102
41
+ assert _primepi(3000) == 430
42
+ assert _primepi(4096) == 564
43
+ assert _primepi(9096) == 1128
44
+ assert _primepi(25023) == 2763
45
+ assert _primepi(10**8) == 5761455
46
+ assert _primepi(253425253) == 13856396
47
+ assert _primepi(8769575643) == 401464322
48
+ sieve.extend(3000)
49
+ assert _primepi(2000) == 303
50
+
51
+
52
+ def test_composite():
53
+ from sympy.ntheory.generate import sieve
54
+ sieve._reset()
55
+ assert composite(1) == 4
56
+ assert composite(2) == 6
57
+ assert composite(5) == 10
58
+ assert composite(11) == 20
59
+ assert composite(41) == 58
60
+ assert composite(57) == 80
61
+ assert composite(296) == 370
62
+ assert composite(559) == 684
63
+ assert composite(3000) == 3488
64
+ assert composite(4096) == 4736
65
+ assert composite(9096) == 10368
66
+ assert composite(25023) == 28088
67
+ sieve.extend(3000)
68
+ assert composite(1957) == 2300
69
+ assert composite(2568) == 2998
70
+ raises(ValueError, lambda: composite(0))
71
+
72
+
73
+ def test_compositepi():
74
+ assert compositepi(1) == 0
75
+ assert compositepi(2) == 0
76
+ assert compositepi(5) == 1
77
+ assert compositepi(11) == 5
78
+ assert compositepi(57) == 40
79
+ assert compositepi(296) == 233
80
+ assert compositepi(559) == 456
81
+ assert compositepi(3000) == 2569
82
+ assert compositepi(4096) == 3531
83
+ assert compositepi(9096) == 7967
84
+ assert compositepi(25023) == 22259
85
+ assert compositepi(10**8) == 94238544
86
+ assert compositepi(253425253) == 239568856
87
+ assert compositepi(8769575643) == 8368111320
88
+ sieve.extend(3000)
89
+ assert compositepi(2321) == 1976
90
+
91
+
92
+ def test_generate():
93
+ from sympy.ntheory.generate import sieve
94
+ sieve._reset()
95
+ assert nextprime(-4) == 2
96
+ assert nextprime(2) == 3
97
+ assert nextprime(5) == 7
98
+ assert nextprime(12) == 13
99
+ assert prevprime(3) == 2
100
+ assert prevprime(7) == 5
101
+ assert prevprime(13) == 11
102
+ assert prevprime(19) == 17
103
+ assert prevprime(20) == 19
104
+
105
+ sieve.extend_to_no(9)
106
+ assert sieve._list[-1] == 23
107
+
108
+ assert sieve._list[-1] < 31
109
+ assert 31 in sieve
110
+
111
+ assert nextprime(90) == 97
112
+ assert nextprime(10**40) == (10**40 + 121)
113
+ primelist = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31,
114
+ 37, 41, 43, 47, 53, 59, 61, 67, 71, 73,
115
+ 79, 83, 89, 97, 101, 103, 107, 109, 113,
116
+ 127, 131, 137, 139, 149, 151, 157, 163,
117
+ 167, 173, 179, 181, 191, 193, 197, 199,
118
+ 211, 223, 227, 229, 233, 239, 241, 251,
119
+ 257, 263, 269, 271, 277, 281, 283, 293]
120
+ for i in range(len(primelist) - 2):
121
+ for j in range(2, len(primelist) - i):
122
+ assert nextprime(primelist[i], j) == primelist[i + j]
123
+ if 3 < i:
124
+ assert nextprime(primelist[i] - 1, j) == primelist[i + j - 1]
125
+ raises(ValueError, lambda: nextprime(2, 0))
126
+ raises(ValueError, lambda: nextprime(2, -1))
127
+ assert prevprime(97) == 89
128
+ assert prevprime(10**40) == (10**40 - 17)
129
+
130
+ raises(ValueError, lambda: Sieve(0))
131
+ raises(ValueError, lambda: Sieve(-1))
132
+ for sieve_interval in [1, 10, 11, 1_000_000]:
133
+ s = Sieve(sieve_interval=sieve_interval)
134
+ for head in range(s._list[-1] + 1, (s._list[-1] + 1)**2, 2):
135
+ for tail in range(head + 1, (s._list[-1] + 1)**2):
136
+ A = list(s._primerange(head, tail))
137
+ B = primelist[bisect(primelist, head):bisect_left(primelist, tail)]
138
+ assert A == B
139
+ for k in range(s._list[-1], primelist[-1] - 1, 2):
140
+ s = Sieve(sieve_interval=sieve_interval)
141
+ s.extend(k)
142
+ assert list(s._list) == primelist[:bisect(primelist, k)]
143
+ s.extend(primelist[-1])
144
+ assert list(s._list) == primelist
145
+
146
+ assert list(sieve.primerange(10, 1)) == []
147
+ assert list(sieve.primerange(5, 9)) == [5, 7]
148
+ sieve._reset(prime=True)
149
+ assert list(sieve.primerange(2, 13)) == [2, 3, 5, 7, 11]
150
+ assert list(sieve.primerange(13)) == [2, 3, 5, 7, 11]
151
+ assert list(sieve.primerange(8)) == [2, 3, 5, 7]
152
+ assert list(sieve.primerange(-2)) == []
153
+ assert list(sieve.primerange(29)) == [2, 3, 5, 7, 11, 13, 17, 19, 23]
154
+ assert list(sieve.primerange(34)) == [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31]
155
+
156
+ assert list(sieve.totientrange(5, 15)) == [4, 2, 6, 4, 6, 4, 10, 4, 12, 6]
157
+ sieve._reset(totient=True)
158
+ assert list(sieve.totientrange(3, 13)) == [2, 2, 4, 2, 6, 4, 6, 4, 10, 4]
159
+ assert list(sieve.totientrange(900, 1000)) == [totient(x) for x in range(900, 1000)]
160
+ assert list(sieve.totientrange(0, 1)) == []
161
+ assert list(sieve.totientrange(1, 2)) == [1]
162
+
163
+ assert list(sieve.mobiusrange(5, 15)) == [-1, 1, -1, 0, 0, 1, -1, 0, -1, 1]
164
+ sieve._reset(mobius=True)
165
+ assert list(sieve.mobiusrange(3, 13)) == [-1, 0, -1, 1, -1, 0, 0, 1, -1, 0]
166
+ assert list(sieve.mobiusrange(1050, 1100)) == [mobius(x) for x in range(1050, 1100)]
167
+ assert list(sieve.mobiusrange(0, 1)) == []
168
+ assert list(sieve.mobiusrange(1, 2)) == [1]
169
+
170
+ assert list(primerange(10, 1)) == []
171
+ assert list(primerange(2, 7)) == [2, 3, 5]
172
+ assert list(primerange(2, 10)) == [2, 3, 5, 7]
173
+ assert list(primerange(1050, 1100)) == [1051, 1061,
174
+ 1063, 1069, 1087, 1091, 1093, 1097]
175
+ s = Sieve()
176
+ for i in range(30, 2350, 376):
177
+ for j in range(2, 5096, 1139):
178
+ A = list(s.primerange(i, i + j))
179
+ B = list(primerange(i, i + j))
180
+ assert A == B
181
+ s = Sieve()
182
+ sieve._reset(prime=True)
183
+ sieve.extend(13)
184
+ for i in range(200):
185
+ for j in range(i, 200):
186
+ A = list(s.primerange(i, j))
187
+ B = list(primerange(i, j))
188
+ assert A == B
189
+ sieve.extend(1000)
190
+ for a, b in [(901, 1103), # a < 1000 < b < 1000**2
191
+ (806, 1002007), # a < 1000 < 1000**2 < b
192
+ (2000, 30001), # 1000 < a < b < 1000**2
193
+ (100005, 1010001), # 1000 < a < 1000**2 < b
194
+ (1003003, 1005000), # 1000**2 < a < b
195
+ ]:
196
+ assert list(primerange(a, b)) == list(s.primerange(a, b))
197
+ sieve._reset(prime=True)
198
+ sieve.extend(100000)
199
+ assert len(sieve._list) == len(set(sieve._list))
200
+ s = Sieve()
201
+ assert s[10] == 29
202
+
203
+ assert nextprime(2, 2) == 5
204
+
205
+ raises(ValueError, lambda: totient(0))
206
+
207
+ raises(ValueError, lambda: primorial(0))
208
+
209
+ assert mr(1, [2]) is False
210
+
211
+ func = lambda i: (i**2 + 1) % 51
212
+ assert next(cycle_length(func, 4)) == (6, 3)
213
+ assert list(cycle_length(func, 4, values=True)) == \
214
+ [4, 17, 35, 2, 5, 26, 14, 44, 50, 2, 5, 26, 14]
215
+ assert next(cycle_length(func, 4, nmax=5)) == (5, None)
216
+ assert list(cycle_length(func, 4, nmax=5, values=True)) == \
217
+ [4, 17, 35, 2, 5]
218
+ sieve.extend(3000)
219
+ assert nextprime(2968) == 2969
220
+ assert prevprime(2930) == 2927
221
+ raises(ValueError, lambda: prevprime(1))
222
+ raises(ValueError, lambda: prevprime(-4))
223
+
224
+
225
+ def test_randprime():
226
+ assert randprime(10, 1) is None
227
+ assert randprime(3, -3) is None
228
+ assert randprime(2, 3) == 2
229
+ assert randprime(1, 3) == 2
230
+ assert randprime(3, 5) == 3
231
+ raises(ValueError, lambda: randprime(-12, -2))
232
+ raises(ValueError, lambda: randprime(-10, 0))
233
+ raises(ValueError, lambda: randprime(20, 22))
234
+ raises(ValueError, lambda: randprime(0, 2))
235
+ raises(ValueError, lambda: randprime(1, 2))
236
+ for a in [100, 300, 500, 250000]:
237
+ for b in [100, 300, 500, 250000]:
238
+ p = randprime(a, a + b)
239
+ assert a <= p < (a + b) and isprime(p)
240
+
241
+
242
+ def test_primorial():
243
+ assert primorial(1) == 2
244
+ assert primorial(1, nth=0) == 1
245
+ assert primorial(2) == 6
246
+ assert primorial(2, nth=0) == 2
247
+ assert primorial(4, nth=0) == 6
248
+
249
+
250
+ def test_search():
251
+ assert 2 in sieve
252
+ assert 2.1 not in sieve
253
+ assert 1 not in sieve
254
+ assert 2**1000 not in sieve
255
+ raises(ValueError, lambda: sieve.search(1))
256
+
257
+
258
+ def test_sieve_slice():
259
+ assert sieve[5] == 11
260
+ assert list(sieve[5:10]) == [sieve[x] for x in range(5, 10)]
261
+ assert list(sieve[5:10:2]) == [sieve[x] for x in range(5, 10, 2)]
262
+ assert list(sieve[1:5]) == [2, 3, 5, 7]
263
+ raises(IndexError, lambda: sieve[:5])
264
+ raises(IndexError, lambda: sieve[0])
265
+ raises(IndexError, lambda: sieve[0:5])
266
+
267
+ def test_sieve_iter():
268
+ values = []
269
+ for value in sieve:
270
+ if value > 7:
271
+ break
272
+ values.append(value)
273
+ assert values == list(sieve[1:5])
274
+
275
+
276
+ def test_sieve_repr():
277
+ assert "sieve" in repr(sieve)
278
+ assert "prime" in repr(sieve)
279
+
280
+
281
+ def test_deprecated_ntheory_symbolic_functions():
282
+ from sympy.testing.pytest import warns_deprecated_sympy
283
+
284
+ with warns_deprecated_sympy():
285
+ assert primepi(0) == 0
lib/python3.12/site-packages/sympy/ntheory/tests/test_hypothesis.py ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from hypothesis import given
2
+ from hypothesis import strategies as st
3
+ from sympy import divisors
4
+ from sympy.functions.combinatorial.numbers import divisor_sigma, totient
5
+ from sympy.ntheory.primetest import is_square
6
+
7
+
8
+ @given(n=st.integers(1, 10**10))
9
+ def test_tau_hypothesis(n):
10
+ div = divisors(n)
11
+ tau_n = len(div)
12
+ assert is_square(n) == (tau_n % 2 == 1)
13
+ sigmas = [divisor_sigma(i) for i in div]
14
+ totients = [totient(n // i) for i in div]
15
+ mul = [a * b for a, b in zip(sigmas, totients)]
16
+ assert n * tau_n == sum(mul)
17
+
18
+
19
+ @given(n=st.integers(1, 10**10))
20
+ def test_totient_hypothesis(n):
21
+ assert totient(n) <= n
22
+ div = divisors(n)
23
+ totients = [totient(i) for i in div]
24
+ assert n == sum(totients)
lib/python3.12/site-packages/sympy/ntheory/tests/test_partitions.py ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from sympy.ntheory.partitions_ import npartitions, _partition_rec, _partition
2
+
3
+
4
+ def test__partition_rec():
5
+ A000041 = [1, 1, 2, 3, 5, 7, 11, 15, 22, 30, 42, 56, 77, 101, 135,
6
+ 176, 231, 297, 385, 490, 627, 792, 1002, 1255, 1575]
7
+ for n, val in enumerate(A000041):
8
+ assert _partition_rec(n) == val
9
+
10
+
11
+ def test__partition():
12
+ assert [_partition(k) for k in range(13)] == \
13
+ [1, 1, 2, 3, 5, 7, 11, 15, 22, 30, 42, 56, 77]
14
+ assert _partition(100) == 190569292
15
+ assert _partition(200) == 3972999029388
16
+ assert _partition(1000) == 24061467864032622473692149727991
17
+ assert _partition(1001) == 25032297938763929621013218349796
18
+ assert _partition(2000) == 4720819175619413888601432406799959512200344166
19
+ assert _partition(10000) % 10**10 == 6916435144
20
+ assert _partition(100000) % 10**10 == 9421098519
21
+
22
+
23
+ def test_deprecated_ntheory_symbolic_functions():
24
+ from sympy.testing.pytest import warns_deprecated_sympy
25
+
26
+ with warns_deprecated_sympy():
27
+ assert npartitions(0) == 1
lib/python3.12/site-packages/sympy/ntheory/tests/test_primetest.py ADDED
@@ -0,0 +1,230 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from math import gcd
2
+
3
+ from sympy.ntheory.generate import Sieve, sieve
4
+ from sympy.ntheory.primetest import (mr, _lucas_extrastrong_params, is_lucas_prp, is_square,
5
+ is_strong_lucas_prp, is_extra_strong_lucas_prp,
6
+ proth_test, isprime, is_euler_pseudoprime,
7
+ is_gaussian_prime, is_fermat_pseudoprime, is_euler_jacobi_pseudoprime,
8
+ MERSENNE_PRIME_EXPONENTS, _lucas_lehmer_primality_test,
9
+ is_mersenne_prime)
10
+
11
+ from sympy.testing.pytest import slow, raises
12
+ from sympy.core.numbers import I, Float
13
+
14
+
15
+ def test_is_fermat_pseudoprime():
16
+ assert is_fermat_pseudoprime(5, 1)
17
+ assert is_fermat_pseudoprime(9, 1)
18
+
19
+
20
+ def test_euler_pseudoprimes():
21
+ assert is_euler_pseudoprime(13, 1)
22
+ assert is_euler_pseudoprime(15, 1)
23
+ assert is_euler_pseudoprime(17, 6)
24
+ assert is_euler_pseudoprime(101, 7)
25
+ assert is_euler_pseudoprime(1009, 10)
26
+ assert is_euler_pseudoprime(11287, 41)
27
+
28
+ raises(ValueError, lambda: is_euler_pseudoprime(0, 4))
29
+ raises(ValueError, lambda: is_euler_pseudoprime(3, 0))
30
+ raises(ValueError, lambda: is_euler_pseudoprime(15, 6))
31
+
32
+ # A006970
33
+ euler_prp = [341, 561, 1105, 1729, 1905, 2047, 2465, 3277,
34
+ 4033, 4681, 5461, 6601, 8321, 8481, 10261, 10585]
35
+ for p in euler_prp:
36
+ assert is_euler_pseudoprime(p, 2)
37
+
38
+ # A048950
39
+ euler_prp = [121, 703, 1729, 1891, 2821, 3281, 7381, 8401, 8911, 10585,
40
+ 12403, 15457, 15841, 16531, 18721, 19345, 23521, 24661, 28009]
41
+ for p in euler_prp:
42
+ assert is_euler_pseudoprime(p, 3)
43
+
44
+ # A033181
45
+ absolute_euler_prp = [1729, 2465, 15841, 41041, 46657, 75361,
46
+ 162401, 172081, 399001, 449065, 488881]
47
+ for p in absolute_euler_prp:
48
+ for a in range(2, p):
49
+ if gcd(a, p) != 1:
50
+ continue
51
+ assert is_euler_pseudoprime(p, a)
52
+
53
+
54
+ def test_is_euler_jacobi_pseudoprime():
55
+ assert is_euler_jacobi_pseudoprime(11, 1)
56
+ assert is_euler_jacobi_pseudoprime(15, 1)
57
+
58
+
59
+ def test_lucas_extrastrong_params():
60
+ assert _lucas_extrastrong_params(3) == (5, 3, 1)
61
+ assert _lucas_extrastrong_params(5) == (12, 4, 1)
62
+ assert _lucas_extrastrong_params(7) == (5, 3, 1)
63
+ assert _lucas_extrastrong_params(9) == (0, 0, 0)
64
+ assert _lucas_extrastrong_params(11) == (21, 5, 1)
65
+ assert _lucas_extrastrong_params(59) == (32, 6, 1)
66
+ assert _lucas_extrastrong_params(479) == (117, 11, 1)
67
+
68
+
69
+ def test_is_extra_strong_lucas_prp():
70
+ assert is_extra_strong_lucas_prp(4) == False
71
+ assert is_extra_strong_lucas_prp(989) == True
72
+ assert is_extra_strong_lucas_prp(10877) == True
73
+ assert is_extra_strong_lucas_prp(9) == False
74
+ assert is_extra_strong_lucas_prp(16) == False
75
+ assert is_extra_strong_lucas_prp(169) == False
76
+
77
+ @slow
78
+ def test_prps():
79
+ oddcomposites = [n for n in range(1, 10**5) if
80
+ n % 2 and not isprime(n)]
81
+ # A checksum would be better.
82
+ assert sum(oddcomposites) == 2045603465
83
+ assert [n for n in oddcomposites if mr(n, [2])] == [
84
+ 2047, 3277, 4033, 4681, 8321, 15841, 29341, 42799, 49141,
85
+ 52633, 65281, 74665, 80581, 85489, 88357, 90751]
86
+ assert [n for n in oddcomposites if mr(n, [3])] == [
87
+ 121, 703, 1891, 3281, 8401, 8911, 10585, 12403, 16531,
88
+ 18721, 19345, 23521, 31621, 44287, 47197, 55969, 63139,
89
+ 74593, 79003, 82513, 87913, 88573, 97567]
90
+ assert [n for n in oddcomposites if mr(n, [325])] == [
91
+ 9, 25, 27, 49, 65, 81, 325, 341, 343, 697, 1141, 2059,
92
+ 2149, 3097, 3537, 4033, 4681, 4941, 5833, 6517, 7987, 8911,
93
+ 12403, 12913, 15043, 16021, 20017, 22261, 23221, 24649,
94
+ 24929, 31841, 35371, 38503, 43213, 44173, 47197, 50041,
95
+ 55909, 56033, 58969, 59089, 61337, 65441, 68823, 72641,
96
+ 76793, 78409, 85879]
97
+ assert not any(mr(n, [9345883071009581737]) for n in oddcomposites)
98
+ assert [n for n in oddcomposites if is_lucas_prp(n)] == [
99
+ 323, 377, 1159, 1829, 3827, 5459, 5777, 9071, 9179, 10877,
100
+ 11419, 11663, 13919, 14839, 16109, 16211, 18407, 18971,
101
+ 19043, 22499, 23407, 24569, 25199, 25877, 26069, 27323,
102
+ 32759, 34943, 35207, 39059, 39203, 39689, 40309, 44099,
103
+ 46979, 47879, 50183, 51983, 53663, 56279, 58519, 60377,
104
+ 63881, 69509, 72389, 73919, 75077, 77219, 79547, 79799,
105
+ 82983, 84419, 86063, 90287, 94667, 97019, 97439]
106
+ assert [n for n in oddcomposites if is_strong_lucas_prp(n)] == [
107
+ 5459, 5777, 10877, 16109, 18971, 22499, 24569, 25199, 40309,
108
+ 58519, 75077, 97439]
109
+ assert [n for n in oddcomposites if is_extra_strong_lucas_prp(n)
110
+ ] == [
111
+ 989, 3239, 5777, 10877, 27971, 29681, 30739, 31631, 39059,
112
+ 72389, 73919, 75077]
113
+
114
+
115
+ def test_proth_test():
116
+ # Proth number
117
+ A080075 = [3, 5, 9, 13, 17, 25, 33, 41, 49, 57, 65,
118
+ 81, 97, 113, 129, 145, 161, 177, 193]
119
+ # Proth prime
120
+ A080076 = [3, 5, 13, 17, 41, 97, 113, 193]
121
+
122
+ for n in range(200):
123
+ if n in A080075:
124
+ assert proth_test(n) == (n in A080076)
125
+ else:
126
+ raises(ValueError, lambda: proth_test(n))
127
+
128
+
129
+ def test_lucas_lehmer_primality_test():
130
+ for p in sieve.primerange(3, 100):
131
+ assert _lucas_lehmer_primality_test(p) == (p in MERSENNE_PRIME_EXPONENTS)
132
+
133
+
134
+ def test_is_mersenne_prime():
135
+ assert is_mersenne_prime(-3) is False
136
+ assert is_mersenne_prime(3) is True
137
+ assert is_mersenne_prime(10) is False
138
+ assert is_mersenne_prime(127) is True
139
+ assert is_mersenne_prime(511) is False
140
+ assert is_mersenne_prime(131071) is True
141
+ assert is_mersenne_prime(2147483647) is True
142
+
143
+
144
+ def test_isprime():
145
+ s = Sieve()
146
+ s.extend(100000)
147
+ ps = set(s.primerange(2, 100001))
148
+ for n in range(100001):
149
+ # if (n in ps) != isprime(n): print n
150
+ assert (n in ps) == isprime(n)
151
+ assert isprime(179424673)
152
+ assert isprime(20678048681)
153
+ assert isprime(1968188556461)
154
+ assert isprime(2614941710599)
155
+ assert isprime(65635624165761929287)
156
+ assert isprime(1162566711635022452267983)
157
+ assert isprime(77123077103005189615466924501)
158
+ assert isprime(3991617775553178702574451996736229)
159
+ assert isprime(273952953553395851092382714516720001799)
160
+ assert isprime(int('''
161
+ 531137992816767098689588206552468627329593117727031923199444138200403\
162
+ 559860852242739162502265229285668889329486246501015346579337652707239\
163
+ 409519978766587351943831270835393219031728127'''))
164
+
165
+ # Some Mersenne primes
166
+ assert isprime(2**61 - 1)
167
+ assert isprime(2**89 - 1)
168
+ assert isprime(2**607 - 1)
169
+ # (but not all Mersenne's are primes
170
+ assert not isprime(2**601 - 1)
171
+
172
+ # pseudoprimes
173
+ #-------------
174
+ # to some small bases
175
+ assert not isprime(2152302898747)
176
+ assert not isprime(3474749660383)
177
+ assert not isprime(341550071728321)
178
+ assert not isprime(3825123056546413051)
179
+ # passes the base set [2, 3, 7, 61, 24251]
180
+ assert not isprime(9188353522314541)
181
+ # large examples
182
+ assert not isprime(877777777777777777777777)
183
+ # conjectured psi_12 given at http://mathworld.wolfram.com/StrongPseudoprime.html
184
+ assert not isprime(318665857834031151167461)
185
+ # conjectured psi_17 given at http://mathworld.wolfram.com/StrongPseudoprime.html
186
+ assert not isprime(564132928021909221014087501701)
187
+ # Arnault's 1993 number; a factor of it is
188
+ # 400958216639499605418306452084546853005188166041132508774506\
189
+ # 204738003217070119624271622319159721973358216316508535816696\
190
+ # 9145233813917169287527980445796800452592031836601
191
+ assert not isprime(int('''
192
+ 803837457453639491257079614341942108138837688287558145837488917522297\
193
+ 427376533365218650233616396004545791504202360320876656996676098728404\
194
+ 396540823292873879185086916685732826776177102938969773947016708230428\
195
+ 687109997439976544144845341155872450633409279022275296229414984230688\
196
+ 1685404326457534018329786111298960644845216191652872597534901'''))
197
+ # Arnault's 1995 number; can be factored as
198
+ # p1*(313*(p1 - 1) + 1)*(353*(p1 - 1) + 1) where p1 is
199
+ # 296744956686855105501541746429053327307719917998530433509950\
200
+ # 755312768387531717701995942385964281211880336647542183455624\
201
+ # 93168782883
202
+ assert not isprime(int('''
203
+ 288714823805077121267142959713039399197760945927972270092651602419743\
204
+ 230379915273311632898314463922594197780311092934965557841894944174093\
205
+ 380561511397999942154241693397290542371100275104208013496673175515285\
206
+ 922696291677532547504444585610194940420003990443211677661994962953925\
207
+ 045269871932907037356403227370127845389912612030924484149472897688540\
208
+ 6024976768122077071687938121709811322297802059565867'''))
209
+ sieve.extend(3000)
210
+ assert isprime(2819)
211
+ assert not isprime(2931)
212
+ raises(ValueError, lambda: isprime(2.0))
213
+ raises(ValueError, lambda: isprime(Float(2)))
214
+
215
+
216
+ def test_is_square():
217
+ assert [i for i in range(25) if is_square(i)] == [0, 1, 4, 9, 16]
218
+
219
+ # issue #17044
220
+ assert not is_square(60 ** 3)
221
+ assert not is_square(60 ** 5)
222
+ assert not is_square(84 ** 7)
223
+ assert not is_square(105 ** 9)
224
+ assert not is_square(120 ** 3)
225
+
226
+ def test_is_gaussianprime():
227
+ assert is_gaussian_prime(7*I)
228
+ assert is_gaussian_prime(7)
229
+ assert is_gaussian_prime(2 + 3*I)
230
+ assert not is_gaussian_prime(2 + 2*I)
lib/python3.12/site-packages/sympy/ntheory/tests/test_qs.py ADDED
@@ -0,0 +1,124 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from __future__ import annotations
2
+
3
+ from sympy.ntheory import qs
4
+ from sympy.ntheory.qs import SievePolynomial, _generate_factor_base, \
5
+ _initialize_first_polynomial, _initialize_ith_poly, \
6
+ _gen_sieve_array, _check_smoothness, _trial_division_stage, _gauss_mod_2, \
7
+ _build_matrix, _find_factor
8
+ from sympy.testing.pytest import slow
9
+
10
+
11
+ @slow
12
+ def test_qs_1():
13
+ assert qs(10009202107, 100, 10000) == {100043, 100049}
14
+ assert qs(211107295182713951054568361, 1000, 10000) == \
15
+ {13791315212531, 15307263442931}
16
+ assert qs(980835832582657*990377764891511, 3000, 50000) == \
17
+ {980835832582657, 990377764891511}
18
+ assert qs(18640889198609*20991129234731, 1000, 50000) == \
19
+ {18640889198609, 20991129234731}
20
+
21
+
22
+ def test_qs_2() -> None:
23
+ n = 10009202107
24
+ M = 50
25
+ # a = 10, b = 15, modified_coeff = [a**2, 2*a*b, b**2 - N]
26
+ sieve_poly = SievePolynomial([100, 1600, -10009195707], 10, 80)
27
+ assert sieve_poly.eval(10) == -10009169707
28
+ assert sieve_poly.eval(5) == -10009185207
29
+
30
+ idx_1000, idx_5000, factor_base = _generate_factor_base(2000, n)
31
+ assert idx_1000 == 82
32
+ assert [factor_base[i].prime for i in range(15)] == \
33
+ [2, 3, 7, 11, 17, 19, 29, 31, 43, 59, 61, 67, 71, 73, 79]
34
+ assert [factor_base[i].tmem_p for i in range(15)] == \
35
+ [1, 1, 3, 5, 3, 6, 6, 14, 1, 16, 24, 22, 18, 22, 15]
36
+ assert [factor_base[i].log_p for i in range(5)] == \
37
+ [710, 1125, 1993, 2455, 2901]
38
+
39
+ g, B = _initialize_first_polynomial(
40
+ n, M, factor_base, idx_1000, idx_5000, seed=0)
41
+ assert g.a == 1133107
42
+ assert g.b == 682543
43
+ assert B == [272889, 409654]
44
+ assert [factor_base[i].soln1 for i in range(15)] == \
45
+ [0, 0, 3, 7, 13, 0, 8, 19, 9, 43, 27, 25, 63, 29, 19]
46
+ assert [factor_base[i].soln2 for i in range(15)] == \
47
+ [0, 1, 1, 3, 12, 16, 15, 6, 15, 1, 56, 55, 61, 58, 16]
48
+ assert [factor_base[i].a_inv for i in range(15)] == \
49
+ [1, 1, 5, 7, 3, 5, 26, 6, 40, 5, 21, 45, 4, 1, 8]
50
+ assert [factor_base[i].b_ainv for i in range(5)] == \
51
+ [[0, 0], [0, 2], [3, 0], [3, 9], [13, 13]]
52
+
53
+ g_1 = _initialize_ith_poly(n, factor_base, 1, g, B)
54
+ assert g_1.a == 1133107
55
+ assert g_1.b == 136765
56
+
57
+ sieve_array = _gen_sieve_array(M, factor_base)
58
+ assert sieve_array[0:5] == [8424, 13603, 1835, 5335, 710]
59
+
60
+ assert _check_smoothness(9645, factor_base) == (5, False)
61
+ assert _check_smoothness(210313, factor_base)[0][0:15] == \
62
+ [0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1]
63
+ assert _check_smoothness(210313, factor_base)[1]
64
+
65
+ partial_relations: dict[int, tuple[int, int]] = {}
66
+ smooth_relation, partial_relation = _trial_division_stage(
67
+ n, M, factor_base, sieve_array, sieve_poly, partial_relations,
68
+ ERROR_TERM=25*2**10)
69
+
70
+ assert partial_relations == {
71
+ 8699: (440, -10009008507),
72
+ 166741: (490, -10008962007),
73
+ 131449: (530, -10008921207),
74
+ 6653: (550, -10008899607)
75
+ }
76
+ assert [smooth_relation[i][0] for i in range(5)] == [
77
+ -250, -670615476700, -45211565844500, -231723037747200, -1811665537200]
78
+ assert [smooth_relation[i][1] for i in range(5)] == [
79
+ -10009139607, 1133094251961, 5302606761, 53804049849, 1950723889]
80
+ assert smooth_relation[0][2][0:15] == [
81
+ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
82
+
83
+ assert _gauss_mod_2(
84
+ [[0, 0, 1], [1, 0, 1], [0, 1, 0], [0, 1, 1], [0, 1, 1]]
85
+ ) == (
86
+ [[[0, 1, 1], 3], [[0, 1, 1], 4]],
87
+ [True, True, True, False, False],
88
+ [[0, 0, 1], [1, 0, 0], [0, 1, 0], [0, 1, 1], [0, 1, 1]]
89
+ )
90
+
91
+
92
+ def test_qs_3():
93
+ N = 1817
94
+ smooth_relations = [
95
+ (2455024, 637, [0, 0, 0, 1]),
96
+ (-27993000, 81536, [0, 1, 0, 1]),
97
+ (11461840, 12544, [0, 0, 0, 0]),
98
+ (149, 20384, [0, 1, 0, 1]),
99
+ (-31138074, 19208, [0, 1, 0, 0])
100
+ ]
101
+
102
+ matrix = _build_matrix(smooth_relations)
103
+ assert matrix == [
104
+ [0, 0, 0, 1],
105
+ [0, 1, 0, 1],
106
+ [0, 0, 0, 0],
107
+ [0, 1, 0, 1],
108
+ [0, 1, 0, 0]
109
+ ]
110
+
111
+ dependent_row, mark, gauss_matrix = _gauss_mod_2(matrix)
112
+ assert dependent_row == [[[0, 0, 0, 0], 2], [[0, 1, 0, 0], 3]]
113
+ assert mark == [True, True, False, False, True]
114
+ assert gauss_matrix == [
115
+ [0, 0, 0, 1],
116
+ [0, 1, 0, 0],
117
+ [0, 0, 0, 0],
118
+ [0, 1, 0, 0],
119
+ [0, 1, 0, 1]
120
+ ]
121
+
122
+ factor = _find_factor(
123
+ dependent_row, mark, gauss_matrix, 0, smooth_relations, N)
124
+ assert factor == 23