Skip to content

Commit ee84487

Browse files
authored
separate function for interlace operator bandwidth (#407)
* separate function for interlace operator bandwidth * constant propagation in interlace_bandwidths * forward operator bandwidths * inline InterlaceOperator_Diagonal * Multiplication SumSpace * version bump to v0.8.6
1 parent 6d044d1 commit ee84487

File tree

4 files changed

+74
-30
lines changed

4 files changed

+74
-30
lines changed

Project.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
name = "ApproxFunBase"
22
uuid = "fbd15aa5-315a-5a7d-a8a4-24992e37be05"
3-
version = "0.8.5"
3+
version = "0.8.6"
44

55
[deps]
66
AbstractFFTs = "621f4979-c628-5d54-868e-fcf4e3e8185c"

src/Operators/general/InterlaceOperator.jl

Lines changed: 58 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -81,62 +81,98 @@ end
8181
const VectorInterlaceOperator = InterlaceOperator{T,1,DS,RS} where {T,DS,RS<:Space{D,R}} where {D,R<:AbstractVector}
8282
const MatrixInterlaceOperator = InterlaceOperator{T,2,DS,RS} where {T,DS,RS<:Space{D,R}} where {D,R<:AbstractVector}
8383

84+
@static if VERSION >= v"1.8"
85+
Base.@constprop :aggressive interlace_bandwidths(args...) = _interlace_bandwidths(args...)
86+
else
87+
interlace_bandwidths(args...) = _interlace_bandwidths(args...)
88+
end
89+
90+
__interlace_ops_bandwidths(ops::AbstractMatrix) = bandwidths.(ops)
91+
__interlace_ops_bandwidths(ops::Diagonal) = bandwidths.(parent(ops))
92+
function __interlace_bandwidths_square(ops::AbstractMatrix, bw = __interlace_ops_bandwidths(ops))
93+
p=size(ops,1)
94+
l,u = 0,0
95+
for k=axes(ops,1), j=axes(ops,2)
96+
opbw = bw[k,j]
97+
l = max(l, p*opbw[1]+k-j)
98+
u = max(u, p*opbw[2]+j-k)
99+
end
100+
l,u
101+
end
102+
function __interlace_bandwidths_square(ops::Diagonal, bw = __interlace_ops_bandwidths(ops))
103+
p=size(ops,1)
104+
l,u = 0,0
105+
for k=axes(ops,1)
106+
opbw = bw[k]
107+
l = max(l, p*opbw[1])
108+
u = max(u, p*opbw[2])
109+
end
110+
l,u
111+
end
84112

85-
function InterlaceOperator(ops::AbstractMatrix{<:Operator},ds::Space,rs::Space)
86-
# calculate bandwidths TODO: generalize
113+
@inline function _interlace_bandwidths(ops::AbstractMatrix{<:Operator}, ds, rs,
114+
allbanded = all(isbanded,ops), bw = allbanded ? __interlace_ops_bandwidths(ops) : nothing)
87115
p=size(ops,1)
88116
dsi = interlacer(ds)
89117
rsi = interlacer(rs)
90118

91-
if size(ops,2) == p && all(isbanded,ops) &&# only support blocksize (1,) for now
119+
if size(ops,2) == p && allbanded && # only support blocksize (1,) for now
92120
all(i->isa(i,AbstractFill) && getindex_value(i) == 1, dsi.blocks) &&
93121
all(i->isa(i,AbstractFill) && getindex_value(i) == 1, rsi.blocks)
94122

95-
l,u = 0,0
96-
for k=1:p,j=1:p
97-
l=max(l,p*bandwidth(ops[k,j],1)+k-j)
98-
end
99-
for k=1:p,j=1:p
100-
u=max(u,p*bandwidth(ops[k,j],2)+j-k)
101-
end
123+
l,u = __interlace_bandwidths_square(ops, bw)
102124
elseif p == 1 && size(ops,2) == 2 && size(ops[1],2) == 1
103125
# special case for example
104126
l,u = max(bandwidth(ops[1],1),bandwidth(ops[2],1)-1),bandwidth(ops[2],2)+1
105127
else
106128
l,u = (1-dimension(rs),dimension(ds)-1) # not banded
107129
end
108130

131+
l,u
132+
end
133+
134+
function InterlaceOperator(ops::AbstractMatrix{<:Operator},ds::Space,rs::Space;
135+
# calculate bandwidths TODO: generalize
136+
bandwidths = interlace_bandwidths(ops, ds, rs))
137+
138+
dsi = interlacer(ds)
139+
rsi = interlacer(rs)
140+
109141
MT = Matrix{Operator{promote_eltypeof(ops)}}
110142
opsm = strictconvert(MT, ops)
111143
InterlaceOperator(opsm,ds,rs,
112144
cache(dsi),
113145
cache(rsi),
114-
(l,u))
146+
bandwidths)
115147
end
116148

117-
118-
function InterlaceOperator(ops::VectorOrTupleOfOp, ds::Space, rs::Space)
119-
# calculate bandwidths
149+
@inline function _interlace_bandwidths(ops::VectorOrTupleOfOp, ds, rs, allbanded = all(isbanded, ops))
120150
p=size(ops,1)
121-
if all(isbanded,ops)
151+
ax1 = first(axes(ops))
152+
if allbanded
122153
l,u = 0,0
123154
#TODO: this code assumes an interlace strategy that might not be right
124-
for k=1:p
125-
l=max(l,p*bandwidth(ops[k],1)+k-1)
126-
end
127-
for k=1:p
128-
u=max(u,p*bandwidth(ops[k],2)+1-k)
155+
for k in ax1
156+
opbw = bandwidths(ops[k])
157+
l = max(l, p*opbw[1]+k-1)
158+
u = max(u, p*opbw[2]+1-k)
129159
end
130160
else
131161
l,u = (1-dimension(rs),dimension(ds)-1) # not banded
132162
end
163+
l,u
164+
end
165+
166+
function InterlaceOperator(ops::VectorOrTupleOfOp, ds::Space, rs::Space;
167+
# calculate bandwidths
168+
bandwidths = interlace_bandwidths(ops, ds, rs))
133169

134170
VT = Vector{Operator{promote_eltypeof(ops)}}
135171
opsv = strictconvert(VT, convert_vector(ops))
136172
InterlaceOperator(opsv,ds,rs,
137173
cache(BlockInterlacer(tuple(blocklengths(ds)))),
138174
cache(interlacer(rs)),
139-
(l,u))
175+
bandwidths)
140176
end
141177

142178
interlace_domainspace(ops::AbstractMatrix, ::Type{NoSpace}) = domainspace(ops)
@@ -148,7 +184,7 @@ interlace_rangespace(ops::RowVector, ::Type{RS}) where {RS} = RS(rangespace(ops[
148184

149185
function InterlaceOperator(opsin::AbstractMatrix{<:Operator},
150186
ds::Type{DS}=NoSpace,rs::Type{RS}=ds) where {DS<:Space,RS<:Space}
151-
isempty(opsin) && throw(ArgumentError("Cannot create InterlaceOperator from empty Matrix"))
187+
isempty(opsin) && throw(ArgumentError("Cannot create InterlaceOperator from an empty matrix"))
152188
ops=promotespaces(opsin)
153189
InterlaceOperator(ops, interlace_domainspace(ops, DS), interlace_rangespace(ops, RS))
154190
end

src/Spaces/ProductSpaceOperators.jl

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -221,14 +221,24 @@ end
221221

222222
#TODO: do in @calculus_operator?
223223

224+
_spacename(::SumSpace) = SumSpace
225+
_spacename(::PiecewiseSpace) = PiecewiseSpace
226+
227+
@inline function InterlaceOperator_Diagonal(t, ds, rs = _spacename(ds)(map(rangespace, t)))
228+
allbanded = all(isbanded, t)
229+
opbw = map(bandwidths, t)
230+
D = Diagonal(convert_vector_or_svector(t))
231+
iopbw = interlace_bandwidths(D, ds, rs, allbanded, opbw)
232+
InterlaceOperator(D, ds, rs, bandwidths = iopbw)
233+
end
234+
224235
for (Op,OpWrap) in ((:Derivative,:DerivativeWrapper),(:Integral,:IntegralWrapper))
225236
_Op = Symbol(:_, Op)
226237
@eval begin
227238
@inline function $_Op(S::PiecewiseSpace, k::Number)
228239
assert_integer(k)
229240
t = map(s->$Op(s,k),components(S))
230-
D = Diagonal(convert_vector_or_svector(t))
231-
O = InterlaceOperator(D, PiecewiseSpace)
241+
O = InterlaceOperator_Diagonal(t, S)
232242
$OpWrap(O,k)
233243
end
234244
@inline function $_Op(S::ArraySpace, k::Number)
@@ -254,8 +264,7 @@ end
254264
# mixed bases.
255265
if typeof(canonicaldomain(S))==typeof(domain(S))
256266
t = map(s->Derivative(s,k),components(S))
257-
D = Diagonal(convert_vector_or_svector(t))
258-
O = InterlaceOperator(D, SumSpace)
267+
O = InterlaceOperator_Diagonal(t, S)
259268
DerivativeWrapper(O,k)
260269
else
261270
DefaultDerivative(S,k)
@@ -301,8 +310,7 @@ Multiplication(f::Fun{SumSpace{SV1,D,R1}},sp::SumSpace{SV2,D,R2}) where {SV1,SV2
301310

302311
function Multiplication(f::Fun, sp::SumSpace)
303312
t = map(s->Multiplication(f,s),components(sp))
304-
D = Diagonal(convert_vector_or_svector(t))
305-
O = InterlaceOperator(D, SumSpace)
313+
O = InterlaceOperator_Diagonal(t, sp)
306314
MultiplicationWrapper(f, O)
307315
end
308316

src/show.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ function show(io::IO,ss::PiecewiseSpace)
158158
end
159159
show(io,s[1])
160160
for sp in s[2:end]
161-
print(io,"")
161+
print(io,"")
162162
show(io,sp)
163163
end
164164
if length(s) == 1

0 commit comments

Comments
 (0)