diff --git a/Misc/NEWS b/Misc/NEWS index 849911bcdd8..0e2969ea511 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -236,6 +236,8 @@ Library Extension Modules ----------------- +- Speed up function calls into the math module. + - Bug #1588217: don't parse "= " as a soft line break in binascii's a2b_qp() function, instead leave it in the string as quopri.decode() does. diff --git a/Modules/mathmodule.c b/Modules/mathmodule.c index e7fc6dd709a..14e6bfc8a92 100644 --- a/Modules/mathmodule.c +++ b/Modules/mathmodule.c @@ -48,10 +48,10 @@ is_error(double x) } static PyObject * -math_1(PyObject *args, double (*func) (double), char *argsfmt) +math_1(PyObject *arg, double (*func) (double)) { - double x; - if (! PyArg_ParseTuple(args, argsfmt, &x)) + double x = PyFloat_AsDouble(arg); + if (x == -1.0 && PyErr_Occurred()) return NULL; errno = 0; PyFPE_START_PROTECT("in math_1", return 0) @@ -65,10 +65,15 @@ math_1(PyObject *args, double (*func) (double), char *argsfmt) } static PyObject * -math_2(PyObject *args, double (*func) (double, double), char *argsfmt) +math_2(PyObject *args, double (*func) (double, double), char *funcname) { + PyObject *ox, *oy; double x, y; - if (! PyArg_ParseTuple(args, argsfmt, &x, &y)) + if (! PyArg_UnpackTuple(args, funcname, 2, 2, &ox, &oy)) + return NULL; + x = PyFloat_AsDouble(ox); + y = PyFloat_AsDouble(oy); + if ((x == -1.0 || y == -1.0) && PyErr_Occurred()) return NULL; errno = 0; PyFPE_START_PROTECT("in math_2", return 0) @@ -83,13 +88,13 @@ math_2(PyObject *args, double (*func) (double, double), char *argsfmt) #define FUNC1(funcname, func, docstring) \ static PyObject * math_##funcname(PyObject *self, PyObject *args) { \ - return math_1(args, func, "d:" #funcname); \ + return math_1(args, func); \ }\ PyDoc_STRVAR(math_##funcname##_doc, docstring); #define FUNC2(funcname, func, docstring) \ static PyObject * math_##funcname(PyObject *self, PyObject *args) { \ - return math_2(args, func, "dd:" #funcname); \ + return math_2(args, func, #funcname); \ }\ PyDoc_STRVAR(math_##funcname##_doc, docstring); @@ -135,11 +140,11 @@ FUNC1(tanh, tanh, "tanh(x)\n\nReturn the hyperbolic tangent of x.") static PyObject * -math_frexp(PyObject *self, PyObject *args) +math_frexp(PyObject *self, PyObject *arg) { - double x; int i; - if (! PyArg_ParseTuple(args, "d:frexp", &x)) + double x = PyFloat_AsDouble(arg); + if (x == -1.0 && PyErr_Occurred()) return NULL; errno = 0; x = frexp(x, &i); @@ -179,10 +184,10 @@ PyDoc_STRVAR(math_ldexp_doc, "ldexp(x, i) -> x * (2**i)"); static PyObject * -math_modf(PyObject *self, PyObject *args) +math_modf(PyObject *self, PyObject *arg) { - double x, y; - if (! PyArg_ParseTuple(args, "d:modf", &x)) + double y, x = PyFloat_AsDouble(arg); + if (x == -1.0 && PyErr_Occurred()) return NULL; errno = 0; x = modf(x, &y); @@ -208,7 +213,7 @@ PyDoc_STRVAR(math_modf_doc, */ static PyObject* -loghelper(PyObject* args, double (*func)(double), char *format, PyObject *arg) +loghelper(PyObject* arg, double (*func)(double), char *funcname) { /* If it is long, do it ourselves. */ if (PyLong_Check(arg)) { @@ -229,7 +234,7 @@ loghelper(PyObject* args, double (*func)(double), char *format, PyObject *arg) } /* Else let libm handle it by itself. */ - return math_1(args, func, format); + return math_1(arg, func); } static PyObject * @@ -239,28 +244,15 @@ math_log(PyObject *self, PyObject *args) PyObject *base = NULL; PyObject *num, *den; PyObject *ans; - PyObject *newargs; if (!PyArg_UnpackTuple(args, "log", 1, 2, &arg, &base)) return NULL; - if (base == NULL) - return loghelper(args, log, "d:log", arg); - newargs = PyTuple_Pack(1, arg); - if (newargs == NULL) - return NULL; - num = loghelper(newargs, log, "d:log", arg); - Py_DECREF(newargs); - if (num == NULL) - return NULL; + num = loghelper(arg, log, "log"); + if (num == NULL || base == NULL) + return num; - newargs = PyTuple_Pack(1, base); - if (newargs == NULL) { - Py_DECREF(num); - return NULL; - } - den = loghelper(newargs, log, "d:log", base); - Py_DECREF(newargs); + den = loghelper(base, log, "log"); if (den == NULL) { Py_DECREF(num); return NULL; @@ -277,25 +269,23 @@ PyDoc_STRVAR(math_log_doc, If the base not specified, returns the natural logarithm (base e) of x."); static PyObject * -math_log10(PyObject *self, PyObject *args) +math_log10(PyObject *self, PyObject *arg) { - PyObject *arg; - - if (!PyArg_UnpackTuple(args, "log10", 1, 1, &arg)) - return NULL; - return loghelper(args, log10, "d:log10", arg); + return loghelper(arg, log10, "log10"); } PyDoc_STRVAR(math_log10_doc, "log10(x) -> the base 10 logarithm of x."); +/* XXX(nnorwitz): Should we use the platform M_PI or something more accurate + like: 3.14159265358979323846264338327950288 */ static const double degToRad = 3.141592653589793238462643383 / 180.0; static PyObject * -math_degrees(PyObject *self, PyObject *args) +math_degrees(PyObject *self, PyObject *arg) { - double x; - if (! PyArg_ParseTuple(args, "d:degrees", &x)) + double x = PyFloat_AsDouble(arg); + if (x == -1.0 && PyErr_Occurred()) return NULL; return PyFloat_FromDouble(x / degToRad); } @@ -304,10 +294,10 @@ PyDoc_STRVAR(math_degrees_doc, "degrees(x) -> converts angle x from radians to degrees"); static PyObject * -math_radians(PyObject *self, PyObject *args) +math_radians(PyObject *self, PyObject *arg) { - double x; - if (! PyArg_ParseTuple(args, "d:radians", &x)) + double x = PyFloat_AsDouble(arg); + if (x == -1.0 && PyErr_Occurred()) return NULL; return PyFloat_FromDouble(x * degToRad); } @@ -316,31 +306,31 @@ PyDoc_STRVAR(math_radians_doc, "radians(x) -> converts angle x from degrees to radians"); static PyMethodDef math_methods[] = { - {"acos", math_acos, METH_VARARGS, math_acos_doc}, - {"asin", math_asin, METH_VARARGS, math_asin_doc}, - {"atan", math_atan, METH_VARARGS, math_atan_doc}, + {"acos", math_acos, METH_O, math_acos_doc}, + {"asin", math_asin, METH_O, math_asin_doc}, + {"atan", math_atan, METH_O, math_atan_doc}, {"atan2", math_atan2, METH_VARARGS, math_atan2_doc}, - {"ceil", math_ceil, METH_VARARGS, math_ceil_doc}, - {"cos", math_cos, METH_VARARGS, math_cos_doc}, - {"cosh", math_cosh, METH_VARARGS, math_cosh_doc}, - {"degrees", math_degrees, METH_VARARGS, math_degrees_doc}, - {"exp", math_exp, METH_VARARGS, math_exp_doc}, - {"fabs", math_fabs, METH_VARARGS, math_fabs_doc}, - {"floor", math_floor, METH_VARARGS, math_floor_doc}, + {"ceil", math_ceil, METH_O, math_ceil_doc}, + {"cos", math_cos, METH_O, math_cos_doc}, + {"cosh", math_cosh, METH_O, math_cosh_doc}, + {"degrees", math_degrees, METH_O, math_degrees_doc}, + {"exp", math_exp, METH_O, math_exp_doc}, + {"fabs", math_fabs, METH_O, math_fabs_doc}, + {"floor", math_floor, METH_O, math_floor_doc}, {"fmod", math_fmod, METH_VARARGS, math_fmod_doc}, - {"frexp", math_frexp, METH_VARARGS, math_frexp_doc}, + {"frexp", math_frexp, METH_O, math_frexp_doc}, {"hypot", math_hypot, METH_VARARGS, math_hypot_doc}, {"ldexp", math_ldexp, METH_VARARGS, math_ldexp_doc}, {"log", math_log, METH_VARARGS, math_log_doc}, - {"log10", math_log10, METH_VARARGS, math_log10_doc}, - {"modf", math_modf, METH_VARARGS, math_modf_doc}, + {"log10", math_log10, METH_O, math_log10_doc}, + {"modf", math_modf, METH_O, math_modf_doc}, {"pow", math_pow, METH_VARARGS, math_pow_doc}, - {"radians", math_radians, METH_VARARGS, math_radians_doc}, - {"sin", math_sin, METH_VARARGS, math_sin_doc}, - {"sinh", math_sinh, METH_VARARGS, math_sinh_doc}, - {"sqrt", math_sqrt, METH_VARARGS, math_sqrt_doc}, - {"tan", math_tan, METH_VARARGS, math_tan_doc}, - {"tanh", math_tanh, METH_VARARGS, math_tanh_doc}, + {"radians", math_radians, METH_O, math_radians_doc}, + {"sin", math_sin, METH_O, math_sin_doc}, + {"sinh", math_sinh, METH_O, math_sinh_doc}, + {"sqrt", math_sqrt, METH_O, math_sqrt_doc}, + {"tan", math_tan, METH_O, math_tan_doc}, + {"tanh", math_tanh, METH_O, math_tanh_doc}, {NULL, NULL} /* sentinel */ }; @@ -358,6 +348,8 @@ initmath(void) if (m == NULL) goto finally; d = PyModule_GetDict(m); + if (d == NULL) + goto finally; if (!(v = PyFloat_FromDouble(atan(1.0) * 4.0))) goto finally;