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

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: address more concerns Created 3 months, 3 weeks ago , Downloaded from: http://bugs.python.org/file10183/range_lean_and_mean5.patch
Right Patch Set: use PyMemberDef Created 3 months, 3 weeks ago , Downloaded from: http://bugs.python.org/file10155/range_lean_and_mean2.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:
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 Return an arithmetic progression of numbers from start " 112 Returns a virtual sequence of numbers from start to stop by step.");
113 "to stop (exclusive) by step.");
114 113
115 static void 114 static void
116 range_dealloc(rangeobject *r) 115 range_dealloc(rangeobject *r)
117 { 116 {
118 Py_DECREF(r->start); 117 Py_DECREF(r->start);
119 Py_DECREF(r->stop); 118 Py_DECREF(r->stop);
120 Py_DECREF(r->step); 119 Py_DECREF(r->step);
121 Py_DECREF(r->length); 120 Py_DECREF(r->length);
122 PyObject_Del(r); 121 PyObject_Del(r);
123 } 122 }
124 123
125 /*Return number of items in range (lo, hi, step), when arguments are 124 /* Return number of items in range (lo, hi, step), when arguments are
126 * PyLong objects. step > 0 required. Return a PyLong with the length. 125 * PyInt or PyLong objects. step > 0 required. Return a value < 0 if
127 * Return NULL when there is an error.*/ 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 */
128 static PyObject * 130 static PyObject *
129 range_compute_length(PyObject *start, PyObject *stop, PyObject *step) 131 range_compute_length(PyObject *start, PyObject *stop, PyObject *step)
130 { 132 {
131 /* ------------------------------------------------------------- 133 /* -------------------------------------------------------------
132 Algorithm is equal to that of get_len_of_range(), but it operates 134 Algorithm is equal to that of get_len_of_range(), but it operates
133 on PyObjects (which are assumed to be PyLong or PyInt objects). 135 on PyObjects (which are assumed to be PyLong or PyInt objects).
134 ---------------------------------------------------------------*/ 136 ---------------------------------------------------------------*/
135 int cmp_result, cmp_call; 137 int cmp_result, cmp_call;
136 PyObject *lo, *hi; 138 PyObject *lo, *hi;
137 PyObject *diff = NULL; 139 PyObject *diff = NULL;
138 PyObject *one = NULL; 140 PyObject *one = NULL;
139 PyObject *tmp1 = NULL, *tmp2 = NULL, *result; 141 PyObject *tmp1 = NULL, *tmp2 = NULL, *result;
140 /* holds sub-expression evaluations */ 142 /* holds sub-expression evaluations */
141 143
142 PyObject *zero = PyLong_FromLong(0); 144 PyObject *zero = PyLong_FromLong(0);
143 if (zero == NULL) 145 if (zero == NULL)
144 return NULL; 146 return NULL;
145 cmp_call = PyObject_Cmp(step, zero, &cmp_result); 147 cmp_call = PyObject_Cmp(step, zero, &cmp_result);
146 Py_DECREF(zero); 148 Py_DECREF(zero);
147 if (cmp_call == -1) 149 if (cmp_call == -1)
148 return NULL; 150 return NULL;
149 151
150 assert(cmp_result != 0); 152 assert(cmp_result != 0);
151 if (cmp_result > 0) { 153 if (cmp_result > 0) {
152 lo = start; 154 lo = start;
153 hi = stop; 155 hi = stop;
154 Py_INCREF(step); 156 Py_INCREF(step);
155 } else { 157 } else {
156 lo = stop; 158 lo = stop;
157 hi = start; 159 hi = start;
158 step = PyNumber_Negative(step); 160 step = PyNumber_Negative(step);
159 if (!step) 161 if (!step)
160 goto Fail; 162 goto Fail;
161 } 163 }
162 164
163 /* if (lo >= hi), return length of 0. */ 165 /* if (lo >= hi), return length of 0. */
164 if (PyObject_Compare(lo, hi) >= 0) { 166 if (PyObject_Compare(lo, hi) >= 0) {
165 Py_XDECREF(step); 167 Py_XDECREF(step);
166 return PyLong_FromLong(0); 168 return PyLong_FromLong(0);
167 } 169 }
168 170
169 if ((one = PyLong_FromLong(1L)) == NULL) 171 if ((one = PyLong_FromLong(1L)) == NULL)
170 goto Fail; 172 goto Fail;
171 173
172 if ((tmp1 = PyNumber_Subtract(hi, lo)) == NULL) 174 if ((tmp1 = PyNumber_Subtract(hi, lo)) == NULL)
173 goto Fail; 175 goto Fail;
174 176
175 if ((diff = PyNumber_Subtract(tmp1, one)) == NULL) 177 if ((diff = PyNumber_Subtract(tmp1, one)) == NULL)
176 goto Fail; 178 goto Fail;
177 179
178 if ((tmp2 = PyNumber_FloorDivide(diff, step)) == NULL) 180 if ((tmp2 = PyNumber_FloorDivide(diff, step)) == NULL)
179 goto Fail; 181 goto Fail;
180 182
181 if ((result = PyNumber_Add(tmp2, one)) == NULL) 183 if ((result = PyNumber_Add(tmp2, one)) == NULL)
182 goto Fail; 184 goto Fail;
183 185
184 Py_DECREF(tmp2); 186 Py_DECREF(tmp2);
185 Py_DECREF(diff); 187 Py_DECREF(diff);
186 Py_DECREF(step); 188 Py_DECREF(step);
187 Py_DECREF(tmp1); 189 Py_DECREF(tmp1);
188 Py_DECREF(one); 190 Py_DECREF(one);
189 return result; 191 return result;
190 192
191 Fail: 193 Fail:
192 Py_XDECREF(tmp2); 194 Py_XDECREF(tmp2);
193 Py_XDECREF(diff); 195 Py_XDECREF(diff);
194 Py_XDECREF(step); 196 Py_XDECREF(step);
195 Py_XDECREF(tmp1); 197 Py_XDECREF(tmp1);
196 Py_XDECREF(one); 198 Py_XDECREF(one);
197 return NULL; 199 return NULL;
198 } 200 }
199 201
200 static Py_ssize_t 202 static Py_ssize_t
201 range_length(rangeobject *r) 203 range_length(rangeobject *r)
202 { 204 {
203 return PyLong_AsSsize_t(r->length); 205 return PyLong_AsSsize_t(r->length);
204 } 206 }
205 207
206 208
207 static PyObject * 209 static PyObject *
208 range_repr(rangeobject *r) 210 range_repr(rangeobject *r)
209 { 211 {
210 Py_ssize_t istep; 212 Py_ssize_t istep;
211 213
212 /* Check for special case values for printing. We don't always 214 /* Check for special case values for printing. We don't always
213 need the step value. We don't care about errors 215 need the step value. We don't care about errors
214 (it means overflow), so clear the errors. */ 216 (it means overflow), so clear the errors. */
215 istep = PyNumber_AsSsize_t(r->step, NULL); 217 istep = PyNumber_AsSsize_t(r->step, NULL);
216 if (istep != 1 || (istep == -1 && PyErr_Occurred())) { 218 if (istep != 1 || (istep == -1 && PyErr_Occurred())) {
217 PyErr_Clear(); 219 PyErr_Clear();
218 } 220 }
219 221
220 if (istep == 1) 222 if (istep == 1)
221 return PyUnicode_FromFormat("range(%R, %R)", r->start, r->stop); 223 return PyUnicode_FromFormat("range(%R, %R)", r->start, r->stop);
222 else 224 else
223 return PyUnicode_FromFormat("range(%R, %R, %R)", 225 return PyUnicode_FromFormat("range(%R, %R, %R)",
224 r->start, r->stop, r->step); 226 r->start, r->stop, r->step);
225 } 227 }
226 228
227 static PyMemberDef range_members[] = { 229 static PyMemberDef range_members[] = {
228 {"start", T_OBJECT, offsetof(rangeobject, start), READONLY}, 230 {"start", T_OBJECT, offsetof(rangeobject, start), READONLY},
229 {"stop", T_OBJECT, offsetof(rangeobject, stop), READONLY}, 231 {"stop", T_OBJECT, offsetof(rangeobject, stop), READONLY},
230 {"step", T_OBJECT, offsetof(rangeobject, step), READONLY}, 232 {"step", T_OBJECT, offsetof(rangeobject, step), READONLY},
231 {0} 233 {0}
232 }; 234 };
233 235
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
234 static PyObject * range_iter(PyObject *seq); 247 static PyObject * range_iter(PyObject *seq);
235 static PyObject * range_reverse(PyObject *seq); 248 static PyObject * range_reverse(PyObject *seq);
236 249
237 PyDoc_STRVAR(reverse_doc, 250 PyDoc_STRVAR(reverse_doc,
238 "Returns a reverse iterator."); 251 "Returns a reverse iterator.");
239
240 static PySequenceMethods range_as_sequence = {
241 (lenfunc)range_length, /* sq_length */
242 0, /* sq_concat */
243 0, /* sq_repeat */
244 0, /* sq_item */
245 0, /* sq_slice */
246 0, /* sq_ass_item */
247 0, /* sq_ass_slice */
248 0, /* sq_contains */
249 0, /* sq_inplace_concat */
250 0, /* sq_inplace_repeat */
251 };
252 252
253 static PyMethodDef range_methods[] = { 253 static PyMethodDef range_methods[] = {
254 {"__reversed__", (PyCFunction)range_reverse, METH_NOARGS, 254 {"__reversed__", (PyCFunction)range_reverse, METH_NOARGS,
255 reverse_doc}, 255 reverse_doc},
256 {NULL, NULL} /* sentinel */ 256 {NULL, NULL} /* sentinel */
257 }; 257 };
258 258
259 PyTypeObject PyRange_Type = { 259 PyTypeObject PyRange_Type = {
260 PyVarObject_HEAD_INIT(&PyType_Type, 0) 260 PyVarObject_HEAD_INIT(&PyType_Type, 0)
261 "range", /* Name of this type */ 261 "range", /* Name of this type */
262 sizeof(rangeobject), /* Basic object size */ 262 sizeof(rangeobject), /* Basic object size */
263 0, /* Item size for varobject */ 263 0, /* Item size for varobject */
264 (destructor)range_dealloc, /* tp_dealloc */ 264 (destructor)range_dealloc, /* tp_dealloc */
265 0, /* tp_print */ 265 0, /* tp_print */
266 0, /* tp_getattr */ 266 0, /* tp_getattr */
267 0, /* tp_setattr */ 267 0, /* tp_setattr */
268 0, /* tp_compare */ 268 0, /* tp_compare */
269 (reprfunc)range_repr, /* tp_repr */ 269 (reprfunc)range_repr, /* tp_repr */
270 0, /* tp_as_number */ 270 0, /* tp_as_number */
271 &range_as_sequence, /* tp_as_sequence */ 271 &range_as_sequence, /* tp_as_sequence */
272 0, /* tp_as_mapping */ 272 0, /* tp_as_mapping */
273 0, /* tp_hash */ 273 0, /* tp_hash */
274 0, /* tp_call */ 274 0, /* tp_call */
275 0, /* tp_str */ 275 0, /* tp_str */
276 PyObject_GenericGetAttr, /* tp_getattro */ 276 PyObject_GenericGetAttr, /* tp_getattro */
277 0, /* tp_setattro */ 277 0, /* tp_setattro */
278 0, /* tp_as_buffer */ 278 0, /* tp_as_buffer */
279 Py_TPFLAGS_DEFAULT, /* tp_flags */ 279 Py_TPFLAGS_DEFAULT, /* tp_flags */
280 range_doc, /* tp_doc */ 280 range_doc, /* tp_doc */
281 0, /* tp_traverse */ 281 0, /* tp_traverse */
282 0, /* tp_clear */ 282 0, /* tp_clear */
283 0, /* tp_richcompare */ 283 0, /* tp_richcompare */
284 0, /* tp_weaklistoffset */ 284 0, /* tp_weaklistoffset */
285 range_iter, /* tp_iter */ 285 range_iter, /* tp_iter */
286 0, /* tp_iternext */ 286 0, /* tp_iternext */
287 range_methods, /* tp_methods */ 287 range_methods, /* tp_methods */
288 range_members, /* tp_members */ 288 range_members, /* tp_members */
mvloewis 2008/05/02 20:17:20 Carrying forward from the previous patch set: this
289 0, /* tp_getset */ 289 0, /* tp_getset */
290 0, /* tp_base */ 290 0, /* tp_base */
291 0, /* tp_dict */ 291 0, /* tp_dict */
292 0, /* tp_descr_get */ 292 0, /* tp_descr_get */
293 0, /* tp_descr_set */ 293 0, /* tp_descr_set */
294 0, /* tp_dictoffset */ 294 0, /* tp_dictoffset */
295 0, /* tp_init */ 295 0, /* tp_init */
296 0, /* tp_alloc */ 296 0, /* tp_alloc */
297 range_new, /* tp_new */ 297 range_new, /* tp_new */
298 }; 298 };
299 299
300 /*********************** range Iterator **************************/ 300 /*********************** range Iterator **************************/
301 301
302 /* There are 2 types of iterators, one for C longs, the other for 302 /* There are 2 types of iterators, one for C longs, the other for
303 Python longs (ie, PyObjects). This should make iteration fast 303 Python longs (ie, PyObjects). This should make iteration fast
304 in the normal case, but possible for any numeric value. 304 in the normal case, but possible for any numeric value.
305 */ 305 */
306 306
307 typedef struct { 307 typedef struct {
308 PyObject_HEAD 308 PyObject_HEAD
309 long index; 309 long index;
310 long start; 310 long start;
311 long step; 311 long step;
312 long len; 312 long len;
313 } rangeiterobject; 313 } rangeiterobject;
314 314
315 static PyObject * 315 static PyObject *
316 rangeiter_next(rangeiterobject *r) 316 rangeiter_next(rangeiterobject *r)
317 { 317 {
318 if (r->index < r->len) 318 if (r->index < r->len)
319 return PyLong_FromLong(r->start + (r->index++) * r->step); 319 return PyLong_FromLong(r->start + (r->index++) * r->step);
320 return NULL; 320 return NULL;
321 } 321 }
322 322
323 static PyObject * 323 static PyObject *
324 rangeiter_len(rangeiterobject *r) 324 rangeiter_len(rangeiterobject *r)
325 { 325 {
326 return PyLong_FromLong(r->len - r->index); 326 return PyLong_FromLong(r->len - r->index);
327 } 327 }
328 328
329 typedef struct { 329 typedef struct {
330 PyObject_HEAD 330 PyObject_HEAD
331 PyObject *index; 331 PyObject *index;
332 PyObject *start; 332 PyObject *start;
333 PyObject *step; 333 PyObject *step;
334 PyObject *length; 334 PyObject *len;
335 } longrangeiterobject; 335 } longrangeiterobject;
336 336
337 static PyObject * 337 static PyObject *
338 longrangeiter_len(longrangeiterobject *r, PyObject *no_args) 338 longrangeiter_len(longrangeiterobject *r, PyObject *no_args)
339 { 339 {
340 return PyNumber_Subtract(r->length, r->index); 340 return PyNumber_Subtract(r->len, r->index);
341 } 341 }
342 342
343 static PyObject *rangeiter_new(PyTypeObject *, PyObject *args, PyObject *kw); 343 static PyObject *rangeiter_new(PyTypeObject *, PyObject *args, PyObject *kw);
344 344
345 PyDoc_STRVAR(length_hint_doc, 345 PyDoc_STRVAR(length_hint_doc,
346 "Private method returning an estimate of len(list(it))."); 346 "Private method returning an estimate of len(list(it)).");
347 347
348 static PyMethodDef rangeiter_methods[] = { 348 static PyMethodDef rangeiter_methods[] = {
349 {"__length_hint__", (PyCFunction)rangeiter_len, METH_NOARGS, 349 {"__length_hint__", (PyCFunction)rangeiter_len, METH_NOARGS,
350 length_hint_doc}, 350 length_hint_doc},
351 {NULL, NULL} /* sentinel */ 351 {NULL, NULL} /* sentinel */
352 }; 352 };
353 353
354 PyTypeObject PyRangeIter_Type = { 354 PyTypeObject PyRangeIter_Type = {
355 PyVarObject_HEAD_INIT(&PyType_Type, 0) 355 PyVarObject_HEAD_INIT(&PyType_Type, 0)
356 "range_iterator", /* tp_name */ 356 "range_iterator", /* tp_name */
357 sizeof(rangeiterobject), /* tp_basicsize */ 357 sizeof(rangeiterobject), /* tp_basicsize */
358 0, /* tp_itemsize */ 358 0, /* tp_itemsize */
359 /* methods */ 359 /* methods */
360 (destructor)PyObject_Del, /* tp_dealloc */ 360 (destructor)PyObject_Del, /* tp_dealloc */
361 0, /* tp_print */ 361 0, /* tp_print */
362 0, /* tp_getattr */ 362 0, /* tp_getattr */
363 0, /* tp_setattr */ 363 0, /* tp_setattr */
364 0, /* tp_compare */ 364 0, /* tp_compare */
365 0, /* tp_repr */ 365 0, /* tp_repr */
366 0, /* tp_as_number */ 366 0, /* tp_as_number */
367 0, /* tp_as_sequence */ 367 0, /* tp_as_sequence */
368 0, /* tp_as_mapping */ 368 0, /* tp_as_mapping */
369 0, /* tp_hash */ 369 0, /* tp_hash */
370 0, /* tp_call */ 370 0, /* tp_call */
371 0, /* tp_str */ 371 0, /* tp_str */
372 PyObject_GenericGetAttr, /* tp_getattro */ 372 PyObject_GenericGetAttr, /* tp_getattro */
373 0, /* tp_setattro */ 373 0, /* tp_setattro */
374 0, /* tp_as_buffer */ 374 0, /* tp_as_buffer */
375 Py_TPFLAGS_DEFAULT, /* tp_flags */ 375 Py_TPFLAGS_DEFAULT, /* tp_flags */
376 0, /* tp_doc */ 376 0, /* tp_doc */
377 0, /* tp_traverse */ 377 0, /* tp_traverse */
378 0, /* tp_clear */ 378 0, /* tp_clear */
379 0, /* tp_richcompare */ 379 0, /* tp_richcompare */
380 0, /* tp_weaklistoffset */ 380 0, /* tp_weaklistoffset */
381 PyObject_SelfIter, /* tp_iter */ 381 PyObject_SelfIter, /* tp_iter */
382 (iternextfunc)rangeiter_next, /* tp_iternext */ 382 (iternextfunc)rangeiter_next, /* tp_iternext */
383 rangeiter_methods, /* tp_methods */ 383 rangeiter_methods, /* tp_methods */
384 0, /* tp_members */ 384 0, /* tp_members */
385 0, /* tp_getset */ 385 0, /* tp_getset */
386 0, /* tp_base */ 386 0, /* tp_base */
387 0, /* tp_dict */ 387 0, /* tp_dict */
388 0, /* tp_descr_get */ 388 0, /* tp_descr_get */
389 0, /* tp_descr_set */ 389 0, /* tp_descr_set */
390 0, /* tp_dictoffset */ 390 0, /* tp_dictoffset */
391 0, /* tp_init */ 391 0, /* tp_init */
392 0, /* tp_alloc */ 392 0, /* tp_alloc */
393 rangeiter_new, /* tp_new */ 393 rangeiter_new, /* tp_new */
394 }; 394 };
395 395
396 /* Return number of items in range/xrange (lo, hi, step). step > 0 396 /* 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 397 * required. Return a value < 0 if & only if the true value is too
398 * large to fit in a signed long. 398 * large to fit in a signed long.
399 */ 399 */
400 static long 400 static long
401 get_len_of_range(long lo, long hi, long step) 401 get_len_of_range(long lo, long hi, long step)
402 { 402 {
403 /* ------------------------------------------------------------- 403 /* -------------------------------------------------------------
404 If lo >= hi, the range is empty. 404 If lo >= hi, the range is empty.
405 Else if n values are in the range, the last one is 405 Else if n values are in the range, the last one is
406 lo + (n-1)*step, which must be <= hi-1. Rearranging, 406 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 407 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 408 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 409 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 410 floor. Letting M be the largest positive long, the worst case
411 for the RHS numerator is hi=M, lo=-M-1, and then 411 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 412 hi-lo-1 = M-(-M-1)-1 = 2*M. Therefore unsigned long has enough
413 precision to compute the RHS exactly. 413 precision to compute the RHS exactly.
414 ---------------------------------------------------------------*/ 414 ---------------------------------------------------------------*/
415 long n = 0; 415 long n = 0;
416 if (lo < hi) { 416 if (lo < hi) {
417 unsigned long uhi = (unsigned long)hi; 417 unsigned long uhi = (unsigned long)hi;
418 unsigned long ulo = (unsigned long)lo; 418 unsigned long ulo = (unsigned long)lo;
419 unsigned long diff = uhi - ulo - 1; 419 unsigned long diff = uhi - ulo - 1;
420 n = (long)(diff / (unsigned long)step + 1); 420 n = (long)(diff / (unsigned long)step + 1);
421 } 421 }
422 return n; 422 return n;
423 } 423 }
424 424
425 static PyObject * 425 static PyObject *
426 int_range_iter(long start, long stop, long step) 426 int_range_iter(long start, long stop, long step)
427 { 427 {
428 rangeiterobject *it = PyObject_New(rangeiterobject, &PyRangeIter_Type); 428 rangeiterobject *it = PyObject_New(rangeiterobject, &PyRangeIter_Type);
429 if (it == NULL) 429 if (it == NULL)
430 return NULL; 430 return NULL;