1318a1319,1507 > static PyObject * > builtin_minmax(PyObject *self, PyObject *args, PyObject *kwds) > { > const char *name = "minmax"; > PyObject *v, *it, *item, *val, *item2, *val2, *minitem, *minval, *maxitem, *maxval, *keyfunc=NULL; > PyObject *result = NULL; > int seqlen, cmp; > > if (PyTuple_Size(args) > 1) > v = args; > else if (!PyArg_UnpackTuple(args, (char *)name, 1, 1, &v)) > return NULL; > > if (kwds != NULL && PyDict_Check(kwds) && PyDict_Size(kwds)) { > keyfunc = PyDict_GetItemString(kwds, "key"); > if (PyDict_Size(kwds)!=1 || keyfunc == NULL) { > PyErr_Format(PyExc_TypeError, > "%s() got an unexpected keyword argument", name); > return NULL; > } > Py_INCREF(keyfunc); > } > > it = PyObject_GetIter(v); > if (it == NULL) { > Py_XDECREF(keyfunc); > return NULL; > } > > minitem = NULL; /* the results */ > maxitem = NULL; > minval = NULL; /* the values associated with the results */ > maxval = NULL; > > /* initialize min and max returns with the first item in the list */ > item = PyIter_Next(it); > if (item == NULL) > { > //minitem = Py_None; > //Py_INCREF(minitem); > //maxitem = Py_None; > //Py_INCREF(maxitem); > goto EarlyExit_short_sequence; > } > > if (keyfunc != NULL) { > val = PyObject_CallFunctionObjArgs(keyfunc, item, NULL); > if (val == NULL) > goto Fail_it_item; > } > /* no key function; the value is the item */ > else { > val = item; > // increment twice, as we will assign to both min and max return vals > Py_INCREF(val); > Py_INCREF(val); > } > > minitem = item; > minval = val; > maxitem = item; /* the result */ > maxval = val; /* the value associated with the result */ > > seqlen = PySequence_Length(v); > > // if even length sequence, put iter back at 0, to safely read by pairs > if (seqlen % 2 == 0) { > it = PyObject_GetIter(v); > } > > // read by pairs > while (( item = PyIter_Next(it) ) && (item2 = PyIter_Next(it))) { > > /* get the value from the key function */ > if (keyfunc != NULL) { > val = PyObject_CallFunctionObjArgs(keyfunc, item, NULL); > val2 = PyObject_CallFunctionObjArgs(keyfunc, item2, NULL); > if (val == NULL || val2 == NULL) > goto Fail_it_item; > } > /* no key function; the value is the item */ > else { > val = item; > Py_INCREF(val); > val2 = item2; > Py_INCREF(val2); > } > > > /* > if a > b: > a,b = b,a > */ > cmp = PyObject_RichCompareBool(val, val2, Py_GT); > if (cmp < 0) > goto Fail_it_item_and_val; > else if (cmp > 0) { > PyObject* tmp; > tmp = val; val = val2; val2 = tmp; > tmp = item; item = item2; item2 = tmp; > } > > /* > if a < min_: > min_ = a > */ > cmp = PyObject_RichCompareBool(val, minval, Py_LT); > if (cmp < 0) > goto Fail_it_item_and_val; > else if (cmp > 0) { > Py_DECREF(minval); > Py_DECREF(minitem); > minval = val; > minitem = item; > } > else { > Py_DECREF(item); > Py_DECREF(val); > } > > /* > if b > max_: > max_ = b > */ > cmp = PyObject_RichCompareBool(val2, maxval, Py_GT); > if (cmp < 0) > goto Fail_it_item_and_val; > else if (cmp > 0) { > Py_DECREF(maxval); > Py_DECREF(maxitem); > maxval = val2; > maxitem = item2; > } > else { > Py_DECREF(item2); > Py_DECREF(val2); > } > } > if (PyErr_Occurred()) > goto Fail_it; > > EarlyExit_short_sequence: > if (maxval == NULL) { > PyErr_Format(PyExc_ValueError, > "%s() arg is an empty sequence", name); > assert(maxitem == NULL); > } > else { > Py_DECREF(maxval); > Py_DECREF(minval); > } > Py_DECREF(it); > Py_XDECREF(keyfunc); > > if (maxitem != NULL) { > result = PyTuple_Pack(2, minitem, maxitem); > Py_DECREF(minitem); > Py_DECREF(maxitem); > } > else { > result = NULL; > } > > return result; > > Fail_it_item_and_val: > Py_DECREF(val); > Py_DECREF(val2); > Fail_it_item: > Py_DECREF(item); > Py_DECREF(item2); > Fail_it: > Py_XDECREF(minval); > Py_XDECREF(minitem); > Py_XDECREF(maxval); > Py_XDECREF(maxitem); > Py_DECREF(it); > Py_XDECREF(keyfunc); > return NULL; > } > > PyDoc_STRVAR(minmax_doc, > "minmax(iterable[, key=func]) -> value\n\ > minmax(a, b, c, ...[, key=func]) -> value\n\ > \n\ > With a single iterable argument, return its smallest and largest items.\n\ > With two or more arguments, return the smallest and largest arguments."); > > 2265a2455 > {"minmax", (PyCFunction)builtin_minmax, METH_VARARGS | METH_KEYWORDS, minmax_doc},