Skip to content

Commit 31c8247

Browse files
committed
Add fullmaterialize
1 parent ff83d09 commit 31c8247

File tree

8 files changed

+136
-153
lines changed

8 files changed

+136
-153
lines changed

src/ContinuumArrays.jl

Lines changed: 43 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,20 @@
11
module ContinuumArrays
22
using IntervalSets, LinearAlgebra, LazyArrays, BandedMatrices, InfiniteArrays, DomainSets
33
import Base: @_inline_meta, axes, getindex, convert, prod, *, /, \, +, -,
4-
IndexStyle, IndexLinear, ==, OneTo
4+
IndexStyle, IndexLinear, ==, OneTo, tail
55
import Base.Broadcast: materialize
6-
import LazyArrays: Mul2
6+
import LazyArrays: Mul2, MemoryLayout
77
import LinearAlgebra: pinv
88
import BandedMatrices: AbstractBandedLayout, _BandedMatrix
99

1010
include("QuasiArrays/QuasiArrays.jl")
1111
using .QuasiArrays
1212
import .QuasiArrays: cardinality, checkindex, QuasiAdjoint, QuasiTranspose, slice, QSlice, SubQuasiArray,
13-
QuasiDiagonal, MulQuasiArray, MulQuasiMatrix, MulQuasiVector, QuasiMatMulMat
13+
QuasiDiagonal, MulQuasiArray, MulQuasiMatrix, MulQuasiVector, QuasiMatMulMat,
14+
_PInvQuasiMatrix
1415

15-
export Spline, LinearSpline, HeavisideSpline, DiracDelta, Derivative, JacobiWeight, Jacobi, Legendre
16+
export Spline, LinearSpline, HeavisideSpline, DiracDelta, Derivative, JacobiWeight, Jacobi, Legendre,
17+
fullmaterialize
1618

1719
####
1820
# Interval indexing support
@@ -48,6 +50,43 @@ function materialize(V::SubQuasiArray{<:Any,2,<:Any,<:Tuple{<:QSlice,<:AbstractU
4850
end
4951

5052

53+
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+
5190
include("operators.jl")
5291
include("bases/bases.jl")
5392

src/QuasiArrays/QuasiArrays.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ import LinearAlgebra: transpose, adjoint, checkeltype_adjoint, checkeltype_trans
2424
AbstractTriangular
2525

2626
import LazyArrays: MemoryLayout, UnknownLayout, Mul2, _materialize, MulLayout, , rmaterialize,
27-
_rmaterialize, _lmaterialize, flatten, _flatten
27+
_rmaterialize, _lmaterialize, flatten, _flatten, AbstractPInv
2828

2929
export AbstractQuasiArray, AbstractQuasiMatrix, AbstractQuasiVector, materialize
3030

src/QuasiArrays/matmul.jl

Lines changed: 32 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -35,15 +35,14 @@ end
3535
QuasiMatMulMat{styleA, styleB, T, V} = QuasiArrayMulArray{styleA, styleB, 2, 2, T, V}
3636
QuasiMatMulQuasiMat{styleA, styleB, T, V} = QuasiArrayMulQuasiArray{styleA, styleB, 2, 2, T, V}
3737

38-
*(A::AbstractQuasiArray, B::AbstractQuasiArray, C::AbstractQuasiArray, D::AbstractQuasiArray...) = materialize(Mul(A,B,C,D...))
39-
*(A::AbstractQuasiArray, B::AbstractQuasiArray) = materialize(Mul(A,B))
40-
*(A::AbstractQuasiArray, B::AbstractArray) = materialize(Mul(A,B))
41-
*(A::AbstractArray, B::AbstractQuasiArray) = materialize(Mul(A,B))
38+
*(A::AbstractQuasiArray, B...) = materialize(Mul(A,B...))
39+
*(A::AbstractQuasiArray, B::AbstractQuasiArray, C...) = materialize(Mul(A,B,C...))
40+
*(A::AbstractArray, B::AbstractQuasiArray, C...) = materialize(Mul(A,B,C...))
4241
pinv(A::AbstractQuasiArray) = materialize(PInv(A))
4342
inv(A::AbstractQuasiArray) = materialize(Inv(A))
4443

45-
*(A::AbstractQuasiArray, B::Mul) = materialize(Mul(A, B.factors...))
46-
*(A::Mul, B::AbstractQuasiArray) = materialize(Mul(A.factors..., B))
44+
*(A::AbstractQuasiArray, B::Mul, C...) = materialize(Mul(A, B.factors..., C...))
45+
*(A::Mul, B::AbstractQuasiArray, C...) = materialize(Mul(A.factors..., B, C...))
4746

4847

4948
####
@@ -99,6 +98,31 @@ transpose(A::MulQuasiArray) = MulQuasiArray(reverse(transpose.(A.mul.factors))..
9998
MemoryLayout(M::MulQuasiArray) = MulLayout(MemoryLayout.(M.mul.factors))
10099

101100

101+
## PInvQuasiMatrix
102+
103+
function _PInvQuasiMatrix end
104+
105+
struct PInvQuasiMatrix{T, PINV<:AbstractPInv} <: AbstractQuasiMatrix{T}
106+
pinv::PINV
107+
global _PInvQuasiMatrix(pinv::PINV) where PINV = new{eltype(pinv), PINV}(pinv)
108+
end
109+
110+
const InvQuasiMatrix{T, INV<:Inv} = PInvQuasiMatrix{T,INV}
111+
112+
PInvQuasiMatrix(M) = _PInvQuasiMatrix(PInv(M))
113+
InvQuasiMatrix(M) = _PInvQuasiMatrix(Inv(M))
114+
115+
axes(A::PInvQuasiMatrix) = axes(A.pinv)
116+
size(A::PInvQuasiMatrix) = map(length, axes(A))
117+
118+
@propagate_inbounds getindex(A::PInvQuasiMatrix{T}, k::Int, j::Int) where T =
119+
(A.pinv*[Zeros(j-1); one(T); Zeros(size(A,2) - j)])[k]
120+
121+
MemoryLayout(M::PInvQuasiMatrix) = MemoryLayout(M.pinv)
122+
123+
*(A::PInvQuasiMatrix, B::AbstractQuasiMatrix, C...) = *(A.pinv, B, C...)
124+
*(A::PInvQuasiMatrix, B::MulQuasiArray, C...) = *(A.pinv, B.mul, C...)
125+
102126

103127
####
104128
# Matrix * Array
@@ -130,7 +154,7 @@ end
130154

131155
function _materialize(M::Mul2{<:Any,<:Any,<:MulQuasiArray,<:AbstractQuasiArray}, _)
132156
As, B = M.factors
133-
(As.mul.factors..., B)
157+
rmaterialize(Mul(As.mul.factors..., B))
134158
end
135159

136160
function _materialize(M::Mul2{<:Any,<:Any,<:AbstractQuasiArray,<:MulQuasiArray}, _)
@@ -141,7 +165,7 @@ end
141165
# A MulQuasiArray can't be materialized further left-to-right, so we do right-to-left
142166
function _materialize(M::Mul2{<:Any,<:Any,<:MulQuasiArray,<:AbstractArray}, _)
143167
As, B = M.factors
144-
(As.mul.factors..., B)
168+
rmaterialize(Mul(As.mul.factors..., B))
145169
end
146170

147171
function _lmaterialize(A::MulQuasiArray, B, C...)

src/bases/bases.jl

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,21 @@
1+
abstract type Basis{T} <: AbstractQuasiMatrix{T} end
2+
struct BasisLayout <: MemoryLayout end
3+
4+
MemoryLayout(::Basis) = BasisLayout()
5+
6+
pinv(J::Basis) = materialize(PInv(J))
7+
materialize(P::PInv{BasisLayout}) = _PInvQuasiMatrix(P)
8+
9+
==(A::Basis, B::Basis) = axes(A)  axes(B) ||
10+
throw(ArgumentError("Override == to compare bases of type $(typeof(A)) and $(typeof(B))"))
11+
12+
function materialize(P::Ldiv{BasisLayout,BasisLayout})
13+
Ai, B = P.factors
14+
A = parent(Ai)
15+
axes(A) == axes(B) || throw(DimensionMismatch("axes of bases must match"))
16+
A == B || throw(ArgumentError("Override materialize for $(typeof(A)) \\ $(typeof(B))"))
17+
Eye(size(A,2))
18+
end
19+
120
include("splines.jl")
221
include("jacobi.jl")

src/bases/jacobi.jl

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,13 @@ function getindex(w::JacobiWeight, x::Real)
99
(1-x)^w.a * (1+x)^w.b
1010
end
1111

12-
abstract type AbstractJacobi{T} <: AbstractQuasiMatrix{T} end
13-
14-
pinv(J::AbstractJacobi) = PInv(J)
12+
abstract type AbstractJacobi{T} <: Basis{T} end
1513

1614
struct Legendre{T} <: AbstractJacobi{T} end
1715
Legendre() = Legendre{Float64}()
1816

17+
==(::Legendre, ::Legendre) = true
18+
1919
struct Jacobi{T} <: AbstractJacobi{T}
2020
b::T
2121
a::T

src/bases/splines.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11

2-
struct Spline{order,T} <: AbstractQuasiMatrix{T}
2+
struct Spline{order,T} <: Basis{T}
33
points::Vector{T}
44
end
55

src/operators.jl

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,3 +48,7 @@ function materialize(M::Mul2{<:Any,<:Any,<:Derivative,<:SubQuasiArray})
4848
P = parent(B)
4949
(Derivative(axes(P,1))*P)[parentindices(B)...]
5050
end
51+
52+
53+
materialize(M::Mul2{<:Any,<:Any,<:Derivative}) = MulQuasiArray(M)
54+
materialize(M::Mul2{<:Any,<:Any,<:Any,<:Derivative}) = MulQuasiArray(M)

0 commit comments

Comments
 (0)