[Scipy-svn] r4650 - in branches/sandbox/scipy/sandbox/mkufunc: . examples mkufunc

scipy-svn@scip... scipy-svn@scip...
Mon Aug 18 15:40:55 CDT 2008


Author: ilan
Date: 2008-08-18 15:40:53 -0500 (Mon, 18 Aug 2008)
New Revision: 4650

Added:
   branches/sandbox/scipy/sandbox/mkufunc/mkufunc/fast_vectorize.py
   branches/sandbox/scipy/sandbox/mkufunc/mkufunc/func_hash.py
   branches/sandbox/scipy/sandbox/mkufunc/mkufunc/test_fast_vectorize.py
Removed:
   branches/sandbox/scipy/sandbox/mkufunc/mkufunc/api.py
   branches/sandbox/scipy/sandbox/mkufunc/mkufunc/test_func_hash.py
   branches/sandbox/scipy/sandbox/mkufunc/mkufunc/test_mkufunc.py
Modified:
   branches/sandbox/scipy/sandbox/mkufunc/TODO.txt
   branches/sandbox/scipy/sandbox/mkufunc/examples/benchmark.py
   branches/sandbox/scipy/sandbox/mkufunc/examples/mandel_py.py
   branches/sandbox/scipy/sandbox/mkufunc/examples/primes.py
   branches/sandbox/scipy/sandbox/mkufunc/mkufunc/__init__.py
   branches/sandbox/scipy/sandbox/mkufunc/mkufunc/driver.py
   branches/sandbox/scipy/sandbox/mkufunc/mkufunc/interactive.py
   branches/sandbox/scipy/sandbox/mkufunc/setup.py
Log:
Numerous changes: renaming, improved hash functions, cleanup.


Modified: branches/sandbox/scipy/sandbox/mkufunc/TODO.txt
===================================================================
--- branches/sandbox/scipy/sandbox/mkufunc/TODO.txt	2008-08-18 05:37:28 UTC (rev 4649)
+++ branches/sandbox/scipy/sandbox/mkufunc/TODO.txt	2008-08-18 20:40:53 UTC (rev 4650)
@@ -1,15 +1,9 @@
 
 - Documentation
 
-- improve caching of pypy compiler output
-
 - think about shipping issues (using weave ext_tools)
 
 - add Csrc attribute to ufunc object
 
+- see if monkeypatch of pypy modules is feasible/desired
 
-- improved function hash
-
-- rename to fast_vectorize
-
-- which python version should this work with?

Modified: branches/sandbox/scipy/sandbox/mkufunc/examples/benchmark.py
===================================================================
--- branches/sandbox/scipy/sandbox/mkufunc/examples/benchmark.py	2008-08-18 05:37:28 UTC (rev 4649)
+++ branches/sandbox/scipy/sandbox/mkufunc/examples/benchmark.py	2008-08-18 20:40:53 UTC (rev 4650)
@@ -6,7 +6,9 @@
 from numpy import linspace, vectorize, allclose, empty_like
 from scipy import weave
 
-from mkufunc.api import mkufunc
+import sys
+sys.path.append('../mkufunc')
+from fast_vectorize import fast_vectorize
 
 
 def f(x):
@@ -15,7 +17,7 @@
 
 vfunc = vectorize(f)
 
-mfunc = mkufunc([(float, float)])(f)
+mfunc = fast_vectorize([(float, float)])(f)
 
 #####################################################################
 support_code = '''
@@ -94,7 +96,7 @@
 start_time = time.time()
 m_y = mfunc(x)
 m_time = time.time() - start_time
-print 'mkufunc: %.6f sec' % m_time
+print 'fast_vectorize: %.6f sec' % m_time
 
 start_time = time.time()
 u_y = ufunc(x)

Modified: branches/sandbox/scipy/sandbox/mkufunc/examples/mandel_py.py
===================================================================
--- branches/sandbox/scipy/sandbox/mkufunc/examples/mandel_py.py	2008-08-18 05:37:28 UTC (rev 4649)
+++ branches/sandbox/scipy/sandbox/mkufunc/examples/mandel_py.py	2008-08-18 20:40:53 UTC (rev 4650)
@@ -1,11 +1,15 @@
 #!/usr/bin/env python
 from numpy import array
-from mkufunc.api import mkufunc
 
+import sys
+sys.path.append('../mkufunc')
+from fast_vectorize import fast_vectorize
+
+
 D = 1000
 
 
-@mkufunc([(float, float, int)])
+@fast_vectorize([(float, float, int)])
 def mandel(cr, ci):
     d = 1
     zr = cr

Modified: branches/sandbox/scipy/sandbox/mkufunc/examples/primes.py
===================================================================
--- branches/sandbox/scipy/sandbox/mkufunc/examples/primes.py	2008-08-18 05:37:28 UTC (rev 4649)
+++ branches/sandbox/scipy/sandbox/mkufunc/examples/primes.py	2008-08-18 20:40:53 UTC (rev 4650)
@@ -7,8 +7,10 @@
     src = 1
 
 
+import sys
+sys.path.append('../mkufunc')
+from fast_vectorize import fast_vectorize
 
-from mkufunc.api import mkufunc
 
 
 def count_primes(N):
@@ -27,7 +29,7 @@
 print 'Python: %.6f sec' % (time.time() - start_time)
 
 
-count_primes = mkufunc(int, src=src)(count_primes)
+count_primes = fast_vectorize(int, src=src)(count_primes)
 
 
 start_time = time.time()

Modified: branches/sandbox/scipy/sandbox/mkufunc/mkufunc/__init__.py
===================================================================
--- branches/sandbox/scipy/sandbox/mkufunc/mkufunc/__init__.py	2008-08-18 05:37:28 UTC (rev 4649)
+++ branches/sandbox/scipy/sandbox/mkufunc/mkufunc/__init__.py	2008-08-18 20:40:53 UTC (rev 4650)
@@ -0,0 +1 @@
+from fast_vectorize import *

Deleted: branches/sandbox/scipy/sandbox/mkufunc/mkufunc/api.py
===================================================================
--- branches/sandbox/scipy/sandbox/mkufunc/mkufunc/api.py	2008-08-18 05:37:28 UTC (rev 4649)
+++ branches/sandbox/scipy/sandbox/mkufunc/mkufunc/api.py	2008-08-18 20:40:53 UTC (rev 4650)
@@ -1,362 +0,0 @@
-""" 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 md5
-from types import FunctionType
-
-import numpy
-from scipy import weave
-
-
-verbose = 0
-showC = 0
-
-def func_hash(f, salt=None):
-    """ Return a MD5 hash for a function object as string.
-    """
-    co = f.func_code
-    return md5.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+                 # return type of function
-            [\s]+                # whitespace
-            %s                   # function name
-            \s*                  # possibly whitespace
-            \([^)]*\)            # argument types
-            \s*                  # possibly whitespace
-            \{.*?\n\}\n          # function body ending with } in single line
-            ''' % self.cname,
-            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_', '')
-        if showC:
-            print '------------------'
-            print res
-            print '------------------'
-
-        return 'inline %s\n' % res
-
-    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], src=0):
-    """ 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)
-
-    global showC
-    showC = src
-
-    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()

Modified: branches/sandbox/scipy/sandbox/mkufunc/mkufunc/driver.py
===================================================================
--- branches/sandbox/scipy/sandbox/mkufunc/mkufunc/driver.py	2008-08-18 05:37:28 UTC (rev 4649)
+++ branches/sandbox/scipy/sandbox/mkufunc/mkufunc/driver.py	2008-08-18 20:40:53 UTC (rev 4650)
@@ -1,3 +1,7 @@
+"""
+This file is essentially the file pypy-dist/pypy/translator/driver.py
+with some modifications to get the c_source_filename.
+"""
 import sys, os
 
 from pypy.translator.translator import TranslationContext, graphof
@@ -131,7 +135,7 @@
             explicit_task = task
             parts = task.split('_')
             if len(parts) == 1:
-                if task in ('annotate'):
+                if task in ('annotate',):
                     expose_task(task)
             else:
                 task, postfix = parts
@@ -186,7 +190,7 @@
     def _maybe_skip(self):
         maybe_skip = []
         if self._disabled:
-            for goal in  self.backend_select_goals(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()
 

Copied: branches/sandbox/scipy/sandbox/mkufunc/mkufunc/fast_vectorize.py (from rev 4649, branches/sandbox/scipy/sandbox/mkufunc/mkufunc/api.py)
===================================================================
--- branches/sandbox/scipy/sandbox/mkufunc/mkufunc/api.py	2008-08-18 05:37:28 UTC (rev 4649)
+++ branches/sandbox/scipy/sandbox/mkufunc/mkufunc/fast_vectorize.py	2008-08-18 20:40:53 UTC (rev 4650)
@@ -0,0 +1,380 @@
+"""fast_vectorize: creates a U function from python source code
+
+Author: Ilan Schnell
+Thanks: Travis Oliphant and Eric Jones
+"""
+import sys
+import re
+import os
+import cStringIO
+import md5
+from types import FunctionType
+
+import numpy
+from scipy import weave
+
+# Local imports
+from func_hash import func_hash
+
+
+_verbose = 0
+_showc = 0
+_force = 0
+
+def c_source_filename(f, argtypes):
+    try:
+        import pypy
+    except ImportError:
+        raise ImportError("""
+################################################################
+weave.fast_vectorize requires pypy to be installed.
+
+You can download...
+################################################################
+""")
+    
+    from interactive import Translation
+
+    t = Translation(f, backend='c')
+    t.annotate(argtypes)
+    t.source()
+    return t.driver.c_source_filename
+
+
+def translate(f, argtypes):
+    """ Return pypy's C output for a given function and argument types.
+        The cache files are in weave's directory.
+    """
+    if _force:
+        filename = c_source_filename(f, argtypes)
+        return open(filename).read()
+    
+    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:
+        os.rename(c_source_filename(f, argtypes), 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+                 # return type of function
+            [\s]+                # whitespace
+            %s                   # function name
+            \s*                  # possibly whitespace
+            \([^)]*\)            # argument types
+            \s*                  # possibly whitespace
+            \{.*?\n\}\n          # function body ending with } in single line
+            ''' % self.cname,
+            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_', '')
+        if _showc:
+            print '------------------'
+            print res
+            print '------------------'
+
+        return 'inline %s\n' % res
+
+    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 fast_vectorize", /* 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,
+                        force = _force,
+                        support_code = support_code(cfuncs),
+                        customize = ufunc_info)
+
+
+
+def fast_vectorize(arg0=[float], showc=0, force=0, verbose=0):
+    """ Python decorator which returns compiled UFunc of the function given.
+
+    >>> from numpy import arange
+    >>> @fast_vectorize
+    ... 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)
+
+    global _showc, _force, _verbose
+    _showc = showc
+    _force = force
+    _verbose = verbose
+    
+    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()


Property changes on: branches/sandbox/scipy/sandbox/mkufunc/mkufunc/fast_vectorize.py
___________________________________________________________________
Name: svn:mergeinfo
   + 

Added: branches/sandbox/scipy/sandbox/mkufunc/mkufunc/func_hash.py
===================================================================
--- branches/sandbox/scipy/sandbox/mkufunc/mkufunc/func_hash.py	2008-08-18 05:37:28 UTC (rev 4649)
+++ branches/sandbox/scipy/sandbox/mkufunc/mkufunc/func_hash.py	2008-08-18 20:40:53 UTC (rev 4650)
@@ -0,0 +1,40 @@
+"""
+
+Author: Ilan Schnell
+"""
+import md5
+import re
+from types import CodeType, FunctionType
+
+def md5sum(s):
+    return md5.md5(s).hexdigest()
+
+
+pat_hex = re.compile(r'0x[0-9a-f]{4,}', re.I)
+
+
+def func_hash(f, salt=None):
+    """ Return a MD5 hash for a function or code object as string.
+    """
+    if type(f) == FunctionType:
+        co = f.func_code
+    elif type(f) == CodeType:
+        co = f
+    else:
+        raise TypeError("Object %r is not function or code object.")
+    
+    res = []
+    for name in dir(co):
+        if not name.startswith('co_'):
+            continue
+        if name == 'co_consts':
+            for c in getattr(co, name):
+                if type(c) == CodeType or \
+                   type(c) == FunctionType:
+                    res.append(func_hash(c))
+                else:
+                    res.append(repr(c))
+        else:
+            res.append(repr(getattr(co, name)))
+            
+    return md5sum(''.join(res) + repr(salt))

Modified: branches/sandbox/scipy/sandbox/mkufunc/mkufunc/interactive.py
===================================================================
--- branches/sandbox/scipy/sandbox/mkufunc/mkufunc/interactive.py	2008-08-18 05:37:28 UTC (rev 4649)
+++ branches/sandbox/scipy/sandbox/mkufunc/mkufunc/interactive.py	2008-08-18 20:40:53 UTC (rev 4650)
@@ -1,3 +1,8 @@
+"""
+This file is essentially the file pypy-dist/pypy/translator/interactive.py
+with some modifications to get the c_source_filename.
+"""
+
 import driver
 
 from pypy.translator.translator import TranslationContext

Copied: branches/sandbox/scipy/sandbox/mkufunc/mkufunc/test_fast_vectorize.py (from rev 4649, branches/sandbox/scipy/sandbox/mkufunc/mkufunc/test_mkufunc.py)
===================================================================
--- branches/sandbox/scipy/sandbox/mkufunc/mkufunc/test_mkufunc.py	2008-08-18 05:37:28 UTC (rev 4649)
+++ branches/sandbox/scipy/sandbox/mkufunc/mkufunc/test_fast_vectorize.py	2008-08-18 20:40:53 UTC (rev 4650)
@@ -0,0 +1,323 @@
+import math
+import unittest
+
+from numpy import array, arange, allclose
+
+from fast_vectorize import Cfunc, genufunc, fast_vectorize
+
+
+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):
+        @fast_vectorize
+        def f(x):
+            return x * x
+        self.check_ufunc(f)
+
+    def test_noargs(self):
+        @fast_vectorize()
+        def f(x):
+            return x * x
+        self.check_ufunc(f)
+
+    def test_varargs(self):
+        for arg in (float,
+                    [float],
+                    [(float, float)]):
+            @fast_vectorize(arg)
+            def f(x):
+                return x * x
+            self.check_ufunc(f)
+
+    def test_int(self):
+        @fast_vectorize(int)
+        def f(x):
+            return x * x
+        self.assertEqual(f(3), 9)
+        self.assert_(isinstance(f(42), int))
+
+    def test_mixed(self):
+        @fast_vectorize([(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, fast_vectorize, {})
+        self.assertRaises(TypeError, fast_vectorize([(float,)]), f)
+        self.assertRaises(TypeError, fast_vectorize([3*(float,)]), f)
+        self.assertRaises(TypeError, fast_vectorize([{}]), f)
+        self.assertRaises(TypeError, fast_vectorize([(int, {})]), f)
+        self.assertRaises(ValueError, fast_vectorize([]), 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_pi(self):
+        @fast_vectorize
+        def f(x): return math.pi * x
+        self.assertFuncsEqual(f, lambda x: math.pi * x)
+
+    def test_e(self):
+        @fast_vectorize
+        def f(x): return math.e * x
+        self.assertFuncsEqual(f, lambda x: math.e * x)
+
+    def test_exp(self):
+        @fast_vectorize
+        def f(x): return math.exp(x)
+        self.assertFuncsEqual(f, math.exp)
+
+    def test_log(self):
+        @fast_vectorize
+        def f(x): return math.log(x)
+        self.assertFuncsEqual(f, math.log)
+
+    def test_log10(self):
+        @fast_vectorize
+        def f(x): return math.log10(x)
+        self.assertFuncsEqual(f, math.log10)
+
+    def test_sqrt(self):
+        @fast_vectorize
+        def f(x): return math.sqrt(x)
+        self.assertFuncsEqual(f, math.sqrt)
+
+    def test_cos(self):
+        @fast_vectorize
+        def f(x): return math.cos(x)
+        self.assertFuncsEqual(f, math.cos)
+
+    def test_sin(self):
+        @fast_vectorize
+        def f(x): return math.sin(x)
+        self.assertFuncsEqual(f, math.sin)
+
+    def test_tan(self):
+        @fast_vectorize
+        def f(x): return math.tan(x)
+        self.assertFuncsEqual(f, math.tan)
+
+    def test_cosh(self):
+        @fast_vectorize
+        def f(x): return math.cosh(x)
+        self.assertFuncsEqual(f, math.cosh)
+
+    def test_sinh(self):
+        @fast_vectorize
+        def f(x): return math.sinh(x)
+        self.assertFuncsEqual(f, math.sinh)
+
+    def test_tanh(self):
+        @fast_vectorize
+        def f(x): return math.tanh(x)
+        self.assertFuncsEqual(f, math.tanh)
+
+    def test_acos(self):
+        @fast_vectorize
+        def f(x): return math.acos(x)
+        self.assertFuncsEqual(f, math.acos)
+
+    def test_asin(self):
+        @fast_vectorize
+        def f(x): return math.asin(x)
+        self.assertFuncsEqual(f, math.asin)
+
+    def test_atan(self):
+        @fast_vectorize
+        def f(x): return math.atan(x)
+        self.assertFuncsEqual(f, math.atan)
+
+    def test_atan2(self):
+        @fast_vectorize
+        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, -1.0])
+        yy = array([1.0, 2.0,  7.5, -8.7,  0.0, -3.2])
+        a = f(xx, yy)
+        b = [math.atan2(x, y) for x, y in zip(xx, yy)]
+        self.assertClose(a, b)
+
+    def test_pow(self):
+        @fast_vectorize
+        def f(x, y):
+            return math.pow(x, y)
+
+        self.assertClose(f(2, 3), 8)
+
+        xx = array([1.0, 3.0, 2.4, 0.0, 0.0, 0.0, 2.3,  2.0])
+        yy = array([1.0, 2.0, 7.5, 0.0, 0.5, 1.0, 0.0, -1.0])
+        a = f(xx, yy)
+        b = [math.pow(x, y) for x, y in zip(xx, yy)]
+        self.assertClose(a, b)
+
+    def test_hypot(self):
+        @fast_vectorize
+        def f(x, y):
+            return math.hypot(x, y)
+
+        self.assertClose(f(3, 4), 5)
+
+        xx = array([3.0, 2.4, -2.4,  3.1, -2.3, -1.0])
+        yy = array([4.0, 7.5,  7.5, -8.7,  0.0, -3.2])
+        a = f(xx, yy)
+        b = [math.hypot(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 = fast_vectorize(f)
+        x = arange(0, 2, 0.1)
+        self.assertClose(uf(x), f(x))
+
+    def test_modulo(self):
+        @fast_vectorize(int)
+        def f(i):
+            return i % 5
+
+        for i in xrange(100):
+            self.assertEqual(f(i), i % 5)
+        
+        self.assert_((f(arange(8)) == array([0, 1, 2, 3, 4, 0, 1, 2])).all())
+
+
+class Control_Flow_Tests(unittest.TestCase):
+
+    def test_if(self):
+        @fast_vectorize(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):
+        @fast_vectorize(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):
+        @fast_vectorize(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
+        @fast_vectorize
+        def f(x):
+            return a * x
+
+        x = arange(0, 1, 0.1)
+        self.assertClose(f(x), a * x)
+
+
+class Misc_Tests(unittest.TestCase, Util):
+
+    def test_lambda(self):
+        self.assertRaises(AssertionError, fast_vectorize, lambda x: x*x + 2)
+
+    def test_angle(self):
+        from math import sin, pi, sqrt
+        @fast_vectorize
+        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])
+
+
+
+if __name__ == '__main__':
+    unittest.main()


Property changes on: branches/sandbox/scipy/sandbox/mkufunc/mkufunc/test_fast_vectorize.py
___________________________________________________________________
Name: svn:mergeinfo
   + 

Deleted: branches/sandbox/scipy/sandbox/mkufunc/mkufunc/test_func_hash.py
===================================================================
--- branches/sandbox/scipy/sandbox/mkufunc/mkufunc/test_func_hash.py	2008-08-18 05:37:28 UTC (rev 4649)
+++ branches/sandbox/scipy/sandbox/mkufunc/mkufunc/test_func_hash.py	2008-08-18 20:40:53 UTC (rev 4650)
@@ -1,48 +0,0 @@
-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()

Deleted: branches/sandbox/scipy/sandbox/mkufunc/mkufunc/test_mkufunc.py
===================================================================
--- branches/sandbox/scipy/sandbox/mkufunc/mkufunc/test_mkufunc.py	2008-08-18 05:37:28 UTC (rev 4649)
+++ branches/sandbox/scipy/sandbox/mkufunc/mkufunc/test_mkufunc.py	2008-08-18 20:40:53 UTC (rev 4650)
@@ -1,324 +0,0 @@
-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_pi(self):
-        @mkufunc
-        def f(x): return math.pi * x
-        self.assertFuncsEqual(f, lambda x: math.pi * x)
-
-    def test_e(self):
-        @mkufunc
-        def f(x): return math.e * x
-        self.assertFuncsEqual(f, lambda x: math.e * x)
-
-    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_log10(self):
-        @mkufunc
-        def f(x): return math.log10(x)
-        self.assertFuncsEqual(f, math.log10)
-
-    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_cosh(self):
-        @mkufunc
-        def f(x): return math.cosh(x)
-        self.assertFuncsEqual(f, math.cosh)
-
-    def test_sinh(self):
-        @mkufunc
-        def f(x): return math.sinh(x)
-        self.assertFuncsEqual(f, math.sinh)
-
-    def test_tanh(self):
-        @mkufunc
-        def f(x): return math.tanh(x)
-        self.assertFuncsEqual(f, math.tanh)
-
-    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, -1.0])
-        yy = array([1.0, 2.0,  7.5, -8.7,  0.0, -3.2])
-        a = f(xx, yy)
-        b = [math.atan2(x, y) for x, y in zip(xx, yy)]
-        self.assertClose(a, b)
-
-    def test_pow(self):
-        @mkufunc
-        def f(x, y):
-            return math.pow(x, y)
-
-        self.assertClose(f(2, 3), 8)
-
-        xx = array([1.0, 3.0, 2.4, 0.0, 0.0, 0.0, 2.3,  2.0])
-        yy = array([1.0, 2.0, 7.5, 0.0, 0.5, 1.0, 0.0, -1.0])
-        a = f(xx, yy)
-        b = [math.pow(x, y) for x, y in zip(xx, yy)]
-        self.assertClose(a, b)
-
-    def test_hypot(self):
-        @mkufunc
-        def f(x, y):
-            return math.hypot(x, y)
-
-        self.assertClose(f(3, 4), 5)
-
-        xx = array([3.0, 2.4, -2.4,  3.1, -2.3, -1.0])
-        yy = array([4.0, 7.5,  7.5, -8.7,  0.0, -3.2])
-        a = f(xx, yy)
-        b = [math.hypot(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))
-
-    def test_modulo(self):
-        @mkufunc(int)
-        def f(i):
-            return i % 5
-
-        for i in xrange(100):
-            self.assertEqual(f(i), i % 5)
-        
-        self.assert_((f(arange(8)) == array([0, 1, 2, 3, 4, 0, 1, 2])).all())
-
-
-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)
-
-
-class Misc_Tests(unittest.TestCase, Util):
-
-    def test_lambda(self):
-        self.assertRaises(AssertionError, mkufunc, lambda x: x*x + 2)
-
-    def test_angle(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])
-
-
-
-
-if __name__ == '__main__':
-    unittest.main()

Modified: branches/sandbox/scipy/sandbox/mkufunc/setup.py
===================================================================
--- branches/sandbox/scipy/sandbox/mkufunc/setup.py	2008-08-18 05:37:28 UTC (rev 4649)
+++ branches/sandbox/scipy/sandbox/mkufunc/setup.py	2008-08-18 20:40:53 UTC (rev 4650)
@@ -10,5 +10,4 @@
     zip_safe = False,
     package_data = {'': ['*.h']},
     packages = find_packages()
-    #install_requires = ['scipy >= 0.6.0']
     )



More information about the Scipy-svn mailing list