import ranlib
import Numeric
import sys
import math
from types import *

ArgumentError = "ArgumentError"

def seed(x=0,y=0):
	"""seed(x, y), set the seed using the integers x, y; 
	Set a random one from clock if  y == 0
	"""
	if type (x) != IntType or type (y) != IntType :
		raise ArgumentError, "seed requires integer arguments."
	if y == 0:
		import time
		t = time.time()
		ndigits = int(math.log10(t))
		base = 10**(ndigits/2)
		x = int(t/base)
		y = 1 + int(t%base)
	ranlib.set_seeds(x,y)

seed()

def get_seed():
	"Return the current seed pair"
	return ranlib.get_seeds()

def random(shape=[]):
	"random(n) or random([n, m, ...]) returns array of random numbers"
	if type(shape) == type(0): shape = [shape]
	n = Numeric.multiply.reduce(shape)
	s = ranlib.sample(n)
	if len(shape) != 0:
		return Numeric.reshape(s, shape)
	else:
		return s[0]

def uniform(minimum, maximum, shape=[]):
	"""uniform(minimum, maximum, shape=[]) returns array of given shape of random reals 
	in given range"""
	return minimum + (maximum-minimum)*random(shape)

def randint(minimum, maximum=None, shape=[]):
	"""randint(min, max, shape=[]) = random integers >=min, < max
	If max not given, random integers >= 0, <min"""
	if maximum == None:
		maximum = minimum
		minimum = 0
	a = Numeric.asarray(uniform(minimum, maximum, shape)).astype(Numeric.Int)
	if len(a.shape) == 0:
		return a[0]
	return a
	 
def random_integers(maximum, minimum=1, shape=[]):
	"""random_integers(max, min=1, shape=[]) = random integers in range min-max inclusive"""
	a = Numeric.asarray(uniform(minimum, maximum+1, shape)).astype(Numeric.Int)
	if len(a.shape) == 0:
		return a[0]
	return a
	 
def permutation(n):
	"permutation(n) = a permutation of indices range(n)"
	return Numeric.argsort(random(n))

def test():
	x, y = get_seed()
	print "Initial seed", x, y
	seed(x, y)
	x1, y1 = get_seed()
	if x1 != x or y1 != y:
		raise SystemExit, "Failed seed test."
	print "First random number is", random()
	print "Average of 10000 random numbers is", Numeric.sum(random(10000))/10000.
	x = random([10,1000])
	if len(x.shape) != 2 or x.shape[0] != 10 or x.shape[1] != 1000:
		raise SystemExit, "random returned wrong shape"
	x.shape = (10000,)
	print "Average of 100 by 100 random numbers is", Numeric.sum(x)/10000.
	y = uniform(0.5,0.6, (1000,10))
	if len(y.shape) !=2 or y.shape[0] != 1000 or y.shape[1] != 10:
		raise SystemExit, "uniform returned wrong shape"
	y.shape = (10000,)
	if Numeric.minimum.reduce(y) <= 0.5 or Numeric.maximum.reduce(y) >= 0.6:
		raise SystemExit, "uniform returned out of desired range"
	print "randint(1, 10, shape=[50])"
	print randint(1, 10, shape=[50])
	print "permutation(10)", permutation(10)
	print "randint(3,9)", randint(3,9)
	print "random_integers(10, shape=[20])"
	print random_integers(10, shape=[20])

if __name__ == '__main__': 
	test()
