#
#   number.py : Number-theoretic functions 
# 
#  Part of the Python Cryptography Toolkit, version 1.1
# 
# Distribute and use freely; there are no restrictions on further 
# dissemination and usage except those imposed by the laws of your 
# country of residence.  This software is provided "as is" without
# warranty of fitness for use or suitability for any purpose, express
# or implied. Use at your own risk or not at all. 
# 


bignum = long
try:
    import gmp
except ImportError:
    try:
        import mpz
        #bignum=mpz.mpz       # Temporarily disabled; the 'outrageous exponent'
                             # error messes things up.
    except ImportError: 
	pass

def long2str(n):
    s=''
    while n>0:
        s=chr(n & 255)+s
        n=n>>8
    return s

import types
def str2long(s):
    if type(s)!=types.StringType: return s   # Integers will be left alone
    return reduce(lambda x,y : x*256+ord(y), s, 0L)
    
def getRandomNumber(N, randfunc):
    "Return an N-bit random number."
    str=randfunc(N/8)
    char=ord(randfunc(1))>>(8-(N%8))
    return str2long(chr(char)+str)
    
def GCD(x,y):
    "Return the GCD of x and y."
    if x<0: x=-x
    if y<0: y=-y
    while x>0: x,y = y%x, x
    return y

def inverse(u, v):
    "Return the inverse of u mod v."
    u3, v3 = long(u), long(v)
    u1, v1 = 1L, 0L
    while v3>0:
	q=u3/v3
	u1, v1 = v1, u1-v1*q
	u3, v3 = v3, u3-v3*q
    while u1<0: u1=u1+v
    return u1
    
# Given a number of bits to generate and a random generation function,
# find a prime number of the appropriate size.

def getPrime(N, randfunc):
    "Return a random N-bit prime number."
    number=getRandomNumber(N, randfunc) | 1
    while (not isPrime(number)):
        number=number+2
    return number

def isPrime(N):
    "Return true if N is prime."
    for i in sieve:
        if (N % i)==0: return 0

    # Compute the highest bit that's set in N
    N1=N - 1L ; n=1L
    while (n<N): n=n<<1L 
    n = n >> 1L

    # Rabin-Miller test
    for c in sieve[:7]:
        a=long(c) ; d=1L ; t=n
        while (t):  # Iterate over the bits in N1
            x=(d*d) % N
            if x==1L and d!=1L and d!=N1: return 0  # Square root of 1 found
            if N1 & t: d=(x*a) % N
            else: d=x
            t = t >> 1L
        if d!=1L: return 0
    return 1

# Small primes used for checking primality; these are all the primes
# less than 256.  This should be enough to eliminate 80% of all the odd
# numbers before needing to do a Rabin-Miller test at all.

sieve=[13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 
       71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 
       137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 
       197, 199, 211, 223, 227, 229, 233, 239, 241, 251]


    
