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