Skip to content

Commit a3fda75

Browse files
authored
update for VectorInterface 0.4 (#11)
* update for VectorInterface 0.4 * Use PackageExtensionCompat * Update default scalars to `One` and `Zero` * make `scale!(v, 0)` return empty sparse array * Update github actions * Remove stray use of Requires
1 parent 139df46 commit a3fda75

File tree

11 files changed

+92
-128
lines changed

11 files changed

+92
-128
lines changed

.github/dependabot.yml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
2+
version: 2
3+
updates:
4+
- package-ecosystem: "github-actions"
5+
directory: "/" # Location of package manifests
6+
schedule:
7+
interval: "weekly"

.github/workflows/ci-julia-nightly.yml

Lines changed: 0 additions & 34 deletions
This file was deleted.

.github/workflows/ci.yml

Lines changed: 36 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,16 @@
11
name: CI
22
on:
3-
- push
4-
- pull_request
3+
workflow_dispatch:
4+
push:
5+
branches:
6+
- master
7+
tags: '*'
8+
pull_request:
9+
10+
concurrency:
11+
group: ${{ github.workflow }}-${{ github.ref }}
12+
cancel-in-progress: true
13+
514
jobs:
615
test:
716
name: Julia ${{ matrix.version }} - ${{ matrix.os }} - ${{ matrix.arch }}
@@ -19,17 +28,39 @@ jobs:
1928
arch:
2029
- x64
2130
steps:
22-
- uses: actions/checkout@v3
31+
- uses: actions/checkout@v4
2332
- uses: julia-actions/setup-julia@v1
2433
with:
2534
version: ${{ matrix.version }}
2635
arch: ${{ matrix.arch }}
2736
- uses: julia-actions/cache@v1
2837
- uses: julia-actions/julia-buildpkg@latest
2938
- uses: julia-actions/julia-runtest@latest
30-
# env:
31-
# JULIA_NUM_THREADS: 4
3239
- uses: julia-actions/julia-processcoverage@v1
3340
- uses: codecov/codecov-action@v3
3441
with:
3542
file: lcov.info
43+
test-nightly:
44+
needs: test
45+
name: Julia nightly - ${{ matrix.os }} - ${{ matrix.arch }}
46+
runs-on: ${{ matrix.os }}
47+
strategy:
48+
fail-fast: false
49+
matrix:
50+
version:
51+
- 'nightly'
52+
os:
53+
- ubuntu-latest
54+
- macOS-latest
55+
- windows-latest
56+
arch:
57+
- x64
58+
steps:
59+
- uses: actions/checkout@v4
60+
- uses: julia-actions/setup-julia@v1
61+
with:
62+
version: ${{ matrix.version }}
63+
arch: ${{ matrix.arch }}
64+
- uses: julia-actions/cache@v1
65+
- uses: julia-actions/julia-buildpkg@latest
66+
- uses: julia-actions/julia-runtest@latest

Project.toml

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,12 @@ version = "0.3.1"
55

66
[deps]
77
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
8-
Requires = "ae029012-a4dd-5104-9daa-d747884805df"
8+
PackageExtensionCompat = "65ce6f38-6b18-4e1d-a461-8949797d7930"
99
TensorOperations = "6aa20fa7-93e2-5fca-9bc0-fbd0db3c71a2"
1010
TupleTools = "9d95972d-f1c8-5527-a6e0-b4b365fa01f6"
1111
VectorInterface = "409d34a3-91d5-4945-b6ec-7529ddf182d8"
1212

1313
[weakdeps]
14-
Requires = "ae029012-a4dd-5104-9daa-d747884805df"
1514
SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf"
1615
TensorOperations = "6aa20fa7-93e2-5fca-9bc0-fbd0db3c71a2"
1716

@@ -20,10 +19,10 @@ SparseArrayKitSparseArrays = "SparseArrays"
2019
SparseArrayKitTensorOperations = "TensorOperations"
2120

2221
[compat]
23-
Requires = "1"
22+
PackageExtensionCompat = "1"
2423
TensorOperations = "4"
2524
TupleTools = "1.1"
26-
VectorInterface = "0.3"
25+
VectorInterface = "0.4.1"
2726
julia = "1.6"
2827

2928
[extras]

ext/SparseArrayKitSparseArrays.jl

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,6 @@
11
module SparseArrayKitSparseArrays
22

3-
@static if isdefined(Base, :get_extension)
4-
using SparseArrays: SparseMatrixCSC, nonzeros, rowvals, nzrange
5-
else
6-
using ..SparseArrays: SparseMatrixCSC, nonzeros, rowvals, nzrange
7-
end
8-
3+
using SparseArrays: SparseMatrixCSC, nonzeros, rowvals, nzrange
94
using SparseArrayKit
105

116
Base.convert(T::Type{<:SparseArray}, a::SparseMatrixCSC) = T(a)

ext/SparseArrayKitTensorOperations.jl

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,7 @@
11
module SparseArrayKitTensorOperations
22

3-
@static if isdefined(Base, :get_extension)
4-
using TensorOperations: TensorOperations, Index2Tuple, linearize
5-
else
6-
using ..TensorOperations: TensorOperations, Index2Tuple, linearize
7-
end
8-
const TO = TensorOperations
9-
3+
import TensorOperations as TO
4+
using TensorOperations: Index2Tuple, linearize, numind
105
using SparseArrayKit: tensoradd!, tensortrace!, tensorcontract!, SparseArray
116

127
function TO.tensoradd!(C::SparseArray, pC::Index2Tuple,
@@ -30,12 +25,12 @@ function TO.tensorcontract!(C::SparseArray, pC::Index2Tuple,
3025
end
3126

3227
function TO.tensoradd_type(TC, pA::Index2Tuple, ::SparseArray, ::Symbol)
33-
return SparseArray{TC,sum(length.(pA))}
28+
return SparseArray{TC,numind(pA)}
3429
end
3530

3631
function TO.tensorcontract_type(TC, pC, ::SparseArray, pA, conjA,
3732
::SparseArray, pB, conjB)
38-
return SparseArray{TC,sum(length.(pC))}
33+
return SparseArray{TC,numind(pC)}
3934
end
4035

4136
end

src/SparseArrayKit.jl

Lines changed: 2 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,9 @@
11
module SparseArrayKit
22

33
using VectorInterface
4-
using VectorInterface: _one
5-
_isone::Number) = α === _one
6-
74
using LinearAlgebra
8-
95
using TupleTools
106

11-
if !isdefined(Base, :get_extension)
12-
using Requires
13-
end
14-
157
const IndexTuple{N} = NTuple{N,Int}
168

179
export SparseArray
@@ -25,16 +17,9 @@ include("linearalgebra.jl")
2517

2618
# Initialization
2719
#-----------------
20+
using PackageExtensionCompat
2821
function __init__()
29-
@static if !isdefined(Base, :get_extension)
30-
@require TensorOperations = "6aa20fa7-93e2-5fca-9bc0-fbd0db3c71a2" begin
31-
include("../ext/SparseArrayKitTensorOperations.jl")
32-
end
33-
34-
@require SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf" begin
35-
include("../ext/SparseArrayKitSparseArrays.jl")
36-
end
37-
end
22+
@require_extensions
3823
end
3924

4025
end

src/linearalgebra.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -90,5 +90,5 @@ function LinearAlgebra.mul!(C::SM, A::ASM, B::ASM, α::Number, β::Number)
9090
return tensorcontract!(C, (1, 2), AA, CA, oindA, cindA, BB, CB, oindB, cindB, α, β)
9191
end
9292

93-
LinearAlgebra.adjoint!(C::SM, A::SM) = tensoradd!(C, (2, 1), A, :C, true, false)
94-
LinearAlgebra.transpose!(C::SM, A::SM) = tensoradd!(C, (2, 1), A, :N, true, false)
93+
LinearAlgebra.adjoint!(C::SM, A::SM) = tensoradd!(C, (2, 1), A, :C, One(), Zero())
94+
LinearAlgebra.transpose!(C::SM, A::SM) = tensoradd!(C, (2, 1), A, :N, One(), Zero())

src/tensoroperations.jl

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,12 @@
22
#-------------------------------
33
function tensoradd!(C::SparseArray{<:Any,N}, indCinA,
44
A::SparseArray{<:Any,N}, CA::Symbol,
5-
α::Number=true, β::Number=true) where {N}
5+
α::Number=One(), β::Number=One()) where {N}
66
(N == length(indCinA) && TupleTools.isperm(indCinA)) ||
77
throw(ArgumentError("Invalid permutation of length $N: $indCinA"))
88
size(C) == TupleTools.getindices(size(A), indCinA) ||
99
throw(DimensionMismatch("non-matching sizes while adding arrays"))
10-
11-
β == one(β) || (iszero(β) ? _zero!(C) : LinearAlgebra.lmul!(β, C))
10+
scale!(C, β)
1211
for (IA, vA) in A.data
1312
IC = CartesianIndex(TupleTools.getindices(IA.I, indCinA))
1413
C[IC] += α * (CA == :C ? conj(vA) : vA)
@@ -18,7 +17,7 @@ end
1817

1918
function tensortrace!(C::SparseArray{<:Any,NC}, indCinA,
2019
A::SparseArray{<:Any,NA}, CA::Symbol, cindA1, cindA2,
21-
α::Number=true, β::Number=false) where {NA,NC}
20+
α::Number=One(), β::Number=Zero()) where {NA,NC}
2221
NC == length(indCinA) ||
2322
throw(ArgumentError("Invalid selection of $NC out of $NA: $indCinA"))
2423
NA - NC == 2 * length(cindA1) == 2 * length(cindA2) ||
@@ -35,7 +34,7 @@ function tensortrace!(C::SparseArray{<:Any,NC}, indCinA,
3534
sizeC == TupleTools.getindices(sizeA, indCinA) ||
3635
throw(DimensionMismatch("non-matching sizes"))
3736

38-
β == one(β) || (iszero(β) ? _zero!(C) : LinearAlgebra.lmul!(β, C))
37+
scale!(C, β)
3938
for (IA, v) in A.data
4039
IAc1 = CartesianIndex(TupleTools.getindices(IA.I, cindA1))
4140
IAc2 = CartesianIndex(TupleTools.getindices(IA.I, cindA2))
@@ -50,7 +49,7 @@ end
5049
function tensorcontract!(C::SparseArray, indCinoAB,
5150
A::SparseArray, CA::Symbol, oindA, cindA,
5251
B::SparseArray, CB::Symbol, oindB, cindB,
53-
α::Number=true, β::Number=false)
52+
α::Number=One(), β::Number=Zero())
5453
pA = (oindA..., cindA...)
5554
(length(pA) == ndims(A) && TupleTools.isperm(pA)) ||
5655
throw(ArgumentError("invalid permutation of length $(ndims(A)): $pA"))
@@ -76,7 +75,7 @@ function tensorcontract!(C::SparseArray, indCinoAB,
7675
TupleTools.getindices((osizeA..., osizeB...), indCinoAB) == size(C) ||
7776
throw(DimensionMismatch("non-matching sizes in uncontracted dimensions"))
7877

79-
β == one(β) || (iszero(β) ? _zero!(C) : LinearAlgebra.lmul!(β, C))
78+
scale!(C, β)
8079

8180
keysA = sort!(collect(nonzero_keys(A));
8281
by=IA -> CartesianIndex(TupleTools.getindices(IA.I, cindA)))

src/vectorinterface.jl

Lines changed: 21 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,22 @@
1-
# Vector interface implementation for 'SparseArray
1+
# Vector interface implementation for SparseArray
22
##################################################################
33
# zerovector & zerovector!!
44
#---------------------------
55
function VectorInterface.zerovector(x::SparseArray, ::Type{S}) where {S<:Number}
6-
T = typeof(zero(eltype(x)) * zero(S))
7-
return SparseArray{T}(undef, size(x))
6+
return SparseArray{S}(undef, size(x))
87
end
9-
108
VectorInterface.zerovector!(x::SparseArray) = _zero!(x)
119
VectorInterface.zerovector!!(x::SparseArray) = zerovector!(x)
1210

1311
# scale, scale! & scale!!
1412
#-------------------------
15-
VectorInterface.scale(x::SparseArray, α::Number) = _isone(α) ? copy(x) : x * α
16-
13+
function VectorInterface.scale(x::SparseArray, α::Number)
14+
α === One() && return copy(x)
15+
α === Zero() && return zerovector(x)
16+
return x * α
17+
end
1718
function VectorInterface.scale!(x::SparseArray, α::Number)
18-
_isone(α) && return x
19+
iszero(α) && return zerovector!(x)
1920
# typical occupation in a dict is about 30% from experimental testing
2021
# the benefits of scaling all values (e.g. SIMD) largely outweight the extra work
2122
scale!(x.data.vals, α)
@@ -25,24 +26,22 @@ function VectorInterface.scale!(y::SparseArray, x::SparseArray, α::Number)
2526
ax = axes(x)
2627
ay = axes(y)
2728
ax == ay || throw(DimensionMismatch("output axes $ay differ from input axes $ax"))
28-
_zero!(y)
29+
zerovector!(y)
2930
for (k, v) in nonzero_pairs(x)
3031
y[k] = scale!!(v, α)
3132
end
3233
return y
3334
end
34-
3535
function VectorInterface.scale!!(x::SparseArray, α::Number)
36-
T = scalartype(x)
37-
if promote_type(T, typeof(α)) <: T
36+
α === One() && return x
37+
if VectorInterface.promote_scale(x, α) <: scalartype(x)
3838
return scale!(x, α)
3939
else
4040
return scale(x, α)
4141
end
4242
end
4343
function VectorInterface.scale!!(y::SparseArray, x::SparseArray, α::Number)
44-
T = scalartype(y)
45-
if promote_type(T, typeof(α), scalartype(x)) <: T
44+
if VectorInterface.promote_scale(x, α) <: scalartype(y)
4645
return scale!(y, x, α)
4746
else
4847
return scale(x, α)
@@ -51,40 +50,30 @@ end
5150

5251
# add, add! & add!!
5352
#-------------------
54-
function VectorInterface.add(y::SparseArray,
55-
x::SparseArray,
56-
α::Number=_one,
57-
β::Number=_one)
53+
function VectorInterface.add(y::SparseArray, x::SparseArray, α::Number, β::Number)
5854
ax = axes(x)
5955
ay = axes(y)
6056
ax == ay || throw(DimensionMismatch("output axes $ay differ from input axes $ax"))
61-
T = promote_type(scalartype(y), scalartype(x), typeof(α), typeof(β))
57+
T = VectorInterface.promote_add(y, x, α, β)
6258
z = SparseArray{T}(undef, size(y))
6359
scale!(z, y, β)
6460
add!(z, x, α)
6561
return z
6662
end
6763

68-
function VectorInterface.add!(y::SparseArray,
69-
x::SparseArray,
70-
α::Number=_one,
71-
β::Number=_one)
64+
function VectorInterface.add!(y::SparseArray, x::SparseArray, α::Number, β::Number)
7265
ax = axes(x)
7366
ay = axes(y)
7467
ax == ay || throw(DimensionMismatch("output axes $ay differ from input axes $ax"))
75-
_isone(β) || (iszero(β) ? _zero!(y) : scale!(y, β))
68+
scale!(y, β)
7669
for (k, v) in nonzero_pairs(x)
7770
increaseindex!(y, scale!!(v, α), k)
7871
end
7972
return y
8073
end
8174

82-
function VectorInterface.add!!(y::SparseArray,
83-
x::SparseArray,
84-
α::Number=_one,
85-
β::Number=_one)
86-
T = scalartype(y)
87-
if promote_type(T, typeof(α), typeof(β), scalartype(x)) <: T
75+
function VectorInterface.add!!(y::SparseArray, x::SparseArray, α::Number, β::Number)
76+
if VectorInterface.promote_add(y, x, α, β) <: scalartype(y)
8877
return add!(y, x, α, β)
8978
else
9079
return add(y, x, α, β)
@@ -97,14 +86,14 @@ function VectorInterface.inner(x::SparseArray, y::SparseArray)
9786
ax = axes(x)
9887
ay = axes(y)
9988
ax == ay || throw(DimensionMismatch("dot arguments have non-matching axes $ax and $ay"))
100-
s = dot(zero(eltype(x)), zero(eltype(y)))
89+
s = zero(VectorInterface.promote_inner(x, y))
10190
if nonzero_length(x) >= nonzero_length(y)
10291
@inbounds for I in nonzero_keys(x)
103-
s += dot(x[I], y[I])
92+
s += VectorInterface.inner(x[I], y[I])
10493
end
10594
else
10695
@inbounds for I in nonzero_keys(y)
107-
s += dot(x[I], y[I])
96+
s += VectorInterface.inner(x[I], y[I])
10897
end
10998
end
11099
return s

0 commit comments

Comments
 (0)