Skip to content

Commit 732bd28

Browse files
authored
Support Infinities v0.1 (#83)
* Support Infinities v0.1 * DiracDelta fixes * avoid stack overflow in derivative * basis view materialize * Update bases.jl * Fix B'D' simplify * Check axes match * better support for vector sub-bases * Update runtests.jl * v0.6.4
1 parent 77f1f97 commit 732bd28

File tree

6 files changed

+92
-25
lines changed

6 files changed

+92
-25
lines changed

Project.toml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
name = "ContinuumArrays"
22
uuid = "7ae1f121-cc2c-504b-ac30-9b923412ae5c"
3-
version = "0.6.3"
3+
version = "0.6.4"
44

55
[deps]
66
ArrayLayouts = "4c555306-a7a7-4459-81d9-ec55ddd5c99a"
@@ -18,10 +18,10 @@ StaticArrays = "90137ffa-7385-5640-81b9-e52037218182"
1818
[compat]
1919
ArrayLayouts = "0.5, 0.6"
2020
BandedMatrices = "0.16"
21-
BlockArrays = "0.14, 0.15"
21+
BlockArrays = "0.15.1"
2222
FillArrays = "0.11"
2323
InfiniteArrays = "0.9, 0.10"
24-
Infinities = "0.0.1, 0.0.2"
24+
Infinities = "0.0.1, 0.0.2, 0.1"
2525
IntervalSets = "0.5"
2626
LazyArrays = "0.20, 0.21"
2727
QuasiArrays = "0.4.1"

src/ContinuumArrays.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ using IntervalSets, LinearAlgebra, LazyArrays, FillArrays, BandedMatrices, Quasi
33
import Base: @_inline_meta, @_propagate_inbounds_meta, axes, getindex, convert, prod, *, /, \, +, -, ==, ^,
44
IndexStyle, IndexLinear, ==, OneTo, _maybetail, tail, similar, copyto!, copy, diff,
55
first, last, show, isempty, findfirst, findlast, findall, Slice, union, minimum, maximum, sum, _sum,
6-
getproperty, isone, iszero, zero, abs, <, , >, , string, summary, to_indices
6+
getproperty, isone, iszero, zero, abs, <, , >, , string, summary, to_indices, view
77
import Base.Broadcast: materialize, BroadcastStyle, broadcasted
88
import LazyArrays: MemoryLayout, Applied, ApplyStyle, flatten, _flatten, colsupport, most, combine_mul_styles, AbstractArrayApplyStyle,
99
adjointlayout, arguments, _mul_arguments, call, broadcastlayout, layout_getindex, UnknownLayout,

src/bases/bases.jl

Lines changed: 31 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ broadcastlayout(::Type{typeof(*)}, ::WeightLayout, ::MappedBasisLayouts) = Mappe
3434

3535
# A sub of a weight is still a weight
3636
sublayout(::WeightLayout, _) = WeightLayout()
37-
sublayout(::AbstractBasisLayout, ::Type{<:Tuple{Map,AbstractUnitRange}}) = MappedBasisLayout()
37+
sublayout(::AbstractBasisLayout, ::Type{<:Tuple{Map,AbstractVector}}) = MappedBasisLayout()
3838

3939

4040
## Weighted basis interface
@@ -290,23 +290,37 @@ end
290290

291291

292292
# Differentiation of sub-arrays
293-
@simplify function *(A::Derivative, B::SubQuasiArray{<:Any,2,<:AbstractQuasiMatrix,<:Tuple{<:Inclusion,<:Any}})
293+
294+
# avoid stack overflow from unmaterialize Derivative() * parent()
295+
_der_sub(DP, inds...) = DP[inds...]
296+
_der_sub(DP::ApplyQuasiMatrix{T,typeof(*),<:Tuple{Derivative,Any}}, kr, jr) where T = ApplyQuasiMatrix{T}(*, DP.args[1], view(DP.args[2], kr, jr))
297+
298+
# need to customise simplifiable so can't use @simplify
299+
simplifiable(::typeof(*), A::Derivative, B::SubQuasiArray{<:Any,2,<:AbstractQuasiMatrix,<:Tuple{<:Inclusion,<:Any}})= simplifiable(*, A, parent(B))
300+
simplifiable(::typeof(*), Ac::QuasiAdjoint{<:Any,<:SubQuasiArray{<:Any,2,<:AbstractQuasiMatrix,<:Tuple{<:Inclusion,<:Any}}}, Bc::QuasiAdjoint{<:Any,<:Derivative}) = simplifiable(*, Bc', Ac')
301+
function mul(A::Derivative, B::SubQuasiArray{<:Any,2,<:AbstractQuasiMatrix,<:Tuple{<:Inclusion,<:Any}})
302+
axes(A,2) == axes(B,1) || throw(DimensionMismatch())
294303
P = parent(B)
295-
(Derivative(axes(P,1))*P)[parentindices(B)...]
304+
_der_sub(Derivative(axes(P,1))*P, parentindices(B)...)
296305
end
306+
mul(Ac::QuasiAdjoint{<:Any,<:SubQuasiArray{<:Any,2,<:AbstractQuasiMatrix,<:Tuple{<:Inclusion,<:Any}}}, Bc::QuasiAdjoint{<:Any,<:Derivative}) = mul(Bc', Ac')'
297307

298-
@simplify function *(A::Derivative, B::SubQuasiArray{<:Any,2,<:AbstractQuasiMatrix,<:Tuple{<:AbstractAffineQuasiVector,<:Any}})
308+
simplifiable(::typeof(*), A::Derivative, B::SubQuasiArray{<:Any,2,<:AbstractQuasiMatrix,<:Tuple{<:AbstractAffineQuasiVector,<:Any}}) = simplifiable(*, A, parent(B))
309+
simplifiable(::typeof(*), Ac::QuasiAdjoint{<:Any,<:SubQuasiArray{<:Any,2,<:AbstractQuasiMatrix,<:Tuple{<:AbstractAffineQuasiVector,<:Any}}}, Bc::QuasiAdjoint{<:Any,<:Derivative}) = simplifiable(*, Bc', Ac')
310+
function mul(A::Derivative, B::SubQuasiArray{<:Any,2,<:AbstractQuasiMatrix,<:Tuple{<:AbstractAffineQuasiVector,<:Any}})
311+
axes(A,2) == axes(B,1) || throw(DimensionMismatch())
299312
P = parent(B)
300313
kr,jr = parentindices(B)
301314
(Derivative(axes(P,1))*P*kr.A)[kr,jr]
302315
end
316+
mul(Ac::QuasiAdjoint{<:Any,<:SubQuasiArray{<:Any,2,<:AbstractQuasiMatrix,<:Tuple{<:AbstractAffineQuasiVector,<:Any}}}, Bc::QuasiAdjoint{<:Any,<:Derivative}) = mul(Bc', Ac')'
303317

304318
# we represent as a Mul with a banded matrix
305-
sublayout(::AbstractBasisLayout, ::Type{<:Tuple{<:Inclusion,<:AbstractUnitRange}}) = SubBasisLayout()
306-
sublayout(::AbstractBasisLayout, ::Type{<:Tuple{<:AbstractAffineQuasiVector,<:AbstractUnitRange}}) = MappedBasisLayout()
307-
sublayout(::WeightedBasisLayouts, ::Type{<:Tuple{<:AbstractAffineQuasiVector,<:AbstractUnitRange}}) = MappedWeightedBasisLayout()
308-
sublayout(::WeightedBasisLayout, ::Type{<:Tuple{<:Inclusion,<:AbstractUnitRange}}) = SubWeightedBasisLayout()
309-
sublayout(::MappedWeightedBasisLayout, ::Type{<:Tuple{<:Inclusion,<:AbstractUnitRange}}) = MappedWeightedBasisLayout()
319+
sublayout(::AbstractBasisLayout, ::Type{<:Tuple{<:Inclusion,<:AbstractVector}}) = SubBasisLayout()
320+
sublayout(::AbstractBasisLayout, ::Type{<:Tuple{<:AbstractAffineQuasiVector,<:AbstractVector}}) = MappedBasisLayout()
321+
sublayout(::WeightedBasisLayouts, ::Type{<:Tuple{<:AbstractAffineQuasiVector,<:AbstractVector}}) = MappedWeightedBasisLayout()
322+
sublayout(::WeightedBasisLayout, ::Type{<:Tuple{<:Inclusion,<:AbstractVector}}) = SubWeightedBasisLayout()
323+
sublayout(::MappedWeightedBasisLayout, ::Type{<:Tuple{<:Inclusion,<:AbstractVector}}) = MappedWeightedBasisLayout()
310324

311325
@inline sub_materialize(::AbstractBasisLayout, V::AbstractQuasiArray) = V
312326
@inline sub_materialize(::AbstractBasisLayout, V::AbstractArray) = V
@@ -348,6 +362,14 @@ function arguments(::ApplyLayout{typeof(*)}, V::SubQuasiArray{<:Any,2,<:Any,<:Tu
348362
A,P
349363
end
350364

365+
function arguments(::ApplyLayout{typeof(*)}, V::SubQuasiArray{<:Any,2,<:Any,<:Tuple{<:Inclusion,<:AbstractVector}})
366+
A = parent(V)
367+
_,jr = parentindices(V)
368+
first(jr) 1 || throw(BoundsError())
369+
P = Eye{Int}((axes(A,2),))[:,jr]
370+
A,P
371+
end
372+
351373
####
352374
# sum
353375
####

src/basisconcat.jl

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,10 @@ end
1515

1616

1717
"""
18-
PiecewiseBasis
18+
PiecewiseBasis(args...)
1919
20-
is an analogue of `Basis` that takes the union of the first axis.
20+
is an analogue of `Basis` that takes the union of the first axis,
21+
and the second axis is a blocked concatenatation of args.
2122
If there is overlap, it uses the first in order.
2223
"""
2324
struct PiecewiseBasis{T, Args} <: AbstractConcatBasis{T}
@@ -31,13 +32,12 @@ PiecewiseBasis(args::AbstractVector) = PiecewiseBasis{eltype(eltype(args))}(args
3132

3233
concatbasis(::PiecewiseBasis, args...) = PiecewiseBasis(args...)
3334

34-
_blockedrange(a::Tuple) = blockedrange(SVector(a...))
35-
_blockedrange(a::AbstractVector) = blockedrange(a)
3635

37-
axes(A::PiecewiseBasis) = (union(axes.(A.args,1)...), _blockedrange(size.(A.args,2)))
36+
axes(A::PiecewiseBasis) = (union(axes.(A.args,1)...), blockedrange(size.(A.args,2)))
3837

3938
==(A::PiecewiseBasis, B::PiecewiseBasis) = all(A.args .== B.args)
4039

40+
4141
function QuasiArrays._getindex(::Type{IND}, A::PiecewiseBasis{T}, (x,j)::IND) where {IND,T}
4242
Jj = findblockindex(axes(A,2), j)
4343
J = Int(block(Jj))
@@ -67,7 +67,7 @@ VcatBasis(args::Vararg{Any,N}) where N = VcatBasis{SVector{N,mapreduce(eltype,pr
6767

6868
concatbasis(::VcatBasis, args...) = VcatBasis(args...)
6969

70-
axes(A::VcatBasis{<:Any,<:Tuple}) = (axes(A.args[1],1), _blockedrange(size.(A.args,2)))
70+
axes(A::VcatBasis{<:Any,<:Tuple}) = (axes(A.args[1],1), blockedrange(size.(A.args,2)))
7171

7272
==(A::VcatBasis, B::VcatBasis) = all(A.args .== B.args)
7373

@@ -99,12 +99,12 @@ HvcatBasis(n::Int, args::Vararg{Any,N}) where N = HvcatBasis{Matrix{mapreduce(el
9999

100100
concatbasis(S::HvcatBasis, args...) = HvcatBasis(S.n, args...)
101101

102-
axes(A::HvcatBasis{<:Any,<:Tuple}) = (axes(A.args[1],1), _blockedrange(size.(A.args,2)))
102+
axes(A::HvcatBasis{<:Any,<:Tuple}) = (axes(A.args[1],1), blockedrange(size.(A.args,2)))
103103

104104
==(A::HvcatBasis, B::HvcatBasis) = all(A.args .== B.args)
105105

106106
function QuasiArrays._getindex(::Type{IND}, A::HvcatBasis{T}, (x,j)::IND) where {T,IND}
107107
Jj = findblockindex(axes(A,2), j)
108108
J = Int(block(Jj))
109109
hvcat(A.n, zeros(J-1)..., A.args[J][x, blockindex(Jj)], zeros(length(A.args)-J)...)::T
110-
end
110+
end

src/operators.jl

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -67,9 +67,12 @@ end
6767

6868
DiracDelta{T}(x, axis::A) where {T,A<:AbstractQuasiVector} = DiracDelta{T,A}(x, axis)
6969
DiracDelta{T}(x, domain) where T = DiracDelta{T}(x, Inclusion(domain))
70-
DiracDelta(x, domain) = DiracDelta{eltype(x)}(x, Inclusion(domain))
70+
DiracDelta(x, domain) = DiracDelta{float(eltype(x))}(x, Inclusion(domain))
7171
DiracDelta(axis::AbstractQuasiVector) = DiracDelta(zero(float(eltype(axis))), axis)
72-
DiracDelta(domain) = DiracDelta(Inclusion(domain))
72+
DiracDelta(x) = DiracDelta(x, Inclusion(x))
73+
DiracDelta{T}() where T = DiracDelta(zero(T))
74+
DiracDelta() = DiracDelta{Float64}()
75+
7376

7477
axes::DiracDelta) =.axis,)
7578
IndexStyle(::Type{<:DiracDelta}) = IndexLinear()
@@ -78,7 +81,7 @@ IndexStyle(::Type{<:DiracDelta}) = IndexLinear()
7881

7982
function getindex::DiracDelta{T}, x::Number) where T
8083
x δ.axis || throw(BoundsError())
81-
x == δ.x ? inv(zero(T)) : zero(T)
84+
convert(T, x == δ.x ? inv(zero(T)) : zero(T))::T
8285
end
8386

8487

@@ -111,6 +114,12 @@ end
111114

112115
^(D::Derivative, k::Integer) = ApplyQuasiArray(^, D, k)
113116

117+
118+
function view(D::Derivative, kr::Inclusion, jr::Inclusion)
119+
@boundscheck axes(D,1) == kr == jr || throw(BoundsError(D,(kr,jr)))
120+
D
121+
end
122+
114123
# struct Multiplication{T,F,A} <: AbstractQuasiMatrix{T}
115124
# f::F
116125
# axis::A

test/runtests.jl

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,16 @@ end
3131
include("test_maps.jl")
3232

3333
@testset "DiracDelta" begin
34-
δ = DiracDelta(-1..3)
34+
δ = DiracDelta()
35+
@test δ == DiracDelta(0, Inclusion(0))
36+
@test axes(δ) (axes(δ,1),) (Inclusion(0.0),)
37+
@test size(δ) (length(δ),) (1,)
38+
@test_throws BoundsError δ[1.1]
39+
@test δ[0.0] Inf
40+
@test Base.IndexStyle(δ) Base.IndexLinear()
41+
42+
δ = DiracDelta(0, -1..3)
43+
@test δ == DiracDelta{Float64}(0, -1..3)
3544
@test axes(δ) (axes(δ,1),) (Inclusion(-1..3),)
3645
@test size(δ) (length(δ),) (ℵ₁,)
3746
@test δ[1.1] 0.0
@@ -203,6 +212,33 @@ end
203212
@test length(fp.args) == 2
204213
@test fp[1.1] 1
205214
@test fp[2.2] 2
215+
216+
217+
@testset "View derivatives" begin
218+
L = LinearSpline(1:5)
219+
H = HeavisideSpline(1:5)
220+
x = axes(L,1)
221+
D = Derivative(x)
222+
223+
@test view(D, x, x) D
224+
@test_throws BoundsError view(D, Inclusion(0..1), x)
225+
jr = [1,3,4]
226+
@test H \ (D*L[:,jr]) == H\(L[:,jr]'D')' == (H \ (D*L))[:,jr]
227+
228+
@test D*L[:,jr]*[1,2,3] == D * L * [1,0,2,3,0]
229+
@test L[:,jr]'D'D*L[:,jr] == (L'D'D*L)[jr,jr]
230+
231+
a = affine(0..1, 1..5)
232+
= Derivative(axes(a,1))
233+
@test H[a,:] \ (D̃ * L[a,:]) == H[a,:] \ (L[a,:]'')' == 4*(H\(D*L))
234+
@test_throws DimensionMismatch D * L[a,:]
235+
@test_throws DimensionMismatch D̃ * L[:,jr]
236+
237+
@test ContinuumArrays.simplifiable(*, D, L[:,jr]) isa Val{true}
238+
@test ContinuumArrays.simplifiable(*, L[:,jr]', D') isa Val{true}
239+
@test ContinuumArrays.simplifiable(*, D̃, L[a,jr]) isa Val{true}
240+
@test ContinuumArrays.simplifiable(*, L[a,jr]', D̃') isa Val{true}
241+
end
206242
end
207243

208244
@testset "Weak Laplacian" begin

0 commit comments

Comments
 (0)