@@ -689,10 +689,6 @@ axes(r::AbstractRange) = (oneto(length(r)),)
689
689
690
690
# Needed to ensure `has_offset_axes` can constant-fold.
691
691
has_offset_axes (:: StepRange ) = false
692
- let baseints = Union{Int8,UInt8,Int16,UInt16,Int32,UInt32,Int64,UInt64,Int128,UInt128}
693
- global firstindex
694
- firstindex (:: StepRange{T,<:baseints} ) where {T<: baseints } = sizeof (T) < sizeof (Int) ? 1 : one (T)
695
- end
696
692
697
693
# n.b. checked_length for these is defined iff checked_add and checked_sub are
698
694
# defined between the relevant types
@@ -755,64 +751,66 @@ length(r::OneTo) = Integer(r.stop - zero(r.stop))
755
751
length (r:: StepRangeLen ) = r. len
756
752
length (r:: LinRange ) = r. len
757
753
758
- let bigints = Union{Int, UInt, Int64, UInt64, Int128, UInt128}
759
- global length, checked_length
754
+ let bigints = Union{Int, UInt, Int64, UInt64, Int128, UInt128},
755
+ smallints = (Int === Int64 ?
756
+ Union{Int8, UInt8, Int16, UInt16, Int32, UInt32} :
757
+ Union{Int8, UInt8, Int16, UInt16}),
758
+ bitints = Union{bigints, smallints}
759
+ global length, checked_length, firstindex
760
760
# compile optimization for which promote_type(T, Int) == T
761
761
length (r:: OneTo{T} ) where {T<: bigints } = r. stop
762
762
# slightly more accurate length and checked_length in extreme cases
763
763
# (near typemax) for types with known `unsigned` functions
764
764
function length (r:: OrdinalRange{T} ) where T<: bigints
765
765
s = step (r)
766
- isempty (r) && return zero (T)
767
766
diff = last (r) - first (r)
767
+ isempty (r) && return zero (diff)
768
768
# if |s| > 1, diff might have overflowed, but unsigned(diff)÷s should
769
769
# therefore still be valid (if the result is representable at all)
770
770
# n.b. !(s isa T)
771
771
if s isa Unsigned || - 1 <= s <= 1 || s == - s
772
- a = div (diff, s) % T
772
+ a = div (diff, s) % typeof (diff)
773
773
elseif s < 0
774
- a = div (unsigned (- diff), - s) % T
774
+ a = div (unsigned (- diff), - s) % typeof (diff)
775
775
else
776
- a = div (unsigned (diff), s) % T
776
+ a = div (unsigned (diff), s) % typeof (diff)
777
777
end
778
- return a + oneunit (T )
778
+ return a + oneunit (a )
779
779
end
780
780
function checked_length (r:: OrdinalRange{T} ) where T<: bigints
781
781
s = step (r)
782
- isempty (r) && return zero (T)
783
782
stop, start = last (r), first (r)
783
+ ET = promote_type (typeof (stop), typeof (start))
784
+ isempty (r) && return zero (ET)
784
785
# n.b. !(s isa T)
785
786
if s > 1
786
787
diff = stop - start
787
- a = convert (T , div (unsigned (diff), s))
788
+ a = convert (ET , div (unsigned (diff), s))
788
789
elseif s < - 1
789
790
diff = start - stop
790
- a = convert (T , div (unsigned (diff), - s))
791
+ a = convert (ET , div (unsigned (diff), - s))
791
792
elseif s > 0
792
- a = div (checked_sub (stop, start), s)
793
+ a = convert (ET, div (checked_sub (stop, start), s) )
793
794
else
794
- a = div (checked_sub (start, stop), - s)
795
+ a = convert (ET, div (checked_sub (start, stop), - s) )
795
796
end
796
- return checked_add (convert (T, a) , oneunit (T ))
797
+ return checked_add (a , oneunit (a ))
797
798
end
798
- end
799
+ firstindex (r :: StepRange{<:bigints,<:bitints} ) = one ( last (r) - first (r))
799
800
800
- # some special cases to favor default Int type
801
- let smallints = (Int === Int64 ?
802
- Union{Int8, UInt8, Int16, UInt16, Int32, UInt32} :
803
- Union{Int8, UInt8, Int16, UInt16})
804
- global length, checked_length
805
- # n.b. !(step isa T)
801
+ # some special cases to favor default Int type
806
802
function length (r:: OrdinalRange{<:smallints} )
807
803
s = step (r)
808
804
isempty (r) && return 0
805
+ # n.b. !(step isa T)
809
806
return Int (div (Int (last (r)) - Int (first (r)), s)) + 1
810
807
end
811
808
length (r:: AbstractUnitRange{<:smallints} ) = Int (last (r)) - Int (first (r)) + 1
812
809
length (r:: OneTo{<:smallints} ) = Int (r. stop)
813
810
checked_length (r:: OrdinalRange{<:smallints} ) = length (r)
814
811
checked_length (r:: AbstractUnitRange{<:smallints} ) = length (r)
815
812
checked_length (r:: OneTo{<:smallints} ) = length (r)
813
+ firstindex (:: StepRange{<:smallints,<:bitints} ) = 1
816
814
end
817
815
818
816
first (r:: OrdinalRange{T} ) where {T} = convert (T, r. start)
0 commit comments