Skip to content

Commit 3b48840

Browse files
authored
Merge pull request #9 from JuliaApproximation/dl/collocation
Support LazyArrays v0.6
2 parents 3cc0434 + e647465 commit 3b48840

File tree

13 files changed

+383
-203
lines changed

13 files changed

+383
-203
lines changed

examples/collocation.jl

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
using ContinuumArrays, FillArrays, InfiniteArrays
2+
import ContinuumArrays.QuasiArrays: Inclusion, QuasiDiagonal
3+
4+
P = Legendre()
5+
X = QuasiDiagonal(Inclusion(-1..1))
6+
7+
@test X[-1:0.1:1,-1:0.1:1] == Diagonal(-1:0.1:1)
8+
9+
axes(X)
10+
J = pinv(P)*X*P
11+
12+
J - I
13+
Vcat(Hcat(1, Zeros(1,∞)), J)

src/ContinuumArrays.jl

Lines changed: 7 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,15 @@ using IntervalSets, LinearAlgebra, LazyArrays, BandedMatrices, InfiniteArrays, D
33
import Base: @_inline_meta, axes, getindex, convert, prod, *, /, \, +, -,
44
IndexStyle, IndexLinear, ==, OneTo, tail
55
import Base.Broadcast: materialize
6-
import LazyArrays: Mul2, MemoryLayout
6+
import LazyArrays: Mul2, MemoryLayout, Applied
77
import LinearAlgebra: pinv
88
import BandedMatrices: AbstractBandedLayout, _BandedMatrix
99

1010
include("QuasiArrays/QuasiArrays.jl")
1111
using .QuasiArrays
12-
import .QuasiArrays: cardinality, checkindex, QuasiAdjoint, QuasiTranspose, slice, QSlice, SubQuasiArray,
12+
import .QuasiArrays: cardinality, checkindex, QuasiAdjoint, QuasiTranspose, slice, Inclusion, SubQuasiArray,
1313
QuasiDiagonal, MulQuasiArray, MulQuasiMatrix, MulQuasiVector, QuasiMatMulMat,
14-
_PInvQuasiMatrix
14+
ApplyQuasiArray, ApplyQuasiMatrix
1515

1616
export Spline, LinearSpline, HeavisideSpline, DiracDelta, Derivative, JacobiWeight, Jacobi, Legendre,
1717
fullmaterialize
@@ -24,12 +24,14 @@ struct AlephInfinity{N} <: Integer end
2424
const ℵ₁ = AlephInfinity{1}()
2525

2626

27+
const QMul2{A,B} = Mul{<:Any, <:Tuple{A,B}}
28+
2729
cardinality(::AbstractInterval) = ℵ₁
2830
*(ℵ::AlephInfinity) =
2931

3032

3133
checkindex(::Type{Bool}, inds::AbstractInterval, i::Real) = (leftendpoint(inds) <= i) & (i <= rightendpoint(inds))
32-
checkindex(::Type{Bool}, inds::AbstractInterval, i::QSlice) = i.axis inds
34+
checkindex(::Type{Bool}, inds::AbstractInterval, i::Inclusion) = i.axis inds
3335
function checkindex(::Type{Bool}, inds::AbstractInterval, I::AbstractArray)
3436
@_inline_meta
3537
b = true
@@ -41,7 +43,7 @@ end
4143

4244

4345
# we represent as a Mul with a banded matrix
44-
function materialize(V::SubQuasiArray{<:Any,2,<:Any,<:Tuple{<:QSlice,<:AbstractUnitRange}})
46+
function materialize(V::SubQuasiArray{<:Any,2,<:Any,<:Tuple{<:Inclusion,<:AbstractUnitRange}})
4547
A = parent(V)
4648
_,jr = parentindices(V)
4749
first(jr) 1 || throw(BoundsError())
@@ -51,42 +53,6 @@ end
5153

5254

5355

54-
55-
most(a) = reverse(tail(reverse(a)))
56-
57-
MulQuasiOrArray = Union{MulArray,MulQuasiArray}
58-
59-
_factors(M::MulQuasiOrArray) = M.mul.factors
60-
_factors(M) = (M,)
61-
62-
function fullmaterialize(M::MulQuasiOrArray)
63-
M_mat = materialize(M.mul)
64-
typeof(M_mat) <: MulQuasiOrArray || return M_mat
65-
typeof(M_mat) == typeof(M) || return(fullmaterialize(M_mat))
66-
67-
ABC = M_mat.mul.factors
68-
length(ABC) 2 && return M_mat
69-
70-
AB = most(ABC)
71-
Mhead = fullmaterialize(Mul(AB...))
72-
73-
typeof(_factors(Mhead)) == typeof(AB) ||
74-
return fullmaterialize(Mul(_factors(Mhead)..., last(ABC)))
75-
76-
BC = tail(ABC)
77-
Mtail = fullmaterialize(Mul(BC...))
78-
typeof(_factors(Mtail)) == typeof(BC) ||
79-
return fullmaterialize(Mul(first(ABC), _factors(Mtail)...))
80-
81-
first(ABC) * Mtail
82-
end
83-
84-
fullmaterialize(M::Mul) = fullmaterialize(materialize(M))
85-
fullmaterialize(M) = M
86-
87-
materialize(M::Mul{<:Tuple,<:Tuple{Vararg{<:Union{Adjoint,QuasiAdjoint,QuasiDiagonal}}}}) =
88-
materialize(Mul(reverse(adjoint.(M.factors))))'
89-
9056
include("operators.jl")
9157
include("bases/bases.jl")
9258

src/QuasiArrays/QuasiArrays.jl

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@ module QuasiArrays
22
using Base, LinearAlgebra, LazyArrays
33
import Base: getindex, size, axes, length, ==, isequal, iterate, CartesianIndices, LinearIndices,
44
Indices, IndexStyle, getindex, setindex!, parent, vec, convert, similar, zero,
5-
map, eachindex, eltype, first, last, firstindex, lastindex
5+
map, eachindex, eltype, first, last, firstindex, lastindex, in
66
import Base: @_inline_meta, DimOrInd, OneTo, @_propagate_inbounds_meta, @_noinline_meta,
7-
DimsInteger, error_if_canonical_getindex, @propagate_inbounds, _return_type, _default_type,
7+
DimsInteger, error_if_canonical_getindex, @propagate_inbounds, _return_type,
88
_maybetail, tail, _getindex, _maybe_reshape, index_ndims, _unsafe_getindex,
99
index_shape, to_shape, unsafe_length, @nloops, @ncall, Slice, unalias
1010
import Base: ViewIndex, Slice, ScalarIndex, RangeIndex, view, viewindexing, ensure_indexable, index_dimsum,
@@ -21,10 +21,11 @@ import Base: Array, Matrix, Vector
2121
import Base.Broadcast: materialize
2222

2323
import LinearAlgebra: transpose, adjoint, checkeltype_adjoint, checkeltype_transpose, Diagonal,
24-
AbstractTriangular
24+
AbstractTriangular, pinv, inv
2525

26-
import LazyArrays: MemoryLayout, UnknownLayout, Mul2, _materialize, MulLayout, , rmaterialize,
27-
_rmaterialize, _lmaterialize, flatten, _flatten, AbstractPInv
26+
import LazyArrays: MemoryLayout, UnknownLayout, Mul2, _materialize, MulLayout, ,
27+
_lmaterialize, InvOrPInv, ApplyStyle,
28+
LayoutApplyStyle, Applied
2829

2930
export AbstractQuasiArray, AbstractQuasiMatrix, AbstractQuasiVector, materialize
3031

@@ -49,4 +50,8 @@ include("abstractquasiarraymath.jl")
4950
include("quasiadjtrans.jl")
5051
include("quasidiagonal.jl")
5152

53+
54+
materialize(M::Applied{<:Any,typeof(*),<:Tuple{Vararg{<:Union{Adjoint,QuasiAdjoint,QuasiDiagonal}}}}) =
55+
materialize(Mul(reverse(adjoint.(M.args))...))'
56+
5257
end

src/QuasiArrays/indices.jl

Lines changed: 45 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -148,32 +148,51 @@ LinearIndices(A::AbstractQuasiArray) = LinearIndices(axes(A))
148148

149149

150150
"""
151-
QSlice(indices)
151+
Inclusion(domain)
152152
153-
Represent an axis as a quasi-vector that returns itself.
153+
Represents the inclusion operator of a domain (that is, a type that overrides in)
154+
as an AbstractQuasiVector. That is, if `v = Inclusion(domain)`, then
155+
`v[x] == x` if `x in domain`, otherwise it throws a `DomainError`.
156+
157+
Inclusions are useful for turning domains into axes. They also serve the same
158+
role as `Slice` does for offset arrays.
154159
"""
155-
struct QSlice{T,AX} <: AbstractQuasiVector{T}
156-
axis::AX
160+
struct Inclusion{T,AX} <: AbstractQuasiVector{T}
161+
domain::AX
162+
end
163+
Inclusion(domain) = Inclusion{eltype(domain),typeof(domain)}(domain)
164+
Inclusion(S::Inclusion) = S
165+
==(A::Inclusion, B::Inclusion) = A.domain == B.domain
166+
axes(S::Inclusion) = (S,)
167+
unsafe_indices(S::Inclusion) = (S,)
168+
axes1(S::Inclusion) = S
169+
axes(S::Inclusion{<:Any,<:OneTo}) = (S.domain,)
170+
unsafe_indices(S::Inclusion{<:Any,<:OneTo}) = (S.domain,)
171+
axes1(S::Inclusion{<:Any,<:OneTo}) = S.domain
172+
173+
first(S::Inclusion) = first(S.domain)
174+
last(S::Inclusion) = last(S.domain)
175+
size(S::Inclusion) = (length(S.domain),)
176+
length(S::Inclusion) = length(S.domain)
177+
unsafe_length(S::Inclusion) = unsafe_length(S.domain)
178+
cardinality(S::Inclusion) = cardinality(S.domain)
179+
getindex(S::Inclusion{T}, i::Real) where T =
180+
(@_inline_meta; @boundscheck checkbounds(S, i); convert(T,i))
181+
getindex(S::Inclusion{T}, i::AbstractVector{<:Real}) where T =
182+
(@_inline_meta; @boundscheck checkbounds(S, i); convert(AbstractVector{T},i))
183+
show(io::IO, r::Inclusion) = print(io, "Inclusion(", r.domain, ")")
184+
iterate(S::Inclusion, s...) = iterate(S.domain, s...)
185+
186+
in(x, S::Inclusion) = x in S.domain
187+
188+
checkindex(::Type{Bool}, inds::Inclusion, i::Real) = i inds.domain
189+
checkindex(::Type{Bool}, inds::Inclusion, ::Colon) = true
190+
checkindex(::Type{Bool}, inds::Inclusion, ::Inclusion) = true
191+
function checkindex(::Type{Bool}, inds::Inclusion, I::AbstractArray)
192+
@_inline_meta
193+
b = true
194+
for i in I
195+
b &= checkindex(Bool, inds, i)
196+
end
197+
b
157198
end
158-
QSlice(axis) = QSlice{eltype(axis),typeof(axis)}(axis)
159-
QSlice(S::QSlice) = S
160-
==(A::QSlice, B::QSlice) = A.axis == B.axis
161-
axes(S::QSlice) = (S,)
162-
unsafe_indices(S::QSlice) = (S,)
163-
axes1(S::QSlice) = S
164-
axes(S::QSlice{<:OneTo}) = (S.axis,)
165-
unsafe_indices(S::QSlice{<:OneTo}) = (S.axis,)
166-
axes1(S::QSlice{<:OneTo}) = S.axis
167-
168-
first(S::QSlice) = first(S.axis)
169-
last(S::QSlice) = last(S.axis)
170-
size(S::QSlice) = (length(S.axis),)
171-
length(S::QSlice) = length(S.axis)
172-
unsafe_length(S::QSlice) = unsafe_length(S.axis)
173-
cardinality(S::QSlice) = cardinality(S.axis)
174-
getindex(S::QSlice, i::Real) = (@_inline_meta; @boundscheck checkbounds(S, i); i)
175-
getindex(S::QSlice, i::AbstractVector{<:Real}) = (@_inline_meta; @boundscheck checkbounds(S, i); i)
176-
show(io::IO, r::QSlice) = print(io, "QSlice(", r.axis, ")")
177-
iterate(S::QSlice, s...) = iterate(S.axis, s...)
178-
179-
checkindex(::Type{Bool}, inds::QSlice, i::Real) = i inds.axis

0 commit comments

Comments
 (0)