Skip to content

Commit c67b83a

Browse files
authored
Rewrite using Derive and new interface (#3)
* Rewrite using Derive and new interface * Bump to v0.2
1 parent f4c7dcf commit c67b83a

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

57 files changed

+1040
-2440
lines changed

Project.toml

Lines changed: 10 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,32 @@
11
name = "SparseArraysBase"
22
uuid = "0d5efcca-f356-4864-8770-e1ed8d78f208"
33
authors = ["ITensor developers <[email protected]> and contributors"]
4-
version = "0.1.0"
4+
version = "0.2.0"
55

66
[deps]
7-
Accessors = "7d9f7c33-5ae7-4f3b-8dc6-eff91059b697"
8-
Adapt = "79e6a3ab-5dfb-504d-930d-738a2a938a0e"
97
ArrayLayouts = "4c555306-a7a7-4459-81d9-ec55ddd5c99a"
108
BroadcastMapConversion = "4a4adec5-520f-4750-bb37-d5e66b4ddeb2"
11-
Compat = "34da2185-b29b-5c13-b0c7-acf172513d20"
9+
Derive = "a07dfc7f-7d04-4eb5-84cc-a97f051f655a"
1210
Dictionaries = "85a47980-9c8c-11e8-2b9f-f7ca1fa99fb4"
1311
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
14-
MacroTools = "1914dd2f-81c6-5fcd-8719-6d5c9610ff09"
15-
NestedPermutedDimsArrays = "2c2a8ec4-3cfc-4276-aa3e-1307b4294e58"
16-
SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf"
17-
TypeParameterAccessors = "7e5a90cf-f82e-492e-a09b-e3e26432c138"
18-
VectorInterface = "409d34a3-91d5-4945-b6ec-7529ddf182d8"
1912

2013
[compat]
21-
Accessors = "0.1.38"
22-
Adapt = "4.1.1"
2314
Aqua = "0.8.9"
24-
ArrayLayouts = "1.10.4"
25-
Compat = "4.16.0"
15+
ArrayLayouts = "1.11.0"
16+
BroadcastMapConversion = "0.1.0"
17+
Derive = "0.3.0"
2618
Dictionaries = "0.4.3"
2719
LinearAlgebra = "1.10"
28-
MacroTools = "0.5.13"
29-
SparseArrays = "1.10"
20+
SafeTestsets = "0.1"
21+
Suppressor = "0.2"
3022
Test = "1.10"
31-
VectorInterface = "0.5.0"
3223
julia = "1.10"
3324

3425
[extras]
3526
Aqua = "4c88cf16-eb10-579e-8560-4a9242c79595"
27+
SafeTestsets = "1bc83da4-3b8d-516f-aca4-4fe02f6d838f"
28+
Suppressor = "fd094767-a336-5f1f-9728-57cf17d0bbfb"
3629
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
3730

3831
[targets]
39-
test = ["Aqua", "Test"]
32+
test = ["Aqua", "Test", "Suppressor", "SafeTestsets"]

README.md

Lines changed: 119 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,10 +32,127 @@ julia> Pkg.add("SparseArraysBase")
3232
## Examples
3333

3434
````julia
35-
using SparseArraysBase: SparseArraysBase
35+
using SparseArraysBase:
36+
SparseArrayDOK,
37+
SparseMatrixDOK,
38+
SparseVectorDOK,
39+
eachstoredindex,
40+
getstoredindex,
41+
getunstoredindex,
42+
isstored,
43+
setstoredindex!,
44+
setunstoredindex!,
45+
storedlength,
46+
storedpairs,
47+
storedvalues,
48+
zero!
49+
using Test: @test, @test_throws
50+
51+
a = SparseArrayDOK{Float64}(2, 2)
52+
````
53+
54+
AbstractArray interface:
55+
56+
````julia
57+
@test iszero(a)
58+
@test iszero(sum(a))
59+
@test iszero(storedlength(a))
60+
61+
a[1, 2] = 12
62+
@test a == [0 12; 0 0]
63+
@test a[1, 1] == 0
64+
@test a[2, 1] == 0
65+
@test a[1, 2] == 12
66+
@test a[2, 2] == 0
67+
````
68+
69+
SparseArraysBase interface:
70+
71+
````julia
72+
using Dictionaries: IndexError
73+
@test issetequal(eachstoredindex(a), [CartesianIndex(1, 2)])
74+
@test getstoredindex(a, 1, 2) == 12
75+
@test_throws IndexError getstoredindex(a, 1, 1)
76+
@test getunstoredindex(a, 1, 1) == 0
77+
@test getunstoredindex(a, 1, 2) == 0
78+
@test !isstored(a, 1, 1)
79+
@test isstored(a, 1, 2)
80+
@test setstoredindex!(copy(a), 21, 1, 2) == [0 21; 0 0]
81+
@test_throws IndexError setstoredindex!(copy(a), 21, 2, 1)
82+
@test setunstoredindex!(copy(a), 21, 1, 2) == [0 21; 0 0]
83+
@test storedlength(a) == 1
84+
@test issetequal(storedpairs(a), [CartesianIndex(1, 2) => 12])
85+
@test issetequal(storedvalues(a), [12])
86+
@test sum(a) == 12
87+
@test isreal(a)
88+
@test !iszero(a)
89+
@test mapreduce(x -> 2x, +, a) == 24
90+
````
91+
92+
AbstractArray functionality:
93+
94+
````julia
95+
b = a .+ 2 .* a'
96+
@test b isa SparseMatrixDOK{Float64}
97+
@test b == [0 12; 24 0]
98+
@test storedlength(b) == 2
99+
@test sum(b) == 36
100+
@test isreal(b)
101+
@test !iszero(b)
102+
@test mapreduce(x -> 2x, +, b) == 72
103+
104+
b = permutedims(a, (2, 1))
105+
@test b isa SparseMatrixDOK{Float64}
106+
@test b[1, 1] == a[1, 1]
107+
@test b[2, 1] == a[1, 2]
108+
@test b[1, 2] == a[2, 1]
109+
@test b[2, 2] == a[2, 2]
110+
111+
b = a * a'
112+
@test b isa SparseMatrixDOK{Float64}
113+
@test b == [144 0; 0 0]
114+
@test storedlength(b) == 1
36115
````
37116

38-
Examples go here.
117+
Second column.
118+
119+
````julia
120+
b = a[1:2, 2]
121+
@test b isa SparseVectorDOK{Float64}
122+
@test b == [12, 0]
123+
@test storedlength(b) == 1
124+
125+
a = SparseArrayDOK{Float64}(2, 2)
126+
a .= 2
127+
for I in eachindex(a)
128+
@test a[I] == 2
129+
end
130+
@test storedlength(a) == length(a)
131+
132+
a = SparseArrayDOK{Float64}(2, 2)
133+
fill!(a, 2)
134+
for I in eachindex(a)
135+
@test a[I] == 2
136+
end
137+
@test storedlength(a) == length(a)
138+
139+
a = SparseArrayDOK{Float64}(2, 2)
140+
fill!(a, 0)
141+
@test iszero(a)
142+
@test iszero(storedlength(a))
143+
144+
a = SparseArrayDOK{Float64}(2, 2)
145+
a[1, 2] = 12
146+
zero!(a)
147+
@test iszero(a)
148+
@test iszero(storedlength(a))
149+
150+
a = SparseArrayDOK{Float64}(2, 2)
151+
a[1, 2] = 12
152+
b = zero(a)
153+
@test iszero(b)
154+
@test iszero(storedlength(b))
155+
````
39156

40157
---
41158

TODO.md

Lines changed: 1 addition & 124 deletions
Original file line numberDiff line numberDiff line change
@@ -1,124 +1 @@
1-
# To-do
2-
3-
- Remove Compat.jl from dependencies and test dependencies.
4-
- Unregistered dependencies: BroadcastMapConversion, NestedPermutedDimsArrays, TypeParameterAccessors.
5-
- Create SparseArraysBaseLinearAlgebraExt, SparseArraysBaseNestedPermutedDimsArraysExt, SparseArraysBaseVectorInterfaceExt.
6-
- Change [sources] entries from paths to urls.
7-
8-
# SparseArraysBase
9-
10-
SparseArraysBase is a package that aims to expand on the sparse array functionality that is currently in Julia Base.
11-
While SparseArrays.jl is centered mostly around `SparseMatrixCSC` and the SuiteSparse library, here we wish to broaden the scope a bit, and consider generic sparse arrays.
12-
Abstractly, the mental model can be considered as a storage object that holds the stored values, and a bijection between the array indices and the indices of the storage.
13-
For now, we focus on providing efficient implementations of Dictionary of Key (DOK) type sparse storage formats, but may expand upon this in the future.
14-
As a result, for typical linear algebra routines, we still expect `SparseMatrixCSC` to be the object of choice.
15-
16-
The design consists of roughly three components:
17-
- `AbstractSparseArray` interface functions
18-
- Overloaded Julia base methods
19-
- `SparseArrayDOK` struct that implements this
20-
21-
## AbstractSparseArray
22-
23-
The first part consists of typical functions that are useful in the context of sparse arrays.
24-
The minimal interface, which enables the usage of the rest of this package, consists of the following functions:
25-
26-
| Signature | Description | Default |
27-
|-----------|-------------|---------|
28-
| `sparse_storage(a::AbstractArray)` | Returns the storage object of the sparse array | `a` |
29-
| `storage_index_to_index(a::AbstractArray, I)` | Converts a storage index to an array index | `I` |
30-
| `index_to_storage_index(a::AbstractArray, I)` | Converts an array index to a storage index | `I` |
31-
32-
Using these primitives, several convenience functions are defined to facilitate the writing of sparse array algorithms.
33-
34-
| Signature | Description | Default |
35-
|-----------|-------------|---------|
36-
| `storage_indices(a)` | Returns the indices of the storage | `eachindex(sparse_storage(a))` |
37-
| `stored_indices(a)` | Returns the indices of the stored values | `Iterators.map(Base.Fix1(storage_index_to_index, a), storage_indices(a))` |
38-
| `stored_length(a)` | Returns the number of stored values | `length(storage_indices(a))` |
39-
40-
<!-- TODO: `getindex!`, `increaseindex!`, `sparse_map`, expose "zero" functionality? -->
41-
42-
Interesting to note here is that the design is such that we can define sparse arrays without having to subtype `AbstractSparseArray`.
43-
To achieve this, each function `f` is defined in terms of `sparse_f`, rather than directly overloading `f`.
44-
<!--
45-
TODO:
46-
In order to opt-in to the sparse array functionality, one needs to dispatch the functions through `sparse_f` instead of `f`.
47-
For convenience, you can automatically dispatch all functions through `sparse_f` by using the following macro:
48-
49-
```julia
50-
@abstractsparsearray MySparseArrayType
51-
```
52-
-->
53-
54-
## Overloaded Julia base methods
55-
56-
The second part consists of overloading Julia base methods to work with sparse arrays.
57-
In particular, specialised implementations exist for the following functions:
58-
59-
- `sparse_similar`
60-
- `sparse_reduce`
61-
- `sparse_map`
62-
- `sparse_map!`
63-
- `sparse_all`
64-
- `sparse_any`
65-
- `sparse_isequal`
66-
- `sparse_fill!`
67-
- `sparse_zero`, `sparse_zero!`, `sparse_iszero`
68-
- `sparse_one`, `sparse_one!`, `sparse_isone`
69-
- `sparse_reshape`, `sparse_reshape!`
70-
- `sparse_cat`, `sparse_cat!`
71-
- `sparse_copy!`, `sparse_copyto!`
72-
- `sparse_permutedims`, `sparse_permutedims!`
73-
- `sparse_mul!`, `sparse_dot`
74-
75-
## SparseArrayDOK
76-
77-
Finally, the `SparseArrayDOK` struct is provided as a concrete implementation of the `AbstractSparseArray` interface.
78-
It is a dictionary of keys (DOK) type sparse array, which stores the values in a `Dictionaries.jl` dictionary, and maps the indices to the keys of the dictionary.
79-
This model is particularly useful for sparse arrays with a small number of non-zero elements, or for arrays that are constructed incrementally, as it boasts fast random accesses and insertions.
80-
The drawback is that sequential iteration is slower than for other sparse array types, leading to slower linear algebra operations.
81-
For the purposes of `SparseArraysBase`, this struct will serve as the canonical example of a sparse array, and will be returned by default when new sparse arrays are created.
82-
83-
One particular feature of `SparseArrayDOK` is that it can be used in cases where the non-stored entries have to be constructed in a non-trivial way.
84-
Typically, sparse arrays use `zero(eltype(a))` to construct the non-stored entries, but this is not always sufficient.
85-
A concrete example is found in `BlockSparseArrays.jl`, where initialization of the non-stored entries requires the construction of a block of zeros of appropriate size.
86-
87-
<!-- TODO: update TODOs -->
88-
89-
## TODO
90-
Still need to implement `Base` functions:
91-
```julia
92-
[x] sparse_zero(a::AbstractArray) = similar(a)
93-
[x] sparse_iszero(a::AbstractArray) = iszero(nonzero_length(a)) # Uses `all`, make `sparse_all`?
94-
[x] sparse_one(a::AbstractArray) = ...
95-
[x] sparse_isreal(a::AbstractArray) = ... # Uses `all`, make `sparse_all`?
96-
[x] sparse_isequal(a1::AbstractArray, a2::AbstractArray) = ...
97-
[x] sparse_conj!(a::AbstractArray) = conj!(nonzeros(a))
98-
[x] sparse_reshape(a::AbstractArray, dims) = ...
99-
[ ] sparse_all(f, a::AbstractArray) = ...
100-
[ ] sparse_getindex(a::AbstractArray, 1:2, 2:3) = ... # Slicing
101-
```
102-
`LinearAlgebra` functions:
103-
```julia
104-
[ ] sparse_mul!
105-
[ ] sparse_lmul!
106-
[ ] sparse_ldiv!
107-
[ ] sparse_rdiv!
108-
[ ] sparse_axpby!
109-
[ ] sparse_axpy!
110-
[ ] sparse_norm
111-
[ ] sparse_dot/sparse_inner
112-
[ ] sparse_adoint!
113-
[ ] sparse_transpose!
114-
115-
# Using conversion to `SparseMatrixCSC`:
116-
[ ] sparse_qr
117-
[ ] sparse_eigen
118-
[ ] sparse_svd
119-
```
120-
`TensorAlgebra` functions:
121-
```julia
122-
[ ] add!
123-
[ ] contract!
124-
```
1+
- Updates for latest Derive.

docs/Project.toml

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
[deps]
2-
BroadcastMapConversion = "4a4adec5-520f-4750-bb37-d5e66b4ddeb2"
2+
Dictionaries = "85a47980-9c8c-11e8-2b9f-f7ca1fa99fb4"
33
Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4"
44
Literate = "98b081ad-f1c9-55d3-8b20-4c87d4299306"
5-
NestedPermutedDimsArrays = "2c2a8ec4-3cfc-4276-aa3e-1307b4294e58"
65
SparseArraysBase = "0d5efcca-f356-4864-8770-e1ed8d78f208"
7-
TypeParameterAccessors = "7e5a90cf-f82e-492e-a09b-e3e26432c138"

examples/Project.toml

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
[deps]
2-
BroadcastMapConversion = "4a4adec5-520f-4750-bb37-d5e66b4ddeb2"
3-
NestedPermutedDimsArrays = "2c2a8ec4-3cfc-4276-aa3e-1307b4294e58"
2+
Dictionaries = "85a47980-9c8c-11e8-2b9f-f7ca1fa99fb4"
43
SparseArraysBase = "0d5efcca-f356-4864-8770-e1ed8d78f208"
5-
TypeParameterAccessors = "7e5a90cf-f82e-492e-a09b-e3e26432c138"
4+
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"

0 commit comments

Comments
 (0)