Exemple #1
0
def cornacchiamodify(d, p):
    """
    Algorithm 26 (Modified cornacchia)
    Input : p be a prime and d be an integer such that d < 0 and d > -4p with
            d = 0, 1 (mod 4)
    Output : the solution of u^2 -d * v^2 = 4p.
    """
    q = 4 * p
    if (d >= 0) or (d <= -q):
        raise ValueError("invalid input")
    if p == 2:
        b = arith1.issquare(d + 8)
        if b:
            return (b, 1)
        else:
            raise ValueError("no solution")
    if arith1.legendre(d, p) == -1:
        raise ValueError("no solution")
    x0 = arith1.modsqrt(d, p)
    if (x0 - d) % 2 != 0:
        x0 = p - x0
    a = 2 * p
    b = x0
    l = arith1.floorsqrt(q)
    while b > l:
        a, b = b, a % b
    c, r = divmod(q - b * b, -d)
    if r:
        raise ValueError("no solution")
    t = arith1.issquare(c)
    if t:
        return (b, t)
    else:
        raise ValueError("no solution")
Exemple #2
0
def cornacchiamodify(d, p):
    """
    Algorithm 26 (Modified cornacchia)
    Input : p be a prime and d be an integer such that d < 0 and d > -4p with
            d = 0, 1 (mod 4)
    Output : the solution of u^2 -d * v^2 = 4p.
    """
    q = 4 * p
    if (d >= 0) or (d <= -q):
        raise ValueError("invalid input")
    if p == 2:
        b = arith1.issquare(d + 8)
        if b:
            return (b, 1)
        else:
            raise ValueError("no solution")
    if arith1.legendre(d, p) == -1:
        raise ValueError("no solution")
    x0 = arith1.modsqrt(d, p)
    if (x0 - d) & 1:
        x0 = p - x0
    a = 2 * p
    b = x0
    l = arith1.floorsqrt(q)
    while b > l:
        a, b = b, a % b
    c, r = divmod(q - b * b, -d)
    if r:
        raise ValueError("no solution")
    t = arith1.issquare(c)
    if t:
        return (b, t)
    else:
        raise ValueError("no solution")
Exemple #3
0
def cornacchia(d, p):
    """
    Return the solution of x^2 + d * y^2 = p .
    p be a prime and d be an integer such that 0 < d < p.
    """
    if (d <= 0) or (d >= p):
        raise ValueError("invalid input")
    k = arith1.legendre(-d, p)
    if k == -1:
        raise ValueError("no solution")
    x0 = arith1.modsqrt(-d, p)
    if x0 < (p / 2):
        x0 = p - x0
    a = p
    b = x0
    l = arith1.floorsqrt(p)
    while b > l:
        a, b = b, a % b
    c, r = divmod(p - b * b, d)
    if r:
        raise ValueError("no solution")
    t = arith1.issquare(c)
    if t == 0:
        raise ValueError("no solution")
    else:
        return (b, t)
def cornacchia(d, p):
    """
    Return the solution of x^2 + d * y^2 = p .
    p be a prime and d be an integer such that 0 < d < p.
    """
    if (d <= 0) or (d >= p):
        raise ValueError("invalid input")
    k = arith1.legendre(-d, p)
    if k == -1:
        raise ValueError("no solution")
    x0 = arith1.modsqrt(-d, p)
    if x0 < (p / 2):
        x0 = p - x0
    a = p
    b = x0
    l = arith1.floorsqrt(p)
    while b > l:
        a, b = b, a % b
    c, r = divmod(p - b * b, d)
    if r:
        raise ValueError("no solution")
    t = arith1.issquare(c)
    if t == 0:
        raise ValueError("no solution")
    else:
        return (b, t)
def _lucas_test_sequence(n, a, b):
    """
    Return x_0, x_1, x_m, x_{m+1} of Lucas sequence of parameter a, b,
    where m = (n - (a**2 - 4*b / n)) // 2.
    """
    d = a**2 - 4 * b
    if (d >= 0 and arith1.issquare(d) or not (gcd.coprime(n, 2 * a * b * d))):
        raise ValueError("Choose another parameters.")

    x_0 = 2
    inv_b = arith1.inverse(b, n)
    x_1 = ((a**2) * inv_b - 2) % n

    # Chain functions
    def even_step(u):
        """
        'double' u.
        """
        return (u**2 - x_0) % n

    def odd_step(u, v):
        """
        'add' u and v.
        """
        return (u * v - x_1) % n

    m = (n - arith1.legendre(d, n)) // 2
    x_m, x_mplus1 = _lucas_chain(m, even_step, odd_step, x_0, x_1)

    return x_0, x_1, x_m, x_mplus1
Exemple #6
0
 def testIssquare(self):
     self.assertTrue(arith1.issquare(1))
     self.assertEqual(1, arith1.issquare(1))
     self.assertTrue(arith1.issquare(289))
     self.assertEqual(17, arith1.issquare(289))
     self.assertFalse(arith1.issquare(2))
     self.assertEqual(0, arith1.issquare(2))
     self.assertFalse(arith1.issquare(0))
     self.assertEqual(0, arith1.issquare(0))
Exemple #7
0
def trivial_test(n):
    """
    Test whether n is squarefree or not.

    This method do anything but factorization.
    """
    if n == 1 or n == 2:
        return True
    if arith1.issquare(n):
        return False
    if n & 1:
        return lenstra(n)
    elif not (n & 3):
        return False
    raise Undetermined("trivial test can't determine squarefreeness")
Exemple #8
0
def trivial_test(n):
    """
    Test whether n is squarefree or not.

    This method do anything but factorization.
    """
    if n == 1 or n == 2:
        return True
    if arith1.issquare(n):
        return False
    if n & 1:
        return lenstra(n)
    elif not (n % 4):
        return False
    raise Undetermined("trivial test can't determine squarefreeness")
Exemple #9
0
def trivial_test_ternary(n):
    """
    Test the squarefreeness of n.
    The return value is one of the ternary logical constants.

    The method uses a series of trivial tests.
    """
    if n == 1 or n == 2:
        return True
    if arith1.issquare(n):
        return False
    if n & 1:
        return lenstra_ternary(n)
    elif not (n & 3):
        return False
    return None
Exemple #10
0
def gen_discriminant(start=0):
    # really should consider generating list of discriminants
    # find a fundamental discriminant. Use start as a starting point.
    d = start
    # compute the odd part
    d_found = False
    while not d_found:
        '''find the next fundamental discriminant'''
        d -= 1
        odd = odd_part(-d)
        # check if the odd part is square free.
        if issquare(odd) not in {0, 1}:
            continue
        if not ((-d) % 16 in {3, 4, 7, 8, 11, 15}):
            continue
        return d
Exemple #11
0
def next_disc(d, absbound):
    """
    Return fundamental discriminant D, such that D < d.
    If there is no D with |d| < |D| < absbound, return False
    """
    # -disc % 16
    negdisc_mod16 = (3, 4, 7, 8, 11, 15)
    for negdisc in bigrange.range(-d + 1, absbound):
        if negdisc & 15 not in negdisc_mod16:
            continue
        if negdisc & 1 and not squarefree.trial_division(negdisc):
            continue
        if arith1.issquare(negdisc):
            continue
        return -negdisc
    return False
Exemple #12
0
def next_disc(d, absbound):
    """
    Return fundamental discriminant D, such that D < d.
    If there is no D with |d| < |D| < absbound, return False
    """
    # -disc % 16
    negdisc_mod16 = (3, 4, 7, 8, 11, 15)
    for negdisc in bigrange.range(-d + 1, absbound):
        if negdisc % 16 not in negdisc_mod16:
            continue
        if negdisc % 2 == 1 and not squarefree.trial_division(negdisc):
            continue
        if arith1.issquare(negdisc):
            continue
        return -negdisc
    return False
Exemple #13
0
def trivial_test_ternary(n):
    """
    Test the squarefreeness of n.
    The return value is one of the ternary logical constants.

    The method uses a series of trivial tests.
    """
    if n == 1 or n == 2:
        return True
    if arith1.issquare(n):
        return False
    if n & 1:
        return lenstra_ternary(n)
    elif not (n % 4):
        return False
    return None
Exemple #14
0
    def generate(self, target, **options):
        """
        Generate squarefree factors of the target number with their
        valuations.  The method may terminate with yielding (1, 1)
        to indicate the factorization is incomplete.

        If a keyword option 'strict' is False (default to True),
        factorization will stop after the first square factor no
        matter whether it is squarefree or not.
        """
        strict = options.get('strict', True)
        options['n'] = target
        primeseq = self._parse_seq(options)
        for p in primeseq:
            if not (target % p):
                e, target = arith1.vp(target, p)
                yield p, e
                if target == 1:
                    break
                elif e > 1 and not strict:
                    yield 1, 1
                    break
                elif trivial_test_ternary(target):
                    # the factor remained is squarefree.
                    yield target, 1
                    break
                q, e = factor_misc.primePowerTest(target)
                if e:
                    yield q, e
                    break
                sqrt = arith1.issquare(target)
                if sqrt:
                    if strict:
                        for q, e in self.factor(sqrt, iterator=primeseq):
                            yield q, 2 * e
                    else:
                        yield sqrt, 2
                    break
            if p ** 3 > target:
                # there are no more square factors of target,
                # thus target is squarefree
                yield target, 1
                break
        else:
            # primeseq is exhausted but target has not been proven prime
            yield 1, 1
Exemple #15
0
    def generate(self, target, **options):
        """
        Generate squarefree factors of the target number with their
        valuations.  The method may terminate with yielding (1, 1)
        to indicate the factorization is incomplete.

        If a keyword option 'strict' is False (default to True),
        factorization will stop after the first square factor no
        matter whether it is squarefree or not.
        """
        strict = options.get('strict', True)
        options['n'] = target
        primeseq = self._parse_seq(options)
        for p in primeseq:
            if not (target % p):
                e, target = arith1.vp(target, p)
                yield p, e
                if target == 1:
                    break
                elif e > 1 and not strict:
                    yield 1, 1
                    break
                elif trivial_test_ternary(target):
                    # the factor remained is squarefree.
                    yield target, 1
                    break
                q, e = factor_misc.primePowerTest(target)
                if e:
                    yield q, e
                    break
                sqrt = arith1.issquare(target)
                if sqrt:
                    if strict:
                        for q, e in self.factor(sqrt, iterator=primeseq):
                            yield q, 2 * e
                    else:
                        yield sqrt, 2
                    break
            if p ** 3 > target:
                # there are no more square factors of target,
                # thus target is squarefree
                yield target, 1
                break
        else:
            # primeseq is exhausted but target has not been proven prime
            yield 1, 1
Exemple #16
0
def cornacchia_smith(p, d):
    '''
    modified Cornacchia's Algorithm to solve a^2 + b^2 |D| = 4p for a and b
    Args:
        p:
        d:

    Returns:
        a, b such that a^2 + b^2 |D| = 4p

    '''
    # check input
    if not -4 * p < d < 0:
        raise ValueError(" -4p < D < 0 not true.")
    elif not (d % 4 in {0, 1}):
        raise ValueError(" D = 0, 1 (mod 4) not true.")

    # case where p=2
    if p == 2:
        r = sqrt(d + 8)
        if r != -1:
            return r, 1
        else:
            return None
    # test for solvability
    if jacobi(d % p, p) < 1:
        return None

    x = modsqrt(d, p)
    if (x % 2) != (d % 2):
        x = p - x
    # euclid chain
    a, b = (2 * p, x)
    c = floorsqrt(4 * p)
    while b > c:
        a, b = b, a % b

    t = 4 * p - b * b
    if t % (-d) != 0:
        return None
    if not issquare(t / (-d)):
        return None
    return b, int(mpmath.sqrt(t / -d))