]> granicus.if.org Git - python/commitdiff
Speed up function calls into the math module by using METH_O.
authorNeal Norwitz <nnorwitz@gmail.com>
Sun, 19 Nov 2006 21:26:53 +0000 (21:26 +0000)
committerNeal Norwitz <nnorwitz@gmail.com>
Sun, 19 Nov 2006 21:26:53 +0000 (21:26 +0000)
There should be no functional changes. However, the error msgs are
slightly different.  Also verified that the module dict is not NULL on init.

Misc/NEWS
Modules/mathmodule.c

index 849911bcdd8e5d78d659c9110fc2626237c59f7f..0e2969ea5113b02748c29178a484d2ed26ce121c 100644 (file)
--- 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.
index e7fc6dd709a7c6d334e52c007a9a631c22c5a737..14e6bfc8a921331366e14a938f9df1269a3a978a 100644 (file)
@@ -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;