@@ -767,17 +767,44 @@ PyTypeObject PyRange_Type = {
767
767
typedef struct {
768
768
PyObject_HEAD
769
769
long start ;
770
+ long stop ;
770
771
long step ;
771
- long len ;
772
772
} rangeiterobject ;
773
773
774
+ /* Return number of items in range (lo, hi, step). step != 0
775
+ * required. The result always fits in an unsigned long.
776
+ */
777
+ static unsigned long
778
+ get_len_of_range (long lo , long hi , long step )
779
+ {
780
+ /* -------------------------------------------------------------
781
+ If step > 0 and lo >= hi, or step < 0 and lo <= hi, the range is empty.
782
+ Else for step > 0, if n values are in the range, the last one is
783
+ lo + (n-1)*step, which must be <= hi-1. Rearranging,
784
+ n <= (hi - lo - 1)/step + 1, so taking the floor of the RHS gives
785
+ the proper value. Since lo < hi in this case, hi-lo-1 >= 0, so
786
+ the RHS is non-negative and so truncation is the same as the
787
+ floor. Letting M be the largest positive long, the worst case
788
+ for the RHS numerator is hi=M, lo=-M-1, and then
789
+ hi-lo-1 = M-(-M-1)-1 = 2*M. Therefore unsigned long has enough
790
+ precision to compute the RHS exactly. The analysis for step < 0
791
+ is similar.
792
+ ---------------------------------------------------------------*/
793
+ assert (step != 0 );
794
+ if (step > 0 && lo < hi )
795
+ return 1UL + (hi - 1UL - lo ) / step ;
796
+ else if (step < 0 && lo > hi )
797
+ return 1UL + (lo - 1UL - hi ) / (0UL - step );
798
+ else
799
+ return 0UL ;
800
+ }
801
+
774
802
static PyObject *
775
803
rangeiter_next (rangeiterobject * r )
776
804
{
777
- if (r -> len > 0 ) {
805
+ if (r -> step > 0 ? r -> start < r -> stop : r -> start > r -> stop ) {
778
806
long result = r -> start ;
779
807
r -> start += r -> step ;
780
- r -> len -- ;
781
808
return PyLong_FromLong (result );
782
809
}
783
810
return NULL ;
@@ -786,7 +813,8 @@ rangeiter_next(rangeiterobject *r)
786
813
static PyObject *
787
814
rangeiter_len (rangeiterobject * r , PyObject * Py_UNUSED (ignored ))
788
815
{
789
- return PyLong_FromLong (r -> len );
816
+ unsigned long ulen = get_len_of_range (r -> start , r -> stop , r -> step );
817
+ return PyLong_FromUnsignedLong (ulen );
790
818
}
791
819
792
820
PyDoc_STRVAR (length_hint_doc ,
@@ -802,7 +830,7 @@ rangeiter_reduce(rangeiterobject *r, PyObject *Py_UNUSED(ignored))
802
830
start = PyLong_FromLong (r -> start );
803
831
if (start == NULL )
804
832
goto err ;
805
- stop = PyLong_FromLong (r -> start + r -> len * r -> step );
833
+ stop = PyLong_FromLong (r -> stop );
806
834
if (stop == NULL )
807
835
goto err ;
808
836
step = PyLong_FromLong (r -> step );
@@ -831,10 +859,12 @@ rangeiter_setstate(rangeiterobject *r, PyObject *state)
831
859
/* silently clip the index value */
832
860
if (index < 0 )
833
861
index = 0 ;
834
- else if (index > r -> len )
835
- index = r -> len ; /* exhausted iterator */
862
+ else {
863
+ unsigned long ulen = get_len_of_range (r -> start , r -> stop , r -> step );
864
+ if ((unsigned long )index > ulen )
865
+ index = (long )ulen ; /* exhausted iterator */
866
+ }
836
867
r -> start += index * r -> step ;
837
- r -> len -= index ;
838
868
Py_RETURN_NONE ;
839
869
}
840
870
@@ -884,34 +914,6 @@ PyTypeObject PyRangeIter_Type = {
884
914
0 , /* tp_members */
885
915
};
886
916
887
- /* Return number of items in range (lo, hi, step). step != 0
888
- * required. The result always fits in an unsigned long.
889
- */
890
- static unsigned long
891
- get_len_of_range (long lo , long hi , long step )
892
- {
893
- /* -------------------------------------------------------------
894
- If step > 0 and lo >= hi, or step < 0 and lo <= hi, the range is empty.
895
- Else for step > 0, if n values are in the range, the last one is
896
- lo + (n-1)*step, which must be <= hi-1. Rearranging,
897
- n <= (hi - lo - 1)/step + 1, so taking the floor of the RHS gives
898
- the proper value. Since lo < hi in this case, hi-lo-1 >= 0, so
899
- the RHS is non-negative and so truncation is the same as the
900
- floor. Letting M be the largest positive long, the worst case
901
- for the RHS numerator is hi=M, lo=-M-1, and then
902
- hi-lo-1 = M-(-M-1)-1 = 2*M. Therefore unsigned long has enough
903
- precision to compute the RHS exactly. The analysis for step < 0
904
- is similar.
905
- ---------------------------------------------------------------*/
906
- assert (step != 0 );
907
- if (step > 0 && lo < hi )
908
- return 1UL + (hi - 1UL - lo ) / step ;
909
- else if (step < 0 && lo > hi )
910
- return 1UL + (lo - 1UL - hi ) / (0UL - step );
911
- else
912
- return 0UL ;
913
- }
914
-
915
917
/* Initialize a rangeiter object. If the length of the rangeiter object
916
918
is not representable as a C long, OverflowError is raised. */
917
919
@@ -922,46 +924,38 @@ fast_range_iter(long start, long stop, long step, long len)
922
924
if (it == NULL )
923
925
return NULL ;
924
926
it -> start = start ;
927
+ it -> stop = stop ;
925
928
it -> step = step ;
926
- it -> len = len ;
927
929
return (PyObject * )it ;
928
930
}
929
931
930
932
typedef struct {
931
933
PyObject_HEAD
932
934
PyObject * start ;
935
+ PyObject * stop ;
933
936
PyObject * step ;
934
- PyObject * len ;
935
937
} longrangeiterobject ;
936
938
937
939
static PyObject *
938
940
longrangeiter_len (longrangeiterobject * r , PyObject * no_args )
939
941
{
940
- Py_INCREF (r -> len );
941
- return r -> len ;
942
+ return compute_range_length (r -> start , r -> stop , r -> step );
942
943
}
943
944
944
945
static PyObject *
945
946
longrangeiter_reduce (longrangeiterobject * r , PyObject * Py_UNUSED (ignored ))
946
947
{
947
- PyObject * product , * stop = NULL ;
948
948
PyObject * range ;
949
949
950
- /* create a range object for pickling. Must calculate the "stop" value */
951
- product = PyNumber_Multiply (r -> len , r -> step );
952
- if (product == NULL )
953
- return NULL ;
954
- stop = PyNumber_Add (r -> start , product );
955
- Py_DECREF (product );
956
- if (stop == NULL )
957
- return NULL ;
950
+ /* create a range object for pickling. */
958
951
Py_INCREF (r -> start );
952
+ Py_INCREF (r -> stop );
959
953
Py_INCREF (r -> step );
960
954
range = (PyObject * )make_range_object (& PyRange_Type ,
961
- r -> start , stop , r -> step );
955
+ r -> start , r -> stop , r -> step );
962
956
if (range == NULL ) {
963
957
Py_DECREF (r -> start );
964
- Py_DECREF (stop );
958
+ Py_DECREF (r -> stop );
965
959
Py_DECREF (r -> step );
966
960
return NULL ;
967
961
}
@@ -978,23 +972,28 @@ longrangeiter_setstate(longrangeiterobject *r, PyObject *state)
978
972
int cmp ;
979
973
980
974
/* clip the value */
981
- cmp = PyObject_RichCompareBool (state , zero , Py_LT );
975
+ cmp = PyObject_RichCompareBool (state , zero , Py_LE );
982
976
if (cmp < 0 )
983
977
return NULL ;
984
978
if (cmp > 0 ) {
985
- state = zero ;
979
+ Py_RETURN_NONE ;
986
980
}
987
- else {
988
- cmp = PyObject_RichCompareBool (r -> len , state , Py_LT );
989
- if (cmp < 0 )
990
- return NULL ;
991
- if (cmp > 0 )
992
- state = r -> len ;
981
+ PyObject * length = compute_range_length (r -> start , r -> stop , r -> step );
982
+ if (length == NULL ) {
983
+ return NULL ;
993
984
}
994
- PyObject * new_len = PyNumber_Subtract (r -> len , state );
995
- if (new_len == NULL )
985
+ cmp = PyObject_RichCompareBool (length , state , Py_LE );
986
+ if (cmp < 0 ) {
987
+ Py_DECREF (length );
996
988
return NULL ;
997
- Py_SETREF (r -> len , new_len );
989
+ }
990
+ if (cmp > 0 ) {
991
+ state = length ;
992
+ }
993
+ else {
994
+ Py_INCREF (state );
995
+ Py_DECREF (length );
996
+ }
998
997
PyObject * product = PyNumber_Multiply (state , r -> step );
999
998
if (product == NULL )
1000
999
return NULL ;
@@ -1020,29 +1019,24 @@ static void
1020
1019
longrangeiter_dealloc (longrangeiterobject * r )
1021
1020
{
1022
1021
Py_XDECREF (r -> start );
1022
+ Py_XDECREF (r -> stop );
1023
1023
Py_XDECREF (r -> step );
1024
- Py_XDECREF (r -> len );
1025
1024
PyObject_Free (r );
1026
1025
}
1027
1026
1028
1027
static PyObject *
1029
1028
longrangeiter_next (longrangeiterobject * r )
1030
1029
{
1031
- if (PyObject_RichCompareBool (r -> len , _PyLong_GetZero (), Py_GT ) != 1 )
1030
+ int s = _PyLong_Sign (r -> step );
1031
+ if (PyObject_RichCompareBool (r -> start , r -> stop , s > 0 ? Py_LT : Py_GT ) != 1 )
1032
1032
return NULL ;
1033
1033
1034
1034
PyObject * new_start = PyNumber_Add (r -> start , r -> step );
1035
1035
if (new_start == NULL ) {
1036
1036
return NULL ;
1037
1037
}
1038
- PyObject * new_len = PyNumber_Subtract (r -> len , _PyLong_GetOne ());
1039
- if (new_len == NULL ) {
1040
- Py_DECREF (new_start );
1041
- return NULL ;
1042
- }
1043
1038
PyObject * result = r -> start ;
1044
1039
r -> start = new_start ;
1045
- Py_SETREF (r -> len , new_len );
1046
1040
return result ;
1047
1041
}
1048
1042
@@ -1129,11 +1123,11 @@ range_iter(PyObject *seq)
1129
1123
return NULL ;
1130
1124
1131
1125
it -> start = r -> start ;
1126
+ it -> stop = r -> stop ;
1132
1127
it -> step = r -> step ;
1133
- it -> len = r -> length ;
1134
1128
Py_INCREF (it -> start );
1129
+ Py_INCREF (it -> stop );
1135
1130
Py_INCREF (it -> step );
1136
- Py_INCREF (it -> len );
1137
1131
return (PyObject * )it ;
1138
1132
}
1139
1133
@@ -1142,7 +1136,7 @@ range_reverse(PyObject *seq, PyObject *Py_UNUSED(ignored))
1142
1136
{
1143
1137
rangeobject * range = (rangeobject * ) seq ;
1144
1138
longrangeiterobject * it ;
1145
- PyObject * sum , * diff , * product ;
1139
+ PyObject * product ;
1146
1140
long lstart , lstop , lstep , new_start , new_stop ;
1147
1141
unsigned long ulen ;
1148
1142
@@ -1213,22 +1207,18 @@ range_reverse(PyObject *seq, PyObject *Py_UNUSED(ignored))
1213
1207
return NULL ;
1214
1208
it -> start = it -> step = NULL ;
1215
1209
1216
- /* start + (len - 1) * step */
1217
- it -> len = range -> length ;
1218
- Py_INCREF (it -> len );
1219
-
1220
- diff = PyNumber_Subtract (it -> len , _PyLong_GetOne ());
1221
- if (!diff )
1210
+ /* new_stop = start - step */
1211
+ it -> stop = PyNumber_Subtract (range -> start , range -> step );
1212
+ if (!it -> stop )
1222
1213
goto create_failure ;
1223
1214
1224
- product = PyNumber_Multiply ( diff , range -> step );
1225
- Py_DECREF ( diff );
1215
+ /* new_start = new_stop + len * step */
1216
+ product = PyNumber_Multiply ( range -> length , range -> step );
1226
1217
if (!product )
1227
1218
goto create_failure ;
1228
1219
1229
- sum = PyNumber_Add (range -> start , product );
1220
+ it -> start = PyNumber_Add (it -> stop , product );
1230
1221
Py_DECREF (product );
1231
- it -> start = sum ;
1232
1222
if (!it -> start )
1233
1223
goto create_failure ;
1234
1224
0 commit comments