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