Skip to content

Commit 9f1be65

Browse files
Merge pull request #276 from JuliaArrays/known
Move known_first, known_step, and known_last to ArrayInterfaceCore
2 parents 8790826 + 04cdd07 commit 9f1be65

File tree

14 files changed

+189
-154
lines changed

14 files changed

+189
-154
lines changed

.github/workflows/Documentation.yml

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,10 @@ jobs:
1414
- uses: julia-actions/setup-julia@latest
1515
with:
1616
version: '1'
17-
- name: Install dependencies
18-
run: julia --project=docs/ -e 'using Pkg; Pkg.develop(PackageSpec(path=pwd())); Pkg.instantiate()'
19-
- name: Build and deploy
17+
- run: julia --project -e 'using Pkg; Pkg.develop([PackageSpec(path=joinpath(pwd(), "lib", "ArrayInterfaceCore"))])'
18+
- uses: julia-actions/julia-buildpkg@latest
19+
- run: julia --project=docs/ -e 'using Pkg; Pkg.develop([PackageSpec(path=joinpath(pwd(), "lib", "ArrayInterfaceCore"))]); Pkg.instantiate()'
20+
- uses: julia-actions/julia-docdeploy@releases/v1
2021
env:
21-
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # For authentication with GitHub Actions token
22-
DOCUMENTER_KEY: ${{ secrets.DOCUMENTER_KEY }} # For authentication with SSH deploy key
23-
run: julia --project=docs/ docs/make.jl
22+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
23+
DOCUMENTER_KEY: ${{ secrets.DOCUMENTER_KEY }}

.github/workflows/Downstream.yml

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -34,29 +34,23 @@ jobs:
3434
with:
3535
version: ${{ matrix.julia-version }}
3636
arch: x64
37-
- name: Setup ArrayInterface
38-
shell: julia --color=yes {0}
39-
run: |
40-
using Pkg
41-
function dev_subpkg(subpkg)
42-
subpkg_path = joinpath("lib", subpkg)
43-
Pkg.develop(Pkg.PackageSpec(path=subpkg_path))
44-
end
45-
dev_subpkg("ArrayInterfaceCore")
46-
Pkg.build()
37+
- uses: julia-actions/julia-buildpkg@latest
4738
- name: Clone Downstream
4839
uses: actions/checkout@v2
4940
with:
5041
repository: ${{ matrix.package.user }}/${{ matrix.package.repo }}
5142
path: downstream
5243
- name: Load this and run the downstream tests
53-
shell: julia --color=yes --project=downstream {0}
44+
shell: julia --color=yes {0}
5445
run: |
5546
using Pkg
5647
try
5748
# force it to use this PR's version of the package
5849
Pkg.develop(PackageSpec(path=".")) # resolver may fail with main deps
59-
50+
Pkg.develop(Pkg.PackageSpec(path=joinpath(pwd(), "lib", "ArrayInterfaceCore")))
51+
Pkg.develop(Pkg.PackageSpec(path=joinpath(pwd(), "lib", "ArrayInterfaceOffsetArrays")))
52+
Pkg.develop(Pkg.PackageSpec(path=joinpath(pwd(), "lib", "ArrayInterfaceStaticArrays")))
53+
Pkg.activate("downstream")
6054
Pkg.update()
6155
Pkg.test() # resolver may fail with test time deps
6256
catch err

.github/workflows/ci.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ on:
99
jobs:
1010
test:
1111
runs-on: ubuntu-latest
12+
continue-on-error: ${{ matrix.group == 'Downstream' }}
1213
strategy:
1314
fail-fast: false
1415
matrix:

Project.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
name = "ArrayInterface"
22
uuid = "4fba245c-0d91-5ea0-9b3e-6abc04ee57a9"
3-
version = "6.0.1"
3+
version = "6.0.2"
44

55
[deps]
66
ArrayInterfaceCore = "30b0a656-2188-435a-8636-2ec0e6a096e2"

docs/make.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using ArrayInterface
2+
using Pkg
23

34
function dev_subpkg(subpkg)
45
subpkg_path = joinpath(dirname(@__DIR__), "lib", subpkg)
@@ -21,4 +22,3 @@ makedocs(;
2122
deploydocs(;
2223
repo="github.com/JuliaArrays/ArrayInterface.jl"
2324
)
24-

lib/ArrayInterfaceCore/Project.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
name = "ArrayInterfaceCore"
22
uuid = "30b0a656-2188-435a-8636-2ec0e6a096e2"
33
authors = ["Zachary P. Christensen <[email protected]>"]
4-
version = "0.1.2"
4+
version = "0.1.3"
55

66
[deps]
77
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"

lib/ArrayInterfaceCore/src/ArrayInterfaceCore.jl

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -441,4 +441,95 @@ Base.@propagate_inbounds function Base.getindex(ind::TridiagonalIndex, i::Int)
441441
end
442442
end
443443

444+
_cartesian_index(i::Tuple{Vararg{Int}}) = CartesianIndex(i)
445+
_cartesian_index(::Any) = nothing
446+
447+
"""
448+
known_first(::Type{T}) -> Union{Int,Nothing}
449+
450+
If `first` of an instance of type `T` is known at compile time, return it.
451+
Otherwise, return `nothing`.
452+
453+
```julia
454+
julia> ArrayInterface.known_first(typeof(1:4))
455+
nothing
456+
457+
julia> ArrayInterface.known_first(typeof(Base.OneTo(4)))
458+
1
459+
```
460+
"""
461+
known_first(x) = known_first(typeof(x))
462+
function known_first(::Type{T}) where {T}
463+
if parent_type(T) <: T
464+
return nothing
465+
else
466+
return known_first(parent_type(T))
467+
end
468+
end
469+
known_first(::Type{Base.OneTo{T}}) where {T} = 1
470+
function known_first(::Type{<:CartesianIndices{N,R}}) where {N,R}
471+
_cartesian_index(ntuple(i -> known_first(R.parameters[i]), Val(N)))
472+
end
473+
474+
"""
475+
known_last(::Type{T}) -> Union{Int,Nothing}
476+
477+
If `last` of an instance of type `T` is known at compile time, return it.
478+
Otherwise, return `nothing`.
479+
480+
```julia
481+
julia> ArrayInterface.known_last(typeof(1:4))
482+
nothing
483+
484+
julia> ArrayInterface.known_first(typeof(static(1):static(4)))
485+
4
486+
487+
```
488+
"""
489+
known_last(x) = known_last(typeof(x))
490+
known_last(::Type{T}) where {T} = parent_type(T) <: T ? nothing : known_last(parent_type(T))
491+
function known_last(::Type{<:CartesianIndices{N,R}}) where {N,R}
492+
_cartesian_index(ntuple(i -> known_last(R.parameters[i]), Val(N)))
493+
end
494+
495+
"""
496+
known_step(::Type{T}) -> Union{Int,Nothing}
497+
498+
If `step` of an instance of type `T` is known at compile time, return it.
499+
Otherwise, return `nothing`.
500+
501+
```julia
502+
julia> ArrayInterface.known_step(typeof(1:2:8))
503+
nothing
504+
505+
julia> ArrayInterface.known_step(typeof(1:4))
506+
1
507+
508+
```
509+
"""
510+
known_step(x) = known_step(typeof(x))
511+
known_step(::Type{T}) where {T} = parent_type(T) <: T ? nothing : known_step(parent_type(T))
512+
known_step(::Type{<:AbstractUnitRange}) = 1
513+
514+
"""
515+
is_splat_index(::Type{T}) -> Bool
516+
Returns `static(true)` if `T` is a type that splats across multiple dimensions.
517+
"""
518+
is_splat_index(@nospecialize(x)) = is_splat_index(typeof(x))
519+
is_splat_index(T::Type) = false
520+
521+
"""
522+
ndims_index(::Type{I}) -> Int
523+
524+
Returns the number of dimension that an instance of `I` maps to when indexing. For example,
525+
`CartesianIndex{3}` maps to 3 dimensions. If this method is not explicitly defined, then `1`
526+
is returned.
527+
"""
528+
ndims_index(@nospecialize(i)) = ndims_index(typeof(i))
529+
ndims_index(::Type{I}) where {I} = 1
530+
ndims_index(::Type{<:Base.AbstractCartesianIndex{N}}) where {N} = N
531+
ndims_index(::Type{<:AbstractArray{T}}) where {T} = ndims_index(T)
532+
ndims_index(::Type{<:AbstractArray{Bool,N}}) where {N} = N
533+
ndims_index(::Type{<:Base.LogicalIndex{<:Any,<:AbstractArray{Bool,N}}}) where {N} = N
534+
444535
end # module

lib/ArrayInterfaceCore/test/runtests.jl

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -239,4 +239,25 @@ end
239239
@test has_sparsestruct(STri)
240240
rowind,colind=findstructralnz(STri)
241241
@test [STri[rowind[i],colind[i]] for i in 1:length(rowind)]==[1,2,3,4,5,6,7,5,6,7]
242-
end
242+
end
243+
244+
@testset "known values" begin
245+
CI = CartesianIndices((2, 2))
246+
247+
@test isnothing(@inferred(ArrayInterfaceCore.known_first(typeof(1:4))))
248+
@test isone(@inferred(ArrayInterfaceCore.known_first(Base.OneTo(4))))
249+
@test isone(@inferred(ArrayInterfaceCore.known_first(typeof(Base.OneTo(4)))))
250+
@test @inferred(ArrayInterfaceCore.known_first(typeof(CI))) == CartesianIndex(1, 1)
251+
@test @inferred(ArrayInterfaceCore.known_first(typeof(CI))) == CartesianIndex(1, 1)
252+
253+
@test isnothing(@inferred(ArrayInterfaceCore.known_last(1:4)))
254+
@test isnothing(@inferred(ArrayInterfaceCore.known_last(typeof(1:4))))
255+
@test @inferred(ArrayInterfaceCore.known_last(typeof(CI))) === nothing
256+
257+
@test isnothing(@inferred(ArrayInterfaceCore.known_step(typeof(1:0.2:4))))
258+
@test isone(@inferred(ArrayInterfaceCore.known_step(1:4)))
259+
@test isone(@inferred(ArrayInterfaceCore.known_step(typeof(1:4))))
260+
@test isone(@inferred(ArrayInterfaceCore.known_step(typeof(Base.Slice(1:4)))))
261+
@test isone(@inferred(ArrayInterfaceCore.known_step(typeof(view(1:4, 1:2)))))
262+
end
263+

src/ArrayInterface.jl

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import ArrayInterfaceCore: allowed_getindex, allowed_setindex!, aos_to_soa, buff
55
parent_type, fast_matrix_colors, findstructralnz, has_sparsestruct,
66
issingular, isstructured, matrix_colors, restructure, lu_instance,
77
safevec, zeromatrix, ColoringAlgorithm, merge_tuple_type,
8-
fast_scalar_indexing, parameterless_type, _is_reshaped
8+
fast_scalar_indexing, parameterless_type, _is_reshaped, ndims_index, is_splat_index
99

1010
# ArrayIndex subtypes and methods
1111
import ArrayInterfaceCore: ArrayIndex, MatrixIndex, VectorIndex, BidiagonalIndex, TridiagonalIndex
@@ -17,6 +17,8 @@ import ArrayInterfaceCore: MatAdjTrans, VecAdjTrans, UpTri, LoTri
1717
import ArrayInterfaceCore: AbstractDevice, AbstractCPU, CPUPointer, CPUTuple, CheckParent,
1818
CPUIndex, GPU, can_avx
1919

20+
import ArrayInterfaceCore: known_first, known_step, known_last
21+
2022
using Static
2123
using Static: Zero, One, nstatic, eq, ne, gt, ge, lt, le, eachop, eachop_tuple,
2224
permute, invariant_permutation, field_type, reduce_tup, find_first_eq

src/axes.jl

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -191,11 +191,11 @@ Base.IndexStyle(::Type{T}) where {T<:LazyAxis} = IndexStyle(parent_type(T))
191191

192192
can_change_size(::Type{LazyAxis{N,P}}) where {N,P} = can_change_size(P)
193193

194-
known_first(::Type{LazyAxis{N,P}}) where {N,P} = known_offsets(P, static(N))
195-
known_first(::Type{LazyAxis{:,P}}) where {P} = 1
194+
ArrayInterfaceCore.known_first(::Type{LazyAxis{N,P}}) where {N,P} = known_offsets(P, static(N))
195+
ArrayInterfaceCore.known_first(::Type{LazyAxis{:,P}}) where {P} = 1
196196
Base.firstindex(x::LazyAxis) = first(x)
197197
@inline function Base.first(x::LazyAxis{N})::Int where {N}
198-
if known_first(x) === nothing
198+
if ArrayInterfaceCore.known_first(x) === nothing
199199
return Int(offsets(parent(x), static(N)))
200200
else
201201
return Int(known_first(x))
@@ -208,8 +208,8 @@ end
208208
return known_first(x)
209209
end
210210
end
211-
known_last(::Type{LazyAxis{N,P}}) where {N,P} = known_last(axes_types(P, static(N)))
212-
known_last(::Type{LazyAxis{:,P}}) where {P} = known_length(P)
211+
ArrayInterfaceCore.known_last(::Type{LazyAxis{N,P}}) where {N,P} = known_last(axes_types(P, static(N)))
212+
ArrayInterfaceCore.known_last(::Type{LazyAxis{:,P}}) where {P} = known_length(P)
213213
Base.lastindex(x::LazyAxis) = last(x)
214214
Base.last(x::LazyAxis) = _last(known_last(x), x)
215215
_last(::Nothing, x) = last(parent(x))

0 commit comments

Comments
 (0)