FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

gh-90350: Optimize builtin functions min() and max() by colorfulappl · Pull Request #30286 · python/cpython · GitHub

Repository navigation

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension .c  (1) .rst  (1) All 2 file types selected
Viewed files
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Unified
Split
Hide whitespace
Diff view
Unified
Split
Hide whitespace
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Optimize builtin functions :func:`min` and :func:`max`.
81 changes: 45 additions & 36 deletions Python/bltinmodule.c
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Original file line number Diff line number Diff line change
Expand Up @@ -1766,45 +1766,39 @@ builtin_locals_impl(PyObject *module)


static PyObject *
min_max(PyObject *args, PyObject *kwds, int op)
min_max(PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames, int op)
{
PyObject *v, *it, *item, *val, *maxitem, *maxval, *keyfunc=NULL;
PyObject *emptytuple, *defaultval = NULL;
static char *kwlist[] = {"key", "default", NULL};
const char *name = op == Py_LT ? "min" : "max";
const int positional = PyTuple_Size(args) > 1;
int ret;
PyObject *it = NULL, *item, *val, *maxitem, *maxval, *keyfunc=NULL;
PyObject *defaultval = NULL;
static const char * const keywords[] = {"key", "default", NULL};
static _PyArg_Parser _parser_min = {"|$OO:min", keywords, 0};
static _PyArg_Parser _parser_max = {"|$OO:max", keywords, 0};
const char *name = (op == Py_LT) ? "min" : "max";
_PyArg_Parser *_parser = (op == Py_LT) ? &_parser_min : &_parser_max;

if (positional) {
v = args;
}
else if (!PyArg_UnpackTuple(args, name, 1, 1, &v)) {
if (PyExceptionClass_Check(PyExc_TypeError)) {
PyErr_Format(PyExc_TypeError, "%s expected at least 1 argument, got 0", name);
}
if (nargs == 0) {
PyErr_Format(PyExc_TypeError, "%s expected at least 1 argument, got 0", name);
return NULL;
}

emptytuple = PyTuple_New(0);
if (emptytuple == NULL)
return NULL;
ret = PyArg_ParseTupleAndKeywords(emptytuple, kwds,
(op == Py_LT) ? "|$OO:min" : "|$OO:max",
kwlist, &keyfunc, &defaultval);
Py_DECREF(emptytuple);
if (!ret)
if (kwnames != NULL && !_PyArg_ParseStackAndKeywords(args + nargs, 0, kwnames, _parser,
&keyfunc, &defaultval)) {
return NULL;
}

const int positional = nargs > 1; // False iff nargs == 1
if (positional && defaultval != NULL) {
PyErr_Format(PyExc_TypeError,
"Cannot specify a default for %s() with multiple "
"positional arguments", name);
return NULL;
}

it = PyObject_GetIter(v);
if (it == NULL) {
return NULL;
if (!positional) {
it = PyObject_GetIter(args[0]);
if (it == NULL) {
return NULL;
}
}

if (keyfunc == Py_None) {
Expand All @@ -1813,7 +1807,24 @@ min_max(PyObject *args, PyObject *kwds, int op)

maxitem = NULL; /* the result */
maxval = NULL; /* the value associated with the result */
while (( item = PyIter_Next(it) )) {
while (1) {
if (it == NULL) {
if (nargs-- <= 0) {
break;
}
item = *args++;
Py_INCREF(item);
}
else {
item = PyIter_Next(it);
if (item == NULL) {
if (PyErr_Occurred()) {
goto Fail_it;
}
break;
}
}

/* get the value from the key function */
if (keyfunc != NULL) {
val = PyObject_CallOneArg(keyfunc, item);
Expand Down Expand Up @@ -1847,8 +1858,6 @@ min_max(PyObject *args, PyObject *kwds, int op)
}
}
}
if (PyErr_Occurred())
goto Fail_it;
if (maxval == NULL) {
assert(maxitem == NULL);
if (defaultval != NULL) {
Expand All @@ -1860,7 +1869,7 @@ min_max(PyObject *args, PyObject *kwds, int op)
}
else
Py_DECREF(maxval);
Py_DECREF(it);
Py_XDECREF(it);
return maxitem;

Fail_it_item_and_val:
Expand All @@ -1870,15 +1879,15 @@ min_max(PyObject *args, PyObject *kwds, int op)
Fail_it:
Py_XDECREF(maxval);
Py_XDECREF(maxitem);
Py_DECREF(it);
Py_XDECREF(it);
return NULL;
}

/* AC: cannot convert yet, waiting for *args support */
static PyObject *
builtin_min(PyObject *self, PyObject *args, PyObject *kwds)
builtin_min(PyObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
{
return min_max(args, kwds, Py_LT);
return min_max(args, nargs, kwnames, Py_LT);
}

PyDoc_STRVAR(min_doc,
Expand All @@ -1893,9 +1902,9 @@ With two or more positional arguments, return the smallest argument.");

/* AC: cannot convert yet, waiting for *args support */
static PyObject *
builtin_max(PyObject *self, PyObject *args, PyObject *kwds)
builtin_max(PyObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
{
return min_max(args, kwds, Py_GT);
return min_max(args, nargs, kwnames, Py_GT);
}

PyDoc_STRVAR(max_doc,
Expand Down Expand Up @@ -3054,8 +3063,8 @@ static PyMethodDef builtin_methods[] = {
BUILTIN_AITER_METHODDEF
BUILTIN_LEN_METHODDEF
BUILTIN_LOCALS_METHODDEF
{"max", _PyCFunction_CAST(builtin_max), METH_VARARGS | METH_KEYWORDS, max_doc},
{"min", _PyCFunction_CAST(builtin_min), METH_VARARGS | METH_KEYWORDS, min_doc},
{"max", _PyCFunction_CAST(builtin_max), METH_FASTCALL | METH_KEYWORDS, max_doc},
{"min", _PyCFunction_CAST(builtin_min), METH_FASTCALL | METH_KEYWORDS, min_doc},
{"next", _PyCFunction_CAST(builtin_next), METH_FASTCALL, next_doc},
BUILTIN_ANEXT_METHODDEF
BUILTIN_OCT_METHODDEF
Expand Down

Back | FazBrowse Home | New Git URL