def is_a000290(n): """Determine whether a non-negative integer is a perfect square. Algorithm: Cohen, p. 40. Examples of use: >>> is_a000290(10 ** 100) True >>> is_a000290(10 ** 100 + 1) False """ def build_residues(m): t = [0] * m for k in range((m + 1) // 2): t[k**2 % m] = 1 return tuple(t) if not isinstance(n, int): raise ValueError(f'{n} is not an integer') if n < 0: return False if n == 0: return True # First time, precompute and store quadratic residues for selected moduli. if not hasattr(is_a000290, 'Q64'): is_a000290.Q64 = build_residues(64) is_a000290.Q135 = build_residues(135) is_a000290.Q143 = build_residues(143) is_a000290.Q119 = build_residues(119) # If n is a quadratic nonresidue for a given modulus, it cannot be a square. if not is_a000290.Q64[n % 64]: return False r = n % (135 * 143 * 119) if not ( is_a000290.Q135[r % 135] and is_a000290.Q143[r % 143] and is_a000290.Q119[r % 119] ): return False # Use a variant of Newton's method to calculate the integer part of sqrt(n), # then check whether the square of that number equals n. x = 2 ** sum(divmod(n.bit_length(), 2)) while True: y = (x + (n // x)) // 2 if y >= x: return x**2 == n x = y