[pypy-svn] r19980 - in pypy/dist/pypy/translator/llvm: . demo module
rxe at codespeak.net
rxe at codespeak.net
Thu Nov 17 16:23:23 CET 2005
Author: rxe
Date: Thu Nov 17 16:23:04 2005
New Revision: 19980
Added:
pypy/dist/pypy/translator/llvm/demo/rrandom.py (contents, props changed)
Modified:
pypy/dist/pypy/translator/llvm/demo/bpnn.py
pypy/dist/pypy/translator/llvm/demo/richards.py
pypy/dist/pypy/translator/llvm/demo/run.py
pypy/dist/pypy/translator/llvm/externs2ll.py
pypy/dist/pypy/translator/llvm/genllvm.py
pypy/dist/pypy/translator/llvm/module/genexterns.c
pypy/dist/pypy/translator/llvm/module/support.py
pypy/dist/pypy/translator/llvm/opwriter.py
Log:
main() is now written in C.
* there is now only one entry_point() which takes a list of strings (argv)
* demo code fixed to reflect this (also bpnn was fixed in the process)
Modified: pypy/dist/pypy/translator/llvm/demo/bpnn.py
==============================================================================
--- pypy/dist/pypy/translator/llvm/demo/bpnn.py (original)
+++ pypy/dist/pypy/translator/llvm/demo/bpnn.py Thu Nov 17 16:23:04 2005
@@ -24,10 +24,10 @@
import time
import os, time
+import rrandom as random
+
# XXX the Translator needs the plain Python version of random.py:
import autopath
-from pypy.lib import random
-
PRINT_IT = False
random.seed(0)
@@ -193,57 +193,37 @@
print 'error %f' % error
i += 1
-def demo():
- # Teach network XOR function
- pat = [
- [[0,0], [0]],
- [[0,1], [1]],
- [[1,0], [1]],
- [[1,1], [0]]
- ]
-
- # create a network with two input, two hidden, and two output nodes
- n = NN(2, 3, 1)
- # train it with some patterns
- n.train(pat, 2000)
- # test it
- n.xtest(pat)
- return 0
-#_________________________________________________________
-
-from pypy.translator.llvm.genllvm import compile_function
-import py
-
-def test_demo():
- py.log.setconsumer("genllvm", py.log.STDOUT)
- py.log.setconsumer("genllvm database prepare", None)
- f = compile_function(demo, [])
-
- print 'Running...'
+def entry_point(args):
T = time.time()
- for i in range(30):
- f()
- t1 = time.time() - T
- print "that took", t1
- T = time.time()
- for i in range(30):
- demo()
- t2 = time.time() - T
- print "compared to", t2
- print "a speed-up of", t2/t1
-
-def main_noargs():
- T = time.time()
os.write(1, 'Running...\n')
for i in range(50):
- demo()
+
+ # Teach network XOR function
+ pat = [
+ [[0,0], [0]],
+ [[0,1], [1]],
+ [[1,0], [1]],
+ [[1,1], [0]]
+ ]
+
+ # create a network with two input, two hidden, and two output nodes
+ n = NN(2, 3, 1)
+ # train it with some patterns
+ n.train(pat, 2000)
+ # test it
+ n.xtest(pat)
t1 = time.time() - T
os.write(1, 'That took... %d msecs \n' % int(t1 * 1000))
+
return 0
+
+#_________________________________________________________
+
+from pypy.translator.llvm.genllvm import compile_function
if __name__ == "__main__":
from pypy.translator.llvm.demo.run import run
- run(main_noargs, "bpnn")
+ run(entry_point, "bpnn")
Modified: pypy/dist/pypy/translator/llvm/demo/richards.py
==============================================================================
--- pypy/dist/pypy/translator/llvm/demo/richards.py (original)
+++ pypy/dist/pypy/translator/llvm/demo/richards.py Thu Nov 17 16:23:04 2005
@@ -360,7 +360,9 @@
class Richards:
- iterations = 750
+ def __init__(self, iterations):
+ assert isinstance(iterations, int)
+ self.iterations = iterations
def run(self):
for i in xrange(self.iterations):
@@ -389,9 +391,7 @@
schedule()
- if taskWorkArea.holdCount == 9297 and taskWorkArea.qpktCount == 23246:
- os.write(1, "iteration %d\n" % i)
- else:
+ if taskWorkArea.holdCount != 9297 or taskWorkArea.qpktCount != 23246:
return False
return True
@@ -399,28 +399,35 @@
class FailedRun(Exception):
pass
-def entry_point():
- r = Richards()
+def entry_point(args):
+ os.write(1, " \n")
+ if len(args) > 2:
+ os.write(1, "command line: richards [iterations]\n")
+ return 2
+
+ iterations = 50
+ if len(args) == 2:
+ iterations = int(args[1])
+
+ os.write(1, "Richards benchmark starting... %s \n" % iterations)
+
+ r = Richards(iterations)
if not r:
raise FailedRun
- startTime = time.time()
+ start_time = time.time()
result = r.run()
- endTime = time.time()
- return result, startTime, endTime
+ endtime = time.time()
-def main_noargs():
- os.write(1, "Richards benchmark starting... \n")
- result, startTime, endTime = entry_point()
if not result:
os.write(1, "Incorrect results!\n")
return 1
- os.write(1, "finished.\n")
- total_s = endTime - startTime
- os.write(1, "\nTotal time for %d iterations: %d msecs\n" %(Richards.iterations, int(1000 * total_s)))
- os.write(1, "Average time for iterations: %d ms\n" % (int(total_s * 1000)/Richards.iterations))
- return 0
+ total_s = endtime - start_time
+ os.write(1, "\nTotal time for %d iterations: %d msecs\n" %(iterations, int(1000 * total_s)))
+ os.write(1, "Average time for iterations: %d ms\n" % (int(total_s * 1000)/iterations))
+ return 0
+
if __name__ == "__main__":
import autopath
from pypy.translator.llvm.demo.run import run
- run(main_noargs, "richards")
+ run(entry_point, "richards")
Added: pypy/dist/pypy/translator/llvm/demo/rrandom.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/translator/llvm/demo/rrandom.py Thu Nov 17 16:23:04 2005
@@ -0,0 +1,782 @@
+"""Random variable generators.
+
+ integers
+ --------
+ uniform within range
+
+ sequences
+ ---------
+ pick random element
+ generate random permutation
+
+ distributions on the real line:
+ ------------------------------
+ uniform
+ normal (Gaussian)
+ lognormal
+ negative exponential
+ gamma
+ beta
+
+ distributions on the circle (angles 0 to 2pi)
+ ---------------------------------------------
+ circular uniform
+ von Mises
+
+Translated from anonymously contributed C/C++ source.
+
+Multi-threading note: the random number generator used here is not thread-
+safe; it is possible that two calls return the same random value. However,
+you can instantiate a different instance of Random() in each thread to get
+generators that don't share state, then use .setstate() and .jumpahead() to
+move the generators to disjoint segments of the full period. For example,
+
+def create_generators(num, delta, firstseed=None):
+ ""\"Return list of num distinct generators.
+ Each generator has its own unique segment of delta elements from
+ Random.random()'s full period.
+ Seed the first generator with optional arg firstseed (default is
+ None, to seed from current time).
+ ""\"
+
+ from random import Random
+ g = Random(firstseed)
+ result = [g]
+ for i in range(num - 1):
+ laststate = g.getstate()
+ g = Random()
+ g.setstate(laststate)
+ g.jumpahead(delta)
+ result.append(g)
+ return result
+
+gens = create_generators(10, 1000000)
+
+That creates 10 distinct generators, which can be passed out to 10 distinct
+threads. The generators don't share state so can be called safely in
+parallel. So long as no thread calls its g.random() more than a million
+times (the second argument to create_generators), the sequences seen by
+each thread will not overlap.
+
+The period of the underlying Wichmann-Hill generator is 6,953,607,871,644,
+and that limits how far this technique can be pushed.
+
+Just for fun, note that since we know the period, .jumpahead() can also be
+used to "move backward in time":
+
+>>> g = Random(42) # arbitrary
+>>> g.random()
+0.25420336316883324
+>>> g.jumpahead(6953607871644L - 1) # move *back* one
+>>> g.random()
+0.25420336316883324
+"""
+# XXX The docstring sucks.
+
+from math import log as _log, exp as _exp, pi as _pi, e as _e
+from math import sqrt as _sqrt, acos as _acos, cos as _cos, sin as _sin
+from math import floor as _floor
+from math import fmod as _fmod
+
+__all__ = ["Random","seed","random","uniform","randint","choice",
+ "randrange","shuffle","normalvariate","lognormvariate",
+ "cunifvariate","expovariate","vonmisesvariate","gammavariate",
+ "stdgamma","gauss","betavariate","paretovariate","weibullvariate",
+ "getstate","setstate","jumpahead","whseed","WichmannHill"]
+
+def _verify(name, computed, expected):
+ if abs(computed - expected) > 1e-7:
+ raise ValueError(
+ "computed value for %s deviates too much "
+ "(computed %g, expected %g)" % (name, computed, expected))
+
+NV_MAGICCONST = 4 * _exp(-0.5)/_sqrt(2.0)
+_verify('NV_MAGICCONST', NV_MAGICCONST, 1.71552776992141)
+
+TWOPI = 2.0*_pi
+_verify('TWOPI', TWOPI, 6.28318530718)
+
+LOG4 = _log(4.0)
+_verify('LOG4', LOG4, 1.38629436111989)
+
+SG_MAGICCONST = 1.0 + _log(4.5)
+_verify('SG_MAGICCONST', SG_MAGICCONST, 2.50407739677627)
+
+del _verify
+
+# Translated by Guido van Rossum from C source provided by
+# Adrian Baddeley.
+
+class Random:
+ """Random number generator base class used by bound module functions.
+
+ Used to instantiate instances of Random to get generators that don't
+ share state. Especially useful for multi-threaded programs, creating
+ a different instance of Random for each thread, and using the jumpahead()
+ method to ensure that the generated sequences seen by each thread don't
+ overlap.
+
+ Class Random can also be subclassed if you want to use a different basic
+ generator of your own devising: in that case, override the following
+ methods: random(), seed(), getstate(), setstate() and jumpahead().
+
+ """
+
+ VERSION = 1 # used by getstate/setstate
+
+ def __init__(self, x=None):
+ """Initialize an instance.
+
+ Optional argument x controls seeding, as for Random.seed().
+ """
+
+ self.seed(x)
+
+## -------------------- core generator -------------------
+
+ # Specific to Wichmann-Hill generator. Subclasses wishing to use a
+ # different core generator should override the seed(), random(),
+ # getstate(), setstate() and jumpahead() methods.
+
+ def seed(self, a=None):
+ """Initialize internal state from hashable object.
+
+ None or no argument seeds from current time.
+
+ If a is not None or an int or long, hash(a) is used instead.
+
+ If a is an int or long, a is used directly. Distinct values between
+ 0 and 27814431486575L inclusive are guaranteed to yield distinct
+ internal states (this guarantee is specific to the default
+ Wichmann-Hill generator).
+ """
+
+ if a is None:
+ # Initialize from current time
+ import time
+ a = long(time.time() * 256)
+
+ if type(a) not in (type(3), type(3L)):
+ a = hash(a)
+
+ a, x = divmod(a, 30268)
+ a, y = divmod(a, 30306)
+ a, z = divmod(a, 30322)
+ self._seed = int(x)+1, int(y)+1, int(z)+1
+
+ self.gauss_next = None
+
+ def random(self):
+ """Get the next random number in the range [0.0, 1.0)."""
+
+ # Wichman-Hill random number generator.
+ #
+ # Wichmann, B. A. & Hill, I. D. (1982)
+ # Algorithm AS 183:
+ # An efficient and portable pseudo-random number generator
+ # Applied Statistics 31 (1982) 188-190
+ #
+ # see also:
+ # Correction to Algorithm AS 183
+ # Applied Statistics 33 (1984) 123
+ #
+ # McLeod, A. I. (1985)
+ # A remark on Algorithm AS 183
+ # Applied Statistics 34 (1985),198-200
+
+ # This part is thread-unsafe:
+ # BEGIN CRITICAL SECTION
+ x, y, z = self._seed
+ x = (171 * x) % 30269
+ y = (172 * y) % 30307
+ z = (170 * z) % 30323
+ self._seed = x, y, z
+ # END CRITICAL SECTION
+
+ # Note: on a platform using IEEE-754 double arithmetic, this can
+ # never return 0.0 (asserted by Tim; proof too long for a comment).
+ return _fmod((x/30269.0 + y/30307.0 + z/30323.0), 1.0)
+
+ def getstate(self):
+ """Return internal state; can be passed to setstate() later."""
+ return self.VERSION, self._seed, self.gauss_next
+
+ def setstate(self, state):
+ """Restore internal state from object returned by getstate()."""
+ version = state[0]
+ if version == 1:
+ version, self._seed, self.gauss_next = state
+ else:
+ raise ValueError("state with version %s passed to "
+ "Random.setstate() of version %s" %
+ (version, self.VERSION))
+
+ def jumpahead(self, n):
+ """Act as if n calls to random() were made, but quickly.
+
+ n is an int, greater than or equal to 0.
+
+ Example use: If you have 2 threads and know that each will
+ consume no more than a million random numbers, create two Random
+ objects r1 and r2, then do
+ r2.setstate(r1.getstate())
+ r2.jumpahead(1000000)
+ Then r1 and r2 will use guaranteed-disjoint segments of the full
+ period.
+ """
+
+ if not n >= 0:
+ raise ValueError("n must be >= 0")
+ x, y, z = self._seed
+ x = int(x * pow(171, n, 30269)) % 30269
+ y = int(y * pow(172, n, 30307)) % 30307
+ z = int(z * pow(170, n, 30323)) % 30323
+ self._seed = x, y, z
+
+ def __whseed(self, x=0, y=0, z=0):
+ """Set the Wichmann-Hill seed from (x, y, z).
+
+ These must be integers in the range [0, 256).
+ """
+
+ if not type(x) == type(y) == type(z) == type(0):
+ raise TypeError('seeds must be integers')
+ if not (0 <= x < 256 and 0 <= y < 256 and 0 <= z < 256):
+ raise ValueError('seeds must be in range(0, 256)')
+ if 0 == x == y == z:
+ # Initialize from current time
+ import time
+ t = long(time.time() * 256)
+ t = int((t&0xffffff) ^ (t>>24))
+ t, x = divmod(t, 256)
+ t, y = divmod(t, 256)
+ t, z = divmod(t, 256)
+ # Zero is a poor seed, so substitute 1
+ self._seed = (x or 1, y or 1, z or 1)
+
+ self.gauss_next = None
+
+ def whseed(self, a=None):
+ """Seed from hashable object's hash code.
+
+ None or no argument seeds from current time. It is not guaranteed
+ that objects with distinct hash codes lead to distinct internal
+ states.
+
+ This is obsolete, provided for compatibility with the seed routine
+ used prior to Python 2.1. Use the .seed() method instead.
+ """
+
+ if a is None:
+ self.__whseed()
+ return
+ a = hash(a)
+ a, x = divmod(a, 256)
+ a, y = divmod(a, 256)
+ a, z = divmod(a, 256)
+ x = (x + a) % 256 or 1
+ y = (y + a) % 256 or 1
+ z = (z + a) % 256 or 1
+ self.__whseed(x, y, z)
+
+## ---- Methods below this point do not need to be overridden when
+## ---- subclassing for the purpose of using a different core generator.
+
+## -------------------- pickle support -------------------
+
+ def __getstate__(self): # for pickle
+ return self.getstate()
+
+ def __setstate__(self, state): # for pickle
+ self.setstate(state)
+
+## -------------------- integer methods -------------------
+
+ def randrange(self, start, stop=None, step=1, int=int, default=None):
+ """Choose a random item from range(start, stop[, step]).
+
+ This fixes the problem with randint() which includes the
+ endpoint; in Python this is usually not what you want.
+ Do not supply the 'int' and 'default' arguments.
+ """
+
+ # This code is a bit messy to make it fast for the
+ # common case while still doing adequate error checking.
+ istart = int(start)
+ if istart != start:
+ raise ValueError, "non-integer arg 1 for randrange()"
+ if stop is default:
+ if istart > 0:
+ return int(self.random() * istart)
+ raise ValueError, "empty range for randrange()"
+
+ # stop argument supplied.
+ istop = int(stop)
+ if istop != stop:
+ raise ValueError, "non-integer stop for randrange()"
+ if step == 1 and istart < istop:
+ try:
+ return istart + int(self.random()*(istop - istart))
+ except OverflowError:
+ # This can happen if istop-istart > sys.maxint + 1, and
+ # multiplying by random() doesn't reduce it to something
+ # <= sys.maxint. We know that the overall result fits
+ # in an int, and can still do it correctly via math.floor().
+ # But that adds another function call, so for speed we
+ # avoided that whenever possible.
+ return int(istart + _floor(self.random()*(istop - istart)))
+ if step == 1:
+ raise ValueError, "empty range for randrange()"
+
+ # Non-unit step argument supplied.
+ istep = int(step)
+ if istep != step:
+ raise ValueError, "non-integer step for randrange()"
+ if istep > 0:
+ n = (istop - istart + istep - 1) / istep
+ elif istep < 0:
+ n = (istop - istart + istep + 1) / istep
+ else:
+ raise ValueError, "zero step for randrange()"
+
+ if n <= 0:
+ raise ValueError, "empty range for randrange()"
+ return istart + istep*int(self.random() * n)
+
+ def randint(self, a, b):
+ """Return random integer in range [a, b], including both end points.
+ """
+
+ return self.randrange(a, b+1)
+
+## -------------------- sequence methods -------------------
+
+ def choice(self, seq):
+ """Choose a random element from a non-empty sequence."""
+ return seq[int(self.random() * len(seq))]
+
+ def shuffle(self, x, random=None, int=int):
+ """x, random=random.random -> shuffle list x in place; return None.
+
+ Optional arg random is a 0-argument function returning a random
+ float in [0.0, 1.0); by default, the standard random.random.
+
+ Note that for even rather small len(x), the total number of
+ permutations of x is larger than the period of most random number
+ generators; this implies that "most" permutations of a long
+ sequence can never be generated.
+ """
+
+ if random is None:
+ random = self.random
+ for i in xrange(len(x)-1, 0, -1):
+ # pick an element in x[:i+1] with which to exchange x[i]
+ j = int(random() * (i+1))
+ x[i], x[j] = x[j], x[i]
+
+## -------------------- real-valued distributions -------------------
+
+## -------------------- uniform distribution -------------------
+
+ def uniform(self, a, b):
+ """Get a random number in the range [a, b)."""
+ return a + (b-a) * self.random()
+
+## -------------------- normal distribution --------------------
+
+ def normalvariate(self, mu, sigma):
+ """Normal distribution.
+
+ mu is the mean, and sigma is the standard deviation.
+
+ """
+ # mu = mean, sigma = standard deviation
+
+ # Uses Kinderman and Monahan method. Reference: Kinderman,
+ # A.J. and Monahan, J.F., "Computer generation of random
+ # variables using the ratio of uniform deviates", ACM Trans
+ # Math Software, 3, (1977), pp257-260.
+
+ random = self.random
+ while 1:
+ u1 = random()
+ u2 = 1.0 - random()
+ z = NV_MAGICCONST*(u1-0.5)/u2
+ zz = z*z/4.0
+ if zz <= -_log(u2):
+ break
+ return mu + z*sigma
+
+## -------------------- lognormal distribution --------------------
+
+ def lognormvariate(self, mu, sigma):
+ """Log normal distribution.
+
+ If you take the natural logarithm of this distribution, you'll get a
+ normal distribution with mean mu and standard deviation sigma.
+ mu can have any value, and sigma must be greater than zero.
+
+ """
+ return _exp(self.normalvariate(mu, sigma))
+
+## -------------------- circular uniform --------------------
+
+ def cunifvariate(self, mean, arc):
+ """Circular uniform distribution.
+
+ mean is the mean angle, and arc is the range of the distribution,
+ centered around the mean angle. Both values must be expressed in
+ radians. Returned values range between mean - arc/2 and
+ mean + arc/2 and are normalized to between 0 and pi.
+
+ Deprecated in version 2.3. Use:
+ (mean + arc * (Random.random() - 0.5)) % Math.pi
+
+ """
+ # mean: mean angle (in radians between 0 and pi)
+ # arc: range of distribution (in radians between 0 and pi)
+
+ return (mean + arc * (self.random() - 0.5)) % _pi
+
+## -------------------- exponential distribution --------------------
+
+ def expovariate(self, lambd):
+ """Exponential distribution.
+
+ lambd is 1.0 divided by the desired mean. (The parameter would be
+ called "lambda", but that is a reserved word in Python.) Returned
+ values range from 0 to positive infinity.
+
+ """
+ # lambd: rate lambd = 1/mean
+ # ('lambda' is a Python reserved word)
+
+ random = self.random
+ u = random()
+ while u <= 1e-7:
+ u = random()
+ return -_log(u)/lambd
+
+## -------------------- von Mises distribution --------------------
+
+ def vonmisesvariate(self, mu, kappa):
+ """Circular data distribution.
+
+ mu is the mean angle, expressed in radians between 0 and 2*pi, and
+ kappa is the concentration parameter, which must be greater than or
+ equal to zero. If kappa is equal to zero, this distribution reduces
+ to a uniform random angle over the range 0 to 2*pi.
+
+ """
+ # mu: mean angle (in radians between 0 and 2*pi)
+ # kappa: concentration parameter kappa (>= 0)
+ # if kappa = 0 generate uniform random angle
+
+ # Based upon an algorithm published in: Fisher, N.I.,
+ # "Statistical Analysis of Circular Data", Cambridge
+ # University Press, 1993.
+
+ # Thanks to Magnus Kessler for a correction to the
+ # implementation of step 4.
+
+ random = self.random
+ if kappa <= 1e-6:
+ return TWOPI * random()
+
+ a = 1.0 + _sqrt(1.0 + 4.0 * kappa * kappa)
+ b = (a - _sqrt(2.0 * a))/(2.0 * kappa)
+ r = (1.0 + b * b)/(2.0 * b)
+
+ while 1:
+ u1 = random()
+
+ z = _cos(_pi * u1)
+ f = (1.0 + r * z)/(r + z)
+ c = kappa * (r - f)
+
+ u2 = random()
+
+ if not (u2 >= c * (2.0 - c) and u2 > c * _exp(1.0 - c)):
+ break
+
+ u3 = random()
+ if u3 > 0.5:
+ theta = (mu % TWOPI) + _acos(f)
+ else:
+ theta = (mu % TWOPI) - _acos(f)
+
+ return theta
+
+## -------------------- gamma distribution --------------------
+
+ def gammavariate(self, alpha, beta):
+ """Gamma distribution. Not the gamma function!
+
+ Conditions on the parameters are alpha > 0 and beta > 0.
+
+ """
+
+ # alpha > 0, beta > 0, mean is alpha*beta, variance is alpha*beta**2
+
+ # Warning: a few older sources define the gamma distribution in terms
+ # of alpha > -1.0
+ if alpha <= 0.0 or beta <= 0.0:
+ raise ValueError, 'gammavariate: alpha and beta must be > 0.0'
+
+ random = self.random
+ if alpha > 1.0:
+
+ # Uses R.C.H. Cheng, "The generation of Gamma
+ # variables with non-integral shape parameters",
+ # Applied Statistics, (1977), 26, No. 1, p71-74
+
+ ainv = _sqrt(2.0 * alpha - 1.0)
+ bbb = alpha - LOG4
+ ccc = alpha + ainv
+
+ while 1:
+ u1 = random()
+ if not 1e-7 < u1 < .9999999:
+ continue
+ u2 = 1.0 - random()
+ v = _log(u1/(1.0-u1))/ainv
+ x = alpha*_exp(v)
+ z = u1*u1*u2
+ r = bbb+ccc*v-x
+ if r + SG_MAGICCONST - 4.5*z >= 0.0 or r >= _log(z):
+ return x * beta
+
+ elif alpha == 1.0:
+ # expovariate(1)
+ u = random()
+ while u <= 1e-7:
+ u = random()
+ return -_log(u) * beta
+
+ else: # alpha is between 0 and 1 (exclusive)
+
+ # Uses ALGORITHM GS of Statistical Computing - Kennedy & Gentle
+
+ while 1:
+ u = random()
+ b = (_e + alpha)/_e
+ p = b*u
+ if p <= 1.0:
+ x = pow(p, 1.0/alpha)
+ else:
+ # p > 1
+ x = -_log((b-p)/alpha)
+ u1 = random()
+ if not (((p <= 1.0) and (u1 > _exp(-x))) or
+ ((p > 1) and (u1 > pow(x, alpha - 1.0)))):
+ break
+ return x * beta
+
+
+ def stdgamma(self, alpha, ainv, bbb, ccc):
+ # This method was (and shall remain) undocumented.
+ # This method is deprecated
+ # for the following reasons:
+ # 1. Returns same as .gammavariate(alpha, 1.0)
+ # 2. Requires caller to provide 3 extra arguments
+ # that are functions of alpha anyway
+ # 3. Can't be used for alpha < 0.5
+
+ # ainv = sqrt(2 * alpha - 1)
+ # bbb = alpha - log(4)
+ # ccc = alpha + ainv
+ import warnings
+ warnings.warn("The stdgamma function is deprecated; "
+ "use gammavariate() instead",
+ DeprecationWarning)
+ return self.gammavariate(alpha, 1.0)
+
+
+
+## -------------------- Gauss (faster alternative) --------------------
+
+ def gauss(self, mu, sigma):
+ """Gaussian distribution.
+
+ mu is the mean, and sigma is the standard deviation. This is
+ slightly faster than the normalvariate() function.
+
+ Not thread-safe without a lock around calls.
+
+ """
+
+ # When x and y are two variables from [0, 1), uniformly
+ # distributed, then
+ #
+ # cos(2*pi*x)*sqrt(-2*log(1-y))
+ # sin(2*pi*x)*sqrt(-2*log(1-y))
+ #
+ # are two *independent* variables with normal distribution
+ # (mu = 0, sigma = 1).
+ # (Lambert Meertens)
+ # (corrected version; bug discovered by Mike Miller, fixed by LM)
+
+ # Multithreading note: When two threads call this function
+ # simultaneously, it is possible that they will receive the
+ # same return value. The window is very small though. To
+ # avoid this, you have to use a lock around all calls. (I
+ # didn't want to slow this down in the serial case by using a
+ # lock here.)
+
+ random = self.random
+ z = self.gauss_next
+ self.gauss_next = None
+ if z is None:
+ x2pi = random() * TWOPI
+ g2rad = _sqrt(-2.0 * _log(1.0 - random()))
+ z = _cos(x2pi) * g2rad
+ self.gauss_next = _sin(x2pi) * g2rad
+
+ return mu + z*sigma
+
+## -------------------- beta --------------------
+## See
+## http://sourceforge.net/bugs/?func=detailbug&bug_id=130030&group_id=5470
+## for Ivan Frohne's insightful analysis of why the original implementation:
+##
+## def betavariate(self, alpha, beta):
+## # Discrete Event Simulation in C, pp 87-88.
+##
+## y = self.expovariate(alpha)
+## z = self.expovariate(1.0/beta)
+## return z/(y+z)
+##
+## was dead wrong, and how it probably got that way.
+
+ def betavariate(self, alpha, beta):
+ """Beta distribution.
+
+ Conditions on the parameters are alpha > -1 and beta} > -1.
+ Returned values range between 0 and 1.
+
+ """
+
+ # This version due to Janne Sinkkonen, and matches all the std
+ # texts (e.g., Knuth Vol 2 Ed 3 pg 134 "the beta distribution").
+ y = self.gammavariate(alpha, 1.)
+ if y == 0:
+ return 0.0
+ else:
+ return y / (y + self.gammavariate(beta, 1.))
+
+## -------------------- Pareto --------------------
+
+ def paretovariate(self, alpha):
+ """Pareto distribution. alpha is the shape parameter."""
+ # Jain, pg. 495
+
+ u = 1.0 - self.random()
+ return 1.0 / pow(u, 1.0/alpha)
+
+## -------------------- Weibull --------------------
+
+ def weibullvariate(self, alpha, beta):
+ """Weibull distribution.
+
+ alpha is the scale parameter and beta is the shape parameter.
+
+ """
+ # Jain, pg. 499; bug fix courtesy Bill Arms
+
+ u = 1.0 - self.random()
+ return alpha * pow(-_log(u), 1.0/beta)
+
+## -------------------- test program --------------------
+
+def _test_generator(n, funccall):
+ import time
+ print n, 'times', funccall
+ code = compile(funccall, funccall, 'eval')
+ sum = 0.0
+ sqsum = 0.0
+ smallest = 1e10
+ largest = -1e10
+ t0 = time.time()
+ for i in range(n):
+ x = eval(code)
+ sum = sum + x
+ sqsum = sqsum + x*x
+ smallest = min(x, smallest)
+ largest = max(x, largest)
+ t1 = time.time()
+ print round(t1-t0, 3), 'sec,',
+ avg = sum/n
+ stddev = _sqrt(sqsum/n - avg*avg)
+ print 'avg %g, stddev %g, min %g, max %g' % \
+ (avg, stddev, smallest, largest)
+
+def _test(N=20000):
+ print 'TWOPI =', TWOPI
+ print 'LOG4 =', LOG4
+ print 'NV_MAGICCONST =', NV_MAGICCONST
+ print 'SG_MAGICCONST =', SG_MAGICCONST
+ _test_generator(N, 'random()')
+ _test_generator(N, 'normalvariate(0.0, 1.0)')
+ _test_generator(N, 'lognormvariate(0.0, 1.0)')
+ _test_generator(N, 'cunifvariate(0.0, 1.0)')
+ _test_generator(N, 'expovariate(1.0)')
+ _test_generator(N, 'vonmisesvariate(0.0, 1.0)')
+ _test_generator(N, 'gammavariate(0.01, 1.0)')
+ _test_generator(N, 'gammavariate(0.1, 1.0)')
+ _test_generator(N, 'gammavariate(0.1, 2.0)')
+ _test_generator(N, 'gammavariate(0.5, 1.0)')
+ _test_generator(N, 'gammavariate(0.9, 1.0)')
+ _test_generator(N, 'gammavariate(1.0, 1.0)')
+ _test_generator(N, 'gammavariate(2.0, 1.0)')
+ _test_generator(N, 'gammavariate(20.0, 1.0)')
+ _test_generator(N, 'gammavariate(200.0, 1.0)')
+ _test_generator(N, 'gauss(0.0, 1.0)')
+ _test_generator(N, 'betavariate(3.0, 3.0)')
+ _test_generator(N, 'paretovariate(1.0)')
+ _test_generator(N, 'weibullvariate(1.0, 1.0)')
+
+ # Test jumpahead.
+ s = getstate()
+ jumpahead(N)
+ r1 = random()
+ # now do it the slow way
+ setstate(s)
+ for i in range(N):
+ random()
+ r2 = random()
+ if r1 != r2:
+ raise ValueError("jumpahead test failed " + `(N, r1, r2)`)
+
+# Create one instance, seeded from current time, and export its methods
+# as module-level functions. The functions are not threadsafe, and state
+# is shared across all uses (both in the user's code and in the Python
+# libraries), but that's fine for most programs and is easier for the
+# casual user than making them instantiate their own Random() instance.
+_inst = Random()
+seed = _inst.seed
+random = _inst.random
+uniform = _inst.uniform
+randint = _inst.randint
+choice = _inst.choice
+randrange = _inst.randrange
+shuffle = _inst.shuffle
+normalvariate = _inst.normalvariate
+lognormvariate = _inst.lognormvariate
+cunifvariate = _inst.cunifvariate
+expovariate = _inst.expovariate
+vonmisesvariate = _inst.vonmisesvariate
+gammavariate = _inst.gammavariate
+stdgamma = _inst.stdgamma
+gauss = _inst.gauss
+betavariate = _inst.betavariate
+paretovariate = _inst.paretovariate
+weibullvariate = _inst.weibullvariate
+getstate = _inst.getstate
+setstate = _inst.setstate
+jumpahead = _inst.jumpahead
+whseed = _inst.whseed
+
+WichmannHill = Random # for compatibility with >= 2.3
+
+if __name__ == '__main__':
+ _test()
Modified: pypy/dist/pypy/translator/llvm/demo/run.py
==============================================================================
--- pypy/dist/pypy/translator/llvm/demo/run.py (original)
+++ pypy/dist/pypy/translator/llvm/demo/run.py Thu Nov 17 16:23:04 2005
@@ -2,23 +2,20 @@
import os
import sys
+from pypy.annotation.model import SomeList, SomeString
+from pypy.annotation.listdef import ListDef
+
from pypy.translator.llvm.genllvm import compile_module
from pypy.translator.translator import Translator
def p():
print 'Running on top of CPython:'
- entry_point()
-
-def c():
- print "Running genc'd version on top of CPython:"
- t = Translator(entry_point)
- a = t.annotate([])
- t.specialize()
- f = t.ccompile()
- f()
+ entry_point([])
def l(name):
- exe_path = compile_module(entry_point, [], exe_name=name)
+ s_list_of_strings = SomeList(ListDef(None, SomeString()))
+ s_list_of_strings.listdef.resize()
+ exe_path = compile_module(entry_point, [s_list_of_strings], exe_name=name)
print 'Running standalone (llvm-based) executable:'
print exe_path
os.system(exe_path)
@@ -32,14 +29,10 @@
if sys.argv[1] == "p":
p()
run_all = False
- elif sys.argv[1] == "c":
- c()
- run_all = False
elif sys.argv[1] == "l":
l(name)
run_all = False
if run_all:
l(name)
- c()
p()
Modified: pypy/dist/pypy/translator/llvm/externs2ll.py
==============================================================================
--- pypy/dist/pypy/translator/llvm/externs2ll.py (original)
+++ pypy/dist/pypy/translator/llvm/externs2ll.py Thu Nov 17 16:23:04 2005
@@ -20,7 +20,9 @@
"%prepare_ValueError",
"%RPyString_FromString",
"%RPyString_AsString",
- "%RPyString_Size"]
+ "%RPyString_Size",
+ "%RPyExceptionOccurred",
+ ]
def get_ll(ccode, function_names):
function_names += support_functions
@@ -47,6 +49,11 @@
# strip declares that are in funcnames
for line in llcode.split('\n'):
+ # For some reason gcc introduces this and then we cant resolve it
+ # XXX Get rid of this - when got more time on our hands
+ if line.find("__main") >= 1:
+ continue
+
# get rid of any of the structs that llvm-gcc introduces to struct types
line = line.replace("%struct.", "%")
@@ -62,9 +69,9 @@
funcname , s = s.split('(', 1)
funcnames[funcname] = True
if line.find("internal") == -1:
- #internal = ''
- internal = 'internal '
- line = '%s%s %s' % (internal, DEFAULT_CCONV, line,)
+ if funcname != "%main":
+ internal = 'internal '
+ line = '%s%s %s' % (internal, DEFAULT_CCONV, line,)
ll_lines.append(line)
# patch calls to function that we just declared fastcc
@@ -92,20 +99,6 @@
decl, impl = llcode.split('implementation')
except:
raise "Can't compile external function code (llcode.c): ERROR:", llcode
- impl += """;functions that should return a bool according to
- ; pypy/rpython/extfunctable.py , but C doesn't have bools!
-
-internal fastcc bool %LL_os_isatty(int %fd) {
- %t = call fastcc int %LL_os_isatty(int %fd)
- %b = cast int %t to bool
- ret bool %b
-}
-internal fastcc bool %LL_stack_too_big() {
- %t = call fastcc int %LL_stack_too_big()
- %b = cast int %t to bool
- ret bool %b
-}
- """
return decl, impl
@@ -142,14 +135,26 @@
def generate_llfile(db, extern_decls):
ccode = []
function_names = []
-
+
def predeclarefn(c_name, llname):
+ print llname
function_names.append(llname)
assert llname[0] == "%"
llname = llname[1:]
assert '\n' not in llname
ccode.append('#define\t%s\t%s\n' % (c_name, llname))
+ # special case name entry_point XXX bit underhand
+ for k, v in db.obj2node.items():
+ try:
+ if isinstance(lltype.typeOf(k), lltype.FuncType):
+ if k._name == "entry_point":
+ predeclarefn("entry_point", v.get_ref())
+ ccode.append('#define ENTRY_POINT_DEFINED 1\n\n')
+ break
+ except TypeError, exc:
+ pass
+
for c_name, obj in extern_decls:
if isinstance(obj, lltype.LowLevelType):
s = "#define %s struct %s\n%s;\n" % (c_name, c_name, c_name)
@@ -162,39 +167,47 @@
if isinstance(lltype.typeOf(obj._obj), lltype.FuncType):
predeclarefn(c_name, db.repr_name(obj._obj))
- include_files = []
- add = include_files.append
- add(path_join(os.path.dirname(__file__), "module", "genexterns.c"))
+ # start building our source
+ src = open(path_join(os.path.dirname(__file__),
+ "module",
+ "genexterns.c")).read()
+
+ # set python version to include
+ if sys.platform == 'darwin':
+ python_h = '"/System/Library/Frameworks/Python.framework/Versions/2.3/include/python2.3/Python.h"'
+ else:
+ python_h = '<python2.3/Python.h>'
+ src = src.replace('__PYTHON_H__', python_h)
+
+ # add our raising ops
+ s = open(path_join(os.path.dirname(__file__),
+ "module",
+ "raisingop.h")).read()
+ src = src.replace('__RAISING_OPS__', s)
+
+
from pypy.translator.c import extfunc
src_path = path_join(os.path.dirname(extfunc.__file__), "src")
- for f in ["ll_os", "ll_math", "ll_time", "ll_strtod", "thread", "stack"]:
- add(path_join(src_path, f + ".h"))
-
+ include_files = [path_join(src_path, f + ".h") for f in
+ ["ll_os", "ll_math", "ll_time",
+ "ll_strtod", "thread", "stack"]]
+
+ includes = []
for f in include_files:
s = open(f).read()
- # XXX this is getting a tad (even more) ridiculous
- if s.find('__RAISING_OP__') >= 0:
- s2 = open(path_join(os.path.dirname(__file__),
- "module",
- "raisingop.h")).read()
- s = s.replace('__RAISING_OP__', s2)
-
+ # XXX this is getting a tad (even more) ridiculous
for name in ["ll_osdefs.h", "thread_pthread.h"]:
include_str = '#include "%s"' % name
if s.find(include_str) >= 0:
s2 = open(path_join(src_path, name)).read()
s = s.replace(include_str, s2)
- if f.find('genexterns.c') >= 0:
- if sys.platform == 'darwin':
- python_h = '"/System/Library/Frameworks/Python.framework/Versions/2.3/include/python2.3/Python.h"'
- else:
- python_h = '<python2.3/Python.h>'
- s = s.replace('__PYTHON_H__', python_h)
-
- ccode.append(s)
- ccode = "".join(ccode)
+ includes.append(s)
+ src = src.replace('__INCLUDE_FILES__', "".join(includes))
+ ccode.append(src)
+ ccode = "".join(ccode)
+
return get_ll(ccode, function_names)
Modified: pypy/dist/pypy/translator/llvm/genllvm.py
==============================================================================
--- pypy/dist/pypy/translator/llvm/genllvm.py (original)
+++ pypy/dist/pypy/translator/llvm/genllvm.py Thu Nov 17 16:23:04 2005
@@ -8,8 +8,7 @@
from pypy.tool.udir import udir
from pypy.translator.llvm.codewriter import CodeWriter
from pypy.translator.llvm import extfuncnode
-from pypy.translator.llvm.module.support import extdeclarations, \
- extfunctions, entry_functions
+from pypy.translator.llvm.module.support import extdeclarations, extfunctions
from pypy.translator.llvm.node import LLVMNode
from pypy.translator.llvm.externs2ll import post_setup_externs, generate_llfile
from pypy.translator.llvm.gc import GcPolicy
@@ -155,8 +154,7 @@
codewriter.append(self.exceptionpolicy.llvmcode(self.entrynode))
# write support implementations
- for impl in extfunctions.values():
- codewriter.append(impl)
+ codewriter.append(extfunctions)
self._checkpoint('write support implentations')
# write all node implementations
@@ -165,7 +163,6 @@
self._checkpoint('write node implementations')
# write entry point if there is one
- self.write_entry_point(codewriter)
codewriter.comment("End of file")
self._checkpoint('done')
@@ -227,15 +224,6 @@
l = "%%%s = type %s" % (c_name, self.db.repr_type(obj))
codewriter.append(l)
- def write_entry_point(self, codewriter):
- # XXX we need to create our own main() that calls the actual
- # entry_point function
- entryfunc_name = self.entrynode.getdecl().split('%pypy_', 1)[1]
- entryfunc_name = entryfunc_name.split('(')[0]
- llcode = entry_functions.get(entryfunc_name, None)
- if llcode:
- codewriter.append(llcode)
-
def _checkpoint(self, msg=None):
if not self.logging:
return
Modified: pypy/dist/pypy/translator/llvm/module/genexterns.c
==============================================================================
--- pypy/dist/pypy/translator/llvm/module/genexterns.c (original)
+++ pypy/dist/pypy/translator/llvm/module/genexterns.c Thu Nov 17 16:23:04 2005
@@ -3,6 +3,7 @@
char *RPyString_AsString(RPyString*);
int RPyString_Size(RPyString*);
RPyString *RPyString_FromString(char *);
+int RPyExceptionOccurred(void);
void raisePyExc_IOError(char *);
void raisePyExc_ValueError(char *);
@@ -17,6 +18,9 @@
RPySTAT_RESULT *ll_stat_result(int, int, int, int, int, int, int, int, int, int);
void RPYTHON_RAISE_OSERROR(int error);
+RPyListOfString *_RPyListOfString_New(int);
+void _RPyListOfString_SetItem(RPyListOfString *, int, RPyString *);
+
#include <errno.h>
#include <locale.h>
#include <ctype.h>
@@ -25,6 +29,55 @@
#include __PYTHON_H__
// overflows/zeros/values raising operations
-__RAISING_OP__
+__RAISING_OPS__
// Append some genc files here manually from python
+__INCLUDE_FILES__
+
+#ifdef ENTRY_POINT_DEFINED
+
+#include <gc/gc.h>
+
+char *RPython_StartupCode() {
+ GC_all_interior_pointers = 0;
+ return NULL;
+}
+
+int entry_point(RPyListOfString *);
+
+int main(int argc, char *argv[])
+{
+ char *errmsg;
+ int i, exitcode;
+ RPyListOfString *list;
+ errmsg = RPython_StartupCode();
+ if (errmsg) goto error;
+
+ list = _RPyListOfString_New(argc);
+ if (RPyExceptionOccurred()) goto memory_out;
+ for (i=0; i<argc; i++) {
+ RPyString *s = RPyString_FromString(argv[i]);
+
+ if (RPyExceptionOccurred()) {
+ goto memory_out;
+ }
+
+ _RPyListOfString_SetItem(list, i, s);
+ }
+
+ exitcode = entry_point(list);
+
+ if (RPyExceptionOccurred()) {
+ goto error; // XXX see genc
+ }
+ return exitcode;
+
+ memory_out:
+ errmsg = "out of memory";
+ error:
+ fprintf(stderr, "Fatal error during initialization: %s\n", errmsg);
+ return 1;
+}
+
+#endif /* ENTRY_POINT_DEFINED */
+
Modified: pypy/dist/pypy/translator/llvm/module/support.py
==============================================================================
--- pypy/dist/pypy/translator/llvm/module/support.py (original)
+++ pypy/dist/pypy/translator/llvm/module/support.py Thu Nov 17 16:23:04 2005
@@ -13,27 +13,26 @@
declare ccc void %llvm.memcpy(sbyte*, sbyte*, uint, uint)
"""
-extfunctions = {}
-
-extfunctions["%RPyString_AsString"] = """
+extfunctions = """
internal fastcc sbyte* %RPyString_AsString(%RPyString* %structstring) {
%source1ptr = getelementptr %RPyString* %structstring, int 0, uint 1, uint 1
%source1 = cast [0 x sbyte]* %source1ptr to sbyte*
ret sbyte* %source1
}
-"""
-
-extfunctions["%RPyString_Size"] = """
internal fastcc int %RPyString_Size(%RPyString* %structstring) {
%sizeptr = getelementptr %RPyString* %structstring, int 0, uint 1, uint 0
%size = load int* %sizeptr
ret int %size
}
-"""
+internal fastcc int %RPyExceptionOccurred() {
+ %tmp.0 = load %RPYTHON_EXCEPTION_VTABLE** %last_exception_type
+ %bool_res = setne %RPYTHON_EXCEPTION_VTABLE* %tmp.0, null
+ %res = cast bool %bool_res to int
+ ret int %res
+}
-extfunctions["%RPyString_FromString"] = """
internal fastcc %RPyString* %RPyString_FromString(sbyte* %s) {
%lenu = call ccc uint %strlen(sbyte* %s)
%len = cast uint %lenu to int
@@ -46,10 +45,6 @@
ret %RPyString* %rpy
}
-"""
-
-# abs functions
-extfunctions["%pypyop_int_abs"] = """
internal fastcc int %pypyop_int_abs(int %x) {
block0:
%cond1 = setge int %x, 0
@@ -62,9 +57,7 @@
ret int %result
}
-"""
-extfunctions["%pypyop_float_abs"] = """
internal fastcc double %pypyop_float_abs(double %x) {
block0:
%cond1 = setge double %x, 0.0
@@ -77,12 +70,25 @@
ret double %result
}
+;; functions that should return a bool according to
+;; pypy/rpython/extfunctable.py , but C doesn't have bools!
+
+internal fastcc bool %LL_os_isatty(int %fd) {
+ %t = call fastcc int %LL_os_isatty(int %fd)
+ %b = cast int %t to bool
+ ret bool %b
+}
+internal fastcc bool %LL_stack_too_big() {
+ %t = call fastcc int %LL_stack_too_big()
+ %b = cast int %t to bool
+ ret bool %b
+}
"""
# prepare exceptions
for exc in "ZeroDivisionError OverflowError ValueError".split():
- extfunctions["%%prepare_%(exc)s" % locals()] = """
+ extfunctions += """
internal fastcc void %%prepare_%(exc)s() {
%%exception_value = cast %%structtype.%(exc)s* %%structinstance.%(exc)s to %%RPYTHON_EXCEPTION*
%%tmp = getelementptr %%RPYTHON_EXCEPTION* %%exception_value, int 0, uint 0
@@ -93,11 +99,9 @@
}
""" % locals()
-
-# prepare and raise exceptions (%msg not used right now!)
for exc in "IOError ZeroDivisionError " \
"OverflowError ValueError RuntimeError".split():
- extfunctions["%%raisePyExc_%(exc)s" % locals()] = """
+ extfunctions += """
internal fastcc void %%raisePyExc_%(exc)s(sbyte* %%msg) {
%%exception_value = cast %%structtype.%(exc)s* %%structinstance.%(exc)s to %%RPYTHON_EXCEPTION*
%%tmp = getelementptr %%RPYTHON_EXCEPTION* %%exception_value, int 0, uint 0
@@ -107,41 +111,4 @@
call fastcc void %%unwind()
ret void
}
-""" % locals()
-
-# main functions to be moved to genexterns
-# XXX rewrite these in C
-entry_functions = {}
-
-entry_functions["main_noargs"] = """
-int %main(int %argc, sbyte** %argv) {
- store int 0, int* %GC_all_interior_pointers
- %ret = call fastcc int %pypy_main_noargs()
- ret int %ret
-}
-"""
-
-entry_functions["entry_point"] = """
-int %main(int %argc, sbyte** %argv) {
-entry:
- store int 0, int* %GC_all_interior_pointers
- %pypy_argv = call fastcc %RPyListOfString* %pypy__RPyListOfString_New__Signed(int %argc)
- br label %no_exit
-
-no_exit:
- %indvar = phi uint [ %indvar.next, %no_exit ], [ 0, %entry ]
- %i.0.0 = cast uint %indvar to int
- %tmp.8 = getelementptr sbyte** %argv, uint %indvar
- %tmp.9 = load sbyte** %tmp.8
- %rpy = call fastcc %RPyString* %RPyString_FromString(sbyte* %tmp.9)
- call fastcc void %pypy__RPyListOfString_SetItem__listPtr_Signed_rpy_stringPtr(%RPyListOfString* %pypy_argv, int %i.0.0, %RPyString* %rpy)
- %inc = add int %i.0.0, 1
- %tmp.2 = setlt int %inc, %argc
- %indvar.next = add uint %indvar, 1
- br bool %tmp.2, label %no_exit, label %loopexit
-
-loopexit:
- %ret = call fastcc int %pypy_entry_point(%RPyListOfString* %pypy_argv)
- ret int %ret
-}
-"""
+""" % locals()
Modified: pypy/dist/pypy/translator/llvm/opwriter.py
==============================================================================
--- pypy/dist/pypy/translator/llvm/opwriter.py (original)
+++ pypy/dist/pypy/translator/llvm/opwriter.py Thu Nov 17 16:23:04 2005
@@ -1,6 +1,5 @@
from pypy.objspace.flow.model import Constant
from pypy.rpython.lltypesystem import lltype
-from pypy.translator.llvm.module.support import extfunctions
from pypy.translator.llvm.extfuncnode import ExternalFuncNode
from pypy.translator.llvm.log import log
log = log.opwriter
More information about the Pypy-commit
mailing list