81
81
const VectorInterlaceOperator = InterlaceOperator{T,1 ,DS,RS} where {T,DS,RS<: Space{D,R} } where {D,R<: AbstractVector }
82
82
const MatrixInterlaceOperator = InterlaceOperator{T,2 ,DS,RS} where {T,DS,RS<: Space{D,R} } where {D,R<: AbstractVector }
83
83
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
84
112
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 )
87
115
p= size (ops,1 )
88
116
dsi = interlacer (ds)
89
117
rsi = interlacer (rs)
90
118
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
92
120
all (i-> isa (i,AbstractFill) && getindex_value (i) == 1 , dsi. blocks) &&
93
121
all (i-> isa (i,AbstractFill) && getindex_value (i) == 1 , rsi. blocks)
94
122
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)
102
124
elseif p == 1 && size (ops,2 ) == 2 && size (ops[1 ],2 ) == 1
103
125
# special case for example
104
126
l,u = max (bandwidth (ops[1 ],1 ),bandwidth (ops[2 ],1 )- 1 ),bandwidth (ops[2 ],2 )+ 1
105
127
else
106
128
l,u = (1 - dimension (rs),dimension (ds)- 1 ) # not banded
107
129
end
108
130
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
+
109
141
MT = Matrix{Operator{promote_eltypeof (ops)}}
110
142
opsm = strictconvert (MT, ops)
111
143
InterlaceOperator (opsm,ds,rs,
112
144
cache (dsi),
113
145
cache (rsi),
114
- (l,u) )
146
+ bandwidths )
115
147
end
116
148
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))
120
150
p= size (ops,1 )
121
- if all (isbanded,ops)
151
+ ax1 = first (axes (ops))
152
+ if allbanded
122
153
l,u = 0 ,0
123
154
# 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)
129
159
end
130
160
else
131
161
l,u = (1 - dimension (rs),dimension (ds)- 1 ) # not banded
132
162
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))
133
169
134
170
VT = Vector{Operator{promote_eltypeof (ops)}}
135
171
opsv = strictconvert (VT, convert_vector (ops))
136
172
InterlaceOperator (opsv,ds,rs,
137
173
cache (BlockInterlacer (tuple (blocklengths (ds)))),
138
174
cache (interlacer (rs)),
139
- (l,u) )
175
+ bandwidths )
140
176
end
141
177
142
178
interlace_domainspace (ops:: AbstractMatrix , :: Type{NoSpace} ) = domainspace (ops)
@@ -148,7 +184,7 @@ interlace_rangespace(ops::RowVector, ::Type{RS}) where {RS} = RS(rangespace(ops[
148
184
149
185
function InterlaceOperator (opsin:: AbstractMatrix{<:Operator} ,
150
186
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 " ))
152
188
ops= promotespaces (opsin)
153
189
InterlaceOperator (ops, interlace_domainspace (ops, DS), interlace_rangespace (ops, RS))
154
190
end
0 commit comments