diff --git a/.github/workflows/Downstream.yml b/.github/workflows/Downstream.yml new file mode 100644 index 0000000..4b15cde --- /dev/null +++ b/.github/workflows/Downstream.yml @@ -0,0 +1,76 @@ +name: Compatibility +on: + push: + branches: [master] + pull_request: + paths-ignore: + - 'LICENSE' + - 'README.md' + - '.github/workflows/TagBot.yml' + +concurrency: + group: build-${{ github.event.pull_request.number || github.ref }}-${{ github.workflow }} + cancel-in-progress: true + +jobs: + pre_job: + # continue-on-error: true # Uncomment once integration is finished + runs-on: ubuntu-latest + # Map a step output to a job output + outputs: + should_skip: ${{ steps.skip_check.outputs.should_skip }} + steps: + - id: skip_check + uses: fkirc/skip-duplicate-actions@v5 + test: + needs: pre_job + if: needs.pre_job.outputs.should_skip != 'true' + name: ${{ matrix.package.group }}/${{ matrix.package.repo }}/${{ matrix.julia-version }} + runs-on: ${{ matrix.os }} + strategy: + fail-fast: true + matrix: + julia-version: ['1'] + os: [ubuntu-latest] + package: + - {repo: BandedMatrices.jl, group: JuliaLinearAlgebra} + - {repo: CircularArrays.jl, group: Vexatos} + - {repo: ClassicalOrthogonalPolynomials.jl, group: JuliaApproximation} + - {repo: ContinuumArrays.jl, group: JuliaApproximation} + - {repo: InfiniteArrays.jl, group: JuliaArrays} + - {repo: IntervalSets.jl, group: JuliaMath} + - {repo: QuasiArrays.jl, group: JuliaApproximation} + + steps: + - uses: actions/checkout@v4 + - uses: julia-actions/setup-julia@v1 + with: + version: ${{ matrix.julia-version }} + arch: x64 + - uses: julia-actions/julia-buildpkg@latest + - name: Clone Downstream + uses: actions/checkout@v4 + with: + repository: ${{ matrix.package.group }}/${{ matrix.package.repo }} + path: downstream + - name: Load this and run the downstream tests + shell: julia --color=yes --project=downstream {0} + run: | + using Pkg + try + # force it to use this PR's version of the package + Pkg.develop(PackageSpec(path=".")) # resolver may fail with main deps + Pkg.update() + Pkg.test(; coverage = true) # resolver may fail with test time deps + catch err + err isa Pkg.Resolve.ResolverError || rethrow() + # If we can't resolve that means this is incompatible by SemVer and this is fine + # It means we marked this as a breaking change, so we don't need to worry about + # Mistakenly introducing a breaking change, as we have intentionally made one + @info "Not compatible with this release. No problem." exception=err + exit(0) # Exit immediately, as a success + end + - uses: julia-actions/julia-processcoverage@v1 + - uses: codecov/codecov-action@v3 + with: + files: lcov.info diff --git a/Project.toml b/Project.toml index 9ef689f..b6dc571 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ name = "PTYQoL" uuid = "551ad714-b11a-4605-8871-12721def4e72" authors = ["Tianyi Pu <912396513@qq.com> and contributors"] -version = "0.1.3" +version = "0.1.4" [weakdeps] LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" @@ -10,6 +10,9 @@ ContinuumArrays = "7ae1f121-cc2c-504b-ac30-9b923412ae5c" IntervalSets = "8197267c-284f-5f27-9208-e0e47529a953" QuasiArrays = "c4ea9172-b204-11e9-377d-29865faadc5c" ClassicalOrthogonalPolynomials = "b30e2e7b-c4ee-47da-9d5f-2c5c27239acd" +InfiniteArrays = "4858937d-0d70-526a-a4dd-2d5cb5dd786c" +BandedMatrices = "aae01518-5342-5314-be14-df237901396f" +ArrayLayouts = "4c555306-a7a7-4459-81d9-ec55ddd5c99a" [extensions] PTYQoLLinearAlgebraExt = "LinearAlgebra" @@ -18,6 +21,9 @@ PTYQoLContinuumArraysExt = "ContinuumArrays" PTYQoLIntervalSetsExt = "IntervalSets" PTYQoLQuasiArraysExt = "QuasiArrays" PTYQoLClassicalOrthogonalPolynomialsExt = "ClassicalOrthogonalPolynomials" +PTYQoLInfiniteArraysExt = "InfiniteArrays" +PTYQoLBandedMatricesExt = "BandedMatrices" +PTYQoLArrayLayoutsExt = "ArrayLayouts" [compat] julia = "1" @@ -29,6 +35,8 @@ DomainSets = "5b8099bc-c8ec-5219-889f-1d9e522a28bf" LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" ClassicalOrthogonalPolynomials = "b30e2e7b-c4ee-47da-9d5f-2c5c27239acd" +InfiniteArrays = "4858937d-0d70-526a-a4dd-2d5cb5dd786c" +ArrayLayouts = "4c555306-a7a7-4459-81d9-ec55ddd5c99a" [targets] -test = ["Test", "LinearAlgebra", "Documenter", "DomainSets", "ContinuumArrays", "ClassicalOrthogonalPolynomials"] +test = ["Test", "LinearAlgebra", "Documenter", "DomainSets", "ContinuumArrays", "ClassicalOrthogonalPolynomials", "InfiniteArrays", "ArrayLayouts"] diff --git a/ext/PTYQoLArrayLayoutsExt.jl b/ext/PTYQoLArrayLayoutsExt.jl new file mode 100644 index 0000000..16a8876 --- /dev/null +++ b/ext/PTYQoLArrayLayoutsExt.jl @@ -0,0 +1,9 @@ +module PTYQoLArrayLayoutsExt + +# https://github.com/JuliaLinearAlgebra/ArrayLayouts.jl/pull/184 +import ArrayLayouts: rowsupport, colsupport + +rowsupport(A, i::CartesianIndex{2}) = rowsupport(A, first(i)) +colsupport(A, i::CartesianIndex{2}) = colsupport(A, last(i)) + +end \ No newline at end of file diff --git a/ext/PTYQoLBandedMatricesExt.jl b/ext/PTYQoLBandedMatricesExt.jl new file mode 100644 index 0000000..25cc0ba --- /dev/null +++ b/ext/PTYQoLBandedMatricesExt.jl @@ -0,0 +1,32 @@ +module PTYQoLBandedMatricesExt + +import BandedMatrices: inbands_getindex, inbands_setindex!, AbstractBandedMatrix, bandwidths, MemoryLayout, BandedLayout +import Base: getindex, setindex!, @propagate_inbounds + +# too tedious to test + +MemoryLayout(::Type{<:AbstractBandedMatrix}) = BandedLayout() + +@propagate_inbounds function getindex(A::AbstractBandedMatrix, j::Integer, k::Integer) + @boundscheck checkbounds(A, j, k) + l, u = bandwidths(A) + if -l ≤ k-j ≤ u + inbands_getindex(A, j, k) + else + zero(eltype(A)) + end +end + +@propagate_inbounds function setindex!(A::AbstractBandedMatrix, v, j::Integer, k::Integer) + @boundscheck checkbounds(A, j, k) + l, u = bandwidths(A) + if -l ≤ k-j ≤ u + inbands_setindex!(A, v, j, k) + elseif iszero(v) + zero(eltype(A)) + else + error("out of band.") + end +end + +end \ No newline at end of file diff --git a/ext/PTYQoLInfiniteArraysExt.jl b/ext/PTYQoLInfiniteArraysExt.jl new file mode 100644 index 0000000..cd0079f --- /dev/null +++ b/ext/PTYQoLInfiniteArraysExt.jl @@ -0,0 +1,14 @@ +module PTYQoLInfiniteArraysExt + +import InfiniteArrays: InfStepRange, AbstractInfUnitRange, Zeros, ∞, diag, Diagonal +#import LinearAlgebra: diag, Diagonal + +infdiag(a, k) = iszero(k) ? copy(a.diag) : Zeros{eltype(a)}(∞) + +for TYP in (InfStepRange, AbstractInfUnitRange) + @eval begin + diag(a::Diagonal{T, <:$TYP}, k::Integer=0) where T = infdiag(a, k) + end +end + +end \ No newline at end of file diff --git a/src/PTYQoL.jl b/src/PTYQoL.jl index 7387401..364996a 100644 --- a/src/PTYQoL.jl +++ b/src/PTYQoL.jl @@ -58,4 +58,16 @@ import Base: == ==(f::Function, ::typeof(identity)) = isone(f) ==(::typeof(identity), f::Function) = isone(f) +import Base: getproperty, Fix2 +getproperty(x) = Fix2(getproperty, x) + +# https://github.com/JuliaLang/julia/pull/52312 +import Base: first, last, lastindex, front, tail, getindex +first(A::CartesianIndex) = first(Tuple(A)) +last(A::CartesianIndex) = last(Tuple(A)) +lastindex(A::CartesianIndex) = lastindex(Tuple(A)) +front(A::CartesianIndex) = CartesianIndex(front(Tuple(A))) +tail(A::CartesianIndex) = CartesianIndex(tail(Tuple(A))) +getindex(A::CartesianIndex, i) = CartesianIndex(Tuple(A)[i]) + end diff --git a/test/runtests.jl b/test/runtests.jl index a5608dd..6e68173 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -1,63 +1,77 @@ using PTYQoL using Test, Documenter -@testset "//" begin - @test 1 // 2 isa Rational - @test 1.0 // 2.0 == 1 // 2 -end - -@testset "dotu" begin - using LinearAlgebra - u = rand(10); v = rand(10) - @test LinearAlgebra.BLAS.dotu(u, v) == LinearAlgebra.BLAS.dotu(u, 1, v, 1) == LinearAlgebra.BLAS.dotu(10, u, 1, v, 1) ≈ u ⋅ v - - u = rand(ComplexF64, 10); v = rand(ComplexF64, 10) - @test endswith(string(which(LinearAlgebra.BLAS.dotu, map(typeof,(10,u,1,v,1))).file), "blas.jl") - @test LinearAlgebra.BLAS.dotu(u, v) == LinearAlgebra.BLAS.dotu(u, 1, v, 1) == LinearAlgebra.BLAS.dotu(10, u, 1, v, 1) -end - -@testset "eps ceil floor" begin - @test eps(ComplexF64) == eps(Float64) - @test ceil(0.5+0.5im) == 1+1im == floor(1.5+1.5im) +@testset "Pull Requests" begin + @testset "https://github.com/JuliaLang/julia/issues/35033" begin + @test startswith(AbstractArray, "Abstract") + @test endswith(AbstractArray, Array) + end + + @testset "https://github.com/JuliaLang/julia/pull/48894" begin + @test AbstractRange{Float64}(1:10) ≡ AbstractVector{Float64}(1:10) ≡ AbstractArray{Float64}(1:10) ≡ 1.0:10 + end + + @testset "https://github.com/JuliaLang/julia/pull/52312" begin + using Base: front, tail + ind = CartesianIndex(1,2,3) + @test first(ind) == 1 + @test last(ind) == ind[end] == 3 + @test front(ind) == ind[1:end-1] == CartesianIndex(1,2) + @test tail(ind) == ind[2:end] == CartesianIndex(2,3) + end end -@testset "front tail" begin - using Base: front, tail - @test front(1:10) == 1:9 == tail(0:9) -end +@testset "Misc" begin + @testset "//" begin + @test 1 // 2 isa Rational + @test 1.0 // 2.0 == 1 // 2 + end -@testset "https://github.com/JuliaLang/julia/issues/35033" begin - @test startswith(AbstractArray, "Abstract") - @test endswith(AbstractArray, Array) -end + @testset "dotu" begin + using LinearAlgebra + u = rand(10); v = rand(10) + @test LinearAlgebra.BLAS.dotu(u, v) == LinearAlgebra.BLAS.dotu(u, 1, v, 1) == LinearAlgebra.BLAS.dotu(10, u, 1, v, 1) ≈ u ⋅ v -@testset "https://github.com/JuliaLang/julia/pull/48894" begin - @test AbstractRange{Float64}(1:10) ≡ AbstractVector{Float64}(1:10) ≡ AbstractArray{Float64}(1:10) ≡ 1.0:10 -end + u = rand(ComplexF64, 10); v = rand(ComplexF64, 10) + @test endswith(string(which(LinearAlgebra.BLAS.dotu, map(typeof,(10,u,1,v,1))).file), "blas.jl") + @test LinearAlgebra.BLAS.dotu(u, v) == LinearAlgebra.BLAS.dotu(u, 1, v, 1) == LinearAlgebra.BLAS.dotu(10, u, 1, v, 1) + end -@testset "Function interface" begin - using Base: Fix2 - @test identity ∘ identity ≡ identity ≡ exp10 ∘ inv(exp10) ≡ log2 ∘ inv(log2) ≡ inv(identity) - @test identity ∘ exp ≡ exp ≡ exp ∘ identity - @test abs ∘ abs ≡ abs - @test inv(exp10 ∘ exp2) ≡ log2 ∘ log10 - @test Fix2(+, 0) == identity == Fix2(*, 1) + @testset "eps ceil floor" begin + @test eps(ComplexF64) == eps(Float64) + @test ceil(0.5+0.5im) == 1+1im == floor(1.5+1.5im) + end - @test Fix2(+, 1) ∘ Fix2(+, 2) == Fix2(+, 3) - @test Fix2(*, 2) ∘ Fix2(*, 3) == Fix2(*, 6) - @test Fix2(+, 3) ^ 5 == Fix2(+, 15) - @test Fix2(*, 4) ^ 3 == Fix2(*, 64) - @test Fix2(^, 2) ∘ Fix2(^, 3) == Fix2(^, 6) -end + @testset "front tail" begin + using Base: front, tail + @test front(1:10) == 1:9 == tail(0:9) + end -@testset "ln" begin - @test ln(1) == 0 # just for coverage + @testset "Function interface" begin + using Base: Fix2 + @test identity ∘ identity ≡ identity ≡ exp10 ∘ inv(exp10) ≡ log2 ∘ inv(log2) ≡ inv(identity) + @test identity ∘ exp ≡ exp ≡ exp ∘ identity + @test abs ∘ abs ≡ abs + @test inv(exp10 ∘ exp2) ≡ log2 ∘ log10 + @test Fix2(+, 0) == identity == Fix2(*, 1) + + @test Fix2(+, 1) ∘ Fix2(+, 2) == Fix2(+, 3) + @test Fix2(*, 2) ∘ Fix2(*, 3) == Fix2(*, 6) + @test Fix2(+, 3) ^ 5 == Fix2(+, 15) + @test Fix2(*, 4) ^ 3 == Fix2(*, 64) + @test Fix2(^, 2) ∘ Fix2(^, 3) == Fix2(^, 6) + end end -@testset "precision_convert" begin - setprecision(256) - x = precision_convert(BigFloat, BigFloat(1), 128) - @test precision(x) == 128 +@testset "Utils" begin + @testset "ln" begin + @test ln(1) == 0 # just for coverage + end + @testset "precision_convert" begin + setprecision(256) + x = precision_convert(BigFloat, BigFloat(1), 128) + @test precision(x) == 128 + end end @testset "Extensions" begin @@ -79,6 +93,19 @@ end @test AbstractJacobi{BigFloat}(Legendre()) isa Legendre{BigFloat} @test AbstractJacobi{Float32}(Ultraspherical(2)) isa Ultraspherical{Float32} end + @testset "InfiniteArrays" begin + using InfiniteArrays + D = Diagonal(1:∞) + @test diag(D) == 1:∞ + @test diag(D, 1) == Zeros(∞) + end + @testset "ArrayLayouts" begin + using ArrayLayouts + A = rand(3,5) + ind = CartesianIndex(2,3) + @test rowsupport(A, ind) == rowsupport(A,2) + @test colsupport(A, ind) == colsupport(A,3) + end end DocMeta.setdocmeta!(PTYQoL, :DocTestSetup, :(using PTYQoL); recursive=true)