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
)
137 range_repr(rangeobject
*r
)
141 if (r
->start
== 0 && r
->step
== 1)
142 rtn
= PyString_FromFormat("xrange(%ld)",
143 r
->start
+ r
->len
* r
->step
);
145 else if (r
->step
== 1)
146 rtn
= PyString_FromFormat("xrange(%ld, %ld)",
148 r
->start
+ r
->len
* r
->step
);
151 rtn
= PyString_FromFormat("xrange(%ld, %ld, %ld)",
153 r
->start
+ r
->len
* r
->step
,
158 static PySequenceMethods range_as_sequence
= {
159 (inquiry
)range_length
, /* sq_length */
162 (intargfunc
)range_item
, /* sq_item */
166 static PyObject
* range_iter(PyObject
*seq
);
168 PyTypeObject PyRange_Type
= {
169 PyObject_HEAD_INIT(&PyType_Type
)
170 0, /* Number of items for varobject */
171 "xrange", /* Name of this type */
172 sizeof(rangeobject
), /* Basic object size */
173 0, /* Item size for varobject */
174 (destructor
)PyObject_Del
, /* tp_dealloc */
179 (reprfunc
)range_repr
, /* tp_repr */
180 0, /* tp_as_number */
181 &range_as_sequence
, /* tp_as_sequence */
182 0, /* tp_as_mapping */
188 0, /* tp_as_buffer */
189 Py_TPFLAGS_DEFAULT
, /* tp_flags */
190 range_doc
, /* tp_doc */
193 0, /* tp_richcompare */
194 0, /* tp_weaklistoffset */
195 (getiterfunc
)range_iter
, /* tp_iter */
202 0, /* tp_descr_get */
203 0, /* tp_descr_set */
204 0, /* tp_dictoffset */
207 range_new
, /* tp_new */
210 /*********************** Xrange Iterator **************************/
220 static PyTypeObject Pyrangeiter_Type
;
223 range_iter(PyObject
*seq
)
227 if (!PyRange_Check(seq
)) {
228 PyErr_BadInternalCall();
231 it
= PyObject_New(rangeiterobject
, &Pyrangeiter_Type
);
235 it
->start
= ((rangeobject
*)seq
)->start
;
236 it
->step
= ((rangeobject
*)seq
)->step
;
237 it
->len
= ((rangeobject
*)seq
)->len
;
238 return (PyObject
*)it
;
242 rangeiter_getiter(PyObject
*it
)
249 rangeiter_next(rangeiterobject
*r
)
251 if (r
->index
< r
->len
)
252 return PyInt_FromLong(r
->start
+ (r
->index
++) * r
->step
);
256 static PyTypeObject Pyrangeiter_Type
= {
257 PyObject_HEAD_INIT(&PyType_Type
)
259 "rangeiterator", /* tp_name */
260 sizeof(rangeiterobject
), /* tp_basicsize */
263 (destructor
)PyObject_Del
, /* tp_dealloc */
269 0, /* tp_as_number */
270 0, /* tp_as_sequence */
271 0, /* tp_as_mapping */
275 PyObject_GenericGetAttr
, /* tp_getattro */
277 0, /* tp_as_buffer */
278 Py_TPFLAGS_DEFAULT
, /* tp_flags */
282 0, /* tp_richcompare */
283 0, /* tp_weaklistoffset */
284 (getiterfunc
)rangeiter_getiter
, /* tp_iter */
285 (iternextfunc
)rangeiter_next
, /* tp_iternext */