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

Delta Between Two Patch Sets: Objects/rangeobject.c

Issue 602: range: lean and mean (Closed) SVN Base: http://svn.python.org/view/*checkout*/python/branches/py3k/
Left Patch Set: use PyMemberDef Created 4 months, 1 week ago , Downloaded from: http://bugs.python.org/file10155/range_lean_and_mean2.patch
Right Patch Set: __len__ is back! Created 4 months, 1 week ago
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
Left: Side by side diff | Download
Right: Side by side diff | Download
LEFTRIGHT
1 /* Range object implementation */ 1 /* Range object implementation */
2 2
3 #include "Python.h" 3 #include "Python.h"
4 #include "structmember.h" 4 #include "structmember.h"
5 5
6 /* Support objects whose length is > PY_SSIZE_T_MAX. 6 /* Support objects whose length is > PY_SSIZE_T_MAX.
7 7
8 This could be sped up for small PyLongs if they fit in an Py_ssize_t. 8 This could be sped up for small PyLongs if they fit in an Py_ssize_t.
9 This only matters on Win64. Though we could use PY_LONG_LONG which 9 This only matters on Win64. Though we could use PY_LONG_LONG which
10 would presumably help perf. 10 would presumably help perf.
11 */ 11 */
12 12
13 typedef struct { 13 typedef struct {
14 PyObject_HEAD 14 PyObject_HEAD
15 PyObject *start; 15 PyObject *start;
16 PyObject *stop; 16 PyObject *stop;
17 PyObject *step; 17 PyObject *step;
18 PyObject *length; 18 PyObject *length;
19 } rangeobject; 19 } rangeobject;
20 20
21 /* Helper function for validating step. Always returns a new reference or 21 /* Helper function for validating step. Always returns a new reference or
22 NULL on error. 22 NULL on error.
23 */ 23 */
24 static PyObject * 24 static PyObject *
25 validate_step(PyObject *step) 25 validate_step(PyObject *step)
26 { 26 {
27 /* No step specified, use a step of 1. */ 27 /* No step specified, use a step of 1. */
28 if (!step) 28 if (!step)
29 return PyLong_FromLong(1); 29 return PyLong_FromLong(1);
30 30
31 step = PyNumber_Index(step); 31 step = PyNumber_Index(step);
32 if (step) { 32 if (step) {
33 Py_ssize_t istep = PyNumber_AsSsize_t(step, NULL); 33 Py_ssize_t istep = PyNumber_AsSsize_t(step, NULL);
34 if (istep == -1 && PyErr_Occurred()) { 34 if (istep == -1 && PyErr_Occurred()) {
35 /* Ignore OverflowError, we know the value isn't 0. */ 35 /* Ignore OverflowError, we know the value isn't 0. */
36 PyErr_Clear(); 36 PyErr_Clear();
37 } 37 }
38 else if (istep == 0) { 38 else if (istep == 0) {
39 PyErr_SetString(PyExc_ValueError, 39 PyErr_SetString(PyExc_ValueError,
40 "range() arg 3 must not be zero"); 40 "range() arg 3 must not be zero");
41 Py_CLEAR(step); 41 Py_CLEAR(step);
42 } 42 }
43 } 43 }
44 44
45 return step; 45 return step;
46 } 46 }
47 47
48 static PyObject* range_compute_length(PyObject *start, 48 static PyObject* range_compute_length(PyObject *start,
49 PyObject *stop, PyObject *step); 49 PyObject *stop, PyObject *step);
50 50
51 /* XXX(nnorwitz): should we error check if the user passes any empty ranges? 51 /* XXX(nnorwitz): should we error check if the user passes any empty ranges?
52 range(-10) 52 range(-10)
53 range(0, -5) 53 range(0, -5)
54 range(0, 5, -1) 54 range(0, 5, -1)
55 */ 55 */
56 static PyObject * 56 static PyObject *
57 range_new(PyTypeObject *type, PyObject *args, PyObject *kw) 57 range_new(PyTypeObject *type, PyObject *args, PyObject *kw)
58 { 58 {
59 rangeobject *obj = NULL; 59 rangeobject *obj = NULL;
60 PyObject *start = NULL, *stop = NULL, *step = NULL, *length = NULL; 60 PyObject *start = NULL, *stop = NULL, *step = NULL, *length = NULL;
61 61
62 if (!_PyArg_NoKeywords("range()", kw)) 62 if (!_PyArg_NoKeywords("range()", kw))
63 return NULL; 63 return NULL;
64 64
65 if (PyTuple_Size(args) <= 1) { 65 if (PyTuple_Size(args) <= 1) {
66 if (!PyArg_UnpackTuple(args, "range", 1, 1, &stop)) 66 if (!PyArg_UnpackTuple(args, "range", 1, 1, &stop))
67 goto Fail; 67 goto Fail;
68 stop = PyNumber_Index(stop); 68 stop = PyNumber_Index(stop);
69 if (!stop) 69 if (!stop)
70 goto Fail; 70 goto Fail;
71 start = PyLong_FromLong(0); 71 start = PyLong_FromLong(0);
72 step = PyLong_FromLong(1); 72 step = PyLong_FromLong(1);
73 if (!start || !step) 73 if (!start || !step)
74 goto Fail; 74 goto Fail;
75 } 75 }
76 else { 76 else {
77 if (!PyArg_UnpackTuple(args, "range", 2, 3, 77 if (!PyArg_UnpackTuple(args, "range", 2, 3,
78 &start, &stop, &step)) 78 &start, &stop, &step))
79 goto Fail; 79 goto Fail;
80 80
81 /* Convert borrowed refs to owned refs */ 81 /* Convert borrowed refs to owned refs */
82 start = PyNumber_Index(start); 82 start = PyNumber_Index(start);
83 stop = PyNumber_Index(stop); 83 stop = PyNumber_Index(stop);
84 step = validate_step(step); 84 step = validate_step(step);
85 if (!start || !stop || !step) 85 if (!start || !stop || !step)
86 goto Fail; 86 goto Fail;
87 } 87 }
88 88
89 length = range_compute_length(start, stop, step); 89 length = range_compute_length(start, stop, step);
90 if (length == NULL) 90 if (length == NULL)
91 goto Fail; 91 goto Fail;
92 obj = PyObject_New(rangeobject, &PyRange_Type); 92 obj = PyObject_New(rangeobject, &PyRange_Type);
93 if (obj == NULL) 93 if (obj == NULL)
94 goto Fail; 94 goto Fail;
95 obj->start = start; 95 obj->start = start;
96 obj->stop = stop; 96 obj->stop = stop;
97 obj->step = step; 97 obj->step = step;
98 obj->length = length; 98 obj->length = length;
99 return (PyObject *) obj; 99 return (PyObject *) obj;
100 100
101 Fail: 101 Fail:
102 Py_XDECREF(start); 102 Py_XDECREF(start);
103 Py_XDECREF(stop); 103 Py_XDECREF(stop);
104 Py_XDECREF(step); 104 Py_XDECREF(step);
105 Py_XDECREF(length); 105 Py_XDECREF(length);
106 return NULL; 106 return NULL;
107 } 107 }
108 108
109 PyDoc_STRVAR(range_doc, 109 PyDoc_STRVAR(range_doc,
110 "range([start,] stop[, step]) -> range object\n\ 110 "range([start,] stop[, step]) -> range object\n\
111 \n\ 111 \n\
112 Returns a virtual sequence of numbers from start to stop by step."); 112 Return an arithmetic progression of numbers from start "
113 "to stop (exclusive) by step.");
113 114
114 static void 115 static void
115 range_dealloc(rangeobject *r) 116 range_dealloc(rangeobject *r)
116 { 117 {
117 Py_DECREF(r->start); 118 Py_DECREF(r->start);
118 Py_DECREF(r->stop); 119 Py_DECREF(r->stop);
119 Py_DECREF(r->step); 120 Py_DECREF(r->step);
120 Py_DECREF(r->length); 121 Py_DECREF(r->length);
121 PyObject_Del(r); 122 PyObject_Del(r);
122 } 123 }
123 124
124 /* Return number of items in range (lo, hi, step), when arguments are
125 * PyInt or PyLong objects. step > 0 required. Return a value < 0 if
126 * & only if the true value is too large to fit in a signed long.
127 * Arguments MUST return 1 with either PyLong_Check() or
128 * PyLong_Check(). Return -1 when there is an error.
129 */
130 static PyObject * 125 static PyObject *
131 range_compute_length(PyObject *start, PyObject *stop, PyObject *step) 126 range_compute_length(PyObject *start, PyObject *stop, PyObject *step)
132 { 127 {
133 /* ------------------------------------------------------------- 128 /* -------------------------------------------------------------
134 Algorithm is equal to that of get_len_of_range(), but it operates 129 Algorithm is equal to that of get_len_of_range(), but it operates
135 on PyObjects (which are assumed to be PyLong or PyInt objects). 130 on PyObjects (which are assumed to be PyLong or PyInt objects).
136 ---------------------------------------------------------------*/ 131 ---------------------------------------------------------------*/
137 int cmp_result, cmp_call; 132 int cmp_result, cmp_call;
138 PyObject *lo, *hi; 133 PyObject *lo, *hi;
139 PyObject *diff = NULL; 134 PyObject *diff = NULL;
140 PyObject *one = NULL; 135 PyObject *one = NULL;
141 PyObject *tmp1 = NULL, *tmp2 = NULL, *result; 136 PyObject *tmp1 = NULL, *tmp2 = NULL, *result;
142 /* holds sub-expression evaluations */ 137 /* holds sub-expression evaluations */
143 138
144 PyObject *zero = PyLong_FromLong(0); 139 PyObject *zero = PyLong_FromLong(0);
145 if (zero == NULL) 140 if (zero == NULL)
146 return NULL; 141 return NULL;
147 cmp_call = PyObject_Cmp(step, zero, &cmp_result); 142 cmp_call = PyObject_Cmp(step, zero, &cmp_result);
148 Py_DECREF(zero); 143 Py_DECREF(zero);
149 if (cmp_call == -1) 144 if (cmp_call == -1)
150 return NULL; 145 return NULL;
151 146
152 assert(cmp_result != 0); 147 assert(cmp_result != 0);
153 if (cmp_result > 0) { 148 if (cmp_result > 0) {
154 lo = start; 149 lo = start;
155 hi = stop; 150 hi = stop;
156 Py_INCREF(step); 151 Py_INCREF(step);
157 } else { 152 } else {
158 lo = stop; 153 lo = stop;
159 hi = start; 154 hi = start;
160 step = PyNumber_Negative(step); 155 step = PyNumber_Negative(step);
161 if (!step) 156 if (!step)
162 goto Fail; 157 goto Fail;
163 } 158 }
164 159
165 /* if (lo >= hi), return length of 0. */ 160 /* if (lo >= hi), return length of 0. */
166 if (PyObject_Compare(lo, hi) >= 0) { 161 if (PyObject_Compare(lo, hi) >= 0) {
167 Py_XDECREF(step); 162 Py_XDECREF(step);
168 return PyLong_FromLong(0); 163 return PyLong_FromLong(0);
169 } 164 }
170 165
171 if ((one = PyLong_FromLong(1L)) == NULL) 166 if ((one = PyLong_FromLong(1L)) == NULL)
172 goto Fail; 167 goto Fail;
173 168
174 if ((tmp1 = PyNumber_Subtract(hi, lo)) == NULL) 169 if ((tmp1 = PyNumber_Subtract(hi, lo)) == NULL)
175 goto Fail; 170 goto Fail;
176 171
177 if ((diff = PyNumber_Subtract(tmp1, one)) == NULL) 172 if ((diff = PyNumber_Subtract(tmp1, one)) == NULL)
178 goto Fail; 173 goto Fail;
179 174
180 if ((tmp2 = PyNumber_FloorDivide(diff, step)) == NULL) 175 if ((tmp2 = PyNumber_FloorDivide(diff, step)) == NULL)
181 goto Fail; 176 goto Fail;
182 177
183 if ((result = PyNumber_Add(tmp2, one)) == NULL) 178 if ((result = PyNumber_Add(tmp2, one)) == NULL)
184 goto Fail; 179 goto Fail;
185 180
186 Py_DECREF(tmp2); 181 Py_DECREF(tmp2);
187 Py_DECREF(diff); 182 Py_DECREF(diff);
188 Py_DECREF(step); 183 Py_DECREF(step);
189 Py_DECREF(tmp1); 184 Py_DECREF(tmp1);
190 Py_DECREF(one); 185 Py_DECREF(one);
191 return result; 186 return result;
192 187
193 Fail: 188 Fail:
194 Py_XDECREF(tmp2); 189 Py_XDECREF(tmp2);
195 Py_XDECREF(diff); 190 Py_XDECREF(diff);
196 Py_XDECREF(step); 191 Py_XDECREF(step);
197 Py_XDECREF(tmp1); 192 Py_XDECREF(tmp1);
198 Py_XDECREF(one); 193 Py_XDECREF(one);
199 return NULL; 194 return NULL;
200 } 195 }
201 196
202 static Py_ssize_t 197 static Py_ssize_t
203 range_length(rangeobject *r) 198 range_length(rangeobject *r)
204 { 199 {
205 return PyLong_AsSsize_t(r->length); 200 return PyLong_AsSsize_t(r->length);
206 } 201 }
207 202
208 203
209 static PyObject * 204 static PyObject *
210 range_repr(rangeobject *r) 205 range_repr(rangeobject *r)
211 { 206 {
212 Py_ssize_t istep; 207 Py_ssize_t istep;
213 208
214 /* Check for special case values for printing. We don't always 209 /* Check for special case values for printing. We don't always
215 need the step value. We don't care about errors 210 need the step value. We don't care about errors
216 (it means overflow), so clear the errors. */ 211 (it means overflow), so clear the errors. */
217 istep = PyNumber_AsSsize_t(r->step, NULL); 212 istep = PyNumber_AsSsize_t(r->step, NULL);
218 if (istep != 1 || (istep == -1 && PyErr_Occurred())) { 213 if (istep != 1 || (istep == -1 && PyErr_Occurred())) {
219 PyErr_Clear(); 214 PyErr_Clear();
220 } 215 }
221 216
222 if (istep == 1) 217 if (istep == 1)
223 return PyUnicode_FromFormat("range(%R, %R)", r->start, r->stop); 218 return PyUnicode_FromFormat("range(%R, %R)", r->start, r->stop);
224 else 219 else
225 return PyUnicode_FromFormat("range(%R, %R, %R)", 220 return PyUnicode_FromFormat("range(%R, %R, %R)",
226 r->start, r->stop, r->step); 221 r->start, r->stop, r->step);
227 } 222 }
228 223
229 static PyMemberDef range_members[] = { 224 static PyMemberDef range_members[] = {
230 {"start", T_OBJECT, offsetof(rangeobject, start), READONLY}, 225 {"start", T_OBJECT, offsetof(rangeobject, start), READONLY},
231 {"stop", T_OBJECT, offsetof(rangeobject, stop), READONLY}, 226 {"stop", T_OBJECT, offsetof(rangeobject, stop), READONLY},
232 {"step", T_OBJECT, offsetof(rangeobject, step), READONLY}, 227 {"step", T_OBJECT, offsetof(rangeobject, step), READONLY},
233 {0} 228 {0}
234 }; 229 };
235 230
236 static PySequenceMethods range_as_sequence = {
237 (lenfunc)range_length, /* sq_length */
238 0, /* sq_concat */
239 0, /* sq_repeat */
240 0, /* sq_item */
241 0, /* sq_slice */
242 0, /* sq_ass_item */
243 0, /* sq_ass_slice */
244 0, /* sq_contains */
245 };
246
247 static PyObject * range_iter(PyObject *seq); 231 static PyObject * range_iter(PyObject *seq);
248 static PyObject * range_reverse(PyObject *seq); 232 static PyObject * range_reverse(PyObject *seq);
249 233
250 PyDoc_STRVAR(reverse_doc, 234 PyDoc_STRVAR(reverse_doc,
251 "Returns a reverse iterator."); 235 "Returns a reverse iterator.");
236
237 static PySequenceMethods range_as_sequence = {
238 (lenfunc)range_length, /* sq_length */
239 0, /* sq_concat */
240 0, /* sq_repeat */
241 0, /* sq_item */
242 0, /* sq_slice */
243 0, /* sq_ass_item */
244 0, /* sq_ass_slice */
245 0, /* sq_contains */
246 0, /* sq_inplace_concat */
247 0, /* sq_inplace_repeat */
248 };
252 249
253 static PyMethodDef range_methods[] = { 250 static PyMethodDef range_methods[] = {
254 {"__reversed__", (PyCFunction)range_reverse, METH_NOARGS, 251 {"__reversed__", (PyCFunction)range_reverse, METH_NOARGS,
255 reverse_doc}, 252 reverse_doc},
256 {NULL, NULL} /* sentinel */ 253 {NULL, NULL} /* sentinel */
257 }; 254 };
258 255
259 PyTypeObject PyRange_Type = { 256 PyTypeObject PyRange_Type = {
260 PyVarObject_HEAD_INIT(&PyType_Type, 0) 257 PyVarObject_HEAD_INIT(&PyType_Type, 0)
261 "range", /* Name of this type */ 258 "range", /* Name of this type */
262 sizeof(rangeobject), /* Basic object size */ 259 sizeof(rangeobject), /* Basic object size */
263 0, /* Item size for varobject */ 260 0, /* Item size for varobject */
264 (destructor)range_dealloc, /* tp_dealloc */ 261 (destructor)range_dealloc, /* tp_dealloc */
265 0, /* tp_print */ 262 0, /* tp_print */
266 0, /* tp_getattr */ 263 0, /* tp_getattr */
267 0, /* tp_setattr */ 264 0, /* tp_setattr */
268 0, /* tp_compare */ 265 0, /* tp_compare */
269 (reprfunc)range_repr, /* tp_repr */ 266 (reprfunc)range_repr, /* tp_repr */
270 0, /* tp_as_number */ 267 0, /* tp_as_number */
271 &range_as_sequence, /* tp_as_sequence */ 268 &range_as_sequence, /* tp_as_sequence */
272 0, /* tp_as_mapping */ 269 0, /* tp_as_mapping */
273 0, /* tp_hash */ 270 0, /* tp_hash */
274 0, /* tp_call */ 271 0, /* tp_call */
275 0, /* tp_str */ 272 0, /* tp_str */
276 PyObject_GenericGetAttr, /* tp_getattro */ 273 PyObject_GenericGetAttr, /* tp_getattro */
277 0, /* tp_setattro */ 274 0, /* tp_setattro */
278 0, /* tp_as_buffer */ 275 0, /* tp_as_buffer */
279 Py_TPFLAGS_DEFAULT, /* tp_flags */ 276 Py_TPFLAGS_DEFAULT, /* tp_flags */
280 range_doc, /* tp_doc */ 277 range_doc, /* tp_doc */
281 0, /* tp_traverse */ 278 0, /* tp_traverse */
282 0, /* tp_clear */ 279 0, /* tp_clear */
283 0, /* tp_richcompare */ 280 0, /* tp_richcompare */
284 0, /* tp_weaklistoffset */ 281 0, /* tp_weaklistoffset */
285 range_iter, /* tp_iter */ 282 range_iter, /* tp_iter */
286 0, /* tp_iternext */ 283 0, /* tp_iternext */
287 range_methods, /* tp_methods */ 284 range_methods, /* tp_methods */
288 range_members, /* tp_members */ 285 range_members, /* tp_members */
mvloewis 2008/05/02 20:17:20 Carrying forward from the previous patch set: this
289 0, /* tp_getset */ 286 0, /* tp_getset */
290 0, /* tp_base */ 287 0, /* tp_base */
291 0, /* tp_dict */ 288 0, /* tp_dict */
292 0, /* tp_descr_get */ 289 0, /* tp_descr_get */
293 0, /* tp_descr_set */ 290 0, /* tp_descr_set */
294 0, /* tp_dictoffset */ 291 0, /* tp_dictoffset */
295 0, /* tp_init */ 292 0, /* tp_init */
296 0, /* tp_alloc */ 293 0, /* tp_alloc */
297 range_new, /* tp_new */ 294 range_new, /* tp_new */
298 }; 295 };
299 296
300 /*********************** range Iterator **************************/ 297 /*********************** range Iterator **************************/
301 298
302 /* There are 2 types of iterators, one for C longs, the other for 299 /* There are 2 types of iterators, one for C longs, the other for
303 Python longs (ie, PyObjects). This should make iteration fast 300 Python longs (ie, PyObjects). This should make iteration fast
304 in the normal case, but possible for any numeric value. 301 in the normal case, but possible for any numeric value.
305 */ 302 */
306 303
307 typedef struct { 304 typedef struct {
308 PyObject_HEAD 305 PyObject_HEAD
309 long index; 306 long index;
310 long start; 307 long start;
311 long step; 308 long step;
312 long len; 309 long len;
313 } rangeiterobject; 310 } rangeiterobject;
314 311
315 static PyObject * 312 static PyObject *
316 rangeiter_next(rangeiterobject *r) 313 rangeiter_next(rangeiterobject *r)
317 { 314 {
318 if (r->index < r->len) 315 if (r->index < r->len)
319 return PyLong_FromLong(r->start + (r->index++) * r->step); 316 return PyLong_FromLong(r->start + (r->index++) * r->step);
320 return NULL; 317 return NULL;
321 } 318 }
322 319
323 static PyObject * 320 static PyObject *
324 rangeiter_len(rangeiterobject *r) 321 rangeiter_len(rangeiterobject *r)
325 { 322 {
326 return PyLong_FromLong(r->len - r->index); 323 return PyLong_FromLong(r->len - r->index);
327 } 324 }
328 325
329 typedef struct { 326 typedef struct {
330 PyObject_HEAD 327 PyObject_HEAD
331 PyObject *index; 328 PyObject *index;
332 PyObject *start; 329 PyObject *start;
333 PyObject *step; 330 PyObject *step;
334 PyObject *len; 331 PyObject *length;
335 } longrangeiterobject; 332 } longrangeiterobject;
336 333
337 static PyObject * 334 static PyObject *
338 longrangeiter_len(longrangeiterobject *r, PyObject *no_args) 335 longrangeiter_len(longrangeiterobject *r, PyObject *no_args)
339 { 336 {
340 return PyNumber_Subtract(r->len, r->index); 337 return PyNumber_Subtract(r->length, r->index);
341 } 338 }
342 339
343 static PyObject *rangeiter_new(PyTypeObject *, PyObject *args, PyObject *kw); 340 static PyObject *rangeiter_new(PyTypeObject *, PyObject *args, PyObject *kw);
344 341
345 PyDoc_STRVAR(length_hint_doc, 342 PyDoc_STRVAR(length_hint_doc,
346 "Private method returning an estimate of len(list(it))."); 343 "Private method returning an estimate of len(list(it)).");
347 344
348 static PyMethodDef rangeiter_methods[] = { 345 static PyMethodDef rangeiter_methods[] = {
349 {"__length_hint__", (PyCFunction)rangeiter_len, METH_NOARGS, 346 {"__length_hint__", (PyCFunction)rangeiter_len, METH_NOARGS,
350 length_hint_doc}, 347 length_hint_doc},
351 {NULL, NULL} /* sentinel */ 348 {NULL, NULL} /* sentinel */
352 }; 349 };
353 350
354 PyTypeObject PyRangeIter_Type = { 351 PyTypeObject PyRangeIter_Type = {
355 PyVarObject_HEAD_INIT(&PyType_Type, 0) 352 PyVarObject_HEAD_INIT(&PyType_Type, 0)
356 "range_iterator", /* tp_name */ 353 "range_iterator", /* tp_name */
357 sizeof(rangeiterobject), /* tp_basicsize */ 354 sizeof(rangeiterobject), /* tp_basicsize */
358 0, /* tp_itemsize */ 355 0, /* tp_itemsize */
359 /* methods */ 356 /* methods */
360 (destructor)PyObject_Del, /* tp_dealloc */ 357 (destructor)PyObject_Del, /* tp_dealloc */
361 0, /* tp_print */ 358 0, /* tp_print */
362 0, /* tp_getattr */ 359 0, /* tp_getattr */
363 0, /* tp_setattr */ 360 0, /* tp_setattr */
364 0, /* tp_compare */ 361 0, /* tp_compare */
365 0, /* tp_repr */ 362 0, /* tp_repr */
366 0, /* tp_as_number */ 363 0, /* tp_as_number */
367 0, /* tp_as_sequence */ 364 0, /* tp_as_sequence */
368 0, /* tp_as_mapping */ 365 0, /* tp_as_mapping */
369 0, /* tp_hash */ 366 0, /* tp_hash */
370 0, /* tp_call */ 367 0, /* tp_call */
371 0, /* tp_str */ 368 0, /* tp_str */
372 PyObject_GenericGetAttr, /* tp_getattro */ 369 PyObject_GenericGetAttr, /* tp_getattro */
373 0, /* tp_setattro */ 370 0, /* tp_setattro */
374 0, /* tp_as_buffer */ 371 0, /* tp_as_buffer */
375 Py_TPFLAGS_DEFAULT, /* tp_flags */ 372 Py_TPFLAGS_DEFAULT, /* tp_flags */
376 0, /* tp_doc */ 373 0, /* tp_doc */
377 0, /* tp_traverse */ 374 0, /* tp_traverse */
378 0, /* tp_clear */ 375 0, /* tp_clear */
379 0, /* tp_richcompare */ 376 0, /* tp_richcompare */
380 0, /* tp_weaklistoffset */ 377 0, /* tp_weaklistoffset */
381 PyObject_SelfIter, /* tp_iter */ 378 PyObject_SelfIter, /* tp_iter */
382 (iternextfunc)rangeiter_next, /* tp_iternext */ 379 (iternextfunc)rangeiter_next, /* tp_iternext */
383 rangeiter_methods, /* tp_methods */ 380 rangeiter_methods, /* tp_methods */
384 0, /* tp_members */ 381 0, /* tp_members */
385 0, /* tp_getset */ 382 0, /* tp_getset */
386 0, /* tp_base */ 383 0, /* tp_base */
387 0, /* tp_dict */ 384 0, /* tp_dict */
388 0, /* tp_descr_get */ 385 0, /* tp_descr_get */
389 0, /* tp_descr_set */ 386 0, /* tp_descr_set */
390 0, /* tp_dictoffset */ 387 0, /* tp_dictoffset */
391 0, /* tp_init */ 388 0, /* tp_init */
392 0, /* tp_alloc */ 389 0, /* tp_alloc */
393 rangeiter_new, /* tp_new */ 390 rangeiter_new, /* tp_new */
394 }; 391 };
395 392
396 /* Return number of items in range/xrange (lo, hi, step). step > 0 393 /* Return number of items in range/xrange (lo, hi, step). step > 0
397 * required. Return a value < 0 if & only if the true value is too 394 * required. Return a value < 0 if & only if the true value is too
398 * large to fit in a signed long. 395 * large to fit in a signed long.
399 */ 396 */
400 static long 397 static long
401 get_len_of_range(long lo, long hi, long step) 398 get_len_of_range(long lo, long hi, long step)
402 { 399 {
403 /* ------------------------------------------------------------- 400 /* -------------------------------------------------------------
404 If lo >= hi, the range is empty. 401 If lo >= hi, the range is empty.
405 Else if n values are in the range, the last one is 402 Else if n values are in the range, the last one is
406 lo + (n-1)*step, which must be <= hi-1. Rearranging, 403 lo + (n-1)*step, which must be <= hi-1. Rearranging,
407 n <= (hi - lo - 1)/step + 1, so taking the floor of the RHS gives 404 n <= (hi - lo - 1)/step + 1, so taking the floor of the RHS gives
408 the proper value. Since lo < hi in this case, hi-lo-1 >= 0, so 405 the proper value. Since lo < hi in this case, hi-lo-1 >= 0, so
409 the RHS is non-negative and so truncation is the same as the 406 the RHS is non-negative and so truncation is the same as the
410 floor. Letting M be the largest positive long, the worst case 407 floor. Letting M be the largest positive long, the worst case
411 for the RHS numerator is hi=M, lo=-M-1, and then 408 for the RHS numerator is hi=M, lo=-M-1, and then
412 hi-lo-1 = M-(-M-1)-1 = 2*M. Therefore unsigned long has enough 409 hi-lo-1 = M-(-M-1)-1 = 2*M. Therefore unsigned long has enough
413 precision to compute the RHS exactly. 410 precision to compute the RHS exactly.
414 ---------------------------------------------------------------*/ 411 ---------------------------------------------------------------*/
415 long n = 0; 412 long n = 0;
416 if (lo < hi) { 413 if (lo < hi) {
417 unsigned long uhi = (unsigned long)hi; 414 unsigned long uhi = (unsigned long)hi;
418 unsigned long ulo = (unsigned long)lo; 415 unsigned long ulo = (unsigned long)lo;
419 unsigned long diff = uhi - ulo - 1; 416 unsigned long diff = uhi - ulo - 1;
420 n = (long)(diff / (unsigned long)step + 1); 417 n = (long)(diff / (unsigned long)step + 1);
421 } 418 }
422 return n; 419 return n;
423 } 420 }
424 421
425 static PyObject * 422 static PyObject *
426 int_range_iter(long start, long stop, long step) 423 int_range_iter(long start, long stop, long step)
427 { 424 {
428 rangeiterobject *it = PyObject_New(rangeiterobject, &PyRangeIter_Type); 425 rangeiterobject *it = PyObject_New(rangeiterobject, &PyRangeIter_Type);
429 if (it == NULL) 426 if (it == NULL)
430 return NULL; 427 return NULL;
431 it->start = start; 428 it->start = start;
432 it->step = step; 429 it->step = step;
433 if (step > 0) 430 if (step > 0)