| 
									
										
										
										
											1993-10-26 17:58:25 +00:00
										 |  |  | /* Range object implementation */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1997-05-02 03:12:38 +00:00
										 |  |  | #include "Python.h"
 | 
					
						
							| 
									
										
										
										
											2011-11-05 15:17:52 -04:00
										 |  |  | #include "structmember.h"
 | 
					
						
							| 
									
										
										
										
											2001-07-09 12:30:54 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-05-07 22:24:25 +00:00
										 |  |  | /* Support objects whose length is > PY_SSIZE_T_MAX.
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-17 08:32:47 +03:00
										 |  |  |    This could be sped up for small PyLongs if they fit in a Py_ssize_t. | 
					
						
							| 
									
										
										
										
											2016-09-06 10:46:49 -07:00
										 |  |  |    This only matters on Win64.  Though we could use long long which | 
					
						
							| 
									
										
										
										
											2007-05-07 22:24:25 +00:00
										 |  |  |    would presumably help perf. | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1993-10-26 17:58:25 +00:00
										 |  |  | typedef struct { | 
					
						
							| 
									
										
										
										
											2007-05-07 22:24:25 +00:00
										 |  |  |     PyObject_HEAD | 
					
						
							|  |  |  |     PyObject *start; | 
					
						
							|  |  |  |     PyObject *stop; | 
					
						
							|  |  |  |     PyObject *step; | 
					
						
							| 
									
										
										
										
											2010-12-03 14:26:13 +00:00
										 |  |  |     PyObject *length; | 
					
						
							| 
									
										
										
										
											1993-10-26 17:58:25 +00:00
										 |  |  | } rangeobject; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-05-07 22:24:25 +00:00
										 |  |  | /* Helper function for validating step.  Always returns a new reference or
 | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |    NULL on error. | 
					
						
							| 
									
										
										
										
											2007-05-07 22:24:25 +00:00
										 |  |  | */ | 
					
						
							|  |  |  | static PyObject * | 
					
						
							| 
									
										
										
										
											2010-11-20 23:05:39 +00:00
										 |  |  | validate_step(PyObject *step) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2007-05-07 22:24:25 +00:00
										 |  |  |     /* No step specified, use a step of 1. */ | 
					
						
							|  |  |  |     if (!step) | 
					
						
							| 
									
										
										
										
											2007-12-02 14:31:20 +00:00
										 |  |  |         return PyLong_FromLong(1); | 
					
						
							| 
									
										
										
										
											2007-05-07 22:24:25 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     step = PyNumber_Index(step); | 
					
						
							| 
									
										
										
										
											2016-06-18 09:51:55 +03:00
										 |  |  |     if (step && _PyLong_Sign(step) == 0) { | 
					
						
							|  |  |  |         PyErr_SetString(PyExc_ValueError, | 
					
						
							|  |  |  |                         "range() arg 3 must not be zero"); | 
					
						
							|  |  |  |         Py_CLEAR(step); | 
					
						
							| 
									
										
										
										
											2007-05-07 22:24:25 +00:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return step; | 
					
						
							| 
									
										
										
										
											2002-06-05 23:12:45 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-12-03 14:26:13 +00:00
										 |  |  | static PyObject * | 
					
						
							|  |  |  | compute_range_length(PyObject *start, PyObject *stop, PyObject *step); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static rangeobject * | 
					
						
							|  |  |  | make_range_object(PyTypeObject *type, PyObject *start, | 
					
						
							|  |  |  |                   PyObject *stop, PyObject *step) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     rangeobject *obj = NULL; | 
					
						
							|  |  |  |     PyObject *length; | 
					
						
							|  |  |  |     length = compute_range_length(start, stop, step); | 
					
						
							|  |  |  |     if (length == NULL) { | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     obj = PyObject_New(rangeobject, type); | 
					
						
							|  |  |  |     if (obj == NULL) { | 
					
						
							|  |  |  |         Py_DECREF(length); | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     obj->start = start; | 
					
						
							|  |  |  |     obj->stop = stop; | 
					
						
							|  |  |  |     obj->step = step; | 
					
						
							|  |  |  |     obj->length = length; | 
					
						
							|  |  |  |     return obj; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-05-07 22:24:25 +00:00
										 |  |  | /* XXX(nnorwitz): should we error check if the user passes any empty ranges?
 | 
					
						
							|  |  |  |    range(-10) | 
					
						
							|  |  |  |    range(0, -5) | 
					
						
							|  |  |  |    range(0, 5, -1) | 
					
						
							|  |  |  | */ | 
					
						
							| 
									
										
										
										
											2002-06-05 23:12:45 +00:00
										 |  |  | static PyObject * | 
					
						
							| 
									
										
										
										
											2010-11-20 23:05:39 +00:00
										 |  |  | range_new(PyTypeObject *type, PyObject *args, PyObject *kw) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2010-12-03 14:26:13 +00:00
										 |  |  |     rangeobject *obj; | 
					
						
							| 
									
										
										
										
											2007-05-07 22:24:25 +00:00
										 |  |  |     PyObject *start = NULL, *stop = NULL, *step = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-06-08 14:41:19 +03:00
										 |  |  |     if (!_PyArg_NoKeywords("range", kw)) | 
					
						
							| 
									
										
										
										
											2007-05-07 22:24:25 +00:00
										 |  |  |         return NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (PyTuple_Size(args) <= 1) { | 
					
						
							|  |  |  |         if (!PyArg_UnpackTuple(args, "range", 1, 1, &stop)) | 
					
						
							| 
									
										
										
										
											2009-06-12 18:40:16 +00:00
										 |  |  |             return NULL; | 
					
						
							| 
									
										
										
										
											2007-05-07 22:24:25 +00:00
										 |  |  |         stop = PyNumber_Index(stop); | 
					
						
							|  |  |  |         if (!stop) | 
					
						
							| 
									
										
										
										
											2009-06-12 18:40:16 +00:00
										 |  |  |             return NULL; | 
					
						
							| 
									
										
										
										
											2017-03-30 09:09:41 +03:00
										 |  |  |         Py_INCREF(_PyLong_Zero); | 
					
						
							|  |  |  |         start = _PyLong_Zero; | 
					
						
							|  |  |  |         Py_INCREF(_PyLong_One); | 
					
						
							|  |  |  |         step = _PyLong_One; | 
					
						
							| 
									
										
										
										
											2007-05-07 22:24:25 +00:00
										 |  |  |     } | 
					
						
							|  |  |  |     else { | 
					
						
							|  |  |  |         if (!PyArg_UnpackTuple(args, "range", 2, 3, | 
					
						
							|  |  |  |                                &start, &stop, &step)) | 
					
						
							| 
									
										
										
										
											2009-06-12 18:40:16 +00:00
										 |  |  |             return NULL; | 
					
						
							| 
									
										
										
										
											2007-05-07 22:24:25 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |         /* Convert borrowed refs to owned refs */ | 
					
						
							|  |  |  |         start = PyNumber_Index(start); | 
					
						
							| 
									
										
										
										
											2009-06-12 18:40:16 +00:00
										 |  |  |         if (!start) | 
					
						
							|  |  |  |             return NULL; | 
					
						
							| 
									
										
										
										
											2007-05-07 22:24:25 +00:00
										 |  |  |         stop = PyNumber_Index(stop); | 
					
						
							| 
									
										
										
										
											2009-06-12 18:40:16 +00:00
										 |  |  |         if (!stop) { | 
					
						
							|  |  |  |             Py_DECREF(start); | 
					
						
							|  |  |  |             return NULL; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         step = validate_step(step);    /* Caution, this can clear exceptions */ | 
					
						
							|  |  |  |         if (!step) { | 
					
						
							|  |  |  |             Py_DECREF(start); | 
					
						
							|  |  |  |             Py_DECREF(stop); | 
					
						
							|  |  |  |             return NULL; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2007-05-07 22:24:25 +00:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-12-03 14:26:13 +00:00
										 |  |  |     obj = make_range_object(type, start, stop, step); | 
					
						
							|  |  |  |     if (obj != NULL) | 
					
						
							|  |  |  |         return (PyObject *) obj; | 
					
						
							| 
									
										
										
										
											2007-05-07 22:24:25 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-12-03 14:26:13 +00:00
										 |  |  |     /* Failed to create object, release attributes */ | 
					
						
							| 
									
										
										
										
											2016-06-18 09:44:03 +03:00
										 |  |  |     Py_DECREF(start); | 
					
						
							|  |  |  |     Py_DECREF(stop); | 
					
						
							|  |  |  |     Py_DECREF(step); | 
					
						
							| 
									
										
										
										
											2007-05-07 22:24:25 +00:00
										 |  |  |     return NULL; | 
					
						
							| 
									
										
										
										
											2002-06-05 23:12:45 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-06-13 20:33:02 +00:00
										 |  |  | PyDoc_STRVAR(range_doc, | 
					
						
							| 
									
										
										
										
											2012-10-07 14:48:36 -07:00
										 |  |  | "range(stop) -> range object\n\
 | 
					
						
							|  |  |  | range(start, stop[, step]) -> range object\n\ | 
					
						
							| 
									
										
										
										
											2002-06-05 23:12:45 +00:00
										 |  |  | \n\ | 
					
						
							| 
									
										
										
										
											2015-04-22 09:16:07 -04:00
										 |  |  | Return an object that produces a sequence of integers from start (inclusive)\n\ | 
					
						
							|  |  |  | to stop (exclusive) by step.  range(i, j) produces i, i+1, i+2, ..., j-1.\n\ | 
					
						
							|  |  |  | start defaults to 0, and stop is omitted!  range(4) produces 0, 1, 2, 3.\n\ | 
					
						
							|  |  |  | These are exactly the valid indices for a list of 4 elements.\n\ | 
					
						
							|  |  |  | When step is given, it specifies the increment (or decrement)."); | 
					
						
							| 
									
										
										
										
											2002-06-05 23:12:45 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-05-07 22:24:25 +00:00
										 |  |  | static void | 
					
						
							| 
									
										
										
										
											2010-11-20 23:05:39 +00:00
										 |  |  | range_dealloc(rangeobject *r) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2007-05-07 22:24:25 +00:00
										 |  |  |     Py_DECREF(r->start); | 
					
						
							|  |  |  |     Py_DECREF(r->stop); | 
					
						
							|  |  |  |     Py_DECREF(r->step); | 
					
						
							| 
									
										
										
										
											2010-12-03 14:26:13 +00:00
										 |  |  |     Py_DECREF(r->length); | 
					
						
							| 
									
										
										
										
											2007-11-15 20:52:21 +00:00
										 |  |  |     PyObject_Del(r); | 
					
						
							| 
									
										
										
										
											2007-05-07 22:24:25 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-28 22:08:40 +00:00
										 |  |  | /* Return number of items in range (lo, hi, step) as a PyLong object,
 | 
					
						
							|  |  |  |  * when arguments are PyLong objects.  Arguments MUST return 1 with | 
					
						
							|  |  |  |  * PyLong_Check().  Return NULL when there is an error. | 
					
						
							| 
									
										
										
										
											2007-05-07 22:24:25 +00:00
										 |  |  |  */ | 
					
						
							|  |  |  | static PyObject* | 
					
						
							| 
									
										
										
										
											2010-12-03 14:26:13 +00:00
										 |  |  | compute_range_length(PyObject *start, PyObject *stop, PyObject *step) | 
					
						
							| 
									
										
										
										
											2010-11-20 23:05:39 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2007-05-07 22:24:25 +00:00
										 |  |  |     /* -------------------------------------------------------------
 | 
					
						
							|  |  |  |     Algorithm is equal to that of get_len_of_range(), but it operates | 
					
						
							| 
									
										
										
										
											2009-06-24 21:14:38 +00:00
										 |  |  |     on PyObjects (which are assumed to be PyLong objects). | 
					
						
							| 
									
										
										
										
											2007-05-07 22:24:25 +00:00
										 |  |  |     ---------------------------------------------------------------*/ | 
					
						
							| 
									
										
										
										
											2009-02-01 10:28:51 +00:00
										 |  |  |     int cmp_result; | 
					
						
							| 
									
										
										
										
											2007-05-07 22:24:25 +00:00
										 |  |  |     PyObject *lo, *hi; | 
					
						
							|  |  |  |     PyObject *diff = NULL; | 
					
						
							|  |  |  |     PyObject *tmp1 = NULL, *tmp2 = NULL, *result; | 
					
						
							|  |  |  |                 /* holds sub-expression evaluations */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-30 09:09:41 +03:00
										 |  |  |     cmp_result = PyObject_RichCompareBool(step, _PyLong_Zero, Py_GT); | 
					
						
							| 
									
										
										
										
											2009-02-01 10:28:51 +00:00
										 |  |  |     if (cmp_result == -1) | 
					
						
							| 
									
										
										
										
											2007-05-07 22:24:25 +00:00
										 |  |  |         return NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-01 10:28:51 +00:00
										 |  |  |     if (cmp_result == 1) { | 
					
						
							| 
									
										
										
										
											2010-12-03 14:26:13 +00:00
										 |  |  |         lo = start; | 
					
						
							|  |  |  |         hi = stop; | 
					
						
							| 
									
										
										
										
											2007-05-07 22:24:25 +00:00
										 |  |  |         Py_INCREF(step); | 
					
						
							|  |  |  |     } else { | 
					
						
							| 
									
										
										
										
											2010-12-03 14:26:13 +00:00
										 |  |  |         lo = stop; | 
					
						
							|  |  |  |         hi = start; | 
					
						
							|  |  |  |         step = PyNumber_Negative(step); | 
					
						
							| 
									
										
										
										
											2007-05-07 22:24:25 +00:00
										 |  |  |         if (!step) | 
					
						
							|  |  |  |             return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* if (lo >= hi), return length of 0. */ | 
					
						
							| 
									
										
										
										
											2015-05-30 17:45:22 +03:00
										 |  |  |     cmp_result = PyObject_RichCompareBool(lo, hi, Py_GE); | 
					
						
							|  |  |  |     if (cmp_result != 0) { | 
					
						
							| 
									
										
										
										
											2016-06-18 09:44:03 +03:00
										 |  |  |         Py_DECREF(step); | 
					
						
							| 
									
										
										
										
											2015-05-30 17:45:22 +03:00
										 |  |  |         if (cmp_result < 0) | 
					
						
							|  |  |  |             return NULL; | 
					
						
							| 
									
										
										
										
											2007-05-07 22:24:25 +00:00
										 |  |  |         return PyLong_FromLong(0); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if ((tmp1 = PyNumber_Subtract(hi, lo)) == NULL) | 
					
						
							|  |  |  |         goto Fail; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-30 09:09:41 +03:00
										 |  |  |     if ((diff = PyNumber_Subtract(tmp1, _PyLong_One)) == NULL) | 
					
						
							| 
									
										
										
										
											2007-05-07 22:24:25 +00:00
										 |  |  |         goto Fail; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if ((tmp2 = PyNumber_FloorDivide(diff, step)) == NULL) | 
					
						
							|  |  |  |         goto Fail; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-30 09:09:41 +03:00
										 |  |  |     if ((result = PyNumber_Add(tmp2, _PyLong_One)) == NULL) | 
					
						
							| 
									
										
										
										
											2007-05-07 22:24:25 +00:00
										 |  |  |         goto Fail; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Py_DECREF(tmp2); | 
					
						
							|  |  |  |     Py_DECREF(diff); | 
					
						
							|  |  |  |     Py_DECREF(step); | 
					
						
							|  |  |  |     Py_DECREF(tmp1); | 
					
						
							|  |  |  |     return result; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   Fail: | 
					
						
							| 
									
										
										
										
											2016-06-18 09:44:03 +03:00
										 |  |  |     Py_DECREF(step); | 
					
						
							| 
									
										
										
										
											2007-05-07 22:24:25 +00:00
										 |  |  |     Py_XDECREF(tmp2); | 
					
						
							|  |  |  |     Py_XDECREF(diff); | 
					
						
							|  |  |  |     Py_XDECREF(tmp1); | 
					
						
							|  |  |  |     return NULL; | 
					
						
							| 
									
										
										
										
											1993-10-26 17:58:25 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-02-15 17:27:45 +00:00
										 |  |  | static Py_ssize_t | 
					
						
							| 
									
										
										
										
											2010-11-20 23:05:39 +00:00
										 |  |  | range_length(rangeobject *r) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2010-12-03 14:26:13 +00:00
										 |  |  |     return PyLong_AsSsize_t(r->length); | 
					
						
							| 
									
										
										
										
											2007-05-07 22:24:25 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							| 
									
										
										
										
											2011-01-12 03:15:52 +00:00
										 |  |  | compute_item(rangeobject *r, PyObject *i) | 
					
						
							| 
									
										
										
										
											2010-11-20 23:05:39 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2011-01-12 03:15:52 +00:00
										 |  |  |     PyObject *incr, *result; | 
					
						
							|  |  |  |     /* PyLong equivalent to:
 | 
					
						
							|  |  |  |      *    return r->start + (i * r->step) | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     incr = PyNumber_Multiply(i, r->step); | 
					
						
							| 
									
										
										
										
											2007-05-07 22:24:25 +00:00
										 |  |  |     if (!incr) | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     result = PyNumber_Add(r->start, incr); | 
					
						
							|  |  |  |     Py_DECREF(incr); | 
					
						
							|  |  |  |     return result; | 
					
						
							| 
									
										
										
										
											1993-12-21 22:50:31 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1997-05-02 03:12:38 +00:00
										 |  |  | static PyObject * | 
					
						
							| 
									
										
										
										
											2011-01-12 03:15:52 +00:00
										 |  |  | compute_range_item(rangeobject *r, PyObject *arg) | 
					
						
							| 
									
										
										
										
											2010-11-20 23:05:39 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2011-01-12 03:15:52 +00:00
										 |  |  |     int cmp_result; | 
					
						
							|  |  |  |     PyObject *i, *result; | 
					
						
							| 
									
										
										
										
											2007-05-07 22:24:25 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-01-12 03:15:52 +00:00
										 |  |  |     /* PyLong equivalent to:
 | 
					
						
							|  |  |  |      *   if (arg < 0) { | 
					
						
							|  |  |  |      *     i = r->length + arg | 
					
						
							|  |  |  |      *   } else { | 
					
						
							|  |  |  |      *     i = arg | 
					
						
							|  |  |  |      *   } | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2017-03-30 09:09:41 +03:00
										 |  |  |     cmp_result = PyObject_RichCompareBool(arg, _PyLong_Zero, Py_LT); | 
					
						
							| 
									
										
										
										
											2011-01-12 03:15:52 +00:00
										 |  |  |     if (cmp_result == -1) { | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (cmp_result == 1) { | 
					
						
							| 
									
										
										
										
											2017-03-30 09:09:41 +03:00
										 |  |  |         i = PyNumber_Add(r->length, arg); | 
					
						
							|  |  |  |         if (!i) { | 
					
						
							|  |  |  |           return NULL; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2011-01-12 03:15:52 +00:00
										 |  |  |     } else { | 
					
						
							| 
									
										
										
										
											2017-03-30 09:09:41 +03:00
										 |  |  |         i = arg; | 
					
						
							|  |  |  |         Py_INCREF(i); | 
					
						
							| 
									
										
										
										
											2011-01-12 03:15:52 +00:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2001-07-09 12:30:54 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-01-12 03:15:52 +00:00
										 |  |  |     /* PyLong equivalent to:
 | 
					
						
							|  |  |  |      *   if (i < 0 || i >= r->length) { | 
					
						
							|  |  |  |      *     <report index out of bounds> | 
					
						
							|  |  |  |      *   } | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2017-03-30 09:09:41 +03:00
										 |  |  |     cmp_result = PyObject_RichCompareBool(i, _PyLong_Zero, Py_LT); | 
					
						
							| 
									
										
										
										
											2011-01-12 03:15:52 +00:00
										 |  |  |     if (cmp_result == 0) { | 
					
						
							|  |  |  |         cmp_result = PyObject_RichCompareBool(i, r->length, Py_GE); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (cmp_result == -1) { | 
					
						
							|  |  |  |        Py_DECREF(i); | 
					
						
							|  |  |  |        return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (cmp_result == 1) { | 
					
						
							|  |  |  |         Py_DECREF(i); | 
					
						
							|  |  |  |         PyErr_SetString(PyExc_IndexError, | 
					
						
							|  |  |  |                         "range object index out of range"); | 
					
						
							| 
									
										
										
										
											2010-12-03 14:26:13 +00:00
										 |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2011-01-12 03:15:52 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     result = compute_item(r, i); | 
					
						
							|  |  |  |     Py_DECREF(i); | 
					
						
							|  |  |  |     return result; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							|  |  |  | range_item(rangeobject *r, Py_ssize_t i) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2012-05-16 14:37:54 +02:00
										 |  |  |     PyObject *res, *arg = PyLong_FromSsize_t(i); | 
					
						
							| 
									
										
										
										
											2011-01-12 03:15:52 +00:00
										 |  |  |     if (!arg) { | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2011-01-13 04:22:54 +00:00
										 |  |  |     res = compute_range_item(r, arg); | 
					
						
							|  |  |  |     Py_DECREF(arg); | 
					
						
							|  |  |  |     return res; | 
					
						
							| 
									
										
										
										
											2011-01-12 03:15:52 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							|  |  |  | compute_slice(rangeobject *r, PyObject *_slice) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     PySliceObject *slice = (PySliceObject *) _slice; | 
					
						
							|  |  |  |     rangeobject *result; | 
					
						
							|  |  |  |     PyObject *start = NULL, *stop = NULL, *step = NULL; | 
					
						
							|  |  |  |     PyObject *substart = NULL, *substop = NULL, *substep = NULL; | 
					
						
							| 
									
										
										
										
											2012-11-17 19:18:10 +00:00
										 |  |  |     int error; | 
					
						
							| 
									
										
										
										
											2011-01-12 03:15:52 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-11-17 19:18:10 +00:00
										 |  |  |     error = _PySlice_GetLongIndices(slice, r->length, &start, &stop, &step); | 
					
						
							|  |  |  |     if (error == -1) | 
					
						
							|  |  |  |         return NULL; | 
					
						
							| 
									
										
										
										
											2011-01-12 03:15:52 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     substep = PyNumber_Multiply(r->step, step); | 
					
						
							|  |  |  |     if (substep == NULL) goto fail; | 
					
						
							|  |  |  |     Py_CLEAR(step); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     substart = compute_item(r, start); | 
					
						
							|  |  |  |     if (substart == NULL) goto fail; | 
					
						
							|  |  |  |     Py_CLEAR(start); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-11-17 19:18:10 +00:00
										 |  |  |     substop = compute_item(r, stop); | 
					
						
							|  |  |  |     if (substop == NULL) goto fail; | 
					
						
							| 
									
										
										
										
											2011-01-12 03:15:52 +00:00
										 |  |  |     Py_CLEAR(stop); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     result = make_range_object(Py_TYPE(r), substart, substop, substep); | 
					
						
							|  |  |  |     if (result != NULL) { | 
					
						
							|  |  |  |         return (PyObject *) result; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | fail: | 
					
						
							|  |  |  |     Py_XDECREF(start); | 
					
						
							|  |  |  |     Py_XDECREF(stop); | 
					
						
							|  |  |  |     Py_XDECREF(step); | 
					
						
							|  |  |  |     Py_XDECREF(substart); | 
					
						
							|  |  |  |     Py_XDECREF(substop); | 
					
						
							|  |  |  |     Py_XDECREF(substep); | 
					
						
							|  |  |  |     return NULL; | 
					
						
							| 
									
										
										
										
											2008-06-10 04:03:04 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-13 21:16:29 +00:00
										 |  |  | /* Assumes (PyLong_CheckExact(ob) || PyBool_Check(ob)) */ | 
					
						
							|  |  |  | static int | 
					
						
							| 
									
										
										
										
											2010-11-20 23:05:39 +00:00
										 |  |  | range_contains_long(rangeobject *r, PyObject *ob) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2010-09-13 21:16:29 +00:00
										 |  |  |     int cmp1, cmp2, cmp3; | 
					
						
							|  |  |  |     PyObject *tmp1 = NULL; | 
					
						
							|  |  |  |     PyObject *tmp2 = NULL; | 
					
						
							|  |  |  |     int result = -1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* Check if the value can possibly be in the range. */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-30 09:09:41 +03:00
										 |  |  |     cmp1 = PyObject_RichCompareBool(r->step, _PyLong_Zero, Py_GT); | 
					
						
							| 
									
										
										
										
											2010-09-13 21:16:29 +00:00
										 |  |  |     if (cmp1 == -1) | 
					
						
							|  |  |  |         goto end; | 
					
						
							|  |  |  |     if (cmp1 == 1) { /* positive steps: start <= ob < stop */ | 
					
						
							|  |  |  |         cmp2 = PyObject_RichCompareBool(r->start, ob, Py_LE); | 
					
						
							|  |  |  |         cmp3 = PyObject_RichCompareBool(ob, r->stop, Py_LT); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else { /* negative steps: stop < ob <= start */ | 
					
						
							|  |  |  |         cmp2 = PyObject_RichCompareBool(ob, r->start, Py_LE); | 
					
						
							|  |  |  |         cmp3 = PyObject_RichCompareBool(r->stop, ob, Py_LT); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (cmp2 == -1 || cmp3 == -1) /* TypeError */ | 
					
						
							|  |  |  |         goto end; | 
					
						
							|  |  |  |     if (cmp2 == 0 || cmp3 == 0) { /* ob outside of range */ | 
					
						
							|  |  |  |         result = 0; | 
					
						
							|  |  |  |         goto end; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* Check that the stride does not invalidate ob's membership. */ | 
					
						
							|  |  |  |     tmp1 = PyNumber_Subtract(ob, r->start); | 
					
						
							|  |  |  |     if (tmp1 == NULL) | 
					
						
							|  |  |  |         goto end; | 
					
						
							|  |  |  |     tmp2 = PyNumber_Remainder(tmp1, r->step); | 
					
						
							|  |  |  |     if (tmp2 == NULL) | 
					
						
							|  |  |  |         goto end; | 
					
						
							| 
									
										
										
										
											2016-09-12 07:47:04 +03:00
										 |  |  |     /* result = ((int(ob) - start) % step) == 0 */ | 
					
						
							| 
									
										
										
										
											2017-03-30 09:09:41 +03:00
										 |  |  |     result = PyObject_RichCompareBool(tmp2, _PyLong_Zero, Py_EQ); | 
					
						
							| 
									
										
										
										
											2010-09-13 21:16:29 +00:00
										 |  |  |   end: | 
					
						
							|  |  |  |     Py_XDECREF(tmp1); | 
					
						
							|  |  |  |     Py_XDECREF(tmp2); | 
					
						
							|  |  |  |     return result; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-09-22 21:47:24 +00:00
										 |  |  | static int | 
					
						
							| 
									
										
										
										
											2010-11-20 23:05:39 +00:00
										 |  |  | range_contains(rangeobject *r, PyObject *ob) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2010-09-13 21:16:29 +00:00
										 |  |  |     if (PyLong_CheckExact(ob) || PyBool_Check(ob)) | 
					
						
							|  |  |  |         return range_contains_long(r, ob); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return (int)_PySequence_IterSearch((PyObject*)r, ob, | 
					
						
							|  |  |  |                                        PY_ITERSEARCH_CONTAINS); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-10-23 19:53:01 +01:00
										 |  |  | /* Compare two range objects.  Return 1 for equal, 0 for not equal
 | 
					
						
							|  |  |  |    and -1 on error.  The algorithm is roughly the C equivalent of | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    if r0 is r1: | 
					
						
							|  |  |  |        return True | 
					
						
							|  |  |  |    if len(r0) != len(r1): | 
					
						
							|  |  |  |        return False | 
					
						
							|  |  |  |    if not len(r0): | 
					
						
							|  |  |  |        return True | 
					
						
							|  |  |  |    if r0.start != r1.start: | 
					
						
							|  |  |  |        return False | 
					
						
							|  |  |  |    if len(r0) == 1: | 
					
						
							|  |  |  |        return True | 
					
						
							|  |  |  |    return r0.step == r1.step | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | range_equals(rangeobject *r0, rangeobject *r1) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     int cmp_result; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (r0 == r1) | 
					
						
							|  |  |  |         return 1; | 
					
						
							|  |  |  |     cmp_result = PyObject_RichCompareBool(r0->length, r1->length, Py_EQ); | 
					
						
							|  |  |  |     /* Return False or error to the caller. */ | 
					
						
							|  |  |  |     if (cmp_result != 1) | 
					
						
							|  |  |  |         return cmp_result; | 
					
						
							|  |  |  |     cmp_result = PyObject_Not(r0->length); | 
					
						
							|  |  |  |     /* Return True or error to the caller. */ | 
					
						
							|  |  |  |     if (cmp_result != 0) | 
					
						
							|  |  |  |         return cmp_result; | 
					
						
							|  |  |  |     cmp_result = PyObject_RichCompareBool(r0->start, r1->start, Py_EQ); | 
					
						
							|  |  |  |     /* Return False or error to the caller. */ | 
					
						
							|  |  |  |     if (cmp_result != 1) | 
					
						
							|  |  |  |         return cmp_result; | 
					
						
							| 
									
										
										
										
											2017-03-30 09:09:41 +03:00
										 |  |  |     cmp_result = PyObject_RichCompareBool(r0->length, _PyLong_One, Py_EQ); | 
					
						
							| 
									
										
										
										
											2011-10-23 19:53:01 +01:00
										 |  |  |     /* Return True or error to the caller. */ | 
					
						
							|  |  |  |     if (cmp_result != 0) | 
					
						
							|  |  |  |         return cmp_result; | 
					
						
							|  |  |  |     return PyObject_RichCompareBool(r0->step, r1->step, Py_EQ); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							|  |  |  | range_richcompare(PyObject *self, PyObject *other, int op) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     int result; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (!PyRange_Check(other)) | 
					
						
							|  |  |  |         Py_RETURN_NOTIMPLEMENTED; | 
					
						
							|  |  |  |     switch (op) { | 
					
						
							|  |  |  |     case Py_NE: | 
					
						
							|  |  |  |     case Py_EQ: | 
					
						
							|  |  |  |         result = range_equals((rangeobject*)self, (rangeobject*)other); | 
					
						
							|  |  |  |         if (result == -1) | 
					
						
							|  |  |  |             return NULL; | 
					
						
							|  |  |  |         if (op == Py_NE) | 
					
						
							|  |  |  |             result = !result; | 
					
						
							|  |  |  |         if (result) | 
					
						
							|  |  |  |             Py_RETURN_TRUE; | 
					
						
							|  |  |  |         else | 
					
						
							|  |  |  |             Py_RETURN_FALSE; | 
					
						
							|  |  |  |     case Py_LE: | 
					
						
							|  |  |  |     case Py_GE: | 
					
						
							|  |  |  |     case Py_LT: | 
					
						
							|  |  |  |     case Py_GT: | 
					
						
							|  |  |  |         Py_RETURN_NOTIMPLEMENTED; | 
					
						
							|  |  |  |     default: | 
					
						
							|  |  |  |         PyErr_BadArgument(); | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Hash function for range objects.  Rough C equivalent of
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    if not len(r): | 
					
						
							|  |  |  |        return hash((len(r), None, None)) | 
					
						
							|  |  |  |    if len(r) == 1: | 
					
						
							|  |  |  |        return hash((len(r), r.start, None)) | 
					
						
							|  |  |  |    return hash((len(r), r.start, r.step)) | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | static Py_hash_t | 
					
						
							|  |  |  | range_hash(rangeobject *r) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     PyObject *t; | 
					
						
							|  |  |  |     Py_hash_t result = -1; | 
					
						
							|  |  |  |     int cmp_result; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     t = PyTuple_New(3); | 
					
						
							|  |  |  |     if (!t) | 
					
						
							|  |  |  |         return -1; | 
					
						
							|  |  |  |     Py_INCREF(r->length); | 
					
						
							|  |  |  |     PyTuple_SET_ITEM(t, 0, r->length); | 
					
						
							|  |  |  |     cmp_result = PyObject_Not(r->length); | 
					
						
							|  |  |  |     if (cmp_result == -1) | 
					
						
							|  |  |  |         goto end; | 
					
						
							|  |  |  |     if (cmp_result == 1) { | 
					
						
							|  |  |  |         Py_INCREF(Py_None); | 
					
						
							|  |  |  |         Py_INCREF(Py_None); | 
					
						
							|  |  |  |         PyTuple_SET_ITEM(t, 1, Py_None); | 
					
						
							|  |  |  |         PyTuple_SET_ITEM(t, 2, Py_None); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else { | 
					
						
							|  |  |  |         Py_INCREF(r->start); | 
					
						
							|  |  |  |         PyTuple_SET_ITEM(t, 1, r->start); | 
					
						
							| 
									
										
										
										
											2017-03-30 09:09:41 +03:00
										 |  |  |         cmp_result = PyObject_RichCompareBool(r->length, _PyLong_One, Py_EQ); | 
					
						
							| 
									
										
										
										
											2011-10-23 19:53:01 +01:00
										 |  |  |         if (cmp_result == -1) | 
					
						
							|  |  |  |             goto end; | 
					
						
							|  |  |  |         if (cmp_result == 1) { | 
					
						
							|  |  |  |             Py_INCREF(Py_None); | 
					
						
							|  |  |  |             PyTuple_SET_ITEM(t, 2, Py_None); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         else { | 
					
						
							|  |  |  |             Py_INCREF(r->step); | 
					
						
							|  |  |  |             PyTuple_SET_ITEM(t, 2, r->step); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     result = PyObject_Hash(t); | 
					
						
							|  |  |  |   end: | 
					
						
							|  |  |  |     Py_DECREF(t); | 
					
						
							|  |  |  |     return result; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-13 21:16:29 +00:00
										 |  |  | static PyObject * | 
					
						
							| 
									
										
										
										
											2010-11-20 23:05:39 +00:00
										 |  |  | range_count(rangeobject *r, PyObject *ob) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2009-09-24 20:04:23 +00:00
										 |  |  |     if (PyLong_CheckExact(ob) || PyBool_Check(ob)) { | 
					
						
							| 
									
										
										
										
											2010-11-20 22:40:10 +00:00
										 |  |  |         int result = range_contains_long(r, ob); | 
					
						
							|  |  |  |         if (result == -1) | 
					
						
							|  |  |  |             return NULL; | 
					
						
							| 
									
										
										
										
											2017-03-30 09:09:41 +03:00
										 |  |  |         return PyLong_FromLong(result); | 
					
						
							| 
									
										
										
										
											2010-09-13 21:16:29 +00:00
										 |  |  |     } else { | 
					
						
							|  |  |  |         Py_ssize_t count; | 
					
						
							|  |  |  |         count = _PySequence_IterSearch((PyObject*)r, ob, PY_ITERSEARCH_COUNT); | 
					
						
							|  |  |  |         if (count == -1) | 
					
						
							|  |  |  |             return NULL; | 
					
						
							|  |  |  |         return PyLong_FromSsize_t(count); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2009-09-22 21:47:24 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-13 21:16:29 +00:00
										 |  |  | static PyObject * | 
					
						
							| 
									
										
										
										
											2010-11-20 23:05:39 +00:00
										 |  |  | range_index(rangeobject *r, PyObject *ob) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2010-09-13 21:16:29 +00:00
										 |  |  |     int contains; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (!PyLong_CheckExact(ob) && !PyBool_Check(ob)) { | 
					
						
							|  |  |  |         Py_ssize_t index; | 
					
						
							|  |  |  |         index = _PySequence_IterSearch((PyObject*)r, ob, PY_ITERSEARCH_INDEX); | 
					
						
							|  |  |  |         if (index == -1) | 
					
						
							|  |  |  |             return NULL; | 
					
						
							|  |  |  |         return PyLong_FromSsize_t(index); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     contains = range_contains_long(r, ob); | 
					
						
							|  |  |  |     if (contains == -1) | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-11-20 22:44:32 +00:00
										 |  |  |     if (contains) { | 
					
						
							|  |  |  |         PyObject *idx, *tmp = PyNumber_Subtract(ob, r->start); | 
					
						
							|  |  |  |         if (tmp == NULL) | 
					
						
							| 
									
										
										
										
											2010-09-13 21:16:29 +00:00
										 |  |  |             return NULL; | 
					
						
							| 
									
										
										
										
											2010-11-20 22:44:32 +00:00
										 |  |  |         /* idx = (ob - r.start) // r.step */ | 
					
						
							|  |  |  |         idx = PyNumber_FloorDivide(tmp, r->step); | 
					
						
							|  |  |  |         Py_DECREF(tmp); | 
					
						
							|  |  |  |         return idx; | 
					
						
							| 
									
										
										
										
											2009-09-22 21:47:24 +00:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2010-11-20 22:44:32 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     /* object is not in the range */ | 
					
						
							|  |  |  |     PyErr_Format(PyExc_ValueError, "%R is not in range", ob); | 
					
						
							| 
									
										
										
										
											2010-09-13 21:16:29 +00:00
										 |  |  |     return NULL; | 
					
						
							| 
									
										
										
										
											2009-09-22 21:47:24 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1997-05-02 03:12:38 +00:00
										 |  |  | static PySequenceMethods range_as_sequence = { | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     (lenfunc)range_length,      /* sq_length */ | 
					
						
							| 
									
										
										
										
											2010-12-03 14:26:13 +00:00
										 |  |  |     0,                          /* sq_concat */ | 
					
						
							|  |  |  |     0,                          /* sq_repeat */ | 
					
						
							|  |  |  |     (ssizeargfunc)range_item,   /* sq_item */ | 
					
						
							|  |  |  |     0,                          /* sq_slice */ | 
					
						
							|  |  |  |     0,                          /* sq_ass_item */ | 
					
						
							|  |  |  |     0,                          /* sq_ass_slice */ | 
					
						
							| 
									
										
										
										
											2009-09-22 21:47:24 +00:00
										 |  |  |     (objobjproc)range_contains, /* sq_contains */ | 
					
						
							| 
									
										
										
										
											1993-10-26 17:58:25 +00:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-12-03 14:26:13 +00:00
										 |  |  | static PyObject * | 
					
						
							|  |  |  | range_repr(rangeobject *r) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     Py_ssize_t istep; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* Check for special case values for printing.  We don't always
 | 
					
						
							| 
									
										
										
										
											2018-08-24 07:39:45 +03:00
										 |  |  |        need the step value.  We don't care about overflow. */ | 
					
						
							| 
									
										
										
										
											2010-12-03 14:26:13 +00:00
										 |  |  |     istep = PyNumber_AsSsize_t(r->step, NULL); | 
					
						
							| 
									
										
										
										
											2018-08-24 07:39:45 +03:00
										 |  |  |     if (istep == -1 && PyErr_Occurred()) { | 
					
						
							|  |  |  |         assert(!PyErr_ExceptionMatches(PyExc_OverflowError)); | 
					
						
							|  |  |  |         return NULL; | 
					
						
							| 
									
										
										
										
											2010-12-03 14:26:13 +00:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (istep == 1) | 
					
						
							|  |  |  |         return PyUnicode_FromFormat("range(%R, %R)", r->start, r->stop); | 
					
						
							|  |  |  |     else | 
					
						
							|  |  |  |         return PyUnicode_FromFormat("range(%R, %R, %R)", | 
					
						
							|  |  |  |                                     r->start, r->stop, r->step); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Pickling support */ | 
					
						
							|  |  |  | static PyObject * | 
					
						
							|  |  |  | range_reduce(rangeobject *r, PyObject *args) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return Py_BuildValue("(O(OOO))", Py_TYPE(r), | 
					
						
							|  |  |  |                          r->start, r->stop, r->step); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							|  |  |  | range_subscript(rangeobject* self, PyObject* item) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (PyIndex_Check(item)) { | 
					
						
							| 
									
										
										
										
											2011-01-12 03:15:52 +00:00
										 |  |  |         PyObject *i, *result; | 
					
						
							|  |  |  |         i = PyNumber_Index(item); | 
					
						
							|  |  |  |         if (!i) | 
					
						
							| 
									
										
										
										
											2010-12-03 14:26:13 +00:00
										 |  |  |             return NULL; | 
					
						
							| 
									
										
										
										
											2011-01-12 03:15:52 +00:00
										 |  |  |         result = compute_range_item(self, i); | 
					
						
							|  |  |  |         Py_DECREF(i); | 
					
						
							|  |  |  |         return result; | 
					
						
							| 
									
										
										
										
											2010-12-03 14:26:13 +00:00
										 |  |  |     } | 
					
						
							|  |  |  |     if (PySlice_Check(item)) { | 
					
						
							| 
									
										
										
										
											2011-01-12 03:15:52 +00:00
										 |  |  |         return compute_slice(self, item); | 
					
						
							| 
									
										
										
										
											2010-12-03 14:26:13 +00:00
										 |  |  |     } | 
					
						
							|  |  |  |     PyErr_Format(PyExc_TypeError, | 
					
						
							|  |  |  |                  "range indices must be integers or slices, not %.200s", | 
					
						
							|  |  |  |                  item->ob_type->tp_name); | 
					
						
							|  |  |  |     return NULL; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyMappingMethods range_as_mapping = { | 
					
						
							|  |  |  |         (lenfunc)range_length,       /* mp_length */ | 
					
						
							|  |  |  |         (binaryfunc)range_subscript, /* mp_subscript */ | 
					
						
							|  |  |  |         (objobjargproc)0,            /* mp_ass_subscript */ | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-20 09:44:46 +03:00
										 |  |  | static int | 
					
						
							|  |  |  | range_bool(rangeobject* self) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return PyObject_IsTrue(self->length); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyNumberMethods range_as_number = { | 
					
						
							|  |  |  |     .nb_bool = (inquiry)range_bool, | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-17 16:30:39 +00:00
										 |  |  | static PyObject * range_iter(PyObject *seq); | 
					
						
							| 
									
										
										
										
											2018-04-30 00:29:33 +05:30
										 |  |  | static PyObject * range_reverse(PyObject *seq, PyObject *Py_UNUSED(ignored)); | 
					
						
							| 
									
										
										
										
											2003-11-06 14:06:48 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | PyDoc_STRVAR(reverse_doc, | 
					
						
							| 
									
										
										
										
											2013-10-06 00:36:45 +03:00
										 |  |  | "Return a reverse iterator."); | 
					
						
							| 
									
										
										
										
											2003-11-06 14:06:48 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-13 21:16:29 +00:00
										 |  |  | PyDoc_STRVAR(count_doc, | 
					
						
							|  |  |  | "rangeobject.count(value) -> integer -- return number of occurrences of value"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyDoc_STRVAR(index_doc, | 
					
						
							| 
									
										
										
										
											2019-05-03 17:52:12 +05:30
										 |  |  | "rangeobject.index(value) -> integer -- return index of value.\n" | 
					
						
							| 
									
										
										
										
											2013-10-06 00:36:45 +03:00
										 |  |  | "Raise ValueError if the value is not present."); | 
					
						
							| 
									
										
										
										
											2010-09-13 21:16:29 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-11-06 14:06:48 +00:00
										 |  |  | static PyMethodDef range_methods[] = { | 
					
						
							| 
									
										
										
										
											2018-04-30 00:29:33 +05:30
										 |  |  |     {"__reversed__",    range_reverse,              METH_NOARGS, reverse_doc}, | 
					
						
							| 
									
										
										
										
											2010-09-13 21:16:29 +00:00
										 |  |  |     {"__reduce__",      (PyCFunction)range_reduce,  METH_VARARGS}, | 
					
						
							|  |  |  |     {"count",           (PyCFunction)range_count,   METH_O,      count_doc}, | 
					
						
							|  |  |  |     {"index",           (PyCFunction)range_index,   METH_O,      index_doc}, | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     {NULL,              NULL}           /* sentinel */ | 
					
						
							| 
									
										
										
										
											2003-11-06 14:06:48 +00:00
										 |  |  | }; | 
					
						
							| 
									
										
										
										
											2002-06-05 20:08:48 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-11-05 15:17:52 -04:00
										 |  |  | static PyMemberDef range_members[] = { | 
					
						
							|  |  |  |     {"start",   T_OBJECT_EX,    offsetof(rangeobject, start),   READONLY}, | 
					
						
							|  |  |  |     {"stop",    T_OBJECT_EX,    offsetof(rangeobject, stop),    READONLY}, | 
					
						
							|  |  |  |     {"step",    T_OBJECT_EX,    offsetof(rangeobject, step),    READONLY}, | 
					
						
							|  |  |  |     {0} | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1997-05-02 03:12:38 +00:00
										 |  |  | PyTypeObject PyRange_Type = { | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |         PyVarObject_HEAD_INIT(&PyType_Type, 0) | 
					
						
							|  |  |  |         "range",                /* Name of this type */ | 
					
						
							|  |  |  |         sizeof(rangeobject),    /* Basic object size */ | 
					
						
							|  |  |  |         0,                      /* Item size for varobject */ | 
					
						
							|  |  |  |         (destructor)range_dealloc, /* tp_dealloc */ | 
					
						
							|  |  |  |         0,                      /* tp_print */ | 
					
						
							|  |  |  |         0,                      /* tp_getattr */ | 
					
						
							|  |  |  |         0,                      /* tp_setattr */ | 
					
						
							|  |  |  |         0,                      /* tp_reserved */ | 
					
						
							|  |  |  |         (reprfunc)range_repr,   /* tp_repr */ | 
					
						
							| 
									
										
										
										
											2017-03-20 09:44:46 +03:00
										 |  |  |         &range_as_number,       /* tp_as_number */ | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |         &range_as_sequence,     /* tp_as_sequence */ | 
					
						
							| 
									
										
										
										
											2010-12-03 14:26:13 +00:00
										 |  |  |         &range_as_mapping,      /* tp_as_mapping */ | 
					
						
							| 
									
										
										
										
											2011-10-23 19:53:01 +01:00
										 |  |  |         (hashfunc)range_hash,   /* tp_hash */ | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |         0,                      /* tp_call */ | 
					
						
							|  |  |  |         0,                      /* tp_str */ | 
					
						
							|  |  |  |         PyObject_GenericGetAttr,  /* tp_getattro */ | 
					
						
							|  |  |  |         0,                      /* tp_setattro */ | 
					
						
							|  |  |  |         0,                      /* tp_as_buffer */ | 
					
						
							|  |  |  |         Py_TPFLAGS_DEFAULT,     /* tp_flags */ | 
					
						
							|  |  |  |         range_doc,              /* tp_doc */ | 
					
						
							|  |  |  |         0,                      /* tp_traverse */ | 
					
						
							|  |  |  |         0,                      /* tp_clear */ | 
					
						
							| 
									
										
										
										
											2011-10-23 19:53:01 +01:00
										 |  |  |         range_richcompare,      /* tp_richcompare */ | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |         0,                      /* tp_weaklistoffset */ | 
					
						
							|  |  |  |         range_iter,             /* tp_iter */ | 
					
						
							|  |  |  |         0,                      /* tp_iternext */ | 
					
						
							|  |  |  |         range_methods,          /* tp_methods */ | 
					
						
							| 
									
										
										
										
											2011-11-05 15:17:52 -04:00
										 |  |  |         range_members,          /* tp_members */ | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |         0,                      /* tp_getset */ | 
					
						
							|  |  |  |         0,                      /* tp_base */ | 
					
						
							|  |  |  |         0,                      /* tp_dict */ | 
					
						
							|  |  |  |         0,                      /* tp_descr_get */ | 
					
						
							|  |  |  |         0,                      /* tp_descr_set */ | 
					
						
							|  |  |  |         0,                      /* tp_dictoffset */ | 
					
						
							|  |  |  |         0,                      /* tp_init */ | 
					
						
							|  |  |  |         0,                      /* tp_alloc */ | 
					
						
							|  |  |  |         range_new,              /* tp_new */ | 
					
						
							| 
									
										
										
										
											2002-06-05 20:08:48 +00:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-05-21 18:01:17 +00:00
										 |  |  | /*********************** range Iterator **************************/ | 
					
						
							| 
									
										
										
										
											2002-06-05 20:08:48 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-05-07 22:24:25 +00:00
										 |  |  | /* There are 2 types of iterators, one for C longs, the other for
 | 
					
						
							| 
									
										
										
										
											2013-08-27 19:40:23 +03:00
										 |  |  |    Python ints (ie, PyObjects).  This should make iteration fast | 
					
						
							| 
									
										
										
										
											2007-05-07 22:24:25 +00:00
										 |  |  |    in the normal case, but possible for any numeric value. | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-06-05 20:08:48 +00:00
										 |  |  | typedef struct { | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |         PyObject_HEAD | 
					
						
							|  |  |  |         long    index; | 
					
						
							|  |  |  |         long    start; | 
					
						
							|  |  |  |         long    step; | 
					
						
							|  |  |  |         long    len; | 
					
						
							| 
									
										
										
										
											2002-06-05 20:08:48 +00:00
										 |  |  | } rangeiterobject; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							| 
									
										
										
										
											2010-11-20 23:05:39 +00:00
										 |  |  | rangeiter_next(rangeiterobject *r) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2007-05-07 22:24:25 +00:00
										 |  |  |     if (r->index < r->len) | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |         /* cast to unsigned to avoid possible signed overflow
 | 
					
						
							| 
									
										
										
										
											2009-11-15 12:56:08 +00:00
										 |  |  |            in intermediate calculations. */ | 
					
						
							|  |  |  |         return PyLong_FromLong((long)(r->start + | 
					
						
							|  |  |  |                                       (unsigned long)(r->index++) * r->step)); | 
					
						
							| 
									
										
										
										
											2007-05-07 22:24:25 +00:00
										 |  |  |     return NULL; | 
					
						
							| 
									
										
										
										
											2002-06-05 20:08:48 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-09-24 21:23:05 +00:00
										 |  |  | static PyObject * | 
					
						
							| 
									
										
										
										
											2018-04-30 00:29:33 +05:30
										 |  |  | rangeiter_len(rangeiterobject *r, PyObject *Py_UNUSED(ignored)) | 
					
						
							| 
									
										
										
										
											2010-11-20 23:05:39 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2007-12-02 14:31:20 +00:00
										 |  |  |     return PyLong_FromLong(r->len - r->index); | 
					
						
							| 
									
										
										
										
											2004-03-10 10:10:42 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-05-07 22:24:25 +00:00
										 |  |  | PyDoc_STRVAR(length_hint_doc, | 
					
						
							|  |  |  |              "Private method returning an estimate of len(list(it))."); | 
					
						
							| 
									
										
										
										
											2004-03-10 10:10:42 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-03 10:49:41 +00:00
										 |  |  | static PyObject * | 
					
						
							| 
									
										
										
										
											2018-04-30 00:29:33 +05:30
										 |  |  | rangeiter_reduce(rangeiterobject *r, PyObject *Py_UNUSED(ignored)) | 
					
						
							| 
									
										
										
										
											2012-04-03 10:49:41 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2018-12-11 08:28:18 +02:00
										 |  |  |     _Py_IDENTIFIER(iter); | 
					
						
							| 
									
										
										
										
											2012-04-03 10:49:41 +00:00
										 |  |  |     PyObject *start=NULL, *stop=NULL, *step=NULL; | 
					
						
							|  |  |  |     PyObject *range; | 
					
						
							| 
									
										
										
										
											2012-10-07 14:56:27 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-03 10:49:41 +00:00
										 |  |  |     /* create a range object for pickling */ | 
					
						
							|  |  |  |     start = PyLong_FromLong(r->start); | 
					
						
							|  |  |  |     if (start == NULL) | 
					
						
							|  |  |  |         goto err; | 
					
						
							|  |  |  |     stop = PyLong_FromLong(r->start + r->len * r->step); | 
					
						
							|  |  |  |     if (stop == NULL) | 
					
						
							|  |  |  |         goto err; | 
					
						
							|  |  |  |     step = PyLong_FromLong(r->step); | 
					
						
							|  |  |  |     if (step == NULL) | 
					
						
							|  |  |  |         goto err; | 
					
						
							|  |  |  |     range = (PyObject*)make_range_object(&PyRange_Type, | 
					
						
							|  |  |  |                                start, stop, step); | 
					
						
							|  |  |  |     if (range == NULL) | 
					
						
							|  |  |  |         goto err; | 
					
						
							|  |  |  |     /* return the result */ | 
					
						
							| 
									
										
										
										
											2018-12-11 08:28:18 +02:00
										 |  |  |     return Py_BuildValue("N(N)i", _PyEval_GetBuiltinId(&PyId_iter), | 
					
						
							|  |  |  |                          range, r->index); | 
					
						
							| 
									
										
										
										
											2012-04-03 10:49:41 +00:00
										 |  |  | err: | 
					
						
							|  |  |  |     Py_XDECREF(start); | 
					
						
							|  |  |  |     Py_XDECREF(stop); | 
					
						
							|  |  |  |     Py_XDECREF(step); | 
					
						
							|  |  |  |     return NULL; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							|  |  |  | rangeiter_setstate(rangeiterobject *r, PyObject *state) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     long index = PyLong_AsLong(state); | 
					
						
							|  |  |  |     if (index == -1 && PyErr_Occurred()) | 
					
						
							|  |  |  |         return NULL; | 
					
						
							| 
									
										
										
										
											2014-03-05 13:47:57 +00:00
										 |  |  |     /* silently clip the index value */ | 
					
						
							|  |  |  |     if (index < 0) | 
					
						
							|  |  |  |         index = 0; | 
					
						
							|  |  |  |     else if (index > r->len) | 
					
						
							|  |  |  |         index = r->len; /* exhausted iterator */ | 
					
						
							| 
									
										
										
										
											2012-04-03 10:49:41 +00:00
										 |  |  |     r->index = index; | 
					
						
							|  |  |  |     Py_RETURN_NONE; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyDoc_STRVAR(reduce_doc, "Return state information for pickling."); | 
					
						
							|  |  |  | PyDoc_STRVAR(setstate_doc, "Set state information for unpickling."); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-09-24 21:23:05 +00:00
										 |  |  | static PyMethodDef rangeiter_methods[] = { | 
					
						
							| 
									
										
										
										
											2007-05-07 22:24:25 +00:00
										 |  |  |     {"__length_hint__", (PyCFunction)rangeiter_len, METH_NOARGS, | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |         length_hint_doc}, | 
					
						
							| 
									
										
										
										
											2012-04-03 10:49:41 +00:00
										 |  |  |     {"__reduce__", (PyCFunction)rangeiter_reduce, METH_NOARGS, | 
					
						
							|  |  |  |         reduce_doc}, | 
					
						
							|  |  |  |     {"__setstate__", (PyCFunction)rangeiter_setstate, METH_O, | 
					
						
							|  |  |  |         setstate_doc}, | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     {NULL,              NULL}           /* sentinel */ | 
					
						
							| 
									
										
										
										
											2005-09-24 21:23:05 +00:00
										 |  |  | }; | 
					
						
							| 
									
										
										
										
											2004-03-10 10:10:42 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-11-29 22:35:39 +00:00
										 |  |  | PyTypeObject PyRangeIter_Type = { | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |         PyVarObject_HEAD_INIT(&PyType_Type, 0) | 
					
						
							|  |  |  |         "range_iterator",                        /* tp_name */ | 
					
						
							|  |  |  |         sizeof(rangeiterobject),                /* tp_basicsize */ | 
					
						
							|  |  |  |         0,                                      /* tp_itemsize */ | 
					
						
							|  |  |  |         /* methods */ | 
					
						
							|  |  |  |         (destructor)PyObject_Del,               /* tp_dealloc */ | 
					
						
							|  |  |  |         0,                                      /* tp_print */ | 
					
						
							|  |  |  |         0,                                      /* tp_getattr */ | 
					
						
							|  |  |  |         0,                                      /* tp_setattr */ | 
					
						
							|  |  |  |         0,                                      /* tp_reserved */ | 
					
						
							|  |  |  |         0,                                      /* tp_repr */ | 
					
						
							|  |  |  |         0,                                      /* tp_as_number */ | 
					
						
							|  |  |  |         0,                                      /* tp_as_sequence */ | 
					
						
							|  |  |  |         0,                                      /* tp_as_mapping */ | 
					
						
							|  |  |  |         0,                                      /* tp_hash */ | 
					
						
							|  |  |  |         0,                                      /* tp_call */ | 
					
						
							|  |  |  |         0,                                      /* tp_str */ | 
					
						
							|  |  |  |         PyObject_GenericGetAttr,                /* tp_getattro */ | 
					
						
							|  |  |  |         0,                                      /* tp_setattro */ | 
					
						
							|  |  |  |         0,                                      /* tp_as_buffer */ | 
					
						
							|  |  |  |         Py_TPFLAGS_DEFAULT,                     /* tp_flags */ | 
					
						
							|  |  |  |         0,                                      /* tp_doc */ | 
					
						
							|  |  |  |         0,                                      /* tp_traverse */ | 
					
						
							|  |  |  |         0,                                      /* tp_clear */ | 
					
						
							|  |  |  |         0,                                      /* tp_richcompare */ | 
					
						
							|  |  |  |         0,                                      /* tp_weaklistoffset */ | 
					
						
							|  |  |  |         PyObject_SelfIter,                      /* tp_iter */ | 
					
						
							|  |  |  |         (iternextfunc)rangeiter_next,           /* tp_iternext */ | 
					
						
							|  |  |  |         rangeiter_methods,                      /* tp_methods */ | 
					
						
							|  |  |  |         0,                                      /* tp_members */ | 
					
						
							| 
									
										
										
										
											2007-05-07 22:24:25 +00:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-15 09:57:26 +00:00
										 |  |  | /* Return number of items in range (lo, hi, step).  step != 0
 | 
					
						
							|  |  |  |  * required.  The result always fits in an unsigned long. | 
					
						
							| 
									
										
										
										
											2007-05-07 22:24:25 +00:00
										 |  |  |  */ | 
					
						
							| 
									
										
										
										
											2009-11-15 09:57:26 +00:00
										 |  |  | static unsigned long | 
					
						
							| 
									
										
										
										
											2010-11-20 23:05:39 +00:00
										 |  |  | get_len_of_range(long lo, long hi, long step) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2007-05-07 22:24:25 +00:00
										 |  |  |     /* -------------------------------------------------------------
 | 
					
						
							| 
									
										
										
										
											2009-11-15 09:57:26 +00:00
										 |  |  |     If step > 0 and lo >= hi, or step < 0 and lo <= hi, the range is empty. | 
					
						
							|  |  |  |     Else for step > 0, if n values are in the range, the last one is | 
					
						
							| 
									
										
										
										
											2007-05-07 22:24:25 +00:00
										 |  |  |     lo + (n-1)*step, which must be <= hi-1.  Rearranging, | 
					
						
							|  |  |  |     n <= (hi - lo - 1)/step + 1, so taking the floor of the RHS gives | 
					
						
							|  |  |  |     the proper value.  Since lo < hi in this case, hi-lo-1 >= 0, so | 
					
						
							|  |  |  |     the RHS is non-negative and so truncation is the same as the | 
					
						
							|  |  |  |     floor.  Letting M be the largest positive long, the worst case | 
					
						
							|  |  |  |     for the RHS numerator is hi=M, lo=-M-1, and then | 
					
						
							|  |  |  |     hi-lo-1 = M-(-M-1)-1 = 2*M.  Therefore unsigned long has enough | 
					
						
							| 
									
										
										
										
											2009-11-15 09:57:26 +00:00
										 |  |  |     precision to compute the RHS exactly.  The analysis for step < 0 | 
					
						
							|  |  |  |     is similar. | 
					
						
							| 
									
										
										
										
											2007-05-07 22:24:25 +00:00
										 |  |  |     ---------------------------------------------------------------*/ | 
					
						
							| 
									
										
										
										
											2009-11-15 09:57:26 +00:00
										 |  |  |     assert(step != 0); | 
					
						
							|  |  |  |     if (step > 0 && lo < hi) | 
					
						
							|  |  |  |         return 1UL + (hi - 1UL - lo) / step; | 
					
						
							|  |  |  |     else if (step < 0 && lo > hi) | 
					
						
							|  |  |  |         return 1UL + (lo - 1UL - hi) / (0UL - step); | 
					
						
							|  |  |  |     else | 
					
						
							|  |  |  |         return 0UL; | 
					
						
							| 
									
										
										
										
											2007-05-07 22:24:25 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-15 09:57:26 +00:00
										 |  |  | /* Initialize a rangeiter object.  If the length of the rangeiter object
 | 
					
						
							|  |  |  |    is not representable as a C long, OverflowError is raised. */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-05-07 22:24:25 +00:00
										 |  |  | static PyObject * | 
					
						
							| 
									
										
										
										
											2010-12-03 14:26:13 +00:00
										 |  |  | fast_range_iter(long start, long stop, long step) | 
					
						
							| 
									
										
										
										
											2010-11-20 23:05:39 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2007-11-29 22:35:39 +00:00
										 |  |  |     rangeiterobject *it = PyObject_New(rangeiterobject, &PyRangeIter_Type); | 
					
						
							| 
									
										
										
										
											2009-11-15 09:57:26 +00:00
										 |  |  |     unsigned long ulen; | 
					
						
							| 
									
										
										
										
											2007-05-07 22:24:25 +00:00
										 |  |  |     if (it == NULL) | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     it->start = start; | 
					
						
							|  |  |  |     it->step = step; | 
					
						
							| 
									
										
										
										
											2009-11-15 09:57:26 +00:00
										 |  |  |     ulen = get_len_of_range(start, stop, step); | 
					
						
							|  |  |  |     if (ulen > (unsigned long)LONG_MAX) { | 
					
						
							| 
									
										
										
										
											2009-11-16 00:34:25 +00:00
										 |  |  |         Py_DECREF(it); | 
					
						
							| 
									
										
										
										
											2009-11-15 09:57:26 +00:00
										 |  |  |         PyErr_SetString(PyExc_OverflowError, | 
					
						
							|  |  |  |                         "range too large to represent as a range_iterator"); | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     it->len = (long)ulen; | 
					
						
							| 
									
										
										
										
											2007-05-07 22:24:25 +00:00
										 |  |  |     it->index = 0; | 
					
						
							|  |  |  |     return (PyObject *)it; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-12-03 14:26:13 +00:00
										 |  |  | typedef struct { | 
					
						
							|  |  |  |     PyObject_HEAD | 
					
						
							|  |  |  |     PyObject *index; | 
					
						
							|  |  |  |     PyObject *start; | 
					
						
							|  |  |  |     PyObject *step; | 
					
						
							|  |  |  |     PyObject *len; | 
					
						
							|  |  |  | } longrangeiterobject; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							|  |  |  | longrangeiter_len(longrangeiterobject *r, PyObject *no_args) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return PyNumber_Subtract(r->len, r->index); | 
					
						
							| 
									
										
										
										
											2007-05-07 22:24:25 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-03 10:49:41 +00:00
										 |  |  | static PyObject * | 
					
						
							| 
									
										
										
										
											2018-04-30 00:29:33 +05:30
										 |  |  | longrangeiter_reduce(longrangeiterobject *r, PyObject *Py_UNUSED(ignored)) | 
					
						
							| 
									
										
										
										
											2012-04-03 10:49:41 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2018-12-11 08:28:18 +02:00
										 |  |  |     _Py_IDENTIFIER(iter); | 
					
						
							| 
									
										
										
										
											2012-04-03 10:49:41 +00:00
										 |  |  |     PyObject *product, *stop=NULL; | 
					
						
							|  |  |  |     PyObject *range; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* create a range object for pickling.  Must calculate the "stop" value */ | 
					
						
							|  |  |  |     product = PyNumber_Multiply(r->len, r->step); | 
					
						
							|  |  |  |     if (product == NULL) | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     stop = PyNumber_Add(r->start, product); | 
					
						
							|  |  |  |     Py_DECREF(product); | 
					
						
							|  |  |  |     if (stop ==  NULL) | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     Py_INCREF(r->start); | 
					
						
							|  |  |  |     Py_INCREF(r->step); | 
					
						
							|  |  |  |     range =  (PyObject*)make_range_object(&PyRange_Type, | 
					
						
							|  |  |  |                                r->start, stop, r->step); | 
					
						
							|  |  |  |     if (range == NULL) { | 
					
						
							|  |  |  |         Py_DECREF(r->start); | 
					
						
							|  |  |  |         Py_DECREF(stop); | 
					
						
							|  |  |  |         Py_DECREF(r->step); | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* return the result */ | 
					
						
							| 
									
										
										
										
											2018-12-11 08:28:18 +02:00
										 |  |  |     return Py_BuildValue("N(N)O", _PyEval_GetBuiltinId(&PyId_iter), | 
					
						
							|  |  |  |                          range, r->index); | 
					
						
							| 
									
										
										
										
											2012-04-03 10:49:41 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							|  |  |  | longrangeiter_setstate(longrangeiterobject *r, PyObject *state) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2014-03-05 13:47:57 +00:00
										 |  |  |     int cmp; | 
					
						
							| 
									
										
										
										
											2015-03-18 21:53:15 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-03-05 13:47:57 +00:00
										 |  |  |     /* clip the value */ | 
					
						
							| 
									
										
										
										
											2017-03-30 09:09:41 +03:00
										 |  |  |     cmp = PyObject_RichCompareBool(state, _PyLong_Zero, Py_LT); | 
					
						
							|  |  |  |     if (cmp < 0) | 
					
						
							| 
									
										
										
										
											2014-03-05 13:47:57 +00:00
										 |  |  |         return NULL; | 
					
						
							|  |  |  |     if (cmp > 0) { | 
					
						
							| 
									
										
										
										
											2017-03-30 09:09:41 +03:00
										 |  |  |         state = _PyLong_Zero; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else { | 
					
						
							|  |  |  |         cmp = PyObject_RichCompareBool(r->len, state, Py_LT); | 
					
						
							|  |  |  |         if (cmp < 0) | 
					
						
							|  |  |  |             return NULL; | 
					
						
							|  |  |  |         if (cmp > 0) | 
					
						
							|  |  |  |             state = r->len; | 
					
						
							| 
									
										
										
										
											2014-03-05 13:47:57 +00:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2015-12-27 12:36:18 +02:00
										 |  |  |     Py_INCREF(state); | 
					
						
							| 
									
										
										
										
											2016-04-06 09:45:48 +03:00
										 |  |  |     Py_XSETREF(r->index, state); | 
					
						
							| 
									
										
										
										
											2012-04-03 10:49:41 +00:00
										 |  |  |     Py_RETURN_NONE; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-05-07 22:24:25 +00:00
										 |  |  | static PyMethodDef longrangeiter_methods[] = { | 
					
						
							|  |  |  |     {"__length_hint__", (PyCFunction)longrangeiter_len, METH_NOARGS, | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |         length_hint_doc}, | 
					
						
							| 
									
										
										
										
											2012-04-03 10:49:41 +00:00
										 |  |  |     {"__reduce__", (PyCFunction)longrangeiter_reduce, METH_NOARGS, | 
					
						
							|  |  |  |         reduce_doc}, | 
					
						
							|  |  |  |     {"__setstate__", (PyCFunction)longrangeiter_setstate, METH_O, | 
					
						
							|  |  |  |         setstate_doc}, | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     {NULL,              NULL}           /* sentinel */ | 
					
						
							| 
									
										
										
										
											2007-05-07 22:24:25 +00:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void | 
					
						
							| 
									
										
										
										
											2010-11-20 23:05:39 +00:00
										 |  |  | longrangeiter_dealloc(longrangeiterobject *r) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2007-05-07 22:24:25 +00:00
										 |  |  |     Py_XDECREF(r->index); | 
					
						
							| 
									
										
										
										
											2007-05-08 15:18:31 +00:00
										 |  |  |     Py_XDECREF(r->start); | 
					
						
							|  |  |  |     Py_XDECREF(r->step); | 
					
						
							|  |  |  |     Py_XDECREF(r->len); | 
					
						
							| 
									
										
										
										
											2007-11-15 20:52:21 +00:00
										 |  |  |     PyObject_Del(r); | 
					
						
							| 
									
										
										
										
											2007-05-07 22:24:25 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							| 
									
										
										
										
											2010-11-20 23:05:39 +00:00
										 |  |  | longrangeiter_next(longrangeiterobject *r) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2017-03-30 09:09:41 +03:00
										 |  |  |     PyObject *product, *new_index, *result; | 
					
						
							| 
									
										
										
										
											2007-05-07 22:24:25 +00:00
										 |  |  |     if (PyObject_RichCompareBool(r->index, r->len, Py_LT) != 1) | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-30 09:09:41 +03:00
										 |  |  |     new_index = PyNumber_Add(r->index, _PyLong_One); | 
					
						
							| 
									
										
										
										
											2009-11-16 00:34:25 +00:00
										 |  |  |     if (!new_index) | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     product = PyNumber_Multiply(r->index, r->step); | 
					
						
							|  |  |  |     if (!product) { | 
					
						
							|  |  |  |         Py_DECREF(new_index); | 
					
						
							| 
									
										
										
										
											2007-05-07 22:24:25 +00:00
										 |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     result = PyNumber_Add(r->start, product); | 
					
						
							|  |  |  |     Py_DECREF(product); | 
					
						
							|  |  |  |     if (result) { | 
					
						
							| 
									
										
										
										
											2016-04-10 18:05:40 +03:00
										 |  |  |         Py_SETREF(r->index, new_index); | 
					
						
							| 
									
										
										
										
											2007-05-07 22:24:25 +00:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2009-11-16 00:34:25 +00:00
										 |  |  |     else { | 
					
						
							|  |  |  |         Py_DECREF(new_index); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2007-05-07 22:24:25 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     return result; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-11-29 22:35:39 +00:00
										 |  |  | PyTypeObject PyLongRangeIter_Type = { | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |         PyVarObject_HEAD_INIT(&PyType_Type, 0) | 
					
						
							|  |  |  |         "longrange_iterator",                   /* tp_name */ | 
					
						
							|  |  |  |         sizeof(longrangeiterobject),            /* tp_basicsize */ | 
					
						
							|  |  |  |         0,                                      /* tp_itemsize */ | 
					
						
							|  |  |  |         /* methods */ | 
					
						
							|  |  |  |         (destructor)longrangeiter_dealloc,      /* tp_dealloc */ | 
					
						
							|  |  |  |         0,                                      /* tp_print */ | 
					
						
							|  |  |  |         0,                                      /* tp_getattr */ | 
					
						
							|  |  |  |         0,                                      /* tp_setattr */ | 
					
						
							|  |  |  |         0,                                      /* tp_reserved */ | 
					
						
							|  |  |  |         0,                                      /* tp_repr */ | 
					
						
							|  |  |  |         0,                                      /* tp_as_number */ | 
					
						
							|  |  |  |         0,                                      /* tp_as_sequence */ | 
					
						
							|  |  |  |         0,                                      /* tp_as_mapping */ | 
					
						
							|  |  |  |         0,                                      /* tp_hash */ | 
					
						
							|  |  |  |         0,                                      /* tp_call */ | 
					
						
							|  |  |  |         0,                                      /* tp_str */ | 
					
						
							|  |  |  |         PyObject_GenericGetAttr,                /* tp_getattro */ | 
					
						
							|  |  |  |         0,                                      /* tp_setattro */ | 
					
						
							|  |  |  |         0,                                      /* tp_as_buffer */ | 
					
						
							|  |  |  |         Py_TPFLAGS_DEFAULT,                     /* tp_flags */ | 
					
						
							|  |  |  |         0,                                      /* tp_doc */ | 
					
						
							|  |  |  |         0,                                      /* tp_traverse */ | 
					
						
							|  |  |  |         0,                                      /* tp_clear */ | 
					
						
							|  |  |  |         0,                                      /* tp_richcompare */ | 
					
						
							|  |  |  |         0,                                      /* tp_weaklistoffset */ | 
					
						
							|  |  |  |         PyObject_SelfIter,                      /* tp_iter */ | 
					
						
							|  |  |  |         (iternextfunc)longrangeiter_next,       /* tp_iternext */ | 
					
						
							|  |  |  |         longrangeiter_methods,                  /* tp_methods */ | 
					
						
							|  |  |  |         0, | 
					
						
							| 
									
										
										
										
											2002-06-05 20:08:48 +00:00
										 |  |  | }; | 
					
						
							| 
									
										
										
										
											2006-04-21 10:40:58 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							| 
									
										
										
										
											2010-11-20 23:05:39 +00:00
										 |  |  | range_iter(PyObject *seq) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2007-05-07 22:24:25 +00:00
										 |  |  |     rangeobject *r = (rangeobject *)seq; | 
					
						
							|  |  |  |     longrangeiterobject *it; | 
					
						
							| 
									
										
										
										
											2007-12-20 22:57:23 +00:00
										 |  |  |     long lstart, lstop, lstep; | 
					
						
							| 
									
										
										
										
											2009-11-15 09:57:26 +00:00
										 |  |  |     PyObject *int_it; | 
					
						
							| 
									
										
										
										
											2007-05-07 22:24:25 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     assert(PyRange_Check(seq)); | 
					
						
							| 
									
										
										
										
											2007-12-20 22:57:23 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-15 09:57:26 +00:00
										 |  |  |     /* If all three fields and the length convert to long, use the int
 | 
					
						
							|  |  |  |      * version */ | 
					
						
							| 
									
										
										
										
											2007-12-20 22:57:23 +00:00
										 |  |  |     lstart = PyLong_AsLong(r->start); | 
					
						
							| 
									
										
										
										
											2009-11-15 09:57:26 +00:00
										 |  |  |     if (lstart == -1 && PyErr_Occurred()) { | 
					
						
							|  |  |  |         PyErr_Clear(); | 
					
						
							|  |  |  |         goto long_range; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     lstop = PyLong_AsLong(r->stop); | 
					
						
							|  |  |  |     if (lstop == -1 && PyErr_Occurred()) { | 
					
						
							|  |  |  |         PyErr_Clear(); | 
					
						
							|  |  |  |         goto long_range; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     lstep = PyLong_AsLong(r->step); | 
					
						
							|  |  |  |     if (lstep == -1 && PyErr_Occurred()) { | 
					
						
							|  |  |  |         PyErr_Clear(); | 
					
						
							|  |  |  |         goto long_range; | 
					
						
							| 
									
										
										
										
											2007-12-20 22:57:23 +00:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2010-12-03 14:26:13 +00:00
										 |  |  |     int_it = fast_range_iter(lstart, lstop, lstep); | 
					
						
							| 
									
										
										
										
											2009-11-15 09:57:26 +00:00
										 |  |  |     if (int_it == NULL && PyErr_ExceptionMatches(PyExc_OverflowError)) { | 
					
						
							|  |  |  |         PyErr_Clear(); | 
					
						
							|  |  |  |         goto long_range; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return (PyObject *)int_it; | 
					
						
							| 
									
										
										
										
											2007-05-07 22:24:25 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-15 09:57:26 +00:00
										 |  |  |   long_range: | 
					
						
							| 
									
										
										
										
											2007-11-29 22:35:39 +00:00
										 |  |  |     it = PyObject_New(longrangeiterobject, &PyLongRangeIter_Type); | 
					
						
							| 
									
										
										
										
											2007-05-07 22:24:25 +00:00
										 |  |  |     if (it == NULL) | 
					
						
							|  |  |  |         return NULL; | 
					
						
							| 
									
										
										
										
											2007-05-08 15:18:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-05-07 22:24:25 +00:00
										 |  |  |     it->start = r->start; | 
					
						
							| 
									
										
										
										
											2007-05-08 15:18:31 +00:00
										 |  |  |     it->step = r->step; | 
					
						
							| 
									
										
										
										
											2010-12-03 14:26:13 +00:00
										 |  |  |     it->len = r->length; | 
					
						
							| 
									
										
										
										
											2017-03-30 09:09:41 +03:00
										 |  |  |     it->index = _PyLong_Zero; | 
					
						
							| 
									
										
										
										
											2007-05-08 15:18:31 +00:00
										 |  |  |     Py_INCREF(it->start); | 
					
						
							|  |  |  |     Py_INCREF(it->step); | 
					
						
							| 
									
										
										
										
											2010-12-03 14:26:13 +00:00
										 |  |  |     Py_INCREF(it->len); | 
					
						
							| 
									
										
										
										
											2017-03-30 09:09:41 +03:00
										 |  |  |     Py_INCREF(it->index); | 
					
						
							| 
									
										
										
										
											2007-05-07 22:24:25 +00:00
										 |  |  |     return (PyObject *)it; | 
					
						
							| 
									
										
										
										
											2006-04-21 10:40:58 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							| 
									
										
										
										
											2018-04-30 00:29:33 +05:30
										 |  |  | range_reverse(PyObject *seq, PyObject *Py_UNUSED(ignored)) | 
					
						
							| 
									
										
										
										
											2010-11-20 23:05:39 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2007-05-07 22:24:25 +00:00
										 |  |  |     rangeobject *range = (rangeobject*) seq; | 
					
						
							|  |  |  |     longrangeiterobject *it; | 
					
						
							| 
									
										
										
										
											2017-03-30 09:09:41 +03:00
										 |  |  |     PyObject *sum, *diff, *product; | 
					
						
							| 
									
										
										
										
											2009-11-15 09:57:26 +00:00
										 |  |  |     long lstart, lstop, lstep, new_start, new_stop; | 
					
						
							|  |  |  |     unsigned long ulen; | 
					
						
							| 
									
										
										
										
											2007-05-07 22:24:25 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     assert(PyRange_Check(seq)); | 
					
						
							| 
									
										
										
										
											2007-12-20 22:57:23 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-15 09:57:26 +00:00
										 |  |  |     /* reversed(range(start, stop, step)) can be expressed as
 | 
					
						
							|  |  |  |        range(start+(n-1)*step, start-step, -step), where n is the number of | 
					
						
							|  |  |  |        integers in the range. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |        If each of start, stop, step, -step, start-step, and the length | 
					
						
							|  |  |  |        of the iterator is representable as a C long, use the int | 
					
						
							|  |  |  |        version.  This excludes some cases where the reversed range is | 
					
						
							|  |  |  |        representable as a range_iterator, but it's good enough for | 
					
						
							|  |  |  |        common cases and it makes the checks simple. */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-12-20 22:57:23 +00:00
										 |  |  |     lstart = PyLong_AsLong(range->start); | 
					
						
							| 
									
										
										
										
											2009-11-15 09:57:26 +00:00
										 |  |  |     if (lstart == -1 && PyErr_Occurred()) { | 
					
						
							|  |  |  |         PyErr_Clear(); | 
					
						
							|  |  |  |         goto long_range; | 
					
						
							| 
									
										
										
										
											2007-05-07 22:24:25 +00:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2009-11-15 09:57:26 +00:00
										 |  |  |     lstop = PyLong_AsLong(range->stop); | 
					
						
							|  |  |  |     if (lstop == -1 && PyErr_Occurred()) { | 
					
						
							|  |  |  |         PyErr_Clear(); | 
					
						
							|  |  |  |         goto long_range; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     lstep = PyLong_AsLong(range->step); | 
					
						
							|  |  |  |     if (lstep == -1 && PyErr_Occurred()) { | 
					
						
							|  |  |  |         PyErr_Clear(); | 
					
						
							|  |  |  |         goto long_range; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     /* check for possible overflow of -lstep */ | 
					
						
							|  |  |  |     if (lstep == LONG_MIN) | 
					
						
							|  |  |  |         goto long_range; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* check for overflow of lstart - lstep:
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |        for lstep > 0, need only check whether lstart - lstep < LONG_MIN. | 
					
						
							|  |  |  |        for lstep < 0, need only check whether lstart - lstep > LONG_MAX | 
					
						
							| 
									
										
										
										
											2007-05-07 22:24:25 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-15 09:57:26 +00:00
										 |  |  |        Rearrange these inequalities as: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |            lstart - LONG_MIN < lstep  (lstep > 0) | 
					
						
							|  |  |  |            LONG_MAX - lstart < -lstep  (lstep < 0) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |        and compute both sides as unsigned longs, to avoid the | 
					
						
							|  |  |  |        possibility of undefined behaviour due to signed overflow. */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (lstep > 0) { | 
					
						
							|  |  |  |          if ((unsigned long)lstart - LONG_MIN < (unsigned long)lstep) | 
					
						
							|  |  |  |             goto long_range; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else { | 
					
						
							|  |  |  |         if (LONG_MAX - (unsigned long)lstart < 0UL - lstep) | 
					
						
							|  |  |  |             goto long_range; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     ulen = get_len_of_range(lstart, lstop, lstep); | 
					
						
							|  |  |  |     if (ulen > (unsigned long)LONG_MAX) | 
					
						
							|  |  |  |         goto long_range; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     new_stop = lstart - lstep; | 
					
						
							|  |  |  |     new_start = (long)(new_stop + ulen * lstep); | 
					
						
							| 
									
										
										
										
											2010-12-03 14:26:13 +00:00
										 |  |  |     return fast_range_iter(new_start, new_stop, -lstep); | 
					
						
							| 
									
										
										
										
											2009-11-15 09:57:26 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | long_range: | 
					
						
							| 
									
										
										
										
											2007-11-29 22:35:39 +00:00
										 |  |  |     it = PyObject_New(longrangeiterobject, &PyLongRangeIter_Type); | 
					
						
							| 
									
										
										
										
											2007-05-07 22:24:25 +00:00
										 |  |  |     if (it == NULL) | 
					
						
							|  |  |  |         return NULL; | 
					
						
							| 
									
										
										
										
											2018-10-31 03:13:16 -06:00
										 |  |  |     it->index = it->start = it->step = NULL; | 
					
						
							| 
									
										
										
										
											2007-05-07 22:24:25 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     /* start + (len - 1) * step */ | 
					
						
							| 
									
										
										
										
											2010-12-03 14:26:13 +00:00
										 |  |  |     it->len = range->length; | 
					
						
							|  |  |  |     Py_INCREF(it->len); | 
					
						
							| 
									
										
										
										
											2009-11-16 00:34:25 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-30 09:09:41 +03:00
										 |  |  |     diff = PyNumber_Subtract(it->len, _PyLong_One); | 
					
						
							| 
									
										
										
										
											2007-05-07 22:24:25 +00:00
										 |  |  |     if (!diff) | 
					
						
							|  |  |  |         goto create_failure; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-15 09:57:26 +00:00
										 |  |  |     product = PyNumber_Multiply(diff, range->step); | 
					
						
							|  |  |  |     Py_DECREF(diff); | 
					
						
							| 
									
										
										
										
											2007-05-07 22:24:25 +00:00
										 |  |  |     if (!product) | 
					
						
							|  |  |  |         goto create_failure; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     sum = PyNumber_Add(range->start, product); | 
					
						
							|  |  |  |     Py_DECREF(product); | 
					
						
							|  |  |  |     it->start = sum; | 
					
						
							|  |  |  |     if (!it->start) | 
					
						
							|  |  |  |         goto create_failure; | 
					
						
							| 
									
										
										
										
											2009-11-15 09:57:26 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-05-07 22:24:25 +00:00
										 |  |  |     it->step = PyNumber_Negative(range->step); | 
					
						
							| 
									
										
										
										
											2009-11-16 00:34:25 +00:00
										 |  |  |     if (!it->step) | 
					
						
							| 
									
										
										
										
											2009-11-15 09:57:26 +00:00
										 |  |  |         goto create_failure; | 
					
						
							| 
									
										
										
										
											2007-05-07 22:24:25 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-30 09:09:41 +03:00
										 |  |  |     it->index = _PyLong_Zero; | 
					
						
							|  |  |  |     Py_INCREF(it->index); | 
					
						
							| 
									
										
										
										
											2007-05-07 22:24:25 +00:00
										 |  |  |     return (PyObject *)it; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | create_failure: | 
					
						
							| 
									
										
										
										
											2009-11-16 00:34:25 +00:00
										 |  |  |     Py_DECREF(it); | 
					
						
							| 
									
										
										
										
											2007-05-07 22:24:25 +00:00
										 |  |  |     return NULL; | 
					
						
							| 
									
										
										
										
											2006-04-21 10:40:58 +00:00
										 |  |  | } |