Advertisement
Guest User

Paul McGuire

a guest
Oct 10th, 2010
121
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Diff 4.67 KB | None | 0 0
  1. 1318a1319,1507
  2. > static PyObject *
  3. > builtin_minmax(PyObject *self, PyObject *args, PyObject *kwds)
  4. > {
  5. >   const char *name = "minmax";
  6. >   PyObject *v, *it, *item, *val, *item2, *val2, *minitem, *minval, *maxitem, *maxval, *keyfunc=NULL;
  7. >   PyObject *result = NULL;
  8. >   int seqlen, cmp;
  9. >
  10. >   if (PyTuple_Size(args) > 1)
  11. >       v = args;
  12. >   else if (!PyArg_UnpackTuple(args, (char *)name, 1, 1, &v))
  13. >       return NULL;
  14. >
  15. >   if (kwds != NULL && PyDict_Check(kwds) && PyDict_Size(kwds)) {
  16. >       keyfunc = PyDict_GetItemString(kwds, "key");
  17. >       if (PyDict_Size(kwds)!=1  ||  keyfunc == NULL) {
  18. >           PyErr_Format(PyExc_TypeError,
  19. >               "%s() got an unexpected keyword argument", name);
  20. >           return NULL;
  21. >       }
  22. >       Py_INCREF(keyfunc);
  23. >   }
  24. >
  25. >   it = PyObject_GetIter(v);
  26. >   if (it == NULL) {
  27. >       Py_XDECREF(keyfunc);
  28. >       return NULL;
  29. >   }
  30. >
  31. >   minitem = NULL; /* the results */
  32. >   maxitem = NULL;
  33. >   minval = NULL;  /* the values associated with the results */
  34. >   maxval = NULL;  
  35. >
  36. >   /* initialize min and max returns with the first item in the list */
  37. >   item = PyIter_Next(it);
  38. >   if (item == NULL)
  39. >   {
  40. >       //minitem = Py_None;
  41. >       //Py_INCREF(minitem);
  42. >       //maxitem = Py_None;
  43. >       //Py_INCREF(maxitem);
  44. >       goto EarlyExit_short_sequence;
  45. >   }
  46. >
  47. >   if (keyfunc != NULL) {
  48. >       val = PyObject_CallFunctionObjArgs(keyfunc, item, NULL);
  49. >       if (val == NULL)
  50. >           goto Fail_it_item;
  51. >   }
  52. >   /* no key function; the value is the item */
  53. >   else {
  54. >       val = item;
  55. >       // increment twice, as we will assign to both min and max return vals
  56. >       Py_INCREF(val);
  57. >       Py_INCREF(val);
  58. >   }
  59. >
  60. >   minitem = item;
  61. >   minval = val;
  62. >   maxitem = item; /* the result */
  63. >   maxval = val;  /* the value associated with the result */
  64. >
  65. >   seqlen = PySequence_Length(v);
  66. >  
  67. >   // if even length sequence, put iter back at 0, to safely read by pairs
  68. >   if (seqlen % 2 == 0) {
  69. >       it = PyObject_GetIter(v);
  70. >   }
  71. >
  72. >   // read by pairs
  73. >   while (( item = PyIter_Next(it) ) && (item2 = PyIter_Next(it))) {
  74. >
  75. >       /* get the value from the key function */
  76. >       if (keyfunc != NULL) {
  77. >           val  = PyObject_CallFunctionObjArgs(keyfunc, item, NULL);
  78. >           val2 = PyObject_CallFunctionObjArgs(keyfunc, item2, NULL);
  79. >           if (val == NULL || val2 == NULL)
  80. >               goto Fail_it_item;
  81. >       }
  82. >       /* no key function; the value is the item */
  83. >       else {
  84. >           val = item;
  85. >           Py_INCREF(val);
  86. >           val2 = item2;
  87. >           Py_INCREF(val2);
  88. >       }
  89. >
  90. >
  91. >       /*
  92. >         if a > b:
  93. >             a,b = b,a
  94. >       */
  95. >       cmp = PyObject_RichCompareBool(val, val2, Py_GT);
  96. >       if (cmp < 0)
  97. >           goto Fail_it_item_and_val;
  98. >       else if (cmp > 0) {
  99. >           PyObject* tmp;
  100. >           tmp = val;  val  = val2;  val2  = tmp;
  101. >           tmp = item; item = item2; item2 = tmp;
  102. >       }
  103. >
  104. >       /*
  105. >         if a < min_:
  106. >             min_ = a
  107. >       */
  108. >       cmp = PyObject_RichCompareBool(val, minval, Py_LT);
  109. >       if (cmp < 0)
  110. >           goto Fail_it_item_and_val;
  111. >       else if (cmp > 0) {
  112. >           Py_DECREF(minval);
  113. >           Py_DECREF(minitem);
  114. >           minval = val;
  115. >           minitem = item;
  116. >       }
  117. >       else {
  118. >           Py_DECREF(item);
  119. >           Py_DECREF(val);
  120. >       }
  121. >
  122. >       /*
  123. >         if b > max_:
  124. >             max_ = b
  125. >       */
  126. >       cmp = PyObject_RichCompareBool(val2, maxval, Py_GT);
  127. >       if (cmp < 0)
  128. >           goto Fail_it_item_and_val;
  129. >       else if (cmp > 0) {
  130. >           Py_DECREF(maxval);
  131. >           Py_DECREF(maxitem);
  132. >           maxval = val2;
  133. >           maxitem = item2;
  134. >       }
  135. >       else {
  136. >           Py_DECREF(item2);
  137. >           Py_DECREF(val2);
  138. >       }
  139. >   }
  140. >   if (PyErr_Occurred())
  141. >       goto Fail_it;
  142. >
  143. > EarlyExit_short_sequence:
  144. >   if (maxval == NULL) {
  145. >       PyErr_Format(PyExc_ValueError,
  146. >                "%s() arg is an empty sequence", name);
  147. >       assert(maxitem == NULL);
  148. >   }
  149. >   else {
  150. >       Py_DECREF(maxval);
  151. >       Py_DECREF(minval);
  152. >   }
  153. >   Py_DECREF(it);
  154. >   Py_XDECREF(keyfunc);
  155. >
  156. >   if (maxitem != NULL) {
  157. >       result = PyTuple_Pack(2, minitem, maxitem);
  158. >       Py_DECREF(minitem);
  159. >       Py_DECREF(maxitem);
  160. >   }
  161. >   else {
  162. >       result = NULL;
  163. >   }
  164. >
  165. >   return result;
  166. >
  167. > Fail_it_item_and_val:
  168. >   Py_DECREF(val);
  169. >   Py_DECREF(val2);
  170. > Fail_it_item:
  171. >   Py_DECREF(item);
  172. >   Py_DECREF(item2);
  173. > Fail_it:
  174. >   Py_XDECREF(minval);
  175. >   Py_XDECREF(minitem);
  176. >   Py_XDECREF(maxval);
  177. >   Py_XDECREF(maxitem);
  178. >   Py_DECREF(it);
  179. >   Py_XDECREF(keyfunc);
  180. >   return NULL;
  181. > }
  182. >
  183. > PyDoc_STRVAR(minmax_doc,
  184. > "minmax(iterable[, key=func]) -> value\n\
  185. > minmax(a, b, c, ...[, key=func]) -> value\n\
  186. > \n\
  187. > With a single iterable argument, return its smallest and largest items.\n\
  188. > With two or more arguments, return the smallest and largest arguments.");
  189. >
  190. >
  191. 2265a2455
  192. >   {"minmax",      (PyCFunction)builtin_minmax,        METH_VARARGS | METH_KEYWORDS, minmax_doc},
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement