[Scipy-svn] r4500 - trunk/scipy/sandbox/mkufunc

scipy-svn@scip... scipy-svn@scip...
Sun Jun 29 17:21:39 CDT 2008


Author: ilan
Date: 2008-06-29 17:21:36 -0500 (Sun, 29 Jun 2008)
New Revision: 4500

Added:
   trunk/scipy/sandbox/mkufunc/pypy_head.h
Removed:
   trunk/scipy/sandbox/mkufunc/head.c
Modified:
   trunk/scipy/sandbox/mkufunc/funcutil.py
   trunk/scipy/sandbox/mkufunc/mkufunc.py
Log:
Implemented caching for pypy translated functions, also temp files are now stored in weave's temp directory.

Modified: trunk/scipy/sandbox/mkufunc/funcutil.py
===================================================================
--- trunk/scipy/sandbox/mkufunc/funcutil.py	2008-06-29 10:30:22 UTC (rev 4499)
+++ trunk/scipy/sandbox/mkufunc/funcutil.py	2008-06-29 22:21:36 UTC (rev 4500)
@@ -41,16 +41,16 @@
         
     return res
 
-def func_hash(f):
-    txt = disassemble2(f.func_code)
+
+def func_hash(f, extra=None):
+    txt = disassemble2(f.func_code) + repr(extra)
     #print txt
     txt = pat_white.sub(' ', txt)
     return hashlib.md5(txt).hexdigest()
 
-
 if __name__ == '__main__':
-    import math
-    from math import *
+#    import math
+#    from math import *
     
     md5sums = []
     
@@ -69,9 +69,14 @@
    
 
     def f(x):
-        return math.sin(x) + math.cos(x)
+        return math.sin(x)
     md5sums.append(func_hash(f))
-    #print md5sums
-    assert md5sums == ['91d13599d610a554dccd6b44cb5ef1f0',
-                       'be0c54b477180f897cbf7604fc565d18',
-                       '732d1ef6c1ce8cc92a7f28917496d292']
+
+    def f(x):
+        return sin(x)
+    md5sums.append(func_hash(f, float))
+    
+    print md5sums
+    #assert md5sums == ['91d13599d610a554dccd6b44cb5ef1f0',
+    #                   'be0c54b477180f897cbf7604fc565d18',
+    #                   '732d1ef6c1ce8cc92a7f28917496d292']

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

Modified: trunk/scipy/sandbox/mkufunc/mkufunc.py
===================================================================
--- trunk/scipy/sandbox/mkufunc/mkufunc.py	2008-06-29 10:30:22 UTC (rev 4499)
+++ trunk/scipy/sandbox/mkufunc/mkufunc.py	2008-06-29 22:21:36 UTC (rev 4500)
@@ -5,24 +5,31 @@
 """
 import sys
 import re
+import os.path
 import cStringIO
 from types import FunctionType
 
 import numpy
-import scipy.weave as weave
+from scipy import weave
 
-from interactive import Translation
 from funcutil import func_hash
 
 
 verbose = False
 
 def translate(f, argtypes):
-
+    cache_fname = os.path.join(weave.catalog.default_dir(),
+                               'pypy_%s.c' % func_hash(f, argtypes))
+    try:
+        return open(cache_fname).read()
+    except IOError:
+        pass
+    
+    from interactive import Translation
     if not verbose:
         tmp = sys.stderr
         sys.stderr = cStringIO.StringIO()
-
+        
     t = Translation(f, backend='c')
     t.annotate(argtypes)
     t.source()
@@ -33,9 +40,15 @@
     c_source_filename = t.driver.c_source_filename
     assert c_source_filename.endswith('.c')
     
-    return open(c_source_filename, 'r').read()
+    src = open(c_source_filename, 'r').read()
 
+    fo = open(cache_fname, 'w')
+    fo.write(src)
+    fo.close()
 
+    return src
+
+
 class Ctype:
     def __init__(self, npy, c):
         self.npy = npy
@@ -180,13 +193,17 @@
 }
 ''' % locals()
 
+pypyc = os.path.join(weave.catalog.default_temp_dir(), 'pypy.c')
 
 def write_pypyc(cfuncs):
     """ Given a list of Cfunc instances, write the C code containing the
     functions into a file.
     """
-    fo = open('pypy.c', 'w');
-    fo.write('#include "head.c"\n\n')
+    header = open(os.path.join(os.path.dirname(__file__),
+                               'pypy_head.h')).read()
+    fo = open(pypyc, 'w')
+    fo.write(header)
+    fo.write('/********************* end header ********************/\n\n')
     for cf in cfuncs:
         fo.write(cf.cfunc())
     fo.close()
@@ -279,13 +296,12 @@
     
     ufunc_info = weave.base_info.custom_info()
     ufunc_info.add_header('"numpy/ufuncobject.h"')
-    ufunc_info.add_include_dir('"."')
     
     return weave.inline(code,
-                        verbose=0, #force=1,
+                        verbose=0,
                         support_code=support_code,
                         customize=ufunc_info,
-                        sources=['pypy.c'])
+                        sources=[pypyc])
 
 
 def mkufunc(arg0=[float]):

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



More information about the Scipy-svn mailing list