close

#Question 1 - Primes
# Write a function to determine whether a given number is prime or not (divisible only by itself and 1). Use the Wikipedia definition of a prime number (https://en.wikipedia.org/wiki/Prime_number) as a reference.
#


def witness_loop_xl(n, k, r, d):
    # WitnessLoop: repeat k times:
    while k > 0:
        # pick a random integer a in the range [2, n - 2]
        a = random.randint(2, n - 2)
        # x <- a^d mod n
        x = pow(a, d, n)
        # if x = 1 or x = n - 1 then do next WitnessLoop
        if x != 1 and x != n - 1:
            do_next = False
            # repeat r - 1 times:
            for i in xrange(1, r):
                # x <- x^2 mod n
                x = pow(x, 2, n)
                # if x = 1 then return composite
                if x == 1:
                    return False
                # if x = n - 1 then do next WitnessLoop
                elif x == n - 1:
                    do_next = True
                    break
            # return composite
            if not do_next:
                return False
        k -= 1

    # return probably prime
    return True


def witness_loop(n, k, r, d):
    # WitnessLoop: repeat k times:
    # pick a random integer a in the range [2, n - 2]
    for a in random.sample(xrange(2, n - 1), min(k, n - 3)):
        # x <- a^d mod n
        x = pow(a, d, n)
        # if x = 1 or x = n - 1 then do next WitnessLoop
        if x != 1 and x != n - 1:
            do_next = False
            # repeat r - 1 times:
            for i in xrange(1, r):
                # x <- x^2 mod n
                x = pow(x, 2, n)
                # if x = 1 then return composite
                if x == 1:
                    return False
                # if x = n - 1 then do next WitnessLoop
                elif x == n - 1:
                    do_next = True
                    break
            # return composite
            if not do_next:
                return False

    # return probably prime
    return True


###
# https://en.wikipedia.org/wiki/Miller%E2%80%93Rabin_primality_test
#
def miller_rabin(n, k):
    # Input: n > 3, an odd integer to be tested for primality;
    # Input: k, a parameter that determines the accuracy of the test
    # Output: composite if n is composite, otherwise probably prime
    if n <= 1:
        return False
    elif n <= 3:
        return True
    elif n & 1 == 0:
        return False
    elif k < 1:
        # raise ValueError('need to repeat at least one time.')
        k = 1
    # realign for excess test runs.
    k = min(k, n - 3)

    # write n - 1 as 2^r*d with d odd by factoring powers of 2 from n - 1
    r = 0
    d = n - 1
    while d & 1 == 0:
        r += 1
        d >>= 1

    if k < sys.maxint / 2:
        # random.sample cause memory error with large test samples.
        return witness_loop(n, k, r, d)
    else:
        # with large random sample set,
        # avoiding possible non-distinct test samples,
        # can be sacrificed for memory conservation with minimum risk.
        return witness_loop_xl(n, k, r, d)


def question1():
    # use cases.
    test = [[5, sys.maxint], [2047, 1], [25326001, 1], [sys.maxint, 7], [997, 2]]
    for n, k in test:
        print 'test number %d (%d times): %r.' % (n, k, miller_rabin(n, k))

    # edge cases.
    test = [[0, 0], [0, sys.maxint], [0, -sys.maxint - 1],
            [-sys.maxint - 1, 0], [-sys.maxint - 1, sys.maxint], [-sys.maxint - 1, -sys.maxint - 1],
            [sys.maxint, 0], [sys.maxint, -sys.maxint - 1], [sys.maxint, sys.maxint]]
    for n, k in test:
        print 'test number %d (%d times): %r.' % (n, k, miller_rabin(n, k))

if __name__ == "__main__":
    question1()
 

arrow
arrow
    文章標籤
    Python
    全站熱搜
    創作者介紹
    創作者 g0d2 的頭像
    g0d2

    kazi1@的部落格

    g0d2 發表在 痞客邦 留言(0) 人氣()