Skip to content

Commit 7f1c579

Browse files
committed
Refinements
1 parent 7dd9ef0 commit 7f1c579

File tree

5 files changed

+244
-4
lines changed

5 files changed

+244
-4
lines changed

src/ApproxFunBase.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ module ApproxFunBase
44
using Base, BlockArrays, BandedMatrices, BlockBandedMatrices, DomainSets, IntervalSets,
55
SpecialFunctions, AbstractFFTs, FFTW, SpecialFunctions, DSP, DualNumbers, FastTransforms,
66
LinearAlgebra, SparseArrays, LowRankApprox, FillArrays, InfiniteArrays #, Arpack
7-
import StaticArrays
7+
import StaticArrays, Calculus
88

99
import DomainSets: Domain, indomain, UnionDomain, ProductDomain, FullSpace, Point, elements, DifferenceDomain,
1010
Interval, ChebyshevInterval, boundary, ∂, rightendpoint, leftendpoint,

src/Fun.jl

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,10 @@ end
2020
const VFun{S,T} = Fun{S,T,Vector{T}}
2121

2222
Fun(sp::Space,coeff::AbstractVector) = Fun{typeof(sp),eltype(coeff),typeof(coeff)}(sp,coeff)
23+
Fun() = Fun(identity)
24+
Fun(d::Domain) = Fun(identity,d)
25+
Fun(d::Space) = Fun(identity,d)
26+
2327

2428
function Fun(sp::Space,v::AbstractVector{Any})
2529
if isempty(v)

src/Operators/Operator.jl

Lines changed: 64 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -486,11 +486,11 @@ macro wrappergetindex(Wrap)
486486
BLAS.axpy!(α,P::ApproxFunBase.SubOperator{T,OP},A::AbstractMatrix) where {T,OP<:$Wrap} =
487487
ApproxFunBase.unwrap_axpy!(α,P,A)
488488

489-
ApproxFunBase.mul_coefficients(A::$Wrap,b) = mul_coefficients(A.op,b)
489+
ApproxFunBase.mul_coefficients(A::$Wrap,b) = ApproxFunBase.mul_coefficients(A.op,b)
490490
ApproxFunBase.mul_coefficients(A::ApproxFunBase.SubOperator{T,OP,Tuple{UnitRange{Int},UnitRange{Int}}},b) where {T,OP<:$Wrap} =
491-
mul_coefficients(view(parent(A).op,S.indexes[1],S.indexes[2]),b)
491+
ApproxFunBase.mul_coefficients(view(parent(A).op,S.indexes[1],S.indexes[2]),b)
492492
ApproxFunBase.mul_coefficients(A::ApproxFunBase.SubOperator{T,OP},b) where {T,OP<:$Wrap} =
493-
mul_coefficients(view(parent(A).op,S.indexes[1],S.indexes[2]),b)
493+
ApproxFunBase.mul_coefficients(view(parent(A).op,S.indexes[1],S.indexes[2]),b)
494494
end
495495

496496
for TYP in (:(BandedMatrices.BandedMatrix),:(ApproxFunBase.RaggedMatrix),
@@ -779,3 +779,64 @@ end
779779

780780
AbstractMatrix(V::Operator) = arraytype(V)(V)
781781
AbstractVector(S::Operator) = Vector(S)
782+
783+
784+
785+
786+
# default copy is to loop through
787+
# override this for most operators.
788+
function default_BandedMatrix(S::Operator)
789+
Y=BandedMatrix{eltype(S)}(undef, size(S), bandwidths(S))
790+
791+
for j=1:size(S,2),k=colrange(Y,j)
792+
@inbounds inbands_setindex!(Y,S[k,j],k,j)
793+
end
794+
795+
Y
796+
end
797+
798+
799+
# default copy is to loop through
800+
# override this for most operators.
801+
function default_RaggedMatrix(S::Operator)
802+
data=Array{eltype(S)}(undef, 0)
803+
cols=Array{Int}(undef, size(S,2)+1)
804+
cols[1]=1
805+
for j=1:size(S,2)
806+
cs=colstop(S,j)
807+
K=cols[j]-1
808+
cols[j+1]=cs+cols[j]
809+
resize!(data,cols[j+1]-1)
810+
811+
for k=1:cs
812+
data[K+k]=S[k,j]
813+
end
814+
end
815+
816+
RaggedMatrix(data,cols,size(S,1))
817+
end
818+
819+
function default_Matrix(S::Operator)
820+
n, m = size(S)
821+
if isinf(n) || isinf(m)
822+
error("Cannot convert $S to a Matrix")
823+
end
824+
825+
eltype(S)[S[k,j] for k=1:n, j=1:m]
826+
end
827+
828+
829+
830+
831+
# The diagonal of the operator may not be the diagonal of the sub
832+
# banded matrix, so the following calculates the row of the
833+
# Banded matrix corresponding to the diagonal of the original operator
834+
835+
836+
diagindshift(S,kr,jr) = first(kr)-first(jr)
837+
diagindshift(S::SubOperator) = diagindshift(S,parentindices(S)[1],parentindices(S)[2])
838+
839+
840+
#TODO: Remove
841+
diagindrow(S,kr,jr) = bandwidth(S,2)+first(jr)-first(kr)+1
842+
diagindrow(S::SubOperator) = diagindrow(S,parentindices(S)[1],parentindices(S)[2])

src/Operators/banded/ToeplitzOperator.jl

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,3 +170,112 @@ function Fun(T::ToeplitzOperator)
170170
Fun(Laurent(Circle()),interlace(T.nonnegative,T.negative))
171171
end
172172
end
173+
174+
175+
176+
####
177+
# Toeplitz/Hankel
178+
####
179+
180+
181+
# αn,α0,αp give the constant for the negative, diagonal and positive
182+
# entries. The usual case is 1,2,1
183+
function toeplitz_axpy!(αn,α0,αp,neg,pos,kr,jr,ret)
184+
dat=ret.data
185+
m=size(dat,2)
186+
187+
dg=diagindrow(ret,kr,jr)
188+
189+
# diagonal
190+
if dg 1
191+
α0p=α0*pos[1]
192+
@simd for j=1:m
193+
@inbounds dat[dg,j]+=α0p
194+
end
195+
end
196+
197+
# positive entries
198+
for k=2:min(length(pos),dg)
199+
αpp=αp*pos[k]
200+
@simd for j=1:m
201+
@inbounds dat[dg-k+1,j]+=αpp
202+
end
203+
end
204+
205+
# negative entries
206+
for k=1:min(length(neg),size(dat,1)-dg)
207+
αnn=αn*neg[k]
208+
@simd for j=1:m
209+
@inbounds dat[dg+k,j]+=αnn
210+
end
211+
end
212+
213+
ret
214+
end
215+
216+
# this routine is for when we want a symmetric toeplitz
217+
function sym_toeplitz_axpy!(αn,α0,αp,cfs,kr,jr,ret)
218+
dg=diagindrow(ret,kr,jr)
219+
220+
dat=ret.data
221+
m=size(dat,2)
222+
# diagonal
223+
if dg 1
224+
α0p=α0*cfs[1]
225+
@simd for j=1:m
226+
@inbounds dat[dg,j]+=α0p
227+
end
228+
end
229+
230+
# positive entries
231+
for k=2:min(length(cfs),dg)
232+
αpp=αp*cfs[k]
233+
@simd for j=1:m
234+
@inbounds dat[dg-k+1,j]+=αpp
235+
end
236+
end
237+
238+
# negative entries
239+
for k=2:min(length(cfs),size(dat,1)-dg+1)
240+
αnn=αn*cfs[k]
241+
@simd for j=1:m
242+
@inbounds dat[dg+k-1,j]+=αnn
243+
end
244+
end
245+
246+
ret
247+
end
248+
249+
toeplitz_axpy!(α,neg,pos,kr,jr,ret) =
250+
toeplitz_axpy!(α,α,α,neg,pos,kr,jr,ret)
251+
252+
sym_toeplitz_axpy!(α0,αp,cfs,kr,jr,ret) =
253+
sym_toeplitz_axpy!(αp,α0,αp,cfs,kr,jr,ret)
254+
255+
256+
function hankel_axpy!(α,cfs,kr,jr,ret)
257+
dat=ret.data
258+
259+
st=stride(dat,2)-2
260+
mink=first(kr)+first(jr)-1
261+
262+
N=length(dat)
263+
264+
# dg gives the row corresponding to the diagonal of the original operator
265+
dg=diagindrow(ret,kr,jr)
266+
267+
# we need the entry where the first entry is written to
268+
# this is going to be a shift of the diagonal of the true operator
269+
dg1=dg+first(kr)-first(jr)
270+
271+
for k=mink:min(length(cfs),size(dat,1)+mink-dg1)
272+
dk=k-mink+dg1
273+
nk=k-mink
274+
αc=α*cfs[k]
275+
@simd for j=dk:st:min(dk+nk*st,N)
276+
@inbounds dat[j]+=αc
277+
end
278+
end
279+
280+
ret
281+
end

src/Spaces/ConstantSpace.jl

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -240,3 +240,69 @@ choosedomainspace(M::ConcreteMultiplication{D,UnsetSpace},sp::UnsetSpace) where
240240
choosedomainspace(M::ConcreteMultiplication{D,UnsetSpace},sp::Space) where {D<:ConstantSpace} = space(M.f)
241241

242242
Base.isfinite(f::Fun{CS}) where {CS<:ConstantSpace} = isfinite(Number(f))
243+
244+
245+
246+
247+
248+
## ConstantSpace and PointSpace default overrides
249+
250+
for SP in (:ConstantSpace,)
251+
for OP in (:abs,:sign,:exp,:sqrt,:angle)
252+
@eval begin
253+
$OP(z::Fun{<:$SP,<:Complex}) = Fun(space(z),$OP.(coefficients(z)))
254+
$OP(z::Fun{<:$SP,<:Real}) = Fun(space(z),$OP.(coefficients(z)))
255+
$OP(z::Fun{<:$SP}) = Fun(space(z),$OP.(coefficients(z)))
256+
end
257+
end
258+
259+
# we need to pad coefficients since 0^0 == 1
260+
for OP in (:^,)
261+
@eval begin
262+
function $OP(z::Fun{<:$SP},k::Integer)
263+
k  0 && return Fun(space(z),$OP.(coefficients(z),k))
264+
Fun(space(z),$OP.(pad(coefficients(z),dimension(space(z))),k))
265+
end
266+
function $OP(z::Fun{<:$SP},k::Number)
267+
k  0 && return Fun(space(z),$OP.(coefficients(z),k))
268+
Fun(space(z),$OP.(pad(coefficients(z),dimension(space(z))),k))
269+
end
270+
end
271+
end
272+
end
273+
274+
275+
for OP in (:(Base.max),:(Base.min))
276+
@eval begin
277+
$OP(a::Fun{CS1,T},b::Fun{CS2,V}) where {CS1<:ConstantSpace,CS2<:ConstantSpace,T<:Real,V<:Real} =
278+
Fun($OP(Number(a),Number(b)),space(a) space(b))
279+
$OP(a::Fun{CS,T},b::Real) where {CS<:ConstantSpace,T<:Real} =
280+
Fun($OP(Number(a),b),space(a))
281+
$OP(a::Real,b::Fun{CS,T}) where {CS<:ConstantSpace,T<:Real} =
282+
Fun($OP(a,Number(b)),space(b))
283+
end
284+
end
285+
286+
for OP in (:<,:(Base.isless),:(<=),:>,:(>=))
287+
@eval begin
288+
$OP(a::Fun{CS},b::Fun{CS}) where {CS<:ConstantSpace} = $OP(convert(Number,a),Number(b))
289+
$OP(a::Fun{CS},b::Number) where {CS<:ConstantSpace} = $OP(convert(Number,a),b)
290+
$OP(a::Number,b::Fun{CS}) where {CS<:ConstantSpace} = $OP(a,convert(Number,b))
291+
end
292+
end
293+
294+
# from DualNumbers
295+
for (funsym, exp) in Calculus.symbolic_derivatives_1arg()
296+
funsym == :abs && continue
297+
funsym == :sign && continue
298+
funsym == :exp && continue
299+
funsym == :sqrt && continue
300+
@eval begin
301+
$(funsym)(z::Fun{CS,T}) where {CS<:ConstantSpace,T<:Real} =
302+
Fun($(funsym)(Number(z)),space(z))
303+
$(funsym)(z::Fun{CS,T}) where {CS<:ConstantSpace,T<:Complex} =
304+
Fun($(funsym)(Number(z)),space(z))
305+
$(funsym)(z::Fun{CS}) where {CS<:ConstantSpace} =
306+
Fun($(funsym)(Number(z)),space(z))
307+
end
308+
end

0 commit comments

Comments
 (0)