Coverage Report

Created: 2026-01-09 06:26

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