def test_isqrt(): from math import sqrt as _sqrt limit = 17984395633462800708566937239551 assert int(_sqrt(limit)) == integer_nthroot(limit, 2)[0] assert int(_sqrt(limit + 1)) != integer_nthroot(limit + 1, 2)[0] assert isqrt(limit + 1) == integer_nthroot(limit + 1, 2)[0] assert isqrt(limit + 1 + S.Half) == integer_nthroot(limit + 1, 2)[0]
def test_powers(): assert integer_nthroot(1, 2) == (1, True) assert integer_nthroot(1, 5) == (1, True) assert integer_nthroot(2, 1) == (2, True) assert integer_nthroot(2, 2) == (1, False) assert integer_nthroot(2, 5) == (1, False) assert integer_nthroot(4, 2) == (2, True) assert integer_nthroot(123**25, 25) == (123, True) assert integer_nthroot(123**25+1, 25) == (123, False) assert integer_nthroot(123**25-1, 25) == (122, False) assert 64**(Rational(1)/3)==4 assert 64**(Rational(2)/3)==16 assert 24*64**(-Rational(1)/2)==3 assert Rational(5**3, 8**3)**Rational(4,3) == Rational(5**4, 8**4) assert Rational(-4,7)**Rational(1,2) == I*Rational(4,7)**Rational(1,2) assert str(Rational(1,4) ** Rational(1,2)) == "1/2" assert str(Rational(1,36) ** Rational(1,2)) == "1/6" assert str((123**25) ** Rational(1,25)) == "123" assert str((123**25+1)**Rational(1,25)) != "123" assert str((123**25-1)**Rational(1,25)) != "123" assert str((123**25-1)**Rational(1,25)) != "122" assert str(Rational(3,5)**(-Rational(1,2))) == "5**(1/2)*(1/3)**(1/2)" assert str(Rational(81,36)**(Rational(3,2))) == "27/8" assert str(Rational(81,36)**(-Rational(3,2))) == "8/27" assert str((-4)**Rational(1,2)) == str(2*I)
def perfect_power(n, candidates=None, recursive=True): """ Return ``(a, b)`` such that ``n`` == ``a**b`` if ``n`` is a perfect power; otherwise return ``None``. By default, attempts to determine the largest possible ``b``. With ``recursive=False``, the smallest possible ``b`` will be chosen (this will be a prime number). """ if n < 3: return None logn = math.log(n,2) max_possible = int(logn)+2 if not candidates: candidates = primerange(2, max_possible) for b in candidates: if b > max_possible: break # Weed out downright impossible candidates if logn/b < 40: a = 2.0**(logn/b) if abs(int(a+0.5)-a) > 0.01: continue # print b r, exact = integer_nthroot(n, b) if exact: if recursive: m = perfect_power(r) if m: return m[0], b*m[1] return r, b
def perfect_power(n, candidates=None, recursive=True): """ Return ``(a, b)`` such that ``n`` == ``a**b`` if ``n`` is a perfect power; otherwise return ``None``. By default, attempts to determine the largest possible ``b``. With ``recursive=False``, the smallest possible ``b`` will be chosen (this will be a prime number). """ if n < 3: return None logn = math.log(n, 2) max_possible = int(logn) + 2 if not candidates: candidates = primerange(2, max_possible) for b in candidates: if b > max_possible: break # Weed out downright impossible candidates if logn / b < 40: a = 2.0**(logn / b) if abs(int(a + 0.5) - a) > 0.01: continue # print b r, exact = integer_nthroot(n, b) if exact: if recursive: m = perfect_power(r) if m: return m[0], b * m[1] return r, b
def is_square(n, prep=True): """Return True if n == a * a for some integer a, else False. If n is suspected of *not* being a square then this is a quick method of confirming that it is not. Examples ======== >>> from sympy.ntheory.primetest import is_square >>> is_square(25) True >>> is_square(2) False References ========== .. [1] http://mersenneforum.org/showpost.php?p=110896 See Also ======== sympy.core.power.integer_nthroot """ if prep: n = as_int(n) if n < 0: return False if n in (0, 1): return True # def magic(n): # s = {x**2 % n for x in range(n)} # return sum(1 << bit for bit in s) # >>> print(hex(magic(128))) # 0x2020212020202130202021202030213 # >>> print(hex(magic(99))) # 0x209060049048220348a410213 # >>> print(hex(magic(91))) # 0x102e403012a0c9862c14213 # >>> print(hex(magic(85))) # 0x121065188e001c46298213 if not 0x2020212020202130202021202030213 & (1 << (n & 127)): return False m = n % (99 * 91 * 85) if not 0x209060049048220348a410213 & (1 << (m % 99)): return False if not 0x102e403012a0c9862c14213 & (1 << (m % 91)): return False if not 0x121065188e001c46298213 & (1 << (m % 85)): return False return integer_nthroot(n, 2)[1]
def root_if_square(n: int): """ n must be pos (not tested) stolen from sympy.ntheory.primetest.s_square """ # if n <= 0: # return False if n == 1: return 1 m = n & 127 if not ((m*0x8bc40d7d) & (m*0xa1e2f5d1) & 0x14020a): m = n % 63 if not ((m*0x3d491df7) & (m*0xc824a9f9) & 0x10f14008): root, is_square = integer_nthroot(n, 2) if is_square: return root return False
def _find_factor(dependent_rows, mark, gauss_matrix, index, smooth_relations, N): """Finds proper factor of N. Here, transform the dependent rows as a combination of independent rows of the gauss_matrix to form the desired relation of the form ``X**2 = Y**2 modN``. After obtaining the desired relation we obtain a proper factor of N by `gcd(X - Y, N)`. Parameters ========== dependent_rows : denoted dependent rows in the reduced matrix form mark : boolean array to denoted dependent and independent rows gauss_matrix : Reduced form of the smooth relations matrix index : denoted the index of the dependent_rows smooth_relations : Smooth relations vectors matrix N : Number to be factored """ idx_in_smooth = dependent_rows[index][1] independent_u = [smooth_relations[idx_in_smooth][0]] independent_v = [smooth_relations[idx_in_smooth][1]] dept_row = dependent_rows[index][0] for idx, val in enumerate(dept_row): if val == 1: for row in range(len(gauss_matrix)): if gauss_matrix[row][idx] == 1 and mark[row] == True: independent_u.append(smooth_relations[row][0]) independent_v.append(smooth_relations[row][1]) break u = 1 v = 1 for i in independent_u: u *= i for i in independent_v: v *= i #assert u**2 % N == v % N v = integer_nthroot(v, 2)[0] return igcd(u - v, N)
def is_square(n, prep=True): """Return True if n == a * a for some integer a, else False. If n is suspected of *not* being a square then this is a quick method of confirming that it is not. Examples ======== >>> from sympy.ntheory.primetest import is_square >>> is_square(25) True >>> is_square(2) False References ========== [1] http://mersenneforum.org/showpost.php?p=110896 See Also ======== sympy.core.power.integer_nthroot """ if prep: n = as_int(n) if n < 0: return False if n in [0, 1]: return True m = n & 127 if not ((m * 0x8BC40D7D) & (m * 0xA1E2F5D1) & 0x14020A): m = n % 63 if not ((m * 0x3D491DF7) & (m * 0xC824A9F9) & 0x10F14008): from sympy.core.power import integer_nthroot return integer_nthroot(n, 2)[1] return False
def factorint(n, limit=None, use_trial=True, use_rho=True, use_pm1=True, verbose=False, visual=None): r""" Given a positive integer ``n``, ``factorint(n)`` returns a dict containing the prime factors of ``n`` as keys and their respective multiplicities as values. For example: >>> from sympy.ntheory import factorint >>> factorint(2000) # 2000 = (2**4) * (5**3) {2: 4, 5: 3} >>> factorint(65537) # This number is prime {65537: 1} For input less than 2, factorint behaves as follows: - ``factorint(1)`` returns the empty factorization, ``{}`` - ``factorint(0)`` returns ``{0:1}`` - ``factorint(-n)`` adds ``-1:1`` to the factors and then factors ``n`` Partial Factorization: If ``limit`` (> 3) is specified, the search is stopped after performing trial division up to (and including) the limit (or taking a corresponding number of rho/p-1 steps). This is useful if one has a large number and only is interested in finding small factors (if any). Note that setting a limit does not prevent larger factors from being found early; it simply means that the largest factor may be composite. Since checking for perfect power is relatively cheap, it is done regardless of the limit setting. This number, for example, has two small factors and a huge semi-prime factor that cannot be reduced easily: >>> from sympy.ntheory import isprime >>> a = 1407633717262338957430697921446883 >>> f = factorint(a, limit=10000) >>> f == {991: 1, 202916782076162456022877024859L: 1, 7: 1} True >>> isprime(max(f)) False This number has a small factor and a residual perfect power whose base is greater than the limit: >>> factorint(3*101**7, limit=5) {3: 1, 101: 7} Visual Factorization: If ``visual`` is set to ``True``, then it will return a visual factorization of the integer. For example: >>> from sympy import pprint >>> pprint(factorint(4200, visual=True)) 3 1 2 1 2 *3 *5 *7 Note that this is achieved by using the evaluate=False flag in Mul and Pow. If you do other manipulations with an expression where evaluate=False, it may evaluate. Therefore, you should use the visual option only for visualization, and use the normal dictionary returned by visual=False if you want to perform operations on the factors. You can easily switch between the two forms by sending them back to factorint: >>> from sympy import Mul, Pow >>> regular = factorint(1764); regular {2: 2, 3: 2, 7: 2} >>> pprint(factorint(regular)) 2 2 2 2 *3 *7 >>> visual = factorint(1764, visual=True); pprint(visual) 2 2 2 2 *3 *7 >>> print factorint(visual) {2: 2, 3: 2, 7: 2} If you want to send a number to be factored in a partially factored form you can do so with a dictionary or unevaluated expression: >>> factorint(factorint({4: 2, 12: 3})) # twice to toggle to dict form {2: 10, 3: 3} >>> factorint(Mul(4, 12, evaluate=False)) {2: 4, 3: 1} The table of the output logic is: ====== ====== ======= ======= Visual ------ ---------------------- Input True False other ====== ====== ======= ======= dict mul dict mul n mul dict dict mul mul dict dict ====== ====== ======= ======= Notes ===== Algorithm: The function switches between multiple algorithms. Trial division quickly finds small factors (of the order 1-5 digits), and finds all large factors if given enough time. The Pollard rho and p-1 algorithms are used to find large factors ahead of time; they will often find factors of the order of 10 digits within a few seconds: >>> factors = factorint(12345678910111213141516) >>> for base, exp in sorted(factors.items()): ... print base, exp ... 2 2 2507191691 1 1231026625769 1 Any of these methods can optionally be disabled with the following boolean parameters: - ``use_trial``: Toggle use of trial division - ``use_rho``: Toggle use of Pollard's rho method - ``use_pm1``: Toggle use of Pollard's p-1 method ``factorint`` also periodically checks if the remaining part is a prime number or a perfect power, and in those cases stops. If ``verbose`` is set to ``True``, detailed progress is printed. See Also ======== smoothness, smoothness_p, divisors """ factordict = {} if visual and not isinstance(n, Mul) and not isinstance(n, dict): factordict = factorint(n, limit=limit, use_trial=use_trial, use_rho=use_rho, use_pm1=use_pm1, verbose=verbose, visual=False) elif isinstance(n, Mul): factordict = dict([(int(k), int(v)) for k, v in n.as_powers_dict().items()]) elif isinstance(n, dict): factordict = n if factordict and (isinstance(n, Mul) or isinstance(n, dict)): # check it for k in factordict.keys(): if isprime(k): continue e = factordict.pop(k) d = factorint(k, limit=limit, use_trial=use_trial, use_rho=use_rho, use_pm1=use_pm1, verbose=verbose, visual=False) for k, v in d.items(): if k in factordict: factordict[k] += v*e else: factordict[k] = v*e if visual or (type(n) is dict and visual is not True and visual is not False): if factordict == {}: return S.One if -1 in factordict: factordict.pop(-1) args = [S.NegativeOne] else: args = [] args.extend([Pow(*i, evaluate=False) for i in sorted(factordict.items())]) return Mul(*args, evaluate=False) elif isinstance(n, dict) or isinstance(n, Mul): return factordict assert use_trial or use_rho or use_pm1 n = as_int(n) if limit: limit = int(limit) # special cases if n < 0: factors = factorint( -n, limit=limit, use_trial=use_trial, use_rho=use_rho, use_pm1=use_pm1, verbose=verbose, visual=False) factors[-1] = 1 return factors if limit: if limit < 2: if n == 1: return {} return {n: 1} elif n < 10: # doing this we are assured of getting a limit > 2 # when we have to compute it later return [{0: 1}, {}, {2: 1}, {3: 1}, {2: 2}, {5: 1}, {2: 1, 3: 1}, {7: 1}, {2: 3}, {3: 2}][n] factors = {} # do simplistic factorization if verbose: sn = str(n) if len(sn) > 50: print 'Factoring %s' % sn[:5] + \ '..(%i other digits)..' % (len(sn) - 10) + sn[-5:] else: print 'Factoring', n if use_trial: # this is the preliminary factorization for small factors small = 2**15 fail_max = 600 small = min(small, limit or small) if verbose: print trial_int_msg % (2, small, fail_max) n, next_p = _factorint_small(factors, n, small, fail_max) else: next_p = 2 if factors and verbose: for k in sorted(factors): print factor_msg % (k, factors[k]) if next_p == 0: if n > 1: factors[int(n)] = 1 if verbose: print complete_msg return factors # continue with more advanced factorization methods # first check if the simplistic run didn't finish # because of the limit and check for a perfect # power before exiting try: if limit and next_p > limit: if verbose: print 'Exceeded limit:', limit _check_termination(factors, n, limit, use_trial, use_rho, use_pm1, verbose) if n > 1: factors[int(n)] = 1 return factors else: # Before quitting (or continuing on)... # ...do a Fermat test since it's so easy and we need the # square root anyway. Finding 2 factors is easy if they are # "close enough." This is the big root equivalent of dividing by # 2, 3, 5. sqrt_n = integer_nthroot(n, 2)[0] a = sqrt_n + 1 a2 = a**2 b2 = a2 - n for i in range(3): b, fermat = integer_nthroot(b2, 2) if fermat: break b2 += 2*a + 1 # equiv to (a+1)**2 - n a += 1 if fermat: if verbose: print fermat_msg if limit: limit -= 1 for r in [a - b, a + b]: facs = factorint(r, limit=limit, use_trial=use_trial, use_rho=use_rho, use_pm1=use_pm1, verbose=verbose) factors.update(facs) raise StopIteration # ...see if factorization can be terminated _check_termination(factors, n, limit, use_trial, use_rho, use_pm1, verbose) except StopIteration: if verbose: print complete_msg return factors # these are the limits for trial division which will # be attempted in parallel with pollard methods low, high = next_p, 2*next_p limit = limit or sqrt_n # add 1 to make sure limit is reached in primerange calls limit += 1 while 1: try: high_ = high if limit < high_: high_ = limit # Trial division if use_trial: if verbose: print trial_msg % (low, high_) ps = sieve.primerange(low, high_) n, found_trial = _trial(factors, n, ps, verbose) if found_trial: _check_termination(factors, n, limit, use_trial, use_rho, use_pm1, verbose) else: found_trial = False if high > limit: if verbose: print 'Exceeded limit:', limit if n > 1: factors[int(n)] = 1 raise StopIteration # Only used advanced methods when no small factors were found if not found_trial: if (use_pm1 or use_rho): high_root = max(int(math.log(high_**0.7)), low, 3) # Pollard p-1 if use_pm1: if verbose: print (pm1_msg % (high_root, high_)) c = pollard_pm1(n, B=high_root, seed=high_) if c: # factor it and let _trial do the update ps = factorint(c, limit=limit - 1, use_trial=use_trial, use_rho=use_rho, use_pm1=use_pm1, verbose=verbose) n, _ = _trial(factors, n, ps, verbose=False) _check_termination(factors, n, limit, use_trial, use_rho, use_pm1, verbose) # Pollard rho if use_rho: max_steps = high_root if verbose: print (rho_msg % (1, max_steps, high_)) c = pollard_rho(n, retries=1, max_steps=max_steps, seed=high_) if c: # factor it and let _trial do the update ps = factorint(c, limit=limit - 1, use_trial=use_trial, use_rho=use_rho, use_pm1=use_pm1, verbose=verbose) n, _ = _trial(factors, n, ps, verbose=False) _check_termination(factors, n, limit, use_trial, use_rho, use_pm1, verbose) except StopIteration: if verbose: print complete_msg return factors low, high = high, high*2
def perfect_power(n, candidates=None, big=True, factor=True): """ Return ``(b, e)`` such that ``n`` == ``b**e`` if ``n`` is a perfect power; otherwise return ``False``. By default, the base is recursively decomposed and the exponents collected so the largest possible ``e`` is sought. If ``big=False`` then the smallest possible ``e`` (thus prime) will be chosen. If ``candidates`` for exponents are given, they are assumed to be sorted and the first one that is larger than the computed maximum will signal failure for the routine. If ``factor=True`` then simultaneous factorization of n is attempted since finding a factor indicates the only possible root for n. This is True by default since only a few small factors will be tested in the course of searching for the perfect power. Examples ======== >>> from sympy import perfect_power >>> perfect_power(16) (2, 4) >>> perfect_power(16, big = False) (4, 2) """ n = int(n) if n < 3: return False logn = math.log(n, 2) max_possible = int(logn) + 2 # only check values less than this not_square = n % 10 in [2, 3, 7, 8] # squares cannot end in 2, 3, 7, 8 if not candidates: candidates = primerange(2 + not_square, max_possible) afactor = 2 + n % 2 for e in candidates: if e < 3: if e == 1 or e == 2 and not_square: continue if e > max_possible: return False # see if there is a factor present if factor: if n % afactor == 0: # find what the potential power is if afactor == 2: e = trailing(n) else: e = multiplicity(afactor, n) # if it's a trivial power we are done if e == 1: return False # maybe the bth root of n is exact r, exact = integer_nthroot(n, e) if not exact: # then remove this factor and check to see if # any of e's factors are a common exponent; if # not then it's not a perfect power n //= afactor**e m = perfect_power(n, candidates=primefactors(e), big=big) if m is False: return False else: r, m = m # adjust the two exponents so the bases can # be combined g = igcd(m, e) if g == 1: return False m //= g e //= g r, e = r**m*afactor**e, g if not big: e0 = primefactors(e) if len(e0) > 1 or e0[0] != e: e0 = e0[0] r, e = r**(e//e0), e0 return r, e else: # get the next factor ready for the next pass through the loop afactor = nextprime(afactor) # Weed out downright impossible candidates if logn/e < 40: b = 2.0**(logn/e) if abs(int(b + 0.5) - b) > 0.01: continue # now see if the plausible e makes a perfect power r, exact = integer_nthroot(n, e) if exact: if big: m = perfect_power(r, big=big, factor=factor) if m is not False: r, e = m[0], e*m[1] return int(r), e else: return False
def test_integer_nthroot_overflow(): assert integer_nthroot(10**(50*50), 50) == (10**50, True) assert integer_nthroot(10**100000, 10000) == (10**10, True)
def factorint(n, limit=None, use_trial=True, use_rho=True, use_pm1=True, verbose=False, visual=None): r""" Given a positive integer ``n``, ``factorint(n)`` returns a dict containing the prime factors of ``n`` as keys and their respective multiplicities as values. For example: >>> from sympy.ntheory import factorint >>> factorint(2000) # 2000 = (2**4) * (5**3) {2: 4, 5: 3} >>> factorint(65537) # This number is prime {65537: 1} For input less than 2, factorint behaves as follows: - ``factorint(1)`` returns the empty factorization, ``{}`` - ``factorint(0)`` returns ``{0:1}`` - ``factorint(-n)`` adds ``-1:1`` to the factors and then factors ``n`` Partial Factorization: If ``limit`` (> 3) is specified, the search is stopped after performing trial division up to (and including) the limit (or taking a corresponding number of rho/p-1 steps). This is useful if one has a large number and only is interested in finding small factors (if any). Note that setting a limit does not prevent larger factors from being found early; it simply means that the largest factor may be composite. Since checking for perfect power is relatively cheap, it is done regardless of the limit setting. This number, for example, has two small factors and a huge semi-prime factor that cannot be reduced easily: >>> from sympy.ntheory import isprime >>> from sympy.core.compatibility import long >>> a = 1407633717262338957430697921446883 >>> f = factorint(a, limit=10000) >>> f == {991: 1, long(202916782076162456022877024859): 1, 7: 1} True >>> isprime(max(f)) False This number has a small factor and a residual perfect power whose base is greater than the limit: >>> factorint(3*101**7, limit=5) {3: 1, 101: 7} Visual Factorization: If ``visual`` is set to ``True``, then it will return a visual factorization of the integer. For example: >>> from sympy import pprint >>> pprint(factorint(4200, visual=True)) 3 1 2 1 2 *3 *5 *7 Note that this is achieved by using the evaluate=False flag in Mul and Pow. If you do other manipulations with an expression where evaluate=False, it may evaluate. Therefore, you should use the visual option only for visualization, and use the normal dictionary returned by visual=False if you want to perform operations on the factors. You can easily switch between the two forms by sending them back to factorint: >>> from sympy import Mul, Pow >>> regular = factorint(1764); regular {2: 2, 3: 2, 7: 2} >>> pprint(factorint(regular)) 2 2 2 2 *3 *7 >>> visual = factorint(1764, visual=True); pprint(visual) 2 2 2 2 *3 *7 >>> print(factorint(visual)) {2: 2, 3: 2, 7: 2} If you want to send a number to be factored in a partially factored form you can do so with a dictionary or unevaluated expression: >>> factorint(factorint({4: 2, 12: 3})) # twice to toggle to dict form {2: 10, 3: 3} >>> factorint(Mul(4, 12, evaluate=False)) {2: 4, 3: 1} The table of the output logic is: ====== ====== ======= ======= Visual ------ ---------------------- Input True False other ====== ====== ======= ======= dict mul dict mul n mul dict dict mul mul dict dict ====== ====== ======= ======= Notes ===== Algorithm: The function switches between multiple algorithms. Trial division quickly finds small factors (of the order 1-5 digits), and finds all large factors if given enough time. The Pollard rho and p-1 algorithms are used to find large factors ahead of time; they will often find factors of the order of 10 digits within a few seconds: >>> factors = factorint(12345678910111213141516) >>> for base, exp in sorted(factors.items()): ... print('%s %s' % (base, exp)) ... 2 2 2507191691 1 1231026625769 1 Any of these methods can optionally be disabled with the following boolean parameters: - ``use_trial``: Toggle use of trial division - ``use_rho``: Toggle use of Pollard's rho method - ``use_pm1``: Toggle use of Pollard's p-1 method ``factorint`` also periodically checks if the remaining part is a prime number or a perfect power, and in those cases stops. If ``verbose`` is set to ``True``, detailed progress is printed. See Also ======== smoothness, smoothness_p, divisors """ factordict = {} if visual and not isinstance(n, Mul) and not isinstance(n, dict): factordict = factorint(n, limit=limit, use_trial=use_trial, use_rho=use_rho, use_pm1=use_pm1, verbose=verbose, visual=False) elif isinstance(n, Mul): factordict = dict([(int(k), int(v)) for k, v in list(n.as_powers_dict().items())]) elif isinstance(n, dict): factordict = n if factordict and (isinstance(n, Mul) or isinstance(n, dict)): # check it for k in list(factordict.keys()): if isprime(k): continue e = factordict.pop(k) d = factorint(k, limit=limit, use_trial=use_trial, use_rho=use_rho, use_pm1=use_pm1, verbose=verbose, visual=False) for k, v in d.items(): if k in factordict: factordict[k] += v * e else: factordict[k] = v * e if visual or (type(n) is dict and visual is not True and visual is not False): if factordict == {}: return S.One if -1 in factordict: factordict.pop(-1) args = [S.NegativeOne] else: args = [] args.extend( [Pow(*i, evaluate=False) for i in sorted(factordict.items())]) return Mul(*args, evaluate=False) elif isinstance(n, dict) or isinstance(n, Mul): return factordict assert use_trial or use_rho or use_pm1 n = as_int(n) if limit: limit = int(limit) # special cases if n < 0: factors = factorint(-n, limit=limit, use_trial=use_trial, use_rho=use_rho, use_pm1=use_pm1, verbose=verbose, visual=False) factors[-1] = 1 return factors if limit and limit < 2: if n == 1: return {} return {n: 1} elif n < 10: # doing this we are assured of getting a limit > 2 # when we have to compute it later return [{ 0: 1 }, {}, { 2: 1 }, { 3: 1 }, { 2: 2 }, { 5: 1 }, { 2: 1, 3: 1 }, { 7: 1 }, { 2: 3 }, { 3: 2 }][n] factors = {} # do simplistic factorization if verbose: sn = str(n) if len(sn) > 50: print('Factoring %s' % sn[:5] + \ '..(%i other digits)..' % (len(sn) - 10) + sn[-5:]) else: print('Factoring', n) if use_trial: # this is the preliminary factorization for small factors small = 2**15 fail_max = 600 small = min(small, limit or small) if verbose: print(trial_int_msg % (2, small, fail_max)) n, next_p = _factorint_small(factors, n, small, fail_max) else: next_p = 2 if factors and verbose: for k in sorted(factors): print(factor_msg % (k, factors[k])) if next_p == 0: if n > 1: factors[int(n)] = 1 if verbose: print(complete_msg) return factors # continue with more advanced factorization methods # first check if the simplistic run didn't finish # because of the limit and check for a perfect # power before exiting try: if limit and next_p > limit: if verbose: print('Exceeded limit:', limit) _check_termination(factors, n, limit, use_trial, use_rho, use_pm1, verbose) if n > 1: factors[int(n)] = 1 return factors else: # Before quitting (or continuing on)... # ...do a Fermat test since it's so easy and we need the # square root anyway. Finding 2 factors is easy if they are # "close enough." This is the big root equivalent of dividing by # 2, 3, 5. sqrt_n = integer_nthroot(n, 2)[0] a = sqrt_n + 1 a2 = a**2 b2 = a2 - n for i in range(3): b, fermat = integer_nthroot(b2, 2) if fermat: break b2 += 2 * a + 1 # equiv to (a+1)**2 - n a += 1 if fermat: if verbose: print(fermat_msg) if limit: limit -= 1 for r in [a - b, a + b]: facs = factorint(r, limit=limit, use_trial=use_trial, use_rho=use_rho, use_pm1=use_pm1, verbose=verbose) factors.update(facs) raise StopIteration # ...see if factorization can be terminated _check_termination(factors, n, limit, use_trial, use_rho, use_pm1, verbose) except StopIteration: if verbose: print(complete_msg) return factors # these are the limits for trial division which will # be attempted in parallel with pollard methods low, high = next_p, 2 * next_p limit = limit or sqrt_n # add 1 to make sure limit is reached in primerange calls limit += 1 while 1: try: high_ = high if limit < high_: high_ = limit # Trial division if use_trial: if verbose: print(trial_msg % (low, high_)) ps = sieve.primerange(low, high_) n, found_trial = _trial(factors, n, ps, verbose) if found_trial: _check_termination(factors, n, limit, use_trial, use_rho, use_pm1, verbose) else: found_trial = False if high > limit: if verbose: print('Exceeded limit:', limit) if n > 1: factors[int(n)] = 1 raise StopIteration # Only used advanced methods when no small factors were found if not found_trial: if (use_pm1 or use_rho): high_root = max(int(math.log(high_**0.7)), low, 3) # Pollard p-1 if use_pm1: if verbose: print(pm1_msg % (high_root, high_)) c = pollard_pm1(n, B=high_root, seed=high_) if c: # factor it and let _trial do the update ps = factorint(c, limit=limit - 1, use_trial=use_trial, use_rho=use_rho, use_pm1=use_pm1, verbose=verbose) n, _ = _trial(factors, n, ps, verbose=False) _check_termination(factors, n, limit, use_trial, use_rho, use_pm1, verbose) # Pollard rho if use_rho: max_steps = high_root if verbose: print(rho_msg % (1, max_steps, high_)) c = pollard_rho(n, retries=1, max_steps=max_steps, seed=high_) if c: # factor it and let _trial do the update ps = factorint(c, limit=limit - 1, use_trial=use_trial, use_rho=use_rho, use_pm1=use_pm1, verbose=verbose) n, _ = _trial(factors, n, ps, verbose=False) _check_termination(factors, n, limit, use_trial, use_rho, use_pm1, verbose) except StopIteration: if verbose: print(complete_msg) return factors low, high = high, high * 2
def test_issue_14704(): a = 144**144 x, xexact = integer_nthroot(a, a) assert x == 1 and xexact is False
def is_square(n, prep=True): """Return True if n == a * a for some integer a, else False. If n is suspected of *not* being a square then this is a quick method of confirming that it is not. Examples ======== >>> from sympy.ntheory.primetest import is_square >>> is_square(25) True >>> is_square(2) False References ========== .. [1] http://mersenneforum.org/showpost.php?p=110896 See Also ======== sympy.core.power.integer_nthroot """ if prep: n = as_int(n) if n < 0: return False if n in (0, 1): return True # def magic(n): # s = {x**2 % n for x in range(n)} # return sum(1 << bit for bit in s) # >>> print(hex(magic(128))) # 0x2020212020202130202021202030213 # >>> print(hex(magic(99))) # 0x209060049048220348a410213 # >>> print(hex(magic(91))) # 0x102e403012a0c9862c14213 # >>> print(hex(magic(85))) # 0x121065188e001c46298213 if not 0x2020212020202130202021202030213 & (1 << (n & 127)): return False # e.g. 2, 3 m = n % (99 * 91 * 85) if not 0x209060049048220348a410213 & (1 << (m % 99)): return False # e.g. 17, 68 if not 0x102e403012a0c9862c14213 & (1 << (m % 91)): return False # e.g. 97, 388 if not 0x121065188e001c46298213 & (1 << (m % 85)): return False # e.g. 793, 1408 # n is either: # a) odd = 4*even + 1 (and square if even = k*(k + 1)) # b) even with # odd multiplicity of 2 --> not square, e.g. 39040 # even multiplicity of 2, e.g. 4, 16, 36, ..., 16324 # removal of factors of 2 to give an odd, and rejection if # any(i%2 for i in divmod(odd - 1, 4)) # will give an odd number in form 4*even + 1. # Use of `trailing` to check the power of 2 is not done since it # does not apply to a large percentage of arbitrary numbers # and the integer_nthroot is able to quickly resolve these cases. return integer_nthroot(n, 2)[1]
def perfect_power(n, candidates=None, big=True, factor=True): """ Return ``(a, b)`` such that ``n`` == ``a**b`` if ``n`` is a perfect power; otherwise return ``None``. By default, the base is recursively decomposed and the exponents collected so the largest possible ``b`` is sought. If ``big=False`` then the smallest possible ``b`` (thus prime) will be chosen. If ``candidates`` are given, they are assumed to be sorted and the first one that is larger than the computed maximum will signal failure for the routine. If ``factor=True`` then simultaneous factorization of n is attempted since finding a factor indicates the only possible root for n. """ n = int(n) if n < 3: return None logn = math.log(n, 2) max_possible = int(logn) + 2 # only check values less than this not_square = n % 10 in [2, 3, 7, 8] # squares cannot end in 2, 3, 7, 8 if not candidates: candidates = primerange(2 + not_square, max_possible) afactor = 2 + n % 2 for b in candidates: if b < 3: if b == 1 or b == 2 and not_square: continue if b > max_possible: return # see if there is a factor present if factor: if n % afactor == 0: # find what the potential power is if afactor == 2: b = trailing(n) else: b = multiplicity(afactor, n) # if it's a trivial power we are done if b == 1: return # maybe the bth root of n is exact r, exact = integer_nthroot(n, b) if not exact: # then remove this factor and check to see if # any of b's factors are a common exponent; if # not then it's not a perfect power n //= afactor**b m = perfect_power(n, candidates=primefactors(b), big=big) if not m: return else: r, m = m # adjust the two exponents so the bases can # be combined g = igcd(m, b) m //= g b //= g r, b = r**m * afactor**b, g if not big: b0 = primefactors(b) if len(b0) > 1 or b0[0] != b: b0 = b0[0] r, b = r**(b // b0), b0 return r, b else: # get the next factor ready for the next pass through the loop afactor = nextprime(afactor) # Weed out downright impossible candidates if logn / b < 40: a = 2.0**(logn / b) if abs(int(a + 0.5) - a) > 0.01: continue # now see if the plausible b makes a perfect power r, exact = integer_nthroot(n, b) if exact: if big: m = perfect_power(r, big=big, factor=factor) if m: r, b = m[0], b * m[1] return int(r), b
def perfect_power(n, candidates=None, big=True, factor=True): """ Return ``(b, e)`` such that ``n`` == ``b**e`` if ``n`` is a perfect power; otherwise return ``False``. By default, the base is recursively decomposed and the exponents collected so the largest possible ``e`` is sought. If ``big=False`` then the smallest possible ``e`` (thus prime) will be chosen. If ``candidates`` for exponents are given, they are assumed to be sorted and the first one that is larger than the computed maximum will signal failure for the routine. If ``factor=True`` then simultaneous factorization of n is attempted since finding a factor indicates the only possible root for n. This is True by default since only a few small factors will be tested in the course of searching for the perfect power. Examples ======== >>> from sympy import perfect_power >>> perfect_power(16) (2, 4) >>> perfect_power(16, big = False) (4, 2) """ n = int(n) if n < 3: return False logn = math.log(n, 2) max_possible = int(logn) + 2 # only check values less than this not_square = n % 10 in [2, 3, 7, 8] # squares cannot end in 2, 3, 7, 8 if not candidates: candidates = primerange(2 + not_square, max_possible) afactor = 2 + n % 2 for e in candidates: if e < 3: if e == 1 or e == 2 and not_square: continue if e > max_possible: return False # see if there is a factor present if factor: if n % afactor == 0: # find what the potential power is if afactor == 2: e = trailing(n) else: e = multiplicity(afactor, n) # if it's a trivial power we are done if e == 1: return False # maybe the bth root of n is exact r, exact = integer_nthroot(n, e) if not exact: # then remove this factor and check to see if # any of e's factors are a common exponent; if # not then it's not a perfect power n //= afactor**e m = perfect_power(n, candidates=primefactors(e), big=big) if m is False: return False else: r, m = m # adjust the two exponents so the bases can # be combined g = igcd(m, e) if g == 1: return False m //= g e //= g r, e = r**m * afactor**e, g if not big: e0 = primefactors(e) if len(e0) > 1 or e0[0] != e: e0 = e0[0] r, e = r**(e // e0), e0 return r, e else: # get the next factor ready for the next pass through the loop afactor = nextprime(afactor) # Weed out downright impossible candidates if logn / e < 40: b = 2.0**(logn / e) if abs(int(b + 0.5) - b) > 0.01: continue # now see if the plausible e makes a perfect power r, exact = integer_nthroot(n, e) if exact: if big: m = perfect_power(r, big=big, factor=factor) if m is not False: r, e = m[0], e * m[1] return int(r), e else: return False
def test_powers(): assert integer_nthroot(1, 2) == (1, True) assert integer_nthroot(1, 5) == (1, True) assert integer_nthroot(2, 1) == (2, True) assert integer_nthroot(2, 2) == (1, False) assert integer_nthroot(2, 5) == (1, False) assert integer_nthroot(4, 2) == (2, True) assert integer_nthroot(123**25, 25) == (123, True) assert integer_nthroot(123**25+1, 25) == (123, False) assert integer_nthroot(123**25-1, 25) == (122, False) assert integer_nthroot(1,1) == (1, True) assert integer_nthroot(0,1) == (0, True) assert integer_nthroot(0,3) == (0, True) assert integer_nthroot(10000, 1) == (10000, True) assert integer_nthroot(4,2) == (2, True) assert integer_nthroot(16,2) == (4, True) assert integer_nthroot(26,2) == (5, False) assert integer_nthroot(1234567**7, 7) == (1234567, True) assert integer_nthroot(1234567**7+1, 7) == (1234567, False) assert integer_nthroot(1234567**7-1, 7) == (1234566, False) b = 25**1000 assert integer_nthroot(b, 1000) == (25, True) assert integer_nthroot(b+1, 1000) == (25, False) assert integer_nthroot(b-1, 1000) == (24, False) c = 10**400 c2 = c**2 assert integer_nthroot(c2, 2) == (c, True) assert integer_nthroot(c2+1, 2) == (c, False) assert integer_nthroot(c2-1, 2) == (c-1, False) assert Rational(5**3, 8**3)**Rational(4,3) == Rational(5**4, 8**4) assert Rational(-4,7)**Rational(1,2) == I*Rational(4,7)**Rational(1,2) assert sqrt(6) + sqrt(24) == 3*sqrt(6) assert sqrt(2) * sqrt(3) == sqrt(6) x = Symbol("x") assert sqrt(49*x) == 7*sqrt(x) assert sqrt((3-sqrt(pi))**2) == 3 - sqrt(pi) assert sqrt(Rational(1,2)) == Rational(1,2) * sqrt(2) # Test that this is fast assert integer_nthroot(2,10**10) == (1, False)
def test_powers(): assert integer_nthroot(1, 2) == (1, True) assert integer_nthroot(1, 5) == (1, True) assert integer_nthroot(2, 1) == (2, True) assert integer_nthroot(2, 2) == (1, False) assert integer_nthroot(2, 5) == (1, False) assert integer_nthroot(4, 2) == (2, True) assert integer_nthroot(123**25, 25) == (123, True) assert integer_nthroot(123**25 + 1, 25) == (123, False) assert integer_nthroot(123**25 - 1, 25) == (122, False) assert integer_nthroot(1, 1) == (1, True) assert integer_nthroot(0, 1) == (0, True) assert integer_nthroot(0, 3) == (0, True) assert integer_nthroot(10000, 1) == (10000, True) assert integer_nthroot(4, 2) == (2, True) assert integer_nthroot(16, 2) == (4, True) assert integer_nthroot(26, 2) == (5, False) assert integer_nthroot(1234567**7, 7) == (1234567, True) assert integer_nthroot(1234567**7 + 1, 7) == (1234567, False) assert integer_nthroot(1234567**7 - 1, 7) == (1234566, False) b = 25**1000 assert integer_nthroot(b, 1000) == (25, True) assert integer_nthroot(b + 1, 1000) == (25, False) assert integer_nthroot(b - 1, 1000) == (24, False) c = 10**400 c2 = c**2 assert integer_nthroot(c2, 2) == (c, True) assert integer_nthroot(c2 + 1, 2) == (c, False) assert integer_nthroot(c2 - 1, 2) == (c - 1, False) assert integer_nthroot(2, 10**10) == (1, False) p, r = integer_nthroot(int(factorial(10000)), 100) assert p % (10**10) == 5322420655 assert not r # Test that this is fast assert integer_nthroot(2, 10**10) == (1, False)
def perfect_power(n, candidates=None, big=True, factor=True): """ Return ``(a, b)`` such that ``n`` == ``a**b`` if ``n`` is a perfect power; otherwise return ``None``. By default, the base is recursively decomposed and the exponents collected so the largest possible ``b`` is sought. If ``big=False`` then the smallest possible ``b`` (thus prime) will be chosen. If ``candidates`` are given, they are assumed to be sorted and the first one that is larger than the computed maximum will signal failure for the routine. If ``factor=True`` then simultaneous factorization of n is attempted since finding a factor indicates the only possible root for n. """ n = int(n) if n < 3: return None logn = math.log(n, 2) max_possible = int(logn) + 2 # only check values less than this not_square = n % 10 in [2, 3, 7, 8] # squares cannot end in 2, 3, 7, 8 if not candidates: candidates = primerange(2 + not_square, max_possible) afactor = 2 + n % 2 for b in candidates: if b < 3: if b == 1 or b == 2 and not_square: continue if b > max_possible: return # see if there is a factor present if factor: if n % afactor == 0: # find what the potential power is if afactor == 2: b = trailing(n) else: b = multiplicity(afactor, n) # if it's a trivial power we are done if b == 1: return # maybe the bth root of n is exact r, exact = integer_nthroot(n, b) if not exact: # then remove this factor and check to see if # any of b's factors are a common exponent; if # not then it's not a perfect power n //= afactor**b m = perfect_power(n, candidates=primefactors(b), big=big) if not m: return else: r, m = m # adjust the two exponents so the bases can # be combined g = igcd(m, b) m //= g b //= g r, b = r**m*afactor**b, g if not big: b0 = primefactors(b) if len(b0) > 1 or b0[0] != b: b0 = b0[0] r, b = r**(b//b0), b0 return r, b else: # get the next factor ready for the next pass through the loop afactor = nextprime(afactor) # Weed out downright impossible candidates if logn/b < 40: a = 2.0**(logn/b) if abs(int(a + 0.5) - a) > 0.01: continue # now see if the plausible b makes a perfect power r, exact = integer_nthroot(n, b) if exact: if big: m = perfect_power(r, big=big, factor=factor) if m: r, b = m[0], b*m[1] return int(r), b
def test_powers(): assert integer_nthroot(1, 2) == (1, True) assert integer_nthroot(1, 5) == (1, True) assert integer_nthroot(2, 1) == (2, True) assert integer_nthroot(2, 2) == (1, False) assert integer_nthroot(2, 5) == (1, False) assert integer_nthroot(4, 2) == (2, True) assert integer_nthroot(123**25, 25) == (123, True) assert integer_nthroot(123**25+1, 25) == (123, False) assert integer_nthroot(123**25-1, 25) == (122, False) assert integer_nthroot(1,1) == (1, True) assert integer_nthroot(0,1) == (0, True) assert integer_nthroot(0,3) == (0, True) assert integer_nthroot(10000, 1) == (10000, True) assert integer_nthroot(4,2) == (2, True) assert integer_nthroot(16,2) == (4, True) assert integer_nthroot(26,2) == (5, False) assert integer_nthroot(1234567**7, 7) == (1234567, True) assert integer_nthroot(1234567**7+1, 7) == (1234567, False) assert integer_nthroot(1234567**7-1, 7) == (1234566, False) b = 25**1000 assert integer_nthroot(b, 1000) == (25, True) assert integer_nthroot(b+1, 1000) == (25, False) assert integer_nthroot(b-1, 1000) == (24, False) c = 10**400 c2 = c**2 assert integer_nthroot(c2, 2) == (c, True) assert integer_nthroot(c2+1, 2) == (c, False) assert integer_nthroot(c2-1, 2) == (c-1, False) assert integer_nthroot(2,10**10) == (1, False) p, r = integer_nthroot(int(factorial(10000)), 100) assert p % (10**10) == 5322420655 assert not r # Test that this is fast assert integer_nthroot(2,10**10) == (1, False)
def test_powers(): assert integer_nthroot(1, 2) == (1, True) assert integer_nthroot(1, 5) == (1, True) assert integer_nthroot(2, 1) == (2, True) assert integer_nthroot(2, 2) == (1, False) assert integer_nthroot(2, 5) == (1, False) assert integer_nthroot(4, 2) == (2, True) assert integer_nthroot(123**25, 25) == (123, True) assert integer_nthroot(123**25 + 1, 25) == (123, False) assert integer_nthroot(123**25 - 1, 25) == (122, False) assert integer_nthroot(1, 1) == (1, True) assert integer_nthroot(0, 1) == (0, True) assert integer_nthroot(0, 3) == (0, True) assert integer_nthroot(10000, 1) == (10000, True) assert integer_nthroot(4, 2) == (2, True) assert integer_nthroot(16, 2) == (4, True) assert integer_nthroot(26, 2) == (5, False) assert integer_nthroot(1234567**7, 7) == (1234567, True) assert integer_nthroot(1234567**7 + 1, 7) == (1234567, False) assert integer_nthroot(1234567**7 - 1, 7) == (1234566, False) b = 25**1000 assert integer_nthroot(b, 1000) == (25, True) assert integer_nthroot(b + 1, 1000) == (25, False) assert integer_nthroot(b - 1, 1000) == (24, False) c = 10**400 c2 = c**2 assert integer_nthroot(c2, 2) == (c, True) assert integer_nthroot(c2 + 1, 2) == (c, False) assert integer_nthroot(c2 - 1, 2) == (c - 1, False) assert Rational(5**3, 8**3)**Rational(4, 3) == Rational(5**4, 8**4) assert Rational(-4, 7)**Rational(1, 2) == I * Rational(4, 7)**Rational(1, 2) assert sqrt(6) + sqrt(24) == 3 * sqrt(6) assert sqrt(2) * sqrt(3) == sqrt(6) x = Symbol("x") assert sqrt(49 * x) == 7 * sqrt(x) assert sqrt((3 - sqrt(pi))**2) == 3 - sqrt(pi) assert sqrt(Rational(1, 2)) == Rational(1, 2) * sqrt(2) # Test that this is fast assert integer_nthroot(2, 10**10) == (1, False)