Coverage Report

Created: 2026-10-31 06:21

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/cpython/Objects/rangeobject.c
Line
Count
Source
1
/* Range object implementation */
2
3
#include "Python.h"
4
#include "pycore_abstract.h"      // _PyIndex_Check()
5
#include "pycore_ceval.h"         // _PyEval_GetBuiltin()
6
#include "pycore_freelist.h"
7
#include "pycore_long.h"          // _PyLong_GetZero()
8
#include "pycore_modsupport.h"    // _PyArg_NoKwnames()
9
#include "pycore_range.h"
10
#include "pycore_tuple.h"         // _PyTuple_ITEMS()
11
12
typedef struct {
13
    PyObject_HEAD
14
    PyObject *start;
15
    PyObject *step;
16
    PyObject *len;
17
} longrangeiterobject;
18
19
/*[clinic input]
20
class range_iterator "_PyRangeIterObject *" "&PyRangeIter_Type"
21
class longrange_iterator "longrangeiterobject *" "&PyLongRangeIter_Type"
22
[clinic start generated code]*/
23
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=c7d97a63d1cfa6b3]*/
24
25
#include "clinic/rangeobject.c.h"
26
27
28
/* Support objects whose length is > PY_SSIZE_T_MAX.
29
30
   This could be sped up for small PyLongs if they fit in a Py_ssize_t.
31
   This only matters on Win64.  Though we could use long long which
32
   would presumably help perf.
33
*/
34
35
typedef struct {
36
    PyObject_HEAD
37
    PyObject *start;
38
    PyObject *stop;
39
    PyObject *step;
40
    PyObject *length;
41
} rangeobject;
42
43
/* Helper function for validating step.  Always returns a new reference or
44
   NULL on error.
45
*/
46
static PyObject *
47
validate_step(PyObject *step)
48
656k
{
49
    /* No step specified, use a step of 1. */
50
656k
    if (!step)
51
528k
        return PyLong_FromLong(1);
52
53
127k
    step = PyNumber_Index(step);
54
127k
    if (step && _PyLong_IsZero((PyLongObject *)step)) {
55
0
        PyErr_SetString(PyExc_ValueError,
56
0
                        "range() arg 3 must not be zero");
57
0
        Py_CLEAR(step);
58
0
    }
59
60
127k
    return step;
61
656k
}
62
63
static PyObject *
64
compute_range_length(PyObject *start, PyObject *stop, PyObject *step);
65
66
static rangeobject *
67
make_range_object(PyTypeObject *type, PyObject *start,
68
                  PyObject *stop, PyObject *step)
69
5.49M
{
70
5.49M
    PyObject *length;
71
5.49M
    length = compute_range_length(start, stop, step);
72
5.49M
    if (length == NULL) {
73
0
        return NULL;
74
0
    }
75
5.49M
    rangeobject *obj = _Py_FREELIST_POP(rangeobject, ranges);
76
5.49M
    if (obj == NULL) {
77
791
        obj = PyObject_New(rangeobject, type);
78
791
        if (obj == NULL) {
79
0
            Py_DECREF(length);
80
0
            return NULL;
81
0
        }
82
791
    }
83
5.49M
    obj->start = start;
84
5.49M
    obj->stop = stop;
85
5.49M
    obj->step = step;
86
5.49M
    obj->length = length;
87
5.49M
    return obj;
88
5.49M
}
89
90
/* XXX(nnorwitz): should we error check if the user passes any empty ranges?
91
   range(-10)
92
   range(0, -5)
93
   range(0, 5, -1)
94
*/
95
static PyObject *
96
range_from_array(PyTypeObject *type, PyObject *const *args, Py_ssize_t num_args)
97
3.92M
{
98
3.92M
    rangeobject *obj;
99
3.92M
    PyObject *start = NULL, *stop = NULL, *step = NULL;
100
101
3.92M
    switch (num_args) {
102
127k
        case 3:
103
127k
            step = args[2];
104
127k
            _Py_FALLTHROUGH;
105
656k
        case 2:
106
            /* Convert borrowed refs to owned refs */
107
656k
            start = PyNumber_Index(args[0]);
108
656k
            if (!start) {
109
0
                return NULL;
110
0
            }
111
656k
            stop = PyNumber_Index(args[1]);
112
656k
            if (!stop) {
113
0
                Py_DECREF(start);
114
0
                return NULL;
115
0
            }
116
656k
            step = validate_step(step);  /* Caution, this can clear exceptions */
117
656k
            if (!step) {
118
0
                Py_DECREF(start);
119
0
                Py_DECREF(stop);
120
0
                return NULL;
121
0
            }
122
656k
            break;
123
3.27M
        case 1:
124
3.27M
            stop = PyNumber_Index(args[0]);
125
3.27M
            if (!stop) {
126
0
                return NULL;
127
0
            }
128
3.27M
            start = _PyLong_GetZero();
129
3.27M
            step = _PyLong_GetOne();
130
3.27M
            break;
131
0
        case 0:
132
0
            PyErr_SetString(PyExc_TypeError,
133
0
                            "range expected at least 1 argument, got 0");
134
0
            return NULL;
135
0
        default:
136
0
            PyErr_Format(PyExc_TypeError,
137
0
                         "range expected at most 3 arguments, got %zd",
138
0
                         num_args);
139
0
            return NULL;
140
3.92M
    }
141
3.92M
    obj = make_range_object(type, start, stop, step);
142
3.92M
    if (obj != NULL) {
143
3.92M
        return (PyObject *) obj;
144
3.92M
    }
145
146
    /* Failed to create object, release attributes */
147
0
    Py_DECREF(start);
148
0
    Py_DECREF(stop);
149
0
    Py_DECREF(step);
150
0
    return NULL;
151
3.92M
}
152
153
static PyObject *
154
range_new(PyTypeObject *type, PyObject *args, PyObject *kw)
155
0
{
156
0
    if (!_PyArg_NoKeywords("range", kw))
157
0
        return NULL;
158
159
0
    return range_from_array(type, _PyTuple_ITEMS(args), PyTuple_GET_SIZE(args));
160
0
}
161
162
163
static PyObject *
164
range_vectorcall(PyObject *rangetype, PyObject *const *args,
165
                 size_t nargsf, PyObject *kwnames)
166
3.92M
{
167
3.92M
    Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
168
3.92M
    if (!_PyArg_NoKwnames("range", kwnames)) {
169
0
        return NULL;
170
0
    }
171
3.92M
    return range_from_array((PyTypeObject *)rangetype, args, nargs);
172
3.92M
}
173
174
PyDoc_STRVAR(range_doc,
175
"range(stop) -> range object\n\
176
range(start, stop[, step]) -> range object\n\
177
\n\
178
Return an object that produces a sequence of integers from start (inclusive)\n\
179
to stop (exclusive) by step.  range(i, j) produces i, i+1, i+2, ..., j-1.\n\
180
start defaults to 0, and stop is omitted!  range(4) produces 0, 1, 2, 3.\n\
181
These are exactly the valid indices for a list of 4 elements.\n\
182
When step is given, it specifies the increment (or decrement).");
183
184
static void
185
range_dealloc(PyObject *op)
186
5.49M
{
187
5.49M
    rangeobject *r = (rangeobject*)op;
188
5.49M
    Py_DECREF(r->start);
189
5.49M
    Py_DECREF(r->stop);
190
5.49M
    Py_DECREF(r->step);
191
5.49M
    Py_DECREF(r->length);
192
5.49M
    _Py_FREELIST_FREE(ranges, r, PyObject_Free);
193
5.49M
}
194
195
static unsigned long
196
get_len_of_range(long lo, long hi, long step);
197
198
/* Return the length as a long, -2 for an overflow and -1 for any other type of error
199
 *
200
 * In case of an overflow no error is set
201
 */
202
static long compute_range_length_long(PyObject *start,
203
2.09M
                PyObject *stop, PyObject *step) {
204
2.09M
    int overflow = 0;
205
206
2.09M
    long long_start = PyLong_AsLongAndOverflow(start, &overflow);
207
2.09M
    if (overflow) {
208
0
        return -2;
209
0
    }
210
2.09M
    if (long_start == -1 && PyErr_Occurred()) {
211
0
        return -1;
212
0
    }
213
2.09M
    long long_stop = PyLong_AsLongAndOverflow(stop, &overflow);
214
2.09M
    if (overflow) {
215
0
        return -2;
216
0
    }
217
2.09M
    if (long_stop == -1 && PyErr_Occurred()) {
218
0
        return -1;
219
0
    }
220
2.09M
    long long_step = PyLong_AsLongAndOverflow(step, &overflow);
221
2.09M
    if (overflow) {
222
0
        return -2;
223
0
    }
224
2.09M
    if (long_step == -1 && PyErr_Occurred()) {
225
0
        return -1;
226
0
    }
227
228
2.09M
    unsigned long ulen = get_len_of_range(long_start, long_stop, long_step);
229
2.09M
    if (ulen > (unsigned long)LONG_MAX) {
230
        /* length too large for a long */
231
0
        return -2;
232
0
    }
233
2.09M
    else {
234
2.09M
        return (long)ulen;
235
2.09M
    }
236
2.09M
}
237
238
/* Return number of items in range (lo, hi, step) as a PyLong object,
239
 * when arguments are PyLong objects.  Arguments MUST return 1 with
240
 * PyLong_Check().  Return NULL when there is an error.
241
 */
242
static PyObject*
243
compute_range_length(PyObject *start, PyObject *stop, PyObject *step)
244
5.49M
{
245
    /* -------------------------------------------------------------
246
    Algorithm is equal to that of get_len_of_range(), but it operates
247
    on PyObjects (which are assumed to be PyLong objects).
248
    ---------------------------------------------------------------*/
249
5.49M
    int cmp_result;
250
5.49M
    PyObject *lo, *hi;
251
5.49M
    PyObject *diff = NULL;
252
5.49M
    PyObject *tmp1 = NULL, *tmp2 = NULL, *result;
253
                /* holds sub-expression evaluations */
254
255
5.49M
    PyObject *zero = _PyLong_GetZero();  // borrowed reference
256
5.49M
    PyObject *one = _PyLong_GetOne();  // borrowed reference
257
258
5.49M
    assert(PyLong_Check(start));
259
5.49M
    assert(PyLong_Check(stop));
260
5.49M
    assert(PyLong_Check(step));
261
262
    /* fast path for start == 0 and step == 1: length is max(stop, 0) */
263
5.49M
    if (start == zero && step == one) {
264
3.39M
        if (_PyLong_IsPositive((const PyLongObject *)stop)) {
265
2.19M
            return Py_NewRef(stop);
266
2.19M
        }
267
1.19M
        return zero;
268
3.39M
    }
269
270
    /* fast path when all arguments fit into a long integer */
271
2.09M
    long len = compute_range_length_long(start, stop, step);
272
2.09M
    if (len >= 0) {
273
2.09M
        return PyLong_FromLong(len);
274
2.09M
    }
275
0
    else if (len == -1) {
276
        /* unexpected error from compute_range_length_long, we propagate to the caller */
277
0
        return NULL;
278
0
    }
279
2.09M
    assert(len == -2);
280
281
0
    cmp_result = PyObject_RichCompareBool(step, zero, Py_GT);
282
0
    if (cmp_result == -1)
283
0
        return NULL;
284
285
0
    if (cmp_result == 1) {
286
0
        lo = start;
287
0
        hi = stop;
288
0
        Py_INCREF(step);
289
0
    } else {
290
0
        lo = stop;
291
0
        hi = start;
292
0
        step = PyNumber_Negative(step);
293
0
        if (!step)
294
0
            return NULL;
295
0
    }
296
297
    /* if (lo >= hi), return length of 0. */
298
0
    cmp_result = PyObject_RichCompareBool(lo, hi, Py_GE);
299
0
    if (cmp_result != 0) {
300
0
        Py_DECREF(step);
301
0
        if (cmp_result < 0)
302
0
            return NULL;
303
0
        result = zero;
304
0
        return Py_NewRef(result);
305
0
    }
306
307
0
    if ((tmp1 = PyNumber_Subtract(hi, lo)) == NULL)
308
0
        goto Fail;
309
310
0
    if ((diff = PyNumber_Subtract(tmp1, one)) == NULL)
311
0
        goto Fail;
312
313
0
    if ((tmp2 = PyNumber_FloorDivide(diff, step)) == NULL)
314
0
        goto Fail;
315
316
0
    if ((result = PyNumber_Add(tmp2, one)) == NULL)
317
0
        goto Fail;
318
319
0
    Py_DECREF(tmp2);
320
0
    Py_DECREF(diff);
321
0
    Py_DECREF(step);
322
0
    Py_DECREF(tmp1);
323
0
    return result;
324
325
0
  Fail:
326
0
    Py_DECREF(step);
327
0
    Py_XDECREF(tmp2);
328
0
    Py_XDECREF(diff);
329
0
    Py_XDECREF(tmp1);
330
0
    return NULL;
331
0
}
332
333
static Py_ssize_t
334
range_length(PyObject *op)
335
1.06k
{
336
1.06k
    rangeobject *r = (rangeobject*)op;
337
1.06k
    return PyLong_AsSsize_t(r->length);
338
1.06k
}
339
340
static PyObject *
341
compute_item(rangeobject *r, PyObject *i)
342
3.12M
{
343
3.12M
    PyObject *incr, *result;
344
    /* PyLong equivalent to:
345
     *    return r->start + (i * r->step)
346
     */
347
3.12M
    if (r->step == _PyLong_GetOne()) {
348
3.12M
        result = PyNumber_Add(r->start, i);
349
3.12M
    }
350
0
    else {
351
0
        incr = PyNumber_Multiply(i, r->step);
352
0
        if (!incr) {
353
0
            return NULL;
354
0
        }
355
0
        result = PyNumber_Add(r->start, incr);
356
0
        Py_DECREF(incr);
357
0
    }
358
3.12M
    return result;
359
3.12M
}
360
361
static PyObject *
362
compute_range_item(rangeobject *r, PyObject *arg)
363
0
{
364
0
    PyObject *zero = _PyLong_GetZero();  // borrowed reference
365
0
    int cmp_result;
366
0
    PyObject *i, *result;
367
368
    /* PyLong equivalent to:
369
     *   if (arg < 0) {
370
     *     i = r->length + arg
371
     *   } else {
372
     *     i = arg
373
     *   }
374
     */
375
0
    cmp_result = PyObject_RichCompareBool(arg, zero, Py_LT);
376
0
    if (cmp_result == -1) {
377
0
        return NULL;
378
0
    }
379
0
    if (cmp_result == 1) {
380
0
        i = PyNumber_Add(r->length, arg);
381
0
        if (!i) {
382
0
          return NULL;
383
0
        }
384
0
    } else {
385
0
        i = Py_NewRef(arg);
386
0
    }
387
388
    /* PyLong equivalent to:
389
     *   if (i < 0 || i >= r->length) {
390
     *     <report index out of bounds>
391
     *   }
392
     */
393
0
    cmp_result = PyObject_RichCompareBool(i, zero, Py_LT);
394
0
    if (cmp_result == 0) {
395
0
        cmp_result = PyObject_RichCompareBool(i, r->length, Py_GE);
396
0
    }
397
0
    if (cmp_result == -1) {
398
0
       Py_DECREF(i);
399
0
       return NULL;
400
0
    }
401
0
    if (cmp_result == 1) {
402
0
        Py_DECREF(i);
403
0
        PyErr_SetString(PyExc_IndexError,
404
0
                        "range object index out of range");
405
0
        return NULL;
406
0
    }
407
408
0
    result = compute_item(r, i);
409
0
    Py_DECREF(i);
410
0
    return result;
411
0
}
412
413
static PyObject *
414
range_item(PyObject *op, Py_ssize_t i)
415
0
{
416
0
    rangeobject *r = (rangeobject*)op;
417
0
    PyObject *res, *arg = PyLong_FromSsize_t(i);
418
0
    if (!arg) {
419
0
        return NULL;
420
0
    }
421
0
    res = compute_range_item(r, arg);
422
0
    Py_DECREF(arg);
423
0
    return res;
424
0
}
425
426
static PyObject *
427
compute_slice(rangeobject *r, PyObject *_slice)
428
1.56M
{
429
1.56M
    PySliceObject *slice = (PySliceObject *) _slice;
430
1.56M
    rangeobject *result;
431
1.56M
    PyObject *start = NULL, *stop = NULL, *step = NULL;
432
1.56M
    PyObject *substart = NULL, *substop = NULL, *substep = NULL;
433
1.56M
    int error;
434
435
1.56M
    error = _PySlice_GetLongIndices(slice, r->length, &start, &stop, &step);
436
1.56M
    if (error == -1)
437
0
        return NULL;
438
439
1.56M
    substep = PyNumber_Multiply(r->step, step);
440
1.56M
    if (substep == NULL) goto fail;
441
1.56M
    Py_CLEAR(step);
442
443
1.56M
    substart = compute_item(r, start);
444
1.56M
    if (substart == NULL) goto fail;
445
1.56M
    Py_CLEAR(start);
446
447
1.56M
    substop = compute_item(r, stop);
448
1.56M
    if (substop == NULL) goto fail;
449
1.56M
    Py_CLEAR(stop);
450
451
1.56M
    result = make_range_object(Py_TYPE(r), substart, substop, substep);
452
1.56M
    if (result != NULL) {
453
1.56M
        return (PyObject *) result;
454
1.56M
    }
455
0
fail:
456
0
    Py_XDECREF(start);
457
0
    Py_XDECREF(stop);
458
0
    Py_XDECREF(step);
459
0
    Py_XDECREF(substart);
460
0
    Py_XDECREF(substop);
461
0
    Py_XDECREF(substep);
462
0
    return NULL;
463
1.56M
}
464
465
/* Assumes (PyLong_CheckExact(ob) || PyBool_Check(ob)) */
466
static int
467
range_contains_long(rangeobject *r, PyObject *ob)
468
0
{
469
0
    PyObject *zero = _PyLong_GetZero();  // borrowed reference
470
0
    int cmp1, cmp2, cmp3;
471
0
    PyObject *tmp1 = NULL;
472
0
    PyObject *tmp2 = NULL;
473
0
    int result = -1;
474
475
    /* Check if the value can possibly be in the range. */
476
477
0
    cmp1 = PyObject_RichCompareBool(r->step, zero, Py_GT);
478
0
    if (cmp1 == -1)
479
0
        goto end;
480
0
    if (cmp1 == 1) { /* positive steps: start <= ob < stop */
481
0
        cmp2 = PyObject_RichCompareBool(r->start, ob, Py_LE);
482
0
        cmp3 = PyObject_RichCompareBool(ob, r->stop, Py_LT);
483
0
    }
484
0
    else { /* negative steps: stop < ob <= start */
485
0
        cmp2 = PyObject_RichCompareBool(ob, r->start, Py_LE);
486
0
        cmp3 = PyObject_RichCompareBool(r->stop, ob, Py_LT);
487
0
    }
488
489
0
    if (cmp2 == -1 || cmp3 == -1) /* TypeError */
490
0
        goto end;
491
0
    if (cmp2 == 0 || cmp3 == 0) { /* ob outside of range */
492
0
        result = 0;
493
0
        goto end;
494
0
    }
495
496
    /* Check that the stride does not invalidate ob's membership. */
497
0
    tmp1 = PyNumber_Subtract(ob, r->start);
498
0
    if (tmp1 == NULL)
499
0
        goto end;
500
0
    tmp2 = PyNumber_Remainder(tmp1, r->step);
501
0
    if (tmp2 == NULL)
502
0
        goto end;
503
    /* result = ((int(ob) - start) % step) == 0 */
504
0
    result = PyObject_RichCompareBool(tmp2, zero, Py_EQ);
505
0
  end:
506
0
    Py_XDECREF(tmp1);
507
0
    Py_XDECREF(tmp2);
508
0
    return result;
509
0
}
510
511
static int
512
range_contains(PyObject *self, PyObject *ob)
513
0
{
514
0
    rangeobject *r = (rangeobject*)self;
515
0
    if (PyLong_CheckExact(ob) || PyBool_Check(ob))
516
0
        return range_contains_long(r, ob);
517
518
0
    return (int)_PySequence_IterSearch((PyObject*)r, ob,
519
0
                                       PY_ITERSEARCH_CONTAINS);
520
0
}
521
522
/* Compare two range objects.  Return 1 for equal, 0 for not equal
523
   and -1 on error.  The algorithm is roughly the C equivalent of
524
525
   if r0 is r1:
526
       return True
527
   if len(r0) != len(r1):
528
       return False
529
   if not len(r0):
530
       return True
531
   if r0.start != r1.start:
532
       return False
533
   if len(r0) == 1:
534
       return True
535
   return r0.step == r1.step
536
*/
537
static int
538
range_equals(rangeobject *r0, rangeobject *r1)
539
0
{
540
0
    int cmp_result;
541
542
0
    if (r0 == r1)
543
0
        return 1;
544
0
    cmp_result = PyObject_RichCompareBool(r0->length, r1->length, Py_EQ);
545
    /* Return False or error to the caller. */
546
0
    if (cmp_result != 1)
547
0
        return cmp_result;
548
0
    cmp_result = PyObject_Not(r0->length);
549
    /* Return True or error to the caller. */
550
0
    if (cmp_result != 0)
551
0
        return cmp_result;
552
0
    cmp_result = PyObject_RichCompareBool(r0->start, r1->start, Py_EQ);
553
    /* Return False or error to the caller. */
554
0
    if (cmp_result != 1)
555
0
        return cmp_result;
556
0
    cmp_result = PyObject_RichCompareBool(r0->length, _PyLong_GetOne(), Py_EQ);
557
    /* Return True or error to the caller. */
558
0
    if (cmp_result != 0)
559
0
        return cmp_result;
560
0
    return PyObject_RichCompareBool(r0->step, r1->step, Py_EQ);
561
0
}
562
563
static PyObject *
564
range_richcompare(PyObject *self, PyObject *other, int op)
565
0
{
566
0
    int result;
567
568
0
    if (!PyRange_Check(other))
569
0
        Py_RETURN_NOTIMPLEMENTED;
570
0
    switch (op) {
571
0
    case Py_NE:
572
0
    case Py_EQ:
573
0
        result = range_equals((rangeobject*)self, (rangeobject*)other);
574
0
        if (result == -1)
575
0
            return NULL;
576
0
        if (op == Py_NE)
577
0
            result = !result;
578
0
        if (result)
579
0
            Py_RETURN_TRUE;
580
0
        else
581
0
            Py_RETURN_FALSE;
582
0
    case Py_LE:
583
0
    case Py_GE:
584
0
    case Py_LT:
585
0
    case Py_GT:
586
0
        Py_RETURN_NOTIMPLEMENTED;
587
0
    default:
588
0
        PyErr_BadArgument();
589
0
        return NULL;
590
0
    }
591
0
}
592
593
/* Hash function for range objects.  Rough C equivalent of
594
595
   if not len(r):
596
       return hash((len(r), None, None))
597
   if len(r) == 1:
598
       return hash((len(r), r.start, None))
599
   return hash((len(r), r.start, r.step))
600
*/
601
static Py_hash_t
602
range_hash(PyObject *op)
603
0
{
604
0
    rangeobject *r = (rangeobject*)op;
605
0
    PyObject *t;
606
0
    Py_hash_t result = -1;
607
0
    int cmp_result;
608
609
0
    t = PyTuple_New(3);
610
0
    if (!t)
611
0
        return -1;
612
0
    PyTuple_SET_ITEM(t, 0, Py_NewRef(r->length));
613
0
    cmp_result = PyObject_Not(r->length);
614
0
    if (cmp_result == -1)
615
0
        goto end;
616
0
    if (cmp_result == 1) {
617
0
        PyTuple_SET_ITEM(t, 1, Py_NewRef(Py_None));
618
0
        PyTuple_SET_ITEM(t, 2, Py_NewRef(Py_None));
619
0
    }
620
0
    else {
621
0
        PyTuple_SET_ITEM(t, 1, Py_NewRef(r->start));
622
0
        cmp_result = PyObject_RichCompareBool(r->length, _PyLong_GetOne(), Py_EQ);
623
0
        if (cmp_result == -1)
624
0
            goto end;
625
0
        if (cmp_result == 1) {
626
0
            PyTuple_SET_ITEM(t, 2, Py_NewRef(Py_None));
627
0
        }
628
0
        else {
629
0
            PyTuple_SET_ITEM(t, 2, Py_NewRef(r->step));
630
0
        }
631
0
    }
632
0
    result = PyObject_Hash(t);
633
0
  end:
634
0
    Py_DECREF(t);
635
0
    return result;
636
0
}
637
638
static PyObject *
639
range_count(PyObject *self, PyObject *ob)
640
0
{
641
0
    rangeobject *r = (rangeobject*)self;
642
0
    if (PyLong_CheckExact(ob) || PyBool_Check(ob)) {
643
0
        int result = range_contains_long(r, ob);
644
0
        if (result == -1)
645
0
            return NULL;
646
0
        return PyLong_FromLong(result);
647
0
    } else {
648
0
        Py_ssize_t count;
649
0
        count = _PySequence_IterSearch((PyObject*)r, ob, PY_ITERSEARCH_COUNT);
650
0
        if (count == -1)
651
0
            return NULL;
652
0
        return PyLong_FromSsize_t(count);
653
0
    }
654
0
}
655
656
static PyObject *
657
range_index(PyObject *self, PyObject *ob)
658
0
{
659
0
    rangeobject *r = (rangeobject*)self;
660
0
    int contains;
661
662
0
    if (!PyLong_CheckExact(ob) && !PyBool_Check(ob)) {
663
0
        Py_ssize_t index;
664
0
        index = _PySequence_IterSearch((PyObject*)r, ob, PY_ITERSEARCH_INDEX);
665
0
        if (index == -1)
666
0
            return NULL;
667
0
        return PyLong_FromSsize_t(index);
668
0
    }
669
670
0
    contains = range_contains_long(r, ob);
671
0
    if (contains == -1)
672
0
        return NULL;
673
674
0
    if (contains) {
675
0
        PyObject *idx = PyNumber_Subtract(ob, r->start);
676
0
        if (idx == NULL) {
677
0
            return NULL;
678
0
        }
679
680
0
        if (r->step == _PyLong_GetOne()) {
681
0
            return idx;
682
0
        }
683
684
        /* idx = (ob - r.start) // r.step */
685
0
        PyObject *sidx = PyNumber_FloorDivide(idx, r->step);
686
0
        Py_DECREF(idx);
687
0
        return sidx;
688
0
    }
689
690
    /* object is not in the range */
691
0
    PyErr_SetString(PyExc_ValueError, "range.index(x): x not in range");
692
0
    return NULL;
693
0
}
694
695
static PySequenceMethods range_as_sequence = {
696
    range_length,               /* sq_length */
697
    0,                          /* sq_concat */
698
    0,                          /* sq_repeat */
699
    range_item,                 /* sq_item */
700
    0,                          /* sq_slice */
701
    0,                          /* sq_ass_item */
702
    0,                          /* sq_ass_slice */
703
    range_contains,             /* sq_contains */
704
};
705
706
static PyObject *
707
range_repr(PyObject *op)
708
0
{
709
0
    rangeobject *r = (rangeobject*)op;
710
0
    Py_ssize_t istep;
711
712
    /* Check for special case values for printing.  We don't always
713
       need the step value.  We don't care about overflow. */
714
0
    istep = PyNumber_AsSsize_t(r->step, NULL);
715
0
    if (istep == -1 && PyErr_Occurred()) {
716
0
        assert(!PyErr_ExceptionMatches(PyExc_OverflowError));
717
0
        return NULL;
718
0
    }
719
720
0
    if (istep == 1)
721
0
        return PyUnicode_FromFormat("range(%R, %R)", r->start, r->stop);
722
0
    else
723
0
        return PyUnicode_FromFormat("range(%R, %R, %R)",
724
0
                                    r->start, r->stop, r->step);
725
0
}
726
727
/* Pickling support */
728
static PyObject *
729
range_reduce(PyObject *op, PyObject *args)
730
0
{
731
0
    rangeobject *r = (rangeobject*)op;
732
0
    return Py_BuildValue("(O(OOO))", Py_TYPE(r),
733
0
                         r->start, r->stop, r->step);
734
0
}
735
736
static PyObject *
737
range_subscript(PyObject *op, PyObject *item)
738
1.56M
{
739
1.56M
    rangeobject *self = (rangeobject*)op;
740
1.56M
    if (_PyIndex_Check(item)) {
741
0
        PyObject *i, *result;
742
0
        i = PyNumber_Index(item);
743
0
        if (!i)
744
0
            return NULL;
745
0
        result = compute_range_item(self, i);
746
0
        Py_DECREF(i);
747
0
        return result;
748
0
    }
749
1.56M
    if (PySlice_Check(item)) {
750
1.56M
        return compute_slice(self, item);
751
1.56M
    }
752
0
    PyErr_Format(PyExc_TypeError,
753
0
                 "range indices must be integers or slices, not %.200s",
754
0
                 Py_TYPE(item)->tp_name);
755
0
    return NULL;
756
1.56M
}
757
758
759
static PyMappingMethods range_as_mapping = {
760
        range_length,                /* mp_length */
761
        range_subscript,             /* mp_subscript */
762
        0,                           /* mp_ass_subscript */
763
};
764
765
static int
766
range_bool(PyObject *op)
767
83.4k
{
768
83.4k
    rangeobject *self = (rangeobject*)op;
769
83.4k
    return PyObject_IsTrue(self->length);
770
83.4k
}
771
772
static PyNumberMethods range_as_number = {
773
    .nb_bool = range_bool,
774
};
775
776
static PyObject * range_iter(PyObject *seq);
777
static PyObject * range_reverse(PyObject *seq, PyObject *Py_UNUSED(ignored));
778
779
PyDoc_STRVAR(reverse_doc,
780
"Return a reverse iterator.");
781
782
PyDoc_STRVAR(count_doc,
783
"rangeobject.count(value) -> integer -- return number of occurrences of value");
784
785
PyDoc_STRVAR(index_doc,
786
"rangeobject.index(value) -> integer -- return index of value.\n"
787
"Raise ValueError if the value is not present.");
788
789
static PyMethodDef range_methods[] = {
790
    {"__reversed__",    range_reverse,              METH_NOARGS, reverse_doc},
791
    {"__reduce__",      range_reduce,               METH_NOARGS},
792
    {"count",           range_count,                METH_O,      count_doc},
793
    {"index",           range_index,                METH_O,      index_doc},
794
    {NULL,              NULL}           /* sentinel */
795
};
796
797
static PyMemberDef range_members[] = {
798
    {"start",   Py_T_OBJECT_EX,    offsetof(rangeobject, start),   Py_READONLY},
799
    {"stop",    Py_T_OBJECT_EX,    offsetof(rangeobject, stop),    Py_READONLY},
800
    {"step",    Py_T_OBJECT_EX,    offsetof(rangeobject, step),    Py_READONLY},
801
    {0}
802
};
803
804
PyTypeObject PyRange_Type = {
805
        PyVarObject_HEAD_INIT(&PyType_Type, 0)
806
        "range",                /* Name of this type */
807
        sizeof(rangeobject),    /* Basic object size */
808
        0,                      /* Item size for varobject */
809
        range_dealloc,          /* tp_dealloc */
810
        0,                      /* tp_vectorcall_offset */
811
        0,                      /* tp_getattr */
812
        0,                      /* tp_setattr */
813
        0,                      /* tp_as_async */
814
        range_repr,             /* tp_repr */
815
        &range_as_number,       /* tp_as_number */
816
        &range_as_sequence,     /* tp_as_sequence */
817
        &range_as_mapping,      /* tp_as_mapping */
818
        range_hash,             /* tp_hash */
819
        0,                      /* tp_call */
820
        0,                      /* tp_str */
821
        PyObject_GenericGetAttr,  /* tp_getattro */
822
        0,                      /* tp_setattro */
823
        0,                      /* tp_as_buffer */
824
        Py_TPFLAGS_DEFAULT | Py_TPFLAGS_SEQUENCE,  /* tp_flags */
825
        range_doc,              /* tp_doc */
826
        0,                      /* tp_traverse */
827
        0,                      /* tp_clear */
828
        range_richcompare,      /* tp_richcompare */
829
        0,                      /* tp_weaklistoffset */
830
        range_iter,             /* tp_iter */
831
        0,                      /* tp_iternext */
832
        range_methods,          /* tp_methods */
833
        range_members,          /* tp_members */
834
        0,                      /* tp_getset */
835
        0,                      /* tp_base */
836
        0,                      /* tp_dict */
837
        0,                      /* tp_descr_get */
838
        0,                      /* tp_descr_set */
839
        0,                      /* tp_dictoffset */
840
        0,                      /* tp_init */
841
        0,                      /* tp_alloc */
842
        range_new,              /* tp_new */
843
        .tp_vectorcall = range_vectorcall
844
};
845
846
/*********************** range Iterator **************************/
847
848
/* There are 2 types of iterators, one for C longs, the other for
849
   Python ints (ie, PyObjects).  This should make iteration fast
850
   in the normal case, but possible for any numeric value.
851
*/
852
853
static PyObject *
854
rangeiter_next(PyObject *op)
855
72.8M
{
856
72.8M
    PyObject *ret = NULL;
857
72.8M
    Py_BEGIN_CRITICAL_SECTION(op);
858
72.8M
    _PyRangeIterObject *r = (_PyRangeIterObject*)op;
859
72.8M
    if (r->len > 0) {
860
72.8M
        long result = r->start;
861
72.8M
        r->start = result + r->step;
862
72.8M
        r->len--;
863
72.8M
        ret = PyLong_FromLong(result);
864
72.8M
    }
865
72.8M
    Py_END_CRITICAL_SECTION();
866
72.8M
    return ret;
867
72.8M
}
868
869
/*[clinic input]
870
@critical_section
871
range_iterator.__length_hint__
872
    self as r: self(type="_PyRangeIterObject *")
873
874
Private method returning an estimate of len(list(it)).
875
[clinic start generated code]*/
876
877
static PyObject *
878
range_iterator___length_hint___impl(_PyRangeIterObject *r)
879
/*[clinic end generated code: output=9ba6f22b1fc23dcc input=e3eb311e99d76e43]*/
880
0
{
881
0
    return PyLong_FromLong(r->len);
882
0
}
883
884
/*[clinic input]
885
@critical_section
886
range_iterator.__reduce__
887
    self as r: self(type="_PyRangeIterObject *")
888
889
Return state information for pickling.
890
[clinic start generated code]*/
891
892
static PyObject *
893
range_iterator___reduce___impl(_PyRangeIterObject *r)
894
/*[clinic end generated code: output=c44d53750c388415 input=75a25b7076dc2c54]*/
895
0
{
896
0
    PyObject *start=NULL, *stop=NULL, *step=NULL;
897
0
    PyObject *range;
898
899
    /* create a range object for pickling */
900
0
    start = PyLong_FromLong(r->start);
901
0
    if (start == NULL)
902
0
        goto err;
903
0
    stop = PyLong_FromLong(r->start + r->len * r->step);
904
0
    if (stop == NULL)
905
0
        goto err;
906
0
    step = PyLong_FromLong(r->step);
907
0
    if (step == NULL)
908
0
        goto err;
909
0
    range = (PyObject*)make_range_object(&PyRange_Type,
910
0
                               start, stop, step);
911
0
    if (range == NULL)
912
0
        goto err;
913
    /* return the result */
914
0
    return Py_BuildValue("N(N)O", _PyEval_GetBuiltin(&_Py_ID(iter)),
915
0
                         range, Py_None);
916
0
err:
917
0
    Py_XDECREF(start);
918
0
    Py_XDECREF(stop);
919
0
    Py_XDECREF(step);
920
0
    return NULL;
921
0
}
922
923
/*[clinic input]
924
@critical_section
925
range_iterator.__setstate__
926
    self as r: self(type="_PyRangeIterObject *")
927
    state: object
928
    /
929
930
Set state information for unpickling.
931
[clinic start generated code]*/
932
933
static PyObject *
934
range_iterator___setstate___impl(_PyRangeIterObject *r, PyObject *state)
935
/*[clinic end generated code: output=464b3cbafc2e3562 input=c8c84fab2519d200]*/
936
0
{
937
0
    long index = PyLong_AsLong(state);
938
0
    if (index == -1 && PyErr_Occurred())
939
0
        return NULL;
940
    /* silently clip the index value */
941
0
    if (index < 0)
942
0
        index = 0;
943
0
    else if (index > r->len)
944
0
        index = r->len; /* exhausted iterator */
945
0
    r->start += index * r->step;
946
0
    r->len -= index;
947
0
    Py_RETURN_NONE;
948
0
}
949
950
static void
951
rangeiter_dealloc(PyObject *self)
952
3.93M
{
953
3.93M
    _Py_FREELIST_FREE(range_iters, (_PyRangeIterObject *)self, PyObject_Free);
954
3.93M
}
955
956
static PyMethodDef rangeiter_methods[] = {
957
    RANGE_ITERATOR___LENGTH_HINT___METHODDEF
958
    RANGE_ITERATOR___REDUCE___METHODDEF
959
    RANGE_ITERATOR___SETSTATE___METHODDEF
960
    {NULL,              NULL}           /* sentinel */
961
};
962
963
PyTypeObject PyRangeIter_Type = {
964
        PyVarObject_HEAD_INIT(&PyType_Type, 0)
965
        "range_iterator",                       /* tp_name */
966
        sizeof(_PyRangeIterObject),             /* tp_basicsize */
967
        0,                                      /* tp_itemsize */
968
        /* methods */
969
        rangeiter_dealloc,                      /* tp_dealloc */
970
        0,                                      /* tp_vectorcall_offset */
971
        0,                                      /* tp_getattr */
972
        0,                                      /* tp_setattr */
973
        0,                                      /* tp_as_async */
974
        0,                                      /* tp_repr */
975
        0,                                      /* tp_as_number */
976
        0,                                      /* tp_as_sequence */
977
        0,                                      /* tp_as_mapping */
978
        0,                                      /* tp_hash */
979
        0,                                      /* tp_call */
980
        0,                                      /* tp_str */
981
        PyObject_GenericGetAttr,                /* tp_getattro */
982
        0,                                      /* tp_setattro */
983
        0,                                      /* tp_as_buffer */
984
        Py_TPFLAGS_DEFAULT,                     /* tp_flags */
985
        0,                                      /* tp_doc */
986
        0,                                      /* tp_traverse */
987
        0,                                      /* tp_clear */
988
        0,                                      /* tp_richcompare */
989
        0,                                      /* tp_weaklistoffset */
990
        PyObject_SelfIter,                      /* tp_iter */
991
        rangeiter_next,                         /* tp_iternext */
992
        rangeiter_methods,                      /* tp_methods */
993
        0,                                      /* tp_members */
994
};
995
996
/* Return number of items in range (lo, hi, step).  step != 0
997
 * required.  The result always fits in an unsigned long.
998
 */
999
static unsigned long
1000
get_len_of_range(long lo, long hi, long step)
1001
6.02M
{
1002
    /* -------------------------------------------------------------
1003
    If step > 0 and lo >= hi, or step < 0 and lo <= hi, the range is empty.
1004
    Else for step > 0, if n values are in the range, the last one is
1005
    lo + (n-1)*step, which must be <= hi-1.  Rearranging,
1006
    n <= (hi - lo - 1)/step + 1, so taking the floor of the RHS gives
1007
    the proper value.  Since lo < hi in this case, hi-lo-1 >= 0, so
1008
    the RHS is non-negative and so truncation is the same as the
1009
    floor.  Letting M be the largest positive long, the worst case
1010
    for the RHS numerator is hi=M, lo=-M-1, and then
1011
    hi-lo-1 = M-(-M-1)-1 = 2*M.  Therefore unsigned long has enough
1012
    precision to compute the RHS exactly.  The analysis for step < 0
1013
    is similar.
1014
    ---------------------------------------------------------------*/
1015
6.02M
    assert(step != 0);
1016
6.02M
    if (step > 0 && lo < hi)
1017
2.68M
        return 1UL + (hi - 1UL - lo) / step;
1018
3.34M
    else if (step < 0 && lo > hi)
1019
881k
        return 1UL + (lo - 1UL - hi) / (0UL - step);
1020
2.46M
    else
1021
2.46M
        return 0UL;
1022
6.02M
}
1023
1024
/* Initialize a rangeiter object.  If the length of the rangeiter object
1025
   is not representable as a C long, OverflowError is raised. */
1026
1027
static PyObject *
1028
fast_range_iter(long start, long stop, long step, long len)
1029
3.93M
{
1030
3.93M
    _PyRangeIterObject *it = _Py_FREELIST_POP(_PyRangeIterObject, range_iters);
1031
3.93M
    if (it == NULL) {
1032
552
        it = PyObject_New(_PyRangeIterObject, &PyRangeIter_Type);
1033
552
        if (it == NULL) {
1034
0
            return NULL;
1035
0
        }
1036
552
    }
1037
3.93M
    assert(Py_IS_TYPE(it, &PyRangeIter_Type));
1038
3.93M
    it->start = start;
1039
3.93M
    it->step = step;
1040
3.93M
    it->len = len;
1041
3.93M
    return (PyObject *)it;
1042
3.93M
}
1043
1044
/*[clinic input]
1045
@critical_section
1046
longrange_iterator.__length_hint__
1047
    self as r: self(type="longrangeiterobject *")
1048
1049
Private method returning an estimate of len(list(it)).
1050
[clinic start generated code]*/
1051
1052
static PyObject *
1053
longrange_iterator___length_hint___impl(longrangeiterobject *r)
1054
/*[clinic end generated code: output=e1bce24da7e8bfde input=ba94b050d940411e]*/
1055
0
{
1056
0
    Py_INCREF(r->len);
1057
0
    return r->len;
1058
0
}
1059
1060
/*[clinic input]
1061
@critical_section
1062
longrange_iterator.__reduce__
1063
    self as r: self(type="longrangeiterobject *")
1064
1065
Return state information for pickling.
1066
[clinic start generated code]*/
1067
1068
static PyObject *
1069
longrange_iterator___reduce___impl(longrangeiterobject *r)
1070
/*[clinic end generated code: output=0077f94ae2a4e99a input=2e8930e897ace086]*/
1071
0
{
1072
0
    PyObject *product, *stop=NULL;
1073
0
    PyObject *range;
1074
1075
    /* create a range object for pickling.  Must calculate the "stop" value */
1076
0
    product = PyNumber_Multiply(r->len, r->step);
1077
0
    if (product == NULL)
1078
0
        return NULL;
1079
0
    stop = PyNumber_Add(r->start, product);
1080
0
    Py_DECREF(product);
1081
0
    if (stop ==  NULL)
1082
0
        return NULL;
1083
0
    range =  (PyObject*)make_range_object(&PyRange_Type,
1084
0
                               Py_NewRef(r->start), stop, Py_NewRef(r->step));
1085
0
    if (range == NULL) {
1086
0
        Py_DECREF(r->start);
1087
0
        Py_DECREF(stop);
1088
0
        Py_DECREF(r->step);
1089
0
        return NULL;
1090
0
    }
1091
1092
    /* return the result */
1093
0
    return Py_BuildValue("N(N)O", _PyEval_GetBuiltin(&_Py_ID(iter)),
1094
0
                         range, Py_None);
1095
0
}
1096
1097
/*[clinic input]
1098
@critical_section
1099
longrange_iterator.__setstate__
1100
    self as r: self(type="longrangeiterobject *")
1101
    state: object
1102
    /
1103
1104
Set state information for unpickling.
1105
[clinic start generated code]*/
1106
1107
static PyObject *
1108
longrange_iterator___setstate___impl(longrangeiterobject *r, PyObject *state)
1109
/*[clinic end generated code: output=870787f0574f0da4 input=8b116de3018de824]*/
1110
0
{
1111
0
    if (!PyLong_CheckExact(state)) {
1112
0
        PyErr_Format(PyExc_TypeError, "state must be an int, not %T", state);
1113
0
        return NULL;
1114
0
    }
1115
1116
0
    PyObject *zero = _PyLong_GetZero();  // borrowed reference
1117
0
    int cmp;
1118
1119
    /* clip the value */
1120
0
    cmp = PyObject_RichCompareBool(state, zero, Py_LT);
1121
0
    if (cmp < 0)
1122
0
        return NULL;
1123
0
    if (cmp > 0) {
1124
0
        state = zero;
1125
0
    }
1126
0
    else {
1127
0
        cmp = PyObject_RichCompareBool(r->len, state, Py_LT);
1128
0
        if (cmp < 0)
1129
0
            return NULL;
1130
0
        if (cmp > 0)
1131
0
            state = r->len;
1132
0
    }
1133
0
    PyObject *product = PyNumber_Multiply(state, r->step);
1134
0
    if (product == NULL)
1135
0
        return NULL;
1136
0
    PyObject *new_start = PyNumber_Add(r->start, product);
1137
0
    Py_DECREF(product);
1138
0
    if (new_start == NULL)
1139
0
        return NULL;
1140
0
    PyObject *new_len = PyNumber_Subtract(r->len, state);
1141
0
    if (new_len == NULL) {
1142
0
        Py_DECREF(new_start);
1143
0
        return NULL;
1144
0
    }
1145
0
    PyObject *tmp = r->start;
1146
0
    r->start = new_start;
1147
0
    Py_SETREF(r->len, new_len);
1148
0
    Py_DECREF(tmp);
1149
0
    Py_RETURN_NONE;
1150
0
}
1151
1152
static PyMethodDef longrangeiter_methods[] = {
1153
    LONGRANGE_ITERATOR___LENGTH_HINT___METHODDEF
1154
    LONGRANGE_ITERATOR___REDUCE___METHODDEF
1155
    LONGRANGE_ITERATOR___SETSTATE___METHODDEF
1156
    {NULL,              NULL}           /* sentinel */
1157
};
1158
1159
static void
1160
longrangeiter_dealloc(PyObject *op)
1161
37
{
1162
37
    longrangeiterobject *r = (longrangeiterobject*)op;
1163
37
    Py_XDECREF(r->start);
1164
37
    Py_XDECREF(r->step);
1165
37
    Py_XDECREF(r->len);
1166
37
    PyObject_Free(r);
1167
37
}
1168
1169
/*[clinic input]
1170
@critical_section
1171
longrange_iterator.__next__ as longrangeiter_next
1172
[clinic start generated code]*/
1173
1174
static PyObject *
1175
longrangeiter_next_impl(longrangeiterobject *self)
1176
/*[clinic end generated code: output=49bf9a9b89c07ba5 input=2c4ac537c23a92d3]*/
1177
0
{
1178
0
    longrangeiterobject *r = self;
1179
0
    if (PyObject_RichCompareBool(r->len, _PyLong_GetZero(), Py_GT) != 1)
1180
0
        return NULL;
1181
1182
0
    PyObject *new_start = PyNumber_Add(r->start, r->step);
1183
0
    if (new_start == NULL) {
1184
0
        return NULL;
1185
0
    }
1186
0
    PyObject *new_len = PyNumber_Subtract(r->len, _PyLong_GetOne());
1187
0
    if (new_len == NULL) {
1188
0
        Py_DECREF(new_start);
1189
0
        return NULL;
1190
0
    }
1191
0
    PyObject *result = r->start;
1192
0
    r->start = new_start;
1193
0
    Py_SETREF(r->len, new_len);
1194
0
    return result;
1195
0
}
1196
1197
PyTypeObject PyLongRangeIter_Type = {
1198
        PyVarObject_HEAD_INIT(&PyType_Type, 0)
1199
        "longrange_iterator",                   /* tp_name */
1200
        sizeof(longrangeiterobject),            /* tp_basicsize */
1201
        0,                                      /* tp_itemsize */
1202
        /* methods */
1203
        longrangeiter_dealloc,                  /* tp_dealloc */
1204
        0,                                      /* tp_vectorcall_offset */
1205
        0,                                      /* tp_getattr */
1206
        0,                                      /* tp_setattr */
1207
        0,                                      /* tp_as_async */
1208
        0,                                      /* tp_repr */
1209
        0,                                      /* tp_as_number */
1210
        0,                                      /* tp_as_sequence */
1211
        0,                                      /* tp_as_mapping */
1212
        0,                                      /* tp_hash */
1213
        0,                                      /* tp_call */
1214
        0,                                      /* tp_str */
1215
        PyObject_GenericGetAttr,                /* tp_getattro */
1216
        0,                                      /* tp_setattro */
1217
        0,                                      /* tp_as_buffer */
1218
        Py_TPFLAGS_DEFAULT,                     /* tp_flags */
1219
        0,                                      /* tp_doc */
1220
        0,                                      /* tp_traverse */
1221
        0,                                      /* tp_clear */
1222
        0,                                      /* tp_richcompare */
1223
        0,                                      /* tp_weaklistoffset */
1224
        PyObject_SelfIter,                      /* tp_iter */
1225
        longrangeiter_next,                     /* tp_iternext */
1226
        longrangeiter_methods,                  /* tp_methods */
1227
        0,
1228
};
1229
1230
static PyObject *
1231
range_iter(PyObject *seq)
1232
3.93M
{
1233
3.93M
    rangeobject *r = (rangeobject *)seq;
1234
3.93M
    longrangeiterobject *it;
1235
3.93M
    long lstart, lstop, lstep;
1236
3.93M
    unsigned long ulen;
1237
1238
3.93M
    assert(PyRange_Check(seq));
1239
1240
    /* If all three fields and the length convert to long, use the int
1241
     * version */
1242
3.93M
    lstart = PyLong_AsLong(r->start);
1243
3.93M
    if (lstart == -1 && PyErr_Occurred()) {
1244
0
        PyErr_Clear();
1245
0
        goto long_range;
1246
0
    }
1247
3.93M
    lstop = PyLong_AsLong(r->stop);
1248
3.93M
    if (lstop == -1 && PyErr_Occurred()) {
1249
37
        PyErr_Clear();
1250
37
        goto long_range;
1251
37
    }
1252
3.93M
    lstep = PyLong_AsLong(r->step);
1253
3.93M
    if (lstep == -1 && PyErr_Occurred()) {
1254
0
        PyErr_Clear();
1255
0
        goto long_range;
1256
0
    }
1257
3.93M
    ulen = get_len_of_range(lstart, lstop, lstep);
1258
3.93M
    if (ulen > (unsigned long)LONG_MAX) {
1259
0
        goto long_range;
1260
0
    }
1261
    /* check for potential overflow of lstart + ulen * lstep */
1262
3.93M
    if (ulen) {
1263
2.69M
        if (lstep > 0) {
1264
2.25M
            if (lstop > LONG_MAX - (lstep - 1))
1265
0
                goto long_range;
1266
2.25M
        }
1267
440k
        else {
1268
440k
            if (lstop < LONG_MIN + (-1 - lstep))
1269
0
                goto long_range;
1270
440k
        }
1271
2.69M
    }
1272
3.93M
    return fast_range_iter(lstart, lstop, lstep, (long)ulen);
1273
1274
37
  long_range:
1275
37
    it = PyObject_New(longrangeiterobject, &PyLongRangeIter_Type);
1276
37
    if (it == NULL)
1277
0
        return NULL;
1278
1279
37
    it->start = Py_NewRef(r->start);
1280
37
    it->step = Py_NewRef(r->step);
1281
37
    it->len = Py_NewRef(r->length);
1282
37
    return (PyObject *)it;
1283
37
}
1284
1285
static PyObject *
1286
range_reverse(PyObject *seq, PyObject *Py_UNUSED(ignored))
1287
8
{
1288
8
    rangeobject *range = (rangeobject*) seq;
1289
8
    longrangeiterobject *it;
1290
8
    PyObject *sum, *diff, *product;
1291
8
    long lstart, lstop, lstep, new_start, new_stop;
1292
8
    unsigned long ulen;
1293
1294
8
    assert(PyRange_Check(seq));
1295
1296
    /* reversed(range(start, stop, step)) can be expressed as
1297
       range(start+(n-1)*step, start-step, -step), where n is the number of
1298
       integers in the range.
1299
1300
       If each of start, stop, step, -step, start-step, and the length
1301
       of the iterator is representable as a C long, use the int
1302
       version.  This excludes some cases where the reversed range is
1303
       representable as a range_iterator, but it's good enough for
1304
       common cases and it makes the checks simple. */
1305
1306
8
    lstart = PyLong_AsLong(range->start);
1307
8
    if (lstart == -1 && PyErr_Occurred()) {
1308
0
        PyErr_Clear();
1309
0
        goto long_range;
1310
0
    }
1311
8
    lstop = PyLong_AsLong(range->stop);
1312
8
    if (lstop == -1 && PyErr_Occurred()) {
1313
0
        PyErr_Clear();
1314
0
        goto long_range;
1315
0
    }
1316
8
    lstep = PyLong_AsLong(range->step);
1317
8
    if (lstep == -1 && PyErr_Occurred()) {
1318
0
        PyErr_Clear();
1319
0
        goto long_range;
1320
0
    }
1321
    /* check for possible overflow of -lstep */
1322
8
    if (lstep == LONG_MIN)
1323
0
        goto long_range;
1324
1325
    /* check for overflow of lstart - lstep:
1326
1327
       for lstep > 0, need only check whether lstart - lstep < LONG_MIN.
1328
       for lstep < 0, need only check whether lstart - lstep > LONG_MAX
1329
1330
       Rearrange these inequalities as:
1331
1332
           lstart - LONG_MIN < lstep  (lstep > 0)
1333
           LONG_MAX - lstart < -lstep  (lstep < 0)
1334
1335
       and compute both sides as unsigned longs, to avoid the
1336
       possibility of undefined behaviour due to signed overflow. */
1337
1338
8
    if (lstep > 0) {
1339
8
         if ((unsigned long)lstart - LONG_MIN < (unsigned long)lstep)
1340
0
            goto long_range;
1341
8
    }
1342
0
    else {
1343
0
        if (LONG_MAX - (unsigned long)lstart < 0UL - lstep)
1344
0
            goto long_range;
1345
0
    }
1346
1347
8
    ulen = get_len_of_range(lstart, lstop, lstep);
1348
8
    if (ulen > (unsigned long)LONG_MAX)
1349
0
        goto long_range;
1350
1351
8
    new_stop = lstart - lstep;
1352
8
    new_start = (long)(new_stop + ulen * lstep);
1353
8
    return fast_range_iter(new_start, new_stop, -lstep, (long)ulen);
1354
1355
0
long_range:
1356
0
    it = PyObject_New(longrangeiterobject, &PyLongRangeIter_Type);
1357
0
    if (it == NULL)
1358
0
        return NULL;
1359
0
    it->start = it->step = NULL;
1360
1361
    /* start + (len - 1) * step */
1362
0
    it->len = Py_NewRef(range->length);
1363
1364
0
    diff = PyNumber_Subtract(it->len, _PyLong_GetOne());
1365
0
    if (!diff)
1366
0
        goto create_failure;
1367
1368
0
    product = PyNumber_Multiply(diff, range->step);
1369
0
    Py_DECREF(diff);
1370
0
    if (!product)
1371
0
        goto create_failure;
1372
1373
0
    sum = PyNumber_Add(range->start, product);
1374
0
    Py_DECREF(product);
1375
0
    it->start = sum;
1376
0
    if (!it->start)
1377
0
        goto create_failure;
1378
1379
0
    it->step = PyNumber_Negative(range->step);
1380
0
    if (!it->step)
1381
0
        goto create_failure;
1382
1383
0
    return (PyObject *)it;
1384
1385
0
create_failure:
1386
0
    Py_DECREF(it);
1387
    return NULL;
1388
0
}