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

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