[Scipy-svn] r4507 - in trunk/scipy/sandbox/mkufunc: . examples mkufunc

scipy-svn at scipy.org scipy-svn at scipy.org
Mon Jun 30 20:32:14 EDT 2008


Author: ilan
Date: 2008-06-30 19:32:12 -0500 (Mon, 30 Jun 2008)
New Revision: 4507

Added:
   trunk/scipy/sandbox/mkufunc/TODO.txt
   trunk/scipy/sandbox/mkufunc/docs/
   trunk/scipy/sandbox/mkufunc/examples/
   trunk/scipy/sandbox/mkufunc/examples/benchmark.py
   trunk/scipy/sandbox/mkufunc/examples/primes.py
   trunk/scipy/sandbox/mkufunc/mkufunc/
   trunk/scipy/sandbox/mkufunc/mkufunc/__init__.py
   trunk/scipy/sandbox/mkufunc/mkufunc/api.py
   trunk/scipy/sandbox/mkufunc/mkufunc/driver.py
   trunk/scipy/sandbox/mkufunc/mkufunc/interactive.py
   trunk/scipy/sandbox/mkufunc/mkufunc/pypy.h
   trunk/scipy/sandbox/mkufunc/mkufunc/test_func_hash.py
   trunk/scipy/sandbox/mkufunc/mkufunc/test_mkufunc.py
   trunk/scipy/sandbox/mkufunc/setup.py
Log:
Made a package which uses setuptools

Added: trunk/scipy/sandbox/mkufunc/TODO.txt
===================================================================

Added: trunk/scipy/sandbox/mkufunc/examples/benchmark.py
===================================================================
--- trunk/scipy/sandbox/mkufunc/examples/benchmark.py	2008-06-30 19:19:55 UTC (rev 4506)
+++ trunk/scipy/sandbox/mkufunc/examples/benchmark.py	2008-07-01 00:32:12 UTC (rev 4507)
@@ -0,0 +1,49 @@
+#!/usr/bin/env python
+from math import sin, cos
+import time
+
+from numpy import arange, vectorize, allclose
+from scipy import weave
+
+from mkufunc.api import mkufunc
+
+
+def f(x):
+    return 4.2 * x * x + 3.7 * x + 1.5
+
+
+vfunc = vectorize(f)
+
+ufunc = mkufunc([(float, float)])(f)
+
+
+x = arange(0, 1000, 0.001)    #print "x =", x, x.dtype
+
+start_time = time.time()
+b_y = x.copy()
+weave.blitz("b_y[:] = 4.2 * x[:] * x[:] + 3.7 * x[:] + 1.5")
+b_time = time.time() - start_time
+print 'blitz: %.6f sec' % b_time
+
+start_time = time.time()
+n_y = f(x)
+n_time = time.time() - start_time
+print 'numpy: %.6f sec' % n_time
+
+start_time = time.time()
+v_y = vfunc(x)
+v_time = time.time() - start_time
+print 'vectorize: %.6f sec' % v_time
+
+start_time = time.time()
+u_y = ufunc(x)
+u_time = time.time() - start_time
+print 'mkufunc: %.6f sec' % u_time
+
+print "speedup over blitz:",     b_time/u_time
+print "speedup over numpy:",     n_time/u_time
+print "speedup over vectorize:", v_time/u_time
+
+assert allclose(b_y, n_y)
+assert allclose(v_y, n_y)
+assert allclose(u_y, n_y)


Property changes on: trunk/scipy/sandbox/mkufunc/examples/benchmark.py
___________________________________________________________________
Name: svn:executable
   + *

Added: trunk/scipy/sandbox/mkufunc/examples/primes.py
===================================================================
--- trunk/scipy/sandbox/mkufunc/examples/primes.py	2008-06-30 19:19:55 UTC (rev 4506)
+++ trunk/scipy/sandbox/mkufunc/examples/primes.py	2008-07-01 00:32:12 UTC (rev 4507)
@@ -0,0 +1,29 @@
+#!/usr/bin/env python
+from math import sqrt
+import time
+
+from numpy import arange
+
+from mkufunc.api import mkufunc
+
+
+def is_prime(n):
+    if n < 2:
+        return 0
+    for i in xrange(2, min(n, int(sqrt(n)+2.0))):
+        if n %i == 0:
+            return 0
+    return 1
+
+
+start_time = time.time()
+assert sum(is_prime(n) for n in xrange(1000000)) == 78498
+print 'Python: %.6f sec' % (time.time() - start_time)
+
+
+is_prime = mkufunc(int)(is_prime)
+
+
+start_time = time.time()
+assert is_prime(arange(1000000)).sum() == 78498
+print 'Compiled: %.6f sec' % (time.time() - start_time)


Property changes on: trunk/scipy/sandbox/mkufunc/examples/primes.py
___________________________________________________________________
Name: svn:executable
   + *

Added: trunk/scipy/sandbox/mkufunc/mkufunc/__init__.py
===================================================================

Added: trunk/scipy/sandbox/mkufunc/mkufunc/api.py
===================================================================
--- trunk/scipy/sandbox/mkufunc/mkufunc/api.py	2008-06-30 19:19:55 UTC (rev 4506)
+++ trunk/scipy/sandbox/mkufunc/mkufunc/api.py	2008-07-01 00:32:12 UTC (rev 4507)
@@ -0,0 +1,346 @@
+""" mkufunc (make U function)
+
+
+Author: Ilan Schnell (with help from Travis Oliphant and Eric Jones)
+"""
+import sys
+import re
+import os, os.path
+import cStringIO
+import hashlib
+from types import FunctionType
+
+import numpy
+from scipy import weave
+
+
+verbose = 0
+
+def func_hash(f, salt=None):
+    """ Return a MD5 hash for a function object as string.
+    """
+    co = f.func_code
+    return hashlib.md5(co.co_code + repr(co.co_names) + repr(salt)
+                       ).hexdigest()
+
+
+def translate(f, argtypes):
+    """ Return pypy's C output for a given function and argument types.
+        The cache files are in weave's directory.
+    """
+    cache_file_name = os.path.join(weave.catalog.default_dir(),
+                                   'pypy_%s.c' % func_hash(f, salt=argtypes))
+    try:
+        return open(cache_file_name).read()
+    
+    except IOError:
+        from interactive import Translation
+        
+        t = Translation(f, backend='c')
+        t.annotate(argtypes)
+        t.source()
+        
+        os.rename(t.driver.c_source_filename, cache_file_name)
+        
+        return translate(f, argtypes)
+
+
+class Ctype:
+    def __init__(self, npy, c):
+        self.npy = npy
+        self.c = c
+
+typedict = {
+    int:    Ctype('NPY_LONG',   'long'  ),
+    float:  Ctype('NPY_DOUBLE', 'double'),
+}
+
+
+class Cfunc(object):
+    """ C compiled python functions
+
+    >>> def sqr(x):
+    ...     return x * x
+
+    >>> signature = [int, int] # only the input arguments are used here
+    
+    compilation is done upon initialization
+    >>> x = Cfunc(sqr, signature, 123)
+    ...
+    >>> x.nin # number of input arguments
+    1
+    >>> x.nout # number of output arguments (must be 1 for now)
+    1
+    >>> x.sig
+    [<type 'int'>, <type 'int'>]
+    
+    Attributes:
+        f           -- the Python function object
+        n           -- id number
+        sig         -- signature
+        nin         -- number of input arguments
+        nout        -- number of output arguments
+        cname       -- name of the C function
+
+    Methods:
+        decl()      -- returns the C declaration for the function
+        cfunc()     -- returns the C function (as string)
+        ufunc_support_code()
+                    -- generate the C support code to make this
+                       function part work with PyUFuncGenericFunction
+    """
+    def __init__(self, f, signature, n):
+        self.f = f
+        self.n = n
+        self.sig = signature
+        self.nin = f.func_code.co_argcount
+        self.nout = len(self.sig) - self.nin
+        assert self.nout == 1                  # for now
+        
+        src = translate(f, signature[:self.nin])
+        
+        self._prefix = 'f%i_' % self.n
+        self._allCsrc = src.replace('pypy_', self._prefix + 'pypy_')
+        self.cname = self._prefix + 'pypy_g_' + f.__name__
+
+    def cfunc(self):
+        p = re.compile(r'^\w+[*\s\w]+' + self.cname +
+                       r'\s*\([^)]*\)\s*\{.*?[\n\r]\}[\n\r]',
+                       re.DOTALL | re.MULTILINE | re.VERBOSE)
+        
+        found = p.findall(self._allCsrc)
+        assert len(found) == 1
+        res = found[0]
+        res = res.replace(self._prefix + 'pypy_g_ll_math_ll_math_', '')
+        return 'inline ' + res + '\n'
+    
+    def ufunc_support_code(self):
+        # Unfortunately the code in here is very hard to read.
+        # In order to make the code clearer, one would need a real template
+        # engine link Cheetah (http://cheetahtemplate.org/).
+        # However, somehting like that would be too much overhead for scipy.
+        n = self.n
+        nin = self.nin
+        cname = self.cname
+
+        def varname(i):
+            return chr(i + ord('a'))
+        
+        declargs = ', '.join('%s %s' % (typedict[self.sig[i]].c, varname(i))
+                             for i in xrange(self.nin))
+        
+        args = ', '.join(varname(i) for i in xrange(self.nin))
+        
+        isn_steps = '\n\t'.join('npy_intp is%i = steps[%i];' % (i, i)
+                                for i in xrange(self.nin))
+        
+        ipn_args = '\n\t'.join('char *ip%i = args[%i];' % (i, i)
+                               for i in xrange(self.nin))
+        
+        body1d_in = '\n\t\t'.join('%s *in%i = (%s *)ip%i;' %
+                                  (2*(typedict[self.sig[i]].c, i))
+                                  for i in xrange(self.nin))
+        
+        body1d_add = '\n\t\t'.join('ip%i += is%i;' % (i, i)
+                                   for i in xrange(self.nin))
+        
+        ptrargs = ', '.join('*in%i' % i for i in xrange(self.nin))
+        
+        rettype = typedict[self.sig[-1]].c
+        
+        return '''
+static %(rettype)s wrap_%(cname)s(%(declargs)s)
+{
+	return %(cname)s(%(args)s);
+}
+
+typedef %(rettype)s Func_%(n)i(%(declargs)s);
+
+static void
+PyUFunc_%(n)i(char **args, npy_intp *dimensions, npy_intp *steps, void *func)
+{
+	npy_intp i, n;
+        %(isn_steps)s
+	npy_intp os = steps[%(nin)s];
+        %(ipn_args)s
+	char *op = args[%(nin)s];
+	Func_%(n)i *f = (Func_%(n)i *) func;
+	n = dimensions[0];
+        
+	for(i = 0; i < n; i++) {
+		%(body1d_in)s
+		%(rettype)s *out = (%(rettype)s *)op;
+		
+		*out = (%(rettype)s) f(%(ptrargs)s);
+
+                %(body1d_add)s
+                op += os;
+	}
+}
+''' % locals()
+
+
+def support_code(cfuncs):
+    """ Given a list of Cfunc instances, return the support code for weave.
+    """
+    acc = cStringIO.StringIO()
+    
+    acc.write('/********************* start pypy.h  **************/\n\n')
+    acc.write(open(os.path.join(os.path.dirname(__file__),
+                                'pypy.h')).read())
+    acc.write('/********************** end pypy.h ****************/\n\n')
+    
+    for cf in cfuncs:
+        acc.write(cf.cfunc())
+        acc.write(cf.ufunc_support_code())
+        
+    fname = cfuncs[0].f.__name__
+    
+    pyufuncs = ''.join('\tPyUFunc_%i,\n' % cf.n for cf in cfuncs)
+    
+    data = ''.join('\t(void *) wrap_%s,\n' % cf.cname for cf in cfuncs)
+    
+    types = ''.join('\t%s  /* %i */\n' %
+                    (''.join(typedict[t].npy + ', ' for t in cf.sig), cf.n)
+                    for cf in cfuncs)
+    
+    acc.write('''
+static PyUFuncGenericFunction %(fname)s_functions[] = {
+%(pyufuncs)s};
+
+static void *%(fname)s_data[] = {
+%(data)s};
+
+static char %(fname)s_types[] = {
+%(types)s};
+''' % locals())
+
+    if verbose:
+        print '------------------ start support_code -----------------'
+        print acc.getvalue()
+        print '------------------- end support_code ------------------'
+        
+    return acc.getvalue()
+
+
+def code(f, signatures):
+    """ Return the code for weave.
+    """
+    nin = f.func_code.co_argcount
+    ntypes = len(signatures)
+    fname = f.__name__
+    fhash = func_hash(f)
+    
+    res = '''
+import_ufunc();
+
+/****************************************************************************
+**  function name: %(fname)s
+**  signatures: %(signatures)r
+**  fhash: %(fhash)s
+*****************************************************************************/
+
+return_val = PyUFunc_FromFuncAndData(
+    %(fname)s_functions,
+    %(fname)s_data,
+    %(fname)s_types,
+    %(ntypes)i,      /* ntypes */
+    %(nin)i,         /* nin */
+    1,               /* nout */
+    PyUFunc_None,    /* identity */
+    "%(fname)s",     /* name */
+    "UFunc created by mkufunc", /* doc */
+    0);
+''' % locals()
+
+    if verbose:
+        print '---------------------- start code ---------------------'
+        print res
+        print '----------------------- end code ----------------------'
+
+    return res
+
+
+def genufunc(f, signatures):
+    """ Return the Ufunc Python object for given function and signatures.
+    """
+    if len(signatures) == 0:
+        raise ValueError("At least one signature needed")
+    
+    signatures.sort(key=lambda sig: [numpy.dtype(typ).num for typ in sig])
+    
+    cfuncs = [Cfunc(f, sig, n) for n, sig in enumerate(signatures)]
+    
+    ufunc_info = weave.base_info.custom_info()
+    ufunc_info.add_header('"numpy/ufuncobject.h"')
+    
+    return weave.inline(code(f, signatures),
+                        verbose=verbose,
+                        support_code=support_code(cfuncs),
+                        customize=ufunc_info)
+
+
+def mkufunc(arg0=[float]):
+    """ Python decorator which returns compiled UFunc of the function given.
+    
+    >>> from numpy import arange
+    >>> from mkufunc.api import mkufunc
+    >>> @mkufunc
+    ... def foo(x):
+    ...     return 4.2 * x * x - x + 6.3
+    ...
+    >>> a = arange(5)
+    >>> a
+    array([0, 1, 2, 3, 4])
+    >>> foo(a)
+    array([  6.3,   9.5,  21.1,  41.1,  69.5])
+    """
+    class UFunc(object):
+        
+        def __init__(self, f):
+            nin = f.func_code.co_argcount
+            nout = 1
+            for i, sig in enumerate(signatures):
+                if isinstance(sig, tuple):
+                    pass
+                elif sig in typedict.keys():
+                    signatures[i] = (nin + nout) * (sig,)
+                else:
+                    raise TypeError("no match for %r" % sig)
+                
+            for sig in signatures:
+                assert isinstance(sig, tuple)
+                if len(sig) != nin + nout:
+                    raise TypeError("signature %r does not match the "
+                                    "number of args of function %s" %
+                                    (sig, f.__name__))
+                for t in sig:
+                    if t not in typedict.keys():
+                        raise TypeError("no match for %r" % t)
+            
+            self.ufunc = genufunc(f, signatures)
+            
+        def __call__(self, *args):
+            return self.ufunc(*args)
+        
+    if isinstance(arg0, FunctionType):
+        f = arg0
+        signatures = [float]
+        return UFunc(f)
+    
+    elif isinstance(arg0, list):
+        signatures = arg0
+        return UFunc
+    
+    elif arg0 in typedict.keys():
+        signatures = [arg0]
+        return UFunc
+    
+    else:
+        raise TypeError("first argument has to be a function, a type, or "
+                        "a list of signatures")
+
+
+if __name__ == '__main__':
+    import doctest
+    doctest.testmod()

Added: trunk/scipy/sandbox/mkufunc/mkufunc/driver.py
===================================================================
--- trunk/scipy/sandbox/mkufunc/mkufunc/driver.py	2008-06-30 19:19:55 UTC (rev 4506)
+++ trunk/scipy/sandbox/mkufunc/mkufunc/driver.py	2008-07-01 00:32:12 UTC (rev 4507)
@@ -0,0 +1,728 @@
+import sys, os
+
+from pypy.translator.translator import TranslationContext, graphof
+from pypy.translator.tool.taskengine import SimpleTaskEngine
+from pypy.translator.goal import query
+from pypy.translator.goal.timing import Timer
+from pypy.annotation import model as annmodel
+from pypy.annotation.listdef import s_list_of_strings
+from pypy.annotation import policy as annpolicy
+from py.compat import optparse
+from pypy.tool.udir import udir
+
+import py
+from pypy.tool.ansi_print import ansi_log
+log = py.log.Producer("translation")
+py.log.setconsumer("translation", ansi_log)
+
+DEFAULTS = {
+  'translation.gc': 'ref',
+  'translation.cc': None,
+  'translation.profopt': None,
+
+  'translation.thread': False, # influences GC policy
+
+  'translation.stackless': False,
+  'translation.debug': True,
+  'translation.insist': False,
+  'translation.backend': 'c',
+  'translation.fork_before': None,
+  'translation.backendopt.raisingop2direct_call' : False,
+  'translation.backendopt.merge_if_blocks': True,
+}
+
+
+def taskdef(taskfunc, deps, title, new_state=None, expected_states=[],
+            idemp=False, earlycheck=None):
+    taskfunc.task_deps = deps
+    taskfunc.task_title = title
+    taskfunc.task_newstate = None
+    taskfunc.task_expected_states = expected_states
+    taskfunc.task_idempotent = idemp
+    taskfunc.task_earlycheck = earlycheck
+    return taskfunc
+
+# TODO:
+# sanity-checks using states
+
+_BACKEND_TO_TYPESYSTEM = {
+    'c': 'lltype',
+    'llvm': 'lltype'
+}
+
+def backend_to_typesystem(backend):
+    return _BACKEND_TO_TYPESYSTEM.get(backend, 'ootype')
+
+# set of translation steps to profile
+PROFILE = set([])
+
+class Instrument(Exception):
+    pass
+
+
+class ProfInstrument(object):
+    name = "profinstrument"
+    def __init__(self, datafile, compiler):
+        self.datafile = datafile
+        self.compiler = compiler
+
+    def first(self):
+        self.compiler._build()
+
+    def probe(self, exe, args):
+        from py.compat import subprocess
+        env = os.environ.copy()
+        env['_INSTRUMENT_COUNTERS'] = str(self.datafile)
+        subprocess.call("'%s' %s" % (exe, args), env=env, shell=True)
+        
+    def after(self):
+        # xxx
+        os._exit(0)
+
+
+class TranslationDriver(SimpleTaskEngine):
+
+    def __init__(self, setopts=None, default_goal=None,
+                 disable=[],
+                 exe_name=None, extmod_name=None,
+                 config=None, overrides=None):
+        self.timer = Timer()
+        SimpleTaskEngine.__init__(self)
+
+        self.log = log
+
+        if config is None:
+            from pypy.config.pypyoption import get_pypy_config
+            config = get_pypy_config(DEFAULTS, translating=True)
+        self.config = config
+        if overrides is not None:
+            self.config.override(overrides)
+
+        if setopts is not None:
+            self.config.set(**setopts)
+        
+        self.exe_name = exe_name
+        self.extmod_name = extmod_name
+
+        self.done = {}
+
+        self.disable(disable)
+
+        if default_goal:
+            default_goal, = self.backend_select_goals([default_goal])
+            if default_goal in self._maybe_skip():
+                default_goal = None
+        
+        self.default_goal = default_goal
+        self.extra_goals = []
+        self.exposed = []
+
+        # expose tasks
+        def expose_task(task, backend_goal=None):
+            if backend_goal is None:
+                backend_goal = task
+            def proc():
+                return self.proceed(backend_goal)
+            self.exposed.append(task)
+            setattr(self, task, proc)
+
+        backend, ts = self.get_backend_and_type_system()
+        for task in self.tasks:
+            explicit_task = task
+            parts = task.split('_')
+            if len(parts) == 1:
+                if task in ('annotate'):
+                    expose_task(task)
+            else:
+                task, postfix = parts
+                if task in ('rtype', 'backendopt', 'llinterpret',
+                            'prehannotatebackendopt', 'hintannotate',
+                            'timeshift'):
+                    if ts:
+                        if ts == postfix:
+                            expose_task(task, explicit_task)
+                    else:
+                        expose_task(explicit_task)
+                elif task in ('source', 'compile', 'run'):
+                    if backend:
+                        if backend == postfix:
+                            expose_task(task, explicit_task)
+                    elif ts:
+                        if ts == backend_to_typesystem(postfix):
+                            expose_task(explicit_task)
+                    else:
+                        expose_task(explicit_task)
+
+    def set_extra_goals(self, goals):
+        self.extra_goals = goals
+
+    def get_info(self): # XXX more?
+        d = {'backend': self.config.translation.backend}
+        return d
+
+    def get_backend_and_type_system(self):
+        type_system = self.config.translation.type_system
+        backend = self.config.translation.backend
+        return backend, type_system
+
+    def backend_select_goals(self, goals):
+        backend, ts = self.get_backend_and_type_system()
+        postfixes = [''] + ['_'+p for p in (backend, ts) if p]
+        l = []
+        for goal in goals:
+            for postfix in postfixes:
+                cand = "%s%s" % (goal, postfix)
+                if cand in self.tasks:
+                    new_goal = cand
+                    break
+            else:
+                raise Exception, "cannot infer complete goal from: %r" % goal 
+            l.append(new_goal)
+        return l
+
+    def disable(self, to_disable):
+        self._disabled = to_disable
+
+    def _maybe_skip(self):
+        maybe_skip = []
+        if self._disabled:
+             for goal in  self.backend_select_goals(self._disabled):
+                 maybe_skip.extend(self._depending_on_closure(goal))
+        return dict.fromkeys(maybe_skip).keys()
+
+
+    def setup(self, entry_point, inputtypes, policy=None, extra={}, empty_translator=None):
+        standalone = inputtypes is None
+        self.standalone = standalone
+
+        if standalone:
+            inputtypes = [s_list_of_strings]
+        self.inputtypes = inputtypes
+
+        if policy is None:
+            policy = annpolicy.AnnotatorPolicy()
+        if standalone:
+            policy.allow_someobjects = False
+        self.policy = policy
+
+        self.extra = extra
+
+        if empty_translator:
+            translator = empty_translator
+        else:
+            translator = TranslationContext(config=self.config)
+
+        self.entry_point = entry_point
+        self.translator = translator
+        self.libdef = None
+
+        self.translator.driver_instrument_result = self.instrument_result
+
+    def setup_library(self, libdef, policy=None, extra={}, empty_translator=None):
+        self.setup(None, None, policy, extra, empty_translator)
+        self.libdef = libdef
+
+    def instrument_result(self, args):
+        backend, ts = self.get_backend_and_type_system()
+        if backend != 'c' or sys.platform == 'win32':
+            raise Exception("instrumentation requires the c backend"
+                            " and unix for now")
+        from pypy.tool.udir import udir
+        
+        datafile = udir.join('_instrument_counters')
+        makeProfInstrument = lambda compiler: ProfInstrument(datafile, compiler)
+
+        pid = os.fork()
+        if pid == 0:
+            # child compiling and running with instrumentation
+            self.config.translation.instrument = True
+            self.config.translation.instrumentctl = (makeProfInstrument,
+                                                     args)
+            raise Instrument
+        else:
+            pid, status = os.waitpid(pid, 0)
+            if os.WIFEXITED(status):
+                status = os.WEXITSTATUS(status)
+                if status != 0:
+                    raise Exception, "instrumentation child failed: %d" % status
+            else:
+                raise Exception, "instrumentation child aborted"
+            import array, struct
+            n = datafile.size()//struct.calcsize('L')
+            datafile = datafile.open('rb')
+            counters = array.array('L')
+            counters.fromfile(datafile, n)
+            datafile.close()
+            return counters
+
+    def info(self, msg):
+        log.info(msg)
+
+    def _profile(self, goal, func):
+        from cProfile import Profile
+        from pypy.tool.lsprofcalltree import KCacheGrind
+        d = {'func':func}
+        prof = Profile()
+        prof.runctx("res = func()", globals(), d)
+        KCacheGrind(prof).output(open(goal + ".out", "w"))
+        return d['res']
+
+    def _do(self, goal, func, *args, **kwds):
+        title = func.task_title
+        if goal in self.done:
+            self.log.info("already done: %s" % title)
+            return
+        else:
+            self.log.info("%s..." % title)
+        self.timer.start_event(goal)
+        try:
+            instrument = False
+            try:
+                if goal in PROFILE:
+                    res = self._profile(goal, func)
+                else:
+                    res = func()
+            except Instrument:
+                instrument = True
+            if not func.task_idempotent:
+                self.done[goal] = True
+            if instrument:
+                self.proceed('compile')
+                assert False, 'we should not get here'
+        finally:
+            self.timer.end_event(goal)
+        return res
+
+    def task_annotate(self):
+        # includes annotation and annotatation simplifications
+        translator = self.translator
+        policy = self.policy
+        self.log.info('with policy: %s.%s' %
+                      (policy.__class__.__module__, policy.__class__.__name__))
+        
+        annmodel.DEBUG = self.config.translation.debug
+        annotator = translator.buildannotator(policy=policy)
+
+        if self.entry_point:
+            s = annotator.build_types(self.entry_point, self.inputtypes)
+
+            self.sanity_check_annotation()
+            if self.standalone and s.knowntype != int:
+                raise Exception("stand-alone program entry point must return an "
+                                "int (and not, e.g., None or always raise an "
+                                "exception).")
+            annotator.simplify()
+            return s
+        else:
+            assert self.libdef is not None
+            for func, inputtypes in self.libdef.functions:
+                annotator.build_types(func, inputtypes)
+            self.sanity_check_annotation()
+            annotator.simplify()
+    #
+    task_annotate = taskdef(task_annotate, [], "Annotating&simplifying")
+
+
+    def sanity_check_annotation(self):
+        translator = self.translator
+        irreg = query.qoutput(query.check_exceptblocks_qgen(translator))
+        if irreg:
+            self.log.info("Some exceptblocks seem insane")
+
+        lost = query.qoutput(query.check_methods_qgen(translator))
+        assert not lost, "lost methods, something gone wrong with the annotation of method defs"
+
+        so = query.qoutput(query.polluted_qgen(translator))
+        tot = len(translator.graphs)
+        percent = int(tot and (100.0*so / tot) or 0)
+        # if there are a few SomeObjects even if the policy doesn't allow
+        # them, it means that they were put there in a controlled way
+        # and then it's not a warning.
+        if not translator.annotator.policy.allow_someobjects:
+            pr = self.log.info
+        elif percent == 0:
+            pr = self.log.info
+        else:
+            pr = log.WARNING
+        pr("-- someobjectness %2d%% (%d of %d functions polluted by SomeObjects)" % (percent, so, tot))
+
+
+
+    def task_rtype_lltype(self):
+        rtyper = self.translator.buildrtyper(type_system='lltype')
+        insist = not self.config.translation.insist
+        rtyper.specialize(dont_simplify_again=True,
+                          crash_on_first_typeerror=insist)
+    #
+    task_rtype_lltype = taskdef(task_rtype_lltype, ['annotate'], "RTyping")
+    RTYPE = 'rtype_lltype'
+
+    def task_rtype_ootype(self):
+        # Maybe type_system should simply be an option used in task_rtype
+        insist = not self.config.translation.insist
+        rtyper = self.translator.buildrtyper(type_system="ootype")
+        rtyper.specialize(dont_simplify_again=True,
+                          crash_on_first_typeerror=insist)
+    #
+    task_rtype_ootype = taskdef(task_rtype_ootype, ['annotate'], "ootyping")
+    OOTYPE = 'rtype_ootype'
+
+    def task_prehannotatebackendopt_lltype(self):
+        from pypy.translator.backendopt.all import backend_optimizations
+        backend_optimizations(self.translator,
+                              inline_threshold=0,
+                              merge_if_blocks=True,
+                              constfold=True,
+                              raisingop2direct_call=False,
+                              remove_asserts=True)
+    #
+    task_prehannotatebackendopt_lltype = taskdef(
+        task_prehannotatebackendopt_lltype,
+        [RTYPE],
+        "Backendopt before Hint-annotate")
+
+    def task_hintannotate_lltype(self):
+        from pypy.jit.hintannotator.annotator import HintAnnotator
+        from pypy.jit.hintannotator.model import OriginFlags
+        from pypy.jit.hintannotator.model import SomeLLAbstractConstant
+
+        get_portal = self.extra['portal']
+        PORTAL, POLICY = get_portal(self)
+        t = self.translator
+        self.portal_graph = graphof(t, PORTAL)
+
+        hannotator = HintAnnotator(base_translator=t, policy=POLICY)
+        self.hint_translator = hannotator.translator
+        hs = hannotator.build_types(self.portal_graph,
+                                    [SomeLLAbstractConstant(v.concretetype,
+                                                            {OriginFlags(): True})
+                                     for v in self.portal_graph.getargs()])
+        count = hannotator.bookkeeper.nonstuboriggraphcount
+        stubcount = hannotator.bookkeeper.stuboriggraphcount
+        self.log.info("The hint-annotator saw %d graphs"
+                      " (and made stubs for %d graphs)." % (count, stubcount))
+        n = len(list(hannotator.translator.graphs[0].iterblocks()))
+        self.log.info("portal has %d blocks" % n)
+        self.hannotator = hannotator
+    #
+    task_hintannotate_lltype = taskdef(task_hintannotate_lltype,
+                                       ['prehannotatebackendopt_lltype'],
+                                       "Hint-annotate")
+
+    def task_timeshift_lltype(self):
+        from pypy.jit.timeshifter.hrtyper import HintRTyper
+        from pypy.jit.codegen import detect_cpu
+        cpu = detect_cpu.autodetect()
+        if cpu == 'i386':
+            from pypy.jit.codegen.i386.rgenop import RI386GenOp as RGenOp
+            RGenOp.MC_SIZE = 32 * 1024 * 1024
+        elif cpu == 'ppc':
+            from pypy.jit.codegen.ppc.rgenop import RPPCGenOp as RGenOp
+            RGenOp.MC_SIZE = 32 * 1024 * 1024
+        else:
+            raise Exception('Unsuported cpu %r'%cpu)
+
+        del self.hint_translator
+        ha = self.hannotator
+        t = self.translator
+        # make the timeshifted graphs
+        hrtyper = HintRTyper(ha, t.rtyper, RGenOp)
+        hrtyper.specialize(origportalgraph=self.portal_graph, view=False)
+    #
+    task_timeshift_lltype = taskdef(task_timeshift_lltype,
+                             ["hintannotate_lltype"],
+                             "Timeshift")
+
+    def task_backendopt_lltype(self):
+        from pypy.translator.backendopt.all import backend_optimizations
+        backend_optimizations(self.translator)
+    #
+    task_backendopt_lltype = taskdef(task_backendopt_lltype,
+                                     [RTYPE,
+                                      '??timeshift_lltype'],
+                                     "lltype back-end optimisations")
+    BACKENDOPT = 'backendopt_lltype'
+
+    def task_backendopt_ootype(self):
+        from pypy.translator.backendopt.all import backend_optimizations
+        backend_optimizations(self.translator)
+    #
+    task_backendopt_ootype = taskdef(task_backendopt_ootype, 
+                                        [OOTYPE], "ootype back-end optimisations")
+    OOBACKENDOPT = 'backendopt_ootype'
+
+
+    def task_stackcheckinsertion_lltype(self):
+        from pypy.translator.transform import insert_ll_stackcheck
+        count = insert_ll_stackcheck(self.translator)
+        self.log.info("inserted %d stack checks." % (count,))
+        
+    task_stackcheckinsertion_lltype = taskdef(
+        task_stackcheckinsertion_lltype,
+        ['?'+BACKENDOPT, RTYPE, 'annotate'],
+        "inserting stack checks")
+    STACKCHECKINSERTION = 'stackcheckinsertion_lltype'
+
+    def possibly_check_for_boehm(self):
+        if self.config.translation.gc == "boehm":
+            from pypy.translator.tool.cbuild import check_boehm_presence
+            from pypy.translator.tool.cbuild import CompilationError
+            try:
+                check_boehm_presence(noerr=False)
+            except CompilationError, e:
+                i = 'Boehm GC not installed.  Try e.g. "translate.py --gc=hybrid"'
+                raise CompilationError('%s\n--------------------\n%s' % (e, i))
+
+    def task_database_c(self):
+        translator = self.translator
+        if translator.annotator is not None:
+            translator.frozen = True
+
+        standalone = self.standalone
+
+        if standalone:
+            from pypy.translator.c.genc import CStandaloneBuilder as CBuilder
+        else:
+            from pypy.translator.c.genc import CExtModuleBuilder as CBuilder
+        cbuilder = CBuilder(self.translator, self.entry_point,
+                            config=self.config)
+        cbuilder.stackless = self.config.translation.stackless
+        if not standalone:     # xxx more messy
+            cbuilder.modulename = self.extmod_name
+        database = cbuilder.build_database()
+        self.log.info("database for generating C source was created")
+        self.cbuilder = cbuilder
+        self.database = database
+    #
+    task_database_c = taskdef(task_database_c,
+                            [STACKCHECKINSERTION, '?'+BACKENDOPT, RTYPE, '?annotate'], 
+                            "Creating database for generating c source",
+                            earlycheck = possibly_check_for_boehm)
+    
+    def task_source_c(self):  # xxx messy
+        translator = self.translator
+        cbuilder = self.cbuilder
+        database = self.database
+        c_source_filename = cbuilder.generate_source(database)
+        self.log.info("written: %s" % (c_source_filename,))
+        self.c_source_filename = str(c_source_filename)
+    #
+    task_source_c = taskdef(task_source_c, ['database_c'], "Generating c source")
+
+    def task_compile_c(self): # xxx messy
+        cbuilder = self.cbuilder
+        cbuilder.compile()
+        
+        if self.standalone:
+            self.c_entryp = cbuilder.executable_name
+            self.create_exe()
+        else:
+            self.c_entryp = cbuilder.get_entry_point()
+    #
+    task_compile_c = taskdef(task_compile_c, ['source_c'], "Compiling c source")
+    
+    
+    def task_run_c(self):
+        self.backend_run('c')
+    #
+    task_run_c = taskdef(task_run_c, ['compile_c'], 
+                         "Running compiled c source",
+                         idemp=True)
+
+    def task_llinterpret_lltype(self):
+        from pypy.rpython.llinterp import LLInterpreter
+        py.log.setconsumer("llinterp operation", None)
+        
+        translator = self.translator
+        interp = LLInterpreter(translator.rtyper)
+        bk = translator.annotator.bookkeeper
+        graph = bk.getdesc(self.entry_point).getuniquegraph()
+        v = interp.eval_graph(graph,
+                              self.extra.get('get_llinterp_args',
+                                             lambda: [])())
+
+        log.llinterpret.event("result -> %s" % v)
+    #
+    task_llinterpret_lltype = taskdef(task_llinterpret_lltype, 
+                                      [STACKCHECKINSERTION, '?'+BACKENDOPT, RTYPE], 
+                                      "LLInterpreting")
+
+    def task_source_llvm(self):
+        translator = self.translator
+        if translator.annotator is None:
+            raise ValueError, "llvm requires annotation."
+
+        from pypy.translator.llvm import genllvm
+
+        self.llvmgen = genllvm.GenLLVM(translator, self.standalone)
+
+        llvm_filename = self.llvmgen.gen_source(self.entry_point)
+        self.log.info("written: %s" % (llvm_filename,))
+    #
+    task_source_llvm = taskdef(task_source_llvm, 
+                               [STACKCHECKINSERTION, BACKENDOPT, RTYPE], 
+                               "Generating llvm source")
+
+    def task_compile_llvm(self):
+        gen = self.llvmgen
+        if self.standalone:
+            exe_name = (self.exe_name or 'testing') % self.get_info()
+            self.c_entryp = gen.compile_standalone(exe_name)
+            self.create_exe()
+        else:
+            self.c_module, self.c_entryp = gen.compile_module()
+    #
+    task_compile_llvm = taskdef(task_compile_llvm, 
+                                ['source_llvm'], 
+                                "Compiling llvm source")
+
+    def task_run_llvm(self):
+        self.backend_run('llvm')
+    #
+    task_run_llvm = taskdef(task_run_llvm, ['compile_llvm'], 
+                            "Running compiled llvm source",
+                            idemp=True)
+
+    def task_source_js(self):
+        from pypy.translator.js.js import JS
+        self.gen = JS(self.translator, functions=[self.entry_point],
+                      stackless=self.config.translation.stackless)
+        filename = self.gen.write_source()
+        self.log.info("Wrote %s" % (filename,))
+    task_source_js = taskdef(task_source_js, 
+                        [OOTYPE],
+                        'Generating Javascript source')
+
+    def task_compile_js(self):
+        pass
+    task_compile_js = taskdef(task_compile_js, ['source_js'],
+                              'Skipping Javascript compilation')
+
+    def task_run_js(self):
+        pass
+    task_run_js = taskdef(task_run_js, ['compile_js'],
+                              'Please manually run the generated code')
+
+    def task_source_cli(self):
+        from pypy.translator.cli.gencli import GenCli
+        from pypy.translator.cli.entrypoint import get_entrypoint
+
+        if self.entry_point is not None: # executable mode
+            entry_point_graph = self.translator.graphs[0]
+            entry_point = get_entrypoint(entry_point_graph)
+        else:
+            # library mode
+            assert self.libdef is not None
+            bk = self.translator.annotator.bookkeeper
+            entry_point = self.libdef.get_entrypoint(bk)
+
+        self.gen = GenCli(udir, self.translator, entry_point, config=self.config)
+        filename = self.gen.generate_source()
+        self.log.info("Wrote %s" % (filename,))
+    task_source_cli = taskdef(task_source_cli, ["?" + OOBACKENDOPT, OOTYPE],
+                             'Generating CLI source')
+
+    def task_compile_cli(self):
+        from pypy.translator.oosupport.support import unpatch_os
+        from pypy.translator.cli.test.runtest import CliFunctionWrapper
+        filename = self.gen.build_exe()
+        self.c_entryp = CliFunctionWrapper(filename)
+        # restore original os values
+        if hasattr(self, 'old_cli_defs'):
+            unpatch_os(self.old_cli_defs)
+        
+        self.log.info("Compiled %s" % filename)
+        if self.standalone and self.exe_name:
+            self.copy_cli_exe()
+    task_compile_cli = taskdef(task_compile_cli, ['source_cli'],
+                              'Compiling CLI source')
+
+    def task_run_cli(self):
+        pass
+    task_run_cli = taskdef(task_run_cli, ['compile_cli'],
+                              'XXX')
+    
+    def task_source_jvm(self):
+        from pypy.translator.jvm.genjvm import GenJvm
+        from pypy.translator.jvm.node import EntryPoint
+
+        entry_point_graph = self.translator.graphs[0]
+        is_func = not self.standalone
+        entry_point = EntryPoint(entry_point_graph, is_func, is_func)
+        self.gen = GenJvm(udir, self.translator, entry_point)
+        self.jvmsource = self.gen.generate_source()
+        self.log.info("Wrote JVM code")
+    task_source_jvm = taskdef(task_source_jvm, ["?" + OOBACKENDOPT, OOTYPE],
+                             'Generating JVM source')
+
+    def task_compile_jvm(self):
+        from pypy.translator.oosupport.support import unpatch_os
+        from pypy.translator.jvm.test.runtest import JvmGeneratedSourceWrapper
+        self.jvmsource.compile()
+        self.c_entryp = JvmGeneratedSourceWrapper(self.jvmsource)
+        # restore original os values
+        if hasattr(self, 'old_cli_defs'):
+            unpatch_os(self.old_cli_defs)
+        self.log.info("Compiled JVM source")
+        if self.standalone and self.exe_name:
+            self.copy_jvm_jar()
+    task_compile_jvm = taskdef(task_compile_jvm, ['source_jvm'],
+                              'Compiling JVM source')
+
+    def task_run_jvm(self):
+        pass
+    task_run_jvm = taskdef(task_run_jvm, ['compile_jvm'],
+                           'XXX')
+
+    def proceed(self, goals):
+        if not goals:
+            if self.default_goal:
+                goals = [self.default_goal]
+            else:
+                self.log.info("nothing to do")
+                return
+        elif isinstance(goals, str):
+            goals = [goals]
+        goals.extend(self.extra_goals)
+        goals = self.backend_select_goals(goals)
+        return self._execute(goals, task_skip = self._maybe_skip())
+
+    def from_targetspec(targetspec_dic, config=None, args=None,
+                        empty_translator=None,
+                        disable=[],
+                        default_goal=None):
+        if args is None:
+            args = []
+
+        driver = TranslationDriver(config=config, default_goal=default_goal,
+                                   disable=disable)
+        # patch some attributes of the os module to make sure they
+        # have the same value on every platform.
+        backend, ts = driver.get_backend_and_type_system()
+        if backend in ('cli', 'jvm'):
+            from pypy.translator.oosupport.support import patch_os
+            driver.old_cli_defs = patch_os()
+        
+        target = targetspec_dic['target']
+        spec = target(driver, args)
+
+        try:
+            entry_point, inputtypes, policy = spec
+        except ValueError:
+            entry_point, inputtypes = spec
+            policy = None
+
+        driver.setup(entry_point, inputtypes, 
+                     policy=policy, 
+                     extra=targetspec_dic,
+                     empty_translator=empty_translator)
+
+        return driver
+
+    from_targetspec = staticmethod(from_targetspec)
+
+    def prereq_checkpt_rtype(self):
+        assert 'pypy.rpython.rmodel' not in sys.modules, (
+            "cannot fork because the rtyper has already been imported")
+    prereq_checkpt_rtype_lltype = prereq_checkpt_rtype
+    prereq_checkpt_rtype_ootype = prereq_checkpt_rtype    

Added: trunk/scipy/sandbox/mkufunc/mkufunc/interactive.py
===================================================================
--- trunk/scipy/sandbox/mkufunc/mkufunc/interactive.py	2008-06-30 19:19:55 UTC (rev 4506)
+++ trunk/scipy/sandbox/mkufunc/mkufunc/interactive.py	2008-07-01 00:32:12 UTC (rev 4507)
@@ -0,0 +1,115 @@
+import driver
+
+from pypy.translator.translator import TranslationContext
+
+
+DEFAULTS = {
+  'translation.backend': None,
+  'translation.type_system': None,
+  'translation.verbose': False,
+}
+
+class Translation(object):
+
+    def __init__(self, entry_point, argtypes=None, **kwds):
+        self.driver = driver.TranslationDriver(overrides=DEFAULTS)
+        self.config = self.driver.config
+
+        self.entry_point = entry_point
+        self.context = TranslationContext(config=self.config)
+        
+        # hook into driver events
+        driver_own_event = self.driver._event
+        def _event(kind, goal, func):
+            self.driver_event(kind, goal, func)
+            driver_own_event(kind, goal, func)
+        self.driver._event = _event
+        self.driver_setup = False
+        
+        self.update_options(argtypes, kwds)
+        # for t.view() to work just after construction
+        graph = self.context.buildflowgraph(entry_point)
+        self.context._prebuilt_graphs[entry_point] = graph
+
+    def driver_event(self, kind, goal, func):
+        if kind == 'pre':
+             self.ensure_setup()
+            
+    def ensure_setup(self, argtypes=None, policy=None, standalone=False):
+        if not self.driver_setup:
+            if standalone:
+                assert argtypes is None
+            else:
+                if argtypes is None:
+                    argtypes = []
+            self.driver.setup(self.entry_point, argtypes, policy,
+                              empty_translator=self.context)
+            self.ann_argtypes = argtypes
+            self.ann_policy = policy
+            self.driver_setup = True
+        else:
+            # check consistency
+            if standalone:
+                assert argtypes is None
+                assert self.ann_argtypes is None
+            elif argtypes is not None and argtypes != self.ann_argtypes:
+                raise Exception("inconsistent argtype supplied")
+            if policy is not None and policy != self.ann_policy:
+                raise Exception("inconsistent annotation polish supplied")
+
+    def update_options(self, argtypes, kwds):
+        if argtypes or kwds.get('policy') or kwds.get('standalone'):
+            self.ensure_setup(argtypes, kwds.get('policy'),
+                                        kwds.get('standalone'))
+        kwds.pop('policy', None)
+        kwds.pop('standalone', None)
+        self.config.translation.set(**kwds)
+
+    def ensure_opt(self, name, value=None, fallback=None):
+        if value is not None:
+            self.update_options(None, {name: value})
+            return value
+        val = getattr(self.config.translation, name, None)
+        if fallback is not None and val is None:
+            self.update_options(None, {name: fallback})
+            return fallback
+        if val is not None:
+            return val
+        raise Exception(
+              "the %r option should have been specified at this point" %name)
+
+    def ensure_type_system(self, type_system=None):
+        if self.config.translation.backend is not None:
+            return self.ensure_opt('type_system')
+        return self.ensure_opt('type_system', type_system, 'lltype')
+        
+    def ensure_backend(self, backend=None):
+        backend = self.ensure_opt('backend', backend)
+        self.ensure_type_system()
+        return backend
+
+    # backend independent
+
+    def annotate(self, argtypes=None, **kwds):
+        self.update_options(argtypes, kwds)
+        return self.driver.annotate()
+
+    # type system dependent
+
+    def rtype(self, argtypes=None, **kwds):
+        self.update_options(argtypes, kwds)
+        ts = self.ensure_type_system()
+        return getattr(self.driver, 'rtype_'+ts)()        
+
+    # backend depedent
+
+    def source(self, argtypes=None, **kwds):
+        self.update_options(argtypes, kwds)
+        backend = self.ensure_backend()
+        self.driver.source_c()
+       
+    def compile(self, argtypes=None, **kwds):
+        self.update_options(argtypes, kwds)
+        backend = self.ensure_backend()
+        self.driver.compile_c()
+        return self.driver.c_entryp

Added: trunk/scipy/sandbox/mkufunc/mkufunc/pypy.h
===================================================================
--- trunk/scipy/sandbox/mkufunc/mkufunc/pypy.h	2008-06-30 19:19:55 UTC (rev 4506)
+++ trunk/scipy/sandbox/mkufunc/mkufunc/pypy.h	2008-07-01 00:32:12 UTC (rev 4507)
@@ -0,0 +1,381 @@
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+
+/* ================================================== g_prerequisite.h === */
+
+typedef unsigned char bool_t;
+
+/* ================================================== exception.h ======== */
+
+#define RPY_DEBUG_RETURN()        /* nothing */
+
+
+/* ================================================== int.h ============== */
+
+/*** unary operations ***/
+
+#define OP_INT_IS_TRUE(x,r)   OP_INT_NE(x,0,r)
+
+#define OP_INT_INVERT(x,r)    r = ~((x))
+
+#define OP_INT_NEG(x,r)    r = -(x)
+
+#define OP_INT_NEG_OVF(x,r) \
+    if ((x) == LONG_MIN) FAIL_OVF("integer negate"); \
+	OP_INT_NEG(x,r)
+#define OP_LLONG_NEG_OVF(x,r) \
+    if ((x) == LLONG_MIN) FAIL_OVF("integer negate"); \
+	OP_LLONG_NEG(x,r)
+
+#define OP_INT_ABS(x,r)    r = (x) >= 0 ? x : -(x)
+
+#define OP_INT_ABS_OVF(x,r) \
+    if ((x) == LONG_MIN) FAIL_OVF("integer absolute"); \
+	OP_INT_ABS(x,r)
+#define OP_LLONG_ABS_OVF(x,r) \
+    if ((x) == LLONG_MIN) FAIL_OVF("integer absolute"); \
+	OP_LLONG_ABS(x,r)
+
+/***  binary operations ***/
+
+#define OP_INT_EQ(x,y,r)	  r = ((x) == (y))
+#define OP_INT_NE(x,y,r)	  r = ((x) != (y))
+#define OP_INT_LE(x,y,r)	  r = ((x) <= (y))
+#define OP_INT_GT(x,y,r)	  r = ((x) >  (y))
+#define OP_INT_LT(x,y,r)	  r = ((x) <  (y))
+#define OP_INT_GE(x,y,r)	  r = ((x) >= (y))
+
+/* addition, subtraction */
+
+#define OP_INT_ADD(x,y,r)     r = (x) + (y)
+
+#define OP_INT_ADD_OVF(x,y,r) \
+	OP_INT_ADD(x,y,r); \
+	if ((r^(x)) >= 0 || (r^(y)) >= 0); \
+	else FAIL_OVF("integer addition")
+
+#define OP_INT_ADD_NONNEG_OVF(x,y,r)  /* y can be assumed >= 0 */ \
+    OP_INT_ADD(x,y,r); \
+    if (r >= (x)); \
+    else FAIL_OVF("integer addition")
+/* XXX can a C compiler be too clever and think it can "prove" that
+ * r >= x always hold above? */
+
+#define OP_INT_SUB(x,y,r)     r = (x) - (y)
+
+#define OP_INT_SUB_OVF(x,y,r) \
+	OP_INT_SUB(x,y,r); \
+	if ((r^(x)) >= 0 || (r^~(y)) >= 0); \
+	else FAIL_OVF("integer subtraction")
+
+#define OP_INT_MUL(x,y,r)     r = (x) * (y)
+
+#if defined(HAVE_LONG_LONG) && SIZE_OF_LONG_LONG < SIZE_OF_LONG
+#  define OP_INT_MUL_OVF_LL      1
+#lse
+#  define OP_INT_MUL_OVF_LL      0
+#endif
+
+#if !OP_INT_MUL_OVF_LL
+
+#define OP_INT_MUL_OVF(x,y,r) \
+	if (op_int_mul_ovf(x,y,&r)); \
+	else FAIL_OVF("integer multiplication")
+
+#else
+
+#define OP_INT_MUL_OVF(x,y,r) \
+	{ \
+		PY_LONG_LONG lr = (PY_LONG_LONG)(x) * (PY_LONG_LONG)(y); \
+		r = (long)lr; \
+		if ((PY_LONG_LONG)r == lr); \
+		else FAIL_OVF("integer multiplication"); \
+	}
+#endif
+
+/* shifting */
+
+/* NB. shifting has same limitations as C: the shift count must be
+       >= 0 and < LONG_BITS. */
+#define OP_INT_RSHIFT(x,y,r)    r = Py_ARITHMETIC_RIGHT_SHIFT(long, x, y)
+#define OP_UINT_RSHIFT(x,y,r)   r = (x) >> (y)
+#define OP_LLONG_RSHIFT(x,y,r)  r = Py_ARITHMETIC_RIGHT_SHIFT(PY_LONG_LONG,x,y)
+#define OP_ULLONG_RSHIFT(x,y,r) r = (x) >> (y)
+
+#define OP_INT_LSHIFT(x,y,r)    r = (x) << (y)
+#define OP_UINT_LSHIFT(x,y,r)   r = (x) << (y)
+#define OP_LLONG_LSHIFT(x,y,r)  r = (x) << (y)
+#define OP_ULLONG_LSHIFT(x,y,r) r = (x) << (y)
+
+#define OP_INT_LSHIFT_OVF(x,y,r) \
+	OP_INT_LSHIFT(x,y,r); \
+	if ((x) != Py_ARITHMETIC_RIGHT_SHIFT(long, r, (y))) \
+		FAIL_OVF("x<<y losing bits or changing sign")
+
+/* the safe value-checking version of the above macros */
+
+#define OP_INT_RSHIFT_VAL(x,y,r) \
+	if ((y) >= 0) { OP_INT_RSHIFT(x,y,r); } \
+	else FAIL_VAL("negative shift count")
+#define OP_LLONG_RSHIFT_VAL(x,y,r) \
+	if ((y) >= 0) { OP_LLONG_RSHIFT(x,y,r); } \
+	else FAIL_VAL("negative shift count")
+
+#define OP_INT_LSHIFT_VAL(x,y,r) \
+	if ((y) >= 0) { OP_INT_LSHIFT(x,y,r); } \
+	else FAIL_VAL("negative shift count")
+#define OP_LLONG_LSHIFT_VAL(x,y,r) \
+	if ((y) >= 0) { OP_LLONG_LSHIFT(x,y,r); } \
+	else FAIL_VAL("negative shift count")
+
+#define OP_INT_LSHIFT_OVF_VAL(x,y,r) \
+	if ((y) >= 0) { OP_INT_LSHIFT_OVF(x,y,r); } \
+	else FAIL_VAL("negative shift count")
+
+/* pff */
+#define OP_UINT_LSHIFT_VAL(x,y,r) \
+	if ((y) >= 0) { OP_UINT_LSHIFT(x,y,r); } \
+	else FAIL_VAL("negative shift count")
+#define OP_ULLONG_LSHIFT_VAL(x,y,r) \
+	if ((y) >= 0) { OP_ULLONG_LSHIFT(x,y,r); } \
+	else FAIL_VAL("negative shift count")
+
+#define OP_UINT_RSHIFT_VAL(x,y,r) \
+	if ((y) >= 0) { OP_UINT_RSHIFT(x,y,r); } \
+	else FAIL_VAL("negative shift count")
+#define OP_ULLONG_RSHIFT_VAL(x,y,r) \
+	if ((y) >= 0) { OP_ULLONG_RSHIFT(x,y,r); } \
+	else FAIL_VAL("negative shift count")
+
+
+/* floor division */
+
+#define OP_INT_FLOORDIV(x,y,r)    r = (x) / (y)
+#define OP_UINT_FLOORDIV(x,y,r)   r = (x) / (y)
+#define OP_LLONG_FLOORDIV(x,y,r)  r = (x) / (y)
+#define OP_ULLONG_FLOORDIV(x,y,r) r = (x) / (y)
+
+#define OP_INT_FLOORDIV_OVF(x,y,r) \
+	if ((y) == -1 && (x) == LONG_MIN) \
+            { FAIL_OVF("integer division"); } \
+        else OP_INT_FLOORDIV(x,y,r)
+
+#define OP_INT_FLOORDIV_ZER(x,y,r) \
+	if ((y)) { OP_INT_FLOORDIV(x,y,r); } \
+	else FAIL_ZER("integer division")
+#define OP_UINT_FLOORDIV_ZER(x,y,r) \
+	if ((y)) { OP_UINT_FLOORDIV(x,y,r); } \
+	else FAIL_ZER("unsigned integer division")
+#define OP_LLONG_FLOORDIV_ZER(x,y,r) \
+	if ((y)) { OP_LLONG_FLOORDIV(x,y,r); } \
+	else FAIL_ZER("integer division")
+#define OP_ULLONG_FLOORDIV_ZER(x,y,r) \
+	if ((y)) { OP_ULLONG_FLOORDIV(x,y,r); } \
+	else FAIL_ZER("unsigned integer division")
+
+#define OP_INT_FLOORDIV_OVF_ZER(x,y,r) \
+	if ((y)) { OP_INT_FLOORDIV_OVF(x,y,r); } \
+	else FAIL_ZER("integer division")
+
+/* modulus */
+
+#define OP_INT_MOD(x,y,r)     r = (x) % (y)
+#define OP_UINT_MOD(x,y,r)    r = (x) % (y)
+#define OP_LLONG_MOD(x,y,r)   r = (x) % (y)
+#define OP_ULLONG_MOD(x,y,r)  r = (x) % (y)
+
+#define OP_INT_MOD_OVF(x,y,r) \
+	if ((y) == -1 && (x) == LONG_MIN) \
+            { FAIL_OVF("integer modulo"); }\
+        else OP_INT_MOD(x,y,r)
+
+#define OP_INT_MOD_ZER(x,y,r) \
+	if ((y)) { OP_INT_MOD(x,y,r); } \
+	else FAIL_ZER("integer modulo")
+#define OP_UINT_MOD_ZER(x,y,r) \
+	if ((y)) { OP_UINT_MOD(x,y,r); } \
+	else FAIL_ZER("unsigned integer modulo")
+#define OP_LLONG_MOD_ZER(x,y,r) \
+	if ((y)) { OP_LLONG_MOD(x,y,r); } \
+	else FAIL_ZER("integer modulo")
+#define OP_ULLONG_MOD_ZER(x,y,r) \
+	if ((y)) { OP_ULLONG_MOD(x,y,r); } \
+	else FAIL_ZER("integer modulo")
+
+#define OP_INT_MOD_OVF_ZER(x,y,r) \
+	if ((y)) { OP_INT_MOD_OVF(x,y,r); } \
+	else FAIL_ZER("integer modulo")
+
+/* bit operations */
+
+#define OP_INT_AND(x,y,r)     r = (x) & (y)
+#define OP_INT_OR( x,y,r)     r = (x) | (y)
+#define OP_INT_XOR(x,y,r)     r = (x) ^ (y)
+
+/*** conversions ***/
+
+#define OP_CAST_BOOL_TO_INT(x,r)    r = (long)(x)
+#define OP_CAST_BOOL_TO_UINT(x,r)   r = (unsigned long)(x)
+#define OP_CAST_UINT_TO_INT(x,r)    r = (long)(x)
+#define OP_CAST_INT_TO_UINT(x,r)    r = (unsigned long)(x)
+#define OP_CAST_INT_TO_LONGLONG(x,r) r = (long long)(x)
+#define OP_CAST_CHAR_TO_INT(x,r)    r = (long)((unsigned char)(x))
+#define OP_CAST_INT_TO_CHAR(x,r)    r = (char)(x)
+#define OP_CAST_PTR_TO_INT(x,r)     r = (long)(x)    /* XXX */
+
+#define OP_TRUNCATE_LONGLONG_TO_INT(x,r) r = (long)(x)
+
+#define OP_CAST_UNICHAR_TO_INT(x,r)    r = (long)((unsigned long)(x)) /*?*/
+#define OP_CAST_INT_TO_UNICHAR(x,r)    r = (unsigned int)(x)
+
+/* bool operations */
+
+#define OP_BOOL_NOT(x, r) r = !(x)
+
+/* _________________ certain implementations __________________ */
+
+#if !OP_INT_MUL_OVF_LL
+/* adjusted from intobject.c, Python 2.3.3 */
+
+/* prototypes */
+
+int op_int_mul_ovf(long a, long b, long *longprod);
+
+/* implementations */
+
+#ifndef PYPY_NOT_MAIN_FILE
+
+int
+op_int_mul_ovf(long a, long b, long *longprod)
+{
+	double doubled_longprod;	/* (double)longprod */
+	double doubleprod;		/* (double)a * (double)b */
+
+	*longprod = a * b;
+	doubleprod = (double)a * (double)b;
+	doubled_longprod = (double)*longprod;
+
+	/* Fast path for normal case:  small multiplicands, and no info
+	   is lost in either method. */
+	if (doubled_longprod == doubleprod)
+		return 1;
+
+	/* Somebody somewhere lost info.  Close enough, or way off?  Note
+	   that a != 0 and b != 0 (else doubled_longprod == doubleprod == 0).
+	   The difference either is or isn't significant compared to the
+	   true value (of which doubleprod is a good approximation).
+	*/
+	{
+		const double diff = doubled_longprod - doubleprod;
+		const double absdiff = diff >= 0.0 ? diff : -diff;
+		const double absprod = doubleprod >= 0.0 ? doubleprod :
+							  -doubleprod;
+		/* absdiff/absprod <= 1/32 iff
+		   32 * absdiff <= absprod -- 5 good bits is "close enough" */
+		if (32.0 * absdiff <= absprod)
+			return 1;
+		return 0;
+	}
+}
+
+#endif /* PYPY_NOT_MAIN_FILE */
+
+#endif /* !OP_INT_MUL_OVF_LL */
+
+/* implementations */
+
+#define OP_UINT_IS_TRUE OP_INT_IS_TRUE
+#define OP_UINT_INVERT OP_INT_INVERT
+#define OP_UINT_ADD OP_INT_ADD
+#define OP_UINT_SUB OP_INT_SUB
+#define OP_UINT_MUL OP_INT_MUL
+#define OP_UINT_LT OP_INT_LT
+#define OP_UINT_LE OP_INT_LE
+#define OP_UINT_EQ OP_INT_EQ
+#define OP_UINT_NE OP_INT_NE
+#define OP_UINT_GT OP_INT_GT
+#define OP_UINT_GE OP_INT_GE
+#define OP_UINT_AND OP_INT_AND
+#define OP_UINT_OR OP_INT_OR
+#define OP_UINT_XOR OP_INT_XOR
+
+#define OP_LLONG_IS_TRUE OP_INT_IS_TRUE
+#define OP_LLONG_NEG     OP_INT_NEG
+#define OP_LLONG_ABS     OP_INT_ABS
+#define OP_LLONG_INVERT  OP_INT_INVERT
+
+#define OP_LLONG_ADD OP_INT_ADD
+#define OP_LLONG_SUB OP_INT_SUB
+#define OP_LLONG_MUL OP_INT_MUL
+#define OP_LLONG_LT  OP_INT_LT
+#define OP_LLONG_LE  OP_INT_LE
+#define OP_LLONG_EQ  OP_INT_EQ
+#define OP_LLONG_NE  OP_INT_NE
+#define OP_LLONG_GT  OP_INT_GT
+#define OP_LLONG_GE  OP_INT_GE
+#define OP_LLONG_AND    OP_INT_AND
+#define OP_LLONG_OR     OP_INT_OR
+#define OP_LLONG_XOR    OP_INT_XOR
+
+#define OP_ULLONG_IS_TRUE OP_LLONG_IS_TRUE
+#define OP_ULLONG_INVERT  OP_LLONG_INVERT
+#define OP_ULLONG_ADD OP_LLONG_ADD
+#define OP_ULLONG_SUB OP_LLONG_SUB
+#define OP_ULLONG_MUL OP_LLONG_MUL
+#define OP_ULLONG_LT OP_LLONG_LT
+#define OP_ULLONG_LE OP_LLONG_LE
+#define OP_ULLONG_EQ OP_LLONG_EQ
+#define OP_ULLONG_NE OP_LLONG_NE
+#define OP_ULLONG_GT OP_LLONG_GT
+#define OP_ULLONG_GE OP_LLONG_GE
+#define OP_ULLONG_AND OP_LLONG_AND
+#define OP_ULLONG_OR OP_LLONG_OR
+#define OP_ULLONG_XOR OP_LLONG_XOR
+
+/* ================================================== float.h ============ */
+
+/*** unary operations ***/
+
+#define OP_FLOAT_IS_TRUE(x,r)   OP_FLOAT_NE(x,0.0,r)
+#define OP_FLOAT_NEG(x,r)       r = -x
+#define OP_FLOAT_ABS(x,r)       r = fabs(x)
+
+/***  binary operations ***/
+
+#define OP_FLOAT_EQ(x,y,r)	  r = (x == y)
+#define OP_FLOAT_NE(x,y,r)	  r = (x != y)
+#define OP_FLOAT_LE(x,y,r)	  r = (x <= y)
+#define OP_FLOAT_GT(x,y,r)	  r = (x >  y)
+#define OP_FLOAT_LT(x,y,r)	  r = (x <  y)
+#define OP_FLOAT_GE(x,y,r)	  r = (x >= y)
+
+#define OP_FLOAT_CMP(x,y,r) \
+	r = ((x > y) - (x < y))
+
+/* addition, subtraction */
+
+#define OP_FLOAT_ADD(x,y,r)     r = x + y
+#define OP_FLOAT_SUB(x,y,r)     r = x - y
+#define OP_FLOAT_MUL(x,y,r)     r = x * y
+#define OP_FLOAT_TRUEDIV(x,y,r) r = x / y
+#define OP_FLOAT_POW(x,y,r)     r = pow(x, y) 
+
+/*** conversions ***/
+
+#define OP_CAST_FLOAT_TO_INT(x,r)       r = (long)(x)
+#define OP_CAST_FLOAT_TO_UINT(x,r)      r = (unsigned long)(x)
+#define OP_CAST_INT_TO_FLOAT(x,r)       r = (double)(x)
+#define OP_CAST_UINT_TO_FLOAT(x,r)      r = (double)(x)
+#define OP_CAST_LONGLONG_TO_FLOAT(x,r)  r = (double)(x)
+#define OP_CAST_BOOL_TO_FLOAT(x,r)      r = (double)(x)
+
+#ifdef HAVE_LONG_LONG
+#define OP_CAST_FLOAT_TO_LONGLONG(x,r)  r = (long long)(x)
+#endif
+
+/* ================================================== support.h ========== */
+
+#define RPyField(ptr, name)             NULL
+

Added: trunk/scipy/sandbox/mkufunc/mkufunc/test_func_hash.py
===================================================================
--- trunk/scipy/sandbox/mkufunc/mkufunc/test_func_hash.py	2008-06-30 19:19:55 UTC (rev 4506)
+++ trunk/scipy/sandbox/mkufunc/mkufunc/test_func_hash.py	2008-07-01 00:32:12 UTC (rev 4507)
@@ -0,0 +1,48 @@
+import unittest
+
+from api import func_hash
+
+
+class Tests(unittest.TestCase):
+    
+    # These tests are very (Python) version specific.
+    
+    def test_simple(self):
+        
+        def f(x):
+            return 2.5 * x * x + 4.7 * x
+        
+        self.assertEqual(func_hash(f),
+                         '5f12e97debf1d2cb9e0a2f92e045b1fb')
+        
+        
+    def test_extra(self):
+        
+        def f(x):
+            return 2.5 * x * x + 4.7 * x
+        
+        self.assertEqual(func_hash(f, salt=[(int, int), (float, float)]),
+                         'e637d9825ef20cb56d364041118ca72e')
+        
+    def test_const(self):
+        
+        def add_a(b):
+            return a + b   # a in globals
+        
+        self.assertEqual(func_hash(add_a),
+                         '9ff237f372bf233470ce940edd58f60d')
+        
+    def test_inner(self):
+        
+        def foo(x):
+            inner1 = lambda t: t/3.0
+            def inner2(n):
+                return n + 3
+            return inner1(x) + inner2(int(x))
+        
+        self.assertEqual(func_hash(foo),
+                         '814c113dfc77e7ebb52915dd3ce9c37a')
+
+
+if __name__ == '__main__':
+    unittest.main()

Added: trunk/scipy/sandbox/mkufunc/mkufunc/test_mkufunc.py
===================================================================
--- trunk/scipy/sandbox/mkufunc/mkufunc/test_mkufunc.py	2008-06-30 19:19:55 UTC (rev 4506)
+++ trunk/scipy/sandbox/mkufunc/mkufunc/test_mkufunc.py	2008-07-01 00:32:12 UTC (rev 4507)
@@ -0,0 +1,270 @@
+import math
+import unittest
+
+from numpy import array, arange, allclose
+
+from api import Cfunc, genufunc, mkufunc
+
+
+class Util:
+
+    def assertClose(self, x, y):
+        self.assert_(allclose(x, y), '%s != %s' % (x, y))
+            
+
+class Internal_Tests(unittest.TestCase, Util):
+    
+    def test_Cfunc(self):
+        def sqr(x):
+            return x * x
+        cf = Cfunc(sqr, [int, int], 42)
+        self.assertEqual(cf.nin, 1)
+        self.assertEqual(cf.nout, 1)
+        self.assertEqual(cf.cname, 'f42_pypy_g_sqr')
+
+    def test_genufunc(self):
+        def foo(x):
+            return x + 17
+        uf = genufunc(foo, [
+                (float, float),
+                (int, int),
+                ])
+        self.assertEqual(uf(4), 21)
+        x = array([1.1, 2.3])
+        y = uf(x)
+        self.assertClose(y, [18.1, 19.3])
+        self.assert_(str(y.dtype).startswith('float'))
+        
+        x = array([1, 4])
+        y = uf(x)
+        self.assertEqual(list(y), [18, 21])
+        self.assert_(str(y.dtype).startswith('int'))
+
+
+class Arg_Tests(unittest.TestCase, Util):
+    
+    def check_ufunc(self, f):
+        for arg in (array([0.0, 1.0, 2.5]),
+                    [0.0, 1.0, 2.5],
+                    (0.0, 1.0, 2.5)):
+            self.assertClose(f(arg), [0.0, 1.0, 6.25])
+            
+        self.assertEqual(f(3), 9)
+        self.assert_(f(-2.5) - 6.25 < 1E-10)
+
+    def test_direct(self):
+        @mkufunc
+        def f(x):
+            return x * x
+        self.check_ufunc(f)
+        
+    def test_noargs(self):
+        @mkufunc()
+        def f(x):
+            return x * x
+        self.check_ufunc(f)
+        
+    def test_varargs(self):
+        for arg in (float,
+                    [float],
+                    [(float, float)]):
+            @mkufunc(arg)
+            def f(x):
+                return x * x
+            self.check_ufunc(f)
+
+    def test_int(self):
+        @mkufunc(int)
+        def f(x):
+            return x * x
+        self.assertEqual(f(3), 9)
+        self.assert_(isinstance(f(42), int))
+        
+    def test_mixed(self):
+        @mkufunc([(int, float, int), float])
+        def f(n, x):
+            return n + x * x
+        
+        y = f(2, 3.9)            # Note that int(2 + 3.9 * 3.9) = 17
+        self.assertEqual(y, 17)
+        self.assert_(isinstance(y, int))
+        
+        y = f(2.0, 3.9)
+        self.assertClose(y, 17.21)
+        self.assert_(isinstance(y, float))
+        
+    def test_exceptions(self):
+        def f(x):
+            return x
+
+        self.assertRaises(TypeError, mkufunc, {})
+        self.assertRaises(TypeError, mkufunc([(float,)]), f)
+        self.assertRaises(TypeError, mkufunc([3*(float,)]), f)
+        self.assertRaises(TypeError, mkufunc([{}]), f)
+        self.assertRaises(TypeError, mkufunc([(int, {})]), f)
+        self.assertRaises(ValueError, mkufunc([]), f)
+        
+
+class Math_Tests(unittest.TestCase, Util):
+    
+    def assertFuncsEqual(self, uf, f):
+        x = 0.4376
+        a = uf(x)
+        b = f(x)
+        self.assertClose(a, b)
+        xx = arange(0.1, 0.9, 0.01)
+        a = uf(xx)
+        b = [f(x) for x in xx]
+        self.assertClose(a, b)
+        
+    def test_exp(self):
+        @mkufunc
+        def f(x): return math.exp(x)
+        self.assertFuncsEqual(f, math.exp)
+
+    def test_log(self):
+        @mkufunc
+        def f(x): return math.log(x)
+        self.assertFuncsEqual(f, math.log)
+
+    def test_sqrt(self):
+        @mkufunc
+        def f(x): return math.sqrt(x)
+        self.assertFuncsEqual(f, math.sqrt)
+        
+    def test_cos(self):
+        @mkufunc
+        def f(x): return math.cos(x)
+        self.assertFuncsEqual(f, math.cos)
+        
+    def test_sin(self):
+        @mkufunc
+        def f(x): return math.sin(x)
+        self.assertFuncsEqual(f, math.sin)
+        
+    def test_tan(self):
+        @mkufunc
+        def f(x): return math.tan(x)
+        self.assertFuncsEqual(f, math.tan)
+        
+    def test_acos(self):
+        @mkufunc
+        def f(x): return math.acos(x)
+        self.assertFuncsEqual(f, math.acos)
+
+    def test_asin(self):
+        @mkufunc
+        def f(x): return math.asin(x)
+        self.assertFuncsEqual(f, math.asin)
+        
+    def test_atan(self):
+        @mkufunc
+        def f(x): return math.atan(x)
+        self.assertFuncsEqual(f, math.atan)
+
+    def test_atan2(self):
+        @mkufunc
+        def f(x, y):
+            return math.atan2(x, y)
+
+        self.assertClose(f(4, 5), math.atan2(4, 5))
+        
+        xx = array([1.0, 3.0, -2.4,  3.1, -2.3])
+        yy = array([1.0, 2.0,  7.5, -8.7,  0.0])
+        a = f(xx, yy)
+        b = [math.atan2(x, y) for x, y in zip(xx, yy)]
+        self.assertClose(a, b)
+        
+    def test_arithmetic(self):
+        def f(x):
+            return (4 * x + 2) / (x * x - 7 * x + 1)
+        uf = mkufunc(f)
+        x = arange(0, 2, 0.1)
+        self.assertClose(uf(x), f(x))
+
+
+class FuncArg_Tests(unittest.TestCase, Util):
+    
+    def test_fargs0(self):
+        def f():
+            return 42
+        
+        uf = mkufunc(f)
+        self.assertEqual(uf(), 42)
+        self.assert_(type(uf()).__name__.startswith('float'))
+
+        uf = mkufunc(int)(f)
+        self.assertEqual(uf(), 42)
+        self.assert_(type(uf()).__name__.startswith('int'))
+
+
+class Control_Flow_Tests(unittest.TestCase):
+
+    def test_if(self):
+        @mkufunc(int)
+        def f(n):
+            if n < 4:
+                return n
+            else:
+                return n * n
+
+        self.assertEqual(f(3), 3)
+        self.assertEqual(f(4), 16)
+
+    def test_switch(self):
+        @mkufunc(int)
+        def f(n):
+            if n < 4:
+                return n
+            elif n == 4:
+                return 42
+            elif n == 5:
+                return 73
+            else:
+                return n * n
+
+        self.assertEqual(f(3), 3)
+        self.assertEqual(f(4), 42)
+        self.assertEqual(f(5), 73)
+        self.assertEqual(f(6), 36)
+
+    def test_loop(self):
+        @mkufunc(int)
+        def f(n):
+            res = 0
+            for i in xrange(n):
+                res += i*i
+            return res
+
+        self.assertEqual(f(3), 5)
+        self.assertEqual(f(95), 281295)
+
+
+class FreeVariable_Tests(unittest.TestCase, Util):
+
+    def test_const(self):
+        a = 13.6
+        @mkufunc
+        def f(x):
+            return a * x
+        
+        x = arange(0, 1, 0.1)
+        self.assertClose(f(x), a * x)
+
+    def test_const2(self):
+        from math import sin, pi, sqrt
+        @mkufunc
+        def sin_deg(angle):
+            return sin(angle / 180.0 * pi)
+        
+        self.assertClose(sin_deg([0, 30, 45, 60, 90, 180, 270, 360]),
+                         [0, 0.5, 1/sqrt(2), sqrt(3)/2, 1, 0, -1, 0])
+        
+
+class Misc_Tests(unittest.TestCase, Util):
+
+    pass
+
+
+if __name__ == '__main__':
+    unittest.main()

Added: trunk/scipy/sandbox/mkufunc/setup.py
===================================================================
--- trunk/scipy/sandbox/mkufunc/setup.py	2008-06-30 19:19:55 UTC (rev 4506)
+++ trunk/scipy/sandbox/mkufunc/setup.py	2008-07-01 00:32:12 UTC (rev 4507)
@@ -0,0 +1,15 @@
+from setuptools import setup, find_packages
+
+setup(
+    author       = 'Ilan Schnell',
+    author_email = 'ischnell at enthought.com',
+    description  = 'C compiled UFuncs from python source',
+
+    name         = "mkufunc",
+    version      = "0.1",
+    
+    zip_safe = False,
+    package_data = {'': ['*.h']},
+    packages = find_packages(),
+    install_requires = ['scipy >= 0.6.0']
+    )




More information about the Scipy-svn mailing list