Skip to content

Commit

Permalink
Add the struct F to represent anonymous functions for constructors (i…
Browse files Browse the repository at this point in the history
…n the REPL)

This is an implementation of @JeffBezanson ’s suggestion in
JuliaLang/julia#21113

Constructors are fast again.
  • Loading branch information
MikaelSlevinsky committed Mar 20, 2017
1 parent 02d9547 commit 6d0b0dc
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 23 deletions.
6 changes: 4 additions & 2 deletions src/Extras/hacks.jl
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,10 @@ end
# end
# end

function Fun(f::Function)
if hasnumargs(f,1)
Fun(f::Function) = Fun(F(f))

function Fun(f::F)
if hasnumargs(f.f,1)
# check for tuple
try
f(0)
Expand Down
18 changes: 15 additions & 3 deletions src/Fun/constructors.jl
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
struct F <: Function
f
end
(f::F)(args...) = f.f(args...)

valsdomain_type_promote{T<:Complex}(::Type{T},::Type{T})=T,T
valsdomain_type_promote{T<:Real}(::Type{T},::Type{T})=T,T
valsdomain_type_promote(::Type{Int},::Type{Int})=Float64,Int
Expand Down Expand Up @@ -83,16 +88,20 @@ Fun{T<:Space}(f::Fun,::Type{T}) = Fun(f,T(domain(f)))


Fun(f::AbstractVector,T::Type) = Fun(f,T())
Fun(T::Type,f::Function) = Fun(T,F(f))
Fun(T::Type,f::Type) = Fun(T(),f)
Fun(T::Type,f) = Fun(T(),f)
Fun(f::Function,T::Type) = Fun(F(f),T())
Fun(f,T::Type) = Fun(f,T())
Fun(f::Function,T::Type,n::Integer) = Fun(F(f),T(),n)
Fun(f,T::Type,n::Integer) = Fun(f,T(),n)

Fun(f::AbstractVector,d::Domain) = Fun(f,Space(d))
Fun{T<:Number}(d::Domain,f::AbstractVector{T}) = Fun(Space(d),f)
Fun(d::Domain,f::AbstractVector) = Fun(Space(d),f)


Fun(f::Function,d::Domain,n) = Fun(F(f),Space(d),n)
Fun(f,d::Domain,n) = Fun(f,Space(d),n)


Expand All @@ -105,6 +114,7 @@ Fun(c::Number,d::Space) = c==0?c*zeros(eltype(d),d):c*ones(eltype(d),d)
## List constructor

Fun{T<:Domain}(c::Number,dl::AbstractVector{T}) = Fun(c,UnionDomain(dl))
Fun{T<:Domain}(f::Function,dl::AbstractVector{T}) = Fun(F(f),UnionDomain(dl))
Fun{T<:Domain}(f::Type,dl::AbstractVector{T}) = Fun(f,UnionDomain(dl))
Fun{T<:Domain}(f::Domain,dl::AbstractVector{T}) = Fun(f,UnionDomain(dl))
Fun{T<:Domain}(f,dl::AbstractVector{T}) = Fun(f,UnionDomain(dl))
Expand Down Expand Up @@ -188,7 +198,8 @@ function abszerocfsFun(f,d::Space)
end

Fun(f::Type, d::Space; method="zerocoefficients") = error("Not impleemnted")
function Fun(f, d::Space; method="zerocoefficients")
Fun(f::Function, d::Space; method = "zerocoefficients") = Fun(F(f), d; method = method)
function Fun(f::F, d::Space; method="zerocoefficients")
T = eltype(domain(d))

if f==identity
Expand All @@ -210,8 +221,8 @@ function Fun(f, d::Space; method="zerocoefficients")
end
end
Fun(f::Type,d::Domain;opts...) = Fun(f,Space(d);opts...)
Fun(f,d::Domain;opts...) = Fun(f,Space(d);opts...)

Fun(f::F,d::Domain;opts...) = Fun(f,Space(d);opts...)
Fun(f::Function,d::Domain;opts...) = Fun(F(f),d;opts...)

# this supports expanding a Fun to a larger or smaller domain.
# we take the union and then intersection to get at any singularities
Expand All @@ -230,6 +241,7 @@ Fun(T::Type,n::Integer) = Fun(T(),n)
Fun(f,n::Integer) = Fun(f,Interval(),n)
Fun(f,d::ClosedInterval,n::Integer) = Fun(f,Domain(d),n)
Fun{M<:Number}(d::ClosedInterval,cfs::AbstractVector{M}) = Fun(Domain(d),1.0*cfs)
Fun(f::Function,d::ClosedInterval) = Fun(F(f),Domain(d))
Fun(f::Type,d::ClosedInterval) = Fun(f,Domain(d))
Fun(f,d::ClosedInterval) = Fun(f,Domain(d))
Fun(f::Number,d::ClosedInterval) = Fun(f,Domain(d))
Expand Down
22 changes: 12 additions & 10 deletions src/Multivariate/LowRankFun.jl
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ end

## Adaptive constructor selector

function LowRankFun(f::Function,dx::Space,dy::Space;method::Symbol=:standard,tolerance::Union{Symbol,Tuple{Symbol,Number}}=:relative,retmax::Bool=false,gridx::Integer=64,gridy::Integer=64,maxrank::Integer=100)
function LowRankFun(f::F,dx::Space,dy::Space;method::Symbol=:standard,tolerance::Union{Symbol,Tuple{Symbol,Number}}=:relative,retmax::Bool=false,gridx::Integer=64,gridy::Integer=64,maxrank::Integer=100)
if method == :standard
F,maxabsf=standardLowRankFun(f,dx,dy;tolerance=tolerance,gridx=gridx,gridy=gridy,maxrank=maxrank)
elseif method == :Cholesky
Expand All @@ -77,7 +77,7 @@ end

## Standard adaptive construction

function standardLowRankFun(f::Function,dx::Space,dy::Space;tolerance::Union{Symbol,Tuple{Symbol,Number}}=:relative,gridx::Integer=64,gridy::Integer=64,maxrank::Integer=100)
function standardLowRankFun(f::F,dx::Space,dy::Space;tolerance::Union{Symbol,Tuple{Symbol,Number}}=:relative,gridx::Integer=64,gridy::Integer=64,maxrank::Integer=100)
xy = checkpoints(dxdy)
T = promote_type(eltype(f(first(xy)...)),eltype(dx),eltype(domain(dx)),eltype(dy),eltype(domain(dy)))

Expand Down Expand Up @@ -131,7 +131,7 @@ end

## Adaptive Cholesky decomposition, when f is Hermitian positive (negative) definite

function CholeskyLowRankFun(f::Function,dx::Space;tolerance::Union{Symbol,Tuple{Symbol,Number}}=:relative,grid::Integer=64,maxrank::Integer=100)
function CholeskyLowRankFun(f::F,dx::Space;tolerance::Union{Symbol,Tuple{Symbol,Number}}=:relative,grid::Integer=64,maxrank::Integer=100)
xy = checkpoints(dxdx)
T = promote_type(eltype(f(first(xy)...)),eltype(dx),eltype(domain(dx)))

Expand Down Expand Up @@ -181,12 +181,14 @@ end

## Construction via TensorSpaces and ProductDomains

LowRankFun{SV,T,DD}(f::Function,S::TensorSpace{SV,T,DD,2};kwds...)=LowRankFun(f,S[1],S[2];kwds...)
LowRankFun(f::Function,dx::Domain,dy::Domain;kwds...)=LowRankFun(f,Space(dx),Space(dy);kwds...)
LowRankFun{D,T}(f::Function,d::ProductDomain{D,T,2};kwds...)=LowRankFun(f,d[1],d[2];kwds...)
LowRankFun(f::Function,args...;kwds...) = LowRankFun(F(f),args...;kwds...)

LowRankFun(f::Function,d1::Vector,d2::Vector;kwds...)=LowRankFun(f,convert(Domain,d1),convert(Domain,d2);kwds...)
LowRankFun(f::Function;kwds...)=LowRankFun(f,Interval(),Interval();kwds...)
LowRankFun{SV,T,DD}(f::F,S::TensorSpace{SV,T,DD,2};kwds...)=LowRankFun(f,S[1],S[2];kwds...)
LowRankFun(f::F,dx::Domain,dy::Domain;kwds...)=LowRankFun(f,Space(dx),Space(dy);kwds...)
LowRankFun{D,T}(f::F,d::ProductDomain{D,T,2};kwds...)=LowRankFun(f,d[1],d[2];kwds...)

LowRankFun(f::F,d1::Vector,d2::Vector;kwds...)=LowRankFun(f,convert(Domain,d1),convert(Domain,d2);kwds...)
LowRankFun(f::F;kwds...)=LowRankFun(f,Interval(),Interval();kwds...)

## Construction from values

Expand All @@ -202,7 +204,7 @@ LowRankFun(f::LowRankFun)=LowRankFun(f,Interval(),Interval())

## Utilities

function findapproxmax!(f::Function,X::Matrix,ptsx::Vector,ptsy::Vector,gridx,gridy)
function findapproxmax!(f::F,X::Matrix,ptsx::Vector,ptsy::Vector,gridx,gridy)
for j=1:gridy
ptsyj = ptsy[j]
@simd for k=1:gridx
Expand All @@ -222,7 +224,7 @@ function findapproxmax!(A::Fun,B::Fun,X::Matrix,ptsx::Vector,ptsy::Vector,gridx,
[ptsx[imptple[1]],ptsy[imptple[2]]]
end

function findcholeskyapproxmax!(f::Function,X::Vector,pts::Vector,grid)
function findcholeskyapproxmax!(f::F,X::Vector,pts::Vector,grid)
@simd for k=1:grid
@inbounds X[k]+=f(pts[k],pts[k])
end
Expand Down
18 changes: 10 additions & 8 deletions src/Multivariate/ProductFun.jl
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ end

## Adaptive construction

function ProductFun{S<:UnivariateSpace,V<:UnivariateSpace}(f::Function,sp::AbstractProductSpace{Tuple{S,V}};tol=100eps())
function ProductFun{S<:UnivariateSpace,V<:UnivariateSpace}(f::F,sp::AbstractProductSpace{Tuple{S,V}};tol=100eps())
for n = 50:100:5000
X = coefficients(ProductFun(f,sp,n,n;tol=tol))
if size(X,1)<n && size(X,2)<n
Expand All @@ -57,24 +57,26 @@ end

## ProductFun values to coefficients

function ProductFun(f::Function,S::AbstractProductSpace,M::Integer,N::Integer;tol=100eps())
function ProductFun(f::F,S::AbstractProductSpace,M::Integer,N::Integer;tol=100eps())
xy = checkpoints(S)
T = promote_type(eltype(f(first(xy)...)),eltype(S))
ptsx,ptsy=points(S,M,N)
vals=T[f(ptsx[k,j],ptsy[k,j]) for k=1:size(ptsx,1), j=1:size(ptsx,2)]
ProductFun(transform!(S,vals),S;tol=tol,chopping=true)
end
ProductFun(f::Function,S::TensorSpace) = ProductFun(LowRankFun(f,S))
ProductFun(f::F,S::TensorSpace) = ProductFun(LowRankFun(f,S))

ProductFun(f,dx::Space,dy::Space)=ProductFun(f,TensorSpace(dx,dy))

ProductFun(f::Function,dx::Space,dy::Space)=ProductFun(F(f),TensorSpace(dx,dy))
ProductFun(f::Function,args...;kwds...) = ProductFun(F(f),args...;kwds...)

## Domains promoted to Spaces

ProductFun(f::Function,D::BivariateDomain,M::Integer,N::Integer)=ProductFun(f,Space(D),M,N)
ProductFun(f,d::Domain)=ProductFun(f,Space(d))
ProductFun(f,dx::UnivariateDomain,dy::UnivariateDomain)=ProductFun(f,Space(dx),Space(dy))
ProductFun(f::Function) = ProductFun(f,Interval(),Interval())
ProductFun(f::F,D::BivariateDomain,M::Integer,N::Integer)=ProductFun(f,Space(D),M,N)
ProductFun(f::F,d::Domain)=ProductFun(f,Space(d))
ProductFun(f::F,dx::UnivariateDomain,dy::UnivariateDomain)=ProductFun(f,Space(dx),Space(dy))
ProductFun(f::F) = ProductFun(f,Interval(),Interval())

## Conversion from other 2D Funs

Expand All @@ -98,7 +100,7 @@ end

## For specifying spaces by anonymous function

ProductFun(f::Function,SF::Function,T::Space,M::Integer,N::Integer)=ProductFun(f,typeof(SF(1))[SF(k) for k=1:N],T,M)
ProductFun(f::F,SF::Function,T::Space,M::Integer,N::Integer)=ProductFun(f,typeof(SF(1))[SF(k) for k=1:N],T,M)

## Conversion of a constant to a ProductFun

Expand Down

0 comments on commit 6d0b0dc

Please sign in to comment.