Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit d0d3e99

Browse files
bpo-35719: Optimize multi-argument math functions. (pythonGH-11527)
Use the fast call convention for math functions atan2(), copysign(), hypot() and remainder() and inline unpacking arguments. This sped up them by 1.3--2.5 times.
1 parent 7934266 commit d0d3e99

File tree

2 files changed

+20
-19
lines changed

2 files changed

+20
-19
lines changed
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Sped up multi-argument :mod:`math` functions atan2(), copysign(),
2+
remainder() and hypot() by 1.3--2.5 times.

Modules/mathmodule.c

Lines changed: 18 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -997,14 +997,14 @@ math_1_to_int(PyObject *arg, double (*func) (double), int can_overflow)
997997
}
998998

999999
static PyObject *
1000-
math_2(PyObject *args, double (*func) (double, double), const char *funcname)
1000+
math_2(PyObject *const *args, Py_ssize_t nargs,
1001+
double (*func) (double, double), const char *funcname)
10011002
{
1002-
PyObject *ox, *oy;
10031003
double x, y, r;
1004-
if (! PyArg_UnpackTuple(args, funcname, 2, 2, &ox, &oy))
1004+
if (!_PyArg_CheckPositional(funcname, nargs, 2, 2))
10051005
return NULL;
1006-
x = PyFloat_AsDouble(ox);
1007-
y = PyFloat_AsDouble(oy);
1006+
x = PyFloat_AsDouble(args[0]);
1007+
y = PyFloat_AsDouble(args[1]);
10081008
if ((x == -1.0 || y == -1.0) && PyErr_Occurred())
10091009
return NULL;
10101010
errno = 0;
@@ -1042,8 +1042,8 @@ math_2(PyObject *args, double (*func) (double, double), const char *funcname)
10421042
PyDoc_STRVAR(math_##funcname##_doc, docstring);
10431043

10441044
#define FUNC2(funcname, func, docstring) \
1045-
static PyObject * math_##funcname(PyObject *self, PyObject *args) { \
1046-
return math_2(args, func, #funcname); \
1045+
static PyObject * math_##funcname(PyObject *self, PyObject *const *args, Py_ssize_t nargs) { \
1046+
return math_2(args, nargs, func, #funcname); \
10471047
}\
10481048
PyDoc_STRVAR(math_##funcname##_doc, docstring);
10491049

@@ -2181,25 +2181,24 @@ math_dist_impl(PyObject *module, PyObject *p, PyObject *q)
21812181

21822182
/* AC: cannot convert yet, waiting for *args support */
21832183
static PyObject *
2184-
math_hypot(PyObject *self, PyObject *args)
2184+
math_hypot(PyObject *self, PyObject *const *args, Py_ssize_t nargs)
21852185
{
2186-
Py_ssize_t i, n;
2186+
Py_ssize_t i;
21872187
PyObject *item;
21882188
double max = 0.0;
21892189
double x, result;
21902190
int found_nan = 0;
21912191
double coord_on_stack[NUM_STACK_ELEMS];
21922192
double *coordinates = coord_on_stack;
21932193

2194-
n = PyTuple_GET_SIZE(args);
2195-
if (n > NUM_STACK_ELEMS) {
2196-
coordinates = (double *) PyObject_Malloc(n * sizeof(double));
2194+
if (nargs > NUM_STACK_ELEMS) {
2195+
coordinates = (double *) PyObject_Malloc(nargs * sizeof(double));
21972196
if (coordinates == NULL) {
21982197
return PyErr_NoMemory();
21992198
}
22002199
}
2201-
for (i=0 ; i<n ; i++) {
2202-
item = PyTuple_GET_ITEM(args, i);
2200+
for (i = 0; i < nargs; i++) {
2201+
item = args[i];
22032202
if (PyFloat_CheckExact(item)) {
22042203
x = PyFloat_AS_DOUBLE(item);
22052204
} else {
@@ -2215,7 +2214,7 @@ math_hypot(PyObject *self, PyObject *args)
22152214
max = x;
22162215
}
22172216
}
2218-
result = vector_norm(n, coordinates, max, found_nan);
2217+
result = vector_norm(nargs, coordinates, max, found_nan);
22192218
if (coordinates != coord_on_stack) {
22202219
PyObject_Free(coordinates);
22212220
}
@@ -2497,10 +2496,10 @@ static PyMethodDef math_methods[] = {
24972496
{"asin", math_asin, METH_O, math_asin_doc},
24982497
{"asinh", math_asinh, METH_O, math_asinh_doc},
24992498
{"atan", math_atan, METH_O, math_atan_doc},
2500-
{"atan2", math_atan2, METH_VARARGS, math_atan2_doc},
2499+
{"atan2", (PyCFunction)(void(*)(void))math_atan2, METH_FASTCALL, math_atan2_doc},
25012500
{"atanh", math_atanh, METH_O, math_atanh_doc},
25022501
MATH_CEIL_METHODDEF
2503-
{"copysign", math_copysign, METH_VARARGS, math_copysign_doc},
2502+
{"copysign", (PyCFunction)(void(*)(void))math_copysign, METH_FASTCALL, math_copysign_doc},
25042503
{"cos", math_cos, METH_O, math_cos_doc},
25052504
{"cosh", math_cosh, METH_O, math_cosh_doc},
25062505
MATH_DEGREES_METHODDEF
@@ -2517,7 +2516,7 @@ static PyMethodDef math_methods[] = {
25172516
MATH_FSUM_METHODDEF
25182517
{"gamma", math_gamma, METH_O, math_gamma_doc},
25192518
MATH_GCD_METHODDEF
2520-
{"hypot", math_hypot, METH_VARARGS, math_hypot_doc},
2519+
{"hypot", (PyCFunction)(void(*)(void))math_hypot, METH_FASTCALL, math_hypot_doc},
25212520
MATH_ISCLOSE_METHODDEF
25222521
MATH_ISFINITE_METHODDEF
25232522
MATH_ISINF_METHODDEF
@@ -2531,7 +2530,7 @@ static PyMethodDef math_methods[] = {
25312530
MATH_MODF_METHODDEF
25322531
MATH_POW_METHODDEF
25332532
MATH_RADIANS_METHODDEF
2534-
{"remainder", math_remainder, METH_VARARGS, math_remainder_doc},
2533+
{"remainder", (PyCFunction)(void(*)(void))math_remainder, METH_FASTCALL, math_remainder_doc},
25352534
{"sin", math_sin, METH_O, math_sin_doc},
25362535
{"sinh", math_sinh, METH_O, math_sinh_doc},
25372536
{"sqrt", math_sqrt, METH_O, math_sqrt_doc},

0 commit comments

Comments
 (0)