Skip to content

Commit

Permalink
Deprecate +/- methods for array+scalar etc (#22932)
Browse files Browse the repository at this point in the history
The elementwise definition is incorrect for linear algebra.
  • Loading branch information
andyferris authored and andreasnoack committed Sep 12, 2017
1 parent 8757abf commit 780407c
Show file tree
Hide file tree
Showing 38 changed files with 185 additions and 156 deletions.
4 changes: 4 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -431,6 +431,10 @@ Deprecated or removed
* `map` on dictionaries previously operated on `key=>value` pairs. This behavior is deprecated,
and in the future `map` will operate only on values ([#5794]).

* Automatically broadcasted `+` and `-` for `array + scalar`, `scalar - array`, and so-on have
been deprecated due to inconsistency with linear algebra. Use `.+` and `.-` for these operations
instead.

Command-line option changes
---------------------------

Expand Down
2 changes: 1 addition & 1 deletion base/abstractarray.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1258,7 +1258,7 @@ function _cat(A, shape::NTuple{N}, catdims, X...) where N
for x in X
for i = 1:N
if concat[i]
inds[i] = offsets[i] + cat_indices(x, i)
inds[i] = offsets[i] .+ cat_indices(x, i)
offsets[i] += cat_size(x, i)
else
inds[i] = 1:shape[i]
Expand Down
4 changes: 2 additions & 2 deletions base/abstractarraymath.jl
Original file line number Diff line number Diff line change
Expand Up @@ -438,7 +438,7 @@ _reperr(s, n, N) = throw(ArgumentError("number of " * s * " repetitions " *
for c in CartesianRange(indices(A))
for i in 1:ndims(A)
n = inner[i]
inner_indices[i] = (1:n) + ((c[i] - 1) * n)
inner_indices[i] = (1:n) .+ ((c[i] - 1) * n)
end
fill!(view(R, inner_indices...), A[c])
end
Expand All @@ -453,7 +453,7 @@ _reperr(s, n, N) = throw(ArgumentError("number of " * s * " repetitions " *
for i in 1:length(outer)
B = view(R, src_indices...)
for j in 2:outer[i]
dest_indices[i] += inner_shape[i]
dest_indices[i] = dest_indices[i] .+ inner_shape[i]
R[dest_indices...] = B
end
src_indices[i] = dest_indices[i] = 1:shape[i]
Expand Down
2 changes: 1 addition & 1 deletion base/arraymath.jl
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ for f in (:+, :-)
end
end

for f in (:/, :\, :*, :+, :-)
for f in (:/, :\, :*)
if f != :/
@eval ($f)(A::Number, B::AbstractArray) = broadcast($f, A, B)
end
Expand Down
2 changes: 0 additions & 2 deletions base/dates/periods.jl
Original file line number Diff line number Diff line change
Expand Up @@ -358,8 +358,6 @@ GeneralPeriod = Union{Period, CompoundPeriod}

for op in (:+, :-)
@eval begin
($op)(x::GeneralPeriod, Y::StridedArray{<:GeneralPeriod}) = broadcast($op, x, Y)
($op)(Y::StridedArray{<:GeneralPeriod}, x::GeneralPeriod) = broadcast($op, Y, x)
($op)(X::StridedArray{<:GeneralPeriod}, Y::StridedArray{<:GeneralPeriod}) =
reshape(CompoundPeriod[($op)(x, y) for (x, y) in zip(X, Y)], promote_shape(size(X), size(Y)))
end
Expand Down
11 changes: 11 additions & 0 deletions base/deprecated.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1766,6 +1766,17 @@ import .Iterators.enumerate
# issue #5794
@deprecate map(f, d::T) where {T<:Associative} T( f(p) for p in pairs(d) )

# PR #22932
@deprecate +(a::Number, b::AbstractArray) broadcast(+, a, b)
@deprecate +(a::AbstractArray, b::Number) broadcast(+, a, b)
@deprecate -(a::Number, b::AbstractArray) broadcast(-, a, b)
@deprecate -(a::AbstractArray, b::Number) broadcast(-, a, b)

@deprecate +(a::Dates.GeneralPeriod, b::StridedArray{<:Dates.GeneralPeriod}) broadcast(+, a, b)
@deprecate +(a::StridedArray{<:Dates.GeneralPeriod}, b::Dates.GeneralPeriod) broadcast(+, a, b)
@deprecate -(a::Dates.GeneralPeriod, b::StridedArray{<:Dates.GeneralPeriod}) broadcast(-, a, b)
@deprecate -(a::StridedArray{<:Dates.GeneralPeriod}, b::Dates.GeneralPeriod) broadcast(-, a, b)

# END 0.7 deprecations

# BEGIN 1.0 deprecations
Expand Down
2 changes: 1 addition & 1 deletion base/gmp.jl
Original file line number Diff line number Diff line change
Expand Up @@ -613,7 +613,7 @@ function base(b::Integer, n::BigInt, pad::Integer=1)
nd = max(nd1, pad)
sv = Base.StringVector(nd + isneg(n))
MPZ.get_str!(pointer(sv) + nd - nd1, b, n)
@inbounds for i = (1:nd-nd1) + isneg(n)
@inbounds for i = (1:nd-nd1) .+ isneg(n)
sv[i] = '0' % UInt8
end
isneg(n) && (sv[1] = '-' % UInt8)
Expand Down
6 changes: 3 additions & 3 deletions base/linalg/arpack.jl
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,8 @@ function aupd_wrapper(T, matvecA!::Function, matvecB::Function, solveSI::Functio
throw(ARPACKException(info[]))
end

x = view(workd, ipntr[1]+zernm1)
y = view(workd, ipntr[2]+zernm1)
x = view(workd, ipntr[1] .+ zernm1)
y = view(workd, ipntr[2] .+ zernm1)
if mode == 1 # corresponds to dsdrv1, dndrv1 or zndrv1
if ido[] == 1
matvecA!(y, x)
Expand Down Expand Up @@ -87,7 +87,7 @@ function aupd_wrapper(T, matvecA!::Function, matvecB::Function, solveSI::Functio
if ido[] == -1
y[:] = solveSI(matvecB(x))
elseif ido[] == 1
y[:] = solveSI(view(workd,ipntr[3]+zernm1))
y[:] = solveSI(view(workd,ipntr[3] .+ zernm1))
elseif ido[] == 2
y[:] = matvecB(x)
elseif ido[] == 99
Expand Down
4 changes: 2 additions & 2 deletions base/linalg/bitarray.jl
Original file line number Diff line number Diff line change
Expand Up @@ -120,10 +120,10 @@ function kron(a::BitMatrix, b::BitMatrix)
R = falses(mA*mB, nA*nB)

for i = 1:mA
ri = (1:mB)+(i-1)*mB
ri = (1:mB) .+ ((i-1)*mB)
for j = 1:nA
if a[i,j]
rj = (1:nB)+(j-1)*nB
rj = (1:nB) .+ ((j-1)*nB)
R[ri,rj] = b
end
end
Expand Down
2 changes: 1 addition & 1 deletion base/linalg/symmetric.jl
Original file line number Diff line number Diff line change
Expand Up @@ -321,7 +321,7 @@ A_mul_Bt(A::AbstractTriangular, B::RealHermSymComplexSym) = A*B
Ac_mul_B(A::RealHermSymComplexHerm, B::AbstractTriangular) = A*B
A_mul_Bc(A::AbstractTriangular, B::RealHermSymComplexHerm) = A*B

for T in (:Symmetric, :Hermitian), op in (:+, :-, :*, :/)
for T in (:Symmetric, :Hermitian), op in (:*, :/)
# Deal with an ambiguous case
@eval ($op)(A::$T, x::Bool) = ($T)(($op)(A.data, x), Symbol(A.uplo))
S = T == :Hermitian ? :Real : :Number
Expand Down
4 changes: 2 additions & 2 deletions base/linalg/transpose.jl
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,8 @@ end
function transposeblock!(f, B::AbstractMatrix, A::AbstractMatrix, m::Int, n::Int, offseti::Int, offsetj::Int)
if m*n<=transposebaselength
@inbounds begin
for j = offsetj+(1:n)
for i = offseti+(1:m)
for j = offsetj .+ (1:n)
for i = offseti .+ (1:m)
B[j,i] = f(A[i,j])
end
end
Expand Down
2 changes: 1 addition & 1 deletion base/multidimensional.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1144,7 +1144,7 @@ end
@inline unchecked_bool_convert(x::Real) = x == 1

function copy_to_bitarray_chunks!(Bc::Vector{UInt64}, pos_d::Int, C::StridedArray{<:Real}, pos_s::Int, numbits::Int)
@inbounds for i = (1:numbits) + pos_s - 1
@inbounds for i = (1:numbits) .+ (pos_s - 1)
try_bool_conversion(C[i])
end

Expand Down
77 changes: 52 additions & 25 deletions base/range.jl
Original file line number Diff line number Diff line change
Expand Up @@ -741,43 +741,67 @@ end
StepRangeLen{T,R,S}(-r.ref, -r.step, length(r), r.offset)
-(r::LinSpace) = LinSpace(-r.start, -r.stop, length(r))

+(x::Real, r::AbstractUnitRange) = range(x + first(r), length(r))
*(x::Number, r::AbstractRange) = range(x*first(r), x*step(r), length(r))
*(x::Number, r::StepRangeLen{T}) where {T} =
StepRangeLen{typeof(x*T(r.ref))}(x*r.ref, x*r.step, length(r), r.offset)
*(x::Number, r::LinSpace) = LinSpace(x * r.start, x * r.stop, r.len)
# separate in case of noncommutative multiplication
*(r::AbstractRange, x::Number) = range(first(r)*x, step(r)*x, length(r))
*(r::StepRangeLen{T}, x::Number) where {T} =
StepRangeLen{typeof(T(r.ref)*x)}(r.ref*x, r.step*x, length(r), r.offset)
*(r::LinSpace, x::Number) = LinSpace(r.start * x, r.stop * x, r.len)

/(r::AbstractRange, x::Number) = range(first(r)/x, step(r)/x, length(r))
/(r::StepRangeLen{T}, x::Number) where {T} =
StepRangeLen{typeof(T(r.ref)/x)}(r.ref/x, r.step/x, length(r), r.offset)
/(r::LinSpace, x::Number) = LinSpace(r.start / x, r.stop / x, r.len)
# also, separate in case of noncommutative multiplication (division)
\(x::Number, r::AbstractRange) = range(x\first(r), x\step(r), x\length(r))
\(x::Number, r::StepRangeLen) = StepRangeLen(x\r.ref, x\r.step, length(r), r.offset)
\(x::Number, r::LinSpace) = LinSpace(x \ r.start, x \ r.stop, r.len)

## scalar-range broadcast operations ##

broadcast(::typeof(-), r::OrdinalRange) = range(-first(r), -step(r), length(r))
broadcast(::typeof(-), r::StepRangeLen) = StepRangeLen(-r.ref, -r.step, length(r), r.offset)
broadcast(::typeof(-), r::LinSpace) = LinSpace(-r.start, -r.stop, length(r))

broadcast(::typeof(+), x::Real, r::AbstractUnitRange) = range(x + first(r), length(r))
# For #18336 we need to prevent promotion of the step type:
+(x::Number, r::AbstractUnitRange) = range(x + first(r), step(r), length(r))
+(x::Number, r::AbstractRange) = (x+first(r)):step(r):(x+last(r))
function +(x::Number, r::StepRangeLen{T}) where T
broadcast(::typeof(+), x::Number, r::AbstractUnitRange) = range(x + first(r), step(r), length(r))
broadcast(::typeof(+), x::Number, r::AbstractRange) = (x+first(r)):step(r):(x+last(r))
function broadcast(::typeof(+), x::Number, r::StepRangeLen{T}) where T
newref = x + r.ref
StepRangeLen{typeof(T(r.ref) + x)}(newref, r.step, length(r), r.offset)
end
function +(x::Number, r::LinSpace)
function broadcast(::typeof(+), x::Number, r::LinSpace)
LinSpace(x + r.start, x + r.stop, r.len)
end
+(r::AbstractRange, x::Number) = x + r # assumes addition is commutative
broadcast(::typeof(+), r::AbstractRange, x::Number) = broadcast(+, x, r) # assumes addition is commutative

-(x::Number, r::AbstractRange) = (x-first(r)):-step(r):(x-last(r))
-(x::Number, r::StepRangeLen) = +(x, -r)
function -(x::Number, r::LinSpace)
broadcast(::typeof(-), x::Number, r::AbstractRange) = (x-first(r)):-step(r):(x-last(r))
broadcast(::typeof(-), x::Number, r::StepRangeLen) = broadcast(+, x, -r)
function broadcast(::typeof(-), x::Number, r::LinSpace)
LinSpace(x - r.start, x - r.stop, r.len)
end

-(r::AbstractRange, x::Number) = +(-x, r)
broadcast(::typeof(-), r::AbstractRange, x::Number) = broadcast(+, -x, r) # assumes addition is commutative

*(x::Number, r::AbstractRange) = range(x*first(r), x*step(r), length(r))
*(x::Number, r::StepRangeLen{T}) where {T} =
StepRangeLen{typeof(x*T(r.ref))}(x*r.ref, x*r.step, length(r), r.offset)
*(x::Number, r::LinSpace) = LinSpace(x * r.start, x * r.stop, r.len)
broadcast(::typeof(*), x::Number, r::AbstractRange) = range(x*first(r), x*step(r), length(r))
broadcast(::typeof(*), x::Number, r::StepRangeLen) = StepRangeLen(x*r.ref, x*r.step, length(r), r.offset)
broadcast(::typeof(*), x::Number, r::LinSpace) = LinSpace(x * r.start, x * r.stop, r.len)
# separate in case of noncommutative multiplication
*(r::AbstractRange, x::Number) = range(first(r)*x, step(r)*x, length(r))
*(r::StepRangeLen{T}, x::Number) where {T} =
StepRangeLen{typeof(T(r.ref)*x)}(r.ref*x, r.step*x, length(r), r.offset)
*(r::LinSpace, x::Number) = LinSpace(r.start * x, r.stop * x, r.len)

/(r::AbstractRange, x::Number) = range(first(r)/x, step(r)/x, length(r))
/(r::StepRangeLen{T}, x::Number) where {T} =
StepRangeLen{typeof(T(r.ref)/x)}(r.ref/x, r.step/x, length(r), r.offset)
/(r::LinSpace, x::Number) = LinSpace(r.start / x, r.stop / x, r.len)

/(x::Number, r::AbstractRange) = [ x/y for y=r ]
broadcast(::typeof(*), r::AbstractRange, x::Number) = range(first(r)*x, step(r)*x, length(r))
broadcast(::typeof(*), r::StepRangeLen, x::Number) = StepRangeLen(r.ref*x, r.step*x, length(r), r.offset)
broadcast(::typeof(*), r::LinSpace, x::Number) = LinSpace(r.start * x, r.stop * x, r.len)

broadcast(::typeof(/), r::AbstractRange, x::Number) = range(first(r)/x, step(r)/x, length(r))
broadcast(::typeof(/), r::StepRangeLen, x::Number) = StepRangeLen(r.ref/x, r.step/x, length(r), r.offset)
broadcast(::typeof(/), r::LinSpace, x::Number) = LinSpace(r.start / x, r.stop / x, r.len)
# also, separate in case of noncommutative multiplication (division)
broadcast(::typeof(\), x::Number, r::AbstractRange) = range(x\first(r), x\step(r), x\length(r))
broadcast(::typeof(\), x::Number, r::StepRangeLen) = StepRangeLen(x\r.ref, x\r.step, length(r), r.offset)
broadcast(::typeof(\), x::Number, r::LinSpace) = LinSpace(x \ r.start, x \ r.stop, r.len)

# promote eltype if at least one container wouldn't change, otherwise join container types.
el_same(::Type{T}, a::Type{<:AbstractArray{T,n}}, b::Type{<:AbstractArray{T,n}}) where {T,n} = a
Expand Down Expand Up @@ -961,3 +985,6 @@ function +(r1::StepRangeLen{T,S}, r2::StepRangeLen{T,S}) where {T,S}
end

-(r1::StepRangeLen, r2::StepRangeLen) = +(r1, -r2)

broadcast(::typeof(+), r1::AbstractRange, r2::AbstractRange) = r1 + r2
broadcast(::typeof(-), r1::AbstractRange, r2::AbstractRange) = r1 - r2
2 changes: 1 addition & 1 deletion base/repl/REPLCompletions.jl
Original file line number Diff line number Diff line change
Expand Up @@ -614,7 +614,7 @@ function shell_completions(string, pos)
r = first(last_parse):prevind(last_parse, last(last_parse))
partial = scs[r]
ret, range = completions(partial, endof(partial))
range += first(r) - 1
range = range .+ (first(r) - 1)
return ret, range, true
end
return String[], 0:-1, false
Expand Down
4 changes: 2 additions & 2 deletions base/show.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1653,7 +1653,7 @@ function print_matrix(io::IO, X::AbstractVecOrMat,
print(io, i == first(rowsA) ? pre : presp)
print_matrix_row(io, X,Lalign,i,colsA[1:length(Lalign)],sep)
print(io, (i - first(rowsA)) % hmod == 0 ? hdots : repeat(" ", length(hdots)))
print_matrix_row(io, X,Ralign,i,n-length(Ralign)+colsA,sep)
print_matrix_row(io, X, Ralign, i, (n - length(Ralign)) .+ colsA, sep)
print(io, i == last(rowsA) ? post : postsp)
if i != last(rowsA); println(io); end
end
Expand Down Expand Up @@ -1681,7 +1681,7 @@ function print_matrix(io::IO, X::AbstractVecOrMat,
print(io, i == first(rowsA) ? pre : presp)
print_matrix_row(io, X,Lalign,i,colsA[1:length(Lalign)],sep)
print(io, (i - first(rowsA)) % hmod == 0 ? hdots : repeat(" ", length(hdots)))
print_matrix_row(io, X,Ralign,i,n-length(Ralign)+colsA,sep)
print_matrix_row(io, X,Ralign,i,(n-length(Ralign)).+colsA,sep)
print(io, i == last(rowsA) ? post : postsp)
if i != rowsA[end] || i == rowsA[halfheight]; println(io); end
if i == rowsA[halfheight]
Expand Down
2 changes: 1 addition & 1 deletion base/sparse/cholmod.jl
Original file line number Diff line number Diff line change
Expand Up @@ -811,7 +811,7 @@ end
function get_perm(F::Factor)
s = unsafe_load(pointer(F))
p = unsafe_wrap(Array, s.Perm, s.n, false)
p + 1
p .+ 1
end
get_perm(FC::FactorComponent) = get_perm(Factor(FC))

Expand Down
4 changes: 2 additions & 2 deletions base/sparse/linalg.jl
Original file line number Diff line number Diff line change
Expand Up @@ -775,7 +775,7 @@ function kron(a::SparseMatrixCSC{Tv,Ti}, b::SparseMatrixCSC{Tv,Ti}) where {Tv,Ti
stopB = colptrB[i+1]-1
lB = stopB - startB + 1

ptr_range = (1:lB) + (colptr[col]-1)
ptr_range = (1:lB) .+ (colptr[col]-1)

colptr[col+1] = colptr[col] + lA * lB
col += 1
Expand All @@ -787,7 +787,7 @@ function kron(a::SparseMatrixCSC{Tv,Ti}, b::SparseMatrixCSC{Tv,Ti}) where {Tv,Ti
nzval[ptr] = nzvalA[ptrA] * nzvalB[ptrB]
ptrB += 1
end
ptr_range += lB
ptr_range = ptr_range .+ lB
end
end
end
Expand Down
16 changes: 8 additions & 8 deletions base/sparse/sparsematrix.jl
Original file line number Diff line number Diff line change
Expand Up @@ -3115,13 +3115,13 @@ function hcat(X::SparseMatrixCSC...)
nX_sofar = 0
@inbounds for i = 1 : num
XI = X[i]
colptr[(1 : nX[i] + 1) + nX_sofar] = XI.colptr .+ nnz_sofar
colptr[(1 : nX[i] + 1) .+ nX_sofar] = XI.colptr .+ nnz_sofar
if nnzX[i] == length(XI.rowval)
rowval[(1 : nnzX[i]) + nnz_sofar] = XI.rowval
nzval[(1 : nnzX[i]) + nnz_sofar] = XI.nzval
rowval[(1 : nnzX[i]) .+ nnz_sofar] = XI.rowval
nzval[(1 : nnzX[i]) .+ nnz_sofar] = XI.nzval
else
rowval[(1 : nnzX[i]) + nnz_sofar] = XI.rowval[1:nnzX[i]]
nzval[(1 : nnzX[i]) + nnz_sofar] = XI.nzval[1:nnzX[i]]
rowval[(1 : nnzX[i]) .+ nnz_sofar] = XI.rowval[1:nnzX[i]]
nzval[(1 : nnzX[i]) .+ nnz_sofar] = XI.nzval[1:nnzX[i]]
end
nnz_sofar += nnzX[i]
nX_sofar += nX[i]
Expand Down Expand Up @@ -3166,9 +3166,9 @@ function blkdiag(X::SparseMatrixCSC...)
nX_sofar = 0
mX_sofar = 0
for i = 1 : num
colptr[(1 : nX[i] + 1) + nX_sofar] = X[i].colptr .+ nnz_sofar
rowval[(1 : nnzX[i]) + nnz_sofar] = X[i].rowval .+ mX_sofar
nzval[(1 : nnzX[i]) + nnz_sofar] = X[i].nzval
colptr[(1 : nX[i] + 1) .+ nX_sofar] = X[i].colptr .+ nnz_sofar
rowval[(1 : nnzX[i]) .+ nnz_sofar] = X[i].rowval .+ mX_sofar
nzval[(1 : nnzX[i]) .+ nnz_sofar] = X[i].nzval
nnz_sofar += nnzX[i]
nX_sofar += nX[i]
mX_sofar += mX[i]
Expand Down
6 changes: 3 additions & 3 deletions base/sparse/sparsevector.jl
Original file line number Diff line number Diff line change
Expand Up @@ -994,7 +994,7 @@ function hvcat(rows::Tuple{Vararg{Int}}, X::_SparseConcatGroup...)
tmp_rows = Vector{SparseMatrixCSC}(nbr)
k = 0
@inbounds for i = 1 : nbr
tmp_rows[i] = hcat(X[(1 : rows[i]) + k]...)
tmp_rows[i] = hcat(X[(1 : rows[i]) .+ k]...)
k += rows[i]
end
vcat(tmp_rows...)
Expand Down Expand Up @@ -1827,7 +1827,7 @@ for isunittri in (true, false), islowertri in (true, false)
nzrange = $( (islowertri && !istrans) || (!islowertri && istrans) ?
:(b.nzind[1]:b.n) :
:(1:b.nzind[end]) )
nzrangeviewbnz = view(b.nzval, nzrange - b.nzind[1] + 1)
nzrangeviewbnz = view(b.nzval, nzrange .- (b.nzind[1] - 1))
nzrangeviewA = $tritype(view(A.data, nzrange, nzrange))
($func)(nzrangeviewA, nzrangeviewbnz)
# could strip any miraculous zeros here perhaps
Expand Down Expand Up @@ -1892,7 +1892,7 @@ function sort(x::SparseVector{Tv,Ti}; kws...) where {Tv,Ti}
n,k = length(x),length(allvals)
z = findfirst(sinds,k)
newnzind = collect(Ti,1:k-1)
newnzind[z:end]+= n-k+1
newnzind[z:end] .+= n-k+1
newnzvals = allvals[deleteat!(sinds[1:k],z)]
SparseVector(n,newnzind,newnzvals)
end
Expand Down
4 changes: 2 additions & 2 deletions test/TestHelpers.jl
Original file line number Diff line number Diff line change
Expand Up @@ -147,9 +147,9 @@ Base.eachindex(::IndexLinear, A::OffsetVector) = indices(A, 1)
# Implementations of indices and indices1. Since bounds-checking is
# performance-critical and relies on indices, these are usually worth
# optimizing thoroughly.
@inline Base.indices(A::OffsetArray, d) = 1 <= d <= length(A.offsets) ? indices(parent(A))[d] + A.offsets[d] : (1:1)
@inline Base.indices(A::OffsetArray, d) = 1 <= d <= length(A.offsets) ? indices(parent(A))[d] .+ A.offsets[d] : (1:1)
@inline Base.indices(A::OffsetArray) = _indices(indices(parent(A)), A.offsets) # would rather use ntuple, but see #15276
@inline _indices(inds, offsets) = (inds[1]+offsets[1], _indices(tail(inds), tail(offsets))...)
@inline _indices(inds, offsets) = (inds[1] .+ offsets[1], _indices(tail(inds), tail(offsets))...)
_indices(::Tuple{}, ::Tuple{}) = ()
Base.indices1(A::OffsetArray{T,0}) where {T} = 1:1 # we only need to specialize this one

Expand Down
Loading

0 comments on commit 780407c

Please sign in to comment.