[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