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) {
