Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(5)

Side by Side Diff: Objects/rangeobject.c

Issue 602: range: lean and mean (Closed) SVN Base: http://svn.python.org/view/*checkout*/python/branches/py3k/
Patch Set: Created 4 months, 1 week ago , Downloaded from: http://bugs.python.org/file10152/range_lean_and_mean.patch
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* Range object implementation */ 1 /* Range object implementation */
2 2
3 #include "Python.h" 3 #include "Python.h"
4 4
5 /* Support objects whose length is > PY_SSIZE_T_MAX. 5 /* Support objects whose length is > PY_SSIZE_T_MAX.
6 6
7 This could be sped up for small PyLongs if they fit in an Py_ssize_t. 7 This could be sped up for small PyLongs if they fit in an Py_ssize_t.
8 This only matters on Win64. Though we could use PY_LONG_LONG which 8 This only matters on Win64. Though we could use PY_LONG_LONG which
9 would presumably help perf. 9 would presumably help perf.
10 */ 10 */
11 11
12 typedef struct { 12 typedef struct {
13 PyObject_HEAD 13 PyObject_HEAD
14 PyObject *start; 14 PyObject *start;
15 PyObject *stop; 15 PyObject *stop;
16 PyObject *step; 16 PyObject *step;
17 PyObject *length;
mvloewis 2008/05/02 05:43:57 What is the purpose of caching the length in the r
GvR 2008/05/02 13:52:47 On 2008/05/02 05:43:57, mvloewis wrote: > What is
Benjamin 2008/05/02 16:56:18 On 2008/05/02 05:43:57, mvloewis wrote: > What is
17 } rangeobject; 18 } rangeobject;
18 19
19 /* Helper function for validating step. Always returns a new reference or 20 /* Helper function for validating step. Always returns a new reference or
20 NULL on error. 21 NULL on error.
21 */ 22 */
22 static PyObject * 23 static PyObject *
23 validate_step(PyObject *step) 24 validate_step(PyObject *step)
24 { 25 {
25 /* No step specified, use a step of 1. */ 26 /* No step specified, use a step of 1. */
26 if (!step) 27 if (!step)
27 return PyLong_FromLong(1); 28 return PyLong_FromLong(1);
28 29
29 step = PyNumber_Index(step); 30 step = PyNumber_Index(step);
30 if (step) { 31 if (step) {
31 Py_ssize_t istep = PyNumber_AsSsize_t(step, NULL); 32 Py_ssize_t istep = PyNumber_AsSsize_t(step, NULL);
32 if (istep == -1 && PyErr_Occurred()) { 33 if (istep == -1 && PyErr_Occurred()) {
33 /* Ignore OverflowError, we know the value isn't 0. */ 34 /* Ignore OverflowError, we know the value isn't 0. */
34 PyErr_Clear(); 35 PyErr_Clear();
35 } 36 }
36 else if (istep == 0) { 37 else if (istep == 0) {
37 PyErr_SetString(PyExc_ValueError, 38 PyErr_SetString(PyExc_ValueError,
38 "range() arg 3 must not be zero"); 39 "range() arg 3 must not be zero");
39 Py_CLEAR(step); 40 Py_CLEAR(step);
40 } 41 }
41 } 42 }
42 43
43 return step; 44 return step;
44 } 45 }
46
47 static PyObject* range_compute_length(PyObject *start,
48 PyObject *stop, PyObject *step);
GvR 2008/05/02 13:52:47 This line is indented one space too many.
45 49
46 /* XXX(nnorwitz): should we error check if the user passes any empty ranges? 50 /* XXX(nnorwitz): should we error check if the user passes any empty ranges?
47 range(-10) 51 range(-10)
48 range(0, -5) 52 range(0, -5)
49 range(0, 5, -1) 53 range(0, 5, -1)
50 */ 54 */
51 static PyObject * 55 static PyObject *
52 range_new(PyTypeObject *type, PyObject *args, PyObject *kw) 56 range_new(PyTypeObject *type, PyObject *args, PyObject *kw)
53 { 57 {
54 rangeobject *obj = NULL; 58 rangeobject *obj = NULL;
55 PyObject *start = NULL, *stop = NULL, *step = NULL; 59 PyObject *start = NULL, *stop = NULL, *step = NULL, *length = NULL;
56 60
57 if (!_PyArg_NoKeywords("range()", kw)) 61 if (!_PyArg_NoKeywords("range()", kw))
58 return NULL; 62 return NULL;
59 63
60 if (PyTuple_Size(args) <= 1) { 64 if (PyTuple_Size(args) <= 1) {
61 if (!PyArg_UnpackTuple(args, "range", 1, 1, &stop)) 65 if (!PyArg_UnpackTuple(args, "range", 1, 1, &stop))
62 goto Fail; 66 goto Fail;
63 stop = PyNumber_Index(stop); 67 stop = PyNumber_Index(stop);
64 if (!stop) 68 if (!stop)
65 goto Fail; 69 goto Fail;
66 start = PyLong_FromLong(0); 70 start = PyLong_FromLong(0);
67 step = PyLong_FromLong(1); 71 step = PyLong_FromLong(1);
68 if (!start || !step) 72 if (!start || !step)
69 goto Fail; 73 goto Fail;
70 } 74 }
71 else { 75 else {
72 if (!PyArg_UnpackTuple(args, "range", 2, 3, 76 if (!PyArg_UnpackTuple(args, "range", 2, 3,
73 &start, &stop, &step)) 77 &start, &stop, &step))
74 goto Fail; 78 goto Fail;
75 79
76 /* Convert borrowed refs to owned refs */ 80 /* Convert borrowed refs to owned refs */
77 start = PyNumber_Index(start); 81 start = PyNumber_Index(start);
78 stop = PyNumber_Index(stop); 82 stop = PyNumber_Index(stop);
79 step = validate_step(step); 83 step = validate_step(step);
80 if (!start || !stop || !step) 84 if (!start || !stop || !step)
81 goto Fail; 85 goto Fail;
82 } 86 }
83 87
88 length = range_compute_length(start, stop, step);
89 if (length == NULL)
90 goto Fail;
84 obj = PyObject_New(rangeobject, &PyRange_Type); 91 obj = PyObject_New(rangeobject, &PyRange_Type);
85 if (obj == NULL) 92 if (obj == NULL)
86 goto Fail; 93 goto Fail;
87 obj->start = start; 94 obj->start = start;
88 obj->stop = stop; 95 obj->stop = stop;
89 obj->step = step; 96 obj->step = step;
97 obj->length = length;
90 return (PyObject *) obj; 98 return (PyObject *) obj;
91 99
92 Fail: 100 Fail:
93 Py_XDECREF(start); 101 Py_XDECREF(start);
94 Py_XDECREF(stop); 102 Py_XDECREF(stop);
95 Py_XDECREF(step); 103 Py_XDECREF(step);
104 Py_XDECREF(length);
96 return NULL; 105 return NULL;
97 } 106 }
98 107
99 PyDoc_STRVAR(range_doc, 108 PyDoc_STRVAR(range_doc,
100 "range([start,] stop[, step]) -> range object\n\ 109 "range([start,] stop[, step]) -> range object\n\
101 \n\ 110 \n\
102 Returns an iterator that generates the numbers in the range on demand."); 111 Returns a virtual sequence of numbers from start to stop by step.");
GvR 2008/05/02 13:52:47 I really don't want to use the word sequence here.
103 112
104 static void 113 static void
105 range_dealloc(rangeobject *r) 114 range_dealloc(rangeobject *r)
106 { 115 {
107 Py_DECREF(r->start); 116 Py_DECREF(r->start);
108 Py_DECREF(r->stop); 117 Py_DECREF(r->stop);
109 Py_DECREF(r->step); 118 Py_DECREF(r->step);
119 Py_DECREF(r->length);
110 PyObject_Del(r); 120 PyObject_Del(r);
111 } 121 }
112 122
113 /* Return number of items in range (lo, hi, step), when arguments are 123 /* Return number of items in range (lo, hi, step), when arguments are
114 * PyInt or PyLong objects. step > 0 required. Return a value < 0 if 124 * PyInt or PyLong objects. step > 0 required. Return a value < 0 if
115 * & only if the true value is too large to fit in a signed long. 125 * & only if the true value is too large to fit in a signed long.
116 * Arguments MUST return 1 with either PyLong_Check() or 126 * Arguments MUST return 1 with either PyLong_Check() or
117 * PyLong_Check(). Return -1 when there is an error. 127 * PyLong_Check(). Return -1 when there is an error.
GvR 2008/05/02 13:52:47 Not your fault, but this comment still references
118 */ 128 */
119 static PyObject* 129 static PyObject *
120 range_length_obj(rangeobject *r) 130 range_compute_length(PyObject *start, PyObject *stop, PyObject *step)
121 { 131 {
122 /* ------------------------------------------------------------- 132 /* -------------------------------------------------------------
123 Algorithm is equal to that of get_len_of_range(), but it operates 133 Algorithm is equal to that of get_len_of_range(), but it operates
124 on PyObjects (which are assumed to be PyLong or PyInt objects). 134 on PyObjects (which are assumed to be PyLong or PyInt objects).
125 ---------------------------------------------------------------*/ 135 ---------------------------------------------------------------*/
126 int cmp_result, cmp_call; 136 int cmp_result, cmp_call;
127 PyObject *lo, *hi; 137 PyObject *lo, *hi;
128 PyObject *step = NULL;
129 PyObject *diff = NULL; 138 PyObject *diff = NULL;
130 PyObject *one = NULL; 139 PyObject *one = NULL;
131 PyObject *tmp1 = NULL, *tmp2 = NULL, *result; 140 PyObject *tmp1 = NULL, *tmp2 = NULL, *result;
132 /* holds sub-expression evaluations */ 141 /* holds sub-expression evaluations */
133 142
134 PyObject *zero = PyLong_FromLong(0); 143 PyObject *zero = PyLong_FromLong(0);
135 if (zero == NULL) 144 if (zero == NULL)
136 return NULL; 145 return NULL;
137 cmp_call = PyObject_Cmp(r->step, zero, &cmp_result); 146 cmp_call = PyObject_Cmp(step, zero, &cmp_result);
138 Py_DECREF(zero); 147 Py_DECREF(zero);
139 if (cmp_call == -1) 148 if (cmp_call == -1)
140 return NULL; 149 return NULL;
141 150
142 assert(cmp_result != 0); 151 assert(cmp_result != 0);
143 if (cmp_result > 0) { 152 if (cmp_result > 0) {
144 lo = r->start; 153 lo = start;
145 hi = r->stop; 154 hi = stop;
146 step = r->step;
147 Py_INCREF(step); 155 Py_INCREF(step);
148 } else { 156 } else {
149 lo = r->stop; 157 lo = stop;
150 hi = r->start; 158 hi = start;
151 step = PyNumber_Negative(r->step); 159 step = PyNumber_Negative(step);
152 if (!step) 160 if (!step)
153 return NULL; 161 goto Fail;
154 } 162 }
155 163
156 /* if (lo >= hi), return length of 0. */ 164 /* if (lo >= hi), return length of 0. */
157 if (PyObject_Compare(lo, hi) >= 0) { 165 if (PyObject_Compare(lo, hi) >= 0) {
158 Py_XDECREF(step); 166 Py_XDECREF(step);
159 return PyLong_FromLong(0); 167 return PyLong_FromLong(0);
160 } 168 }
161 169
162 if ((one = PyLong_FromLong(1L)) == NULL) 170 if ((one = PyLong_FromLong(1L)) == NULL)
163 goto Fail; 171 goto Fail;
164 172
165 if ((tmp1 = PyNumber_Subtract(hi, lo)) == NULL) 173 if ((tmp1 = PyNumber_Subtract(hi, lo)) == NULL)
166 goto Fail; 174 goto Fail;
167 175
168 if ((diff = PyNumber_Subtract(tmp1, one)) == NULL) 176 if ((diff = PyNumber_Subtract(tmp1, one)) == NULL)
169 goto Fail; 177 goto Fail;
170 178
171 if ((tmp2 = PyNumber_FloorDivide(diff, step)) == NULL) 179 if ((tmp2 = PyNumber_FloorDivide(diff, step)) == NULL)
172 goto Fail; 180 goto Fail;
173 181
174 if ((result = PyNumber_Add(tmp2, one)) == NULL) 182 if ((result = PyNumber_Add(tmp2, one)) == NULL)
175 goto Fail; 183 goto Fail;
176 184
177 Py_DECREF(tmp2); 185 Py_DECREF(tmp2);
178 Py_DECREF(diff); 186 Py_DECREF(diff);
179 Py_DECREF(step); 187 Py_DECREF(step);
180 Py_DECREF(tmp1); 188 Py_DECREF(tmp1);
181 Py_DECREF(one); 189 Py_DECREF(one);
182 return result; 190 return result;
183 191
184 Fail: 192 Fail:
185 Py_XDECREF(tmp2); 193 Py_XDECREF(tmp2);
186 Py_XDECREF(diff); 194 Py_XDECREF(diff);
187 Py_XDECREF(step); 195 Py_XDECREF(step);
188 Py_XDECREF(tmp1); 196 Py_XDECREF(tmp1);
189 Py_XDECREF(one); 197 Py_XDECREF(one);
190 return NULL; 198 return NULL;
191 } 199 }
192 200
193 static Py_ssize_t 201 static Py_ssize_t
194 range_length(rangeobject *r) 202 range_length(rangeobject *r)
195 { 203 {
196 PyObject *len = range_length_obj(r); 204 return PyLong_AsSsize_t(r->length);
197 Py_ssize_t result = -1;
198 if (len) {
199 result = PyLong_AsSsize_t(len);
200 Py_DECREF(len);
201 }
202 return result;
203 } 205 }
204 206
205 /* range(...)[x] is necessary for: seq[:] = range(...) */
206
207 static PyObject *
208 range_item(rangeobject *r, Py_ssize_t i)
209 {
210 Py_ssize_t len = range_length(r);
211 PyObject *rem, *incr, *result;
212
213 /* XXX(nnorwitz): should negative indices be supported? */
214 /* XXX(nnorwitz): should support range[x] where x > PY_SSIZE_T_MAX? */
215 if (i < 0 || i >= len) {
216 if (!PyErr_Occurred())
217 PyErr_SetString(PyExc_IndexError,
218 "range object index out of range");
219 return NULL;
220 }
221
222 /* XXX(nnorwitz): optimize for short ints. */
223 rem = PyLong_FromSsize_t(i);
224 if (!rem)
225 return NULL;
226 incr = PyNumber_Multiply(rem, r->step);
227 Py_DECREF(rem);
228 if (!incr)
229 return NULL;
230 result = PyNumber_Add(r->start, incr);
231 Py_DECREF(incr);
232 return result;
233 }
234 207
235 static PyObject * 208 static PyObject *
236 range_repr(rangeobject *r) 209 range_repr(rangeobject *r)
237 { 210 {
238 Py_ssize_t istep; 211 Py_ssize_t istep;
239 212
240 /* Check for special case values for printing. We don't always 213 /* Check for special case values for printing. We don't always
241 need the step value. We don't care about errors 214 need the step value. We don't care about errors
242 (it means overflow), so clear the errors. */ 215 (it means overflow), so clear the errors. */
243 istep = PyNumber_AsSsize_t(r->step, NULL); 216 istep = PyNumber_AsSsize_t(r->step, NULL);
244 if (istep != 1 || (istep == -1 && PyErr_Occurred())) { 217 if (istep != 1 || (istep == -1 && PyErr_Occurred())) {
245 PyErr_Clear(); 218 PyErr_Clear();
246 } 219 }
247 220
248 if (istep == 1) 221 if (istep == 1)
249 return PyUnicode_FromFormat("range(%R, %R)", r->start, r->stop); 222 return PyUnicode_FromFormat("range(%R, %R)", r->start, r->stop);
250 else 223 else
251 return PyUnicode_FromFormat("range(%R, %R, %R)", 224 return PyUnicode_FromFormat("range(%R, %R, %R)",
252 r->start, r->stop, r->step); 225 r->start, r->stop, r->step);
253 } 226 }
254 227
228 static PyObject *
229 range_getstart(rangeobject *obj)
230 {
231 return obj->start;
232 }
233
234 static PyObject *
235 range_getstop(rangeobject *obj)
236 {
237 return obj->stop;
238 }
239
240 static PyObject *
241 range_getstep(rangeobject *obj)
242 {
243 return obj->step;
244 }
245
246 static PyGetSetDef range_getset[] = {
247 {"start", (getter)range_getstart, NULL, "The start of the range"},
248 {"stop", (getter)range_getstop, NULL, "Where the range stops."},
249 {"step", (getter)range_getstep, NULL, "How much the range jumps."},
250 {0},
251 };
252
255 static PySequenceMethods range_as_sequence = { 253 static PySequenceMethods range_as_sequence = {
256 (lenfunc)range_length, /* sq_length */ 254 (lenfunc)range_length, /* sq_length */
GvR 2008/05/02 13:52:47 The latest discussion on the list suggests to remo
257 0, /* sq_concat */ 255 0, /* sq_concat */
258 0, /* sq_repeat */ 256 0, /* sq_repeat */
259 (ssizeargfunc)range_item, /* sq_item */ 257 0, /* sq_item */
260 0, /* sq_slice */ 258 0, /* sq_slice */
259 0, /* sq_ass_item */
260 0, /* sq_ass_slice */
261 0, /* sq_contains */
261 }; 262 };
262 263
263 static PyObject * range_iter(PyObject *seq); 264 static PyObject * range_iter(PyObject *seq);
264 static PyObject * range_reverse(PyObject *seq); 265 static PyObject * range_reverse(PyObject *seq);
265 266
266 PyDoc_STRVAR(reverse_doc, 267 PyDoc_STRVAR(reverse_doc,
267 "Returns a reverse iterator."); 268 "Returns a reverse iterator.");
268 269
269 static PyMethodDef range_methods[] = { 270 static PyMethodDef range_methods[] = {
270 {"__reversed__", (PyCFunction)range_reverse, METH_NOARGS, 271 {"__reversed__", (PyCFunction)range_reverse, METH_NOARGS,
271 reverse_doc}, 272 reverse_doc},
272 {NULL, NULL} /* sentinel */ 273 {NULL, NULL} /* sentinel */
273 }; 274 };
274 275
275 PyTypeObject PyRange_Type = { 276 PyTypeObject PyRange_Type = {
276 PyVarObject_HEAD_INIT(&PyType_Type, 0) 277 PyVarObject_HEAD_INIT(&PyType_Type, 0)
277 "range", /* Name of this type */ 278 "range", /* Name of this type */
278 sizeof(rangeobject), /* Basic object size */ 279 sizeof(rangeobject), /* Basic object size */
279 0, /* Item size for varobject */ 280 0, /* Item size for varobject */
280 (destructor)range_dealloc, /* tp_dealloc */ 281 (destructor)range_dealloc, /* tp_dealloc */
281 0, /* tp_print */ 282 0, /* tp_print */
282 0, /* tp_getattr */ 283 0, /* tp_getattr */
283 0, /* tp_setattr */ 284 0, /* tp_setattr */
284 0, /* tp_compare */ 285 0, /* tp_compare */
285 (reprfunc)range_repr, /* tp_repr */ 286 (reprfunc)range_repr, /* tp_repr */
286 0, /* tp_as_number */ 287 0, /* tp_as_number */
287 &range_as_sequence, /* tp_as_sequence */ 288 &range_as_sequence, /* tp_as_sequence */
288 0, /* tp_as_mapping */ 289 0, /* tp_as_mapping */
289 0, /* tp_hash */ 290 0, /* tp_hash */
290 0, /* tp_call */ 291 0, /* tp_call */
291 0, /* tp_str */ 292 0, /* tp_str */
292 PyObject_GenericGetAttr, /* tp_getattro */ 293 PyObject_GenericGetAttr, /* tp_getattro */
293 0, /* tp_setattro */ 294 0, /* tp_setattro */
294 0, /* tp_as_buffer */ 295 0, /* tp_as_buffer */
295 Py_TPFLAGS_DEFAULT, /* tp_flags */ 296 Py_TPFLAGS_DEFAULT, /* tp_flags */
296 range_doc, /* tp_doc */ 297 range_doc, /* tp_doc */
297 0, /* tp_traverse */ 298 0, /* tp_traverse */
298 0, /* tp_clear */ 299 0, /* tp_clear */
299 0, /* tp_richcompare */ 300 0, /* tp_richcompare */
300 0, /* tp_weaklistoffset */ 301 0, /* tp_weaklistoffset */
301 range_iter, /* tp_iter */ 302 range_iter, /* tp_iter */
302 0, /* tp_iternext */ 303 0, /* tp_iternext */
303 range_methods, /* tp_methods */ 304 range_methods, /* tp_methods */
304 0, /* tp_members */ 305 0, /* tp_members */
305 0, »»/* tp_getset */ 306 range_getset,»»/* tp_getset */
GvR 2008/05/02 13:52:47 Please use spaces to indent the comment.
306 0, /* tp_base */ 307 0, /* tp_base */
307 0, /* tp_dict */ 308 0, /* tp_dict */
308 0, /* tp_descr_get */ 309 0, /* tp_descr_get */
309 0, /* tp_descr_set */ 310 0, /* tp_descr_set */
310 0, /* tp_dictoffset */ 311 0, /* tp_dictoffset */
311 0, /* tp_init */ 312 0, /* tp_init */
312 0, /* tp_alloc */ 313 0, /* tp_alloc */
313 range_new, /* tp_new */ 314 range_new, /* tp_new */
314 }; 315 };
315 316
316 /*********************** range Iterator **************************/ 317 /*********************** range Iterator **************************/
317 318
318 /* There are 2 types of iterators, one for C longs, the other for 319 /* There are 2 types of iterators, one for C longs, the other for
319 Python longs (ie, PyObjects). This should make iteration fast 320 Python longs (ie, PyObjects). This should make iteration fast
320 in the normal case, but possible for any numeric value. 321 in the normal case, but possible for any numeric value.
321 */ 322 */
322 323
323 typedef struct { 324 typedef struct {
324 PyObject_HEAD 325 PyObject_HEAD
325 long index; 326 long index;
326 long start; 327 long start;
327 long step; 328 long step;
328 long len; 329 long len;
329 } rangeiterobject; 330 } rangeiterobject;
330 331
331 static PyObject * 332 static PyObject *
332 rangeiter_next(rangeiterobject *r) 333 rangeiter_next(rangeiterobject *r)
333 { 334 {
334 if (r->index < r->len) 335 if (r->index < r->len)
335 return PyLong_FromLong(r->start + (r->index++) * r->step); 336 return PyLong_FromLong(r->start + (r->index++) * r->step);
336 return NULL; 337 return NULL;
337 } 338 }
338 339
339 static PyObject * 340 static PyObject *
340 rangeiter_len(rangeiterobject *r) 341 rangeiter_len(rangeiterobject *r)
341 { 342 {
342 return PyLong_FromLong(r->len - r->index); 343 return PyLong_FromLong(r->len - r->index);
343 } 344 }
344 345
345 typedef struct { 346 typedef struct {
346 PyObject_HEAD 347 PyObject_HEAD
347 PyObject *index; 348 PyObject *index;
348 PyObject *start; 349 PyObject *start;
349 PyObject *step; 350 PyObject *step;
350 PyObject *len; 351 PyObject *len;
351 } longrangeiterobject; 352 } longrangeiterobject;
352 353
353 static PyObject * 354 static PyObject *
354 longrangeiter_len(longrangeiterobject *r, PyObject *no_args) 355 longrangeiter_len(longrangeiterobject *r, PyObject *no_args)
355 { 356 {
(...skipping 244 matching lines...) Show 10 above Show 10 below
600 it->index = PyLong_FromLong(0); 601 it->index = PyLong_FromLong(0);
601 if (!it->index) 602 if (!it->index)
602 goto create_failure; 603 goto create_failure;
603 604
604 return (PyObject *)it; 605 return (PyObject *)it;
605 606
606 create_failure: 607 create_failure:
607 Py_DECREF(it); 608 Py_DECREF(it);
608 return NULL; 609 return NULL;
609 } 610 }
610 611
611 static PyObject * 612 static PyObject *
612 range_reverse(PyObject *seq) 613 range_reverse(PyObject *seq)
613 { 614 {
614 rangeobject *range = (rangeobject*) seq; 615 rangeobject *range = (rangeobject*) seq;
615 longrangeiterobject *it; 616 longrangeiterobject *it;
616 PyObject *one, *sum, *diff, *len = NULL, *product; 617 PyObject *one, *sum, *diff, *len = NULL, *product;
617 long lstart, lstop, lstep; 618 long lstart, lstop, lstep;
618 619
619 /* XXX(nnorwitz): do the calc for the new start/stop first, 620 /* XXX(nnorwitz): do the calc for the new start/stop first,
620 then if they fit, call the proper iter()? 621 then if they fit, call the proper iter()?
621 */ 622 */
622 assert(PyRange_Check(seq)); 623 assert(PyRange_Check(seq));
623 624
624 /* If all three fields convert to long, use the int version */ 625 /* If all three fields convert to long, use the int version */
625 lstart = PyLong_AsLong(range->start); 626 lstart = PyLong_AsLong(range->start);
626 if (lstart != -1 || !PyErr_Occurred()) { 627 if (lstart != -1 || !PyErr_Occurred()) {
627 lstop = PyLong_AsLong(range->stop); 628 lstop = PyLong_AsLong(range->stop);
628 if (lstop != -1 || !PyErr_Occurred()) { 629 if (lstop != -1 || !PyErr_Occurred()) {
629 lstep = PyLong_AsLong(range->step); 630 lstep = PyLong_AsLong(range->step);
630 if (lstep != -1 || !PyErr_Occurred()) { 631 if (lstep != -1 || !PyErr_Occurred()) {
631 /* XXX(nnorwitz): need to check for overflow and simplify. */ 632 /* XXX(nnorwitz): need to check for overflow and simplify. */
632 long len = get_len_of_range(lstart, lstop, lstep); 633 long len = get_len_of_range(lstart, lstop, lstep);
633 long new_start = lstart + (len - 1) * lstep; 634 long new_start = lstart + (len - 1) * lstep;
634 long new_stop = lstart; 635 long new_stop = lstart;
635 if (lstep > 0) 636 if (lstep > 0)
636 new_stop -= 1; 637 new_stop -= 1;
637 else 638 else
638 new_stop += 1; 639 new_stop += 1;
639 return int_range_iter(new_start, new_stop, -lstep); 640 return int_range_iter(new_start, new_stop, -lstep);
640 } 641 }
641 } 642 }
642 } 643 }
643 PyErr_Clear(); 644 PyErr_Clear();
644 645
645 it = PyObject_New(longrangeiterobject, &PyLongRangeIter_Type); 646 it = PyObject_New(longrangeiterobject, &PyLongRangeIter_Type);
646 if (it == NULL) 647 if (it == NULL)
647 return NULL; 648 return NULL;
648