diff --git a/Project.toml b/Project.toml index 45fda1893..bf38b8494 100644 --- a/Project.toml +++ b/Project.toml @@ -1,6 +1,6 @@ name = "ArrayInterface" uuid = "4fba245c-0d91-5ea0-9b3e-6abc04ee57a9" -version = "3.2.2" +version = "4" [deps] Compat = "34da2185-b29b-5c13-b0c7-acf172513d20" @@ -14,20 +14,5 @@ Static = "aedffcd0-7271-4cad-89d0-dc628f76c6d3" Compat = "3.37" IfElse = "0.1" Requires = "0.5, 1.0" -Static = "0.4" +Static = "0.5" julia = "1.2" - -[extras] -Aqua = "4c88cf16-eb10-579e-8560-4a9242c79595" -BandedMatrices = "aae01518-5342-5314-be14-df237901396f" -BlockBandedMatrices = "ffab5731-97b5-5995-9138-79e8c1846df0" -IfElse = "615f187c-cbe4-4ef1-ba3b-2fcf58d6d173" -LabelledArrays = "2ee39098-c373-598a-b85f-a56591580800" -OffsetArrays = "6fe1bfb0-de20-5000-8ca7-80f57d26f881" -Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" -StaticArrays = "90137ffa-7385-5640-81b9-e52037218182" -SuiteSparse = "4607b0f0-06f3-5cda-b6b1-a6196a1729e9" -Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" - -[targets] -test = ["Test", "LabelledArrays", "StaticArrays", "BandedMatrices", "BlockBandedMatrices", "SuiteSparse", "Random", "OffsetArrays", "Aqua", "IfElse"] diff --git a/docs/src/api.md b/docs/src/api.md index cab8f0c40..2ef0588ee 100644 --- a/docs/src/api.md +++ b/docs/src/api.md @@ -57,7 +57,6 @@ ArrayInterface.matrix_colors ArrayInterface.offset1 ArrayInterface.offsets ArrayInterface.parent_type -ArrayInterface.reduce_tup ArrayInterface.restructure ArrayInterface.safevec ArrayInterface.setindex! diff --git a/docs/src/index.md b/docs/src/index.md index 0fc669969..030dc9f91 100644 --- a/docs/src/index.md +++ b/docs/src/index.md @@ -44,7 +44,7 @@ julia> ArrayInterface.size(a) (static(1), 3) julia> ArrayInterface.known_size(typeof(a)) -(1, nothing) +(1, missing) ``` @@ -62,8 +62,8 @@ Methods should avoid forcing conversion to static sizes when dynamic sizes could Fore example, `fxn(x) = _fxn(Static.static(ArrayInterface.size(x)), x)` would result in dynamic dispatch if `x` is an instance of `Matrix`. Additionally, `ArrayInterface.size` should only be used outside of generated functions to avoid possible world age issues. -Generally, `ArrayInterface.size` uses the return of `known_size` to form a static value for those dimensions with known length and only queries dimensions corresponding to `nothing`. -For example, the previous example had a known size of `(1, nothing)`. +Generally, `ArrayInterface.size` uses the return of `known_size` to form a static value for those dimensions with known length and only queries dimensions corresponding to `missing`. +For example, the previous example had a known size of `(1, missing)`. Therefore, `ArrayInterface.size` would have compile time information about the first dimension returned as `static(1)` and would only look up the size of the second dimension at run time. This means the above example `ArrayInterface.size(a)` would lower to code similar to this at compile time: `Static.StaticInt(1), Base.arraysize(x, 1)`. Generic support for `ArrayInterface.known_size` relies on calling `known_length` for each type returned from `axes_types`. @@ -155,7 +155,7 @@ using ArrayInterface: axes_types, parent_type, to_dims for dim in 1:ndims(A) # offset relative to parent array O = relative_known_offsets(A, dim) - if O === nothing # offset is not known at compile time and is an `Int` + if O === missing # offset is not known at compile time and is an `Int` push!(out.args, :(IdOffsetRange{Int, axes_types($P, $(static(dim)))})) else # offset is known, therefore it is a `StaticInt` push!(out.args, :(IdOffsetRange{StaticInt{$O}, axes_types($P, $(static(dim))})) diff --git a/src/ArrayInterface.jl b/src/ArrayInterface.jl index 9536c6e85..03b856eef 100644 --- a/src/ArrayInterface.jl +++ b/src/ArrayInterface.jl @@ -5,8 +5,8 @@ using Requires using LinearAlgebra using SparseArrays using Static -using Static: Zero, One, nstatic, _get_tuple, eq, ne, gt, ge, lt, le, eachop, eachop_tuple, - find_first_eq, permute, invariant_permutation +using Static: Zero, One, nstatic, eq, ne, gt, ge, lt, le, eachop, eachop_tuple, + find_first_eq, permute, invariant_permutation, field_type, reduce_tup using Base.Cartesian import Compat @@ -81,10 +81,10 @@ buffer(x::SparseMatrixCSC) = getfield(x, :nzval) buffer(x::SparseVector) = getfield(x, :nzval) """ - known_length(::Type{T}) -> Union{Int,Nothing} + known_length(::Type{T}) -> Union{Int,Missing} If `length` of an instance of type `T` is known at compile time, return it. -Otherwise, return `nothing`. +Otherwise, return `missing`. """ known_length(x) = known_length(typeof(x)) known_length(::Type{<:NamedTuple{L}}) where {L} = length(L) @@ -95,13 +95,11 @@ known_length(::Type{<:Number}) = 1 known_length(::Type{<:AbstractCartesianIndex{N}}) where {N} = N function known_length(::Type{T}) where {T} if parent_type(T) <: T - return nothing + return missing else - return _known_length(known_size(T)) + return prod(known_size(T)) end end -_known_length(x::Tuple{Vararg{Union{Nothing,Int}}}) = nothing -_known_length(x::Tuple{Vararg{Int}}) = prod(x) """ can_change_size(::Type{T}) -> Bool @@ -419,10 +417,10 @@ Indicates the most efficient way to access elements from the collection in low-l For `GPUArrays`, will return `ArrayInterface.GPU()`. For `AbstractArray` supporting a `pointer` method, returns `ArrayInterface.CPUPointer()`. For other `AbstractArray`s and `Tuple`s, returns `ArrayInterface.CPUIndex()`. -Otherwise, returns `nothing`. +Otherwise, returns `missing`. """ device(A) = device(typeof(A)) -device(::Type) = nothing +device(::Type) = missing device(::Type{<:Tuple}) = CPUTuple() device(::Type{T}) where {T<:Array} = CPUPointer() device(::Type{T}) where {T<:AbstractArray} = _device(has_parent(T), T) @@ -601,7 +599,7 @@ end function Base.length(A::AbstractArray2) len = known_length(A) - if len === nothing + if len === missing return Int(prod(size(A))) else return Int(len) @@ -807,6 +805,53 @@ function __init__() end @require BandedMatrices = "aae01518-5342-5314-be14-df237901396f" begin + struct BandedMatrixIndex <: MatrixIndex + count::Int + rowsize::Int + colsize::Int + bandinds::Array{Int,1} + bandsizes::Array{Int,1} + isrow::Bool + end + + Base.firstindex(i::BandedMatrixIndex) = 1 + Base.lastindex(i::BandedMatrixIndex) = i.count + Base.length(i::BandedMatrixIndex) = lastindex(i) + @propagate_inbounds function Base.getindex(ind::BandedMatrixIndex, i::Int) + @boundscheck 1 <= i <= ind.count || throw(BoundsError(ind, i)) + _i = i + p = 1 + while _i - ind.bandsizes[p] > 0 + _i -= ind.bandsizes[p] + p += 1 + end + bandind = ind.bandinds[p] + startfromone = !xor(ind.isrow, (bandind > 0)) + if startfromone + return _i + else + return _i + abs(bandind) + end + end + + function _bandsize(bandind, rowsize, colsize) + -(rowsize - 1) <= bandind <= colsize - 1 || throw(ErrorException("Invalid Bandind")) + if (bandind * (colsize - rowsize) > 0) & (abs(bandind) <= abs(colsize - rowsize)) + return min(rowsize, colsize) + elseif bandind * (colsize - rowsize) <= 0 + return min(rowsize, colsize) - abs(bandind) + else + return min(rowsize, colsize) - abs(bandind) + abs(colsize - rowsize) + end + end + + function BandedMatrixIndex(rowsize, colsize, lowerbandwidth, upperbandwidth, isrow) + upperbandwidth > -lowerbandwidth || throw(ErrorException("Invalid Bandwidths")) + bandinds = upperbandwidth:-1:-lowerbandwidth + bandsizes = [_bandsize(band, rowsize, colsize) for band in bandinds] + BandedMatrixIndex(sum(bandsizes), rowsize, colsize, bandinds, bandsizes, isrow) + end + function findstructralnz(x::BandedMatrices.BandedMatrix) l, u = BandedMatrices.bandwidths(x) rowsize, colsize = Base.size(x) @@ -829,6 +874,82 @@ function __init__() @require BlockBandedMatrices = "ffab5731-97b5-5995-9138-79e8c1846df0" begin @require BlockArrays = "8e7c35d0-a365-5155-bbbb-fb81a777f24e" begin + struct BlockBandedMatrixIndex <: MatrixIndex + count::Int + refinds::Array{Int,1} + refcoords::Array{Int,1}# storing col or row inds at ref points + isrow::Bool + end + Base.firstindex(i::BlockBandedMatrixIndex) = 1 + Base.lastindex(i::BlockBandedMatrixIndex) = i.count + Base.length(i::BlockBandedMatrixIndex) = lastindex(i) + function BlockBandedMatrixIndex(nrowblock, ncolblock, rowsizes, colsizes, l, u) + blockrowind = BandedMatrixIndex(nrowblock, ncolblock, l, u, true) + blockcolind = BandedMatrixIndex(nrowblock, ncolblock, l, u, false) + sortedinds = sort( + [(blockrowind[i], blockcolind[i]) for i = 1:length(blockrowind)], + by = x -> x[1], + ) + sort!(sortedinds, by = x -> x[2], alg = InsertionSort)# stable sort keeps the second index in order + refinds = Array{Int,1}() + refrowcoords = Array{Int,1}() + refcolcoords = Array{Int,1}() + rowheights = pushfirst!(copy(rowsizes), 1) + cumsum!(rowheights, rowheights) + blockheight = 0 + blockrow = 1 + blockcol = 1 + currenti = 1 + lastrowind = sortedinds[1][1] - 1 + lastcolind = sortedinds[1][2] + for ind in sortedinds + rowind, colind = ind + if colind == lastcolind + if rowind > lastrowind + blockheight += rowsizes[rowind] + end + else + for j = blockcol:blockcol+colsizes[lastcolind]-1 + push!(refinds, currenti) + push!(refrowcoords, blockrow) + push!(refcolcoords, j) + currenti += blockheight + end + blockcol += colsizes[lastcolind] + blockrow = rowheights[rowind] + blockheight = rowsizes[rowind] + end + lastcolind = colind + lastrowind = rowind + end + for j = blockcol:blockcol+colsizes[lastcolind]-1 + push!(refinds, currenti) + push!(refrowcoords, blockrow) + push!(refcolcoords, j) + currenti += blockheight + end + push!(refinds, currenti)# guard + push!(refrowcoords, -1) + push!(refcolcoords, -1) + rowindobj = BlockBandedMatrixIndex(currenti - 1, refinds, refrowcoords, true) + colindobj = BlockBandedMatrixIndex(currenti - 1, refinds, refcolcoords, false) + rowindobj, colindobj + end + @propagate_inbounds function Base.getindex(ind::BlockBandedMatrixIndex, i::Int) + @boundscheck 1 <= i <= ind.count || throw(BoundsError(ind, i)) + p = 1 + while i - ind.refinds[p] >= 0 + p += 1 + end + p -= 1 + _i = i - ind.refinds[p] + if ind.isrow + return ind.refcoords[p] + _i + else + return ind.refcoords[p] + end + end + function findstructralnz(x::BlockBandedMatrices.BlockBandedMatrix) l, u = BlockBandedMatrices.blockbandwidths(x) nrowblock = BlockBandedMatrices.blocksize(x, 1) @@ -844,6 +965,87 @@ function __init__() u, ) end + struct BandedBlockBandedMatrixIndex <: MatrixIndex + count::Int + refinds::Array{Int,1} + refcoords::Array{Int,1}# storing col or row inds at ref points + reflocalinds::Array{BandedMatrixIndex,1} + isrow::Bool + end + Base.firstindex(i::BandedBlockBandedMatrixIndex) = 1 + Base.lastindex(i::BandedBlockBandedMatrixIndex) = i.count + Base.length(i::BandedBlockBandedMatrixIndex) = lastindex(i) + @propagate_inbounds function Base.getindex(ind::BandedBlockBandedMatrixIndex, i::Int) + @boundscheck 1 <= i <= ind.count || throw(BoundsError(ind, i)) + p = 1 + while i - ind.refinds[p] >= 0 + p += 1 + end + p -= 1 + _i = i - ind.refinds[p] + 1 + ind.reflocalinds[p][_i] + ind.refcoords[p] - 1 + end + + + function BandedBlockBandedMatrixIndex( + nrowblock, + ncolblock, + rowsizes, + colsizes, + l, + u, + lambda, + mu, + ) + blockrowind = BandedMatrixIndex(nrowblock, ncolblock, l, u, true) + blockcolind = BandedMatrixIndex(nrowblock, ncolblock, l, u, false) + sortedinds = sort( + [(blockrowind[i], blockcolind[i]) for i = 1:length(blockrowind)], + by = x -> x[1], + ) + sort!(sortedinds, by = x -> x[2], alg = InsertionSort)# stable sort keeps the second index in order + rowheights = pushfirst!(copy(rowsizes), 1) + cumsum!(rowheights, rowheights) + colwidths = pushfirst!(copy(colsizes), 1) + cumsum!(colwidths, colwidths) + currenti = 1 + refinds = Array{Int,1}() + refrowcoords = Array{Int,1}() + refcolcoords = Array{Int,1}() + reflocalrowinds = Array{BandedMatrixIndex,1}() + reflocalcolinds = Array{BandedMatrixIndex,1}() + for ind in sortedinds + rowind, colind = ind + localrowind = + BandedMatrixIndex(rowsizes[rowind], colsizes[colind], lambda, mu, true) + localcolind = + BandedMatrixIndex(rowsizes[rowind], colsizes[colind], lambda, mu, false) + push!(refinds, currenti) + push!(refrowcoords, rowheights[rowind]) + push!(refcolcoords, colwidths[colind]) + push!(reflocalrowinds, localrowind) + push!(reflocalcolinds, localcolind) + currenti += localrowind.count + end + push!(refinds, currenti) + push!(refrowcoords, -1) + push!(refcolcoords, -1) + rowindobj = BandedBlockBandedMatrixIndex( + currenti - 1, + refinds, + refrowcoords, + reflocalrowinds, + true, + ) + colindobj = BandedBlockBandedMatrixIndex( + currenti - 1, + refinds, + refcolcoords, + reflocalcolinds, + false, + ) + rowindobj, colindobj + end function findstructralnz(x::BlockBandedMatrices.BandedBlockBandedMatrix) l, u = BlockBandedMatrices.blockbandwidths(x) @@ -936,7 +1138,7 @@ function __init__() Static.eachop_tuple(_offset_axis_type, Static.nstatic(Val(ndims(T))), ArrayInterface.parent_type(T)) end function ArrayInterface.known_offsets(::Type{A}) where {A<:OffsetArrays.OffsetArray} - ntuple(identity -> nothing, Val(ndims(A))) + ntuple(identity -> missing, Val(ndims(A))) end function ArrayInterface.offsets(A::OffsetArrays.OffsetArray) map(+, ArrayInterface.offsets(parent(A)), relative_offsets(A)) diff --git a/src/array_index.jl b/src/array_index.jl index 3e1ce456f..24137aab7 100644 --- a/src/array_index.jl +++ b/src/array_index.jl @@ -28,161 +28,10 @@ struct TridiagonalIndex <: MatrixIndex isrow::Bool end -struct BandedMatrixIndex <: MatrixIndex - count::Int - rowsize::Int - colsize::Int - bandinds::Array{Int,1} - bandsizes::Array{Int,1} - isrow::Bool -end - -function _bandsize(bandind, rowsize, colsize) - -(rowsize - 1) <= bandind <= colsize - 1 || throw(ErrorException("Invalid Bandind")) - if (bandind * (colsize - rowsize) > 0) & (abs(bandind) <= abs(colsize - rowsize)) - return min(rowsize, colsize) - elseif bandind * (colsize - rowsize) <= 0 - return min(rowsize, colsize) - abs(bandind) - else - return min(rowsize, colsize) - abs(bandind) + abs(colsize - rowsize) - end -end - -function BandedMatrixIndex(rowsize, colsize, lowerbandwidth, upperbandwidth, isrow) - upperbandwidth > -lowerbandwidth || throw(ErrorException("Invalid Bandwidths")) - bandinds = upperbandwidth:-1:-lowerbandwidth - bandsizes = [_bandsize(band, rowsize, colsize) for band in bandinds] - BandedMatrixIndex(sum(bandsizes), rowsize, colsize, bandinds, bandsizes, isrow) -end - -struct BlockBandedMatrixIndex <: MatrixIndex - count::Int - refinds::Array{Int,1} - refcoords::Array{Int,1}# storing col or row inds at ref points - isrow::Bool -end - -function BlockBandedMatrixIndex(nrowblock, ncolblock, rowsizes, colsizes, l, u) - blockrowind = BandedMatrixIndex(nrowblock, ncolblock, l, u, true) - blockcolind = BandedMatrixIndex(nrowblock, ncolblock, l, u, false) - sortedinds = sort( - [(blockrowind[i], blockcolind[i]) for i = 1:length(blockrowind)], - by = x -> x[1], - ) - sort!(sortedinds, by = x -> x[2], alg = InsertionSort)# stable sort keeps the second index in order - refinds = Array{Int,1}() - refrowcoords = Array{Int,1}() - refcolcoords = Array{Int,1}() - rowheights = pushfirst!(copy(rowsizes), 1) - cumsum!(rowheights, rowheights) - blockheight = 0 - blockrow = 1 - blockcol = 1 - currenti = 1 - lastrowind = sortedinds[1][1] - 1 - lastcolind = sortedinds[1][2] - for ind in sortedinds - rowind, colind = ind - if colind == lastcolind - if rowind > lastrowind - blockheight += rowsizes[rowind] - end - else - for j = blockcol:blockcol+colsizes[lastcolind]-1 - push!(refinds, currenti) - push!(refrowcoords, blockrow) - push!(refcolcoords, j) - currenti += blockheight - end - blockcol += colsizes[lastcolind] - blockrow = rowheights[rowind] - blockheight = rowsizes[rowind] - end - lastcolind = colind - lastrowind = rowind - end - for j = blockcol:blockcol+colsizes[lastcolind]-1 - push!(refinds, currenti) - push!(refrowcoords, blockrow) - push!(refcolcoords, j) - currenti += blockheight - end - push!(refinds, currenti)# guard - push!(refrowcoords, -1) - push!(refcolcoords, -1) - rowindobj = BlockBandedMatrixIndex(currenti - 1, refinds, refrowcoords, true) - colindobj = BlockBandedMatrixIndex(currenti - 1, refinds, refcolcoords, false) - rowindobj, colindobj -end - -struct BandedBlockBandedMatrixIndex <: MatrixIndex - count::Int - refinds::Array{Int,1} - refcoords::Array{Int,1}# storing col or row inds at ref points - reflocalinds::Array{BandedMatrixIndex,1} - isrow::Bool -end - -function BandedBlockBandedMatrixIndex( - nrowblock, - ncolblock, - rowsizes, - colsizes, - l, - u, - lambda, - mu, -) - blockrowind = BandedMatrixIndex(nrowblock, ncolblock, l, u, true) - blockcolind = BandedMatrixIndex(nrowblock, ncolblock, l, u, false) - sortedinds = sort( - [(blockrowind[i], blockcolind[i]) for i = 1:length(blockrowind)], - by = x -> x[1], - ) - sort!(sortedinds, by = x -> x[2], alg = InsertionSort)# stable sort keeps the second index in order - rowheights = pushfirst!(copy(rowsizes), 1) - cumsum!(rowheights, rowheights) - colwidths = pushfirst!(copy(colsizes), 1) - cumsum!(colwidths, colwidths) - currenti = 1 - refinds = Array{Int,1}() - refrowcoords = Array{Int,1}() - refcolcoords = Array{Int,1}() - reflocalrowinds = Array{BandedMatrixIndex,1}() - reflocalcolinds = Array{BandedMatrixIndex,1}() - for ind in sortedinds - rowind, colind = ind - localrowind = - BandedMatrixIndex(rowsizes[rowind], colsizes[colind], lambda, mu, true) - localcolind = - BandedMatrixIndex(rowsizes[rowind], colsizes[colind], lambda, mu, false) - push!(refinds, currenti) - push!(refrowcoords, rowheights[rowind]) - push!(refcolcoords, colwidths[colind]) - push!(reflocalrowinds, localrowind) - push!(reflocalcolinds, localcolind) - currenti += localrowind.count - end - push!(refinds, currenti) - push!(refrowcoords, -1) - push!(refcolcoords, -1) - rowindobj = BandedBlockBandedMatrixIndex( - currenti - 1, - refinds, - refrowcoords, - reflocalrowinds, - true, - ) - colindobj = BandedBlockBandedMatrixIndex( - currenti - 1, - refinds, - refcolcoords, - reflocalcolinds, - false, - ) - rowindobj, colindobj -end - +Base.firstindex(i::Union{BidiagonalIndex,TridiagonalIndex}) = 1 +Base.lastindex(i::Union{BidiagonalIndex,TridiagonalIndex}) = i.count +Base.length(i::Union{BidiagonalIndex,TridiagonalIndex}) = lastindex(i) + """ StrideIndex(x) @@ -204,10 +53,6 @@ struct StrideIndex{N,R,C,S,O} <: ArrayIndex{N} end end -Base.firstindex(i::Union{TridiagonalIndex,BandedBlockBandedMatrixIndex,BandedMatrixIndex,BidiagonalIndex,BlockBandedMatrixIndex}) = 1 -Base.lastindex(i::Union{TridiagonalIndex,BandedBlockBandedMatrixIndex,BandedMatrixIndex,BidiagonalIndex,BlockBandedMatrixIndex}) = i.count -Base.length(i::Union{TridiagonalIndex,BandedBlockBandedMatrixIndex,BandedMatrixIndex,BidiagonalIndex,BlockBandedMatrixIndex}) = i.count - ## getindex @propagate_inbounds Base.getindex(x::ArrayIndex, i::CanonicalInt, ii::CanonicalInt...) = x[NDIndex(i, ii...)] @propagate_inbounds function Base.getindex(ind::BidiagonalIndex, i::Int) @@ -233,49 +78,6 @@ end end end -@propagate_inbounds function Base.getindex(ind::BandedMatrixIndex, i::Int) - @boundscheck 1 <= i <= ind.count || throw(BoundsError(ind, i)) - _i = i - p = 1 - while _i - ind.bandsizes[p] > 0 - _i -= ind.bandsizes[p] - p += 1 - end - bandind = ind.bandinds[p] - startfromone = !xor(ind.isrow, (bandind > 0)) - if startfromone - return _i - else - return _i + abs(bandind) - end -end - -@propagate_inbounds function Base.getindex(ind::BlockBandedMatrixIndex, i::Int) - @boundscheck 1 <= i <= ind.count || throw(BoundsError(ind, i)) - p = 1 - while i - ind.refinds[p] >= 0 - p += 1 - end - p -= 1 - _i = i - ind.refinds[p] - if ind.isrow - return ind.refcoords[p] + _i - else - return ind.refcoords[p] - end -end - -@propagate_inbounds function Base.getindex(ind::BandedBlockBandedMatrixIndex, i::Int) - @boundscheck 1 <= i <= ind.count || throw(BoundsError(ind, i)) - p = 1 - while i - ind.refinds[p] >= 0 - p += 1 - end - p -= 1 - _i = i - ind.refinds[p] + 1 - ind.reflocalinds[p][_i] + ind.refcoords[p] - 1 -end - @inline function Base.getindex(x::StrideIndex{N}, i::AbstractCartesianIndex) where {N} return _strides2int(offsets(x), strides(x), Tuple(i)) + static(1) end @@ -288,3 +90,4 @@ end end return Expr(:block, Expr(:meta, :inline), out) end + diff --git a/src/axes.jl b/src/axes.jl index a3c923684..174294e37 100644 --- a/src/axes.jl +++ b/src/axes.jl @@ -11,7 +11,7 @@ axes_types(x, dim) = axes_types(typeof(x), dim) if D > ndims(T) return SOneTo{1} else - return _get_tuple(axes_types(T), dim) + return field_type(axes_types(T), dim) end end @inline function axes_types(::Type{T}, dim::Int) where {T} @@ -39,10 +39,10 @@ function axes_types(::Type{T}) where {T<:MatAdjTrans} Tuple{axes_types(parent_type(T), static(2)),axes_types(parent_type(T), static(1))} end function axes_types(::Type{T}) where {T<:PermutedDimsArray} - eachop_tuple(_get_tuple, to_parent_dims(T), axes_types(parent_type(T))) + eachop_tuple(field_type, to_parent_dims(T), axes_types(parent_type(T))) end function axes_types(::Type{T}) where {T<:AbstractRange} - if known_length(T) === nothing + if known_length(T) === missing return Tuple{OneTo{Int}} else return Tuple{SOneTo{known_length(T)}} @@ -50,7 +50,7 @@ function axes_types(::Type{T}) where {T<:AbstractRange} end axes_types(::Type{T}) where {T<:ReshapedArray} = NTuple{ndims(T),OneTo{Int}} function _sub_axis_type(::Type{I}, dim::StaticInt{D}) where {I<:Tuple,D} - axes_types(_get_tuple(I, dim), static(1)) + axes_types(field_type(I, dim), static(1)) end @inline function axes_types(::Type{T}) where {N,P,I,T<:SubArray{<:Any,N,P,I}} return eachop_tuple(_sub_axis_type, to_parent_dims(T), I) @@ -63,7 +63,7 @@ end function _non_reshaped_axis_type(::Type{A}, d::StaticInt{D}) where {A,D} paxis = axes_types(parent_type(A), d) if D === 1 - if known_length(paxis) === nothing + if known_length(paxis) === missing return paxis else return SOneTo{div(known_length(paxis) * sizeof(eltype(parent_type(A))), sizeof(eltype(A)))} @@ -134,7 +134,7 @@ if isdefined(Base, :ReshapedReinterpretArray) return merge_tuple_type(Tuple{SOneTo{div(sizeof(S), sizeof(T))}}, axes_types(parent_type(A))) elseif sizeof(S) < sizeof(T) P = parent_type(A) - return eachop_tuple(_get_tuple, tail(nstatic(Val(ndims(P)))), axes_types(P)) + return eachop_tuple(field_type, tail(nstatic(Val(ndims(P)))), axes_types(P)) else return axes_types(parent_type(A)) end @@ -192,7 +192,7 @@ end # For now we just make sure the linear elements are accurate. parent_type(::Type{LazyAxis{:,P}}) where {P<:Array} = OneTo{Int} @inline function parent_type(::Type{LazyAxis{:,P}}) where {P} - if known_length(P) === nothing + if known_length(P) === missing return OptionallyStaticUnitRange{StaticInt{1},Int} else return SOneTo{known_length(P)} @@ -209,14 +209,14 @@ known_first(::Type{LazyAxis{N,P}}) where {N,P} = known_offsets(P, static(N)) known_first(::Type{LazyAxis{:,P}}) where {P} = 1 Base.firstindex(x::LazyAxis) = first(x) @inline function Base.first(x::LazyAxis{N})::Int where {N} - if known_first(x) === nothing + if known_first(x) === missing return Int(offsets(parent(x), static(N))) else return Int(known_first(x)) end end @inline function Base.first(x::LazyAxis{:})::Int - if known_first(x) === nothing + if known_first(x) === missing return first(parent(x)) else return known_first(x) @@ -226,20 +226,20 @@ known_last(::Type{LazyAxis{N,P}}) where {N,P} = known_last(axes_types(P, static( known_last(::Type{LazyAxis{:,P}}) where {P} = known_length(P) Base.lastindex(x::LazyAxis) = last(x) Base.last(x::LazyAxis) = _last(known_last(x), x) -_last(::Nothing, x) = last(parent(x)) +_last(::Missing, x) = last(parent(x)) _last(N::Int, x) = N known_length(::Type{LazyAxis{N,P}}) where {N,P} = known_size(P, static(N)) known_length(::Type{LazyAxis{:,P}}) where {P} = known_length(P) @inline function Base.length(x::LazyAxis{N})::Int where {N} - if known_length(x) === nothing + if known_length(x) === missing return size(getfield(x, :parent), static(N)) else return known_length(x) end end @inline function Base.length(x::LazyAxis{:})::Int - if known_length(x) === nothing + if known_length(x) === missing return length(parent(x)) else return known_length(x) @@ -255,7 +255,7 @@ Base.axes1(x::Slice{<:LazyAxis}) = indices(parent(x.indices)) Base.to_shape(x::LazyAxis) = length(x) @inline function Base.checkindex(::Type{Bool}, x::LazyAxis, i::Integer) - if known_first(x) === nothing || known_last(x) === nothing + if known_first(x) === missing || known_last(x) === missing return checkindex(Bool, parent(x), i) else # everything is static so we don't have to retrieve the axis return (!(known_first(x) > i) || !(known_last(x) < i)) diff --git a/src/dimensions.jl b/src/dimensions.jl index 42218ad94..73b65f580 100644 --- a/src/dimensions.jl +++ b/src/dimensions.jl @@ -207,7 +207,7 @@ An error is thrown if any keywords are used which do not occur in `nda`'s names. 1. parse into static dimnension names and key words. 2. find each dimnames in key words -3. if nothing is found use Colon() +3. if missing is found use Colon() 4. if (ndims - ncolon) === nkwargs then all were found, else error =# order_named_inds(x::Tuple, ::NamedTuple{(),Tuple{}}) = () @@ -241,6 +241,6 @@ function _order_named_inds_check(inds::Tuple{Vararg{Any,N}}, nkwargs::Int) where if (N - ncolon(inds, 0)) !== nkwargs error("Not all keywords matched dimension names.") end - return nothing + return missing end diff --git a/src/indexing.jl b/src/indexing.jl index 3e29b2c98..21d0646f9 100644 --- a/src/indexing.jl +++ b/src/indexing.jl @@ -8,12 +8,12 @@ end """ is_splat_index(::Type{T}) -> StaticBool - + Returns `static(true)` if `T` is a type that splats across multiple dimensions. """ is_splat_index(@nospecialize(x)) = is_splat_index(typeof(x)) is_splat_index(::Type{T}) where {T} = static(false) -_is_splat(::Type{I}, i::StaticInt) where {I} = is_splat_index(_get_tuple(I, i)) +_is_splat(::Type{I}, i::StaticInt) where {I} = is_splat_index(field_type(I, i)) """ ndims_index(::Type{I}) -> StaticInt @@ -29,7 +29,7 @@ ndims_index(::Type{<:AbstractCartesianIndex{N}}) where {N} = static(N) ndims_index(::Type{<:AbstractArray{T}}) where {T} = ndims_index(T) ndims_index(::Type{<:AbstractArray{Bool,N}}) where {N} = static(N) ndims_index(::Type{<:LogicalIndex{<:Any,<:AbstractArray{Bool,N}}}) where {N} = static(N) -_ndims_index(::Type{I}, i::StaticInt) where {I} = ndims_index(_get_tuple(I, i)) +_ndims_index(::Type{I}, i::StaticInt) where {I} = ndims_index(field_type(I, i)) """ to_indices(A, I::Tuple) -> Tuple @@ -277,7 +277,7 @@ previously executed `to_index(old_axis, arg) -> index`. `to_axis` assumes that """ @inline function to_axis(axis, inds) if !can_change_size(axis) && - (known_length(inds) !== nothing && known_length(axis) === known_length(inds)) + (known_length(inds) !== missing && known_length(axis) === known_length(inds)) return axis else return to_axis(IndexStyle(axis), axis, inds) @@ -368,7 +368,7 @@ Returns a collection of `A` given `inds`. `inds` is assumed to have been bounds- function unsafe_get_collection(A, inds) axs = to_axes(A, inds) dest = similar(A, axs) - if map(Base.unsafe_length, axes(dest)) == map(Base.unsafe_length, axs) + if map(length, axes(dest)) == map(length, axs) Base._unsafe_getindex!(dest, A, inds...) else Base.throw_checksize_error(dest, axs) diff --git a/src/ranges.jl b/src/ranges.jl index 94735fd9a..534439498 100644 --- a/src/ranges.jl +++ b/src/ranges.jl @@ -1,16 +1,16 @@ _cartesian_index(i::Tuple{Vararg{Int}}) = CartesianIndex(i) -_cartesian_index(::Any) = nothing +_cartesian_index(::Any) = missing """ - known_first(::Type{T}) -> Union{Int,Nothing} + known_first(::Type{T}) -> Union{Int,Missing} If `first` of an instance of type `T` is known at compile time, return it. -Otherwise, return `nothing`. +Otherwise, return `missing`. ```julia julia> ArrayInterface.known_first(typeof(1:4)) -nothing +missing julia> ArrayInterface.known_first(typeof(Base.OneTo(4))) 1 @@ -19,7 +19,7 @@ julia> ArrayInterface.known_first(typeof(Base.OneTo(4))) known_first(x) = known_first(typeof(x)) function known_first(::Type{T}) where {T} if parent_type(T) <: T - return nothing + return missing else return known_first(parent_type(T)) end @@ -30,14 +30,14 @@ function known_first(::Type{T}) where {N,R,T<:CartesianIndices{N,R}} end """ - known_last(::Type{T}) -> Union{Int,Nothing} + known_last(::Type{T}) -> Union{Int,Missing} If `last` of an instance of type `T` is known at compile time, return it. -Otherwise, return `nothing`. +Otherwise, return `missing`. ```julia julia> ArrayInterface.known_last(typeof(1:4)) -nothing +missing julia> ArrayInterface.known_first(typeof(static(1):static(4))) 4 @@ -47,7 +47,7 @@ julia> ArrayInterface.known_first(typeof(static(1):static(4))) known_last(x) = known_last(typeof(x)) function known_last(::Type{T}) where {T} if parent_type(T) <: T - return nothing + return missing else return known_last(parent_type(T)) end @@ -57,14 +57,14 @@ function known_last(::Type{T}) where {N,R,T<:CartesianIndices{N,R}} end """ - known_step(::Type{T}) -> Union{Int,Nothing} + known_step(::Type{T}) -> Union{Int,Missing} If `step` of an instance of type `T` is known at compile time, return it. -Otherwise, return `nothing`. +Otherwise, return `missing`. ```julia julia> ArrayInterface.known_step(typeof(1:2:8)) -nothing +missing julia> ArrayInterface.known_step(typeof(1:4)) 1 @@ -74,7 +74,7 @@ julia> ArrayInterface.known_step(typeof(1:4)) known_step(x) = known_step(typeof(x)) function known_step(::Type{T}) where {T} if parent_type(T) <: T - return nothing + return missing else return known_step(parent_type(T)) end @@ -215,21 +215,21 @@ known_last(::Type{<:OptionallyStaticUnitRange{<:Any,StaticInt{L}}}) where {L} = known_last(::Type{<:OptionallyStaticStepRange{<:Any,<:Any,StaticInt{L}}}) where {L} = L::Int @inline function Base.first(r::OptionallyStaticRange)::Int - if known_first(r) === nothing + if known_first(r) === missing return getfield(r, :start) else return known_first(r) end end function Base.step(r::OptionallyStaticStepRange)::Int - if known_step(r) === nothing + if known_step(r) === missing return getfield(r, :step) else return known_step(r) end end @inline function Base.last(r::OptionallyStaticRange)::Int - if known_last(r) === nothing + if known_last(r) === missing return getfield(r, :stop) else return known_last(r) @@ -343,7 +343,7 @@ Base.length(r::OptionallyStaticUnitRange) = _range_length(static_first(r), stati return _range_length(static_first(r), static_step(r), static_last(r)) end end -_range_length(start, stop) = nothing +_range_length(start, stop) = missing function _range_length(start::CanonicalInt, stop::CanonicalInt) if start > stop return 0 @@ -363,7 +363,7 @@ _range_length(start::CanonicalInt, ::One, stop::CanonicalInt) = _range_length(st return Base.checked_add(Int(div(Base.checked_sub(start, stop), -step)), 1) end end -_range_length(start, step, stop) = nothing +_range_length(start, step, stop) = missing Base.AbstractUnitRange{Int}(r::OptionallyStaticUnitRange) = r function Base.AbstractUnitRange{T}(r::OptionallyStaticUnitRange) where {T} @@ -376,13 +376,13 @@ end Base.eachindex(r::OptionallyStaticRange) = One():static_length(r) @inline function Base.iterate(r::OptionallyStaticRange) - isempty(r) && return nothing + isempty(r) && return missing fi = Int(first(r)); fi, fi end function Base.iterate(::SUnitRange{F,L}) where {F,L} if L::Int < F::Int - return nothing + return missing else return (F::Int, F::Int) end @@ -392,7 +392,7 @@ function Base.iterate(::SOneTo{n}, s::Int) where {n} s2 = s + 1 return (s2, s2) else - return nothing + return missing end end @@ -432,137 +432,6 @@ end end end -""" - reduce_tup(f::F, inds::Tuple{Vararg{Any,N}}) where {F,N} - -An optimized `reduce` for tuples. `Base.reduce`'s `afoldl` will often not inline. -Additionally, `reduce_tup` attempts to order the reduction in an optimal manner. - -```julia -julia> using StaticArrays, ArrayInterface, BenchmarkTools - -julia> rsum(v::SVector) = ArrayInterface.reduce_tup(+, v.data) -rsum (generic function with 2 methods) - -julia> for n ∈ 2:16 - @show n - v = @SVector rand(n) - s1 = @btime sum(\$(Ref(v))[]) - s2 = @btime rsum(\$(Ref(v))[]) - end -n = 2 - 0.863 ns (0 allocations: 0 bytes) - 0.863 ns (0 allocations: 0 bytes) -n = 3 - 0.862 ns (0 allocations: 0 bytes) - 0.863 ns (0 allocations: 0 bytes) -n = 4 - 0.862 ns (0 allocations: 0 bytes) - 0.862 ns (0 allocations: 0 bytes) -n = 5 - 1.074 ns (0 allocations: 0 bytes) - 0.864 ns (0 allocations: 0 bytes) -n = 6 - 0.864 ns (0 allocations: 0 bytes) - 0.862 ns (0 allocations: 0 bytes) -n = 7 - 1.075 ns (0 allocations: 0 bytes) - 0.864 ns (0 allocations: 0 bytes) -n = 8 - 1.077 ns (0 allocations: 0 bytes) - 0.865 ns (0 allocations: 0 bytes) -n = 9 - 1.081 ns (0 allocations: 0 bytes) - 0.865 ns (0 allocations: 0 bytes) -n = 10 - 1.195 ns (0 allocations: 0 bytes) - 0.867 ns (0 allocations: 0 bytes) -n = 11 - 1.357 ns (0 allocations: 0 bytes) - 1.400 ns (0 allocations: 0 bytes) -n = 12 - 1.543 ns (0 allocations: 0 bytes) - 1.074 ns (0 allocations: 0 bytes) -n = 13 - 1.702 ns (0 allocations: 0 bytes) - 1.077 ns (0 allocations: 0 bytes) -n = 14 - 1.913 ns (0 allocations: 0 bytes) - 0.867 ns (0 allocations: 0 bytes) -n = 15 - 2.076 ns (0 allocations: 0 bytes) - 1.077 ns (0 allocations: 0 bytes) -n = 16 - 2.273 ns (0 allocations: 0 bytes) - 1.078 ns (0 allocations: 0 bytes) -``` - -More importantly, `reduce_tup(_pick_range, inds)` often performs better than `reduce(_pick_range, inds)`. -```julia -julia> using ArrayInterface, BenchmarkTools, Static - -julia> inds = (Base.OneTo(100), 1:100, 1:static(100)) -(Base.OneTo(100), 1:100, 1:static(100)) - -julia> @btime reduce(ArrayInterface._pick_range, \$(Ref(inds))[]) - 6.405 ns (0 allocations: 0 bytes) -Base.Slice(static(1):static(100)) - -julia> @btime ArrayInterface.reduce_tup(ArrayInterface._pick_range, \$(Ref(inds))[]) - 2.570 ns (0 allocations: 0 bytes) -Base.Slice(static(1):static(100)) - -julia> inds = (Base.OneTo(100), 1:100, 1:UInt(100)) -(Base.OneTo(100), 1:100, 0x0000000000000001:0x0000000000000064) - -julia> @btime reduce(ArrayInterface._pick_range, \$(Ref(inds))[]) - 6.411 ns (0 allocations: 0 bytes) -Base.Slice(static(1):100) - -julia> @btime ArrayInterface.reduce_tup(ArrayInterface._pick_range, \$(Ref(inds))[]) - 2.592 ns (0 allocations: 0 bytes) -Base.Slice(static(1):100) - -julia> inds = (Base.OneTo(100), 1:100, 1:UInt(100), Int32(1):Int32(100)) -(Base.OneTo(100), 1:100, 0x0000000000000001:0x0000000000000064, 1:100) - -julia> @btime reduce(ArrayInterface._pick_range, \$(Ref(inds))[]) - 9.048 ns (0 allocations: 0 bytes) -Base.Slice(static(1):100) - -julia> @btime ArrayInterface.reduce_tup(ArrayInterface._pick_range, \$(Ref(inds))[]) - 2.569 ns (0 allocations: 0 bytes) -Base.Slice(static(1):100) -``` -""" -@generated function reduce_tup(f::F, inds::Tuple{Vararg{Any,N}}) where {F,N} - q = Expr(:block, Expr(:meta, :inline, :propagate_inbounds)) - if N == 1 - push!(q.args, :(inds[1])) - return q - end - syms = Vector{Symbol}(undef, N) - i = 0 - for n ∈ 1:N - syms[n] = iₙ = Symbol(:i_, (i += 1)) - push!(q.args, Expr(:(=), iₙ, Expr(:ref, :inds, n))) - end - W = 1 << (8sizeof(N) - 2 - leading_zeros(N)) - while W > 0 - _N = length(syms) - for _ ∈ 2W:W:_N - for w ∈ 1:W - new_sym = Symbol(:i_, (i += 1)) - push!(q.args, Expr(:(=), new_sym, Expr(:call, :f, syms[w], syms[w+W]))) - syms[w] = new_sym - end - deleteat!(syms, 1+W:2W) - end - W >>>= 1 - end - q -end - @propagate_inbounds function _pick_range(x, y) fst = _try_static(static_first(x), static_first(y)) lst = _try_static(static_last(x), static_last(y)) diff --git a/src/size.jl b/src/size.jl index 6d9326361..22619ce58 100644 --- a/src/size.jl +++ b/src/size.jl @@ -46,7 +46,7 @@ size(a::Array, dim::Integer) = Base.arraysize(a, convert(Int, dim)) function size(a::A, dim::Integer) where {A} if parent_type(A) <: A len = known_size(A, dim) - if len === nothing + if len === missing return Int(length(axes(a, dim))) else return StaticInt(len) @@ -66,15 +66,15 @@ end """ known_size(::Type{T}) -> Tuple - known_size(::Type{T}, dim) -> Union{Int,Nothing} + known_size(::Type{T}, dim) -> Union{Int,Missing} Returns the size of each dimension of `A` or along dimension `dim` of `A` that is known at -compile time. If a dimension does not have a known size along a dimension then `nothing` is +compile time. If a dimension does not have a known size along a dimension then `missing` is returned in its position. """ known_size(x) = known_size(typeof(x)) known_size(::Type{T}) where {T} = eachop(_known_size, nstatic(Val(ndims(T))), axes_types(T)) -_known_size(::Type{T}, dim::StaticInt) where {T} = known_length(_get_tuple(T, dim)) +_known_size(::Type{T}, dim::StaticInt) where {T} = known_length(field_type(T, dim)) @inline known_size(x, dim) = known_size(typeof(x), dim) @inline known_size(::Type{T}, dim) where {T} = known_size(T, to_dims(T, dim)) @inline function known_size(::Type{T}, dim::CanonicalInt) where {T} diff --git a/src/stridelayout.jl b/src/stridelayout.jl index 8343ab1cd..c54cd027b 100644 --- a/src/stridelayout.jl +++ b/src/stridelayout.jl @@ -16,15 +16,15 @@ function stride_preserving_index(::Type{T}) where {N,T<:Tuple{Vararg{Any,N}}} end end function _stride_preserving_index(::Type{T}, i::StaticInt) where {T} - return stride_preserving_index(_get_tuple(T, i)) + return stride_preserving_index(field_type(T, i)) end """ known_offsets(::Type{T}) -> Tuple - known_offsets(::Type{T}, dim) -> Union{Int,Nothing} + known_offsets(::Type{T}, dim) -> Union{Int,Missing} Returns a tuple of offset values known at compile time. If the offset of a given axis is -not known at compile time `nothing` is returned its position. +not known at compile time `missing` is returned its position. """ known_offsets(x, dim) = known_offsets(typeof(x), dim) known_offsets(::Type{T}, dim) where {T} = known_offsets(T, to_dims(T, dim)) @@ -40,7 +40,7 @@ known_offsets(x) = known_offsets(typeof(x)) function known_offsets(::Type{T}) where {T} return eachop(_known_offsets, nstatic(Val(ndims(T))), axes_types(T)) end -_known_offsets(::Type{T}, dim::StaticInt) where {T} = known_first(_get_tuple(T, dim)) +_known_offsets(::Type{T}, dim::StaticInt) where {T} = known_first(field_type(T, dim)) known_offsets(::Type{<:StrideIndex{N,R,C,S,O}}) where {N,R,C,S,O} = known(O) @@ -58,7 +58,7 @@ offsets(x::StrideIndex) = getfield(x, :offsets) offsets(x) = eachop(_offsets, nstatic(Val(ndims(x))), x) function _offsets(x::X, dim::StaticInt{D}) where {X,D} start = known_first(axes_types(X, dim)) - if start === nothing + if start === missing return first(axes(x, dim)) else return static(start) @@ -69,7 +69,7 @@ end @inline offsets(x::StrideIndex, ::StaticInt{dim}) where {dim} = getfield(offsets(x), dim) """ - known_offset1(::Type{T}) -> Union{Int,Nothing} + known_offset1(::Type{T}) -> Union{Int,Missing} Returns the linear offset of array `x` if known at compile time. """ @@ -89,7 +89,7 @@ Returns the offset of the linear indices for `x`. """ @inline function offset1(x::X) where {X} o1 = known_offset1(X) - if o1 === nothing + if o1 === missing if ndims(X) === 0 return 1 else @@ -105,14 +105,14 @@ end Returns the axis of an array of type `T` containing contiguous data. If no axis is contiguous, it returns a `StaticInt{-1}`. -If unknown, it returns `nothing`. +If unknown, it returns `missing`. """ contiguous_axis(x) = contiguous_axis(typeof(x)) contiguous_axis(::Type{<:StrideIndex{N,R,C}}) where {N,R,C} = static(C) -contiguous_axis(::Type{<:StrideIndex{N,R,nothing}}) where {N,R} = nothing +contiguous_axis(::Type{<:StrideIndex{N,R,missing}}) where {N,R} = missing function contiguous_axis(::Type{T}) where {T} if parent_type(T) <: T - return nothing + return missing else return contiguous_axis(parent_type(T)) end @@ -123,8 +123,8 @@ contiguous_axis(::Type{<:AbstractRange}) = One() contiguous_axis(::Type{<:Tuple}) = One() function contiguous_axis(::Type{T}) where {T<:VecAdjTrans} c = contiguous_axis(parent_type(T)) - if c === nothing - return nothing + if c === missing + return missing elseif c === One() return StaticInt{2}() else @@ -133,8 +133,8 @@ function contiguous_axis(::Type{T}) where {T<:VecAdjTrans} end function contiguous_axis(::Type{T}) where {T<:MatAdjTrans} c = contiguous_axis(parent_type(T)) - if c === nothing - return nothing + if c === missing + return missing elseif isone(-c) return c else @@ -143,8 +143,8 @@ function contiguous_axis(::Type{T}) where {T<:MatAdjTrans} end function contiguous_axis(::Type{T}) where {T<:PermutedDimsArray} c = contiguous_axis(parent_type(T)) - if c === nothing - return nothing + if c === missing + return missing elseif isone(-c) return c else @@ -152,29 +152,29 @@ function contiguous_axis(::Type{T}) where {T<:PermutedDimsArray} end end function contiguous_axis(::Type{Base.ReshapedArray{T, 1, A, Tuple{}}}) where {T, A} - IfElse.ifelse(is_column_major(A) & is_dense(A), static(1), nothing) + IfElse.ifelse(is_column_major(A) & is_dense(A), static(1), missing) end function contiguous_axis(::Type{Base.ReshapedArray{T, 1, LinearAlgebra.Adjoint{T, A}, Tuple{}}}) where {T, A <: AbstractVector{T}} - IfElse.ifelse(is_column_major(A) & is_dense(A), static(1), nothing) + IfElse.ifelse(is_column_major(A) & is_dense(A), static(1), missing) end function contiguous_axis(::Type{Base.ReshapedArray{T, 1, LinearAlgebra.Transpose{T, A}, Tuple{}}}) where {T, A <: AbstractVector{T}} - IfElse.ifelse(is_column_major(A) & is_dense(A), static(1), nothing) + IfElse.ifelse(is_column_major(A) & is_dense(A), static(1), missing) end function contiguous_axis(::Type{T}) where {T<:SubArray} return _contiguous_axis(T, contiguous_axis(parent_type(T))) end -_contiguous_axis(::Type{A}, ::Nothing) where {T,N,P,I,A<:SubArray{T,N,P,I}} = nothing +_contiguous_axis(::Type{A}, ::Missing) where {T,N,P,I,A<:SubArray{T,N,P,I}} = missing _contiguous_axis(::Type{A}, c::StaticInt{-1}) where {T,N,P,I,A<:SubArray{T,N,P,I}} = c function _contiguous_axis(::Type{A}, c::StaticInt{C}) where {T,N,P,I,A<:SubArray{T,N,P,I},C} - if _get_tuple(I, c) <: AbstractUnitRange + if field_type(I, c) <: AbstractUnitRange return from_parent_dims(A)[C] - elseif _get_tuple(I, c) <: AbstractArray + elseif field_type(I, c) <: AbstractArray return -One() - elseif _get_tuple(I, c) <: Integer + elseif field_type(I, c) <: Integer return -One() else - return nothing + return missing end end @@ -184,7 +184,7 @@ function contiguous_axis(::Type{R}) where {T,N,S,A<:Array{S},R<:ReinterpretArray if isbitstype(S) return One() else - return nothing + return missing end end @@ -197,7 +197,7 @@ function contiguous_axis_indicator(::Type{A}) where {D,A<:AbstractArray{<:Any,D} return contiguous_axis_indicator(contiguous_axis(A), Val(D)) end contiguous_axis_indicator(::A) where {A<:AbstractArray} = contiguous_axis_indicator(A) -contiguous_axis_indicator(::Nothing, ::Val) = nothing +contiguous_axis_indicator(::Missing, ::Val) = missing function contiguous_axis_indicator(c::StaticInt{N}, dim::Val{D}) where {N,D} return map(i -> eq(c, i), nstatic(dim)) end @@ -215,7 +215,7 @@ stride_rank(::Type{<:StrideIndex{N,R}}) where {N,R} = static(R) stride_rank(x) = stride_rank(typeof(x)) function stride_rank(::Type{T}) where {T} if parent_type(T) <: T - return nothing + return missing else return stride_rank(parent_type(T)) end @@ -227,7 +227,7 @@ stride_rank(::Type{<:Tuple}) = (One(),) stride_rank(::Type{T}) where {T<:VecAdjTrans} = (StaticInt(2), StaticInt(1)) stride_rank(::Type{T}) where {T<:MatAdjTrans} = _stride_rank(T, stride_rank(parent_type(T))) -_stride_rank(::Type{T}, ::Nothing) where {T<:MatAdjTrans} = nothing +_stride_rank(::Type{T}, ::Missing) where {T<:MatAdjTrans} = missing function _stride_rank(::Type{T}, rank) where {T<:MatAdjTrans} return (getfield(rank, 2), getfield(rank, 1)) end @@ -235,11 +235,11 @@ end function stride_rank(::Type{T},) where {T<:PermutedDimsArray} return _stride_rank(T, stride_rank(parent_type(T))) end -_stride_rank(::Type{T}, ::Nothing) where {T<:PermutedDimsArray} = nothing +_stride_rank(::Type{T}, ::Missing) where {T<:PermutedDimsArray} = missing _stride_rank(::Type{T}, r) where {T<:PermutedDimsArray} = permute(r, to_parent_dims(T)) stride_rank(::Type{T}) where {T<:SubArray} = _stride_rank(T, stride_rank(parent_type(T))) -_stride_rank(::Any, ::Any) = nothing +_stride_rank(::Any, ::Any) = missing _stride_rank(::Type{T}, r::Tuple) where {T<:SubArray} = permute(r, to_parent_dims(T)) stride_rank(x, i) = stride_rank(x)[i] @@ -277,17 +277,17 @@ function stride_rank(::Type{Base.ReshapedArray{T, N, P, Tuple{Vararg{Base.Signed _reshaped_striderank(is_column_major(P), Val{N}(), Val{M}()) end function stride_rank(::Type{Base.ReshapedArray{T, 1, A, Tuple{}}}) where {T, A} - IfElse.ifelse(is_column_major(A) & is_dense(A), (static(1),), nothing) + IfElse.ifelse(is_column_major(A) & is_dense(A), (static(1),), missing) end function stride_rank(::Type{Base.ReshapedArray{T, 1, LinearAlgebra.Adjoint{T, A}, Tuple{}}}) where {T, A <: AbstractVector{T}} - IfElse.ifelse(is_dense(A), (static(1),), nothing) + IfElse.ifelse(is_dense(A), (static(1),), missing) end function stride_rank(::Type{Base.ReshapedArray{T, 1, LinearAlgebra.Transpose{T, A}, Tuple{}}}) where {T, A <: AbstractVector{T}} - IfElse.ifelse(is_dense(A), (static(1),), nothing) + IfElse.ifelse(is_dense(A), (static(1),), missing) end _reshaped_striderank(::True, ::Val{N}, ::Val{0}) where {N} = nstatic(Val(N)) -_reshaped_striderank(_, __, ___) = nothing +_reshaped_striderank(_, __, ___) = missing """ contiguous_batch_size(::Type{T}) -> StaticInt{N} @@ -295,16 +295,16 @@ _reshaped_striderank(_, __, ___) = nothing Returns the Base.size of contiguous batches if `!isone(stride_rank(T, contiguous_axis(T)))`. If `isone(stride_rank(T, contiguous_axis(T)))`, then it will return `StaticInt{0}()`. If `contiguous_axis(T) == -1`, it will return `StaticInt{-1}()`. -If unknown, it will return `nothing`. +If unknown, it will return `missing`. """ contiguous_batch_size(x) = contiguous_batch_size(typeof(x)) contiguous_batch_size(::Type{T}) where {T} = _contiguous_batch_size(contiguous_axis(T), stride_rank(T)) -_contiguous_batch_size(_, __) = nothing +_contiguous_batch_size(_, __) = missing function _contiguous_batch_size(::StaticInt{D}, ::R) where {D,R<:Tuple} if R.parameters[D].parameters[1] === 1 return Zero() else - return nothing + return missing end end _contiguous_batch_size(::StaticInt{-1}, ::R) where {R<:Tuple} = -One() @@ -322,7 +322,7 @@ end function contiguous_batch_size(::Type{S}) where {N,NP,T,A<:AbstractArray{T,NP},I,S<:SubArray{T,N,A,I}} return _contiguous_batch_size(S, contiguous_batch_size(A), contiguous_axis(A)) end -_contiguous_batch_size(::Any, ::Any, ::Any) = nothing +_contiguous_batch_size(::Any, ::Any, ::Any) = missing function _contiguous_batch_size(::Type{<:SubArray{T,N,A,I}}, b::StaticInt{B}, c::StaticInt{C}) where {T,N,A,I,B,C} if I.parameters[C] <: AbstractUnitRange return b @@ -338,7 +338,7 @@ contiguous_batch_size(::Type{<:Base.ReinterpretArray{T,N,S,A}}) where {T,N,S,A} Returns `True()` if elements of `A` are stored in column major order. Otherwise returns `False()`. """ is_column_major(A) = is_column_major(stride_rank(A), contiguous_batch_size(A)) -is_column_major(sr::Nothing, cbs) = False() +is_column_major(sr::Missing, cbs) = False() is_column_major(sr::R, cbs) where {R} = _is_column_major(sr, cbs) is_column_major(::AbstractRange) = False() @@ -357,7 +357,7 @@ where `stride_rank(A)[i] + 1 == stride_rank(A)[j]`. dense_dims(x) = dense_dims(typeof(x)) function dense_dims(::Type{T}) where {T} if parent_type(T) <: T - return nothing + return missing else return dense_dims(parent_type(T)) end @@ -370,24 +370,24 @@ dense_dims(::Type{<:AbstractRange}) = (True(),) dense_dims(::Type{<:Tuple}) = (True(),) function dense_dims(::Type{T}) where {T<:VecAdjTrans} dense = dense_dims(parent_type(T)) - if dense === nothing - return nothing + if dense === missing + return missing else return (True(), first(dense)) end end function dense_dims(::Type{T}) where {T<:MatAdjTrans} dense = dense_dims(parent_type(T)) - if dense === nothing - return nothing + if dense === missing + return missing else return (last(dense), first(dense)) end end function dense_dims(::Type{T}) where {T<:PermutedDimsArray} dense = dense_dims(parent_type(T)) - if dense === nothing - return nothing + if dense === missing + return missing else return permute(dense, to_parent_dims(T)) end @@ -402,7 +402,7 @@ if VERSION ≥ v"1.6.0-DEV.1581" end end -_dense_dims(::Type{S}, ::Nothing, ::Val{R}) where {R,N,NP,T,A<:AbstractArray{T,NP},I,S<:SubArray{T,N,A,I}} = nothing +_dense_dims(::Type{S}, ::Missing, ::Val{R}) where {R,N,NP,T,A<:AbstractArray{T,NP},I,S<:SubArray{T,N,A,I}} = missing @generated function _dense_dims( ::Type{S}, ::D, @@ -433,11 +433,11 @@ _dense_dims(::Type{S}, ::Nothing, ::Val{R}) where {R,N,NP,T,A<:AbstractArray{T,N push!(dense_tup.args, :(False())) end end - # If n != N, then an axis was indexed by something other than an integer or `AbstractUnitRange`, so we return `nothing`. + # If n != N, then an axis was indexed by something other than an integer or `AbstractUnitRange`, so we return `missing`. if length(dense_tup.args) === N return dense_tup else - return nothing + return missing end end @@ -452,12 +452,12 @@ _is_dense(t::Tuple{True}) = True() _is_dense(t::Tuple{}) = True() -_reshaped_dense_dims(_, __, ___, ____) = nothing +_reshaped_dense_dims(_, __, ___, ____) = missing function _reshaped_dense_dims(dense::D, ::True, ::Val{N}, ::Val{0}) where {D,N} if all(dense) return _all_dense(Val{N}()) else - return nothing + return missing end end function _reshaped_dense_dims(dense::Tuple{Static.False}, ::True, ::Val{N}, ::Val{0}) where {N} @@ -466,10 +466,10 @@ end """ known_strides(::Type{T}) -> Tuple - known_strides(::Type{T}, dim) -> Union{Int,Nothing} + known_strides(::Type{T}, dim) -> Union{Int,Missing} Returns the strides of array `A` known at compile time. Any strides that are not known at -compile time are represented by `nothing`. +compile time are represented by `missing`. """ known_strides(x, dim) = known_strides(typeof(x), dim) known_strides(::Type{T}, dim) where {T} = known_strides(T, to_dims(T, dim)) @@ -624,7 +624,7 @@ function strides(A::SubArray) end maybe_static_step(x::AbstractRange) = static_step(x) -maybe_static_step(_) = nothing +maybe_static_step(_) = missing @generated function size_to_strides(sz::S, init) where {N,S<:Tuple{Vararg{Any,N}}} out = Expr(:block, Expr(:meta, :inline)) @@ -632,8 +632,8 @@ maybe_static_step(_) = nothing prev = :init i = 1 while i <= (N - 1) - if S.parameters[i] <: Nothing || (i > 1 && t.args[i - 1] === :nothing) - push!(t.args, :nothing) + if S.parameters[i] <: Missing || (i > 1 && t.args[i - 1] === :missing) + push!(t.args, :missing) else next = Symbol(:val_, i) push!(out.args, :($next = $prev * getfield(sz, $i))) diff --git a/test/Project.toml b/test/Project.toml new file mode 100644 index 000000000..9a96f6ef9 --- /dev/null +++ b/test/Project.toml @@ -0,0 +1,22 @@ +[deps] +Aqua = "4c88cf16-eb10-579e-8560-4a9242c79595" +BandedMatrices = "aae01518-5342-5314-be14-df237901396f" +BlockBandedMatrices = "ffab5731-97b5-5995-9138-79e8c1846df0" +IfElse = "615f187c-cbe4-4ef1-ba3b-2fcf58d6d173" +LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" +OffsetArrays = "6fe1bfb0-de20-5000-8ca7-80f57d26f881" +Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" +SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf" +Static = "aedffcd0-7271-4cad-89d0-dc628f76c6d3" +StaticArrays = "90137ffa-7385-5640-81b9-e52037218182" +SuiteSparse = "4607b0f0-06f3-5cda-b6b1-a6196a1729e9" +Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" + +[compat] +Aqua = "0.5" +BandedMatrices = "0.16" +BlockBandedMatrices = "0.11" +IfElse = "0.1" +OffsetArrays = "1" +Static = "0.5" +StaticArrays = "1.2.5, 1.3" diff --git a/test/array_index.jl b/test/array_index.jl index f193b2b35..1912016b2 100644 --- a/test/array_index.jl +++ b/test/array_index.jl @@ -15,7 +15,7 @@ end @test @inferred(ArrayInterface.offsets(ap_index, static(1))) === ArrayInterface.offset1(Ap) @test @inferred(ArrayInterface.known_strides(ap_index)) === ArrayInterface.known_strides(Ap) @test @inferred(ArrayInterface.contiguous_axis(ap_index)) == 1 -@test @inferred(ArrayInterface.contiguous_axis(ArrayInterface.StrideIndex{2,(1,2),nothing,NTuple{2,Int},NTuple{2,Int}})) == nothing +@test @inferred(ArrayInterface.contiguous_axis(ArrayInterface.StrideIndex{2,(1,2),missing,NTuple{2,Int},NTuple{2,Int}})) === missing @test @inferred(ArrayInterface.stride_rank(ap_index)) == (1, 3) let v = Float64.(1:10)', v2 = transpose(parent(v)) diff --git a/test/ranges.jl b/test/ranges.jl index baf8d944a..04c9c7f6b 100644 --- a/test/ranges.jl +++ b/test/ranges.jl @@ -51,25 +51,25 @@ @test reverse(static(1):static(2):static(9)) === static(9):static(-2):static(1) end - @test isnothing(@inferred(ArrayInterface.known_first(typeof(1:4)))) + @test ismissing(@inferred(ArrayInterface.known_first(typeof(1:4)))) @test isone(@inferred(ArrayInterface.known_first(Base.OneTo(4)))) @test isone(@inferred(ArrayInterface.known_first(typeof(Base.OneTo(4))))) @test isone(@inferred(ArrayInterface.known_first(typeof(static(1):2:10)))) - @test isnothing(@inferred(ArrayInterface.known_last(1:4))) - @test isnothing(@inferred(ArrayInterface.known_last(typeof(1:4)))) + @test ismissing(@inferred(ArrayInterface.known_last(1:4))) + @test ismissing(@inferred(ArrayInterface.known_last(typeof(1:4)))) @test isone(@inferred(ArrayInterface.known_last(typeof(static(-1):static(2):static(1))))) # CartesianIndices CI = CartesianIndices((2, 2)) @test @inferred(ArrayInterface.known_first(typeof(CI))) == CartesianIndex(1, 1) - @test @inferred(ArrayInterface.known_last(typeof(CI))) == nothing + @test @inferred(ArrayInterface.known_last(typeof(CI))) === missing CI = CartesianIndices((static(1):static(2), static(1):static(2))) @test @inferred(ArrayInterface.known_first(typeof(CI))) == CartesianIndex(1, 1) @test @inferred(ArrayInterface.known_last(typeof(CI))) == CartesianIndex(2, 2) - @test isnothing(@inferred(ArrayInterface.known_step(typeof(1:0.2:4)))) + @test ismissing(@inferred(ArrayInterface.known_step(typeof(1:0.2:4)))) @test isone(@inferred(ArrayInterface.known_step(1:4))) @test isone(@inferred(ArrayInterface.known_step(typeof(1:4)))) @test isone(@inferred(ArrayInterface.known_step(typeof(Base.Slice(1:4))))) @@ -86,7 +86,7 @@ @test @inferred(length(static(1):static(2):static(0))) == 0 @test @inferred(length(static(0):static(-2):static(1))) == 0 - @test @inferred(ArrayInterface.known_length(typeof(ArrayInterface.OptionallyStaticStepRange(static(1), 2, 10)))) === nothing + @test @inferred(ArrayInterface.known_length(typeof(ArrayInterface.OptionallyStaticStepRange(static(1), 2, 10)))) === missing @test @inferred(ArrayInterface.known_length(typeof(ArrayInterface.SOneTo{-10}()))) === 0 @test @inferred(ArrayInterface.known_length(typeof(ArrayInterface.OptionallyStaticStepRange(static(1), static(1), static(10))))) === 10 @test @inferred(ArrayInterface.known_length(typeof(ArrayInterface.OptionallyStaticStepRange(static(2), static(1), static(10))))) === 9 diff --git a/test/runtests.jl b/test/runtests.jl index 97cb5f589..6e37e0355 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -66,7 +66,7 @@ else @test !fast_scalar_indexing(qr(rand(10, 10), Val(true)).Q) end @test !fast_scalar_indexing(lq(rand(10, 10)).Q) -@test fast_scalar_indexing(Nothing) # test default +@test fast_scalar_indexing(Missing) # test default @testset "can_setindex" begin @test !@inferred(ArrayInterface.can_setindex(1:2)) @@ -286,7 +286,7 @@ ArrayInterface.parent_type(::Type{DenseWrapper{T,N,P}}) where {T,N,P} = P @test @inferred(device(OffsetArray(@SArray(zeros(2,2,2)),-123,29,3231))) === ArrayInterface.CPUTuple() @test @inferred(device(OffsetArray(@view(@SArray(zeros(2,2,2))[1,1:2,:]),-3,4))) === ArrayInterface.CPUTuple() @test @inferred(device(OffsetArray(@MArray(zeros(2,2,2)),8,-2,-5))) === ArrayInterface.CPUPointer() - @test isnothing(device("Hello, world!")) + @test ismissing(device("Hello, world!")) @test @inferred(device(DenseWrapper{Int,2,Matrix{Int}})) === ArrayInterface.CPUPointer() #= @btime ArrayInterface.contiguous_axis($(reshape(view(zeros(100), 1:60), (3,4,5)))) @@ -309,10 +309,10 @@ ArrayInterface.parent_type(::Type{DenseWrapper{T,N,P}}) where {T,N,P} = P @test @inferred(contiguous_axis((3,4))) === StaticInt(1) @test @inferred(contiguous_axis(rand(4)')) === StaticInt(2) @test @inferred(contiguous_axis(view(@view(PermutedDimsArray(A,(3,1,2))[2:3,2,:])', :, 1)')) === StaticInt(-1) - @test @inferred(contiguous_axis(DummyZeros(3,4))) === nothing - @test @inferred(contiguous_axis(PermutedDimsArray(DummyZeros(3,4), (2, 1)))) === nothing - @test @inferred(contiguous_axis(view(DummyZeros(3,4), 1, :))) === nothing - @test @inferred(contiguous_axis(view(DummyZeros(3,4), 1, :)')) === nothing + @test @inferred(contiguous_axis(DummyZeros(3,4))) === missing + @test @inferred(contiguous_axis(PermutedDimsArray(DummyZeros(3,4), (2, 1)))) === missing + @test @inferred(contiguous_axis(view(DummyZeros(3,4), 1, :))) === missing + @test @inferred(contiguous_axis(view(DummyZeros(3,4), 1, :)')) === missing @test @inferred(ArrayInterface.contiguous_axis_indicator(@SArray(zeros(2,2,2)))) == (true,false,false) @test @inferred(ArrayInterface.contiguous_axis_indicator(A)) == (true,false,false) @@ -326,7 +326,7 @@ ArrayInterface.parent_type(::Type{DenseWrapper{T,N,P}}) where {T,N,P} = P @test @inferred(ArrayInterface.contiguous_axis_indicator(@view(PermutedDimsArray(A,(3,1,2))[2:3,2,:])')) == (false,false) @test @inferred(ArrayInterface.contiguous_axis_indicator(@view(PermutedDimsArray(A,(3,1,2))[:,1:2,1])')) == (true,false) @test @inferred(ArrayInterface.contiguous_axis_indicator(@view(PermutedDimsArray(A,(3,1,2))[:,1:2,[1,3,4]]))) == (false,true,false) - @test @inferred(ArrayInterface.contiguous_axis_indicator(DummyZeros(3,4))) === nothing + @test @inferred(ArrayInterface.contiguous_axis_indicator(DummyZeros(3,4))) === missing @test @inferred(contiguous_batch_size(@SArray(zeros(2,2,2)))) === ArrayInterface.StaticInt(0) @test @inferred(contiguous_batch_size(A)) === ArrayInterface.StaticInt(0) @@ -361,9 +361,9 @@ ArrayInterface.parent_type(::Type{DenseWrapper{T,N,P}}) where {T,N,P} = P @test @inferred(stride_rank(@view(PermutedDimsArray(A,(3,1,2))[:,1:2,1])')) == (1, 3) @test @inferred(stride_rank(@view(PermutedDimsArray(A,(3,1,2))[:,2,1])')) == (2, 1) @test @inferred(stride_rank(@view(PermutedDimsArray(A,(3,1,2))[:,1:2,[1,3,4]]))) == (3, 1, 2) - @test @inferred(stride_rank(DummyZeros(3,4)')) === nothing - @test @inferred(stride_rank(PermutedDimsArray(DummyZeros(3,4), (2, 1)))) === nothing - @test @inferred(stride_rank(view(DummyZeros(3,4), 1, :))) === nothing + @test @inferred(stride_rank(DummyZeros(3,4)')) === missing + @test @inferred(stride_rank(PermutedDimsArray(DummyZeros(3,4), (2, 1)))) === missing + @test @inferred(stride_rank(view(DummyZeros(3,4), 1, :))) === missing uA = reinterpret(reshape, UInt64, A) @test @inferred(stride_rank(uA)) === stride_rank(A) rA = reinterpret(reshape, SVector{3,Float64}, A) @@ -417,11 +417,11 @@ ArrayInterface.parent_type(::Type{DenseWrapper{T,N,P}}) where {T,N,P} = P # first need to develop a standard method for reconstructing arrays @test @inferred(dense_dims(vec(parent(A)))) == (true,) @test @inferred(dense_dims(vec(parent(A))')) == (true,true) - @test @inferred(dense_dims(DummyZeros(3,4))) === nothing - @test @inferred(dense_dims(DummyZeros(3,4)')) === nothing - @test @inferred(dense_dims(PermutedDimsArray(DummyZeros(3,4), (2, 1)))) === nothing - @test @inferred(dense_dims(view(DummyZeros(3,4), :, 1))) === nothing - @test @inferred(dense_dims(view(DummyZeros(3,4), :, 1)')) === nothing + @test @inferred(dense_dims(DummyZeros(3,4))) === missing + @test @inferred(dense_dims(DummyZeros(3,4)')) === missing + @test @inferred(dense_dims(PermutedDimsArray(DummyZeros(3,4), (2, 1)))) === missing + @test @inferred(dense_dims(view(DummyZeros(3,4), :, 1))) === missing + @test @inferred(dense_dims(view(DummyZeros(3,4), :, 1)')) === missing @test @inferred(ArrayInterface.is_dense(A)) === @inferred(ArrayInterface.is_dense(A)) === @inferred(ArrayInterface.is_dense(PermutedDimsArray(A,(3,1,2)))) === @inferred(ArrayInterface.is_dense(Array{Float64,0}(undef))) === True() @test @inferred(ArrayInterface.is_dense(@view(PermutedDimsArray(A,(3,1,2))[2:3,1:2,:]))) === @inferred(ArrayInterface.is_dense(@view(PermutedDimsArray(A,(3,1,2))[2:3,:,[1,2]]))) === @inferred(ArrayInterface.is_dense(@view(PermutedDimsArray(A,(3,1,2))[2:3,[1,2,3],:]))) === False() @@ -523,31 +523,31 @@ end @test @inferred(ArrayInterface.size(Mp2)) == size(Mp2) @test @inferred(ArrayInterface.size(D)) == size(D) - @test @inferred(ArrayInterface.known_size(A)) === (nothing, nothing, nothing) - @test @inferred(ArrayInterface.known_size(Ap)) === (nothing,nothing) - @test @inferred(ArrayInterface.known_size(Wrapper(Ap))) === (nothing,nothing) + @test @inferred(ArrayInterface.known_size(A)) === (missing, missing, missing) + @test @inferred(ArrayInterface.known_size(Ap)) === (missing,missing) + @test @inferred(ArrayInterface.known_size(Wrapper(Ap))) === (missing,missing) @test @inferred(ArrayInterface.known_size(R)) === (2,) @test @inferred(ArrayInterface.known_size(Wrapper(R))) === (2,) @test @inferred(ArrayInterface.known_size(Rnr)) === (4,) @test @inferred(ArrayInterface.known_size(Rnr, static(1))) === 4 - @test @inferred(ArrayInterface.known_size(Ar)) === (nothing,nothing, nothing,) - @test @inferred(ArrayInterface.known_size(Ar, static(1))) === nothing + @test @inferred(ArrayInterface.known_size(Ar)) === (missing,missing, missing,) + @test @inferred(ArrayInterface.known_size(Ar, static(1))) === missing @test @inferred(ArrayInterface.known_size(Ar, static(4))) === 1 - @test @inferred(ArrayInterface.known_size(A2)) === (nothing, nothing, nothing) - @test @inferred(ArrayInterface.known_size(A2r)) === (nothing, nothing, nothing) + @test @inferred(ArrayInterface.known_size(A2)) === (missing, missing, missing) + @test @inferred(ArrayInterface.known_size(A2r)) === (missing, missing, missing) @test @inferred(ArrayInterface.known_size(S)) === (2, 3, 4) @test @inferred(ArrayInterface.known_size(Wrapper(S))) === (2, 3, 4) - @test @inferred(ArrayInterface.known_size(Sp)) === (nothing, nothing, 3) - @test @inferred(ArrayInterface.known_size(Wrapper(Sp))) === (nothing, nothing, 3) - @test @inferred(ArrayInterface.known_size(Sp2)) === (nothing, 3, 2) - @test @inferred(ArrayInterface.known_size(Sp2, StaticInt(1))) === nothing + @test @inferred(ArrayInterface.known_size(Sp)) === (missing, missing, 3) + @test @inferred(ArrayInterface.known_size(Wrapper(Sp))) === (missing, missing, 3) + @test @inferred(ArrayInterface.known_size(Sp2)) === (missing, 3, 2) + @test @inferred(ArrayInterface.known_size(Sp2, StaticInt(1))) === missing @test @inferred(ArrayInterface.known_size(Sp2, StaticInt(2))) === 3 @test @inferred(ArrayInterface.known_size(Sp2, StaticInt(3))) === 2 @test @inferred(ArrayInterface.known_size(M)) === (2, 3, 4) @test @inferred(ArrayInterface.known_size(Mp)) === (3, 4) - @test @inferred(ArrayInterface.known_size(Mp2)) === (2, nothing) + @test @inferred(ArrayInterface.known_size(Mp2)) === (2, missing) @test @inferred(ArrayInterface.strides(A)) === (StaticInt(1), 3, 12) @test @inferred(ArrayInterface.strides(Ap)) === (StaticInt(1), 12) @@ -574,12 +574,12 @@ end @test @inferred(ArrayInterface.strides(Mp2)) == strides(Mp2) @test_throws MethodError ArrayInterface.strides(DummyZeros(3,4)) - @test @inferred(ArrayInterface.known_strides(A)) === (1, nothing, nothing) - @test @inferred(ArrayInterface.known_strides(Ap)) === (1, nothing) - @test @inferred(ArrayInterface.known_strides(Ar)) === (1, nothing, nothing) - @test @inferred(ArrayInterface.known_strides(reshape(view(zeros(100), 1:60), (3,4,5)))) === (1, nothing, nothing) - @test @inferred(ArrayInterface.known_strides(A2)) === (1, nothing, nothing) - @test @inferred(ArrayInterface.known_strides(A2r)) === (1, nothing, nothing) + @test @inferred(ArrayInterface.known_strides(A)) === (1, missing, missing) + @test @inferred(ArrayInterface.known_strides(Ap)) === (1, missing) + @test @inferred(ArrayInterface.known_strides(Ar)) === (1, missing, missing) + @test @inferred(ArrayInterface.known_strides(reshape(view(zeros(100), 1:60), (3,4,5)))) === (1, missing, missing) + @test @inferred(ArrayInterface.known_strides(A2)) === (1, missing, missing) + @test @inferred(ArrayInterface.known_strides(A2r)) === (1, missing, missing) @test @inferred(ArrayInterface.known_strides(S)) === (1, 2, 6) @test @inferred(ArrayInterface.known_strides(Sp)) === (6, 1, 2) @@ -735,10 +735,10 @@ end @testset "known_length" begin @test ArrayInterface.known_length(@inferred(ArrayInterface.indices(SOneTo(7)))) == 7 - @test ArrayInterface.known_length(1:2) === nothing + @test ArrayInterface.known_length(1:2) === missing @test ArrayInterface.known_length((1,)) == 1 @test ArrayInterface.known_length((a=1,b=2)) == 2 - @test ArrayInterface.known_length([]) === nothing + @test ArrayInterface.known_length([]) === missing @test ArrayInterface.known_length(CartesianIndex((1,2,3))) === 3 x = view(SArray{Tuple{3,3,3}}(ones(3,3,3)), :, SOneTo(2), 2) @@ -814,13 +814,6 @@ end @test ArrayInterface.deleteat((1, 2, 3), [1, 2]) == (3,) end -@testset "reduce_tup" begin - for n ∈ 2:16 - x = ntuple(_ -> rand(Bool) ? rand() : (rand(Bool) ? rand(0x00:0x1f) : rand(0:31)), n) - @test @inferred(ArrayInterface.reduce_tup(+, x)) ≈ reduce(+, x) - end -end - @testset "axes" begin include("axes.jl") end