1 /* Range object implementation */
13 PyRange_New(long start
, long len
, long step
, int reps
)
18 PyErr_SetString(PyExc_ValueError
,
19 "PyRange_New's 'repetitions' argument must be 1");
23 obj
= PyObject_New(rangeobject
, &PyRange_Type
);
33 long last
= start
+ (len
- 1) * step
;
35 (last
> (PyInt_GetMax() - step
)) :
36 (last
< (-1 - PyInt_GetMax() - step
))) {
37 PyErr_SetString(PyExc_OverflowError
,
46 return (PyObject
*) obj
;
49 /* Return number of items in range/xrange (lo, hi, step). step > 0
50 * required. Return a value < 0 if & only if the true value is too
51 * large to fit in a signed long.
54 get_len_of_range(long lo
, long hi
, long step
)
56 /* -------------------------------------------------------------
57 If lo >= hi, the range is empty.
58 Else if n values are in the range, the last one is
59 lo + (n-1)*step, which must be <= hi-1. Rearranging,
60 n <= (hi - lo - 1)/step + 1, so taking the floor of the RHS gives
61 the proper value. Since lo < hi in this case, hi-lo-1 >= 0, so
62 the RHS is non-negative and so truncation is the same as the
63 floor. Letting M be the largest positive long, the worst case
64 for the RHS numerator is hi=M, lo=-M-1, and then
65 hi-lo-1 = M-(-M-1)-1 = 2*M. Therefore unsigned long has enough
66 precision to compute the RHS exactly.
67 ---------------------------------------------------------------*/
70 unsigned long uhi
= (unsigned long)hi
;
71 unsigned long ulo
= (unsigned long)lo
;
72 unsigned long diff
= uhi
- ulo
- 1;
73 n
= (long)(diff
/ (unsigned long)step
+ 1);
79 range_new(PyTypeObject
*type
, PyObject
*args
, PyObject
*kw
)
81 long ilow
= 0, ihigh
= 0, istep
= 1;
84 if (PyTuple_Size(args
) <= 1) {
85 if (!PyArg_ParseTuple(args
,
86 "l;xrange() requires 1-3 int arguments",
91 if (!PyArg_ParseTuple(args
,
92 "ll|l;xrange() requires 1-3 int arguments",
93 &ilow
, &ihigh
, &istep
))
97 PyErr_SetString(PyExc_ValueError
, "xrange() arg 3 must not be zero");
101 n
= get_len_of_range(ilow
, ihigh
, istep
);
103 n
= get_len_of_range(ihigh
, ilow
, -istep
);
105 PyErr_SetString(PyExc_OverflowError
,
106 "xrange() result has too many items");
109 return PyRange_New(ilow
, n
, istep
, 1);
112 PyDoc_STRVAR(range_doc
,
113 "xrange([start,] stop[, step]) -> xrange object\n\
115 Like range(), but instead of returning a list, returns an object that\n\
116 generates the numbers in the range on demand. This is slightly slower\n\
117 than range() but more memory efficient.");
120 range_item(rangeobject
*r
, int i
)
122 if (i
< 0 || i
>= r
->len
) {
123 PyErr_SetString(PyExc_IndexError
,
124 "xrange object index out of range");
127 return PyInt_FromLong(r
->start
+ (i
% r
->len
) * r
->step
);
131 range_length(rangeobject
*r
)
133 #if LONG_MAX != INT_MAX
134 if (r
->len
> INT_MAX
) {
135 PyErr_SetString(PyExc_ValueError
,
136 "xrange object size cannot be reported");
140 return (int)(r
->len
);
144 range_repr(rangeobject
*r
)
148 if (r
->start
== 0 && r
->step
== 1)
149 rtn
= PyString_FromFormat("xrange(%ld)",
150 r
->start
+ r
->len
* r
->step
);
152 else if (r
->step
== 1)
153 rtn
= PyString_FromFormat("xrange(%ld, %ld)",
155 r
->start
+ r
->len
* r
->step
);
158 rtn
= PyString_FromFormat("xrange(%ld, %ld, %ld)",
160 r
->start
+ r
->len
* r
->step
,
165 static PySequenceMethods range_as_sequence
= {
166 (inquiry
)range_length
, /* sq_length */
169 (intargfunc
)range_item
, /* sq_item */
173 static PyObject
* range_iter(PyObject
*seq
);
175 PyTypeObject PyRange_Type
= {
176 PyObject_HEAD_INIT(&PyType_Type
)
177 0, /* Number of items for varobject */
178 "xrange", /* Name of this type */
179 sizeof(rangeobject
), /* Basic object size */
180 0, /* Item size for varobject */
181 (destructor
)PyObject_Del
, /* tp_dealloc */
186 (reprfunc
)range_repr
, /* tp_repr */
187 0, /* tp_as_number */
188 &range_as_sequence
, /* tp_as_sequence */
189 0, /* tp_as_mapping */
195 0, /* tp_as_buffer */
196 Py_TPFLAGS_DEFAULT
, /* tp_flags */
197 range_doc
, /* tp_doc */
200 0, /* tp_richcompare */
201 0, /* tp_weaklistoffset */
202 (getiterfunc
)range_iter
, /* tp_iter */
209 0, /* tp_descr_get */
210 0, /* tp_descr_set */
211 0, /* tp_dictoffset */
214 range_new
, /* tp_new */
217 /*********************** Xrange Iterator **************************/
227 static PyTypeObject Pyrangeiter_Type
;
230 range_iter(PyObject
*seq
)
234 if (!PyRange_Check(seq
)) {
235 PyErr_BadInternalCall();
238 it
= PyObject_New(rangeiterobject
, &Pyrangeiter_Type
);
242 it
->start
= ((rangeobject
*)seq
)->start
;
243 it
->step
= ((rangeobject
*)seq
)->step
;
244 it
->len
= ((rangeobject
*)seq
)->len
;
245 return (PyObject
*)it
;
249 rangeiter_getiter(PyObject
*it
)
256 rangeiter_next(rangeiterobject
*r
)
258 if (r
->index
< r
->len
)
259 return PyInt_FromLong(r
->start
+ (r
->index
++) * r
->step
);
263 static PyTypeObject Pyrangeiter_Type
= {
264 PyObject_HEAD_INIT(&PyType_Type
)
266 "rangeiterator", /* tp_name */
267 sizeof(rangeiterobject
), /* tp_basicsize */
270 (destructor
)PyObject_Del
, /* tp_dealloc */
276 0, /* tp_as_number */
277 0, /* tp_as_sequence */
278 0, /* tp_as_mapping */
282 PyObject_GenericGetAttr
, /* tp_getattro */
284 0, /* tp_as_buffer */
285 Py_TPFLAGS_DEFAULT
, /* tp_flags */
289 0, /* tp_richcompare */
290 0, /* tp_weaklistoffset */
291 (getiterfunc
)rangeiter_getiter
, /* tp_iter */
292 (iternextfunc
)rangeiter_next
, /* tp_iternext */