cython-devel

changeset 2765:dda8f62132fc

specialised implementation for 'float(x) -> C double' to avoid redundant calls of float()
author Stefan Behnel <scoder@users.berlios.de>
date Tue Dec 08 01:26:53 2009 +0100 (2 years ago)
parents 885dbfad02aa
children c1f3e5f0c594
files Cython/Compiler/Optimize.py
line diff
1.1 --- a/Cython/Compiler/Optimize.py Tue Dec 08 01:05:01 2009 +0100 1.2 +++ b/Cython/Compiler/Optimize.py Tue Dec 08 01:26:53 2009 +0100 1.3 @@ -884,6 +884,13 @@ 1.4 pytype_utility_code) 1.5 return node 1.6 1.7 + def _handle_simple_function_float(self, node, pos_args): 1.8 + if len(pos_args) == 0: 1.9 + return ExprNodes.FloatNode(node.pos, value='0.0') 1.10 + if len(pos_args) > 1: 1.11 + self._error_wrong_arg_count('float', node, pos_args, 1) 1.12 + return node 1.13 + 1.14 # specific handlers for general call nodes 1.15 1.16 def _handle_general_function_dict(self, node, pos_args, kwargs): 1.17 @@ -1123,6 +1130,34 @@ 1.18 is_temp = node.is_temp 1.19 ) 1.20 1.21 + PyObject_AsDouble_func_type = PyrexTypes.CFuncType( 1.22 + PyrexTypes.c_double_type, [ 1.23 + PyrexTypes.CFuncTypeArg("obj", PyrexTypes.py_object_type, None), 1.24 + ], 1.25 + exception_value = "((double)-1)", 1.26 + exception_check = True) 1.27 + 1.28 + def _handle_simple_function_float(self, node, pos_args): 1.29 + # Note: this requires the float() function to be typed as 1.30 + # returning a C 'double' 1.31 + if len(pos_args) != 1: 1.32 + self._error_wrong_arg_count('float', node, pos_args, 1) 1.33 + return node 1.34 + func_arg = pos_args[0] 1.35 + if isinstance(func_arg, ExprNodes.CoerceToPyTypeNode): 1.36 + func_arg = func_arg.arg 1.37 + if func_arg.type is PyrexTypes.c_double_type: 1.38 + return func_arg 1.39 + elif node.type.assignable_from(func_arg.type) or func_arg.type.is_numeric: 1.40 + return ExprNodes.CastNode(func_arg, node.type) 1.41 + return ExprNodes.PythonCapiCallNode( 1.42 + node.pos, "__Pyx_PyObject_AsDouble", 1.43 + self.PyObject_AsDouble_func_type, 1.44 + args = pos_args, 1.45 + is_temp = node.is_temp, 1.46 + utility_code = pyobject_as_double_utility_code, 1.47 + py_name = "float") 1.48 + 1.49 ### builtin functions 1.50 1.51 Pyx_strlen_func_type = PyrexTypes.CFuncType( 1.52 @@ -1626,6 +1661,45 @@ 1.53 ) 1.54 1.55 1.56 +pyobject_as_double_utility_code = UtilityCode( 1.57 +proto = ''' 1.58 +static double __Pyx__PyObject_AsDouble(PyObject* obj); /* proto */ 1.59 + 1.60 +#define __Pyx_PyObject_AsDouble(obj) \\ 1.61 + ((likely(PyFloat_CheckExact(obj))) ? \\ 1.62 + PyFloat_AS_DOUBLE(obj) : __Pyx__PyObject_AsDouble(obj)) 1.63 +''', 1.64 +impl=''' 1.65 +static double __Pyx__PyObject_AsDouble(PyObject* obj) { 1.66 + PyObject* float_value; 1.67 + if (Py_TYPE(obj)->tp_as_number && Py_TYPE(obj)->tp_as_number->nb_float) { 1.68 + return PyFloat_AsDouble(obj); 1.69 + } else if (PyUnicode_CheckExact(obj) || PyString_CheckExact(obj)) { 1.70 +#if PY_MAJOR_VERSION >= 3 1.71 + float_value = PyFloat_FromString(obj); 1.72 +#else 1.73 + float_value = PyFloat_FromString(obj, 0); 1.74 +#endif 1.75 + } else { 1.76 + PyObject* args = PyTuple_New(1); 1.77 + if (unlikely(!args)) goto bad; 1.78 + PyTuple_SET_ITEM(args, 0, obj); 1.79 + float_value = PyObject_Call((PyObject*)&PyFloat_Type, args, 0); 1.80 + PyTuple_SET_ITEM(args, 0, 0); 1.81 + Py_DECREF(args); 1.82 + } 1.83 + if (likely(float_value)) { 1.84 + double value = PyFloat_AS_DOUBLE(float_value); 1.85 + Py_DECREF(float_value); 1.86 + return value; 1.87 + } 1.88 +bad: 1.89 + return (double)-1; 1.90 +} 1.91 +''' 1.92 +) 1.93 + 1.94 + 1.95 pytype_utility_code = UtilityCode( 1.96 proto = """ 1.97 static INLINE PyObject* __Pyx_Type(PyObject* o) {