Speed up function calls into the math module by using METH_O.
There should be no functional changes. However, the error msgs are slightly different. Also verified that the module dict is not NULL on init.
This commit is contained in:
parent
07529354db
commit
45e230a8e1
|
@ -236,6 +236,8 @@ Library
|
||||||
Extension Modules
|
Extension Modules
|
||||||
-----------------
|
-----------------
|
||||||
|
|
||||||
|
- Speed up function calls into the math module.
|
||||||
|
|
||||||
- Bug #1588217: don't parse "= " as a soft line break in binascii's
|
- 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()
|
a2b_qp() function, instead leave it in the string as quopri.decode()
|
||||||
does.
|
does.
|
||||||
|
|
|
@ -48,10 +48,10 @@ is_error(double x)
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
math_1(PyObject *args, double (*func) (double), char *argsfmt)
|
math_1(PyObject *arg, double (*func) (double))
|
||||||
{
|
{
|
||||||
double x;
|
double x = PyFloat_AsDouble(arg);
|
||||||
if (! PyArg_ParseTuple(args, argsfmt, &x))
|
if (x == -1.0 && PyErr_Occurred())
|
||||||
return NULL;
|
return NULL;
|
||||||
errno = 0;
|
errno = 0;
|
||||||
PyFPE_START_PROTECT("in math_1", return 0)
|
PyFPE_START_PROTECT("in math_1", return 0)
|
||||||
|
@ -65,10 +65,15 @@ math_1(PyObject *args, double (*func) (double), char *argsfmt)
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject *
|
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;
|
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;
|
return NULL;
|
||||||
errno = 0;
|
errno = 0;
|
||||||
PyFPE_START_PROTECT("in math_2", return 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) \
|
#define FUNC1(funcname, func, docstring) \
|
||||||
static PyObject * math_##funcname(PyObject *self, PyObject *args) { \
|
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);
|
PyDoc_STRVAR(math_##funcname##_doc, docstring);
|
||||||
|
|
||||||
#define FUNC2(funcname, func, docstring) \
|
#define FUNC2(funcname, func, docstring) \
|
||||||
static PyObject * math_##funcname(PyObject *self, PyObject *args) { \
|
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);
|
PyDoc_STRVAR(math_##funcname##_doc, docstring);
|
||||||
|
|
||||||
|
@ -135,11 +140,11 @@ FUNC1(tanh, tanh,
|
||||||
"tanh(x)\n\nReturn the hyperbolic tangent of x.")
|
"tanh(x)\n\nReturn the hyperbolic tangent of x.")
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
math_frexp(PyObject *self, PyObject *args)
|
math_frexp(PyObject *self, PyObject *arg)
|
||||||
{
|
{
|
||||||
double x;
|
|
||||||
int i;
|
int i;
|
||||||
if (! PyArg_ParseTuple(args, "d:frexp", &x))
|
double x = PyFloat_AsDouble(arg);
|
||||||
|
if (x == -1.0 && PyErr_Occurred())
|
||||||
return NULL;
|
return NULL;
|
||||||
errno = 0;
|
errno = 0;
|
||||||
x = frexp(x, &i);
|
x = frexp(x, &i);
|
||||||
|
@ -179,10 +184,10 @@ PyDoc_STRVAR(math_ldexp_doc,
|
||||||
"ldexp(x, i) -> x * (2**i)");
|
"ldexp(x, i) -> x * (2**i)");
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
math_modf(PyObject *self, PyObject *args)
|
math_modf(PyObject *self, PyObject *arg)
|
||||||
{
|
{
|
||||||
double x, y;
|
double y, x = PyFloat_AsDouble(arg);
|
||||||
if (! PyArg_ParseTuple(args, "d:modf", &x))
|
if (x == -1.0 && PyErr_Occurred())
|
||||||
return NULL;
|
return NULL;
|
||||||
errno = 0;
|
errno = 0;
|
||||||
x = modf(x, &y);
|
x = modf(x, &y);
|
||||||
|
@ -208,7 +213,7 @@ PyDoc_STRVAR(math_modf_doc,
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static PyObject*
|
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 it is long, do it ourselves. */
|
||||||
if (PyLong_Check(arg)) {
|
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. */
|
/* Else let libm handle it by itself. */
|
||||||
return math_1(args, func, format);
|
return math_1(arg, func);
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
|
@ -239,28 +244,15 @@ math_log(PyObject *self, PyObject *args)
|
||||||
PyObject *base = NULL;
|
PyObject *base = NULL;
|
||||||
PyObject *num, *den;
|
PyObject *num, *den;
|
||||||
PyObject *ans;
|
PyObject *ans;
|
||||||
PyObject *newargs;
|
|
||||||
|
|
||||||
if (!PyArg_UnpackTuple(args, "log", 1, 2, &arg, &base))
|
if (!PyArg_UnpackTuple(args, "log", 1, 2, &arg, &base))
|
||||||
return NULL;
|
return NULL;
|
||||||
if (base == NULL)
|
|
||||||
return loghelper(args, log, "d:log", arg);
|
|
||||||
|
|
||||||
newargs = PyTuple_Pack(1, arg);
|
num = loghelper(arg, log, "log");
|
||||||
if (newargs == NULL)
|
if (num == NULL || base == NULL)
|
||||||
return NULL;
|
return num;
|
||||||
num = loghelper(newargs, log, "d:log", arg);
|
|
||||||
Py_DECREF(newargs);
|
|
||||||
if (num == NULL)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
newargs = PyTuple_Pack(1, base);
|
den = loghelper(base, log, "log");
|
||||||
if (newargs == NULL) {
|
|
||||||
Py_DECREF(num);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
den = loghelper(newargs, log, "d:log", base);
|
|
||||||
Py_DECREF(newargs);
|
|
||||||
if (den == NULL) {
|
if (den == NULL) {
|
||||||
Py_DECREF(num);
|
Py_DECREF(num);
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -277,25 +269,23 @@ PyDoc_STRVAR(math_log_doc,
|
||||||
If the base not specified, returns the natural logarithm (base e) of x.");
|
If the base not specified, returns the natural logarithm (base e) of x.");
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
math_log10(PyObject *self, PyObject *args)
|
math_log10(PyObject *self, PyObject *arg)
|
||||||
{
|
{
|
||||||
PyObject *arg;
|
return loghelper(arg, log10, "log10");
|
||||||
|
|
||||||
if (!PyArg_UnpackTuple(args, "log10", 1, 1, &arg))
|
|
||||||
return NULL;
|
|
||||||
return loghelper(args, log10, "d:log10", arg);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PyDoc_STRVAR(math_log10_doc,
|
PyDoc_STRVAR(math_log10_doc,
|
||||||
"log10(x) -> the base 10 logarithm of x.");
|
"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 const double degToRad = 3.141592653589793238462643383 / 180.0;
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
math_degrees(PyObject *self, PyObject *args)
|
math_degrees(PyObject *self, PyObject *arg)
|
||||||
{
|
{
|
||||||
double x;
|
double x = PyFloat_AsDouble(arg);
|
||||||
if (! PyArg_ParseTuple(args, "d:degrees", &x))
|
if (x == -1.0 && PyErr_Occurred())
|
||||||
return NULL;
|
return NULL;
|
||||||
return PyFloat_FromDouble(x / degToRad);
|
return PyFloat_FromDouble(x / degToRad);
|
||||||
}
|
}
|
||||||
|
@ -304,10 +294,10 @@ PyDoc_STRVAR(math_degrees_doc,
|
||||||
"degrees(x) -> converts angle x from radians to degrees");
|
"degrees(x) -> converts angle x from radians to degrees");
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
math_radians(PyObject *self, PyObject *args)
|
math_radians(PyObject *self, PyObject *arg)
|
||||||
{
|
{
|
||||||
double x;
|
double x = PyFloat_AsDouble(arg);
|
||||||
if (! PyArg_ParseTuple(args, "d:radians", &x))
|
if (x == -1.0 && PyErr_Occurred())
|
||||||
return NULL;
|
return NULL;
|
||||||
return PyFloat_FromDouble(x * degToRad);
|
return PyFloat_FromDouble(x * degToRad);
|
||||||
}
|
}
|
||||||
|
@ -316,31 +306,31 @@ PyDoc_STRVAR(math_radians_doc,
|
||||||
"radians(x) -> converts angle x from degrees to radians");
|
"radians(x) -> converts angle x from degrees to radians");
|
||||||
|
|
||||||
static PyMethodDef math_methods[] = {
|
static PyMethodDef math_methods[] = {
|
||||||
{"acos", math_acos, METH_VARARGS, math_acos_doc},
|
{"acos", math_acos, METH_O, math_acos_doc},
|
||||||
{"asin", math_asin, METH_VARARGS, math_asin_doc},
|
{"asin", math_asin, METH_O, math_asin_doc},
|
||||||
{"atan", math_atan, METH_VARARGS, math_atan_doc},
|
{"atan", math_atan, METH_O, math_atan_doc},
|
||||||
{"atan2", math_atan2, METH_VARARGS, math_atan2_doc},
|
{"atan2", math_atan2, METH_VARARGS, math_atan2_doc},
|
||||||
{"ceil", math_ceil, METH_VARARGS, math_ceil_doc},
|
{"ceil", math_ceil, METH_O, math_ceil_doc},
|
||||||
{"cos", math_cos, METH_VARARGS, math_cos_doc},
|
{"cos", math_cos, METH_O, math_cos_doc},
|
||||||
{"cosh", math_cosh, METH_VARARGS, math_cosh_doc},
|
{"cosh", math_cosh, METH_O, math_cosh_doc},
|
||||||
{"degrees", math_degrees, METH_VARARGS, math_degrees_doc},
|
{"degrees", math_degrees, METH_O, math_degrees_doc},
|
||||||
{"exp", math_exp, METH_VARARGS, math_exp_doc},
|
{"exp", math_exp, METH_O, math_exp_doc},
|
||||||
{"fabs", math_fabs, METH_VARARGS, math_fabs_doc},
|
{"fabs", math_fabs, METH_O, math_fabs_doc},
|
||||||
{"floor", math_floor, METH_VARARGS, math_floor_doc},
|
{"floor", math_floor, METH_O, math_floor_doc},
|
||||||
{"fmod", math_fmod, METH_VARARGS, math_fmod_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},
|
{"hypot", math_hypot, METH_VARARGS, math_hypot_doc},
|
||||||
{"ldexp", math_ldexp, METH_VARARGS, math_ldexp_doc},
|
{"ldexp", math_ldexp, METH_VARARGS, math_ldexp_doc},
|
||||||
{"log", math_log, METH_VARARGS, math_log_doc},
|
{"log", math_log, METH_VARARGS, math_log_doc},
|
||||||
{"log10", math_log10, METH_VARARGS, math_log10_doc},
|
{"log10", math_log10, METH_O, math_log10_doc},
|
||||||
{"modf", math_modf, METH_VARARGS, math_modf_doc},
|
{"modf", math_modf, METH_O, math_modf_doc},
|
||||||
{"pow", math_pow, METH_VARARGS, math_pow_doc},
|
{"pow", math_pow, METH_VARARGS, math_pow_doc},
|
||||||
{"radians", math_radians, METH_VARARGS, math_radians_doc},
|
{"radians", math_radians, METH_O, math_radians_doc},
|
||||||
{"sin", math_sin, METH_VARARGS, math_sin_doc},
|
{"sin", math_sin, METH_O, math_sin_doc},
|
||||||
{"sinh", math_sinh, METH_VARARGS, math_sinh_doc},
|
{"sinh", math_sinh, METH_O, math_sinh_doc},
|
||||||
{"sqrt", math_sqrt, METH_VARARGS, math_sqrt_doc},
|
{"sqrt", math_sqrt, METH_O, math_sqrt_doc},
|
||||||
{"tan", math_tan, METH_VARARGS, math_tan_doc},
|
{"tan", math_tan, METH_O, math_tan_doc},
|
||||||
{"tanh", math_tanh, METH_VARARGS, math_tanh_doc},
|
{"tanh", math_tanh, METH_O, math_tanh_doc},
|
||||||
{NULL, NULL} /* sentinel */
|
{NULL, NULL} /* sentinel */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -358,6 +348,8 @@ initmath(void)
|
||||||
if (m == NULL)
|
if (m == NULL)
|
||||||
goto finally;
|
goto finally;
|
||||||
d = PyModule_GetDict(m);
|
d = PyModule_GetDict(m);
|
||||||
|
if (d == NULL)
|
||||||
|
goto finally;
|
||||||
|
|
||||||
if (!(v = PyFloat_FromDouble(atan(1.0) * 4.0)))
|
if (!(v = PyFloat_FromDouble(atan(1.0) * 4.0)))
|
||||||
goto finally;
|
goto finally;
|
||||||
|
|
Loading…
Reference in New Issue