Skip to content

Commit f97d55a

Browse files
authored
Initial package draft (#1)
1 parent 10e8b9b commit f97d55a

17 files changed

+663
-33
lines changed

Project.toml

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,27 @@ uuid = "a07dfc7f-7d04-4eb5-84cc-a97f051f655a"
33
authors = ["ITensor developers <[email protected]> and contributors"]
44
version = "0.1.0"
55

6+
[deps]
7+
Adapt = "79e6a3ab-5dfb-504d-930d-738a2a938a0e"
8+
ExproniconLite = "55351af7-c7e9-48d6-89ff-24e801d99491"
9+
MLStyle = "d8e11817-5142-5d16-987a-aa16d5891078"
10+
TypeParameterAccessors = "7e5a90cf-f82e-492e-a09b-e3e26432c138"
11+
612
[compat]
13+
Adapt = "4.1.1"
714
Aqua = "0.8.9"
15+
ExproniconLite = "0.10.13"
16+
MLStyle = "0.4.17"
817
SafeTestsets = "0.1"
918
Suppressor = "0.2"
1019
Test = "1.10"
1120
julia = "1.10"
1221

1322
[extras]
1423
Aqua = "4c88cf16-eb10-579e-8560-4a9242c79595"
15-
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
1624
SafeTestsets = "1bc83da4-3b8d-516f-aca4-4fe02f6d838f"
1725
Suppressor = "fd094767-a336-5f1f-9728-57cf17d0bbfb"
26+
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
1827

1928
[targets]
2029
test = ["Aqua", "Test", "Suppressor", "SafeTestsets"]

README.md

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

3434
````julia
35-
using Derive: Derive
35+
using Derive: Derive, @derive, @interface, interface
36+
using Test: @test
3637
````
3738

38-
Examples go here.
39+
Define an interface.
40+
41+
````julia
42+
struct SparseArrayInterface end
43+
````
44+
45+
Define interface functions.
46+
47+
````julia
48+
@interface SparseArrayInterface() function Base.getindex(a, I::Int...)
49+
checkbounds(a, I...)
50+
!isstored(a, I...) && return getunstoredindex(a, I...)
51+
return getstoredindex(a, I...)
52+
end
53+
@interface SparseArrayInterface() function Base.setindex!(a, value, I::Int...)
54+
checkbounds(a, I...)
55+
iszero(value) && return a
56+
if !isstored(a, I...)
57+
setunstoredindex!(a, value, I...)
58+
return a
59+
end
60+
setstoredindex!(a, value, I...)
61+
return a
62+
end
63+
````
64+
65+
Define a type that will derive the interface.
66+
67+
````julia
68+
struct SparseArrayDOK{T,N} <: AbstractArray{T,N}
69+
storage::Dict{CartesianIndex{N},T}
70+
size::NTuple{N,Int}
71+
end
72+
storage(a::SparseArrayDOK) = a.storage
73+
Base.size(a::SparseArrayDOK) = a.size
74+
function SparseArrayDOK{T}(size::Int...) where {T}
75+
N = length(size)
76+
return SparseArrayDOK{T,N}(Dict{CartesianIndex{N},T}(), size)
77+
end
78+
function isstored(a::SparseArrayDOK, I::Int...)
79+
return CartesianIndex(I) in keys(storage(a))
80+
end
81+
function getstoredindex(a::SparseArrayDOK, I::Int...)
82+
return storage(a)[CartesianIndex(I)]
83+
end
84+
function getunstoredindex(a::SparseArrayDOK, I::Int...)
85+
return zero(eltype(a))
86+
end
87+
function setstoredindex!(a::SparseArrayDOK, value, I::Int...)
88+
storage(a)[CartesianIndex(I)] = value
89+
return a
90+
end
91+
function setunstoredindex!(a::SparseArrayDOK, value, I::Int...)
92+
storage(a)[CartesianIndex(I)] = value
93+
return a
94+
end
95+
````
96+
97+
Speficy the interface the type adheres to.
98+
99+
````julia
100+
Derive.interface(::Type{<:SparseArrayDOK}) = SparseArrayInterface()
101+
````
102+
103+
Derive the interface for the type.
104+
105+
````julia
106+
@derive (T=SparseArrayDOK,) begin
107+
Base.getindex(::T, ::Int...)
108+
Base.setindex!(::T, ::Any, ::Int...)
109+
end
110+
111+
a = SparseArrayDOK{Float64}(2, 2)
112+
a[1, 1] = 2
113+
@test a[1, 1] == 2
114+
@test a[2, 1] == 0
115+
@test a[1, 2] == 0
116+
@test a[2, 2] == 0
117+
````
118+
119+
Call the sparse array interface on a dense array.
120+
121+
````julia
122+
isstored(a::AbstractArray, I::Int...) = true
123+
getstoredindex(a::AbstractArray, I::Int...) = getindex(a, I...)
124+
setstoredindex!(a::AbstractArray, value, I::Int...) = setindex!(a, value, I...)
125+
126+
a = zeros(2, 2)
127+
@interface SparseArrayInterface() a[1, 1] = 2
128+
@test @interface(SparseArrayInterface(), a[1, 1]) == 2
129+
@test @interface(SparseArrayInterface(), a[2, 1]) == 0
130+
@test @interface(SparseArrayInterface(), a[1, 2]) == 0
131+
@test @interface(SparseArrayInterface(), a[2, 2]) == 0
132+
````
39133

40134
---
41135

TODO.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# Fix this, there is a namespace issue:
2+
# Use `GlobalRef`, use a generalization of `globalref_derive`.
3+
function derive(::Val{:AbstractArrayOps}, type)
4+
return quote
5+
ArrayLayouts.MemoryLayout(::Type{<:$type})
6+
LinearAlgebra.mul!(::Any, ::$type, ::$type, ::Number, ::Number)
7+
end
8+
end
9+

docs/make.jl

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
11
using Derive: Derive
22
using Documenter: Documenter, DocMeta, deploydocs, makedocs
33

4-
DocMeta.setdocmeta!(
5-
Derive, :DocTestSetup, :(using Derive); recursive=true
6-
)
4+
DocMeta.setdocmeta!(Derive, :DocTestSetup, :(using Derive); recursive=true)
75

86
include("make_index.jl")
97

@@ -12,13 +10,9 @@ makedocs(;
1210
authors="ITensor developers <[email protected]> and contributors",
1311
sitename="Derive.jl",
1412
format=Documenter.HTML(;
15-
canonical="https://ITensor.github.io/Derive.jl",
16-
edit_link="main",
17-
assets=String[],
13+
canonical="https://ITensor.github.io/Derive.jl", edit_link="main", assets=String[]
1814
),
1915
pages=["Home" => "index.md"],
2016
)
2117

22-
deploydocs(;
23-
repo="github.com/ITensor/Derive.jl", devbranch="main", push_preview=true
24-
)
18+
deploydocs(; repo="github.com/ITensor/Derive.jl", devbranch="main", push_preview=true)

examples/README.jl

Lines changed: 79 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,5 +37,82 @@ julia> Pkg.add("Derive")
3737

3838
# ## Examples
3939

40-
using Derive: Derive
41-
# Examples go here.
40+
using Derive: Derive, @derive, @interface, interface
41+
using Test: @test
42+
43+
# Define an interface.
44+
struct SparseArrayInterface end
45+
46+
# Define interface functions.
47+
@interface SparseArrayInterface() function Base.getindex(a, I::Int...)
48+
checkbounds(a, I...)
49+
!isstored(a, I...) && return getunstoredindex(a, I...)
50+
return getstoredindex(a, I...)
51+
end
52+
@interface SparseArrayInterface() function Base.setindex!(a, value, I::Int...)
53+
checkbounds(a, I...)
54+
iszero(value) && return a
55+
if !isstored(a, I...)
56+
setunstoredindex!(a, value, I...)
57+
return a
58+
end
59+
setstoredindex!(a, value, I...)
60+
return a
61+
end
62+
63+
# Define a type that will derive the interface.
64+
struct SparseArrayDOK{T,N} <: AbstractArray{T,N}
65+
storage::Dict{CartesianIndex{N},T}
66+
size::NTuple{N,Int}
67+
end
68+
storage(a::SparseArrayDOK) = a.storage
69+
Base.size(a::SparseArrayDOK) = a.size
70+
function SparseArrayDOK{T}(size::Int...) where {T}
71+
N = length(size)
72+
return SparseArrayDOK{T,N}(Dict{CartesianIndex{N},T}(), size)
73+
end
74+
function isstored(a::SparseArrayDOK, I::Int...)
75+
return CartesianIndex(I) in keys(storage(a))
76+
end
77+
function getstoredindex(a::SparseArrayDOK, I::Int...)
78+
return storage(a)[CartesianIndex(I)]
79+
end
80+
function getunstoredindex(a::SparseArrayDOK, I::Int...)
81+
return zero(eltype(a))
82+
end
83+
function setstoredindex!(a::SparseArrayDOK, value, I::Int...)
84+
storage(a)[CartesianIndex(I)] = value
85+
return a
86+
end
87+
function setunstoredindex!(a::SparseArrayDOK, value, I::Int...)
88+
storage(a)[CartesianIndex(I)] = value
89+
return a
90+
end
91+
92+
# Speficy the interface the type adheres to.
93+
Derive.interface(::Type{<:SparseArrayDOK}) = SparseArrayInterface()
94+
95+
# Derive the interface for the type.
96+
@derive (T=SparseArrayDOK,) begin
97+
Base.getindex(::T, ::Int...)
98+
Base.setindex!(::T, ::Any, ::Int...)
99+
end
100+
101+
a = SparseArrayDOK{Float64}(2, 2)
102+
a[1, 1] = 2
103+
@test a[1, 1] == 2
104+
@test a[2, 1] == 0
105+
@test a[1, 2] == 0
106+
@test a[2, 2] == 0
107+
108+
# Call the sparse array interface on a dense array.
109+
isstored(a::AbstractArray, I::Int...) = true
110+
getstoredindex(a::AbstractArray, I::Int...) = getindex(a, I...)
111+
setstoredindex!(a::AbstractArray, value, I::Int...) = setindex!(a, value, I...)
112+
113+
a = zeros(2, 2)
114+
@interface SparseArrayInterface() a[1, 1] = 2
115+
@test @interface(SparseArrayInterface(), a[1, 1]) == 2
116+
@test @interface(SparseArrayInterface(), a[2, 1]) == 0
117+
@test @interface(SparseArrayInterface(), a[1, 2]) == 0
118+
@test @interface(SparseArrayInterface(), a[2, 2]) == 0

src/Derive.jl

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,12 @@
11
module Derive
22

3-
# Write your package code here.
3+
include("interface_function.jl")
4+
include("abstractinterface.jl")
5+
include("derive_macro.jl")
6+
include("interface_macro.jl")
7+
include("wrappedarrays.jl")
8+
include("abstractarrayinterface.jl")
9+
include("defaultarrayinterface.jl")
10+
include("traits.jl")
411

512
end

src/abstractarrayinterface.jl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
# TODO: Add `ndims` type parameter.
2+
abstract type AbstractArrayInterface <: AbstractInterface end

src/abstractinterface.jl

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# Get the interface of an object.
2+
interface(x) = interface(typeof(x))
3+
# TODO: Define as `DefaultInterface()`.
4+
interface(::Type) = error("Interface unknown.")
5+
6+
# Adapted from `Base.Broadcast.combine_styles`.
7+
# Get the combined interfaces of the input objects.
8+
function combine_interfaces(x1, x2, x_rest...)
9+
return combine_interfaces(combine_interfaces(x1, x2), x_rest...)
10+
end
11+
combine_interfaces(x1, x2) = comine_interface_rule(interface(x1), interface(x2))
12+
combine_interfaces(x) = interface(x)
13+
14+
# Rules for combining interfaces.
15+
function combine_interface_rule(
16+
interface1::Interface, interface2::Interface
17+
) where {Interface}
18+
return interface1
19+
end
20+
# TODO: Define as `UnknownInterface()`.
21+
combine_interface_rule(interface1, interface2) = error("No rule for combining interfaces.")
22+
23+
abstract type AbstractInterface end
24+
25+
(interface::AbstractInterface)(f) = InterfaceFunction(interface, f)

src/defaultarrayinterface.jl

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# TODO: Add `ndims` type parameter.
2+
struct DefaultArrayInterface <: AbstractArrayInterface end
3+
4+
using TypeParameterAccessors: parenttype
5+
function interface(a::Type{<:AbstractArray})
6+
parenttype(a) === a && return DefaultArrayInterface()
7+
return interface(parenttype(a))
8+
end

0 commit comments

Comments
 (0)