From bd844d437f812b1c7d7e76c4e08d1c9b81e5746b Mon Sep 17 00:00:00 2001 From: mattsignorelli Date: Fri, 29 Mar 2024 15:16:28 -0400 Subject: [PATCH 01/29] added function clear\! --- src/GTPSA.jl | 1 + src/operators.jl | 9 +++++++++ 2 files changed, 10 insertions(+) diff --git a/src/GTPSA.jl b/src/GTPSA.jl index ccd90fd1..4ab80736 100644 --- a/src/GTPSA.jl +++ b/src/GTPSA.jl @@ -118,6 +118,7 @@ export scalar, setGTPSA!, getGTPSA, + clear!, # Temporaries: @FastGTPSA, diff --git a/src/operators.jl b/src/operators.jl index 3ad84c58..e54a2748 100644 --- a/src/operators.jl +++ b/src/operators.jl @@ -1,3 +1,12 @@ +# -- clear -- +function clear!(t::TPS) + mad_tpsa_clear!(t.tpsa) +end + +function clear!(t::ComplexTPS) + mad_ctpsa_clear!(t.tpsa) +end + # -- zero -- function zero(t::TPS)::TPS return TPS(mad_tpsa_new(t.tpsa, MAD_TPSA_SAME)) From c8ba8d2c6a10f96ac5b2f45bc65e224db01ccb4c Mon Sep 17 00:00:00 2001 From: mattsignorelli Date: Fri, 29 Mar 2024 16:29:20 -0400 Subject: [PATCH 02/29] Remove redundant warnings in show --- src/show.jl | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/show.jl b/src/show.jl index ea0d2b84..0862d023 100644 --- a/src/show.jl +++ b/src/show.jl @@ -286,7 +286,7 @@ function show_vec(io::IO, m::Vector{<:Union{TPS,ComplexTPS}}) desc = unsafe_load(Base.unsafe_convert(Ptr{Desc}, unsafe_load(first(m).tpsa).d)) diffdescs = false for i in eachindex(m) - if desc != unsafe_load(Base.unsafe_convert(Ptr{Desc}, unsafe_load(m[i].tpsa).d)) + if !diffdescs && desc != unsafe_load(Base.unsafe_convert(Ptr{Desc}, unsafe_load(m[i].tpsa).d)) println(io, "WARNING: Atleast one $(eltype(m)) has a different Descriptor!") diffdescs = true lines_used[] += 1 @@ -330,7 +330,9 @@ function show_map!(io::IO, m::Vector{<:Union{TPS,ComplexTPS}}, lines_used::Ref=R for i in eachindex(m) curdesc = unsafe_load(Base.unsafe_convert(Ptr{Desc}, unsafe_load(m[i].tpsa).d)) if only_vars && (desc.nv != curdesc.nv) - error("Cannot use only_vars = true for vector with TPSs having different number of variables") + println(io, "Cannot print $(typeof(m)): unable to resolve GTPSA Descriptor.") + lines_used[]+=1 + return end max_nn = max(max_nn, curdesc.nv+curdesc.np) end From b7fdc00ad4b49e7bfca4df7d50560990459820cc Mon Sep 17 00:00:00 2001 From: mattsignorelli Date: Mon, 1 Apr 2024 15:15:04 -0400 Subject: [PATCH 03/29] indexing update, clear, copy --- docs/src/man/k_methods.md | 1 + docs/src/man/o_all.md | 2 +- src/GTPSA.jl | 44 +- src/getset.jl | 154 +++- src/operators.jl | 13 +- test/runtests.jl | 416 ++++----- test/type_stable.jl | 1709 +++++++++++++++++++------------------ 7 files changed, 1215 insertions(+), 1124 deletions(-) diff --git a/docs/src/man/k_methods.md b/docs/src/man/k_methods.md index fd6ed9cd..923c5775 100644 --- a/docs/src/man/k_methods.md +++ b/docs/src/man/k_methods.md @@ -1,5 +1,6 @@ # [TPS and Map Methods](@id tpsmapmethods) ```@docs +clear! cutord deriv evaluate diff --git a/docs/src/man/o_all.md b/docs/src/man/o_all.md index d11e520f..49f08e7a 100644 --- a/docs/src/man/o_all.md +++ b/docs/src/man/o_all.md @@ -6,7 +6,7 @@ sin, cos, tan, csc, sec, cot, sinc, sinh, cosh, tanh, csch, sech, coth, asin, acos, atan, acsc, asec, acot, asinh, acosh, atanh, acsch, asech, acoth, zero, one, real, imag, conj, angle, complex, promote_rule, getindex, setindex!, ==, <, >, <=, >=, -!=, isequal, show +!=, isequal, show, copy! ``` `GTPSA.jl` overloads (and exports) the following functions from the corresponding packages: diff --git a/src/GTPSA.jl b/src/GTPSA.jl index 4ab80736..813d4aa4 100644 --- a/src/GTPSA.jl +++ b/src/GTPSA.jl @@ -57,7 +57,8 @@ import Base: +, >=, !=, isequal, - show + show, + copy! import LinearAlgebra: norm import SpecialFunctions: erf, erfc @@ -141,16 +142,6 @@ include("low_level/desc.jl") include("low_level/rtpsa.jl") include("low_level/ctpsa.jl") -# Useful type-generic functions: -cycle!(t::Ptr{RTPSA}, i::Cint, n::Cint, m_::Vector{Cuchar}, v_::Ref{Cdouble}) = (@inline; mad_tpsa_cycle!(t, i, n, m_, v_)) -cycle!(t::Ptr{CTPSA}, i::Cint, n::Cint, m_::Vector{Cuchar}, v_::Ref{ComplexF64}) = (@inline; mad_ctpsa_cycle!(t, i, n, m_, v_)) -idxm(t::Ptr{RTPSA}, n::Cint, m::Vector{Cuchar}) = (@inline; mad_tpsa_idxm(t, n, m)) -idxm(t::Ptr{CTPSA}, n::Cint, m::Vector{Cuchar}) = (@inline; mad_ctpsa_idxm(t, n, m)) -seti!(t::Ptr{RTPSA}, i::Cint, a::Cdouble, b::Cdouble) = (@inline; mad_tpsa_seti!(t, i, a, b)) -seti!(t::Ptr{CTPSA}, i::Cint, a::ComplexF64, b::ComplexF64) = (@inline; mad_ctpsa_seti!(t, i, a, b)) -setm!(t::Ptr{RTPSA}, n::Cint, m::Vector{Cuchar}, a::Cdouble, b::Cdouble) = (@inline; mad_tpsa_setm!(t, n, m, a, b)) -setm!(t::Ptr{CTPSA}, n::Cint, m::Vector{Cuchar}, a::ComplexF64, b::ComplexF64) = (@inline; mad_ctpsa_setm!(t, n, m, a, b)) - const MAD_TPSA::String = :("libgtpsa") const MAD_TPSA_DEFAULT::Cuchar = 255 const MAD_TPSA_SAME::Cuchar = 254 @@ -538,6 +529,17 @@ function low_ComplexTPS(a::Real, tb::TPS, use::Union{TPS,ComplexTPS}) return low_ComplexTPS(a, tb, Descriptor(Base.unsafe_convert(Ptr{Desc}, unsafe_load(use.tpsa)))) end +# Useful type-generic functions: +cycle!(t::Ptr{RTPSA}, i::Cint, n::Cint, m_::Vector{Cuchar}, v_::Ref{Cdouble}) = (@inline; mad_tpsa_cycle!(t, i, n, m_, v_)) +cycle!(t::Ptr{CTPSA}, i::Cint, n::Cint, m_::Vector{Cuchar}, v_::Ref{ComplexF64}) = (@inline; mad_ctpsa_cycle!(t, i, n, m_, v_)) +idxm(t::Ptr{RTPSA}, n::Cint, m::Vector{Cuchar}) = (@inline; mad_tpsa_idxm(t, n, m)) +idxm(t::Ptr{CTPSA}, n::Cint, m::Vector{Cuchar}) = (@inline; mad_ctpsa_idxm(t, n, m)) +getdesc(t::Union{TPS,ComplexTPS}) = Descriptor(Base.unsafe_convert(Ptr{Desc}, unsafe_load(t.tpsa).d)) +numvars(t::Union{TPS,ComplexTPS}) = unsafe_load(Base.unsafe_convert(Ptr{Desc}, unsafe_load(t.tpsa).d)).nv +numparams(t::Union{TPS,ComplexTPS}) = unsafe_load(Base.unsafe_convert(Ptr{Desc}, unsafe_load(t.tpsa).d)).np +numnn(t::Union{TPS,ComplexTPS}) = unsafe_load(Base.unsafe_convert(Ptr{Desc}, unsafe_load(t.tpsa).d)).nn + + # --- Variable/parameter generators --- """ @@ -806,14 +808,19 @@ function low_mono(T::Type, d::Union{Descriptor,TPS,ComplexTPS}, v, param, params end # Function to convert var=>ord, params=(param=>ord,) to low level sparse monomial format (varidx1, ord1, varidx2, ord2, paramidx, ordp1,...) -function pairs_to_sm(t::Union{TPS,ComplexTPS}, vars::Union{Vector{<:Pair{<:Integer, <:Integer}},Tuple{Vararg{Pair{<:Integer,<:Integer}}}}; params::Vector{<:Pair{<:Integer,<:Integer}}=Pair{Int,Int}[])::Tuple{Vector{Cint}, Cint} +function pairs_to_sm(t::Union{TPS,ComplexTPS}, vars::Union{Vector{<:Pair{<:Integer, <:Integer}},Tuple{Vararg{Pair{<:Integer,<:Integer}}}}; params::Union{Vector{<:Pair{<:Integer,<:Integer}},Tuple{Vararg{<:Pair{<:Integer,<:Integer}}},Nothing}=nothing)::Tuple{Vector{Cint}, Cint} # WE MUST Order THE VARIABLES !!! - desc = unsafe_load(Base.unsafe_convert(Ptr{Desc}, unsafe_load(t.tpsa).d)) - nv = desc.nv # TOTAL NUMBER OF VARS!!!!!! + nv = numvars(t) numv = Cint(length(vars)) - nump = Cint(length(params)) - imin = min(minimum(x->x.first, vars,init=typemax(Int)), minimum(x->x.first+nv, params,init=typemax(Int))) - imax = max(maximum(x->x.first, vars,init=0), maximum(x->x.first+nv, params,init=0)) + if !isnothing(params) + nump = Cint(length(params)) + imin = min(minimum(x->x.first, vars,init=typemax(Int)), minimum(x->x.first+nv, params,init=typemax(Int))) + imax = max(maximum(x->x.first, vars,init=0), maximum(x->x.first+nv, params,init=0)) + else + nump = 0 + imin = minimum(x->x.first, vars,init=typemax(Int)) + imax = maximum(x->x.first, vars,init=0) + end len = imax-imin+1 sm = zeros(Cint, 2*len) sm[1:2:end] = imin:imax @@ -829,8 +836,7 @@ end # Function to convert var=>ord, params=(param=>ord,) to monomial format (byte array of orders) function pairs_to_m(t::Union{TPS,ComplexTPS}, vars::Union{Vector{<:Pair{<:Integer, <:Integer}},Tuple{Vararg{Pair{<:Integer,<:Integer}}}}; params::Vector{<:Pair{<:Integer,<:Integer}}=Pair{Int,Int}[],zero_mono=true)::Tuple{Vector{UInt8}, Cint} - desc = unsafe_load(Base.unsafe_convert(Ptr{Desc}, unsafe_load(t.tpsa).d)) - nv = desc.nv + nv = numvars(t) n = Cint(0) if isempty(params) n = Cint(maximum(map(x->x.first, vars))) diff --git a/src/getset.jl b/src/getset.jl index f1c0d175..4388b86d 100644 --- a/src/getset.jl +++ b/src/getset.jl @@ -9,46 +9,119 @@ lowtype(::Type{TPS}) = Ptr{RTPSA} lowtype(::Type{ComplexTPS}) = Ptr{CTPSA} # --- Setters --- -function setindex!(t::TPS, v::Real, ords::Integer...) - mad_tpsa_setm!(t.tpsa, convert(Cint, length(ords)), convert(Vector{Cuchar}, [ords...]), 0.0, convert(Cdouble, v)) +seti!(t::Ptr{RTPSA}, i::Cint, a::Cdouble, b::Cdouble) = mad_tpsa_seti!(t, i, a, b) +seti!(t::Ptr{CTPSA}, i::Cint, a::ComplexF64, b::ComplexF64) = mad_ctpsa_seti!(t, i, a, b) +setm!(t::Ptr{RTPSA}, n::Cint, m::Vector{Cuchar}, a::Float64, b::Float64) = mad_tpsa_setm!(t, n, m, a, b) +setm!(t::Ptr{CTPSA}, n::Cint, m::Vector{Cuchar}, a::ComplexF64, b::ComplexF64) = mad_ctpsa_setm!(t, n, m, a, b) +setsm!(t::Ptr{RTPSA}, n::Cint, m::Vector{Cint}, a::Float64, b::Float64)= mad_tpsa_setsm!(t, n, m, a, b) +setsm!(t::Ptr{CTPSA}, n::Cint, m::Vector{Cint}, a::ComplexF64, b::ComplexF64)= mad_ctpsa_setsm!(t, n, m, a, b) + +# Flat index: Integer... +# Monomial: Vector{<:Integer}, Tuple{Vararg{<:Integer}} +# Sparse Monomial: Pair{<:Integer,<:Integer}... , Vector{<:Pair{<:Integer,<:Integer}}, Tuple{Vararg{<:Pair{<:Integer,<:Integer}}} +const SMIndexType = Union{Vector{<:Pair{<:Integer,<:Integer}}, Tuple{Vararg{<:Pair{<:Integer,<:Integer}}}} +const MIndexType = Union{Vector{<:Integer}, Tuple{Vararg{<:Integer}}} +const TPSIndexType = Union{Integer, + MIndexType, + SMIndexType} + +# All +function setindex!(t::Union{TPS,ComplexTPS}, v::Number, idx::Union{TPSIndexType,Nothing}=nothing; param::Union{<:Integer,Nothing}=nothing, params::Union{SMIndexType,Nothing}=nothing) + lowset!(t, v, idx, param, params) end -function setindex!(t::TPS, v::Real, vars::Pair{<:Integer, <:Integer}...; params::Vector{<:Pair{<:Integer,<:Integer}}=Pair{Int,Int}[]) - sm, n = pairs_to_sm(t, vars, params=params) - mad_tpsa_setsm!(t.tpsa, n, sm, 0.0, convert(Cdouble, v)) +# To override Base number.jl +#setindex!(t::Union{ComplexTPS, TPS}, v::Number, idx::Integer) = lowset!(t, v, tuple(idx), nothing, nothing) + +# Flat index +function lowset!(t::Union{TPS,ComplexTPS}, v::Number, i::Union{Nothing,<:Integer}, param::Union{Nothing,<:Integer}, params::Nothing) + if !xor(isempty(i), isnothing(param)) + error("Invalid monomial index specified. Please use ONE of variable/parameter index, index by order, or index by sparse monomial.") + end + + if isnothing(param) + seti!(t.tpsa, Cint(i), (numtype(t))(0), (numtype(t))(v)) + else + nv = numvars(t) + seti!(t.tpsa, Cint(nv+param), (numtype(t))(0), (numtype(t))(v)) + end end -function setindex!(ct::ComplexTPS, v::Number, ords::Integer...) - mad_ctpsa_setm!(ct.tpsa, convert(Cint, length(ords)), convert(Vector{Cuchar}, [ords...]), convert(ComplexF64, 0), convert(ComplexF64, v)) +# Monomial +function lowset!(t::Union{TPS,ComplexTPS}, v::Number, ords::MIndexType, param::Nothing, params::Nothing) + setm!(t.tpsa, convert(Cint, length(ords)), collect(Cuchar, ords), (numtype(t))(0), (numtype(t))(v)) end -function setindex!(ct::ComplexTPS, v::Number, vars::Pair{<:Integer, <:Integer}...; params::Vector{<:Pair{<:Integer,<:Integer}}=Pair{Int,Int}[]) - sm, n = pairs_to_sm(ct, vars, params=params) - mad_ctpsa_setsm!(ct.tpsa, n, sm, convert(ComplexF64, 0), convert(ComplexF64, v)) +# By sparse monomial +function lowset!(t::Union{TPS,ComplexTPS}, v::Number, vars::SMIndexType, param::Nothing, params::Union{SMIndexType,Nothing}) + sm, n = pairs_to_sm(t, vars, params=params) + setsm!(t.tpsa, n, sm, (numtype(t))(0), (numtype(t))(v)) +end + +# Sparse monomial with nothing for vars +function lowset!(t::Union{TPS,ComplexTPS}, v::Number, vars::Nothing, param::Nothing, params::SMIndexType) + sm, n = pairs_to_sm(t, Pair{Int,Int}[], params=params) + setsm!(t.tpsa, n, sm, (numtype(t))(0), (numtype(t))(v)) end +# In case someone forgets tuple: +lowset!(t, v, idx, param, params) = error("Invalid monomial index specified. Please use ONE of variable/parameter index, index by order, or index by sparse monomial.") + # --- Getters --- +geti(t::Ptr{RTPSA}, i::Cint) = mad_tpsa_geti(t, i) +geti(t::Ptr{CTPSA}, i::Cint) = mad_ctpsa_geti(t, i) getm(t::Ptr{RTPSA}, n::Cint, m::Vector{Cuchar}) = mad_tpsa_getm(t, n, m) getm(t::Ptr{CTPSA}, n::Cint, m::Vector{Cuchar}) = mad_ctpsa_getm(t, n, m) getsm(t::Ptr{RTPSA}, n::Cint, m::Vector{Cint})= mad_tpsa_getsm(t, n, m) getsm(t::Ptr{CTPSA}, n::Cint, m::Vector{Cint})= mad_ctpsa_getsm(t, n, m) -function getindex(t::Union{TPS,ComplexTPS}, ords::Integer...) - return getm(t.tpsa, convert(Cint, length(ords)), convert(Vector{Cuchar}, [ords...])) +# All +function getindex(t::Union{TPS,ComplexTPS}, idx::Union{TPSIndexType,Nothing}=nothing; param::Union{<:Integer,Nothing}=nothing, params::Union{SMIndexType,Nothing}=nothing) + lowget(t, idx, param, params) end -function getindex(t::Union{TPS,ComplexTPS}, vars::Pair{<:Integer, <:Integer}...; params::Vector{<:Pair{<:Integer,<:Integer}}=Pair{Int,Int}[]) - # use sparse monomial getter +# To override Base number.jl +getindex(t::Union{ComplexTPS, TPS}, idx::Integer) = lowget(t, idx, nothing, nothing) + +# Flat index +function lowget(t::Union{TPS,ComplexTPS}, i::Union{Nothing,<:Integer}, param::Union{Nothing,<:Integer}, params::Nothing) + if !xor(isempty(i), isnothing(param)) + error("Invalid monomial index specified. Please use ONE of variable/parameter index, index by order, or index by sparse monomial.") + end + + if isnothing(param) + return geti(t.tpsa, Cint(i)) + else + nv = numvars(t) + return geti(t.tpsa, Cint(nv+param)) + end +end + +# Monomial +function lowget(t::Union{TPS,ComplexTPS}, ords::MIndexType, param::Nothing, params::Nothing) + return getm(t.tpsa, convert(Cint, length(ords)), collect(Cuchar, ords)) +end + +# By sparse monomial +function lowget(t::Union{TPS,ComplexTPS}, vars::SMIndexType, param::Nothing, params::Union{SMIndexType,Nothing}) sm, n = pairs_to_sm(t, vars, params=params) return getsm(t.tpsa, n, sm) end +# Sparse monomial with nothing for vars +function lowget(t::Union{TPS,ComplexTPS}, vars::Nothing, param::Nothing, params::SMIndexType) + sm, n = pairs_to_sm(t, Pair{Int,Int}[], params=params) + return getsm(t.tpsa, n, sm) +end + +lowget(t, idx, param, params) = error("Invalid monomial index specified. Please use ONE of variable/parameter index, index by order, or index by sparse monomial.") + + + +# --- Slicing (getter) --- +#= function getindex(t::Union{TPS,ComplexTPS}, ords::Union{Integer,Colon}...) - #= - if !(ords[1:end-1] isa Tuple{Vararg{Integer}}) - error("Invalid monomial index: colon must appear at end.") - end=# return slice(t, setup_mono(t,ords,nothing,nothing), false) end @@ -57,11 +130,6 @@ function getindex(t::Union{TPS,ComplexTPS}, vars::Union{Pair{<:Integer, <:Intege end getindex(t::Union{TPS,ComplexTPS}) = t - -#= -function getindex(::TPS) - return TPS[] -end =# # --- par --- @@ -149,8 +217,7 @@ function setup_mono(t1::Union{TPS,ComplexTPS}, v::Integer, param::Nothing, param end function setup_mono(t1::Union{TPS,ComplexTPS}, v::Nothing, param::Integer, params::Nothing)::Vector{Cuchar} - desc = unsafe_load(Base.unsafe_convert(Ptr{Desc}, unsafe_load(t1.tpsa).d)) - nv = desc.nv # TOTAL NUMBER OF VARS!!!! + nv = numvars(t1) # TOTAL NUMBER OF VARS!!!! par_mono = ones(Cuchar, param+nv+1).*0xff par_mono[nv+param] = 0x1 return par_mono @@ -164,7 +231,7 @@ end # Monomial by order: # This one should ALWAYS be called by par or splicing colon IS in the tuple or vector somewhere function setup_mono(t1::Union{TPS,ComplexTPS}, v::Union{Tuple{Vararg{Union{<:Integer,<:Colon}}},Vector{<:Any}}, param::Nothing, params::Nothing)::Vector{Cuchar} - return [replace(x-> x isa Colon ? 0xff::Cuchar : convert(Cuchar, x)::Cuchar, v)...] + return collect(replace(x-> x isa Colon ? 0xff::Cuchar : convert(Cuchar, x)::Cuchar, v)) end # By definition, sparse monomial makes everything else zero. SO if we reach this, it is automatically @@ -195,9 +262,8 @@ function setup_mono(t1::Union{TPS,ComplexTPS}, v, param, params) end function slice(t1::Union{TPS,ComplexTPS}, par_mono::Vector{Cuchar}, par_it=true) - desc = unsafe_load(Base.unsafe_convert(Ptr{Desc}, unsafe_load(t1.tpsa).d)) - nv = desc.nv # TOTAL NUMBER OF VARS!!!! - np = desc.np + nv = numvars(t1) + np = numparams(t1) t = zero(t1) v = Cint(length(par_mono)) coef = Ref{numtype(t)}() @@ -247,10 +313,9 @@ in the TPS. - `result` -- Preallocated `Vector` to fill with the gradient of the TPS """ function gradient!(result::Vector{<:Union{Float64,ComplexF64}}, t::Union{TPS,ComplexTPS}; include_params=false) - desc = unsafe_load(Base.unsafe_convert(Ptr{Desc}, unsafe_load(t.tpsa).d)) - n = desc.nv + n = numvars(t) if include_params - n += desc.np + n += numparams(t) end if length(result) != n error("Incorrect size for result") @@ -274,10 +339,9 @@ first-order monomial coefficients already in the TPS. - `grad` -- Gradient of the TPS """ function gradient(t::Union{TPS,ComplexTPS}; include_params=false) - desc = unsafe_load(Base.unsafe_convert(Ptr{Desc}, unsafe_load(t.tpsa).d)) - n = desc.nv + n = numvars(t) if include_params - n += desc.np + n += numparams(t) end grad = Vector{numtype(t)}(undef, n) getv!(t.tpsa, Cint(1), n, grad) @@ -301,10 +365,9 @@ in the TPSs. - `result` -- Preallocated matrix to fill with the Jacobian of `m` """ function jacobian!(result::Matrix{<:Union{Float64,ComplexF64}}, m::Vector{<:Union{TPS,ComplexTPS}}; include_params=false) - desc = unsafe_load(Base.unsafe_convert(Ptr{Desc}, unsafe_load(first(m).tpsa).d)) - n = desc.nv + n = numvars(first(m)) if include_params - n += desc.np + n += numparams(first(m)) end if size(result)[2] != n error("Incorrect size for result") @@ -335,10 +398,9 @@ the first-order monomial coefficients already in the TPSs. - `J` -- Jacobian of `m` """ function jacobian(m::Vector{<:Union{TPS,ComplexTPS}}; include_params=false) - desc = unsafe_load(Base.unsafe_convert(Ptr{Desc}, unsafe_load(first(m).tpsa).d)) - n = desc.nv + n = numvars(first(m)) if include_params - n += desc.np + n += numparams(first(m)) end J = Matrix{numtype(first(m))}(undef, length(m), n) grad = Vector{numtype(first(m))}(undef, n) @@ -367,10 +429,9 @@ first-order monomial coefficients already in the TPSs and filling `result`. - `result` -- Preallocated matrix to fill with the transpose of the Jacobian of `m` """ function jacobiant!(result::Matrix{<:Union{Float64,ComplexF64}}, m::Vector{<:Union{TPS,ComplexTPS}}; include_params=false) - desc = unsafe_load(Base.unsafe_convert(Ptr{Desc}, unsafe_load(first(m).tpsa).d)) - n = desc.nv + n = numvars(first(m)) if include_params - n += desc.np + n += numparams(first(m)) end if size(result)[2] != n error("Incorrect size for result") @@ -398,10 +459,9 @@ first-order monomial coefficients already in the TPSs. - `Jt` -- Transpose of the Jacobian of `m` """ function jacobiant(m::Vector{<:Union{TPS,ComplexTPS}}; include_params=false) - desc = unsafe_load(Base.unsafe_convert(Ptr{Desc}, unsafe_load(first(m).tpsa).d)) - n = desc.nv + n = numvars(first(m)) if include_params - n += desc.np + n += numparams(first(m)) end result = Matrix{numtype(first(m))}(undef, length(m), n) jacobiant!(result, m, include_params=include_params) diff --git a/src/operators.jl b/src/operators.jl index e54a2748..29eb1669 100644 --- a/src/operators.jl +++ b/src/operators.jl @@ -1,4 +1,4 @@ -# -- clear -- +# --- clear --- function clear!(t::TPS) mad_tpsa_clear!(t.tpsa) end @@ -7,7 +7,16 @@ function clear!(t::ComplexTPS) mad_ctpsa_clear!(t.tpsa) end -# -- zero -- +# --- copy --- +function copy!(t::TPS, t1::TPS) + mad_tpsa_copy!(t1.tpsa, t.tpsa) +end + +function copy!(ct::ComplexTPS, ct1::ComplexTPS) + mad_ctpsa_copy!(ct1.tpsa, ct.tpsa) +end + +# --- zero --- function zero(t::TPS)::TPS return TPS(mad_tpsa_new(t.tpsa, MAD_TPSA_SAME)) end diff --git a/test/runtests.jl b/test/runtests.jl index 205b6c57..ed2e0929 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -136,9 +136,9 @@ import GTPSA: Desc, RTPSA, CTPSA # Now do operators # Test definition of 1-norm: tn = zero(t1) - tn[0] = 1; tn[1] = 2; tn[2] = 3; tn[3] = 4; tn[4] = 5; tn[5] = 6 + tn[0] = 1; tn[[1]] = 2; tn[[2]] = 3; tn[[3]] = 4; tn[[4]] = 5; tn[[5]] = 6 tcn = zero(ct1) - tcn[0] = 1+1im; tcn[1] = 2+2im; tcn[2] = 3+3im; tcn[3] = 4+4im; tcn[4] = 5+5im; tcn[5] = 6+6im + tcn[0] = 1+1im; tcn[[1]] = 2+2im; tcn[[2]] = 3+3im; tcn[[3]] = 4+4im; tcn[[4]] = 5+5im; tcn[[5]] = 6+6im @test norm(tn) == sum([i for i in 1:6]) @test norm(tcn) == sum([abs(i+i*im) for i in 1:6]) @@ -405,7 +405,7 @@ end @testset "Functions: identities, using TPSs" begin d = Descriptor(1, 5) t = TPS(use=d) - t[0] = 0.5; t[1] = 2; t[2] = 3; t[3] = 4; t[4] = 5; t[5] = 6 + t[0] = 0.5; t[[1]] = 2; t[[2]] = 3; t[[3]] = 4; t[[4]] = 5; t[[5]] = 6 tol = 1e-10 @@ -462,7 +462,7 @@ end @test norm(complex(t,t) - (t+im*t)) < tol t = ComplexTPS(t) - t[0] = 0.5+0.5im; t[1] = 2+2im; t[2] = 3+3im; t[3] = 4+4im; t[4] = 5+5im; t[5] = 6+6im + t[0] = 0.5+0.5im; t[[1]] = 2+2im; t[[2]] = 3+3im; t[[3]] = 4+4im; t[[4]] = 5+5im; t[[5]] = 6+6im @test norm(sin(t)^2+cos(t)^2 - 1) < tol @test norm(1/sin(t) - csc(t)) < tol @test norm(1/cos(t) - sec(t)) < tol @@ -522,216 +522,216 @@ end tol = 1e-18 f = sin(v[1]) - @test abs(f[0] - 0) < tol - @test abs(f[1] - 1) < tol - @test abs(f[2] - 0) < tol - @test abs(f[3] - -1/factorial(3)) < tol - @test abs(f[4] - 0) < tol - @test abs(f[5] - 1/factorial(5)) < tol - @test abs(f[6] - 0) < tol - @test abs(f[7] - -1/factorial(7)) < tol - @test abs(f[8] - 0) < tol - @test abs(f[9] - 1/factorial(9)) < tol - @test abs(f[10] - 0) < tol - - @test abs(f[1=>1] - f[1]) < tol - @test abs(f[1=>2] - f[2]) < tol - @test abs(f[1=>3] - f[3]) < tol - @test abs(f[1=>4] - f[4]) < tol - @test abs(f[1=>5] - f[5]) < tol - @test abs(f[1=>6] - f[6]) < tol - @test abs(f[1=>7] - f[7]) < tol - @test abs(f[1=>8] - f[8]) < tol - @test abs(f[1=>9] - f[9]) < tol - @test abs(f[1=>10] - f[10]) < tol + @test abs(f[[0]] - 0) < tol + @test abs(f[[1]] - 1) < tol + @test abs(f[[2]] - 0) < tol + @test abs(f[[3]] - -1/factorial(3)) < tol + @test abs(f[[4]] - 0) < tol + @test abs(f[[5]] - 1/factorial(5)) < tol + @test abs(f[[6]] - 0) < tol + @test abs(f[[7]] - -1/factorial(7)) < tol + @test abs(f[[8]] - 0) < tol + @test abs(f[[9]] - 1/factorial(9)) < tol + @test abs(f[[10]] - 0) < tol + + @test abs(f[[1=>1]] - f[[1]]) < tol + @test abs(f[[1=>2]] - f[[2]]) < tol + @test abs(f[[1=>3]] - f[[3]]) < tol + @test abs(f[[1=>4]] - f[[4]]) < tol + @test abs(f[[1=>5]] - f[[5]]) < tol + @test abs(f[[1=>6]] - f[[6]]) < tol + @test abs(f[[1=>7]] - f[[7]]) < tol + @test abs(f[[1=>8]] - f[[8]]) < tol + @test abs(f[[1=>9]] - f[[9]]) < tol + @test abs(f[[1=>10]] - f[[10]]) < tol fc = complex(f) - @test abs(fc[0] - 0) < tol - @test abs(fc[1] - 1) < tol - @test abs(fc[2] - 0) < tol - @test abs(fc[3] - -1/factorial(3)) < tol - @test abs(fc[4] - 0) < tol - @test abs(fc[5] - 1/factorial(5)) < tol - @test abs(fc[6] - 0) < tol - @test abs(fc[7] - -1/factorial(7)) < tol - @test abs(fc[8] - 0) < tol - @test abs(fc[9] - 1/factorial(9)) < tol - @test abs(fc[10] - 0) < tol - - @test abs(fc[1=>1] - f[1]) < tol - @test abs(fc[1=>2] - f[2]) < tol - @test abs(fc[1=>3] - f[3]) < tol - @test abs(fc[1=>4] - f[4]) < tol - @test abs(fc[1=>5] - f[5]) < tol - @test abs(fc[1=>6] - f[6]) < tol - @test abs(fc[1=>7] - f[7]) < tol - @test abs(fc[1=>8] - f[8]) < tol - @test abs(fc[1=>9] - f[9]) < tol - @test abs(fc[1=>10] - f[10]) < tol + @test abs(fc[[0]] - 0) < tol + @test abs(fc[[1]] - 1) < tol + @test abs(fc[[2]] - 0) < tol + @test abs(fc[[3]] - -1/factorial(3)) < tol + @test abs(fc[[4]] - 0) < tol + @test abs(fc[[5]] - 1/factorial(5)) < tol + @test abs(fc[[6]] - 0) < tol + @test abs(fc[[7]] - -1/factorial(7)) < tol + @test abs(fc[[8]] - 0) < tol + @test abs(fc[[9]] - 1/factorial(9)) < tol + @test abs(fc[[10]] - 0) < tol + + @test abs(fc[[1=>1]] - f[[1]]) < tol + @test abs(fc[[1=>2]] - f[[2]]) < tol + @test abs(fc[[1=>3]] - f[[3]]) < tol + @test abs(fc[[1=>4]] - f[[4]]) < tol + @test abs(fc[[1=>5]] - f[[5]]) < tol + @test abs(fc[[1=>6]] - f[[6]]) < tol + @test abs(fc[[1=>7]] - f[[7]]) < tol + @test abs(fc[[1=>8]] - f[[8]]) < tol + @test abs(fc[[1=>9]] - f[[9]]) < tol + @test abs(fc[[1=>10]] - f[[10]]) < tol f2 = sin(v[1]) + cos(v[2]) - @test abs(f2[0] - 1) < tol - @test abs(f2[1] - 1) < tol - @test abs(f2[2] - 0) < tol - @test abs(f2[3] - -1/factorial(3)) < tol - @test abs(f2[4] - 0) < tol - @test abs(f2[5] - 1/factorial(5)) < tol - @test abs(f2[6] - 0) < tol - @test abs(f2[7] - -1/factorial(7)) < tol - @test abs(f2[8] - 0) < tol - @test abs(f2[9] - 1/factorial(9)) < tol - @test abs(f2[10] - 0) < tol - - @test abs(f2[0,0] - 1) < tol - @test abs(f2[0,1] - 0) < tol - @test abs(f2[0,2] - -1/factorial(2)) < tol - @test abs(f2[0,3] - 0) < tol - @test abs(f2[0,4] - 1/factorial(4)) < tol - @test abs(f2[0,5] - 0) < tol - @test abs(f2[0,6] - -1/factorial(6)) < tol - @test abs(f2[0,7] - 0) < tol - @test abs(f2[0,8] - 1/factorial(8)) < tol - @test abs(f2[0,9] - 0) < tol - @test abs(f2[0,10] - -1/factorial(10)) < tol - - @test abs(f2[1=>1] - f2[1]) < tol - @test abs(f2[1=>2] - f2[2]) < tol - @test abs(f2[1=>3] - f2[3]) < tol - @test abs(f2[1=>4] - f2[4]) < tol - @test abs(f2[1=>5] - f2[5]) < tol - @test abs(f2[1=>6] - f2[6]) < tol - @test abs(f2[1=>7] - f2[7]) < tol - @test abs(f2[1=>8] - f2[8]) < tol - @test abs(f2[1=>9] - f2[9]) < tol - @test abs(f2[1=>10] - f2[10]) < tol - - @test abs(f2[2=>1] - f2[0,1]) < tol - @test abs(f2[2=>2] - f2[0,2]) < tol - @test abs(f2[2=>3] - f2[0,3]) < tol - @test abs(f2[2=>4] - f2[0,4]) < tol - @test abs(f2[2=>5] - f2[0,5]) < tol - @test abs(f2[2=>6] - f2[0,6]) < tol - @test abs(f2[2=>7] - f2[0,7]) < tol - @test abs(f2[2=>8] - f2[0,8]) < tol - @test abs(f2[2=>9] - f2[0,9]) < tol - @test abs(f2[2=>10] - f2[0,10]) < tol + @test abs(f2[[0]] - 1) < tol + @test abs(f2[[1]] - 1) < tol + @test abs(f2[[2]] - 0) < tol + @test abs(f2[[3]] - -1/factorial(3)) < tol + @test abs(f2[[4]] - 0) < tol + @test abs(f2[[5]] - 1/factorial(5)) < tol + @test abs(f2[[6]] - 0) < tol + @test abs(f2[[7]] - -1/factorial(7)) < tol + @test abs(f2[[8]] - 0) < tol + @test abs(f2[[9]] - 1/factorial(9)) < tol + @test abs(f2[[10]] - 0) < tol + + @test abs(f2[[0,0]] - 1) < tol + @test abs(f2[[0,1]] - 0) < tol + @test abs(f2[[0,2]] - -1/factorial(2)) < tol + @test abs(f2[[0,3]] - 0) < tol + @test abs(f2[[0,4]] - 1/factorial(4)) < tol + @test abs(f2[[0,5]] - 0) < tol + @test abs(f2[[0,6]] - -1/factorial(6)) < tol + @test abs(f2[[0,7]] - 0) < tol + @test abs(f2[[0,8]] - 1/factorial(8)) < tol + @test abs(f2[[0,9]] - 0) < tol + @test abs(f2[[0,10]] - -1/factorial(10)) < tol + + @test abs(f2[[1=>1]] - f2[[1]]) < tol + @test abs(f2[[1=>2]] - f2[[2]]) < tol + @test abs(f2[[1=>3]] - f2[[3]]) < tol + @test abs(f2[[1=>4]] - f2[[4]]) < tol + @test abs(f2[[1=>5]] - f2[[5]]) < tol + @test abs(f2[[1=>6]] - f2[[6]]) < tol + @test abs(f2[[1=>7]] - f2[[7]]) < tol + @test abs(f2[[1=>8]] - f2[[8]]) < tol + @test abs(f2[[1=>9]] - f2[[9]]) < tol + @test abs(f2[[1=>10]] - f2[[10]]) < tol + + @test abs(f2[[2=>1]] - f2[[0,1]]) < tol + @test abs(f2[[2=>2]] - f2[[0,2]]) < tol + @test abs(f2[[2=>3]] - f2[[0,3]]) < tol + @test abs(f2[[2=>4]] - f2[[0,4]]) < tol + @test abs(f2[[2=>5]] - f2[[0,5]]) < tol + @test abs(f2[[2=>6]] - f2[[0,6]]) < tol + @test abs(f2[[2=>7]] - f2[[0,7]]) < tol + @test abs(f2[[2=>8]] - f2[[0,8]]) < tol + @test abs(f2[[2=>9]] - f2[[0,9]]) < tol + @test abs(f2[[2=>10]] - f2[[0,10]]) < tol f2c = complex(sin(v[1]) + cos(v[2])) - @test abs(f2c[0] - 1) < tol - @test abs(f2c[1] - 1) < tol - @test abs(f2c[2] - 0) < tol - @test abs(f2c[3] - -1/factorial(3)) < tol - @test abs(f2c[4] - 0) < tol - @test abs(f2c[5] - 1/factorial(5)) < tol - @test abs(f2c[6] - 0) < tol - @test abs(f2c[7] - -1/factorial(7)) < tol - @test abs(f2c[8] - 0) < tol - @test abs(f2c[9] - 1/factorial(9)) < tol - @test abs(f2c[10] - 0) < tol - - @test abs(f2c[0,0] - 1) < tol - @test abs(f2c[0,1] - 0) < tol - @test abs(f2c[0,2] - -1/factorial(2)) < tol - @test abs(f2c[0,3] - 0) < tol - @test abs(f2c[0,4] - 1/factorial(4)) < tol - @test abs(f2c[0,5] - 0) < tol - @test abs(f2c[0,6] - -1/factorial(6)) < tol - @test abs(f2c[0,7] - 0) < tol - @test abs(f2c[0,8] - 1/factorial(8)) < tol - @test abs(f2c[0,9] - 0) < tol - @test abs(f2c[0,10] - -1/factorial(10)) < tol - - @test abs(f2c[1=>1] - f2c[1]) < tol - @test abs(f2c[1=>2] - f2c[2]) < tol - @test abs(f2c[1=>3] - f2c[3]) < tol - @test abs(f2c[1=>4] - f2c[4]) < tol - @test abs(f2c[1=>5] - f2c[5]) < tol - @test abs(f2c[1=>6] - f2c[6]) < tol - @test abs(f2c[1=>7] - f2c[7]) < tol - @test abs(f2c[1=>8] - f2c[8]) < tol - @test abs(f2c[1=>9] - f2c[9]) < tol - @test abs(f2c[1=>10] - f2c[10]) < tol - - @test abs(f2c[2=>1] - f2c[0,1]) < tol - @test abs(f2c[2=>2] - f2c[0,2]) < tol - @test abs(f2c[2=>3] - f2c[0,3]) < tol - @test abs(f2c[2=>4] - f2c[0,4]) < tol - @test abs(f2c[2=>5] - f2c[0,5]) < tol - @test abs(f2c[2=>6] - f2c[0,6]) < tol - @test abs(f2c[2=>7] - f2c[0,7]) < tol - @test abs(f2c[2=>8] - f2c[0,8]) < tol - @test abs(f2c[2=>9] - f2c[0,9]) < tol - @test abs(f2c[2=>10] - f2c[0,10]) < tol + @test abs(f2c[[0]] - 1) < tol + @test abs(f2c[[1]] - 1) < tol + @test abs(f2c[[2]] - 0) < tol + @test abs(f2c[[3]] - -1/factorial(3)) < tol + @test abs(f2c[[4]] - 0) < tol + @test abs(f2c[[5]] - 1/factorial(5)) < tol + @test abs(f2c[[6]] - 0) < tol + @test abs(f2c[[7]] - -1/factorial(7)) < tol + @test abs(f2c[[8]] - 0) < tol + @test abs(f2c[[9]] - 1/factorial(9)) < tol + @test abs(f2c[[10]] - 0) < tol + + @test abs(f2c[[0,0]] - 1) < tol + @test abs(f2c[[0,1]] - 0) < tol + @test abs(f2c[[0,2]] - -1/factorial(2)) < tol + @test abs(f2c[[0,3]] - 0) < tol + @test abs(f2c[[0,4]] - 1/factorial(4)) < tol + @test abs(f2c[[0,5]] - 0) < tol + @test abs(f2c[[0,6]] - -1/factorial(6)) < tol + @test abs(f2c[[0,7]] - 0) < tol + @test abs(f2c[[0,8]] - 1/factorial(8)) < tol + @test abs(f2c[[0,9]] - 0) < tol + @test abs(f2c[[0,10]] - -1/factorial(10)) < tol + + @test abs(f2c[[1=>1]] - f2c[[1]]) < tol + @test abs(f2c[[1=>2]] - f2c[[2]]) < tol + @test abs(f2c[[1=>3]] - f2c[[3]]) < tol + @test abs(f2c[[1=>4]] - f2c[[4]]) < tol + @test abs(f2c[[1=>5]] - f2c[[5]]) < tol + @test abs(f2c[[1=>6]] - f2c[[6]]) < tol + @test abs(f2c[[1=>7]] - f2c[[7]]) < tol + @test abs(f2c[[1=>8]] - f2c[[8]]) < tol + @test abs(f2c[[1=>9]] - f2c[[9]]) < tol + @test abs(f2c[[1=>10]] - f2c[[10]]) < tol + + @test abs(f2c[[2=>1]] - f2c[[0,1]]) < tol + @test abs(f2c[[2=>2]] - f2c[[0,2]]) < tol + @test abs(f2c[[2=>3]] - f2c[[0,3]]) < tol + @test abs(f2c[[2=>4]] - f2c[[0,4]]) < tol + @test abs(f2c[[2=>5]] - f2c[[0,5]]) < tol + @test abs(f2c[[2=>6]] - f2c[[0,6]]) < tol + @test abs(f2c[[2=>7]] - f2c[[0,7]]) < tol + @test abs(f2c[[2=>8]] - f2c[[0,8]]) < tol + @test abs(f2c[[2=>9]] - f2c[[0,9]]) < tol + @test abs(f2c[[2=>10]] - f2c[[0,10]]) < tol f3 = sin(v[1]) + cos(v[2]) + exp(p[1]) - @test abs(f3[0] - 2) < tol - @test abs(f3[1] - 1) < tol - @test abs(f3[2] - 0) < tol - @test abs(f3[3] - -1/factorial(3)) < tol - @test abs(f3[4] - 0) < tol - @test abs(f3[5] - 1/factorial(5)) < tol - @test abs(f3[6] - 0) < tol - @test abs(f3[7] - -1/factorial(7)) < tol - @test abs(f3[8] - 0) < tol - @test abs(f3[9] - 1/factorial(9)) < tol - @test abs(f3[10] - 0) < tol - - @test abs(f3[0,0] - 2) < tol - @test abs(f3[0,1] - 0) < tol - @test abs(f3[0,2] - -1/factorial(2)) < tol - @test abs(f3[0,3] - 0) < tol - @test abs(f3[0,4] - 1/factorial(4)) < tol - @test abs(f3[0,5] - 0) < tol - @test abs(f3[0,6] - -1/factorial(6)) < tol - @test abs(f3[0,7] - 0) < tol - @test abs(f3[0,8] - 1/factorial(8)) < tol - @test abs(f3[0,9] - 0) < tol - @test abs(f3[0,10] - -1/factorial(10)) < tol - - @test abs(f3[0,0,0,0] - 2) < tol - @test abs(f3[0,0,0,1] - 1/factorial(1)) < tol - @test abs(f3[0,0,0,2] - 1/factorial(2)) < tol - @test abs(f3[0,0,0,3] - 1/factorial(3)) < tol - @test abs(f3[0,0,0,4] - 1/factorial(4)) < tol - @test abs(f3[0,0,0,5] - 1/factorial(5)) < tol - @test abs(f3[0,0,0,6] - 1/factorial(6)) < tol - @test abs(f3[0,0,0,7] - 1/factorial(7)) < tol - @test abs(f3[0,0,0,8] - 1/factorial(8)) < tol - @test abs(f3[0,0,0,9] - 1/factorial(9)) < tol - @test abs(f3[0,0,0,10] - 1/factorial(10)) < tol - - @test abs(f3[1=>1] - f3[1]) < tol - @test abs(f3[1=>2] - f3[2]) < tol - @test abs(f3[1=>3] - f3[3]) < tol - @test abs(f3[1=>4] - f3[4]) < tol - @test abs(f3[1=>5] - f3[5]) < tol - @test abs(f3[1=>6] - f3[6]) < tol - @test abs(f3[1=>7] - f3[7]) < tol - @test abs(f3[1=>8] - f3[8]) < tol - @test abs(f3[1=>9] - f3[9]) < tol - @test abs(f3[1=>10] - f3[10]) < tol - - @test abs(f3[2=>1] - f3[0,1]) < tol - @test abs(f3[2=>2] - f3[0,2]) < tol - @test abs(f3[2=>3] - f3[0,3]) < tol - @test abs(f3[2=>4] - f3[0,4]) < tol - @test abs(f3[2=>5] - f3[0,5]) < tol - @test abs(f3[2=>6] - f3[0,6]) < tol - @test abs(f3[2=>7] - f3[0,7]) < tol - @test abs(f3[2=>8] - f3[0,8]) < tol - @test abs(f3[2=>9] - f3[0,9]) < tol - @test abs(f3[2=>10] - f3[0,10]) < tol - - @test abs(f3[params=[1=>1]] - f3[0,0,0,1]) < tol - @test abs(f3[params=[1=>2]] - f3[0,0,0,2]) < tol - @test abs(f3[params=[1=>3]] - f3[0,0,0,3]) < tol - @test abs(f3[params=[1=>4]] - f3[0,0,0,4]) < tol - @test abs(f3[params=[1=>5]] - f3[0,0,0,5]) < tol - @test abs(f3[params=[1=>6]] - f3[0,0,0,6]) < tol - @test abs(f3[params=[1=>7]] - f3[0,0,0,7]) < tol - @test abs(f3[params=[1=>8]] - f3[0,0,0,8]) < tol - @test abs(f3[params=[1=>9]] - f3[0,0,0,9]) < tol - @test abs(f3[params=[1=>10]] - f3[0,0,0,10]) < tol + @test abs(f3[[0]] - 2) < tol + @test abs(f3[[1]] - 1) < tol + @test abs(f3[[2]] - 0) < tol + @test abs(f3[[3]] - -1/factorial(3)) < tol + @test abs(f3[[4]] - 0) < tol + @test abs(f3[[5]] - 1/factorial(5)) < tol + @test abs(f3[[6]] - 0) < tol + @test abs(f3[[7]] - -1/factorial(7)) < tol + @test abs(f3[[8]] - 0) < tol + @test abs(f3[[9]] - 1/factorial(9)) < tol + @test abs(f3[[10]] - 0) < tol + + @test abs(f3[[0,0]] - 2) < tol + @test abs(f3[[0,1]] - 0) < tol + @test abs(f3[[0,2]] - -1/factorial(2)) < tol + @test abs(f3[[0,3]] - 0) < tol + @test abs(f3[[0,4]] - 1/factorial(4)) < tol + @test abs(f3[[0,5]] - 0) < tol + @test abs(f3[[0,6]] - -1/factorial(6)) < tol + @test abs(f3[[0,7]] - 0) < tol + @test abs(f3[[0,8]] - 1/factorial(8)) < tol + @test abs(f3[[0,9]] - 0) < tol + @test abs(f3[[0,10]] - -1/factorial(10)) < tol + + @test abs(f3[[0,0,0,0]] - 2) < tol + @test abs(f3[[0,0,0,1]] - 1/factorial(1)) < tol + @test abs(f3[[0,0,0,2]] - 1/factorial(2)) < tol + @test abs(f3[[0,0,0,3]] - 1/factorial(3)) < tol + @test abs(f3[[0,0,0,4]] - 1/factorial(4)) < tol + @test abs(f3[[0,0,0,5]] - 1/factorial(5)) < tol + @test abs(f3[[0,0,0,6]] - 1/factorial(6)) < tol + @test abs(f3[[0,0,0,7]] - 1/factorial(7)) < tol + @test abs(f3[[0,0,0,8]] - 1/factorial(8)) < tol + @test abs(f3[[0,0,0,9]] - 1/factorial(9)) < tol + @test abs(f3[[0,0,0,10]] - 1/factorial(10)) < tol + + @test abs(f3[[1=>1]] - f3[[1]]) < tol + @test abs(f3[[1=>2]] - f3[[2]]) < tol + @test abs(f3[[1=>3]] - f3[[3]]) < tol + @test abs(f3[[1=>4]] - f3[[4]]) < tol + @test abs(f3[[1=>5]] - f3[[5]]) < tol + @test abs(f3[[1=>6]] - f3[[6]]) < tol + @test abs(f3[[1=>7]] - f3[[7]]) < tol + @test abs(f3[[1=>8]] - f3[[8]]) < tol + @test abs(f3[[1=>9]] - f3[[9]]) < tol + @test abs(f3[[1=>10]] - f3[[10]]) < tol + + @test abs(f3[[2=>1]]- f3[[0,1]]) < tol + @test abs(f3[[2=>2]]- f3[[0,2]]) < tol + @test abs(f3[[2=>3]]- f3[[0,3]]) < tol + @test abs(f3[[2=>4]]- f3[[0,4]]) < tol + @test abs(f3[[2=>5]]- f3[[0,5]]) < tol + @test abs(f3[[2=>6]]- f3[[0,6]]) < tol + @test abs(f3[[2=>7]]- f3[[0,7]]) < tol + @test abs(f3[[2=>8]]- f3[[0,8]]) < tol + @test abs(f3[[2=>9]]- f3[[0,9]]) < tol + @test abs(f3[[2=>10]]- f3[[0,10]]) < tol + + @test abs(f3[params=[1=>1]] - f3[[0,0,0,1]]) < tol + @test abs(f3[params=[1=>2]] - f3[[0,0,0,2]]) < tol + @test abs(f3[params=[1=>3]] - f3[[0,0,0,3]]) < tol + @test abs(f3[params=[1=>4]] - f3[[0,0,0,4]]) < tol + @test abs(f3[params=[1=>5]] - f3[[0,0,0,5]]) < tol + @test abs(f3[params=[1=>6]] - f3[[0,0,0,6]]) < tol + @test abs(f3[params=[1=>7]] - f3[[0,0,0,7]]) < tol + @test abs(f3[params=[1=>8]] - f3[[0,0,0,8]]) < tol + @test abs(f3[params=[1=>9]] - f3[[0,0,0,9]]) < tol + @test abs(f3[params=[1=>10]] - f3[[0,0,0,10]]) < tol @@ -1037,7 +1037,7 @@ end @testset "@FastGTPSA - Functions: identities, using TPSs" begin d = Descriptor(1, 5) t = TPS(use=d) - t[0] = 0.5; t[1] = 2; t[2] = 3; t[3] = 4; t[4] = 5; t[5] = 6 + t[0] = 0.5; t[[1]] = 2; t[[2]] = 3; t[[3]] = 4; t[[4]] = 5; t[[5]] = 6 tol = 1e-10 @@ -1094,7 +1094,7 @@ end @test @FastGTPSA(norm(complex(t,t) - (t+im*t))) < tol t = ComplexTPS(t) - t[0] = 0.5+0.5im; t[1] = 2+2im; t[2] = 3+3im; t[3] = 4+4im; t[4] = 5+5im; t[5] = 6+6im + t[0] = 0.5+0.5im; t[[1]] = 2+2im; t[[2]] = 3+3im; t[[3]] = 4+4im; t[[4]] = 5+5im; t[[5]] = 6+6im @test @FastGTPSA(norm(sin(t)^2+cos(t)^2 - 1)) < tol @test @FastGTPSA(norm(1/sin(t) - csc(t))) < tol @test @FastGTPSA(norm(1/cos(t) - sec(t))) < tol diff --git a/test/type_stable.jl b/test/type_stable.jl index 4d5d2abd..c6c80a79 100644 --- a/test/type_stable.jl +++ b/test/type_stable.jl @@ -131,88 +131,89 @@ function type_stable_test() # Now do operators # Test definition of 1-norm: tn = zero(t1) - tn[0] = 1; tn[1] = 2; tn[2] = 3; tn[3] = 4; tn[4] = 5; tn[5] = 6 + tn[0] = 1; tn[[1]] = 2; tn[[2]] = 3; tn[[3]] = 4; tn[[4]] = 5; tn[[5]] = 6 tcn = zero(ct1) - tcn[0] = 1+1im; tcn[1] = 2+2im; tcn[2] = 3+3im; tcn[3] = 4+4im; tcn[4] = 5+5im; tcn[5] = 6+6im + tcn[0] = 1+1im; tcn[[1]] = 2+2im; tcn[[2]] = 3+3im; tcn[[3]] = 4+4im; tcn[[4]] = 5+5im; tcn[[5]] = 6+6im + norm(tn) == sum([i for i in 1:6]) norm(tcn) == sum([abs(i+i*im) for i in 1:6]) # TPS: - norm(t1 + t2 - t3) - norm(t2 + t1 - t3) - norm(t1 + 2 - t3) - norm(2 + t1 - t3) - norm(t3 - t2 - t1) - norm(t2 - t3 - -t1) - norm(t3 - 2 - t1) - norm(2 - t3 - -t1) - norm(t2 * t3 - 6) - norm(t3 * t2 - 6) - norm(t2 * 5 - 10) - norm(5 * t2 - 10 * t1) - norm(t1 / t2 - 1/2) - norm(t2 / t1 - 2) - norm(1 / t2 - 1/2) - norm(t2 / 3 - 2/3) - norm(t2 / t2 - t1) - norm(t2 / t2 - 1) - norm(t2 ^ t3 - 8) - norm(t3 ^ t2 - 9) - norm(t2 ^ 3 - 8) - norm(t2 ^ (1/2) - sqrt(2)) - norm(t2 ^ (1/2) - sqrt(t2)) - norm(2 ^ t3 - 8) - norm(inv(t3) - 1/t3) - norm(inv(t3) - 1/3) + norm(t1 + t2 - t3) < tol + norm(t2 + t1 - t3) < tol + norm(t1 + 2 - t3) < tol + norm(2 + t1 - t3) < tol + norm(t3 - t2 - t1) < tol + norm(t2 - t3 - -t1) < tol + norm(t3 - 2 - t1) < tol + norm(2 - t3 - -t1) < tol + norm(t2 * t3 - 6) < tol + norm(t3 * t2 - 6) < tol + norm(t2 * 5 - 10) < tol + norm(5 * t2 - 10 * t1) < tol + norm(t1 / t2 - 1/2) < tol + norm(t2 / t1 - 2) < tol + norm(1 / t2 - 1/2) < tol + norm(t2 / 3 - 2/3) < tol + norm(t2 / t2 - t1) < tol + norm(t2 / t2 - 1) < tol + norm(t2 ^ t3 - 8) < tol + norm(t3 ^ t2 - 9) < tol + norm(t2 ^ 3 - 8) < tol + norm(t2 ^ (1/2) - sqrt(2)) < tol + norm(t2 ^ (1/2) - sqrt(t2)) < tol + norm(2 ^ t3 - 8) < tol + norm(inv(t3) - 1/t3) < tol + norm(inv(t3) - 1/3) < tol # ComplexTPS: - norm(ct1 + ct2 - ct3) - norm(ct2 + ct1 - ct3) - norm(ct1 + (2+2im) - ct3) - norm((2+2im) + ct1 - ct3) - norm(ct3 - ct2 - ct1) - norm(ct2 - ct3 - -ct1) - norm(ct3 - (2+2im) - ct1) - norm((2+2im) - ct3 - -ct1) - norm(ct2 * ct3 - (2+2im)*(3+3im)) - norm(ct3 * ct2 - (2+2im)*(3+3im)) - norm(ct2 * 5 - (10+10im)) - norm(5 * ct2 - (10 * ct1)) - norm(ct1 / ct2 - (1+im)/(2+2im)) - norm(ct2 / ct1 - 2) - norm(1 / ct2 - 1/(2+2im)) - norm(ct2 / 3 - (2+2im)/3) - norm(ct2 / ct2 - 1) - norm(ct2 ^ ct3 - (2+2im)^(3+3im)) - norm(ct3 ^ ct2 - (3+3im)^(2+2im)) - norm(ct2 ^ 3 - (2+2im)^3) - norm(ct2 ^ (1/2) - sqrt(2+2im)) - norm(ct2 ^ (1/2) - sqrt(ct2)) - norm(2 ^ ct3 - 2^(3+3im)) - norm(inv(ct3) - 1/ct3) - norm(inv(ct3) - 1/(3+3im)) + norm(ct1 + ct2 - ct3) < tol + norm(ct2 + ct1 - ct3) < tol + norm(ct1 + (2+2im) - ct3) < tol + norm((2+2im) + ct1 - ct3) < tol + norm(ct3 - ct2 - ct1) < tol + norm(ct2 - ct3 - -ct1) < tol + norm(ct3 - (2+2im) - ct1) < tol + norm((2+2im) - ct3 - -ct1) < tol + norm(ct2 * ct3 - (2+2im)*(3+3im)) < tol + norm(ct3 * ct2 - (2+2im)*(3+3im)) < tol + norm(ct2 * 5 - (10+10im)) < tol + norm(5 * ct2 - (10 * ct1)) < tol + norm(ct1 / ct2 - (1+im)/(2+2im)) < tol + norm(ct2 / ct1 - 2) < tol + norm(1 / ct2 - 1/(2+2im)) < tol + norm(ct2 / 3 - (2+2im)/3) < tol + norm(ct2 / ct2 - 1) < tol + norm(ct2 ^ ct3 - (2+2im)^(3+3im)) < tol + norm(ct3 ^ ct2 - (3+3im)^(2+2im)) < tol + norm(ct2 ^ 3 - (2+2im)^3) < tol + norm(ct2 ^ (1/2) - sqrt(2+2im)) < tol + norm(ct2 ^ (1/2) - sqrt(ct2)) < tol + norm(2 ^ ct3 - 2^(3+3im)) < tol + norm(inv(ct3) - 1/ct3) < tol + norm(inv(ct3) - 1/(3+3im)) < tol # Promotion of TPS to ComplexTPS - norm(t1 + ct2 - (1 + (2+2im))) - norm(ct2 + t1 - (1 + (2+2im))) - norm(t1 + (2+2im) - (1 + (2+2im))) - norm((2+2im) + t1 - (1 + (2+2im))) - norm(t3 - ct2 - (3 - (2+2im))) - norm(ct2 - t3 - ((2+2im) - 3)) - norm(t3 - (2+2im) - (3 - (2+2im))) - norm((2+2im) - t3 - ((2+2im) - 3)) - norm(t2 * ct3 - 2 * (3+3im)) - norm(ct3 * t2 - 2 * (3+3im)) - norm(t2 * (3+3im) - 2 * (3+3im)) - norm((3+3im) * t2 - 2 * (3+3im)) - norm(t2 / ct3 - 2/(3+3im)) - norm(ct3 / t2 - (3+3im)/2) - norm(t2 / (3+3im) - 2/(3+3im)) - norm((3+3im) / t2 - (3+3im)/2) - norm(t2 ^ ct3 - 2^(3+3im)) - norm(ct3 ^ t2 - (3+3im)^2) - norm(t2 ^ (3+3im) - 2^(3+3im)) - norm((3+3im)^t2 - (3+3im)^2) + norm(t1 + ct2 - (1 + (2+2im))) < tol + norm(ct2 + t1 - (1 + (2+2im))) < tol + norm(t1 + (2+2im) - (1 + (2+2im))) < tol + norm((2+2im) + t1 - (1 + (2+2im))) < tol + norm(t3 - ct2 - (3 - (2+2im))) < tol + norm(ct2 - t3 - ((2+2im) - 3)) < tol + norm(t3 - (2+2im) - (3 - (2+2im))) < tol + norm((2+2im) - t3 - ((2+2im) - 3)) < tol + norm(t2 * ct3 - 2 * (3+3im)) < tol + norm(ct3 * t2 - 2 * (3+3im)) < tol + norm(t2 * (3+3im) - 2 * (3+3im)) < tol + norm((3+3im) * t2 - 2 * (3+3im)) < tol + norm(t2 / ct3 - 2/(3+3im)) < tol + norm(ct3 / t2 - (3+3im)/2) < tol + norm(t2 / (3+3im) - 2/(3+3im)) < tol + norm((3+3im) / t2 - (3+3im)/2) < tol + norm(t2 ^ ct3 - 2^(3+3im)) < tol + norm(ct3 ^ t2 - (3+3im)^2) < tol + norm(t2 ^ (3+3im) - 2^(3+3im)) < tol + norm((3+3im)^t2 - (3+3im)^2) < tol d = Descriptor(1, 5) t = TPS(use=d) @@ -227,75 +228,78 @@ function type_stable_test() t3[0] = 3 - norm(abs(-t) - abs(-v) ) - norm(sqrt(t) - sqrt(v)) - norm(exp(t) - exp(v)) - norm(log(t) - log(v)) - norm(sin(t) - sin(v)) - norm(cos(t) - cos(v)) - norm(tan(t) - tan(v)) - norm(csc(t) - csc(v)) - norm(sec(t) - sec(v)) - norm(cot(t) - cot(v)) - norm(sinc(t) - sinc(v)) - norm(sinh(t) - sinh(v)) - norm(cosh(t) - cosh(v)) - norm(tanh(t) - tanh(v)) - norm(csch(t) - csch(v)) - norm(sech(t) - sech(v)) - norm(coth(t) - coth(v)) - norm(asin(t) - asin(v)) - norm(acos(t) - acos(v)) - norm(atan(t) - atan(v)) - norm(acsc(1/t) - acsc(1/v)) - norm(asec(1/t) - asec(1/v)) - norm(acot(1/t) - acot(1/v)) - norm(asinh(t) - asinh(v)) - norm(acosh(1/t) - acosh(1/v)) - norm(atanh(t) - atanh(v)) - norm(acsch(1/t) - acsch(1/v)) - norm(asech(t) - asech(v)) - norm(acoth(1/t) - acoth(1/v)) - norm(asinc(t/pi) - asin(v)/(v)) - norm(asinhc(t/pi) - asinh(v)/(v)) - norm(zero(t) - zero(v)) - norm(real(t) - real(v)) - norm(imag(t) - imag(v)) - norm(conj(t) - conj(v)) - norm(sinhc(t/pi) - sinh(v)/v) - norm(erf(t) - erf(v)) - norm(erfc(t) - erfc(v)) - norm(-im*erf(t*im) - erfi(v)) - norm(atan(t3,t2) - atan(3,2)) - norm(atan(t3,2) - atan(3,2)) - norm(atan(3,t2) - atan(3,2)) - norm(atan(t3,-t2) - atan(3,-2)) - norm(atan(t3,-2) - atan(3,-2)) - norm(atan(3,-t2) - atan(3,-2)) - norm(atan(-t3,-t2) - atan(-3,-2)) - norm(atan(-t3,-2) - atan(-3,-2)) - norm(atan(-3,-t2) - atan(-3,-2)) - norm(atan(-t3,t2) - atan(-3,2)) - norm(atan(-t3,2) - atan(-3,2)) - norm(atan(-3,t2) - atan(-3,2)) - norm(hypot(t2,t3) - hypot(2,3)) - norm(hypot(2,t3) - hypot(2,3)) - norm(hypot(t2,3) - hypot(2,3)) - norm(hypot(t1,t2,t3) - hypot(1,2,3)) - norm(hypot(1, t2, t3) - hypot(1,2,3)) - norm(hypot(t1, 2, t3) - hypot(1,2,3)) - norm(hypot(t1, t2, 3) - hypot(1,2,3)) - norm(hypot(1, 2, t3) - hypot(1,2,3)) - norm(hypot(1, t2, 3) - hypot(1,2,3)) - norm(hypot(t1, 2, 3) - hypot(1,2,3)) - norm(angle(t2) - angle(2)) - norm(angle(-t2) - angle(-2)) - norm(complex(t3) - complex(3)) - norm(complex(t2,t3) - complex(2,3)) - norm(polar(t2) - (abs(2)+im*atan(0,2))) - norm(polar(-t1) - (abs(-1)+im*atan(0,-1))) - norm(rect(t2) - (2*cos(0) + 2*sin(0))) - norm(rect(-t1) - (-1*cos(0) + -1*sin(0))) + norm(abs(-t) - abs(-v) ) < tol + norm(sqrt(t) - sqrt(v)) < tol + norm(exp(t) - exp(v)) < tol + norm(log(t) - log(v)) < tol + norm(sin(t) - sin(v)) < tol + norm(cos(t) - cos(v)) < tol + norm(tan(t) - tan(v)) < tol + norm(csc(t) - csc(v)) < tol + norm(sec(t) - sec(v)) < tol + norm(cot(t) - cot(v)) < tol + norm(sinc(t) - sinc(v)) < tol + norm(sinh(t) - sinh(v)) < tol + norm(cosh(t) - cosh(v)) < tol + norm(tanh(t) - tanh(v)) < tol + norm(csch(t) - csch(v)) < tol + norm(sech(t) - sech(v)) < tol + norm(coth(t) - coth(v)) < tol + norm(asin(t) - asin(v)) < tol + norm(acos(t) - acos(v)) < tol + norm(atan(t) - atan(v)) < tol + norm(acsc(1/t) - acsc(1/v)) < tol + norm(asec(1/t) - asec(1/v)) < tol + norm(acot(1/t) - acot(1/v)) < tol + norm(asinh(t) - asinh(v)) < tol + norm(acosh(1/t) - acosh(1/v)) < tol + norm(atanh(t) - atanh(v)) < tol + norm(acsch(1/t) - acsch(1/v)) < tol + norm(asech(t) - asech(v)) < tol + norm(acoth(1/t) - acoth(1/v)) < tol + norm(asinc(t/pi) - asin(v)/(v)) < tol + norm(asinhc(t/pi) - asinh(v)/(v)) < tol + norm(zero(t) - zero(v)) < tol + norm(real(t) - real(v)) < tol + norm(imag(t) - imag(v)) < tol + norm(conj(t) - conj(v)) < tol + norm(sinhc(t/pi) - sinh(v)/v) < tol + norm(erf(t) - erf(v)) < tol + norm(erfc(t) - erfc(v)) < tol + norm(-im*erf(t*im) - erfi(v)) < tol + + norm(atan(t3,t2) - atan(3,2)) < tol + norm(atan(t3,2) - atan(3,2)) < tol + norm(atan(3,t2) - atan(3,2)) < tol + norm(atan(t3,-t2) - atan(3,-2)) < tol + norm(atan(t3,-2) - atan(3,-2)) < tol + norm(atan(3,-t2) - atan(3,-2)) < tol + norm(atan(-t3,-t2) - atan(-3,-2)) < tol + norm(atan(-t3,-2) - atan(-3,-2)) < tol + norm(atan(-3,-t2) - atan(-3,-2)) < tol + norm(atan(-t3,t2) - atan(-3,2)) < tol + norm(atan(-t3,2) - atan(-3,2)) < tol + norm(atan(-3,t2) - atan(-3,2)) < tol + + norm(hypot(t2,t3) - hypot(2,3)) < tol + norm(hypot(2,t3) - hypot(2,3)) < tol + norm(hypot(t2,3) - hypot(2,3)) < tol + norm(hypot(t1,t2,t3) - hypot(1,2,3)) < tol + norm(hypot(1, t2, t3) - hypot(1,2,3)) < tol + norm(hypot(t1, 2, t3) - hypot(1,2,3)) < tol + norm(hypot(t1, t2, 3) - hypot(1,2,3)) < tol + norm(hypot(1, 2, t3) - hypot(1,2,3)) < tol + norm(hypot(1, t2, 3) - hypot(1,2,3)) < tol + norm(hypot(t1, 2, 3) - hypot(1,2,3)) < tol + norm(angle(t2) - angle(2)) < tol + norm(angle(-t2) - angle(-2)) < tol + norm(complex(t3) - complex(3)) < tol + norm(complex(t2,t3) - complex(2,3)) < tol + norm(polar(t2) - (abs(2)+im*atan(0,2))) < tol + norm(polar(-t1) - (abs(-1)+im*atan(0,-1))) < tol + norm(rect(t2) - (2*cos(0) + im*2*sin(0))) < tol + norm(rect(-t1) - (-1*cos(0) + im*-1*sin(0))) < tol + v = 0.5+0.5im t = ComplexTPS(t) @@ -306,196 +310,200 @@ function type_stable_test() ct2[0] = 2 + 2im ct3 = zero(ct1) ct3[0] = 3 + 3im - norm(abs(-t) - abs(-v) ) - norm(sqrt(t) - sqrt(v)) - norm(exp(t) - exp(v)) - norm(log(t) - log(v)) - norm(sin(t) - sin(v)) - norm(cos(t) - cos(v)) - norm(tan(t) - tan(v)) - norm(csc(t) - csc(v)) - norm(sec(t) - sec(v)) - norm(cot(t) - cot(v)) - norm(sinc(t) - sinc(v)) - norm(sinh(t) - sinh(v)) - norm(cosh(t) - cosh(v)) - norm(tanh(t) - tanh(v)) - norm(csch(t) - csch(v)) - norm(sech(t) - sech(v)) - norm(coth(t) - coth(v)) - norm(asin(t) - asin(v)) - norm(acos(t) - acos(v)) - norm(atan(t) - atan(v)) - norm(acsc(t) - acsc(v)) - norm(asec(t) - asec(v)) - norm(acot(t) - acot(v)) - norm(asinh(t) - asinh(v)) - norm(acosh(t) - acosh(v)) - norm(atanh(t) - atanh(v)) - norm(acsch(t) - acsch(v)) - norm(asech(t) - asech(v)) - norm(acoth(t) - acoth(v)) - norm(asinc(t) - asin(v)/v) - norm(asinhc(t) - asinh(v)/v) - norm(zero(t) - zero(v)) - norm(real(t) - real(v)) - norm(imag(t) - imag(v)) - norm(conj(t) - conj(v)) - norm(sinhc(t/pi) - sinh(v)/v) - norm(erf(t) - erf(v)) - norm(erfc(t) - erfc(v)) - norm(-im*erf(t*im) - erfi(v)) - norm(hypot(ct2,ct3) - hypot(2+2im,3+3im)) - norm(hypot(2+2im,ct3) - hypot(2+2im,3+3im)) - norm(hypot(ct2,3+3im) - hypot(2+2im,3+3im)) - norm(hypot(ct1,ct2,ct3) - hypot(1+1im,2+2im,3+3im)) - norm(hypot(1+1im, ct2, ct3) - hypot(1+1im,2+2im,3+3im)) - norm(hypot(ct1, 2+2im, ct3) - hypot(1+1im,2+2im,3+3im)) - norm(hypot(ct1, ct2, 3+3im) - hypot(1+1im,2+2im,3+3im)) - norm(hypot(1+1im, 2+2im, ct3) - hypot(1+1im,2+2im,3+3im)) - norm(hypot(1+1im, ct2, 3+3im) - hypot(1+1im,2+2im,3+3im)) - norm(hypot(ct1, 2+2im, 3+3im) - hypot(1+1im,2+2im,3+3im)) - norm(angle(t2+im*t3) - angle(2+3im)) - norm(angle(t2-im*t3) - angle(2-3im)) - norm(angle(-t2-im*t3) - angle(-2-3im)) - norm(angle(-t2+im*t3) - angle(-2+3im)) - norm(angle(ct2) - angle(2+2im)) - norm(angle(-ct2) - angle(-2-2im)) - norm(complex(ct3) - complex(3+3im)) - norm(polar(ct2) - (abs(2+2im)+im*angle(2+2im))) - norm(polar(-ct1) - (abs(-1-im)+im*angle(-1-im))) - norm(rect(ct2) - (2*cos(2) + 2*sin(2))) - norm(rect(-ct1) - (-1*cos(-1) + -1*sin(-1))) + norm(abs(-t) - abs(-v) ) < tol + norm(sqrt(t) - sqrt(v)) < tol + norm(exp(t) - exp(v)) < tol + norm(log(t) - log(v)) < tol + norm(sin(t) - sin(v)) < tol + norm(cos(t) - cos(v)) < tol + norm(tan(t) - tan(v)) < tol + norm(csc(t) - csc(v)) < tol + norm(sec(t) - sec(v)) < tol + norm(cot(t) - cot(v)) < tol + norm(sinc(t) - sinc(v)) < tol + norm(sinh(t) - sinh(v)) < tol + norm(cosh(t) - cosh(v)) < tol + norm(tanh(t) - tanh(v)) < tol + norm(csch(t) - csch(v)) < tol + norm(sech(t) - sech(v)) < tol + norm(coth(t) - coth(v)) < tol + + norm(asin(t) - asin(v)) < tol + norm(acos(t) - acos(v)) < tol + norm(atan(t) - atan(v)) < tol + norm(acsc(t) - acsc(v)) < tol + norm(asec(t) - asec(v)) < tol + norm(acot(t) - acot(v)) < tol + norm(asinh(t) - asinh(v)) < tol + norm(acosh(t) - acosh(v)) < tol + norm(atanh(t) - atanh(v)) < tol + norm(acsch(t) - acsch(v)) < tol + norm(asech(t) - asech(v)) < tol + norm(acoth(t) - acoth(v)) < tol + norm(asinc(t/pi) - asin(v)/v) < tol + norm(asinhc(t/pi) - asinh(v)/v) < tol + + norm(zero(t) - zero(v)) < tol + norm(real(t) - real(v)) < tol + norm(imag(t) - imag(v)) < tol + norm(conj(t) - conj(v)) < tol + norm(sinhc(t/pi) - sinh(v)/v) < tol + norm(erf(t) - erf(v)) < tol + norm(erfc(t) - erfc(v)) < tol + norm(-im*erf(t*im) - erfi(v)) < tol + norm(hypot(ct2,ct3) - hypot(2+2im,3+3im)) < tol + norm(hypot(2+2im,ct3) - hypot(2+2im,3+3im)) < tol + norm(hypot(ct2,3+3im) - hypot(2+2im,3+3im)) < tol + norm(hypot(ct1,ct2,ct3) - hypot(1+1im,2+2im,3+3im)) < tol + norm(hypot(1+1im, ct2, ct3) - hypot(1+1im,2+2im,3+3im)) < tol + norm(hypot(ct1, 2+2im, ct3) - hypot(1+1im,2+2im,3+3im)) < tol + norm(hypot(ct1, ct2, 3+3im) - hypot(1+1im,2+2im,3+3im)) < tol + norm(hypot(1+1im, 2+2im, ct3) - hypot(1+1im,2+2im,3+3im)) < tol + norm(hypot(1+1im, ct2, 3+3im) - hypot(1+1im,2+2im,3+3im)) < tol + norm(hypot(ct1, 2+2im, 3+3im) - hypot(1+1im,2+2im,3+3im)) < tol + + norm(angle(t2+im*t3) - angle(2+3im)) < tol + norm(angle(t2-im*t3) - angle(2-3im)) < tol + norm(angle(-t2-im*t3) - angle(-2-3im)) < tol + norm(angle(-t2+im*t3) - angle(-2+3im)) < tol + norm(angle(ct2) - angle(2+2im)) < tol + norm(angle(-ct2) - angle(-2-2im)) < tol + norm(complex(ct3) - complex(3+3im)) < tol + norm(polar(ct2) - (abs(2+2im)+im*angle(2+2im))) < tol + norm(polar(-ct1) - (abs(-1-im)+im*angle(-1-im))) < tol + norm(rect(ct2) - (2*cos(2) + im*2*sin(2))) < tol + norm(rect(-ct1) - (-1*cos(-1) + im*-1*sin(-1))) < tol + # Hypot, mixing TPS with ComplexTPS - norm(hypot(ct1, ct2, t3) - hypot(1+1im,2+2im,3)) - norm(hypot(ct1, t2, ct3) - hypot(1+1im,2,3+3im)) - norm(hypot(t1, ct2, ct3) - hypot(1,2+2im,3+3im)) - norm(hypot(ct1, t2, t3) - hypot(1+1im,2,3)) - norm(hypot(t1, ct2, t3) - hypot(1,2+2im,3)) - norm(hypot(t1, t2, ct3) - hypot(1,2,3+3im)) - norm(hypot(ct1,t2,3+3im) - hypot(1+1im,2,3+3im)) - norm(hypot(t1, ct2, 3+3im) - hypot(1,2+2im,3+3im)) - norm(hypot(ct1,2+2im,t3) - hypot(1+1im,2+2im,3)) - norm(hypot(t1,2+2im,ct3) - hypot(1,2+2im,3+3im)) - norm(hypot(1+1im,ct2,t3) - hypot(1+1im,2+2im,3)) - norm(hypot(1+1im, t2, ct3) - hypot(1+1im,2,3+3im)) - norm(hypot(t1,t2,3+3im) - hypot(1,2,3+3im)) - norm(hypot(t1,2+2im,t3) - hypot(1,2+2im,3)) - norm(hypot(1+1im,t2,t3) - hypot(1+1im,2,3)) - norm(hypot(t1,2,3+3im) - hypot(1,2,3+3im)) - norm(hypot(1,t2,3+3im) - hypot(1,2,3+3im)) - norm(hypot(1+1im,2,t3) - hypot(1+1im,2,3)) + norm(hypot(ct1, ct2, t3) - hypot(1+1im,2+2im,3)) < tol + norm(hypot(ct1, t2, ct3) - hypot(1+1im,2,3+3im)) < tol + norm(hypot(t1, ct2, ct3) - hypot(1,2+2im,3+3im)) < tol + norm(hypot(ct1, t2, t3) - hypot(1+1im,2,3)) < tol + norm(hypot(t1, ct2, t3) - hypot(1,2+2im,3)) < tol + norm(hypot(t1, t2, ct3) - hypot(1,2,3+3im)) < tol + norm(hypot(ct1,t2,3+3im) - hypot(1+1im,2,3+3im)) < tol + norm(hypot(t1, ct2, 3+3im) - hypot(1,2+2im,3+3im)) < tol + norm(hypot(ct1,2+2im,t3) - hypot(1+1im,2+2im,3)) < tol + norm(hypot(t1,2+2im,ct3) - hypot(1,2+2im,3+3im)) < tol + norm(hypot(1+1im,ct2,t3) - hypot(1+1im,2+2im,3)) < tol + norm(hypot(1+1im, t2, ct3) - hypot(1+1im,2,3+3im)) < tol + norm(hypot(t1,t2,3+3im) - hypot(1,2,3+3im)) < tol + norm(hypot(t1,2+2im,t3) - hypot(1,2+2im,3)) < tol + norm(hypot(1+1im,t2,t3) - hypot(1+1im,2,3)) < tol + norm(hypot(t1,2,3+3im) - hypot(1,2,3+3im)) < tol + norm(hypot(1,t2,3+3im) - hypot(1,2,3+3im)) < tol + norm(hypot(1+1im,2,t3) - hypot(1+1im,2,3)) < tol d = Descriptor(1, 5) t = TPS(use=d) - t[0] = 0.5; t[1] = 2; t[2] = 3; t[3] = 4; t[4] = 5; t[5] = 6 + t[0] = 0.5; t[[1]] = 2; t[[2]] = 3; t[[3]] = 4; t[[4]] = 5; t[[5]] = 6 tol = 1e-10 - norm(sin(t)^2+cos(t)^2 - 1) - norm(1/sin(t) - csc(t)) - norm(1/cos(t) - sec(t)) - norm(1/tan(t) - cot(t)) - norm(sin(t)/cos(t) - tan(t)) - norm(cos(2*t) - cos(t)^2 + sin(t)^2) - norm(sec(t)^2 - 1 - tan(t)^2) - norm(sin(t/2) - sqrt((1-cos(t))/2)) - norm(cos(t/2) - sqrt((1+cos(t))/2)) - norm(sqrt(t^2) - abs(t)) - norm(csc(t)^2 - cot(t)^2 - 1) - norm(exp(log(t)) - t) - norm(log(exp(t)) - t) - norm(log(exp(t)) - exp(log(t))) - norm(log(t^2) - 2*log(t)) - norm(5*log(t) - log(t^5)) - norm(t*log(5) - log(5^t)) - norm(sinc(t) - sin(pi*t)/(pi*t)) - norm(sinhc(t/pi) - sinh(t)/t) - norm(exp(im*t) - cos(t) - im*sin(t)) - norm(real(exp(im*t)) - cos(t)) - norm(imag(exp(im*t)) - sin(t)) - norm(sinh(t) - (exp(t) - exp(-t))/2) - norm(cosh(t) - (exp(t) + exp(-t))/2) - norm(tanh(t) - sinh(t)/cosh(t)) - norm(csch(t) - 1/sinh(t)) - norm(sech(t) - 1/cosh(t)) - norm(coth(t) - cosh(t)/sinh(t)) - norm(coth(t) - 1/tanh(t)) - norm(cosh(t)^2 - sinh(t)^2 - 1) - norm(1 - tanh(t)^2 - sech(t)^2) - norm(coth(t)^2 - 1 - csch(t)^2) - norm(asin(sin(t)) - t) - norm(acos(cos(t)) - t) - norm(atan(tan(t)) - t) - norm(acsc(1/t) - asin(t)) - norm(asec(1/t) - acos(t)) - norm(acot(1/t) - atan(t)) - norm(asinh(sinh(t)) - t) - norm(acosh(cosh(t)) - t) - norm(atanh(tanh(t)) - t) - norm(acsch(t) - asinh(1/t)) - norm(asech(t) - acosh(1/t)) - norm(acoth(1/t) - atanh(t)) - norm(asinc(t/pi) - asin(t)/t) - norm(asinhc(t/pi) - asinh(t)/t) - norm(erfc(t) - 1 + erf(t)) - norm(erf(-t) + erf(t)) - norm(angle(t)) - norm(complex(t) - t) - norm(complex(t,t) - (t+im*t)) + norm(sin(t)^2+cos(t)^2 - 1) < tol + norm(1/sin(t) - csc(t)) < tol + norm(1/cos(t) - sec(t)) < tol + norm(1/tan(t) - cot(t)) < tol + norm(sin(t)/cos(t) - tan(t)) < tol + norm(cos(2*t) - cos(t)^2 + sin(t)^2) < tol + norm(sec(t)^2 - 1 - tan(t)^2) < tol + norm(sin(t/2) - sqrt((1-cos(t))/2)) < tol + norm(cos(t/2) - sqrt((1+cos(t))/2)) < tol + norm(sqrt(t^2) - abs(t)) < tol + norm(csc(t)^2 - cot(t)^2 - 1) < tol + norm(exp(log(t)) - t) < tol + norm(log(exp(t)) - t) < tol + norm(log(exp(t)) - exp(log(t))) < tol + norm(log(t^2) - 2*log(t)) < tol + norm(5*log(t) - log(t^5)) < tol + norm(t*log(5) - log(5^t)) < tol + norm(sinc(t) - sin(pi*t)/(pi*t)) < tol + norm(sinhc(t/pi) - sinh(t)/t) < tol + norm(exp(im*t) - cos(t) - im*sin(t)) < tol + norm(real(exp(im*t)) - cos(t)) < tol + norm(imag(exp(im*t)) - sin(t)) < tol + norm(sinh(t) - (exp(t) - exp(-t))/2) < tol + norm(cosh(t) - (exp(t) + exp(-t))/2) < tol + norm(tanh(t) - sinh(t)/cosh(t)) < tol + norm(csch(t) - 1/sinh(t)) < tol + norm(sech(t) - 1/cosh(t)) < tol + norm(coth(t) - cosh(t)/sinh(t)) < tol + norm(coth(t) - 1/tanh(t)) < tol + norm(cosh(t)^2 - sinh(t)^2 - 1) < tol + norm(1 - tanh(t)^2 - sech(t)^2) < tol + norm(coth(t)^2 - 1 - csch(t)^2) < tol + norm(asin(sin(t)) - t) < tol + norm(acos(cos(t)) - t) < tol + norm(atan(tan(t)) - t) < tol + norm(acsc(1/t) - asin(t)) < tol + norm(asec(1/t) - acos(t)) < tol + norm(acot(1/t) - atan(t)) < tol + norm(asinh(sinh(t)) - t) < tol + norm(acosh(cosh(t)) - t) < tol + norm(atanh(tanh(t)) - t) < tol + norm(acsch(t) - asinh(1/t)) < tol + norm(asech(t) - acosh(1/t)) < tol + norm(acoth(1/t) - atanh(t)) < tol + norm(asinc(t/pi) - asin(t)/t) < tol + norm(asinhc(t/pi) - asinh(t)/t) < tol + norm(erfc(t) - 1 + erf(t)) < tol + norm(erf(-t) + erf(t)) < tol + norm(angle(t)) < tol + norm(complex(t) - t) < tol + norm(complex(t,t) - (t+im*t)) < tol t = ComplexTPS(t) - t[0] = 0.5+0.5im; t[1] = 2+2im; t[2] = 3+3im; t[3] = 4+4im; t[4] = 5+5im; t[5] = 6+6im - norm(sin(t)^2+cos(t)^2 - 1) - norm(1/sin(t) - csc(t)) - norm(1/cos(t) - sec(t)) - norm(1/tan(t) - cot(t)) - norm(sin(t)/cos(t) - tan(t)) - norm(cos(2*t) - cos(t)^2 + sin(t)^2) - norm(sec(t)^2 - 1 - tan(t)^2) - norm(sin(t/2) - sqrt((1-cos(t))/2)) - norm(cos(t/2) - sqrt((1+cos(t))/2)) - norm(sqrt(t^2) - t) - norm(csc(t)^2 - cot(t)^2 - 1) - norm(exp(log(t)) - t) - norm(log(exp(t)) - t) - norm(log(exp(t)) - exp(log(t))) - norm(log(t^2) - 2*log(t)) - norm(5*log(t) - log(t^5) - 2*pi*im) - norm(t*log(5) - log(5^t)) - norm(sinc(t/pi) - sin(t)/t) - norm(sinhc(t/pi) - sinh(t)/t) - norm(exp(im*t) - cos(t) - im*sin(t)) - norm(sinh(t) - (exp(t) - exp(-t))/2) - norm(cosh(t) - (exp(t) + exp(-t))/2) - norm(tanh(t) - sinh(t)/cosh(t)) - norm(csch(t) - 1/sinh(t)) - norm(sech(t) - 1/cosh(t)) - norm(coth(t) - cosh(t)/sinh(t)) - norm(coth(t) - 1/tanh(t)) - norm(cosh(t)^2 - sinh(t)^2 - 1) - norm(1 - tanh(t)^2 - sech(t)^2) - norm(coth(t)^2 - 1 - csch(t)^2) - - norm(asin(sin(t)) - t) - norm(acos(cos(t)) - t) - norm(atan(tan(t)) - t) - norm(acsc(t) - asin(1/t)) - norm(asec(t) - acos(1/t)) - norm(acot(t) - acot(1/t)) - norm(asinh(sinh(t)) - t) - norm(acosh(cosh(t)) - t) - norm(atanh(tanh(t)) - t) - norm(acsch(t) - asinh(1/t)) - norm(asech(t) - acosh(1/t)) - norm(acoth(t) - acoth(1/t)) - norm(asinc(t) - asin(t)/t) - norm(asinhc(t) - asinh(t)/t) - - norm(erfc(t) - 1 + erf(t)) - norm(erf(-t) + erf(t)) - norm(angle(t) - atan(imag(t),real(t))) - norm(complex(t) - t) + t[0] = 0.5+0.5im; t[[1]] = 2+2im; t[[2]] = 3+3im; t[[3]] = 4+4im; t[[4]] = 5+5im; t[[5]] = 6+6im + norm(sin(t)^2+cos(t)^2 - 1) < tol + norm(1/sin(t) - csc(t)) < tol + norm(1/cos(t) - sec(t)) < tol + norm(1/tan(t) - cot(t)) < tol + norm(sin(t)/cos(t) - tan(t)) < tol + norm(cos(2*t) - cos(t)^2 + sin(t)^2) < tol + norm(sec(t)^2 - 1 - tan(t)^2) < tol + norm(sin(t/2) - sqrt((1-cos(t))/2)) < tol + norm(cos(t/2) - sqrt((1+cos(t))/2)) < tol + norm(sqrt(t^2) - t) < tol + norm(csc(t)^2 - cot(t)^2 - 1) < tol + norm(exp(log(t)) - t) < tol + norm(log(exp(t)) - t) < tol + norm(log(exp(t)) - exp(log(t))) < tol + norm(log(t^2) - 2*log(t)) < tol + norm(5*log(t) - log(t^5) - 2*pi*im) < tol + norm(t*log(5) - log(5^t)) < tol + norm(sinc(t/pi) - sin(t)/t) < tol + norm(sinhc(t/pi) - sinh(t)/t) < tol + norm(exp(im*t) - cos(t) - im*sin(t)) < tol + norm(sinh(t) - (exp(t) - exp(-t))/2) < tol + norm(cosh(t) - (exp(t) + exp(-t))/2) < tol + norm(tanh(t) - sinh(t)/cosh(t)) < tol + norm(csch(t) - 1/sinh(t)) < tol + norm(sech(t) - 1/cosh(t)) < tol + norm(coth(t) - cosh(t)/sinh(t)) < tol + norm(coth(t) - 1/tanh(t)) < tol + norm(cosh(t)^2 - sinh(t)^2 - 1) < tol + norm(1 - tanh(t)^2 - sech(t)^2) < tol + norm(coth(t)^2 - 1 - csch(t)^2) < tol + + norm(asin(sin(t)) - t) < tol + norm(acos(cos(t)) - t) < tol + norm(atan(tan(t)) - t) < tol + norm(acsc(t) - asin(1/t)) < tol + norm(asec(t) - acos(1/t)) < tol + norm(acot(t) - atan(1/t)) < tol + norm(asinh(sinh(t)) - t) < tol + norm(acosh(cosh(t)) - t) < tol + norm(atanh(tanh(t)) - t) < tol + norm(acsch(t) - asinh(1/t)) < tol + norm(asech(t) - acosh(1/t)) < tol + norm(acoth(t) - atanh(1/t)) < tol + norm(asinc(t/pi) - asin(t)/t) < tol + norm(asinhc(t/pi) - asinh(t)/t) < tol + + norm(erfc(t) - 1 + erf(t)) < tol + norm(erf(-t) + erf(t)) < tol + norm(angle(t) - atan(imag(t),real(t))) < tol + norm(complex(t) - t) < tol d = Descriptor(3,10,2,10) v = vars(d) @@ -503,216 +511,216 @@ function type_stable_test() tol = 1e-18 f = sin(v[1]) - abs(f[0] - 0) - abs(f[1] - 1) - abs(f[2] - 0) - abs(f[3] - -1/factorial(3)) - abs(f[4] - 0) - abs(f[5] - 1/factorial(5)) - abs(f[6] - 0) - abs(f[7] - -1/factorial(7)) - abs(f[8] - 0) - abs(f[9] - 1/factorial(9)) - abs(f[10] - 0) - - abs(f[1=>1] - f[1]) - abs(f[1=>2] - f[2]) - abs(f[1=>3] - f[3]) - abs(f[1=>4] - f[4]) - abs(f[1=>5] - f[5]) - abs(f[1=>6] - f[6]) - abs(f[1=>7] - f[7]) - abs(f[1=>8] - f[8]) - abs(f[1=>9] - f[9]) - abs(f[1=>10] - f[10]) + abs(f[[0]] - 0) < tol + abs(f[[1]] - 1) < tol + abs(f[[2]] - 0) < tol + abs(f[[3]] - -1/factorial(3)) < tol + abs(f[[4]] - 0) < tol + abs(f[[5]] - 1/factorial(5)) < tol + abs(f[[6]] - 0) < tol + abs(f[[7]] - -1/factorial(7)) < tol + abs(f[[8]] - 0) < tol + abs(f[[9]] - 1/factorial(9)) < tol + abs(f[[10]] - 0) < tol + + abs(f[[1=>1]] - f[[1]]) < tol + abs(f[[1=>2]] - f[[2]]) < tol + abs(f[[1=>3]] - f[[3]]) < tol + abs(f[[1=>4]] - f[[4]]) < tol + abs(f[[1=>5]] - f[[5]]) < tol + abs(f[[1=>6]] - f[[6]]) < tol + abs(f[[1=>7]] - f[[7]]) < tol + abs(f[[1=>8]] - f[[8]]) < tol + abs(f[[1=>9]] - f[[9]]) < tol + abs(f[[1=>10]] - f[[10]]) < tol fc = complex(f) - abs(fc[0] - 0) - abs(fc[1] - 1) - abs(fc[2] - 0) - abs(fc[3] - -1/factorial(3)) - abs(fc[4] - 0) - abs(fc[5] - 1/factorial(5)) - abs(fc[6] - 0) - abs(fc[7] - -1/factorial(7)) - abs(fc[8] - 0) - abs(fc[9] - 1/factorial(9)) - abs(fc[10] - 0) - - abs(fc[1=>1] - f[1]) - abs(fc[1=>2] - f[2]) - abs(fc[1=>3] - f[3]) - abs(fc[1=>4] - f[4]) - abs(fc[1=>5] - f[5]) - abs(fc[1=>6] - f[6]) - abs(fc[1=>7] - f[7]) - abs(fc[1=>8] - f[8]) - abs(fc[1=>9] - f[9]) - abs(fc[1=>10] - f[10]) + abs(fc[[0]] - 0) < tol + abs(fc[[1]] - 1) < tol + abs(fc[[2]] - 0) < tol + abs(fc[[3]] - -1/factorial(3)) < tol + abs(fc[[4]] - 0) < tol + abs(fc[[5]] - 1/factorial(5)) < tol + abs(fc[[6]] - 0) < tol + abs(fc[[7]] - -1/factorial(7)) < tol + abs(fc[[8]] - 0) < tol + abs(fc[[9]] - 1/factorial(9)) < tol + abs(fc[[10]] - 0) < tol + + abs(fc[[1=>1]] - f[[1]]) < tol + abs(fc[[1=>2]] - f[[2]]) < tol + abs(fc[[1=>3]] - f[[3]]) < tol + abs(fc[[1=>4]] - f[[4]]) < tol + abs(fc[[1=>5]] - f[[5]]) < tol + abs(fc[[1=>6]] - f[[6]]) < tol + abs(fc[[1=>7]] - f[[7]]) < tol + abs(fc[[1=>8]] - f[[8]]) < tol + abs(fc[[1=>9]] - f[[9]]) < tol + abs(fc[[1=>10]] - f[[10]]) < tol f2 = sin(v[1]) + cos(v[2]) - abs(f2[0] - 1) - abs(f2[1] - 1) - abs(f2[2] - 0) - abs(f2[3] - -1/factorial(3)) - abs(f2[4] - 0) - abs(f2[5] - 1/factorial(5)) - abs(f2[6] - 0) - abs(f2[7] - -1/factorial(7)) - abs(f2[8] - 0) - abs(f2[9] - 1/factorial(9)) - abs(f2[10] - 0) - - abs(f2[0,0] - 1) - abs(f2[0,1] - 0) - abs(f2[0,2] - -1/factorial(2)) - abs(f2[0,3] - 0) - abs(f2[0,4] - 1/factorial(4)) - abs(f2[0,5] - 0) - abs(f2[0,6] - -1/factorial(6)) - abs(f2[0,7] - 0) - abs(f2[0,8] - 1/factorial(8)) - abs(f2[0,9] - 0) - abs(f2[0,10] - -1/factorial(10)) - - abs(f2[1=>1] - f2[1]) - abs(f2[1=>2] - f2[2]) - abs(f2[1=>3] - f2[3]) - abs(f2[1=>4] - f2[4]) - abs(f2[1=>5] - f2[5]) - abs(f2[1=>6] - f2[6]) - abs(f2[1=>7] - f2[7]) - abs(f2[1=>8] - f2[8]) - abs(f2[1=>9] - f2[9]) - abs(f2[1=>10] - f2[10]) - - abs(f2[2=>1] - f2[0,1]) - abs(f2[2=>2] - f2[0,2]) - abs(f2[2=>3] - f2[0,3]) - abs(f2[2=>4] - f2[0,4]) - abs(f2[2=>5] - f2[0,5]) - abs(f2[2=>6] - f2[0,6]) - abs(f2[2=>7] - f2[0,7]) - abs(f2[2=>8] - f2[0,8]) - abs(f2[2=>9] - f2[0,9]) - abs(f2[2=>10] - f2[0,10]) + abs(f2[[0]] - 1) < tol + abs(f2[[1]] - 1) < tol + abs(f2[[2]] - 0) < tol + abs(f2[[3]] - -1/factorial(3)) < tol + abs(f2[[4]] - 0) < tol + abs(f2[[5]] - 1/factorial(5)) < tol + abs(f2[[6]] - 0) < tol + abs(f2[[7]] - -1/factorial(7)) < tol + abs(f2[[8]] - 0) < tol + abs(f2[[9]] - 1/factorial(9)) < tol + abs(f2[[10]] - 0) < tol + + abs(f2[[0,0]] - 1) < tol + abs(f2[[0,1]] - 0) < tol + abs(f2[[0,2]] - -1/factorial(2)) < tol + abs(f2[[0,3]] - 0) < tol + abs(f2[[0,4]] - 1/factorial(4)) < tol + abs(f2[[0,5]] - 0) < tol + abs(f2[[0,6]] - -1/factorial(6)) < tol + abs(f2[[0,7]] - 0) < tol + abs(f2[[0,8]] - 1/factorial(8)) < tol + abs(f2[[0,9]] - 0) < tol + abs(f2[[0,10]] - -1/factorial(10)) < tol + + abs(f2[[1=>1]] - f2[[1]]) < tol + abs(f2[[1=>2]] - f2[[2]]) < tol + abs(f2[[1=>3]] - f2[[3]]) < tol + abs(f2[[1=>4]] - f2[[4]]) < tol + abs(f2[[1=>5]] - f2[[5]]) < tol + abs(f2[[1=>6]] - f2[[6]]) < tol + abs(f2[[1=>7]] - f2[[7]]) < tol + abs(f2[[1=>8]] - f2[[8]]) < tol + abs(f2[[1=>9]] - f2[[9]]) < tol + abs(f2[[1=>10]] - f2[[10]]) < tol + + abs(f2[[2=>1]] - f2[[0,1]]) < tol + abs(f2[[2=>2]] - f2[[0,2]]) < tol + abs(f2[[2=>3]] - f2[[0,3]]) < tol + abs(f2[[2=>4]] - f2[[0,4]]) < tol + abs(f2[[2=>5]] - f2[[0,5]]) < tol + abs(f2[[2=>6]] - f2[[0,6]]) < tol + abs(f2[[2=>7]] - f2[[0,7]]) < tol + abs(f2[[2=>8]] - f2[[0,8]]) < tol + abs(f2[[2=>9]] - f2[[0,9]]) < tol + abs(f2[[2=>10]] - f2[[0,10]]) < tol f2c = complex(sin(v[1]) + cos(v[2])) - abs(f2c[0] - 1) - abs(f2c[1] - 1) - abs(f2c[2] - 0) - abs(f2c[3] - -1/factorial(3)) - abs(f2c[4] - 0) - abs(f2c[5] - 1/factorial(5)) - abs(f2c[6] - 0) - abs(f2c[7] - -1/factorial(7)) - abs(f2c[8] - 0) - abs(f2c[9] - 1/factorial(9)) - abs(f2c[10] - 0) - - abs(f2c[0,0] - 1) - abs(f2c[0,1] - 0) - abs(f2c[0,2] - -1/factorial(2)) - abs(f2c[0,3] - 0) - abs(f2c[0,4] - 1/factorial(4)) - abs(f2c[0,5] - 0) - abs(f2c[0,6] - -1/factorial(6)) - abs(f2c[0,7] - 0) - abs(f2c[0,8] - 1/factorial(8)) - abs(f2c[0,9] - 0) - abs(f2c[0,10] - -1/factorial(10)) - - abs(f2c[1=>1] - f2c[1]) - abs(f2c[1=>2] - f2c[2]) - abs(f2c[1=>3] - f2c[3]) - abs(f2c[1=>4] - f2c[4]) - abs(f2c[1=>5] - f2c[5]) - abs(f2c[1=>6] - f2c[6]) - abs(f2c[1=>7] - f2c[7]) - abs(f2c[1=>8] - f2c[8]) - abs(f2c[1=>9] - f2c[9]) - abs(f2c[1=>10] - f2c[10]) - - abs(f2c[2=>1] - f2c[0,1]) - abs(f2c[2=>2] - f2c[0,2]) - abs(f2c[2=>3] - f2c[0,3]) - abs(f2c[2=>4] - f2c[0,4]) - abs(f2c[2=>5] - f2c[0,5]) - abs(f2c[2=>6] - f2c[0,6]) - abs(f2c[2=>7] - f2c[0,7]) - abs(f2c[2=>8] - f2c[0,8]) - abs(f2c[2=>9] - f2c[0,9]) - abs(f2c[2=>10] - f2c[0,10]) + abs(f2c[[0]] - 1) < tol + abs(f2c[[1]] - 1) < tol + abs(f2c[[2]] - 0) < tol + abs(f2c[[3]] - -1/factorial(3)) < tol + abs(f2c[[4]] - 0) < tol + abs(f2c[[5]] - 1/factorial(5)) < tol + abs(f2c[[6]] - 0) < tol + abs(f2c[[7]] - -1/factorial(7)) < tol + abs(f2c[[8]] - 0) < tol + abs(f2c[[9]] - 1/factorial(9)) < tol + abs(f2c[[10]] - 0) < tol + + abs(f2c[[0,0]] - 1) < tol + abs(f2c[[0,1]] - 0) < tol + abs(f2c[[0,2]] - -1/factorial(2)) < tol + abs(f2c[[0,3]] - 0) < tol + abs(f2c[[0,4]] - 1/factorial(4)) < tol + abs(f2c[[0,5]] - 0) < tol + abs(f2c[[0,6]] - -1/factorial(6)) < tol + abs(f2c[[0,7]] - 0) < tol + abs(f2c[[0,8]] - 1/factorial(8)) < tol + abs(f2c[[0,9]] - 0) < tol + abs(f2c[[0,10]] - -1/factorial(10)) < tol + + abs(f2c[[1=>1]] - f2c[[1]]) < tol + abs(f2c[[1=>2]] - f2c[[2]]) < tol + abs(f2c[[1=>3]] - f2c[[3]]) < tol + abs(f2c[[1=>4]] - f2c[[4]]) < tol + abs(f2c[[1=>5]] - f2c[[5]]) < tol + abs(f2c[[1=>6]] - f2c[[6]]) < tol + abs(f2c[[1=>7]] - f2c[[7]]) < tol + abs(f2c[[1=>8]] - f2c[[8]]) < tol + abs(f2c[[1=>9]] - f2c[[9]]) < tol + abs(f2c[[1=>10]] - f2c[[10]]) < tol + + abs(f2c[[2=>1]] - f2c[[0,1]]) < tol + abs(f2c[[2=>2]] - f2c[[0,2]]) < tol + abs(f2c[[2=>3]] - f2c[[0,3]]) < tol + abs(f2c[[2=>4]] - f2c[[0,4]]) < tol + abs(f2c[[2=>5]] - f2c[[0,5]]) < tol + abs(f2c[[2=>6]] - f2c[[0,6]]) < tol + abs(f2c[[2=>7]] - f2c[[0,7]]) < tol + abs(f2c[[2=>8]] - f2c[[0,8]]) < tol + abs(f2c[[2=>9]] - f2c[[0,9]]) < tol + abs(f2c[[2=>10]] - f2c[[0,10]]) < tol f3 = sin(v[1]) + cos(v[2]) + exp(p[1]) - abs(f3[0] - 2) - abs(f3[1] - 1) - abs(f3[2] - 0) - abs(f3[3] - -1/factorial(3)) - abs(f3[4] - 0) - abs(f3[5] - 1/factorial(5)) - abs(f3[6] - 0) - abs(f3[7] - -1/factorial(7)) - abs(f3[8] - 0) - abs(f3[9] - 1/factorial(9)) - abs(f3[10] - 0) - - abs(f3[0,0] - 2) - abs(f3[0,1] - 0) - abs(f3[0,2] - -1/factorial(2)) - abs(f3[0,3] - 0) - abs(f3[0,4] - 1/factorial(4)) - abs(f3[0,5] - 0) - abs(f3[0,6] - -1/factorial(6)) - abs(f3[0,7] - 0) - abs(f3[0,8] - 1/factorial(8)) - abs(f3[0,9] - 0) - abs(f3[0,10] - -1/factorial(10)) - - abs(f3[0,0,0,0] - 2) - abs(f3[0,0,0,1] - 1/factorial(1)) - abs(f3[0,0,0,2] - 1/factorial(2)) - abs(f3[0,0,0,3] - 1/factorial(3)) - abs(f3[0,0,0,4] - 1/factorial(4)) - abs(f3[0,0,0,5] - 1/factorial(5)) - abs(f3[0,0,0,6] - 1/factorial(6)) - abs(f3[0,0,0,7] - 1/factorial(7)) - abs(f3[0,0,0,8] - 1/factorial(8)) - abs(f3[0,0,0,9] - 1/factorial(9)) - abs(f3[0,0,0,10] - 1/factorial(10)) - - abs(f3[1=>1] - f3[1]) - abs(f3[1=>2] - f3[2]) - abs(f3[1=>3] - f3[3]) - abs(f3[1=>4] - f3[4]) - abs(f3[1=>5] - f3[5]) - abs(f3[1=>6] - f3[6]) - abs(f3[1=>7] - f3[7]) - abs(f3[1=>8] - f3[8]) - abs(f3[1=>9] - f3[9]) - abs(f3[1=>10] - f3[10]) - - abs(f3[2=>1] - f3[0,1]) - abs(f3[2=>2] - f3[0,2]) - abs(f3[2=>3] - f3[0,3]) - abs(f3[2=>4] - f3[0,4]) - abs(f3[2=>5] - f3[0,5]) - abs(f3[2=>6] - f3[0,6]) - abs(f3[2=>7] - f3[0,7]) - abs(f3[2=>8] - f3[0,8]) - abs(f3[2=>9] - f3[0,9]) - abs(f3[2=>10] - f3[0,10]) - - abs(f3[params=[1=>1]] - f3[0,0,0,1]) - abs(f3[params=[1=>2]] - f3[0,0,0,2]) - abs(f3[params=[1=>3]] - f3[0,0,0,3]) - abs(f3[params=[1=>4]] - f3[0,0,0,4]) - abs(f3[params=[1=>5]] - f3[0,0,0,5]) - abs(f3[params=[1=>6]] - f3[0,0,0,6]) - abs(f3[params=[1=>7]] - f3[0,0,0,7]) - abs(f3[params=[1=>8]] - f3[0,0,0,8]) - abs(f3[params=[1=>9]] - f3[0,0,0,9]) - abs(f3[params=[1=>10]] - f3[0,0,0,10]) + abs(f3[[0]] - 2) < tol + abs(f3[[1]] - 1) < tol + abs(f3[[2]] - 0) < tol + abs(f3[[3]] - -1/factorial(3)) < tol + abs(f3[[4]] - 0) < tol + abs(f3[[5]] - 1/factorial(5)) < tol + abs(f3[[6]] - 0) < tol + abs(f3[[7]] - -1/factorial(7)) < tol + abs(f3[[8]] - 0) < tol + abs(f3[[9]] - 1/factorial(9)) < tol + abs(f3[[10]] - 0) < tol + + abs(f3[[0,0]] - 2) < tol + abs(f3[[0,1]] - 0) < tol + abs(f3[[0,2]] - -1/factorial(2)) < tol + abs(f3[[0,3]] - 0) < tol + abs(f3[[0,4]] - 1/factorial(4)) < tol + abs(f3[[0,5]] - 0) < tol + abs(f3[[0,6]] - -1/factorial(6)) < tol + abs(f3[[0,7]] - 0) < tol + abs(f3[[0,8]] - 1/factorial(8)) < tol + abs(f3[[0,9]] - 0) < tol + abs(f3[[0,10]] - -1/factorial(10)) < tol + + abs(f3[[0,0,0,0]] - 2) < tol + abs(f3[[0,0,0,1]] - 1/factorial(1)) < tol + abs(f3[[0,0,0,2]] - 1/factorial(2)) < tol + abs(f3[[0,0,0,3]] - 1/factorial(3)) < tol + abs(f3[[0,0,0,4]] - 1/factorial(4)) < tol + abs(f3[[0,0,0,5]] - 1/factorial(5)) < tol + abs(f3[[0,0,0,6]] - 1/factorial(6)) < tol + abs(f3[[0,0,0,7]] - 1/factorial(7)) < tol + abs(f3[[0,0,0,8]] - 1/factorial(8)) < tol + abs(f3[[0,0,0,9]] - 1/factorial(9)) < tol + abs(f3[[0,0,0,10]] - 1/factorial(10)) < tol + + abs(f3[[1=>1]] - f3[[1]]) < tol + abs(f3[[1=>2]] - f3[[2]]) < tol + abs(f3[[1=>3]] - f3[[3]]) < tol + abs(f3[[1=>4]] - f3[[4]]) < tol + abs(f3[[1=>5]] - f3[[5]]) < tol + abs(f3[[1=>6]] - f3[[6]]) < tol + abs(f3[[1=>7]] - f3[[7]]) < tol + abs(f3[[1=>8]] - f3[[8]]) < tol + abs(f3[[1=>9]] - f3[[9]]) < tol + abs(f3[[1=>10]] - f3[[10]]) < tol + + abs(f3[[2=>1]]- f3[[0,1]]) < tol + abs(f3[[2=>2]]- f3[[0,2]]) < tol + abs(f3[[2=>3]]- f3[[0,3]]) < tol + abs(f3[[2=>4]]- f3[[0,4]]) < tol + abs(f3[[2=>5]]- f3[[0,5]]) < tol + abs(f3[[2=>6]]- f3[[0,6]]) < tol + abs(f3[[2=>7]]- f3[[0,7]]) < tol + abs(f3[[2=>8]]- f3[[0,8]]) < tol + abs(f3[[2=>9]]- f3[[0,9]]) < tol + abs(f3[[2=>10]]- f3[[0,10]]) < tol + + abs(f3[params=[1=>1]] - f3[[0,0,0,1]]) < tol + abs(f3[params=[1=>2]] - f3[[0,0,0,2]]) < tol + abs(f3[params=[1=>3]] - f3[[0,0,0,3]]) < tol + abs(f3[params=[1=>4]] - f3[[0,0,0,4]]) < tol + abs(f3[params=[1=>5]] - f3[[0,0,0,5]]) < tol + abs(f3[params=[1=>6]] - f3[[0,0,0,6]]) < tol + abs(f3[params=[1=>7]] - f3[[0,0,0,7]]) < tol + abs(f3[params=[1=>8]] - f3[[0,0,0,8]]) < tol + abs(f3[params=[1=>9]] - f3[[0,0,0,9]]) < tol + abs(f3[params=[1=>10]] - f3[[0,0,0,10]]) < tol d = Descriptor(1, 5) t = TPS(use=d) @@ -738,81 +746,81 @@ function type_stable_test() tol = 1e-14 # TPS: - @FastGTPSA(norm(t1 + t2 - t3)) - @FastGTPSA(norm(t2 + t1 - t3)) - @FastGTPSA(norm(t1 + 2 - t3)) - @FastGTPSA(norm(2 + t1 - t3)) - @FastGTPSA(norm(t3 - t2 - t1)) - @FastGTPSA(norm(t2 - t3 - -t1)) - @FastGTPSA(norm(t3 - 2 - t1)) - @FastGTPSA(norm(2 - t3 - -t1)) - @FastGTPSA(norm(t2 * t3 - 6)) - @FastGTPSA(norm(t3 * t2 - 6)) - @FastGTPSA(norm(t2 * 5 - 10)) - @FastGTPSA(norm(5 * t2 - 10 * t1)) - @FastGTPSA(norm(t1 / t2 - 1/2)) - @FastGTPSA(norm(t2 / t1 - 2)) - @FastGTPSA(norm(1 / t2 - 1/2)) - @FastGTPSA(norm(t2 / 3 - 2/3)) - @FastGTPSA(norm(t2 / t2 - t1)) - @FastGTPSA(norm(t2 / t2 - 1)) - @FastGTPSA(norm(t2 ^ t3 - 8)) - @FastGTPSA(norm(t3 ^ t2 - 9)) - @FastGTPSA(norm(t2 ^ 3 - 8)) - @FastGTPSA(norm(t2 ^ (1/2) - sqrt(2))) - @FastGTPSA(norm(t2 ^ (1/2) - sqrt(t2))) - @FastGTPSA(norm(2 ^ t3 - 8)) - @FastGTPSA(norm(inv(t3) - 1/t3)) - @FastGTPSA(norm(inv(t3) - 1/3)) + @FastGTPSA(norm(t1 + t2 - t3)) < tol + @FastGTPSA(norm(t2 + t1 - t3)) < tol + @FastGTPSA(norm(t1 + 2 - t3)) < tol + @FastGTPSA(norm(2 + t1 - t3)) < tol + @FastGTPSA(norm(t3 - t2 - t1)) < tol + @FastGTPSA(norm(t2 - t3 - -t1)) < tol + @FastGTPSA(norm(t3 - 2 - t1)) < tol + @FastGTPSA(norm(2 - t3 - -t1)) < tol + @FastGTPSA(norm(t2 * t3 - 6)) < tol + @FastGTPSA(norm(t3 * t2 - 6)) < tol + @FastGTPSA(norm(t2 * 5 - 10)) < tol + @FastGTPSA(norm(5 * t2 - 10 * t1)) < tol + @FastGTPSA(norm(t1 / t2 - 1/2)) < tol + @FastGTPSA(norm(t2 / t1 - 2)) < tol + @FastGTPSA(norm(1 / t2 - 1/2)) < tol + @FastGTPSA(norm(t2 / 3 - 2/3)) < tol + @FastGTPSA(norm(t2 / t2 - t1)) < tol + @FastGTPSA(norm(t2 / t2 - 1)) < tol + @FastGTPSA(norm(t2 ^ t3 - 8)) < tol + @FastGTPSA(norm(t3 ^ t2 - 9)) < tol + @FastGTPSA(norm(t2 ^ 3 - 8)) < tol + @FastGTPSA(norm(t2 ^ (1/2) - sqrt(2))) < tol + @FastGTPSA(norm(t2 ^ (1/2) - sqrt(t2))) < tol + @FastGTPSA(norm(2 ^ t3 - 8)) < tol + @FastGTPSA(norm(inv(t3) - 1/t3)) < tol + @FastGTPSA(norm(inv(t3) - 1/3)) < tol # ComplexTPS: - @FastGTPSA(norm(ct1 + ct2 - ct3)) - @FastGTPSA(norm(ct2 + ct1 - ct3)) - @FastGTPSA(norm(ct1 + (2+2im) - ct3)) - @FastGTPSA(norm((2+2im) + ct1 - ct3)) - @FastGTPSA(norm(ct3 - ct2 - ct1)) - @FastGTPSA(norm(ct2 - ct3 - -ct1)) - @FastGTPSA(norm(ct3 - (2+2im) - ct1)) - @FastGTPSA(norm((2+2im) - ct3 - -ct1)) - @FastGTPSA(norm(ct2 * ct3 - (2+2im)*(3+3im))) - @FastGTPSA(norm(ct3 * ct2 - (2+2im)*(3+3im))) - @FastGTPSA(norm(ct2 * 5 - (10+10im))) - @FastGTPSA(norm(5 * ct2 - (10 * ct1))) - @FastGTPSA(norm(ct1 / ct2 - (1+im)/(2+2im))) - @FastGTPSA(norm(ct2 / ct1 - 2)) - @FastGTPSA(norm(1 / ct2 - 1/(2+2im))) - @FastGTPSA(norm(ct2 / 3 - (2+2im)/3)) - @FastGTPSA(norm(ct2 / ct2 - 1)) - @FastGTPSA(norm(ct2 ^ ct3 - (2+2im)^(3+3im))) - @FastGTPSA(norm(ct3 ^ ct2 - (3+3im)^(2+2im))) - @FastGTPSA(norm(ct2 ^ 3 - (2+2im)^3)) - @FastGTPSA(norm(ct2 ^ (1/2) - sqrt(2+2im))) - @FastGTPSA(norm(ct2 ^ (1/2) - sqrt(ct2))) - @FastGTPSA(norm(2 ^ ct3 - 2^(3+3im))) - @FastGTPSA(norm(inv(ct3) - 1/ct3)) - @FastGTPSA(norm(inv(ct3) - 1/(3+3im))) + @FastGTPSA(norm(ct1 + ct2 - ct3)) < tol + @FastGTPSA(norm(ct2 + ct1 - ct3)) < tol + @FastGTPSA(norm(ct1 + (2+2im) - ct3)) < tol + @FastGTPSA(norm((2+2im) + ct1 - ct3)) < tol + @FastGTPSA(norm(ct3 - ct2 - ct1)) < tol + @FastGTPSA(norm(ct2 - ct3 - -ct1)) < tol + @FastGTPSA(norm(ct3 - (2+2im) - ct1)) < tol + @FastGTPSA(norm((2+2im) - ct3 - -ct1)) < tol + @FastGTPSA(norm(ct2 * ct3 - (2+2im)*(3+3im))) < tol + @FastGTPSA(norm(ct3 * ct2 - (2+2im)*(3+3im))) < tol + @FastGTPSA(norm(ct2 * 5 - (10+10im))) < tol + @FastGTPSA(norm(5 * ct2 - (10 * ct1))) < tol + @FastGTPSA(norm(ct1 / ct2 - (1+im)/(2+2im))) < tol + @FastGTPSA(norm(ct2 / ct1 - 2)) < tol + @FastGTPSA(norm(1 / ct2 - 1/(2+2im))) < tol + @FastGTPSA(norm(ct2 / 3 - (2+2im)/3)) < tol + @FastGTPSA(norm(ct2 / ct2 - 1)) < tol + @FastGTPSA(norm(ct2 ^ ct3 - (2+2im)^(3+3im))) < tol + @FastGTPSA(norm(ct3 ^ ct2 - (3+3im)^(2+2im))) < tol + @FastGTPSA(norm(ct2 ^ 3 - (2+2im)^3)) < tol + @FastGTPSA(norm(ct2 ^ (1/2) - sqrt(2+2im))) < tol + @FastGTPSA(norm(ct2 ^ (1/2) - sqrt(ct2))) < tol + @FastGTPSA(norm(2 ^ ct3 - 2^(3+3im))) < tol + @FastGTPSA(norm(inv(ct3) - 1/ct3)) < tol + @FastGTPSA(norm(inv(ct3) - 1/(3+3im))) < tol # Promotion of TPS to ComplexTPS - @FastGTPSA(norm(t1 + ct2 - (1 + (2+2im)))) - @FastGTPSA(norm(ct2 + t1 - (1 + (2+2im)))) - @FastGTPSA(norm(t1 + (2+2im) - (1 + (2+2im)))) - @FastGTPSA(norm((2+2im) + t1 - (1 + (2+2im)))) - @FastGTPSA(norm(t3 - ct2 - (3 - (2+2im)))) - @FastGTPSA(norm(ct2 - t3 - ((2+2im) - 3))) - @FastGTPSA(norm(t3 - (2+2im) - (3 - (2+2im)))) - @FastGTPSA(norm((2+2im) - t3 - ((2+2im) - 3))) - @FastGTPSA(norm(t2 * ct3 - 2 * (3+3im))) - @FastGTPSA(norm(ct3 * t2 - 2 * (3+3im))) - @FastGTPSA(norm(t2 * (3+3im) - 2 * (3+3im))) - @FastGTPSA(norm((3+3im) * t2 - 2 * (3+3im))) - @FastGTPSA(norm(t2 / ct3 - 2/(3+3im))) - @FastGTPSA(norm(ct3 / t2 - (3+3im)/2)) - @FastGTPSA(norm(t2 / (3+3im) - 2/(3+3im))) - @FastGTPSA(norm((3+3im) / t2 - (3+3im)/2)) - @FastGTPSA(norm(t2 ^ ct3 - 2^(3+3im))) - @FastGTPSA(norm(ct3 ^ t2 - (3+3im)^2)) - @FastGTPSA(norm(t2 ^ (3+3im) - 2^(3+3im))) - @FastGTPSA(norm((3+3im)^t2 - (3+3im)^2)) + @FastGTPSA(norm(t1 + ct2 - (1 + (2+2im)))) < tol + @FastGTPSA(norm(ct2 + t1 - (1 + (2+2im)))) < tol + @FastGTPSA(norm(t1 + (2+2im) - (1 + (2+2im)))) < tol + @FastGTPSA(norm((2+2im) + t1 - (1 + (2+2im)))) < tol + @FastGTPSA(norm(t3 - ct2 - (3 - (2+2im)))) < tol + @FastGTPSA(norm(ct2 - t3 - ((2+2im) - 3))) < tol + @FastGTPSA(norm(t3 - (2+2im) - (3 - (2+2im)))) < tol + @FastGTPSA(norm((2+2im) - t3 - ((2+2im) - 3))) < tol + @FastGTPSA(norm(t2 * ct3 - 2 * (3+3im))) < tol + @FastGTPSA(norm(ct3 * t2 - 2 * (3+3im))) < tol + @FastGTPSA(norm(t2 * (3+3im) - 2 * (3+3im))) < tol + @FastGTPSA(norm((3+3im) * t2 - 2 * (3+3im))) < tol + @FastGTPSA(norm(t2 / ct3 - 2/(3+3im))) < tol + @FastGTPSA(norm(ct3 / t2 - (3+3im)/2)) < tol + @FastGTPSA(norm(t2 / (3+3im) - 2/(3+3im))) < tol + @FastGTPSA(norm((3+3im) / t2 - (3+3im)/2)) < tol + @FastGTPSA(norm(t2 ^ ct3 - 2^(3+3im))) < tol + @FastGTPSA(norm(ct3 ^ t2 - (3+3im)^2)) < tol + @FastGTPSA(norm(t2 ^ (3+3im) - 2^(3+3im))) < tol + @FastGTPSA(norm((3+3im)^t2 - (3+3im)^2)) < tol # Make sure stack is 0: desc = unsafe_load(Base.unsafe_convert(Ptr{Desc}, unsafe_load(t1.tpsa).d)) @@ -834,76 +842,78 @@ function type_stable_test() t3[0] = 3 - @FastGTPSA(norm(abs(-t) - abs(-v) )) - @FastGTPSA(norm(sqrt(t) - sqrt(v))) - @FastGTPSA(norm(exp(t) - exp(v))) - @FastGTPSA(norm(log(t) - log(v))) - @FastGTPSA(norm(sin(t) - sin(v))) - @FastGTPSA(norm(cos(t) - cos(v))) - @FastGTPSA(norm(tan(t) - tan(v))) - @FastGTPSA(norm(csc(t) - csc(v))) - @FastGTPSA(norm(sec(t) - sec(v))) - @FastGTPSA(norm(cot(t) - cot(v))) - @FastGTPSA(norm(sinc(t) - sinc(v))) - @FastGTPSA(norm(sinh(t) - sinh(v))) - @FastGTPSA(norm(cosh(t) - cosh(v))) - @FastGTPSA(norm(tanh(t) - tanh(v))) - @FastGTPSA(norm(csch(t) - csch(v))) - @FastGTPSA(norm(sech(t) - sech(v))) - @FastGTPSA(norm(coth(t) - coth(v))) - @FastGTPSA(norm(asin(t) - asin(v))) - @FastGTPSA(norm(acos(t) - acos(v))) - @FastGTPSA(norm(atan(t) - atan(v))) - @FastGTPSA(norm(acsc(1/t) - acsc(1/v))) - @FastGTPSA(norm(asec(1/t) - asec(1/v))) - @FastGTPSA(norm(acot(1/t) - acot(1/v))) - @FastGTPSA(norm(asinh(t) - asinh(v))) - @FastGTPSA(norm(acosh(1/t) - acosh(1/v))) - @FastGTPSA(norm(atanh(t) - atanh(v))) - @FastGTPSA(norm(acsch(1/t) - acsch(1/v))) - @FastGTPSA(norm(asech(t) - asech(v))) - @FastGTPSA(norm(acoth(1/t) - acoth(1/v))) - @FastGTPSA(norm(asinc(t/pi) - asin(v)/(v))) - @FastGTPSA(norm(asinhc(t/pi) - asinh(v)/(v))) - @FastGTPSA(norm(zero(t) - zero(v))) - @FastGTPSA(norm(real(t) - real(v))) - @FastGTPSA(norm(imag(t) - imag(v))) - @FastGTPSA(norm(conj(t) - conj(v))) - @FastGTPSA(norm(sinhc(t/pi) - sinh(v)/v)) - @FastGTPSA(norm(erf(t) - erf(v))) - @FastGTPSA(norm(erfc(t) - erfc(v))) - @FastGTPSA(norm(-im*erf(t*im) - erfi(v))) - @FastGTPSA(norm(atan(t3,t2) - atan(3,2))) - @FastGTPSA(norm(atan(t3,2) - atan(3,2))) - @FastGTPSA(norm(atan(3,t2) - atan(3,2))) - @FastGTPSA(norm(atan(t3,-t2) - atan(3,-2))) - @FastGTPSA(norm(atan(t3,-2) - atan(3,-2))) - @FastGTPSA(norm(atan(3,-t2) - atan(3,-2))) - @FastGTPSA(norm(atan(-t3,-t2) - atan(-3,-2))) - @FastGTPSA(norm(atan(-t3,-2) - atan(-3,-2))) - @FastGTPSA(norm(atan(-3,-t2) - atan(-3,-2))) - @FastGTPSA(norm(atan(-t3,t2) - atan(-3,2))) - @FastGTPSA(norm(atan(-t3,2) - atan(-3,2))) - @FastGTPSA(norm(atan(-3,t2) - atan(-3,2))) - @FastGTPSA(norm(hypot(t2,t3) - hypot(2,3))) - @FastGTPSA(norm(hypot(2,t3) - hypot(2,3))) - @FastGTPSA(norm(hypot(t2,3) - hypot(2,3))) - @FastGTPSA(norm(hypot(t1,t2,t3) - hypot(1,2,3))) - @FastGTPSA(norm(hypot(1, t2, t3) - hypot(1,2,3))) - @FastGTPSA(norm(hypot(t1, 2, t3) - hypot(1,2,3))) - @FastGTPSA(norm(hypot(t1, t2, 3) - hypot(1,2,3))) - @FastGTPSA(norm(hypot(1, 2, t3) - hypot(1,2,3))) - @FastGTPSA(norm(hypot(1, t2, 3) - hypot(1,2,3))) - @FastGTPSA(norm(hypot(t1, 2, 3) - hypot(1,2,3))) - - @FastGTPSA(norm(angle(t2) - angle(2))) - @FastGTPSA(norm(angle(-t2) - angle(-2))) - @FastGTPSA(norm(complex(t3) - complex(3))) - @FastGTPSA(norm(complex(t2,t3) - complex(2,3))) - @FastGTPSA(norm(polar(t2) - (abs(2)+im*atan(0,2)))) - @FastGTPSA(norm(polar(-t1) - (abs(-1)+im*atan(0,-1)))) - @FastGTPSA(norm(rect(t2) - (2*cos(0) + 2*sin(0)))) - @FastGTPSA(norm(rect(-t1) - (-1*cos(0) + -1*sin(0)))) + @FastGTPSA(norm(abs(-t) - abs(-v) )) < tol + @FastGTPSA(norm(sqrt(t) - sqrt(v))) < tol + @FastGTPSA(norm(exp(t) - exp(v))) < tol + @FastGTPSA(norm(log(t) - log(v))) < tol + @FastGTPSA(norm(sin(t) - sin(v))) < tol + @FastGTPSA(norm(cos(t) - cos(v))) < tol + @FastGTPSA(norm(tan(t) - tan(v))) < tol + @FastGTPSA(norm(csc(t) - csc(v))) < tol + @FastGTPSA(norm(sec(t) - sec(v))) < tol + @FastGTPSA(norm(cot(t) - cot(v))) < tol + @FastGTPSA(norm(sinc(t) - sinc(v))) < tol + @FastGTPSA(norm(sinh(t) - sinh(v))) < tol + @FastGTPSA(norm(cosh(t) - cosh(v))) < tol + @FastGTPSA(norm(tanh(t) - tanh(v))) < tol + @FastGTPSA(norm(csch(t) - csch(v))) < tol + @FastGTPSA(norm(sech(t) - sech(v))) < tol + @FastGTPSA(norm(coth(t) - coth(v))) < tol + @FastGTPSA(norm(asin(t) - asin(v))) < tol + @FastGTPSA(norm(acos(t) - acos(v))) < tol + @FastGTPSA(norm(atan(t) - atan(v))) < tol + @FastGTPSA(norm(acsc(1/t) - acsc(1/v))) < tol + @FastGTPSA(norm(asec(1/t) - asec(1/v))) < tol + @FastGTPSA(norm(acot(1/t) - acot(1/v))) < tol + @FastGTPSA(norm(asinh(t) - asinh(v))) < tol + @FastGTPSA(norm(acosh(1/t) - acosh(1/v))) < tol + @FastGTPSA(norm(atanh(t) - atanh(v))) < tol + @FastGTPSA(norm(acsch(1/t) - acsch(1/v))) < tol + @FastGTPSA(norm(asech(t) - asech(v))) < tol + @FastGTPSA(norm(acoth(1/t) - acoth(1/v))) < tol + @FastGTPSA(norm(asinc(t/pi) - asin(v)/(v))) < tol + @FastGTPSA(norm(asinhc(t/pi) - asinh(v)/(v))) < tol + @FastGTPSA(norm(zero(t) - zero(v))) < tol + @FastGTPSA(norm(real(t) - real(v))) < tol + @FastGTPSA(norm(imag(t) - imag(v))) < tol + @FastGTPSA(norm(conj(t) - conj(v))) < tol + @FastGTPSA(norm(sinhc(t/pi) - sinh(v)/v)) < tol + @FastGTPSA(norm(erf(t) - erf(v))) < tol + @FastGTPSA(norm(erfc(t) - erfc(v))) < tol + @FastGTPSA(norm(-im*erf(t*im) - erfi(v))) < tol + @FastGTPSA(norm(atan(t3,t2) - atan(3,2))) < tol + @FastGTPSA(norm(atan(t3,2) - atan(3,2))) < tol + @FastGTPSA(norm(atan(3,t2) - atan(3,2))) < tol + @FastGTPSA(norm(atan(t3,-t2) - atan(3,-2))) < tol + @FastGTPSA(norm(atan(t3,-2) - atan(3,-2))) < tol + @FastGTPSA(norm(atan(3,-t2) - atan(3,-2))) < tol + @FastGTPSA(norm(atan(-t3,-t2) - atan(-3,-2))) < tol + @FastGTPSA(norm(atan(-t3,-2) - atan(-3,-2))) < tol + @FastGTPSA(norm(atan(-3,-t2) - atan(-3,-2))) < tol + @FastGTPSA(norm(atan(-t3,t2) - atan(-3,2))) < tol + @FastGTPSA(norm(atan(-t3,2) - atan(-3,2))) < tol + @FastGTPSA(norm(atan(-3,t2) - atan(-3,2))) < tol + + @FastGTPSA(norm(hypot(t2,t3) - hypot(2,3))) < tol + @FastGTPSA(norm(hypot(2,t3) - hypot(2,3))) < tol + @FastGTPSA(norm(hypot(t2,3) - hypot(2,3))) < tol + @FastGTPSA(norm(hypot(t1,t2,t3) - hypot(1,2,3))) < tol + @FastGTPSA(norm(hypot(1, t2, t3) - hypot(1,2,3))) < tol + @FastGTPSA(norm(hypot(t1, 2, t3) - hypot(1,2,3))) < tol + @FastGTPSA(norm(hypot(t1, t2, 3) - hypot(1,2,3))) < tol + @FastGTPSA(norm(hypot(1, 2, t3) - hypot(1,2,3))) < tol + @FastGTPSA(norm(hypot(1, t2, 3) - hypot(1,2,3))) < tol + @FastGTPSA(norm(hypot(t1, 2, 3) - hypot(1,2,3))) < tol + + @FastGTPSA(norm(angle(t2) - angle(2))) < tol + @FastGTPSA(norm(angle(-t2) - angle(-2))) < tol + @FastGTPSA(norm(complex(t3) - complex(3))) < tol + @FastGTPSA(norm(complex(t2,t3) - complex(2,3))) < tol + @FastGTPSA(norm(polar(t2) - (abs(2)+im*atan(0,2)))) < tol + @FastGTPSA(norm(polar(-t1) - (abs(-1)+im*atan(0,-1)))) < tol + @FastGTPSA(norm(rect(t2) - (2*cos(0) + im*2*sin(0)))) < tol + @FastGTPSA(norm(rect(-t1) - (-1*cos(0) + im*-1*sin(0)))) < tol + v = 0.5+0.5im t = ComplexTPS(t) @@ -914,86 +924,89 @@ function type_stable_test() ct2[0] = 2 + 2im ct3 = zero(ct1) ct3[0] = 3 + 3im - @FastGTPSA(norm(abs(-t) - abs(-v) )) - @FastGTPSA(norm(sqrt(t) - sqrt(v))) - @FastGTPSA(norm(exp(t) - exp(v))) - @FastGTPSA(norm(log(t) - log(v))) - @FastGTPSA(norm(sin(t) - sin(v))) - @FastGTPSA(norm(cos(t) - cos(v))) - @FastGTPSA(norm(tan(t) - tan(v))) - @FastGTPSA(norm(csc(t) - csc(v))) - @FastGTPSA(norm(sec(t) - sec(v))) - @FastGTPSA(norm(cot(t) - cot(v))) - @FastGTPSA(norm(sinc(t) - sinc(v))) - @FastGTPSA(norm(sinh(t) - sinh(v))) - @FastGTPSA(norm(cosh(t) - cosh(v))) - @FastGTPSA(norm(tanh(t) - tanh(v))) - @FastGTPSA(norm(csch(t) - csch(v))) - @FastGTPSA(norm(sech(t) - sech(v))) - @FastGTPSA(norm(coth(t) - coth(v))) - @FastGTPSA(norm(asin(t) - asin(v))) - @FastGTPSA(norm(acos(t) - acos(v))) - @FastGTPSA(norm(atan(t) - atan(v))) - @FastGTPSA(norm(acsc(t) - acsc(v))) - @FastGTPSA(norm(asec(t) - asec(v))) - @FastGTPSA(norm(acot(t) - acot(v))) - @FastGTPSA(norm(asinh(t) - asinh(v))) - @FastGTPSA(norm(acosh(t) - acosh(v))) - @FastGTPSA(norm(atanh(t) - atanh(v))) - @FastGTPSA(norm(acsch(t) - acsch(v))) - @FastGTPSA(norm(asech(t) - asech(v))) - @FastGTPSA(norm(acoth(t) - acoth(v))) - @FastGTPSA(norm(asinc(t) - asin(v)/v)) - @FastGTPSA(norm(asinhc(t) - asinh(v)/v)) - @FastGTPSA(norm(zero(t) - zero(v))) - @FastGTPSA(norm(real(t) - real(v))) - @FastGTPSA(norm(imag(t) - imag(v))) - @FastGTPSA(norm(conj(t) - conj(v))) - @FastGTPSA(norm(sinhc(t/pi) - sinh(v)/v)) - @FastGTPSA(norm(erf(t) - erf(v))) - @FastGTPSA(norm(erfc(t) - erfc(v))) - @FastGTPSA(norm(-im*erf(t*im) - erfi(v))) - @FastGTPSA(norm(hypot(ct2,ct3) - hypot(2+2im,3+3im))) - @FastGTPSA(norm(hypot(2+2im,ct3) - hypot(2+2im,3+3im))) - @FastGTPSA(norm(hypot(ct2,3+3im) - hypot(2+2im,3+3im))) - @FastGTPSA(norm(hypot(ct1,ct2,ct3) - hypot(1+1im,2+2im,3+3im))) - @FastGTPSA(norm(hypot(1+1im, ct2, ct3) - hypot(1+1im,2+2im,3+3im))) - @FastGTPSA(norm(hypot(ct1, 2+2im, ct3) - hypot(1+1im,2+2im,3+3im))) - @FastGTPSA(norm(hypot(ct1, ct2, 3+3im) - hypot(1+1im,2+2im,3+3im))) - @FastGTPSA(norm(hypot(1+1im, 2+2im, ct3) - hypot(1+1im,2+2im,3+3im))) - @FastGTPSA(norm(hypot(1+1im, ct2, 3+3im) - hypot(1+1im,2+2im,3+3im))) - @FastGTPSA(norm(hypot(ct1, 2+2im, 3+3im) - hypot(1+1im,2+2im,3+3im))) - - @FastGTPSA(norm(angle(t2+im*t3) - angle(2+3im))) - @FastGTPSA(norm(angle(t2-im*t3) - angle(2-3im))) - @FastGTPSA(norm(angle(-t2-im*t3) - angle(-2-3im))) - @FastGTPSA(norm(angle(-t2+im*t3) - angle(-2+3im))) - @FastGTPSA(norm(angle(ct2) - angle(2+2im))) - @FastGTPSA(norm(angle(-ct2) - angle(-2-2im))) - @FastGTPSA(norm(complex(ct3) - complex(3+3im))) - @FastGTPSA(norm(polar(ct2) - (abs(2+2im)+im*angle(2+2im)))) - @FastGTPSA(norm(polar(-ct1) - (abs(-1-im)+im*angle(-1-im)))) - @FastGTPSA(norm(rect(ct2) - (2*cos(2) + 2*sin(2)))) - @FastGTPSA(norm(rect(-ct1) - (-1*cos(-1) + -1*sin(-1)))) + @FastGTPSA(norm(abs(-t) - abs(-v) )) < tol + @FastGTPSA(norm(sqrt(t) - sqrt(v))) < tol + @FastGTPSA(norm(exp(t) - exp(v))) < tol + @FastGTPSA(norm(log(t) - log(v))) < tol + @FastGTPSA(norm(sin(t) - sin(v))) < tol + @FastGTPSA(norm(cos(t) - cos(v))) < tol + @FastGTPSA(norm(tan(t) - tan(v))) < tol + @FastGTPSA(norm(csc(t) - csc(v))) < tol + @FastGTPSA(norm(sec(t) - sec(v))) < tol + @FastGTPSA(norm(cot(t) - cot(v))) < tol + @FastGTPSA(norm(sinc(t) - sinc(v))) < tol + @FastGTPSA(norm(sinh(t) - sinh(v))) < tol + @FastGTPSA(norm(cosh(t) - cosh(v))) < tol + @FastGTPSA(norm(tanh(t) - tanh(v))) < tol + @FastGTPSA(norm(csch(t) - csch(v))) < tol + @FastGTPSA(norm(sech(t) - sech(v))) < tol + @FastGTPSA(norm(coth(t) - coth(v))) < tol + + @FastGTPSA(norm(asin(t) - asin(v))) < tol + @FastGTPSA(norm(acos(t) - acos(v))) < tol + @FastGTPSA(norm(atan(t) - atan(v))) < tol + @FastGTPSA(norm(acsc(t) - acsc(v))) < tol + @FastGTPSA(norm(asec(t) - asec(v))) < tol + @FastGTPSA(norm(acot(t) - acot(v))) < tol + @FastGTPSA(norm(asinh(t) - asinh(v))) < tol + @FastGTPSA(norm(acosh(t) - acosh(v))) < tol + @FastGTPSA(norm(atanh(t) - atanh(v))) < tol + @FastGTPSA(norm(acsch(t) - acsch(v))) < tol + @FastGTPSA(norm(asech(t) - asech(v))) < tol + @FastGTPSA(norm(acoth(t) - acoth(v))) < tol + @FastGTPSA(norm(asinc(t/pi) - asin(v)/v)) < tol + @FastGTPSA(norm(asinhc(t/pi) - asinh(v)/v)) < tol + + @FastGTPSA(norm(zero(t) - zero(v))) < tol + @FastGTPSA(norm(real(t) - real(v))) < tol + @FastGTPSA(norm(imag(t) - imag(v))) < tol + @FastGTPSA(norm(conj(t) - conj(v))) < tol + @FastGTPSA(norm(sinhc(t/pi) - sinh(v)/v)) < tol + @FastGTPSA(norm(erf(t) - erf(v))) < tol + @FastGTPSA(norm(erfc(t) - erfc(v))) < tol + @FastGTPSA(norm(-im*erf(t*im) - erfi(v))) < tol + @FastGTPSA(norm(hypot(ct2,ct3) - hypot(2+2im,3+3im))) < tol + @FastGTPSA(norm(hypot(2+2im,ct3) - hypot(2+2im,3+3im))) < tol + @FastGTPSA(norm(hypot(ct2,3+3im) - hypot(2+2im,3+3im))) < tol + @FastGTPSA(norm(hypot(ct1,ct2,ct3) - hypot(1+1im,2+2im,3+3im))) < tol + @FastGTPSA(norm(hypot(1+1im, ct2, ct3) - hypot(1+1im,2+2im,3+3im))) < tol + @FastGTPSA(norm(hypot(ct1, 2+2im, ct3) - hypot(1+1im,2+2im,3+3im))) < tol + @FastGTPSA(norm(hypot(ct1, ct2, 3+3im) - hypot(1+1im,2+2im,3+3im))) < tol + @FastGTPSA(norm(hypot(1+1im, 2+2im, ct3) - hypot(1+1im,2+2im,3+3im))) < tol + @FastGTPSA(norm(hypot(1+1im, ct2, 3+3im) - hypot(1+1im,2+2im,3+3im))) < tol + @FastGTPSA(norm(hypot(ct1, 2+2im, 3+3im) - hypot(1+1im,2+2im,3+3im))) < tol + + @FastGTPSA(norm(angle(t2+im*t3) - angle(2+3im))) < tol + @FastGTPSA(norm(angle(t2-im*t3) - angle(2-3im))) < tol + @FastGTPSA(norm(angle(-t2-im*t3) - angle(-2-3im))) < tol + @FastGTPSA(norm(angle(-t2+im*t3) - angle(-2+3im))) < tol + @FastGTPSA(norm(angle(ct2) - angle(2+2im))) < tol + @FastGTPSA(norm(angle(-ct2) - angle(-2-2im))) < tol + @FastGTPSA(norm(complex(ct3) - complex(3+3im))) < tol + @FastGTPSA(norm(polar(ct2) - (abs(2+2im)+im*angle(2+2im)))) < tol + @FastGTPSA(norm(polar(-ct1) - (abs(-1-im)+im*angle(-1-im)))) < tol + @FastGTPSA(norm(rect(ct2) - (2*cos(2) + im*2*sin(2)))) < tol + @FastGTPSA(norm(rect(-ct1) - (-1*cos(-1) + im*-1*sin(-1)))) < tol + # Hypot, mixing TPS with ComplexTPS - @FastGTPSA(norm(hypot(ct1, ct2, t3) - hypot(1+1im,2+2im,3))) - @FastGTPSA(norm(hypot(ct1, t2, ct3) - hypot(1+1im,2,3+3im))) - @FastGTPSA(norm(hypot(t1, ct2, ct3) - hypot(1,2+2im,3+3im))) - @FastGTPSA(norm(hypot(ct1, t2, t3) - hypot(1+1im,2,3))) - @FastGTPSA(norm(hypot(t1, ct2, t3) - hypot(1,2+2im,3))) - @FastGTPSA(norm(hypot(t1, t2, ct3) - hypot(1,2,3+3im))) - @FastGTPSA(norm(hypot(ct1,t2,3+3im) - hypot(1+1im,2,3+3im))) - @FastGTPSA(norm(hypot(t1, ct2, 3+3im) - hypot(1,2+2im,3+3im))) - @FastGTPSA(norm(hypot(ct1,2+2im,t3) - hypot(1+1im,2+2im,3))) - @FastGTPSA(norm(hypot(t1,2+2im,ct3) - hypot(1,2+2im,3+3im))) - @FastGTPSA(norm(hypot(1+1im,ct2,t3) - hypot(1+1im,2+2im,3))) - @FastGTPSA(norm(hypot(1+1im, t2, ct3) - hypot(1+1im,2,3+3im))) - @FastGTPSA(norm(hypot(t1,t2,3+3im) - hypot(1,2,3+3im))) - @FastGTPSA(norm(hypot(t1,2+2im,t3) - hypot(1,2+2im,3))) - @FastGTPSA(norm(hypot(1+1im,t2,t3) - hypot(1+1im,2,3))) - @FastGTPSA(norm(hypot(t1,2,3+3im) - hypot(1,2,3+3im))) - @FastGTPSA(norm(hypot(1,t2,3+3im) - hypot(1,2,3+3im))) - @FastGTPSA(norm(hypot(1+1im,2,t3) - hypot(1+1im,2,3))) + @FastGTPSA(norm(hypot(ct1, ct2, t3) - hypot(1+1im,2+2im,3))) < tol + @FastGTPSA(norm(hypot(ct1, t2, ct3) - hypot(1+1im,2,3+3im))) < tol + @FastGTPSA(norm(hypot(t1, ct2, ct3) - hypot(1,2+2im,3+3im))) < tol + @FastGTPSA(norm(hypot(ct1, t2, t3) - hypot(1+1im,2,3))) < tol + @FastGTPSA(norm(hypot(t1, ct2, t3) - hypot(1,2+2im,3))) < tol + @FastGTPSA(norm(hypot(t1, t2, ct3) - hypot(1,2,3+3im))) < tol + @FastGTPSA(norm(hypot(ct1,t2,3+3im) - hypot(1+1im,2,3+3im))) < tol + @FastGTPSA(norm(hypot(t1, ct2, 3+3im) - hypot(1,2+2im,3+3im))) < tol + @FastGTPSA(norm(hypot(ct1,2+2im,t3) - hypot(1+1im,2+2im,3))) < tol + @FastGTPSA(norm(hypot(t1,2+2im,ct3) - hypot(1,2+2im,3+3im))) < tol + @FastGTPSA(norm(hypot(1+1im,ct2,t3) - hypot(1+1im,2+2im,3))) < tol + @FastGTPSA(norm(hypot(1+1im, t2, ct3) - hypot(1+1im,2,3+3im))) < tol + @FastGTPSA(norm(hypot(t1,t2,3+3im) - hypot(1,2,3+3im))) < tol + @FastGTPSA(norm(hypot(t1,2+2im,t3) - hypot(1,2+2im,3))) < tol + @FastGTPSA(norm(hypot(1+1im,t2,t3) - hypot(1+1im,2,3))) < tol + @FastGTPSA(norm(hypot(t1,2,3+3im) - hypot(1,2,3+3im))) < tol + @FastGTPSA(norm(hypot(1,t2,3+3im) - hypot(1,2,3+3im))) < tol + @FastGTPSA(norm(hypot(1+1im,2,t3) - hypot(1+1im,2,3))) < tol # Make sure stack is 0: desc = unsafe_load(Base.unsafe_convert(Ptr{Desc}, unsafe_load(t1.tpsa).d)) @@ -1001,115 +1014,117 @@ function type_stable_test() ctmpidx = unsafe_load(desc.cti) ctmpidx == 0 tmpidx == 0 + d = Descriptor(1, 5) t = TPS(use=d) - t[0] = 0.5; t[1] = 2; t[2] = 3; t[3] = 4; t[4] = 5; t[5] = 6 + t[0] = 0.5; t[[1]] = 2; t[[2]] = 3; t[[3]] = 4; t[[4]] = 5; t[[5]] = 6 tol = 1e-10 - @FastGTPSA(norm(sin(t)^2+cos(t)^2 - 1)) - @FastGTPSA(norm(1/sin(t) - csc(t))) - @FastGTPSA(norm(1/cos(t) - sec(t))) - @FastGTPSA(norm(1/tan(t) - cot(t))) - @FastGTPSA(norm(sin(t)/cos(t) - tan(t))) - @FastGTPSA(norm(cos(2*t) - cos(t)^2 + sin(t)^2)) - @FastGTPSA(norm(sec(t)^2 - 1 - tan(t)^2)) - @FastGTPSA(norm(sin(t/2) - sqrt((1-cos(t))/2))) - @FastGTPSA(norm(cos(t/2) - sqrt((1+cos(t))/2))) - @FastGTPSA(norm(sqrt(t^2) - abs(t))) - @FastGTPSA(norm(csc(t)^2 - cot(t)^2 - 1)) - @FastGTPSA(norm(exp(log(t)) - t)) - @FastGTPSA(norm(log(exp(t)) - t)) - @FastGTPSA(norm(log(exp(t)) - exp(log(t)))) - @FastGTPSA(norm(log(t^2) - 2*log(t))) - @FastGTPSA(norm(5*log(t) - log(t^5))) - @FastGTPSA(norm(t*log(5) - log(5^t))) - @FastGTPSA(norm(sinc(t) - sin(pi*t)/(pi*t))) - @FastGTPSA(norm(sinhc(t/pi) - sinh(t)/t)) - @FastGTPSA(norm(exp(im*t) - cos(t) - im*sin(t))) - @FastGTPSA(norm(real(exp(im*t)) - cos(t))) - @FastGTPSA(norm(imag(exp(im*t)) - sin(t))) - @FastGTPSA(norm(sinh(t) - (exp(t) - exp(-t))/2)) - @FastGTPSA(norm(cosh(t) - (exp(t) + exp(-t))/2)) - @FastGTPSA(norm(tanh(t) - sinh(t)/cosh(t))) - @FastGTPSA(norm(csch(t) - 1/sinh(t))) - @FastGTPSA(norm(sech(t) - 1/cosh(t))) - @FastGTPSA(norm(coth(t) - cosh(t)/sinh(t))) - @FastGTPSA(norm(coth(t) - 1/tanh(t))) - @FastGTPSA(norm(cosh(t)^2 - sinh(t)^2 - 1)) - @FastGTPSA(norm(1 - tanh(t)^2 - sech(t)^2)) - @FastGTPSA(norm(coth(t)^2 - 1 - csch(t)^2)) - @FastGTPSA(norm(asin(sin(t)) - t)) - @FastGTPSA(norm(acos(cos(t)) - t)) - @FastGTPSA(norm(atan(tan(t)) - t)) - @FastGTPSA(norm(acsc(1/t) - asin(t))) - @FastGTPSA(norm(asec(1/t) - acos(t))) - @FastGTPSA(norm(acot(1/t) - atan(t))) - @FastGTPSA(norm(asinh(sinh(t)) - t)) - @FastGTPSA(norm(acosh(cosh(t)) - t)) - @FastGTPSA(norm(atanh(tanh(t)) - t)) - @FastGTPSA(norm(acsch(t) - asinh(1/t))) - @FastGTPSA(norm(asech(t) - acosh(1/t))) - @FastGTPSA(norm(acoth(1/t) - atanh(t))) - @FastGTPSA(norm(asinc(t/pi) - asin(t)/t)) - @FastGTPSA(norm(asinhc(t/pi) - asinh(t)/t)) - @FastGTPSA(norm(erfc(t) - 1 + erf(t))) - @FastGTPSA(norm(erf(-t) + erf(t))) - @FastGTPSA(norm(angle(t))) - @FastGTPSA(norm(complex(t) - t)) - @FastGTPSA(norm(complex(t,t) - (t+im*t))) + @FastGTPSA(norm(sin(t)^2+cos(t)^2 - 1)) < tol + @FastGTPSA(norm(1/sin(t) - csc(t))) < tol + @FastGTPSA(norm(1/cos(t) - sec(t))) < tol + @FastGTPSA(norm(1/tan(t) - cot(t))) < tol + @FastGTPSA(norm(sin(t)/cos(t) - tan(t))) < tol + @FastGTPSA(norm(cos(2*t) - cos(t)^2 + sin(t)^2)) < tol + @FastGTPSA(norm(sec(t)^2 - 1 - tan(t)^2)) < tol + @FastGTPSA(norm(sin(t/2) - sqrt((1-cos(t))/2))) < tol + @FastGTPSA(norm(cos(t/2) - sqrt((1+cos(t))/2))) < tol + @FastGTPSA(norm(sqrt(t^2) - abs(t))) < tol + @FastGTPSA(norm(csc(t)^2 - cot(t)^2 - 1)) < tol + @FastGTPSA(norm(exp(log(t)) - t)) < tol + @FastGTPSA(norm(log(exp(t)) - t)) < tol + @FastGTPSA(norm(log(exp(t)) - exp(log(t)))) < tol + @FastGTPSA(norm(log(t^2) - 2*log(t))) < tol + @FastGTPSA(norm(5*log(t) - log(t^5))) < tol + @FastGTPSA(norm(t*log(5) - log(5^t))) < tol + @FastGTPSA(norm(sinc(t) - sin(pi*t)/(pi*t))) < tol + @FastGTPSA(norm(sinhc(t/pi) - sinh(t)/t)) < tol + @FastGTPSA(norm(exp(im*t) - cos(t) - im*sin(t))) < tol + @FastGTPSA(norm(real(exp(im*t)) - cos(t))) < tol + @FastGTPSA(norm(imag(exp(im*t)) - sin(t))) < tol + @FastGTPSA(norm(sinh(t) - (exp(t) - exp(-t))/2)) < tol + @FastGTPSA(norm(cosh(t) - (exp(t) + exp(-t))/2)) < tol + @FastGTPSA(norm(tanh(t) - sinh(t)/cosh(t))) < tol + @FastGTPSA(norm(csch(t) - 1/sinh(t))) < tol + @FastGTPSA(norm(sech(t) - 1/cosh(t))) < tol + @FastGTPSA(norm(coth(t) - cosh(t)/sinh(t))) < tol + @FastGTPSA(norm(coth(t) - 1/tanh(t))) < tol + @FastGTPSA(norm(cosh(t)^2 - sinh(t)^2 - 1)) < tol + @FastGTPSA(norm(1 - tanh(t)^2 - sech(t)^2)) < tol + @FastGTPSA(norm(coth(t)^2 - 1 - csch(t)^2)) < tol + @FastGTPSA(norm(asin(sin(t)) - t)) < tol + @FastGTPSA(norm(acos(cos(t)) - t)) < tol + @FastGTPSA(norm(atan(tan(t)) - t)) < tol + @FastGTPSA(norm(acsc(1/t) - asin(t))) < tol + @FastGTPSA(norm(asec(1/t) - acos(t))) < tol + @FastGTPSA(norm(acot(1/t) - atan(t))) < tol + @FastGTPSA(norm(asinh(sinh(t)) - t)) < tol + @FastGTPSA(norm(acosh(cosh(t)) - t)) < tol + @FastGTPSA(norm(atanh(tanh(t)) - t)) < tol + @FastGTPSA(norm(acsch(t) - asinh(1/t))) < tol + @FastGTPSA(norm(asech(t) - acosh(1/t))) < tol + @FastGTPSA(norm(acoth(1/t) - atanh(t))) < tol + @FastGTPSA(norm(asinc(t/pi) - asin(t)/t)) < tol + @FastGTPSA(norm(asinhc(t/pi) - asinh(t)/t)) < tol + @FastGTPSA(norm(erfc(t) - 1 + erf(t))) < tol + @FastGTPSA(norm(erf(-t) + erf(t))) < tol + @FastGTPSA(norm(angle(t))) < tol + @FastGTPSA(norm(complex(t) - t)) < tol + @FastGTPSA(norm(complex(t,t) - (t+im*t))) < tol t = ComplexTPS(t) - t[0] = 0.5+0.5im; t[1] = 2+2im; t[2] = 3+3im; t[3] = 4+4im; t[4] = 5+5im; t[5] = 6+6im - @FastGTPSA(norm(sin(t)^2+cos(t)^2 - 1)) - @FastGTPSA(norm(1/sin(t) - csc(t))) - @FastGTPSA(norm(1/cos(t) - sec(t))) - @FastGTPSA(norm(1/tan(t) - cot(t))) - @FastGTPSA(norm(sin(t)/cos(t) - tan(t))) - @FastGTPSA(norm(cos(2*t) - cos(t)^2 + sin(t)^2)) - @FastGTPSA(norm(sec(t)^2 - 1 - tan(t)^2)) - @FastGTPSA(norm(sin(t/2) - sqrt((1-cos(t))/2))) - @FastGTPSA(norm(cos(t/2) - sqrt((1+cos(t))/2))) - @FastGTPSA(norm(sqrt(t^2) - t)) - @FastGTPSA(norm(csc(t)^2 - cot(t)^2 - 1)) - @FastGTPSA(norm(exp(log(t)) - t)) - @FastGTPSA(norm(log(exp(t)) - t)) - @FastGTPSA(norm(log(exp(t)) - exp(log(t)))) - @FastGTPSA(norm(log(t^2) - 2*log(t))) - @FastGTPSA(norm(5*log(t) - log(t^5) - 2*pi*im)) - @FastGTPSA(norm(t*log(5) - log(5^t))) - @FastGTPSA(norm(sinc(t/pi) - sin(t)/t)) - @FastGTPSA(norm(sinhc(t/pi) - sinh(t)/t)) - @FastGTPSA(norm(exp(im*t) - cos(t) - im*sin(t))) - @FastGTPSA(norm(sinh(t) - (exp(t) - exp(-t))/2)) - @FastGTPSA(norm(cosh(t) - (exp(t) + exp(-t))/2)) - @FastGTPSA(norm(tanh(t) - sinh(t)/cosh(t))) - @FastGTPSA(norm(csch(t) - 1/sinh(t))) - @FastGTPSA(norm(sech(t) - 1/cosh(t))) - @FastGTPSA(norm(coth(t) - cosh(t)/sinh(t))) - @FastGTPSA(norm(coth(t) - 1/tanh(t))) - @FastGTPSA(norm(cosh(t)^2 - sinh(t)^2 - 1)) - @FastGTPSA(norm(1 - tanh(t)^2 - sech(t)^2)) - @FastGTPSA(norm(coth(t)^2 - 1 - csch(t)^2)) - - @FastGTPSA(norm(asin(sin(t)) - t)) - @FastGTPSA(norm(acos(cos(t)) - t)) - @FastGTPSA(norm(atan(tan(t)) - t)) - @FastGTPSA(norm(acsc(t) - asin(1/t))) - @FastGTPSA(norm(asec(t) - acos(1/t))) - @FastGTPSA(norm(acot(t) - acot(1/t))) - @FastGTPSA(norm(asinh(sinh(t)) - t)) - @FastGTPSA(norm(acosh(cosh(t)) - t)) - @FastGTPSA(norm(atanh(tanh(t)) - t)) - @FastGTPSA(norm(acsch(t) - asinh(1/t))) - @FastGTPSA(norm(asech(t) - acosh(1/t))) - @FastGTPSA(norm(acoth(t) - acoth(1/t))) - @FastGTPSA(norm(asinc(t) - asin(t)/t)) - @FastGTPSA(norm(asinhc(t) - asinh(t)/t)) - @FastGTPSA(norm(erfc(t) - 1 + erf(t))) - @FastGTPSA(norm(erf(-t) + erf(t))) - @FastGTPSA(norm(angle(t) - atan(imag(t),real(t)))) - @FastGTPSA(norm(complex(t) - t)) + t[0] = 0.5+0.5im; t[[1]] = 2+2im; t[[2]] = 3+3im; t[[3]] = 4+4im; t[[4]] = 5+5im; t[[5]] = 6+6im + @FastGTPSA(norm(sin(t)^2+cos(t)^2 - 1)) < tol + @FastGTPSA(norm(1/sin(t) - csc(t))) < tol + @FastGTPSA(norm(1/cos(t) - sec(t))) < tol + @FastGTPSA(norm(1/tan(t) - cot(t))) < tol + @FastGTPSA(norm(sin(t)/cos(t) - tan(t))) < tol + @FastGTPSA(norm(cos(2*t) - cos(t)^2 + sin(t)^2)) < tol + @FastGTPSA(norm(sec(t)^2 - 1 - tan(t)^2)) < tol + @FastGTPSA(norm(sin(t/2) - sqrt((1-cos(t))/2))) < tol + @FastGTPSA(norm(cos(t/2) - sqrt((1+cos(t))/2))) < tol + @FastGTPSA(norm(sqrt(t^2) - t)) < tol + @FastGTPSA(norm(csc(t)^2 - cot(t)^2 - 1)) < tol + @FastGTPSA(norm(exp(log(t)) - t)) < tol + @FastGTPSA(norm(log(exp(t)) - t)) < tol + @FastGTPSA(norm(log(exp(t)) - exp(log(t)))) < tol + @FastGTPSA(norm(log(t^2) - 2*log(t))) < tol + @FastGTPSA(norm(5*log(t) - log(t^5) - 2*pi*im)) < tol + @FastGTPSA(norm(t*log(5) - log(5^t))) < tol + @FastGTPSA(norm(sinc(t/pi) - sin(t)/t)) < tol + @FastGTPSA(norm(sinhc(t/pi) - sinh(t)/t)) < tol + @FastGTPSA(norm(exp(im*t) - cos(t) - im*sin(t))) < tol + @FastGTPSA(norm(sinh(t) - (exp(t) - exp(-t))/2)) < tol + @FastGTPSA(norm(cosh(t) - (exp(t) + exp(-t))/2)) < tol + @FastGTPSA(norm(tanh(t) - sinh(t)/cosh(t))) < tol + @FastGTPSA(norm(csch(t) - 1/sinh(t))) < tol + @FastGTPSA(norm(sech(t) - 1/cosh(t))) < tol + @FastGTPSA(norm(coth(t) - cosh(t)/sinh(t))) < tol + @FastGTPSA(norm(coth(t) - 1/tanh(t))) < tol + @FastGTPSA(norm(cosh(t)^2 - sinh(t)^2 - 1)) < tol + @FastGTPSA(norm(1 - tanh(t)^2 - sech(t)^2)) < tol + @FastGTPSA(norm(coth(t)^2 - 1 - csch(t)^2)) < tol + + @FastGTPSA(norm(asin(sin(t)) - t)) < tol + @FastGTPSA(norm(acos(cos(t)) - t)) < tol + @FastGTPSA(norm(atan(tan(t)) - t)) < tol + @FastGTPSA(norm(acsc(t) - asin(1/t))) < tol + @FastGTPSA(norm(asec(t) - acos(1/t))) < tol + @FastGTPSA(norm(acot(t) - atan(1/t))) < tol + @FastGTPSA(norm(asinh(sinh(t)) - t)) < tol + @FastGTPSA(norm(acosh(cosh(t)) - t)) < tol + @FastGTPSA(norm(atanh(tanh(t)) - t)) < tol + @FastGTPSA(norm(acsch(t) - asinh(1/t))) < tol + @FastGTPSA(norm(asech(t) - acosh(1/t))) < tol + @FastGTPSA(norm(acoth(t) - atanh(1/t))) < tol + @FastGTPSA(norm(asinc(t/pi) - asin(t)/t)) < tol + @FastGTPSA(norm(asinhc(t/pi) - asinh(t)/t)) < tol + + @FastGTPSA(norm(erfc(t) - 1 + erf(t))) < tol + @FastGTPSA(norm(erf(-t) + erf(t))) < tol + @FastGTPSA(norm(angle(t) - atan(imag(t),real(t)))) < tol + @FastGTPSA(norm(complex(t) - t)) < tol # Make sure stack is 0: desc = unsafe_load(Base.unsafe_convert(Ptr{Desc}, unsafe_load(t.tpsa).d)) From 0b170e26a3205481cbe38625f3a519c768d3c222 Mon Sep 17 00:00:00 2001 From: mattsignorelli Date: Mon, 1 Apr 2024 16:14:16 -0400 Subject: [PATCH 04/29] slicing and par updated --- = | 0 src/GTPSA.jl | 2 +- src/getset.jl | 64 ++++++++++++++++++++++++++++----------------------- 3 files changed, 36 insertions(+), 30 deletions(-) create mode 100644 = diff --git a/= b/= new file mode 100644 index 00000000..e69de29b diff --git a/src/GTPSA.jl b/src/GTPSA.jl index 813d4aa4..34415324 100644 --- a/src/GTPSA.jl +++ b/src/GTPSA.jl @@ -835,7 +835,7 @@ function pairs_to_sm(t::Union{TPS,ComplexTPS}, vars::Union{Vector{<:Pair{<:Integ end # Function to convert var=>ord, params=(param=>ord,) to monomial format (byte array of orders) -function pairs_to_m(t::Union{TPS,ComplexTPS}, vars::Union{Vector{<:Pair{<:Integer, <:Integer}},Tuple{Vararg{Pair{<:Integer,<:Integer}}}}; params::Vector{<:Pair{<:Integer,<:Integer}}=Pair{Int,Int}[],zero_mono=true)::Tuple{Vector{UInt8}, Cint} +function pairs_to_m(t::Union{TPS,ComplexTPS}, vars::Union{Vector{<:Pair{<:Integer, <:Integer}},Tuple{Vararg{Pair{<:Integer,<:Integer}}}}; params::Union{Vector{<:Pair{<:Integer, <:Integer}},Tuple{Vararg{Pair{<:Integer,<:Integer}}}}=Pair{Int,Int}[],zero_mono=true)::Tuple{Vector{UInt8}, Cint} nv = numvars(t) n = Cint(0) if isempty(params) diff --git a/src/getset.jl b/src/getset.jl index 4388b86d..16fca452 100644 --- a/src/getset.jl +++ b/src/getset.jl @@ -120,17 +120,24 @@ lowget(t, idx, param, params) = error("Invalid monomial index specified. Please # --- Slicing (getter) --- -#= -function getindex(t::Union{TPS,ComplexTPS}, ords::Union{Integer,Colon}...) - return slice(t, setup_mono(t,ords,nothing,nothing), false) -end -function getindex(t::Union{TPS,ComplexTPS}, vars::Union{Pair{<:Integer, <:Integer}, Colon}...; params::Vector{<:Pair{<:Integer,<:Integer}}=Pair{Int,Int}[]) - return slice(t, setup_mono(t, vars, nothing, params), false) +# Vectors (which will be Vector{Any}) must be converted to tuples so SM or M indexing can be resolved: +const SMColonIndexType = Tuple{Vararg{<:Union{Pair{<:Integer,<:Integer},<:Colon}}} +const MColonIndexType =Tuple{Vararg{<:Union{<:Integer,<:Colon}}} +const TPSColonIndexType = Union{Integer, Colon, + MColonIndexType, + SMColonIndexType, + Vector{<:Any}} + +function getindex(t::Union{TPS,ComplexTPS}, v::TPSColonIndexType; param::Union{<:Integer,Nothing}=nothing, params::Union{SMIndexType, Nothing}=nothing) + if (v isa Vector) + par_mono = setup_mono(t, tuple(v...), param, params) + else + par_mono = setup_mono(t, v, param, params) + end + return slice(t, par_mono, false) end -getindex(t::Union{TPS,ComplexTPS}) = t -=# # --- par --- """ @@ -200,16 +207,21 @@ TPS: 3.0000000000000000e+00 7 2 1 1 2 1 | 0 0 ``` """ -function par(t::Union{TPS,ComplexTPS}, v::Union{Integer, Vector{<:Union{<:Pair{<:Integer,<:Integer},<:Integer, <:Any}}, Tuple{Vararg{Union{<:Integer,Pair{<:Integer,<:Integer},<:Colon}}}, Nothing}=nothing; param::Union{<:Integer,Nothing}=nothing, params::Union{Vector{<:Pair{<:Integer,<:Integer}}, Nothing}=nothing) - if (v isa Vector) && !(last(v) isa Colon) - par_mono = setup_mono(t, tuple(v...,:), param, params) +function par(t::Union{TPS,ComplexTPS}, v::Union{TPSColonIndexType, Vector{Pair{<:Integer,<:Integer}}, Vector{<:Integer}, Nothing}=nothing; param::Union{<:Integer,Nothing}=nothing, params::Union{SMIndexType, Nothing}=nothing) + if (v isa Vector) + tmpv = tuple(v...) + if tmpv isa MColonIndexType # because par-ing, must add colon + par_mono = setup_mono(t, tuple(tmpv...,:), param, params) + else + par_mono = setup_mono(t, tmpv, param, params) + end else par_mono = setup_mono(t, v, param, params) end return slice(t, par_mono) end -# Variable/parameter: +# Flat index: function setup_mono(t1::Union{TPS,ComplexTPS}, v::Integer, param::Nothing, params::Nothing)::Vector{Cuchar} par_mono = ones(Cuchar, v+1).*0xff par_mono[v] = 0x1 @@ -222,37 +234,32 @@ function setup_mono(t1::Union{TPS,ComplexTPS}, v::Nothing, param::Integer, param par_mono[nv+param] = 0x1 return par_mono end -#= -# Default to scalar part as TPS if nothing passed: -function setup_mono(t1::Union{TPS,ComplexTPS}, v::Nothing, param::Nothing, params::Nothing)::Vector{Cuchar} - return [0x0] -end -=# + # Monomial by order: # This one should ALWAYS be called by par or splicing colon IS in the tuple or vector somewhere -function setup_mono(t1::Union{TPS,ComplexTPS}, v::Union{Tuple{Vararg{Union{<:Integer,<:Colon}}},Vector{<:Any}}, param::Nothing, params::Nothing)::Vector{Cuchar} +function setup_mono(t1::Union{TPS,ComplexTPS}, v::MColonIndexType, param::Nothing, params::Nothing)::Vector{Cuchar} return collect(replace(x-> x isa Colon ? 0xff::Cuchar : convert(Cuchar, x)::Cuchar, v)) end # By definition, sparse monomial makes everything else zero. SO if we reach this, it is automatically # assumed that everything else is colon except those explictly made ix_var=>0 # Monomial by sparse monomial: -function setup_mono(t1::Union{TPS,ComplexTPS}, v::Union{Vector{<:Pair{<:Integer,<:Integer}}, Tuple{Vararg{Union{Pair{<:Integer,<:Integer},<:Colon}}}}, param::Nothing, params::Vector{<:Pair{<:Integer,<:Integer}})::Vector{Cuchar} +function setup_mono(t1::Union{TPS,ComplexTPS}, v::SMColonIndexType, param::Nothing, params::SMIndexType)::Vector{Cuchar} # Need to create array of orders with length nv + np ords, ___ = pairs_to_m(t1,filter(x->!(x isa Colon), v),params=params,zero_mono=false) - return [ords..., 0xff] + return vcat(ords, 0xff) end -function setup_mono(t1::Union{TPS,ComplexTPS}, v::Union{Vector{<:Pair{<:Integer,<:Integer}}, Tuple{Vararg{Union{Pair{<:Integer,<:Integer},<:Colon}}}}, param::Nothing, params::Nothing)::Vector{Cuchar} +function setup_mono(t1::Union{TPS,ComplexTPS}, v::SMColonIndexType, param::Nothing, params::Nothing)::Vector{Cuchar} # Need to create array of orders with length nv + np ords, ___ = pairs_to_m(t1,filter(x->!(x isa Colon), v),zero_mono=false) - return [ords..., 0xff] + return vcat(ords, 0xff) end -function setup_mono(t1::Union{TPS,ComplexTPS}, v::Nothing, param::Nothing, params::Vector{<:Pair{<:Integer,<:Integer}})::Vector{Cuchar} +function setup_mono(t1::Union{TPS,ComplexTPS}, v::Nothing, param::Nothing, params::SMIndexType)::Vector{Cuchar} # Need to create array of orders with length nv + np ords, ___ = pairs_to_m(t1,Pair{Int,Int}[],params=params,zero_mono=false) - return [ords..., 0xff] + return vcat(ords, 0xff) end @@ -280,10 +287,9 @@ function slice(t1::Union{TPS,ComplexTPS}, par_mono::Vector{Cuchar}, par_it=true) tmp = zeros(Cuchar, np+nv) tmp[invalid_idxs] .= mono[invalid_idxs] tmp[v+1:end] .= mono[v+1:end] - t[tmp...] = coef[] + t[tmp] = coef[] else - t[mono...] = coef[] - + t[mono] = coef[] end end end @@ -405,7 +411,7 @@ function jacobian(m::Vector{<:Union{TPS,ComplexTPS}}; include_params=false) J = Matrix{numtype(first(m))}(undef, length(m), n) grad = Vector{numtype(first(m))}(undef, n) for i=1:length(m) - mad_tpsa_getv!(m[i].tpsa, Cint(1), n, grad) + getv!(m[i].tpsa, Cint(1), n, grad) J[i,:] = grad end return J From cc14187ae1b7621b68445f892f33bbebce966666 Mon Sep 17 00:00:00 2001 From: mattsignorelli Date: Tue, 2 Apr 2024 11:25:10 -0400 Subject: [PATCH 05/29] lots of dev, reorganization, indexing --- = | 0 docs/src/man/g_monoindex.md | 52 ++- docs/src/man/h_mono.md | 26 +- docs/src/man/j_slice.md | 36 +- docs/src/quickstart.md | 55 ++- src/GTPSA.jl | 811 +----------------------------------- src/ctors.jl | 241 +++++++++++ src/descriptor.jl | 89 ++++ src/getset.jl | 75 ++-- src/global.jl | 47 +++ src/low.jl | 6 + src/methods.jl | 20 +- src/tps.jl | 248 +++++++++++ src/utils.jl | 150 +++++++ 14 files changed, 963 insertions(+), 893 deletions(-) delete mode 100644 = create mode 100644 src/ctors.jl create mode 100644 src/descriptor.jl create mode 100644 src/global.jl create mode 100644 src/low.jl create mode 100644 src/tps.jl create mode 100644 src/utils.jl diff --git a/= b/= deleted file mode 100644 index e69de29b..00000000 diff --git a/docs/src/man/g_monoindex.md b/docs/src/man/g_monoindex.md index 8a9d41ac..d079cd7f 100644 --- a/docs/src/man/g_monoindex.md +++ b/docs/src/man/g_monoindex.md @@ -4,9 +4,12 @@ Individual monomial coefficients in a TPS can be get/set with two methods of indexing: **by order**, and **by sparse monomial**. ## By Order -`t[, ..., ,, ..., ]` +``` +t[[, ..., ,, ..., ]] +t[(, ..., ,, ..., )] +``` -A particular monomial can be indexed by specifying the orders of each variable and parameter. For example, for a TPS `t` with variables ``x_1``, ``x_2`` and parameter ``k_1`` the ``x_1^3x_2^1k_1^2`` monomial coefficient is accessed with `t[3,1,2]`. The 0th order part (the *scalar* part) of the TPS is indexed with `t[0,0,0]` or equivalently `t[0]`, as leaving out trailing zeros for unincluded variables/parameters is allowed. +A particular monomial can be indexed by specifying the orders of each variable and parameter. For example, for a TPS `t` with variables ``x_1``, ``x_2`` and parameters ``k_1``, ``k_2``, the ``x_1^3x_2^1k_1^2`` monomial coefficient is accessed with `t[[3,1,2,0]]` or equivalently `t[[3,1,2]]`, as leaving out trailing zeros for unincluded variables/parameters is allowed. A tuple is also allowed instead of a vector for the list of orders. ### Examples ```@repl @@ -15,16 +18,19 @@ d = Descriptor(2, 6, 3, 6); # 2 variables, 3 parameters all to 6th order x = vars(d); k = params(d); f = 5 + sin(x[1])*sin(x[2])*cos(k[1]) -f[3,1,2] # Leave out trailing zeros for unincluded variables/parameters -f[0] # Scalar part -f[1,1,1,1,1] = 123; # Set monomial coefficient +f[[3,1,2]] # Leave out trailing zeros for unincluded variables/parameters +f[[0]] # Scalar part +f[(1,1,1,1,1)] = 123; # Set monomial coefficient print(f) ``` ## By Sparse Monomial -`t[ => , ..., params=[ => , ...]]` +``` +t[[ => , ...], params=[ => , ...]] +t[( => , ...), params=( => , ...)] +``` -In GTPSAs with many variables and parameters, indexing-by-order is inconvenient because each order needs to be included up to the last included variable/parameter with nonzero order. In this case, a particular monomial can be indexed instead by specifying each variable/parameter number and its corresponding order in pairs. For example, for a TPS with variables ``x_1, ..., x_{15}`` and parameters ``k_1, ..., k_{10}``, the ``x_{1}^3x_{15}^1k_{10}^2`` monomial coefficient is accessed with `t[1=>3, 15=>1, params=[10=>2]]`. The scalar part of the TPS cannot be get/set with this method. +In GTPSAs with many variables and parameters, indexing-by-order is inconvenient because each order needs to be included up to the last included variable/parameter with nonzero order. In this case, a particular monomial can be indexed instead by specifying each variable/parameter number and its corresponding order in pairs. For example, for a TPS with variables ``x_1, ..., x_{15}`` and parameters ``k_1, ..., k_{10}``, the ``x_{1}^3x_{15}^1k_{10}^2`` monomial coefficient is accessed with `t[[1=>3, 15=>1], params=[10=>2]]`. The scalar part of the TPS cannot be get/set with this method. A tuple is also allowed instead of a vector for the list of pairs. ### Examples ```@repl @@ -34,11 +40,39 @@ GTPSA.show_sparse = true; # Use sparse output x = vars(d); k = params(d); f = 5 + sin(x[1])*sin(x[15])*cos(k[10]) -f[1=>3, 15=>1, params=[10=>2]] -f[1=>1, 15=>2, params=[10=>3]] = 123; # Set monomial coefficient +f[[1=>3, 15=>1], params=[10=>2]] +f[(1=>1, 15=>2), params=(10=>3,)] = 123; # Set monomial coefficient print(f) ``` +## By Monomial Index +``` +t[idx] +t[param=param_idx] +``` + +*This indexing method is not recommended/requires care when indexing monomials above first order.* Indexes the TPS with all monomials sorted by order. For example, for a TPS with one variable ``x_1`` and one parameter ``k_1`` the ``x_1`` monomial is indexed with `t[1]` and the ``x_1^2`` monomial is indexed with either `t[3]`. The ``k_1`` monomial can be indexed with either `t[2]` or equivalently using the `param` helper kwarg `t[param=1]`, which simply adds the number of variables in the GTPSA to the provided index. Note that above first-order, the `param` kwarg is basically useless. The zeroth order part, or the *scalar* part of the TPS, can be set with `t[0]`. This method requires zero allocations for indexing, unlike the other two. + +### Examples +```@repl +using GTPSA; GTPSA.show_sparse = false; GTPSA.show_header=false; #hide +# Example of indexing by monomial index ----------- +d = Descriptor(2, 10, 1, 10); +t = TPS(use=d); # Create zero TPS based on d + +t[0] = 0; +t[1] = 1; +t[2] = 2; +t[3] = 3; # or t[param=1] = 3 +t[4] = 4; +t[5] = 5; +t[6] = 6; +t[7] = 7; +t[8] = 8; +t[9] = 9; +t[10] = 10; +print(t) +``` diff --git a/docs/src/man/h_mono.md b/docs/src/man/h_mono.md index ea3e1587..74029593 100644 --- a/docs/src/man/h_mono.md +++ b/docs/src/man/h_mono.md @@ -2,34 +2,34 @@ *Creates a TPS corresponding to a specific monomial* ## Syntax ``` -m = mono(var_idx [, use=(descriptor|tps|complextps)]) -m = mono(param=param_idx [, use=(descriptor|tps|complextps)]) - m = mono(orders [, use=(descriptor|tps|complextps)]) m = mono([vars_sparse_mono] [, params=params_sparse_mono] [, use=(descriptor|tps|complextps)]) +m = mono(idx [, use=(descriptor|tps|complextps)]) +m = mono(param=param_idx [, use=(descriptor|tps|complextps)]) + m = complexmono(...) ``` ## Description -#### Index by Variable/Parameter - -`m = mono(var_idx)` creates a `TPS` equal to the variable specified by `var_idx` and the `Descriptor` in `GTPSA.desc_current` +#### Indexing by Order -`m = mono(param=param_idx)` creates a `TPS` equal to the parameter specified by `param_idx` and the `Descriptor` in `GTPSA.desc_current` +`m = mono(orders)` creates a `TPS` equal to the monomial specified by the indexing-by-order vector/tuple `orders` using the `Descriptor` in `GTPSA.desc_current` ------ -#### Indexing by Order +#### Indexing by Sparse Monomial -`m = mono(orders)` creates a `TPS` equal to the monomial specified by the indexing-by-order vector `orders` and the `Descriptor` in `GTPSA.desc_current` +`m = mono(vars_sparse_mono, params=params_sparse_mono)` creates a `TPS` equal to the monomial specified by the indexing-by-sparse monomial vector/tuple `vars_sparse_mono` and `params_sparse_mono` using the `Descriptor` in `GTPSA.desc_current` ------ -#### Indexing by Sparse Monomial +#### Indexing by Monomial Index + +`m = mono(idx)` creates a `TPS` equal to the monomial specified by `idx` and the `Descriptor` in `GTPSA.desc_current` -`m = mono(vars_sparse_mono, params=params_sparse_mono)` creates a `TPS` equal to the monomial specified by the indexing-by-sparse monomial vector `vars_sparse_mono` and `params_sparse_mono` and the `Descriptor` in `GTPSA.desc_current` +`m = mono(param=param_idx)` creates a `TPS` equal to the monomial specified by `param_idx + nv` where `nv` is the number of variables in the GTPSA, using the `Descriptor` in `GTPSA.desc_current` ------ @@ -50,9 +50,9 @@ d1 = Descriptor(3, 15, 2, 15); # 3 vars, 2 params, all to order 15 x1 = mono(1) k1 = mono(param=1) m312 = mono([3,1,2]) -m31221 = mono([3,1,2,2,1]) +m31221 = mono((3,1,2,2,1)) # Tuples allowed for indexing m312 = mono([1=>3, 2=>1, 3=>3]) -m31221 = mono([1=>3, 2=>1, 3=>2], params=[1=>2, 2=>1]) +m31221 = mono((1=>3, 2=>1, 3=>2), params=(1=>2, 2=>1)) ``` ## Documentation diff --git a/docs/src/man/j_slice.md b/docs/src/man/j_slice.md index d0a659f3..7ca23855 100644 --- a/docs/src/man/j_slice.md +++ b/docs/src/man/j_slice.md @@ -10,15 +10,22 @@ d = Descriptor(5, 10, 2, 10); x = vars(d); k = params(d); f = 2*x[1]^2*x[3] + 3*x[1]^2*x[2]*x[3]*x[4]^2*x[5]*k[1] + 6*x[3] + 5 -g = f[2,:,1] -h = f[2,:,1,:] +g = f[[2,:,1]] +h = f[[2,:,1,:]] ``` A TPS can also be sliced with indexing by sparse monomial. In this case, if a colon is included anywhere in the sparse monomial variable index, then all orders of all variables and parameters not explicity specified will be included (colon position does not matter in sparse monomial indexing): ```@repl slice -g = f[1=>2, :, 3=>1, 4=>0, 5=>0, params=[1=>0, 2=>0]] -h = f[1=>2, 3=>1, :] # Colon position is irrelevant in slicing with sparse monomial indexing +g = f[[1=>2, :, 3=>1, 4=>0, 5=>0], params=[1=>0, 2=>0]] +h = f[(1=>2, 3=>1, :)] # Colon position is irrelevant in slicing with sparse monomial indexing +``` + +When indexing by monomial index, a colon simply needs to be included after the variable index, or just a colon if a parameter is specified: + +```@repl slice +fx1 = f[1,:] +fk1 = f[:,param=2] ``` ## `par` @@ -30,22 +37,15 @@ h = f[1=>2, 3=>1, :] # Colon position is irrelevant in slicing with sparse mono ### Syntax ``` -f = par(tps, var_idx) -f = par(tps, param=param_idx) - f = par(tps, orders) f = par(tps [, vars_sparse_mono] [, params=params_sparse_mono]) + +f = par(tps, idx) +f = par(tps, param=param_idx) ``` ### Description -#### Index by Variable/Parameter -`f = par(tps, var_idx)` extracts the polynomial from the TPS with a first-order dependence on the specified variable, and removes the variable from the polynomial - -`f = par(tps, param=param_idx)` extracts the polynomial from the TPS with a first-order dependence on the specified parameter, and removes the parameter from the polynomial - ------- - #### Indexing by Order `f = par(tps, orders)` extracts the polynomial from the TPS with the monomial indexed-by-order in `orders`, and removes the variables/parameters included in the indexing from the polynomial @@ -58,6 +58,14 @@ f = par(tps [, vars_sparse_mono] [, params=params_sparse_mono]) `f = par(tps, vars_sparse_mono, params=params_sparse_mono)` extracts the polynomial from the TPS with the monomial indexed-by-sparse monomial in `vars_sparse_mono` and `params_sparse_mono`, and removes the variables and/or parameters included in the indexing from the polynomial +------ + +#### Indexing by Monomial Index +`f = par(tps, idx)` extracts the polynomial from the TPS with a first-order dependence on the specified monomial, and removes the variable from the polynomial + +`f = par(tps, param=param_idx)` extracts the polynomial from the TPS with a first-order dependence on the specified monomial with index `param_idx+nv` where `nv` is the number of variables in the GTPSA, and removes the parameter from the polynomial + + ### Examples ```@repl par diff --git a/docs/src/quickstart.md b/docs/src/quickstart.md index f6e5bad0..6c957a0d 100644 --- a/docs/src/quickstart.md +++ b/docs/src/quickstart.md @@ -52,12 +52,13 @@ Another global variable `GTPSA.show_eps` can be set to exclude showing monomials !!! note The value of a partial derivative is equal to the monomial coefficient in the Taylor series multiplied by a constant factor. E.g. for an expansion around zero ``f(x)\approx f(0) + \frac{\partial f}{\partial x}\rvert_0x + \frac{1}{2!}\frac{\partial^2 f}{\partial x^2}\rvert_0 x^2 + ...``, the 2nd order monomial coefficient is ``\frac{1}{2!}\frac{\partial^2 f}{\partial x^2}\rvert_0``. -Individual monomial coefficients in a TPS `t` can be get/set with two methods of indexing: +Individual monomial coefficients in a TPS `t` can be get/set with three methods of indexing: -1. **By Order:** `t[, ..., ]`. For example, for a TPS with variables ``x_1``, ``x_2``, the ``x_1^3x_2^1`` monomial coefficient is accessed with `t[3,1]`. The 0th order part (the *scalar* part) of the TPS is indexed with `t[0,0]` or equivalently `t[0]`, as leaving out trailing zeros for unincluded variables is allowed. -2. **By Sparse Monomial** `t[ => , ...]`. This method of indexing is convenient when a TPS contains many variables and parameters. For example, for a TPS with variables ``x_1,x_2,...x_{100}``, the ``x_{1}^3x_{99}^1`` monomial coefficient is accessed with `t[1=>3, 99=>1]`. The scalar part of the TPS cannot be get/set with this method. +1. **By Order:** `t[[, ..., ]]`. For example, for a TPS with three variables ``x_1``, ``x_2``, and ``x_3``, the ``x_1^3x_2^1`` monomial coefficient is accessed with `t[[3,1,0]]` or equivalently `t[[3,1]]`, as leaving out trailing zeros for unincluded variables is allowed. A tuple is also allowed instead of a vector for the list of orders. +2. **By Sparse Monomial** `t[[ => , ...]]`. This method of indexing is convenient when a TPS contains many variables and parameters. For example, for a TPS with variables ``x_1,x_2,...x_{100}``, the ``x_{1}^3x_{99}^1`` monomial coefficient is accessed with `t[[1=>3, 99=>1]]`. A tuple is also allowed instead of a vector for the list of pairs. +3. **By Monomial Index** `t[idx]`. *This method is not recommended for indexing above first order.* Indexes the TPS with all monomials sorted by order. For example, for a TPS with two variables ``x_1`` and ``x_2``, the ``x_1`` monomial is indexed with `t[1]` and the ``x_1^2`` monomial is indexed with `t[3]`. The zeroth order part, or the *scalar* part of the TPS, can be set with `t[0]`. This method requires zero allocations for indexing, unlike the other two. -These two methods of indexing are best shown with an example: +These three methods of indexing are best shown with an example: ```@example using GTPSA; GTPSA.show_header=false; GTPSA.show_sparse=false;#hide @@ -65,11 +66,11 @@ using GTPSA; GTPSA.show_header=false; GTPSA.show_sparse=false;#hide d = Descriptor(3, 10); t = TPS(use=d); # Create zero TPS based on d -t[0] = 1; -t[1] = 2; -t[0,1] = 3; -t[0,0,1] = 4; -t[2,1,3] = 5; +t[[0]] = 1; +t[[1]] = 2; +t[[0,1]] = 3; +t[(0,0,1)] = 4; # Tuples also allowed +t[(2,1,3)] = 5; print(t) ``` @@ -80,14 +81,34 @@ using GTPSA; GTPSA.show_header=false; GTPSA.show_sparse=false; #hide d = Descriptor(3, 10); t = TPS(use=d); # Create zero TPS based on d -t[1=>1] = 2; -t[2=>1] = 3; -t[3=>1] = 4; -t[1=>2,2=>1,3=>3] = 5; +t[[1=>1]] = 2; +t[[2=>1]] = 3; +t[[3=>1]] = 4; +t[(1=>2,2=>1,3=>3)] = 5; # Tuples also allowed print(t) ``` +```@example +using GTPSA; GTPSA.show_sparse = false; GTPSA.show_header=false; #hide +# Example of indexing by monomial index ----------- +d = Descriptor(3, 10); +t = TPS(use=d); # Create zero TPS based on d + +t[0] = 0; +t[1] = 1; +t[2] = 2; +t[3] = 3; +t[4] = 4; +t[5] = 5; +t[6] = 6; +t[7] = 7; +t[8] = 8; +t[9] = 9; +t[10] = 10; +print(t) +``` + ### Gradients, Jacobians, Hessians The convenience getters `gradient`, `jacobian`, and `hessian` (as well as their corresponding in-place methods `gradient!`, `jacobian!`, and `hessian!`) are also provided for extracting partial derivatives from a TPS/Vector of TPSs. Note that these functions are not actually calculating anything - at this point the TPS should already have been propagated through the system, and these functions are just extracting the corresponding partial derivatives. @@ -119,8 +140,8 @@ d = Descriptor(5, 10); x = vars(d); f = 2*x[1]^2*x[3] + 3*x[1]^2*x[2]*x[3]*x[4]^2*x[5] + 6*x[3] + 5; -g = f[2,:,1]; -h = f[2,:,1,:]; +g = f[[2,:,1]]; +h = f[[2,:,1,:]]; print(f) print(g) @@ -131,8 +152,8 @@ A TPS can also be sliced with indexing by sparse monomial. In this case, if a co ```@example slice # Colon position does not matter in sparse-monomial indexing -g = f[1=>2, :, 3=>1, 4=>0, 5=>0]; -h = f[1=>2, 3=>1, :]; +g = f[[1=>2, :, 3=>1, 4=>0, 5=>0]]; +h = f[[1=>2, 3=>1, :]]; print(g) diff --git a/src/GTPSA.jl b/src/GTPSA.jl index 34415324..6d410697 100644 --- a/src/GTPSA.jl +++ b/src/GTPSA.jl @@ -79,6 +79,7 @@ export norm, polar, rect, + clear!, # Monomial as TPS creators: vars, @@ -119,7 +120,6 @@ export scalar, setGTPSA!, getGTPSA, - clear!, # Temporaries: @FastGTPSA, @@ -133,803 +133,16 @@ export __t_asech, __t_acoth, __t_real, __t_imag, __t_conj, __t_angle, __t_complex, __t_sinhc, __t_asinc, __t_asinhc, __t_erf, __t_erfc, __t_norm, __t_polar, __t_rect +include("low.jl") # Low level, 1-to-1 Julia-to-C code including C struct definitions +include("descriptor.jl") # Descriptor struct and constructors +include("global.jl") # Global variables +include("tps.jl") # TPS/ComplexTPS structs and constructors +include("utils.jl") # Utility functions including changing Descriptor of TPS +include("ctors.jl") # Convenience constructors (vars, params, mono) +include("getset.jl") # Indexing/slicing TPS, par, convenience getters (gradient, jacobian, hessian) +include("show.jl") # Output +include("operators.jl") # TPS math overloaded operators/functions +include("methods.jl") # Higher-level TPS functions (derivatives, integrals, evaluate, etc) +include("fast_gtpsa.jl") # Everything for the @FastGTPSA macro - -# Low-level functions/structs and constants -const NAMSZ::Int = 16 -include("low_level/mono.jl") -include("low_level/desc.jl") -include("low_level/rtpsa.jl") -include("low_level/ctpsa.jl") - -const MAD_TPSA::String = :("libgtpsa") -const MAD_TPSA_DEFAULT::Cuchar = 255 -const MAD_TPSA_SAME::Cuchar = 254 -const MAD_DESC_CURR::Ptr{Desc} = C_NULL -const DESC_MAX_TMP::Int = 8 - -# Wrapper struct for Ptr{Desc} -struct Descriptor - desc::Ptr{Desc} - function Descriptor(desc::Ptr{Desc})::Descriptor - d = new(desc) - return d - end -end - -# Global non-constants (types MUST be specified) -desc_current::Descriptor = Descriptor(MAD_DESC_CURR) # Current Descriptor -show_eps::Float64 = 0.0 # Print epsilon -show_sparse::Bool = false # Use sparse monomial print -show_header::Bool = false # Print a header above each TPS - -""" - setGTPSA!(a::AbstractString, val) - -Function to set global variables in GTPSA. Options for `a` are: - -- `desc_current::Descriptor` -- defines the `Descriptor` to use when that information is not explicitly (or implicitly in a TPS copy constructor) available, e.g. when calling `TPS(a)` where `a` is not a TPS. This is set each time a new `Descriptor` is defined -- `show_eps::Float64` -- defines the value below which the absolute value of a monomial coefficient is NOT printed -- `show_sparse::Bool` -- specifies whether the sparse monomial format is used for printing. This is useful for GTPSAs containing a large number of variables and parameters -- `show_header::Bool` -- specifies whether or not to print the GTPSA `Descriptor` information above each TPS output -""" -function setGTPSA!(a::AbstractString, val) - a == "desc_current" && (return (GTPSA.desc_current = val)) - a == "show_eps" && (return (GTPSA.show_eps = val)) - a == "show_sparse" && (return (GTPSA.show_sparse = val)) - a == "show_header" && (return (GTPSA.show_header = val)) - error("Global variable \"$(a)\" does not exist!") -end - -""" - getGTPSA(a::AbstractString) - -Function to get global variables in GTPSA. Options for `a` are: - -- `desc_current::Descriptor` -- defines the `Descriptor` to use when that information is not explicitly (or implicitly in a TPS copy constructor) available, e.g. when calling `TPS(a)` where `a` is not a TPS. This is set each time a new `Descriptor` is defined -- `show_eps::Float64` -- defines the value below which the absolute value of a monomial coefficient is NOT printed -- `show_sparse::Bool` -- specifies whether the sparse monomial format is used for printing. This is useful for GTPSAs containing a large number of variables and parameters -- `show_header::Bool` -- specifies whether or not to print the GTPSA `Descriptor` information above each TPS output -""" -function getGTPSA(a::AbstractString) - a == "desc_current" && (return GTPSA.desc_current) - a == "show_eps" && (return GTPSA.show_eps) - a == "show_sparse" && (return GTPSA.show_sparse) - a == "show_header" && (return GTPSA.show_header) - error("Global variable \"$(a)\" does not exist!") -end - -# Descriptor outer constructors -""" - Descriptor(nv::Integer, mo::Integer)::Descriptor - -Creates a TPSA `Descriptor` with `nv` variables, and a maximum truncation order `mo`. - -### Input -- `nv` -- Number of variables in the TPSA -- `mo` -- Maximum truncation order of the TPSA -""" -function Descriptor(nv::Integer, mo::Integer)::Descriptor - d = Descriptor(mad_desc_newv(convert(Cint, nv), convert(Cuchar, mo))) - GTPSA.desc_current = d - return d -end - -""" - Descriptor(vos::Vector{<:Integer}, mo::Integer)::Descriptor - -Creates a TPSA `Descriptor` with `length(vos)` variables with individual truncation -orders specified in the Vector `vos`, and a maximum truncation order `mo` for the TPSA. - -### Input -- `vos` -- `Vector` of the individual truncation orders of each variable -- `mo` -- Maximum truncation order of the TPSA, <= sum(vos) -""" -function Descriptor(vos::Vector{<:Integer}, mo::Integer)::Descriptor - all(vos .<= mo) == true || error("Atleast one variable truncation order is > the maximum truncation order!") - mo <= sum(vos) || (@info "Maximum order too high: setting maximum order = sum($vos) = $(sum(vos))"; mo = sum(vos)) - nv = length(vos) - np = 0 - po = 0 - no = vos - d = Descriptor(mad_desc_newvpo(convert(Cint, nv), convert(Cuchar, mo), convert(Cint, np), convert(Cuchar, po), convert(Vector{Cuchar}, no))) - GTPSA.desc_current = d - return d -end - -""" - Descriptor(nv::Integer, mo::Integer, np::Integer, po::Integer)::Descriptor - -Creates a TPSA `Descriptor` with `nv` variables and `np` parameters. The maximum -truncation order is `mo` (including the parameters), and the truncation order for -the parameters part of a monomial is `po`. - -### Input -- `nv` -- Number of variables in the TPSA -- `mo` -- Maximum truncation order of the TPSA including variables and parameters -- `np` -- Number of parameters in the TPSA -- `po` -- Truncation order of the parameters part of a monomial -""" -function Descriptor(nv::Integer, mo::Integer, np::Integer, po::Integer)::Descriptor - d = Descriptor(mad_desc_newvp(convert(Cint, nv), convert(Cuchar, mo), convert(Cint, np), convert(Cuchar, po))) - GTPSA.desc_current = d - return d -end - - -""" - Descriptor(vos::Vector{<:Integer}, mo::Integer, pos::Vector{<:Integer}, po::Integer)::Descriptor - -Creates a TPSA `Descriptor` with `length(vos)` variables with individual truncation -orders specified in `vos`, and `length(pos)` parameters with individual truncation -orders specified in `pos`. The maximum truncation order including both variables and -parameters is `mo`, and the truncation order for just the parameters part of the is `po`. - -### Input -- `vos` -- `Vector` of the individual truncation orders of each variable -- `mo` -- Maximum truncation order of the TPSA including variables and parameters -- `pos` -- `Vector` of the individual truncation orders of each parameter -- `po` -- Truncation order of the parameters part of a monomial -""" -function Descriptor(vos::Vector{<:Integer}, mo::Integer, pos::Vector{<:Integer}, po::Integer)::Descriptor - nv = length(vos) - np = length(pos) - no = vcat(vos,pos) - d = Descriptor(mad_desc_newvpo(convert(Cint, nv), convert(Cuchar, mo), convert(Cint, np), convert(Cuchar, po), convert(Vector{Cuchar}, no))) - GTPSA.desc_current = d - return d -end - -# Wrapper struct for Ptr{RTPSA} -mutable struct TPS <: Real - tpsa::Ptr{RTPSA} - function TPS(t1::Ptr{RTPSA})::TPS - t = new(t1) - f(x) = mad_tpsa_del!(x.tpsa) - finalizer(f,t) - return t - end -end - -# Wrapper struct for Ptr{CTPSA} -mutable struct ComplexTPS <: Number - tpsa::Ptr{CTPSA} - function ComplexTPS(ct1::Ptr{CTPSA})::ComplexTPS - ct = new(ct1) - f(x) = mad_ctpsa_del!(x.tpsa) - finalizer(f,ct) - return ct - end -end - -""" - TPS(ta::Union{Real,Nothing}=nothing; use::Union{Descriptor,TPS,ComplexTPS,Nothing}=nothing)::TPS - -Constructor to create a new `TPS` equal to the real value `ta`. If `ta` is a `TPS`, this -is equivalent to a copy constructor, with the result by default having the same `Descriptor` as `ta`. -If `ta` is not a `TPS`, then the `Descriptor` used will by default be `GTPSA.desc_current`. The `Descriptor` -for the constructed `TPS` can be set using `use`. If a `TPS` or `ComplexTPS` is passed to `use`, -the `Descriptor` for that TPS will be used. - -The constructor can also be used to create a copy of a `TPS` under one `Descriptor` to instead -have a different `Descriptor`. In this case, invalid monomials under the new `Descriptor` are removed. - -### Input -- `ta` -- Any `Real` -- `use` -- (Optional) specify which `Descriptor` to use, default is `nothing` which uses the `Descriptor` for `ta` if `ta isa TPS`, else uses `GTPSA.desc_current` - -### Output -- `ret` -- New `TPS` equal to `ta` with removal of invalid monomials if `ta` is a `TPS` and a new `Descriptor` is specified -""" -function TPS(ta::Union{Real,Nothing}=nothing; use::Union{Descriptor,TPS,ComplexTPS,Nothing}=nothing)::TPS - return low_TPS(ta, use) -end - -# --- Blank TPS --- -function low_TPS(ta::Nothing, use::Descriptor) - return TPS(mad_tpsa_newd(use.desc, MAD_TPSA_DEFAULT)) -end - -function low_TPS(ta::Nothing, use::Union{TPS,ComplexTPS}) - return TPS(mad_tpsa_new(Base.unsafe_convert(Ptr{RTPSA}, use.tpsa), MAD_TPSA_SAME)) -end - -function low_TPS(ta::Nothing, use::Nothing) - return TPS(mad_tpsa_newd(GTPSA.desc_current.desc, MAD_TPSA_DEFAULT)) -end - -# --- Copy ctor --- -function low_TPS(t1::TPS, use::Nothing) - t = TPS(mad_tpsa_new(t1.tpsa, MAD_TPSA_SAME)) - mad_tpsa_copy!(t1.tpsa, t.tpsa) - return t -end - -# --- Change descriptor --- -function low_TPS(t1::TPS, use::Descriptor) - return change(t1, use) -end - -function low_TPS(t1::TPS, use::Union{TPS,ComplexTPS}) - return change(t1, Descriptor(Base.unsafe_convert(Ptr{Desc}, unsafe_load(use.tpsa).d))) -end - -# --- promote real to TPS --- -function low_TPS(a::Real, use::Nothing) - t = TPS(mad_tpsa_newd(GTPSA.desc_current.desc, MAD_TPSA_DEFAULT)) - mad_tpsa_set0!(t.tpsa, convert(Float64, 0), convert(Float64,a)) - return t -end - -function low_TPS(a::Real, use::Union{TPS,ComplexTPS}) - t = TPS(mad_tpsa_new(Base.unsafe_convert(Ptr{RTPSA}, use.tpsa), MAD_TPSA_SAME)) - mad_tpsa_set0!(t.tpsa, 0.0, convert(Float64,a)) - return t -end - -function low_TPS(a::Real, use::Descriptor) - t = TPS(mad_tpsa_newd(use.desc, MAD_TPSA_DEFAULT)) - mad_tpsa_set0!(t.tpsa, 0.0, convert(Float64,a)) - return t -end - -# ----------------------- -""" - ComplexTPS(cta::Union{Number,Nothing}=nothing; use::Union{Descriptor,TPS,ComplexTPS,Nothing}=nothing)::ComplexTPS - -Constructor to create a new `ComplexTPS` equal to the number `cta`. If `cta` is a `ComplexTPS` (or `TPS`), this -is equivalent to a copy constructor, with the result by default having the same `Descriptor` as `cta`. If `cta` -is not a `TPS` or`ComplexTPS`, then the `Descriptor` used will by default be `GTPSA.desc_current`. The `Descriptor` -for the constructed `ComplexTPS` can be set using `use`. If a `TPS` or `ComplexTPS` is passed to `use`, -the `Descriptor` for that TPS will be used. - -The constructor can also be used to create a copy of a `ComplexTPS` under one `Descriptor` to instead -have a different `Descriptor`. In this case, invalid monomials under the new `Descriptor` are removed. - -### Input -- `cta` -- Any `Number` -- `use` -- (Optional) specify which `Descriptor` to use, default is `nothing` which uses the `Descriptor` for `cta` if `cta <: Union{TPS,ComplexTPS}`, else uses `GTPSA.desc_current` - -### Output -- `ret` -- New `ComplexTPS` equal to `cta` with removal of invalid monomials if `cta` is a `TPS`/`ComplexTPS` and a new `Descriptor` is specified -""" -function ComplexTPS(cta::Union{Number,Nothing}=nothing; use::Union{Descriptor,TPS,ComplexTPS,Nothing}=nothing)::ComplexTPS - return low_ComplexTPS(cta, use) -end - -# For some reason I need to explicitly define this: -ComplexTPS(t::ComplexTPS; use::Union{Descriptor,TPS,ComplexTPS,Nothing}=nothing) = low_ComplexTPS(t,use) - -# --- Blank ComplexTPS --- -function low_ComplexTPS(cta::Nothing, use::Descriptor) - return ComplexTPS(mad_ctpsa_newd(use.desc, MAD_TPSA_DEFAULT)) -end - -function low_ComplexTPS(cta::Nothing, use::Union{TPS,ComplexTPS}) - return ComplexTPS(mad_ctpsa_new(Base.unsafe_convert(Ptr{CTPSA}, use.tpsa), MAD_TPSA_SAME)) -end - -function low_ComplexTPS(cta::Nothing, use::Nothing) - return ComplexTPS(mad_ctpsa_newd(GTPSA.desc_current.desc, MAD_TPSA_DEFAULT)) -end - -# --- Copy ctor --- -function low_ComplexTPS(ct1::ComplexTPS, use::Nothing) - ct = ComplexTPS(mad_ctpsa_new(ct1.tpsa, MAD_TPSA_SAME)) - mad_ctpsa_copy!(ct1.tpsa, ct.tpsa) - return ct -end - -function low_ComplexTPS(t1::TPS, use::Nothing) - ct = ComplexTPS(mad_ctpsa_new(Base.unsafe_convert(Ptr{CTPSA}, t1.tpsa), MAD_TPSA_SAME)) - mad_ctpsa_cplx!(t1.tpsa, Base.unsafe_convert(Ptr{RTPSA}, C_NULL), ct.tpsa) - return ct -end - -# --- Change descriptor --- -function low_ComplexTPS(t1::Union{TPS,ComplexTPS}, use::Descriptor) - return change(t1, use) -end - -function low_ComplexTPS(t1::Union{TPS,ComplexTPS}, use::Union{TPS,ComplexTPS}) - return change(t1, Descriptor(Base.unsafe_convert(Ptr{Desc}, unsafe_load(use.tpsa).d))) -end - -# --- promote number to ComplexTPS --- -function low_ComplexTPS(a::Union{Real,Complex}, use::Nothing) - ct = ComplexTPS(mad_ctpsa_newd(GTPSA.desc_current.desc, MAD_TPSA_DEFAULT)) - mad_ctpsa_set0!(ct.tpsa, convert(ComplexF64, 0), convert(ComplexF64,a)) - return ct -end - -function low_ComplexTPS(a::Union{Real,Complex}, use::Union{TPS,ComplexTPS}) - ct = ComplexTPS(mad_ctpsa_new(Base.unsafe_convert(Ptr{CTPSA}, use.tpsa), MAD_TPSA_SAME)) - mad_ctpsa_set0!(ct.tpsa, convert(ComplexF64, 0), convert(ComplexF64,a)) - return ct -end - -function low_ComplexTPS(a::Union{Real,Complex}, use::Descriptor) - ct = ComplexTPS(mad_ctpsa_newd(use.desc, MAD_TPSA_DEFAULT)) - mad_ctpsa_set0!(ct.tpsa, convert(ComplexF64, 0), convert(ComplexF64,a)) - return ct -end - -# ----------------------- - -# Special real argument ctors -function ComplexTPS(ta::Real, tb::Real; use::Union{Descriptor,TPS,ComplexTPS,Nothing}=nothing)::ComplexTPS - low_ComplexTPS(ta, tb, use) -end - -function low_ComplexTPS(t1::TPS, t2::TPS, use::Nothing) - ct = ComplexTPS(mad_ctpsa_new(Base.unsafe_convert(Ptr{CTPSA}, t1.tpsa), MAD_TPSA_SAME)) - mad_ctpsa_cplx!(t1.tpsa, t2.tpsa, ct.tpsa) - return ct -end - -function low_ComplexTPS(t1::TPS, a::Real, use::Nothing) - ct = ComplexTPS(mad_ctpsa_new(Base.unsafe_convert(Ptr{CTPSA}, t1.tpsa), MAD_TPSA_SAME)) - mad_ctpsa_cplx!(t1.tpsa, Base.unsafe_convert(Ptr{RTPSA}, C_NULL), ct.tpsa) - mad_ctpsa_set0!(ct.tpsa, convert(ComplexF64, 1), convert(ComplexF64, complex(0,a))) - return ct -end - -function low_ComplexTPS(a::Real, t1::TPS, use::Nothing) - ct = ComplexTPS(mad_ctpsa_new(Base.unsafe_convert(Ptr{CTPSA}, t1.tpsa), MAD_TPSA_SAME)) - mad_ctpsa_cplx!(Base.unsafe_convert(Ptr{RTPSA}, C_NULL), t1.tpsa, ct.tpsa) - mad_ctpsa_set0!(ct.tpsa, convert(ComplexF64, 1), convert(ComplexF64, a)) - return ct -end - -function low_ComplexTPS(a::Real, b::Real, use::Nothing) - ct = ComplexTPS(mad_ctpsa_newd(GTPSA.desc_current.desc, MAD_TPSA_DEFAULT)) - mad_ctpsa_set0!(ct.tpsa, convert(ComplexF64, 0), convert(ComplexF64, complex(a,b))) - return ct -end - -function low_ComplexTPS(a::Real, b::Real, use::Descriptor) - ct = ComplexTPS(mad_ctpsa_newd(use.desc, MAD_TPSA_DEFAULT)) - mad_ctpsa_set0!(ct.tpsa, convert(ComplexF64, 0), convert(ComplexF64, complex(a,b))) - return ct -end - -function low_ComplexTPS(a::Real, b::Real, use::Union{TPS,ComplexTPS}) - ct = ComplexTPS(mad_ctpsa_new(Base.unsafe_convert(Ptr{CTPSA}, use.tpsa), MAD_TPSA_SAME)) - mad_ctpsa_set0!(ct.tpsa, convert(ComplexF64, 0), convert(ComplexF64, complex(a,b))) - return ct -end - -function low_ComplexTPS(ta::TPS, tb::TPS, use::Descriptor) - ct = change(ta, use, type=ComplexTPS) - change!(ct, tb, 1, im) - return ct -end - -function low_ComplexTPS(ta::TPS, b::Real, use::Descriptor) - ct = change(ta, use, type=ComplexTPS) - mad_ctpsa_set0!(ct.tpsa, convert(ComplexF64, 1), convert(ComplexF64, complex(0,b))) - return ct -end - -function low_ComplexTPS(a::Real, tb::TPS, use::Descriptor) - ct = change(tb, use, type=ComplexTPS, scl2=im) - mad_ctpsa_set0!(ct.tpsa, convert(ComplexF64, 1), convert(ComplexF64, a)) - return ct -end - -function low_ComplexTPS(ta::TPS, tb::TPS, use::Union{TPS,ComplexTPS}) - return low_ComplexTPS(ta, tb, Descriptor(Base.unsafe_convert(Ptr{Desc}, unsafe_load(use.tpsa)))) -end - -function low_ComplexTPS(ta::TPS, b::Real, use::Union{TPS,ComplexTPS}) - return low_ComplexTPS(ta, b, Descriptor(Base.unsafe_convert(Ptr{Desc}, unsafe_load(use.tpsa)))) -end - -function low_ComplexTPS(a::Real, tb::TPS, use::Union{TPS,ComplexTPS}) - return low_ComplexTPS(a, tb, Descriptor(Base.unsafe_convert(Ptr{Desc}, unsafe_load(use.tpsa)))) -end - -# Useful type-generic functions: -cycle!(t::Ptr{RTPSA}, i::Cint, n::Cint, m_::Vector{Cuchar}, v_::Ref{Cdouble}) = (@inline; mad_tpsa_cycle!(t, i, n, m_, v_)) -cycle!(t::Ptr{CTPSA}, i::Cint, n::Cint, m_::Vector{Cuchar}, v_::Ref{ComplexF64}) = (@inline; mad_ctpsa_cycle!(t, i, n, m_, v_)) -idxm(t::Ptr{RTPSA}, n::Cint, m::Vector{Cuchar}) = (@inline; mad_tpsa_idxm(t, n, m)) -idxm(t::Ptr{CTPSA}, n::Cint, m::Vector{Cuchar}) = (@inline; mad_ctpsa_idxm(t, n, m)) -getdesc(t::Union{TPS,ComplexTPS}) = Descriptor(Base.unsafe_convert(Ptr{Desc}, unsafe_load(t.tpsa).d)) -numvars(t::Union{TPS,ComplexTPS}) = unsafe_load(Base.unsafe_convert(Ptr{Desc}, unsafe_load(t.tpsa).d)).nv -numparams(t::Union{TPS,ComplexTPS}) = unsafe_load(Base.unsafe_convert(Ptr{Desc}, unsafe_load(t.tpsa).d)).np -numnn(t::Union{TPS,ComplexTPS}) = unsafe_load(Base.unsafe_convert(Ptr{Desc}, unsafe_load(t.tpsa).d)).nn - - -# --- Variable/parameter generators --- - -""" - vars(use::Union{Descriptor,TPS,ComplexTPS}=GTPSA.desc_current)::Vector{TPS} - -Returns `TPS`s corresponding to the variables for the `Descriptor` specified by `use`. -Default value is `GTPSA.desc_current`. - -### Input -- `use` -- (Optional) Specify which TPSA `Descriptor` to use, default is `GTPSA.desc_current` - -### Output -- `x` -- `Vector` containing unit `TPS`s corresponding to each variable -""" -function vars(use::Union{Descriptor,TPS,ComplexTPS}=GTPSA.desc_current)::Vector{TPS} - t1 = TPS(use=use) - desc = unsafe_load(mad_tpsa_desc(t1.tpsa)) - nv = desc.nv - if nv < 1 - return TPS[] - end - x = Vector{TPS}(undef, nv) - t1[1] = 1.0 - x[1] = t1 - for i=2:nv - t = TPS(use=use) - mad_tpsa_seti!(t.tpsa, Cint(i), 0.0, 1.0) - x[i] = t - end - return x -end - -""" - params(use::Union{Descriptor,TPS,ComplexTPS}=GTPSA.desc_current)::Vector{TPS} - -Returns `TPS`s corresponding to the parameters for the `Descriptor` specified by `use`. -Default value is `GTPSA.desc_current`. - -### Input -- `use` -- (Optional) Specify which TPSA `Descriptor` to use, default is `GTPSA.desc_current` - -### Output -- `k` -- `Vector` containing unit `TPS`s corresponding to each parameter -""" -function params(use::Union{Descriptor,TPS,ComplexTPS}=GTPSA.desc_current)::Vector{TPS} - t1 = TPS(use=use) - desc = unsafe_load(mad_tpsa_desc(t1.tpsa)) - nv = desc.nv - np = desc.np - if np < 1 - return TPS[] - end - k = Vector{TPS}(undef, np) - mad_tpsa_seti!(t1.tpsa, Cint(nv+1), 0.0, 1.0) - k[1] = t1 - for i=nv+2:nv+np - t = TPS(use=use) - mad_tpsa_seti!(t.tpsa, Cint(i), 0.0, 1.0) - k[i-nv] = t - end - return k -end - - -""" - complexvars(use::Union{Descriptor,TPS,ComplexTPS}=GTPSA.desc_current)::Vector{ComplexTPS} - -Returns `ComplexTPS`s corresponding to the variables for the `Descriptor` specified by `use`. -Default value is `GTPSA.desc_current`. - -### Input -- `use` -- (Optional) Specify which TPSA `Descriptor` to use, default is `GTPSA.desc_current` - -### Output -- `x` -- `Vector` containing unit `ComplexTPS`s corresponding to each variable -""" -function complexvars(use::Union{Descriptor,TPS,ComplexTPS}=GTPSA.desc_current)::Vector{ComplexTPS} - ct1 = ComplexTPS(use=use) - desc = unsafe_load(mad_ctpsa_desc(ct1.tpsa)) - nv = desc.nv - if nv < 1 - return ComplexTPS[] - end - x = Vector{ComplexTPS}(undef, nv) - ct1[1] = 1.0 - x[1] = ct1 - for i=2:nv - ct = ComplexTPS(use=use) - mad_ctpsa_seti!(ct.tpsa, Cint(i), ComplexF64(0.0), ComplexF64(1.0)) - x[i] = ct - end - return x -end - -""" - complexparams(d::Descriptor=GTPSA.desc_current)::Vector{ComplexTPS} - -Returns `ComplexTPS`s corresponding to the parameters for the `Descriptor` specified by `use`. -Default value is `GTPSA.desc_current`. - -### Input -- `use` -- (Optional) Specify which TPSA `Descriptor` to use, default is `GTPSA.desc_current` - -### Output -- `k` -- `Vector` containing unit `ComplexTPS`s corresponding to each parameter -""" -function complexparams(use::Union{Descriptor,TPS,ComplexTPS}=GTPSA.desc_current)::Vector{ComplexTPS} - ct1 = ComplexTPS(use=use) - desc = unsafe_load(mad_ctpsa_desc(ct1.tpsa)) - nv = desc.nv - np = desc.np - if np < 1 - return ComplexTPS[] - end - k = Vector{ComplexTPS}(undef, np) - mad_ctpsa_seti!(ct1.tpsa, Cint(nv+1), ComplexF64(0.0), ComplexF64(1.0)) - k[1] = ct1 - for i=nv+2:nv+np - ct = ComplexTPS(use=use) - mad_ctpsa_seti!(ct.tpsa, Cint(i), ComplexF64(0.0), ComplexF64(1.0)) - k[i-nv] = ct - end - return k -end - -""" - mono(v::Union{Integer, Vector{<:Union{<:Pair{<:Integer,<:Integer},<:Integer}}, Nothing}=nothing; param::Union{<:Integer,Nothing}=nothing, params::Union{Vector{<:Pair{<:Integer,<:Integer}}, Nothing}=nothing, use::Descriptor=GTPSA.desc_current)::TPS - -Returns a `TPS` corresponding to a specific monomial, specified using the variable/parameter index, or -monomial indexing-by-order OR monomial indexing-by-sparse monomial. - -### Input -- `v` -- An integer (for variable index), an array of orders for each variable (for indexing-by-order), or an array of pairs (sparse monomial) -- `param` -- (Keyword argument, optional) An integer for the parameter index -- `params` -- (Keyword argument, optional) An array of pairs for sparse-monomial indexing -- `use` -- (Keyword argument, optional) The descriptor to use to generate the monomial. Default is most recently-defined. - -# Examples: Variable/Parameter Index: -```julia-repl -julia> d = Descriptor(3,10,2,10); - -julia> mono(1) -TPS: - Coefficient Order Exponent - 1.0000000000000000e+00 1 1 0 0 0 0 - - -julia> mono(2, use=d) -TPS: - Coefficient Order Exponent - 1.0000000000000000e+00 1 0 1 0 0 0 - - -julia> mono(param=2) -TPS: - Coefficient Order Exponent - 1.0000000000000000e+00 1 0 0 0 0 1 -``` - -# Examples: Monomial Index-by-Order -```julia-repl -julia> mono([1]) -TPS: - Coefficient Order Exponent - 1.0000000000000000e+00 1 1 0 0 0 0 - - -julia> mono([0,1]) -TPS: - Coefficient Order Exponent - 1.0000000000000000e+00 1 0 1 0 0 0 - - -julia> mono([0,0,0,0,1], use=d) -TPS: - Coefficient Order Exponent - 1.0000000000000000e+00 1 0 0 0 0 1 - - -julia> mono([1,0,0,0,1]) -TPS: - Coefficient Order Exponent - 1.0000000000000000e+00 2 1 0 0 0 1 -``` - -# Examples: Monomial Index-by-Sparse Monomial -```julia-repl -julia> mono([1=>1]) -TPS: - Coefficient Order Exponent - 1.0000000000000000e+00 1 1 0 0 0 0 - - -julia> mono([2=>1]) -TPS: - Coefficient Order Exponent - 1.0000000000000000e+00 1 0 1 0 0 0 - - -julia> mono([1=>1], params=[2=>1], use=d) -TPS: - Coefficient Order Exponent - 1.0000000000000000e+00 2 1 0 0 0 1 -``` -""" -function mono(v::Union{Integer, Vector{<:Union{<:Pair{<:Integer,<:Integer},<:Integer}}, Nothing}=nothing; param::Union{<:Integer,Nothing}=nothing, params::Union{Vector{<:Pair{<:Integer,<:Integer}}, Nothing}=nothing, use::Union{Descriptor,TPS,ComplexTPS}=GTPSA.desc_current)::TPS - return low_mono(TPS, use, v, param, params) -end - -function complexmono(v::Union{Integer, Vector{<:Union{<:Pair{<:Integer,<:Integer},<:Integer}}, Nothing}=nothing; param::Union{<:Integer,Nothing}=nothing, params::Union{Vector{<:Pair{<:Integer,<:Integer}}, Nothing}=nothing, use::Union{Descriptor,TPS,ComplexTPS}=GTPSA.desc_current)::ComplexTPS - return low_mono(ComplexTPS, use, v, param, params) -end - -# Variable/parameter: -function low_mono(T::Type, d::Union{Descriptor,TPS,ComplexTPS}, v::Integer, param::Nothing, params::Nothing)::T - t = T(use=d) - seti!(t.tpsa, Cint(v), convert(numtype(T), 0.0), convert(numtype(T), 1.0)) - return t -end - -function low_mono(T::Type, d::Union{Descriptor,TPS,ComplexTPS}, v::Nothing, param::Integer, params::Nothing)::T - t = T(use=d) - desc = unsafe_load(mad_tpsa_desc(t.tpsa)) - nv = desc.nv # TOTAL NUMBER OF VARS!!!! - seti!(t.tpsa, Cint(param) + nv, convert(numtype(T), 0.0), convert(numtype(T), 1.0)) - return t -end - -# Default to scalar value if nothing passed -function low_mono(T::Type, d::Union{Descriptor,TPS,ComplexTPS}, v::Nothing, param::Nothing, params::Nothing)::T - t = T(use=d) - t[0] = 1.0 - return t -end - -# Monomial by order: -function low_mono(T::Type, d::Union{Descriptor,TPS,ComplexTPS}, v::Vector{<:Integer}, param::Nothing, params::Nothing)::T - t = T(use=d) - t[v...] = 1.0 - return t -end - -# Monomial by sparse monomial: -function low_mono(T::Type, d::Union{Descriptor,TPS,ComplexTPS}, v::Vector{<:Pair{<:Integer,<:Integer}}, param::Nothing, params::Vector{<:Pair{<:Integer,<:Integer}})::T - t = T(use=d) - t[v..., params=params] = 1.0 - return t -end - -function low_mono(T::Type, d::Union{Descriptor,TPS,ComplexTPS}, v::Vector{<:Pair{<:Integer,<:Integer}}, param::Nothing, params::Nothing)::T - t = T(use=d) - # Need to create array of orders with length nv + np - t[v...] = 1.0 - return t -end - -function low_mono(T::Type, d::Union{Descriptor,TPS,ComplexTPS}, v::Nothing, param::Nothing, params::Vector{<:Pair{<:Integer,<:Integer}})::T - t = T(use=d) - t[params=params] = 1.0 - return t -end - -# Throw error if no above use cases satisfied: -function low_mono(T::Type, d::Union{Descriptor,TPS,ComplexTPS}, v, param, params) - error("Invalid monomial specified. Please use ONE of variable/parameter index, index by order, or index by sparse monomial.") -end - -# Function to convert var=>ord, params=(param=>ord,) to low level sparse monomial format (varidx1, ord1, varidx2, ord2, paramidx, ordp1,...) -function pairs_to_sm(t::Union{TPS,ComplexTPS}, vars::Union{Vector{<:Pair{<:Integer, <:Integer}},Tuple{Vararg{Pair{<:Integer,<:Integer}}}}; params::Union{Vector{<:Pair{<:Integer,<:Integer}},Tuple{Vararg{<:Pair{<:Integer,<:Integer}}},Nothing}=nothing)::Tuple{Vector{Cint}, Cint} - # WE MUST Order THE VARIABLES !!! - nv = numvars(t) - numv = Cint(length(vars)) - if !isnothing(params) - nump = Cint(length(params)) - imin = min(minimum(x->x.first, vars,init=typemax(Int)), minimum(x->x.first+nv, params,init=typemax(Int))) - imax = max(maximum(x->x.first, vars,init=0), maximum(x->x.first+nv, params,init=0)) - else - nump = 0 - imin = minimum(x->x.first, vars,init=typemax(Int)) - imax = maximum(x->x.first, vars,init=0) - end - len = imax-imin+1 - sm = zeros(Cint, 2*len) - sm[1:2:end] = imin:imax - for i=1:numv - sm[2*(vars[i].first-imin+1)] = convert(Cint, vars[i].second) - end - for i=1:nump - sm[2*(params[i].first+nv-imin+1)] = convert(Cint, params[i].second) - end - - return sm, 2*len -end - -# Function to convert var=>ord, params=(param=>ord,) to monomial format (byte array of orders) -function pairs_to_m(t::Union{TPS,ComplexTPS}, vars::Union{Vector{<:Pair{<:Integer, <:Integer}},Tuple{Vararg{Pair{<:Integer,<:Integer}}}}; params::Union{Vector{<:Pair{<:Integer, <:Integer}},Tuple{Vararg{Pair{<:Integer,<:Integer}}}}=Pair{Int,Int}[],zero_mono=true)::Tuple{Vector{UInt8}, Cint} - nv = numvars(t) - n = Cint(0) - if isempty(params) - n = Cint(maximum(map(x->x.first, vars))) - else - n = Cint(maximum(map(x->x.first, params))) + nv - end - if zero_mono - ords = zeros(Cuchar, n) - else - ords = ones(Cuchar, n).*0xff - end - for var in vars - ords[var.first] = convert(Cuchar, var.second) - end - for param in params - ords[nv + param.first] = convert(Cuchar, param.second) - end - return ords, n -end - -# Generic function to make new copy of TPS with different descriptor -function change(t1::Union{TPS,ComplexTPS}, newd::Descriptor; type::Type=typeof(t1), scl2::Number=1) - # Quick check if actually changing - if Base.unsafe_convert(Ptr{Desc}, unsafe_load(t1.tpsa).d) == newd.desc - return type(t1) - end - - # THE NUMBER OF VARIABLES and PARAMETERS MUST AGREE!!! - unsafe_load(Base.unsafe_convert(Ptr{Desc}, unsafe_load(t1.tpsa).d)).nv == unsafe_load(newd.desc).nv || error("Number of variables in GTPSAs do not agree!") - unsafe_load(Base.unsafe_convert(Ptr{Desc}, unsafe_load(t1.tpsa).d)).np == unsafe_load(newd.desc).np || error("Number of parameters in GTPSAs do not agree!") - - t = type(use=newd) - change!(t, t1, 0, scl2) - return t -end - -function change!(t::Union{TPS,ComplexTPS},t1::Union{TPS,ComplexTPS}, scl1::Number=0, scl2::Number=1) - desc = unsafe_load(Base.unsafe_convert(Ptr{Desc}, unsafe_load(t1.tpsa).d)) - nv = desc.nv - np = desc.np - coef = Ref{numtype(t1)}() - mono = Vector{Cuchar}(undef, np+nv) - idx = cycle!(t1.tpsa, Cint(-1), np+nv, mono, coef) - while idx >= 0 - # if valid monomial in new descriptor: - if convert(Bool, mad_desc_isvalidm(Base.unsafe_convert(Ptr{Desc}, unsafe_load(t.tpsa).d), np+nv, mono)) - setm!(t.tpsa, np+nv, mono, convert(numtype(t), scl1), convert(numtype(t), scl2*coef[])) # set new tpsa - end - idx = cycle!(t1.tpsa, idx, np+nv, mono, coef) - end -end - -include("getset.jl") -include("show.jl") -include("operators.jl") -include("methods.jl") -include("fast_gtpsa.jl") - -# Prevent undefined behavior -# Until AbstractComplex is implemented, I make the ctor return error because this should never happen -# asumming I wrapped enough -#= -Complex(t1::TPS) = complex(t1) -Complex(t1::TPS, t2::TPS) = complex(t1, t2) -Complex(t1::TPS, a::Real) = complex(t1, a) -Complex(a::Real, t1::TPS) = complex(a, t1) -Complex{TPS}(t1::TPS) = complex(t1) -Complex{TPS}(t1::TPS, t2::TPS) = complex(t1, t2) -Complex{TPS}(t1::TPS, a::Real) = complex(t1, a) -Complex{TPS}(a::Real, t1::TPS) = complex(a, t1)=# -Complex(t1::TPS) = error("ComplexTPS can only be defined as an AbstractComplex type (to be implemented in Julia PR #35587). If this error was reached without explicitly attempting to create a Complex{TPS}, please submit an issue to GTPSA.jl with an example.") -Complex(t1::TPS, t2::TPS) = error("ComplexTPS can only be defined as an AbstractComplex type (to be implemented in Julia PR #35587). If this error was reached without explicitly attempting to create a Complex{TPS}, please submit an issue to GTPSA.jl with an example.") -Complex(t1::TPS, a::Real) = error("ComplexTPS can only be defined as an AbstractComplex type (to be implemented in Julia PR #35587). If this error was reached without explicitly attempting to create a Complex{TPS}, please submit an issue to GTPSA.jl with an example.") -Complex(a::Real, t1::TPS) = error("ComplexTPS can only be defined as an AbstractComplex type (to be implemented in Julia PR #35587). If this error was reached without explicitly attempting to create a Complex{TPS}, please submit an issue to GTPSA.jl with an example.") -Complex{TPS}(t1::TPS) = error("ComplexTPS can only be defined as an AbstractComplex type (to be implemented in Julia PR #35587). If this error was reached without explicitly attempting to create a Complex{TPS}, please submit an issue to GTPSA.jl with an example.") -Complex{TPS}(t1::TPS, t2::TPS) = error("ComplexTPS can only be defined as an AbstractComplex type (to be implemented in Julia PR #35587). If this error was reached without explicitly attempting to create a Complex{TPS}, please submit an issue to GTPSA.jl with an example.") -Complex{TPS}(t1::TPS, a::Real) = error("ComplexTPS can only be defined as an AbstractComplex type (to be implemented in Julia PR #35587). If this error was reached without explicitly attempting to create a Complex{TPS}, please submit an issue to GTPSA.jl with an example.") -Complex{TPS}(a::Real, t1::TPS) = error("ComplexTPS can only be defined as an AbstractComplex type (to be implemented in Julia PR #35587). If this error was reached without explicitly attempting to create a Complex{TPS}, please submit an issue to GTPSA.jl with an example.") - - -promote_rule(::Type{TPS}, ::Union{Type{<:AbstractFloat}, Type{<:Integer}, Type{<:Rational}, Type{<:AbstractIrrational}}) = TPS -promote_rule(::Type{ComplexTPS}, ::Union{Type{Complex{<:Real}},Type{<:AbstractFloat}, Type{<:Integer}, Type{<:Rational}, Type{<:AbstractIrrational}}) = ComplexTPS -promote_rule(::Type{TPS}, ::Union{Type{ComplexTPS}, Type{Complex{<:Real}}}) = ComplexTPS - -# Handle bool which is special for some reason -+(t::TPS, z::Complex{Bool}) = t + Complex{Int}(z) -+(z::Complex{Bool}, t::TPS) = Complex{Int}(z) + t --(t::TPS, z::Complex{Bool}) = t - Complex{Int}(z) --(z::Complex{Bool}, t::TPS) = Complex{Int}(z) - t -*(t::TPS, z::Complex{Bool}) = t * Complex{Int}(z) -*(z::Complex{Bool}, t::TPS) = Complex{Int}(z) * t -/(t::TPS, z::Complex{Bool}) = t / Complex{Int}(z) -/(z::Complex{Bool}, t::TPS) = Complex{Int}(z) / t -^(t::TPS, z::Complex{Bool}) = t ^ Complex{Int}(z) -^(z::Complex{Bool}, t::TPS) = Complex{Int}(z) ^ t end diff --git a/src/ctors.jl b/src/ctors.jl new file mode 100644 index 00000000..c067d1bc --- /dev/null +++ b/src/ctors.jl @@ -0,0 +1,241 @@ + + +# --- Variable/parameter generators --- + +""" + vars(use::Union{Descriptor,TPS,ComplexTPS}=GTPSA.desc_current)::Vector{TPS} + +Returns `TPS`s corresponding to the variables for the `Descriptor` specified by `use`. +Default value is `GTPSA.desc_current`. + +### Input +- `use` -- (Optional) Specify which TPSA `Descriptor` to use, default is `GTPSA.desc_current` + +### Output +- `x` -- `Vector` containing unit `TPS`s corresponding to each variable +""" +function vars(use::Union{Descriptor,TPS,ComplexTPS}=GTPSA.desc_current)::Vector{TPS} + nv = numvars(use) + x = Vector{TPS}(undef, nv) + for i=1:nv + t = TPS(use=use) + t[i] = 1.0 + x[i] = t + end + return x +end + +""" + params(use::Union{Descriptor,TPS,ComplexTPS}=GTPSA.desc_current)::Vector{TPS} + +Returns `TPS`s corresponding to the parameters for the `Descriptor` specified by `use`. +Default value is `GTPSA.desc_current`. + +### Input +- `use` -- (Optional) Specify which TPSA `Descriptor` to use, default is `GTPSA.desc_current` + +### Output +- `k` -- `Vector` containing unit `TPS`s corresponding to each parameter +""" +function params(use::Union{Descriptor,TPS,ComplexTPS}=GTPSA.desc_current)::Vector{TPS} + nv = numvars(use) + np = numparams(use) + k = Vector{TPS}(undef, np) + for i=nv+1:nv+np + t = TPS(use=use) + t[i] = 1.0 + k[i-nv] = t + end + return k +end + + +""" + complexvars(use::Union{Descriptor,TPS,ComplexTPS}=GTPSA.desc_current)::Vector{ComplexTPS} + +Returns `ComplexTPS`s corresponding to the variables for the `Descriptor` specified by `use`. +Default value is `GTPSA.desc_current`. + +### Input +- `use` -- (Optional) Specify which TPSA `Descriptor` to use, default is `GTPSA.desc_current` + +### Output +- `x` -- `Vector` containing unit `ComplexTPS`s corresponding to each variable +""" +function complexvars(use::Union{Descriptor,TPS,ComplexTPS}=GTPSA.desc_current)::Vector{ComplexTPS} + nv = numvars(use) + x = Vector{ComplexTPS}(undef, nv) + for i=1:nv + t = ComplexTPS(use=use) + t[i] = 1.0 + x[i] = t + end + return x +end + +""" + complexparams(d::Descriptor=GTPSA.desc_current)::Vector{ComplexTPS} + +Returns `ComplexTPS`s corresponding to the parameters for the `Descriptor` specified by `use`. +Default value is `GTPSA.desc_current`. + +### Input +- `use` -- (Optional) Specify which TPSA `Descriptor` to use, default is `GTPSA.desc_current` + +### Output +- `k` -- `Vector` containing unit `ComplexTPS`s corresponding to each parameter +""" +function complexparams(use::Union{Descriptor,TPS,ComplexTPS}=GTPSA.desc_current)::Vector{ComplexTPS} + nv = numvars(use) + np = numparams(use) + k = Vector{ComplexTPS}(undef, np) + for i=nv+1:nv+np + t = ComplexTPS(use=use) + t[i] = 1.0 + k[i-nv] = t + end + return k +end + +""" + mono(v::Union{Integer, Vector{<:Union{<:Pair{<:Integer,<:Integer},<:Integer}}, Nothing}=nothing; param::Union{Integer,Nothing}=nothing, params::Union{Vector{<:Pair{<:Integer,<:Integer}}, Nothing}=nothing, use::Descriptor=GTPSA.desc_current)::TPS + +Returns a `TPS` corresponding to a specific monomial, specified using the variable/parameter index, or +monomial indexing-by-order OR monomial indexing-by-sparse monomial. + +### Input +- `v` -- An integer (for variable index), an array of orders for each variable (for indexing-by-order), or an array of pairs (sparse monomial) +- `param` -- (Keyword argument, optional) An integer for the parameter index +- `params` -- (Keyword argument, optional) An array of pairs for sparse-monomial indexing +- `use` -- (Keyword argument, optional) The descriptor to use to generate the monomial. Default is most recently-defined. + +# Examples: Variable/Parameter Index: +```julia-repl +julia> d = Descriptor(3,10,2,10); + +julia> mono(1) +TPS: + Coefficient Order Exponent + 1.0000000000000000e+00 1 1 0 0 0 0 + + +julia> mono(2, use=d) +TPS: + Coefficient Order Exponent + 1.0000000000000000e+00 1 0 1 0 0 0 + + +julia> mono(param=2) +TPS: + Coefficient Order Exponent + 1.0000000000000000e+00 1 0 0 0 0 1 +``` + +# Examples: Monomial Index-by-Order +```julia-repl +julia> mono([1]) +TPS: + Coefficient Order Exponent + 1.0000000000000000e+00 1 1 0 0 0 0 + + +julia> mono([0,1]) +TPS: + Coefficient Order Exponent + 1.0000000000000000e+00 1 0 1 0 0 0 + + +julia> mono([0,0,0,0,1], use=d) +TPS: + Coefficient Order Exponent + 1.0000000000000000e+00 1 0 0 0 0 1 + + +julia> mono([1,0,0,0,1]) +TPS: + Coefficient Order Exponent + 1.0000000000000000e+00 2 1 0 0 0 1 +``` + +# Examples: Monomial Index-by-Sparse Monomial +```julia-repl +julia> mono([1=>1]) +TPS: + Coefficient Order Exponent + 1.0000000000000000e+00 1 1 0 0 0 0 + + +julia> mono([2=>1]) +TPS: + Coefficient Order Exponent + 1.0000000000000000e+00 1 0 1 0 0 0 + + +julia> mono([1=>1], params=[2=>1], use=d) +TPS: + Coefficient Order Exponent + 1.0000000000000000e+00 2 1 0 0 0 1 +``` +""" +function mono(v::Union{TPSIndexType,Nothing}=nothing; param::Union{Integer,Nothing}=nothing, params::Union{SMIndexType,Nothing}=nothing, use::Union{Descriptor,TPS,ComplexTPS}=GTPSA.desc_current) + return low_mono(TPS, use, v, param, params) +end + +function complexmono(v::Union{TPSIndexType,Nothing}=nothing; param::Union{Integer,Nothing}=nothing, params::Union{SMIndexType,Nothing}=nothing, use::Union{Descriptor,TPS,ComplexTPS}=GTPSA.desc_current) + return low_mono(ComplexTPS, use, v, param, params) +end + +# Variable/parameter: +function low_mono(T::Type, d::Union{Descriptor,TPS,ComplexTPS}, v::Integer, param::Nothing, params::Nothing) + t = T(use=d) + seti!(t.tpsa, Cint(v), convert(numtype(T), 0.0), convert(numtype(T), 1.0)) + return t +end + +function low_mono(T::Type, d::Union{Descriptor,TPS,ComplexTPS}, v::Nothing, param::Integer, params::Nothing) + t = T(use=d) + desc = unsafe_load(mad_tpsa_desc(t.tpsa)) + nv = desc.nv # TOTAL NUMBER OF VARS!!!! + seti!(t.tpsa, Cint(param) + nv, convert(numtype(T), 0.0), convert(numtype(T), 1.0)) + return t +end + +# Default to scalar value if nothing passed +function low_mono(T::Type, d::Union{Descriptor,TPS,ComplexTPS}, v::Nothing, param::Nothing, params::Nothing) + t = T(use=d) + t[0] = 1.0 + return t +end + +# Monomial by order: +function low_mono(T::Type, d::Union{Descriptor,TPS,ComplexTPS}, v::MIndexType, param::Nothing, params::Nothing) + t = T(use=d) + t[v] = 1.0 + return t +end + +# Monomial by sparse monomial: +function low_mono(T::Type, d::Union{Descriptor,TPS,ComplexTPS}, v::SMIndexType, param::Nothing, params::SMIndexType) + t = T(use=d) + t[v, params=params] = 1.0 + return t +end + +function low_mono(T::Type, d::Union{Descriptor,TPS,ComplexTPS}, v::SMIndexType, param::Nothing, params::Nothing) + t = T(use=d) + # Need to create array of orders with length nv + np + t[v] = 1.0 + return t +end + +function low_mono(T::Type, d::Union{Descriptor,TPS,ComplexTPS}, v::Nothing, param::Nothing, params::SMIndexType) + t = T(use=d) + t[params=params] = 1.0 + return t +end + +# Throw error if no above use cases satisfied: +function low_mono(T::Type, d::Union{Descriptor,TPS,ComplexTPS}, v, param, params) + error("Invalid monomial specified. Please use ONE of variable/parameter index, index by order, or index by sparse monomial.") +end + diff --git a/src/descriptor.jl b/src/descriptor.jl new file mode 100644 index 00000000..46dfb625 --- /dev/null +++ b/src/descriptor.jl @@ -0,0 +1,89 @@ +# Wrapper struct for Ptr{Desc} +struct Descriptor + desc::Ptr{Desc} + function Descriptor(desc::Ptr{Desc})::Descriptor + d = new(desc) + return d + end +end + +# Descriptor outer constructors +""" + Descriptor(nv::Integer, mo::Integer)::Descriptor + +Creates a TPSA `Descriptor` with `nv` variables, and a maximum truncation order `mo`. + +### Input +- `nv` -- Number of variables in the TPSA +- `mo` -- Maximum truncation order of the TPSA +""" +function Descriptor(nv::Integer, mo::Integer)::Descriptor + d = Descriptor(mad_desc_newv(convert(Cint, nv), convert(Cuchar, mo))) + GTPSA.desc_current = d + return d +end + +""" + Descriptor(vos::Vector{<:Integer}, mo::Integer)::Descriptor + +Creates a TPSA `Descriptor` with `length(vos)` variables with individual truncation +orders specified in the Vector `vos`, and a maximum truncation order `mo` for the TPSA. + +### Input +- `vos` -- `Vector` of the individual truncation orders of each variable +- `mo` -- Maximum truncation order of the TPSA, <= sum(vos) +""" +function Descriptor(vos::Vector{<:Integer}, mo::Integer)::Descriptor + all(vos .<= mo) == true || error("Atleast one variable truncation order is > the maximum truncation order!") + mo <= sum(vos) || (@info "Maximum order too high: setting maximum order = sum($vos) = $(sum(vos))"; mo = sum(vos)) + nv = length(vos) + np = 0 + po = 0 + no = vos + d = Descriptor(mad_desc_newvpo(convert(Cint, nv), convert(Cuchar, mo), convert(Cint, np), convert(Cuchar, po), convert(Vector{Cuchar}, no))) + GTPSA.desc_current = d + return d +end + +""" + Descriptor(nv::Integer, mo::Integer, np::Integer, po::Integer)::Descriptor + +Creates a TPSA `Descriptor` with `nv` variables and `np` parameters. The maximum +truncation order is `mo` (including the parameters), and the truncation order for +the parameters part of a monomial is `po`. + +### Input +- `nv` -- Number of variables in the TPSA +- `mo` -- Maximum truncation order of the TPSA including variables and parameters +- `np` -- Number of parameters in the TPSA +- `po` -- Truncation order of the parameters part of a monomial +""" +function Descriptor(nv::Integer, mo::Integer, np::Integer, po::Integer)::Descriptor + d = Descriptor(mad_desc_newvp(convert(Cint, nv), convert(Cuchar, mo), convert(Cint, np), convert(Cuchar, po))) + GTPSA.desc_current = d + return d +end + + +""" + Descriptor(vos::Vector{<:Integer}, mo::Integer, pos::Vector{<:Integer}, po::Integer)::Descriptor + +Creates a TPSA `Descriptor` with `length(vos)` variables with individual truncation +orders specified in `vos`, and `length(pos)` parameters with individual truncation +orders specified in `pos`. The maximum truncation order including both variables and +parameters is `mo`, and the truncation order for just the parameters part of the is `po`. + +### Input +- `vos` -- `Vector` of the individual truncation orders of each variable +- `mo` -- Maximum truncation order of the TPSA including variables and parameters +- `pos` -- `Vector` of the individual truncation orders of each parameter +- `po` -- Truncation order of the parameters part of a monomial +""" +function Descriptor(vos::Vector{<:Integer}, mo::Integer, pos::Vector{<:Integer}, po::Integer)::Descriptor + nv = length(vos) + np = length(pos) + no = vcat(vos,pos) + d = Descriptor(mad_desc_newvpo(convert(Cint, nv), convert(Cuchar, mo), convert(Cint, np), convert(Cuchar, po), convert(Vector{Cuchar}, no))) + GTPSA.desc_current = d + return d +end \ No newline at end of file diff --git a/src/getset.jl b/src/getset.jl index 16fca452..29aea9da 100644 --- a/src/getset.jl +++ b/src/getset.jl @@ -1,13 +1,3 @@ -numtype(t::TPS) = Float64 -numtype(ct::ComplexTPS) = ComplexF64 -numtype(::Type{TPS}) = Float64 -numtype(::Type{ComplexTPS}) = ComplexF64 - -lowtype(t::TPS) = Ptr{RTPSA} -lowtype(ct::ComplexTPS) = Ptr{CTPSA} -lowtype(::Type{TPS}) = Ptr{RTPSA} -lowtype(::Type{ComplexTPS}) = Ptr{CTPSA} - # --- Setters --- seti!(t::Ptr{RTPSA}, i::Cint, a::Cdouble, b::Cdouble) = mad_tpsa_seti!(t, i, a, b) seti!(t::Ptr{CTPSA}, i::Cint, a::ComplexF64, b::ComplexF64) = mad_ctpsa_seti!(t, i, a, b) @@ -16,17 +6,8 @@ setm!(t::Ptr{CTPSA}, n::Cint, m::Vector{Cuchar}, a::ComplexF64, b::ComplexF64) = setsm!(t::Ptr{RTPSA}, n::Cint, m::Vector{Cint}, a::Float64, b::Float64)= mad_tpsa_setsm!(t, n, m, a, b) setsm!(t::Ptr{CTPSA}, n::Cint, m::Vector{Cint}, a::ComplexF64, b::ComplexF64)= mad_ctpsa_setsm!(t, n, m, a, b) -# Flat index: Integer... -# Monomial: Vector{<:Integer}, Tuple{Vararg{<:Integer}} -# Sparse Monomial: Pair{<:Integer,<:Integer}... , Vector{<:Pair{<:Integer,<:Integer}}, Tuple{Vararg{<:Pair{<:Integer,<:Integer}}} -const SMIndexType = Union{Vector{<:Pair{<:Integer,<:Integer}}, Tuple{Vararg{<:Pair{<:Integer,<:Integer}}}} -const MIndexType = Union{Vector{<:Integer}, Tuple{Vararg{<:Integer}}} -const TPSIndexType = Union{Integer, - MIndexType, - SMIndexType} - # All -function setindex!(t::Union{TPS,ComplexTPS}, v::Number, idx::Union{TPSIndexType,Nothing}=nothing; param::Union{<:Integer,Nothing}=nothing, params::Union{SMIndexType,Nothing}=nothing) +function setindex!(t::Union{TPS,ComplexTPS}, v::Number, idx::Union{TPSIndexType,Nothing}=nothing; param::Union{Integer,Nothing}=nothing, params::Union{SMIndexType,Nothing}=nothing) lowset!(t, v, idx, param, params) end @@ -34,8 +15,8 @@ end #setindex!(t::Union{ComplexTPS, TPS}, v::Number, idx::Integer) = lowset!(t, v, tuple(idx), nothing, nothing) # Flat index -function lowset!(t::Union{TPS,ComplexTPS}, v::Number, i::Union{Nothing,<:Integer}, param::Union{Nothing,<:Integer}, params::Nothing) - if !xor(isempty(i), isnothing(param)) +function lowset!(t::Union{TPS,ComplexTPS}, v::Number, i::Union{Nothing,Integer}, param::Union{Nothing,Integer}, params::Nothing) + if !xor(isnothing(i), isnothing(param)) error("Invalid monomial index specified. Please use ONE of variable/parameter index, index by order, or index by sparse monomial.") end @@ -77,16 +58,20 @@ getsm(t::Ptr{RTPSA}, n::Cint, m::Vector{Cint})= mad_tpsa_getsm(t, n, m) getsm(t::Ptr{CTPSA}, n::Cint, m::Vector{Cint})= mad_ctpsa_getsm(t, n, m) # All -function getindex(t::Union{TPS,ComplexTPS}, idx::Union{TPSIndexType,Nothing}=nothing; param::Union{<:Integer,Nothing}=nothing, params::Union{SMIndexType,Nothing}=nothing) - lowget(t, idx, param, params) +function getindex(t::Union{TPS,ComplexTPS}, idx::Union{TPSIndexType,Nothing}=nothing; param::Union{Integer,Nothing}=nothing, params::Union{SMIndexType,Nothing}=nothing) + #println(typeof(t)) + #println(typeof(idx)) + #println(typeof(param)) + #println(typeof(params)) + return lowget(t, idx, param, params) end # To override Base number.jl getindex(t::Union{ComplexTPS, TPS}, idx::Integer) = lowget(t, idx, nothing, nothing) # Flat index -function lowget(t::Union{TPS,ComplexTPS}, i::Union{Nothing,<:Integer}, param::Union{Nothing,<:Integer}, params::Nothing) - if !xor(isempty(i), isnothing(param)) +function lowget(t::Union{TPS,ComplexTPS}, i::Union{Nothing,Integer}, param::Union{Nothing,Integer}, params::Nothing) + if !xor(isnothing(i), isnothing(param)) error("Invalid monomial index specified. Please use ONE of variable/parameter index, index by order, or index by sparse monomial.") end @@ -118,18 +103,16 @@ end lowget(t, idx, param, params) = error("Invalid monomial index specified. Please use ONE of variable/parameter index, index by order, or index by sparse monomial.") - # --- Slicing (getter) --- # Vectors (which will be Vector{Any}) must be converted to tuples so SM or M indexing can be resolved: -const SMColonIndexType = Tuple{Vararg{<:Union{Pair{<:Integer,<:Integer},<:Colon}}} -const MColonIndexType =Tuple{Vararg{<:Union{<:Integer,<:Colon}}} -const TPSColonIndexType = Union{Integer, Colon, - MColonIndexType, +const SMColonIndexType = Tuple{Vararg{Union{Pair{<:Integer,<:Integer},Colon}}} +const MColonIndexType =Tuple{Vararg{Union{Integer,Colon}}} +const TPSColonIndexType = Union{MColonIndexType, SMColonIndexType, Vector{<:Any}} -function getindex(t::Union{TPS,ComplexTPS}, v::TPSColonIndexType; param::Union{<:Integer,Nothing}=nothing, params::Union{SMIndexType, Nothing}=nothing) +function getindex(t::Union{TPS,ComplexTPS}, v::TPSColonIndexType; param::Union{Integer,Nothing}=nothing, params::Union{SMIndexType, Nothing}=nothing) if (v isa Vector) par_mono = setup_mono(t, tuple(v...), param, params) else @@ -138,15 +121,30 @@ function getindex(t::Union{TPS,ComplexTPS}, v::TPSColonIndexType; param::Union{< return slice(t, par_mono, false) end +# For flat indexing: +function getindex(t::Union{TPS,ComplexTPS}, v::Integer, c::Colon) + par_mono = setup_mono(t, v, nothing, nothing) + return slice(t, par_mono,false) +end + +function getindex(t::Union{TPS,ComplexTPS}, c::Colon; param::Union{Integer,Nothing}=nothing) + if isnothing(param) + return t + else + par_mono = setup_mono(t, nothing, param, nothing) + return slice(t, par_mono,false) + end +end + # --- par --- """ - par(t::Union{TPS,ComplexTPS}, v::Union{Integer, Vector{<:Union{<:Pair{<:Integer,<:Integer},<:Integer, <:Any}}, Tuple{Vararg{Union{<:Integer,Pair{<:Integer,<:Integer},<:Colon}}}, Nothing}=nothing; param::Union{<:Integer,Nothing}=nothing, params::Union{Vector{<:Pair{<:Integer,<:Integer}}, Nothing}=nothing) + par(t::Union{TPS,ComplexTPS}, v::Union{TPSColonIndexType, Vector{Pair{<:Integer,<:Integer}}, Vector{<:Integer}, Integer, Colon, Nothing}=nothing; param::Union{Integer,Nothing}=nothing, params::Union{SMIndexType, Nothing}=nothing) Extracts a polynomial from the TPS containing the specified monomial, and removes the monomial. ### Input -- `v` -- An integer (for variable index), an array of orders for each variable (for indexing-by-order), or an array of pairs (sparse monomial) +- `v` -- An integer (for variable index), an array/tuple of orders for each variable (for indexing-by-order), or an array/tuple of pairs (sparse monomial) - `param` -- (Keyword argument, optional) An integer for the parameter index - `params` -- (Keyword argument, optional) An array of pairs for sparse-monomial indexing @@ -207,7 +205,7 @@ TPS: 3.0000000000000000e+00 7 2 1 1 2 1 | 0 0 ``` """ -function par(t::Union{TPS,ComplexTPS}, v::Union{TPSColonIndexType, Vector{Pair{<:Integer,<:Integer}}, Vector{<:Integer}, Nothing}=nothing; param::Union{<:Integer,Nothing}=nothing, params::Union{SMIndexType, Nothing}=nothing) +function par(t::Union{TPS,ComplexTPS}, v::Union{TPSColonIndexType, Vector{Pair{<:Integer,<:Integer}}, Vector{<:Integer}, Integer, Colon, Nothing}=nothing; param::Union{Integer,Nothing}=nothing, params::Union{SMIndexType, Nothing}=nothing) if (v isa Vector) tmpv = tuple(v...) if tmpv isa MColonIndexType # because par-ing, must add colon @@ -228,7 +226,7 @@ function setup_mono(t1::Union{TPS,ComplexTPS}, v::Integer, param::Nothing, param return par_mono end -function setup_mono(t1::Union{TPS,ComplexTPS}, v::Nothing, param::Integer, params::Nothing)::Vector{Cuchar} +function setup_mono(t1::Union{TPS,ComplexTPS}, v::Union{Nothing,Colon}, param::Integer, params::Nothing)::Vector{Cuchar} nv = numvars(t1) # TOTAL NUMBER OF VARS!!!! par_mono = ones(Cuchar, param+nv+1).*0xff par_mono[nv+param] = 0x1 @@ -268,6 +266,9 @@ function setup_mono(t1::Union{TPS,ComplexTPS}, v, param, params) error("Invalid monomial specified. Please use ONE of variable/parameter index, index by order, or index by sparse monomial.") end +idxm(t::Ptr{RTPSA}, n::Cint, m::Vector{Cuchar}) = (@inline; mad_tpsa_idxm(t, n, m)) +idxm(t::Ptr{CTPSA}, n::Cint, m::Vector{Cuchar}) = (@inline; mad_ctpsa_idxm(t, n, m)) + function slice(t1::Union{TPS,ComplexTPS}, par_mono::Vector{Cuchar}, par_it=true) nv = numvars(t1) np = numparams(t1) @@ -289,7 +290,7 @@ function slice(t1::Union{TPS,ComplexTPS}, par_mono::Vector{Cuchar}, par_it=true) tmp[v+1:end] .= mono[v+1:end] t[tmp] = coef[] else - t[mono] = coef[] + t[idx] = coef[] end end end diff --git a/src/global.jl b/src/global.jl new file mode 100644 index 00000000..deae699f --- /dev/null +++ b/src/global.jl @@ -0,0 +1,47 @@ +const MAD_TPSA::String = :("libgtpsa") +const MAD_TPSA_DEFAULT::Cuchar = 255 +const MAD_TPSA_SAME::Cuchar = 254 +const MAD_DESC_CURR::Ptr{Desc} = C_NULL +const DESC_MAX_TMP::Int = 8 + +# Global non-constants (types MUST be specified) +desc_current::Descriptor = Descriptor(MAD_DESC_CURR) # Current Descriptor +show_eps::Float64 = 0.0 # Print epsilon +show_sparse::Bool = false # Use sparse monomial print +show_header::Bool = false # Print a header above each TPS + +""" + setGTPSA!(a::AbstractString, val) + +Function to set global variables in GTPSA. Options for `a` are: + +- `desc_current::Descriptor` -- defines the `Descriptor` to use when that information is not explicitly (or implicitly in a TPS copy constructor) available, e.g. when calling `TPS(a)` where `a` is not a TPS. This is set each time a new `Descriptor` is defined +- `show_eps::Float64` -- defines the value below which the absolute value of a monomial coefficient is NOT printed +- `show_sparse::Bool` -- specifies whether the sparse monomial format is used for printing. This is useful for GTPSAs containing a large number of variables and parameters +- `show_header::Bool` -- specifies whether or not to print the GTPSA `Descriptor` information above each TPS output +""" +function setGTPSA!(a::AbstractString, val) + a == "desc_current" && (return (GTPSA.desc_current = val)) + a == "show_eps" && (return (GTPSA.show_eps = val)) + a == "show_sparse" && (return (GTPSA.show_sparse = val)) + a == "show_header" && (return (GTPSA.show_header = val)) + error("Global variable \"$(a)\" does not exist!") +end + +""" + getGTPSA(a::AbstractString) + +Function to get global variables in GTPSA. Options for `a` are: + +- `desc_current::Descriptor` -- defines the `Descriptor` to use when that information is not explicitly (or implicitly in a TPS copy constructor) available, e.g. when calling `TPS(a)` where `a` is not a TPS. This is set each time a new `Descriptor` is defined +- `show_eps::Float64` -- defines the value below which the absolute value of a monomial coefficient is NOT printed +- `show_sparse::Bool` -- specifies whether the sparse monomial format is used for printing. This is useful for GTPSAs containing a large number of variables and parameters +- `show_header::Bool` -- specifies whether or not to print the GTPSA `Descriptor` information above each TPS output +""" +function getGTPSA(a::AbstractString) + a == "desc_current" && (return GTPSA.desc_current) + a == "show_eps" && (return GTPSA.show_eps) + a == "show_sparse" && (return GTPSA.show_sparse) + a == "show_header" && (return GTPSA.show_header) + error("Global variable \"$(a)\" does not exist!") +end \ No newline at end of file diff --git a/src/low.jl b/src/low.jl new file mode 100644 index 00000000..b9385f06 --- /dev/null +++ b/src/low.jl @@ -0,0 +1,6 @@ +# Low-level functions/structs and constants +const NAMSZ::Int = 16 +include("low_level/mono.jl") +include("low_level/desc.jl") +include("low_level/rtpsa.jl") +include("low_level/ctpsa.jl") \ No newline at end of file diff --git a/src/methods.jl b/src/methods.jl index 74a0642e..9e6c2242 100644 --- a/src/methods.jl +++ b/src/methods.jl @@ -1,11 +1,23 @@ # --- Evaluate --- +eval!(na::Cint, ma::Vector{Ptr{RTPSA}}, nb::Cint, tb::Vector{Float64}, tc::Vector{Float64}) = mad_tpsa_eval!(na, ma, nb, tb, tc) +eval!(na::Cint, ma::Vector{Ptr{CTPSA}}, nb::Cint, tb::Vector{ComplexF64}, tc::Vector{ComplexF64}) = mad_ctpsa_eval!(na, ma, nb, tb, tc) + +function evaluate!(tc::Vector{<:Number}, m::Vector{<:Union{TPS,ComplexTPS}}, tb::Vector{<:Number}; work_low::Vector{lowtype(eltype(m))}=Vector{lowtype(eltype(m))}(undef, length(m))) + na = Cint(length(m)) + nb = Cint(length(tb)) + @assert na == nb "Vector lengths for TPSs and evaluation point disagree" + @assert length(tc) == nb "Output vector length disagrees with input vector length" + + +end + # TPS: """ evaluate(m::Vector{TPS}, x::Vector{<:Real})::Vector{Float64} Evaluates `m` at the point `x`. """ -function evaluate(m::Vector{TPS}, x::Vector{<:Real})::Vector{Float64} +function evaluate(m::Vector{<:Union{TPS,ComplexTPS}, x::Vector{<:Number}) na = Cint(length(m)) ma = map(t->t.tpsa, m) nb = Cint(length(x)) @@ -79,8 +91,8 @@ derivm!(tpsa1::Ptr{RTPSA}, tpsa::Ptr{RTPSA}, n::Cint, ords::Vector{Cuchar}) = (@ derivm!(ctpsa1::Ptr{CTPSA}, ctpsa::Ptr{CTPSA}, n::Cint, ords::Vector{Cuchar}) = (@inline; mad_ctpsa_derivm!(ctpsa1, ctpsa, n, ords)) """ - deriv(t1::Union{TPS,ComplexTPS}, v::Union{Integer, Vector{<:Union{<:Pair{<:Integer,<:Integer},<:Integer}}, Nothing}=nothing; param::Union{<:Integer,Nothing}=nothing, params::Union{Vector{<:Pair{<:Integer,<:Integer}}, Nothing}=nothing) - ∂(t1::Union{TPS,ComplexTPS}, v::Union{Integer, Vector{<:Union{<:Pair{<:Integer,<:Integer},<:Integer}}, Nothing}=nothing; param::Union{<:Integer,Nothing}=nothing, params::Union{Vector{<:Pair{<:Integer,<:Integer}}, Nothing}=nothing) + deriv(t1::Union{TPS,ComplexTPS}, v::Union{Integer, Vector{<:Union{<:Pair{<:Integer,<:Integer},<:Integer}}, Nothing}=nothing; param::Union{Integer,Nothing}=nothing, params::Union{Vector{<:Pair{<:Integer,<:Integer}}, Nothing}=nothing) + ∂(t1::Union{TPS,ComplexTPS}, v::Union{Integer, Vector{<:Union{<:Pair{<:Integer,<:Integer},<:Integer}}, Nothing}=nothing; param::Union{Integer,Nothing}=nothing, params::Union{Vector{<:Pair{<:Integer,<:Integer}}, Nothing}=nothing) Differentiates `t1` wrt the variable/parameter specified by the variable/parameter index, or alternatively any monomial specified by indexing-by-order OR indexing-by-sparse monomial. @@ -148,7 +160,7 @@ TPS: 1.0000000000000000e+00 0 0 0 ``` """ -function deriv(t1::Union{TPS,ComplexTPS}, v::Union{Integer, Vector{<:Union{<:Pair{<:Integer,<:Integer},<:Integer}}, Nothing}=nothing; param::Union{<:Integer,Nothing}=nothing, params::Union{Vector{<:Pair{<:Integer,<:Integer}}, Nothing}=nothing) +function deriv(t1::Union{TPS,ComplexTPS}, v::Union{Integer, Vector{<:Union{<:Pair{<:Integer,<:Integer},<:Integer}}, Nothing}=nothing; param::Union{Integer,Nothing}=nothing, params::Union{Vector{<:Pair{<:Integer,<:Integer}}, Nothing}=nothing) return low_deriv(t1, v, param, params) end diff --git a/src/tps.jl b/src/tps.jl new file mode 100644 index 00000000..b004043d --- /dev/null +++ b/src/tps.jl @@ -0,0 +1,248 @@ +# Wrapper struct for Ptr{RTPSA} +mutable struct TPS <: Real + tpsa::Ptr{RTPSA} + function TPS(t1::Ptr{RTPSA})::TPS + t = new(t1) + f(x) = mad_tpsa_del!(x.tpsa) + finalizer(f,t) + return t + end +end + +# Wrapper struct for Ptr{CTPSA} +mutable struct ComplexTPS <: Number + tpsa::Ptr{CTPSA} + function ComplexTPS(ct1::Ptr{CTPSA})::ComplexTPS + ct = new(ct1) + f(x) = mad_ctpsa_del!(x.tpsa) + finalizer(f,ct) + return ct + end +end + +""" + TPS(ta::Union{Real,Nothing}=nothing; use::Union{Descriptor,TPS,ComplexTPS,Nothing}=nothing)::TPS + +Constructor to create a new `TPS` equal to the real value `ta`. If `ta` is a `TPS`, this +is equivalent to a copy constructor, with the result by default having the same `Descriptor` as `ta`. +If `ta` is not a `TPS`, then the `Descriptor` used will by default be `GTPSA.desc_current`. The `Descriptor` +for the constructed `TPS` can be set using `use`. If a `TPS` or `ComplexTPS` is passed to `use`, +the `Descriptor` for that TPS will be used. + +The constructor can also be used to create a copy of a `TPS` under one `Descriptor` to instead +have a different `Descriptor`. In this case, invalid monomials under the new `Descriptor` are removed. + +### Input +- `ta` -- Any `Real` +- `use` -- (Optional) specify which `Descriptor` to use, default is `nothing` which uses the `Descriptor` for `ta` if `ta isa TPS`, else uses `GTPSA.desc_current` + +### Output +- `ret` -- New `TPS` equal to `ta` with removal of invalid monomials if `ta` is a `TPS` and a new `Descriptor` is specified +""" +function TPS(ta::Union{Real,Nothing}=nothing; use::Union{Descriptor,TPS,ComplexTPS,Nothing}=nothing)::TPS + return low_TPS(ta, use) +end + +# --- Blank TPS --- +function low_TPS(ta::Nothing, use::Descriptor) + return TPS(mad_tpsa_newd(use.desc, MAD_TPSA_DEFAULT)) +end + +function low_TPS(ta::Nothing, use::Union{TPS,ComplexTPS}) + return TPS(mad_tpsa_new(Base.unsafe_convert(Ptr{RTPSA}, use.tpsa), MAD_TPSA_SAME)) +end + +function low_TPS(ta::Nothing, use::Nothing) + return TPS(mad_tpsa_newd(GTPSA.desc_current.desc, MAD_TPSA_DEFAULT)) +end + +# --- Copy ctor --- +function low_TPS(t1::TPS, use::Nothing) + t = TPS(mad_tpsa_new(t1.tpsa, MAD_TPSA_SAME)) + mad_tpsa_copy!(t1.tpsa, t.tpsa) + return t +end + +# --- Change descriptor --- +function low_TPS(t1::TPS, use::Descriptor) + return change(t1, use) +end + +function low_TPS(t1::TPS, use::Union{TPS,ComplexTPS}) + return change(t1, Descriptor(Base.unsafe_convert(Ptr{Desc}, unsafe_load(use.tpsa).d))) +end + +# --- promote real to TPS --- +function low_TPS(a::Real, use::Nothing) + t = TPS(mad_tpsa_newd(GTPSA.desc_current.desc, MAD_TPSA_DEFAULT)) + mad_tpsa_set0!(t.tpsa, convert(Float64, 0), convert(Float64,a)) + return t +end + +function low_TPS(a::Real, use::Union{TPS,ComplexTPS}) + t = TPS(mad_tpsa_new(Base.unsafe_convert(Ptr{RTPSA}, use.tpsa), MAD_TPSA_SAME)) + mad_tpsa_set0!(t.tpsa, 0.0, convert(Float64,a)) + return t +end + +function low_TPS(a::Real, use::Descriptor) + t = TPS(mad_tpsa_newd(use.desc, MAD_TPSA_DEFAULT)) + mad_tpsa_set0!(t.tpsa, 0.0, convert(Float64,a)) + return t +end + +# ----------------------- +""" + ComplexTPS(cta::Union{Number,Nothing}=nothing; use::Union{Descriptor,TPS,ComplexTPS,Nothing}=nothing)::ComplexTPS + +Constructor to create a new `ComplexTPS` equal to the number `cta`. If `cta` is a `ComplexTPS` (or `TPS`), this +is equivalent to a copy constructor, with the result by default having the same `Descriptor` as `cta`. If `cta` +is not a `TPS` or`ComplexTPS`, then the `Descriptor` used will by default be `GTPSA.desc_current`. The `Descriptor` +for the constructed `ComplexTPS` can be set using `use`. If a `TPS` or `ComplexTPS` is passed to `use`, +the `Descriptor` for that TPS will be used. + +The constructor can also be used to create a copy of a `ComplexTPS` under one `Descriptor` to instead +have a different `Descriptor`. In this case, invalid monomials under the new `Descriptor` are removed. + +### Input +- `cta` -- Any `Number` +- `use` -- (Optional) specify which `Descriptor` to use, default is `nothing` which uses the `Descriptor` for `cta` if `cta <: Union{TPS,ComplexTPS}`, else uses `GTPSA.desc_current` + +### Output +- `ret` -- New `ComplexTPS` equal to `cta` with removal of invalid monomials if `cta` is a `TPS`/`ComplexTPS` and a new `Descriptor` is specified +""" +function ComplexTPS(cta::Union{Number,Nothing}=nothing; use::Union{Descriptor,TPS,ComplexTPS,Nothing}=nothing)::ComplexTPS + return low_ComplexTPS(cta, use) +end + +# For some reason I need to explicitly define this: +ComplexTPS(t::ComplexTPS; use::Union{Descriptor,TPS,ComplexTPS,Nothing}=nothing) = low_ComplexTPS(t,use) + +# --- Blank ComplexTPS --- +function low_ComplexTPS(cta::Nothing, use::Descriptor) + return ComplexTPS(mad_ctpsa_newd(use.desc, MAD_TPSA_DEFAULT)) +end + +function low_ComplexTPS(cta::Nothing, use::Union{TPS,ComplexTPS}) + return ComplexTPS(mad_ctpsa_new(Base.unsafe_convert(Ptr{CTPSA}, use.tpsa), MAD_TPSA_SAME)) +end + +function low_ComplexTPS(cta::Nothing, use::Nothing) + return ComplexTPS(mad_ctpsa_newd(GTPSA.desc_current.desc, MAD_TPSA_DEFAULT)) +end + +# --- Copy ctor --- +function low_ComplexTPS(ct1::ComplexTPS, use::Nothing) + ct = ComplexTPS(mad_ctpsa_new(ct1.tpsa, MAD_TPSA_SAME)) + mad_ctpsa_copy!(ct1.tpsa, ct.tpsa) + return ct +end + +function low_ComplexTPS(t1::TPS, use::Nothing) + ct = ComplexTPS(mad_ctpsa_new(Base.unsafe_convert(Ptr{CTPSA}, t1.tpsa), MAD_TPSA_SAME)) + mad_ctpsa_cplx!(t1.tpsa, Base.unsafe_convert(Ptr{RTPSA}, C_NULL), ct.tpsa) + return ct +end + +# --- Change descriptor --- +function low_ComplexTPS(t1::Union{TPS,ComplexTPS}, use::Descriptor) + return change(t1, use) +end + +function low_ComplexTPS(t1::Union{TPS,ComplexTPS}, use::Union{TPS,ComplexTPS}) + return change(t1, Descriptor(Base.unsafe_convert(Ptr{Desc}, unsafe_load(use.tpsa).d))) +end + +# --- promote number to ComplexTPS --- +function low_ComplexTPS(a::Union{Real,Complex}, use::Nothing) + ct = ComplexTPS(mad_ctpsa_newd(GTPSA.desc_current.desc, MAD_TPSA_DEFAULT)) + mad_ctpsa_set0!(ct.tpsa, convert(ComplexF64, 0), convert(ComplexF64,a)) + return ct +end + +function low_ComplexTPS(a::Union{Real,Complex}, use::Union{TPS,ComplexTPS}) + ct = ComplexTPS(mad_ctpsa_new(Base.unsafe_convert(Ptr{CTPSA}, use.tpsa), MAD_TPSA_SAME)) + mad_ctpsa_set0!(ct.tpsa, convert(ComplexF64, 0), convert(ComplexF64,a)) + return ct +end + +function low_ComplexTPS(a::Union{Real,Complex}, use::Descriptor) + ct = ComplexTPS(mad_ctpsa_newd(use.desc, MAD_TPSA_DEFAULT)) + mad_ctpsa_set0!(ct.tpsa, convert(ComplexF64, 0), convert(ComplexF64,a)) + return ct +end + +# ----------------------- + +# Special real argument ctors +function ComplexTPS(ta::Real, tb::Real; use::Union{Descriptor,TPS,ComplexTPS,Nothing}=nothing)::ComplexTPS + low_ComplexTPS(ta, tb, use) +end + +function low_ComplexTPS(t1::TPS, t2::TPS, use::Nothing) + ct = ComplexTPS(mad_ctpsa_new(Base.unsafe_convert(Ptr{CTPSA}, t1.tpsa), MAD_TPSA_SAME)) + mad_ctpsa_cplx!(t1.tpsa, t2.tpsa, ct.tpsa) + return ct +end + +function low_ComplexTPS(t1::TPS, a::Real, use::Nothing) + ct = ComplexTPS(mad_ctpsa_new(Base.unsafe_convert(Ptr{CTPSA}, t1.tpsa), MAD_TPSA_SAME)) + mad_ctpsa_cplx!(t1.tpsa, Base.unsafe_convert(Ptr{RTPSA}, C_NULL), ct.tpsa) + mad_ctpsa_set0!(ct.tpsa, convert(ComplexF64, 1), convert(ComplexF64, complex(0,a))) + return ct +end + +function low_ComplexTPS(a::Real, t1::TPS, use::Nothing) + ct = ComplexTPS(mad_ctpsa_new(Base.unsafe_convert(Ptr{CTPSA}, t1.tpsa), MAD_TPSA_SAME)) + mad_ctpsa_cplx!(Base.unsafe_convert(Ptr{RTPSA}, C_NULL), t1.tpsa, ct.tpsa) + mad_ctpsa_set0!(ct.tpsa, convert(ComplexF64, 1), convert(ComplexF64, a)) + return ct +end + +function low_ComplexTPS(a::Real, b::Real, use::Nothing) + ct = ComplexTPS(mad_ctpsa_newd(GTPSA.desc_current.desc, MAD_TPSA_DEFAULT)) + mad_ctpsa_set0!(ct.tpsa, convert(ComplexF64, 0), convert(ComplexF64, complex(a,b))) + return ct +end + +function low_ComplexTPS(a::Real, b::Real, use::Descriptor) + ct = ComplexTPS(mad_ctpsa_newd(use.desc, MAD_TPSA_DEFAULT)) + mad_ctpsa_set0!(ct.tpsa, convert(ComplexF64, 0), convert(ComplexF64, complex(a,b))) + return ct +end + +function low_ComplexTPS(a::Real, b::Real, use::Union{TPS,ComplexTPS}) + ct = ComplexTPS(mad_ctpsa_new(Base.unsafe_convert(Ptr{CTPSA}, use.tpsa), MAD_TPSA_SAME)) + mad_ctpsa_set0!(ct.tpsa, convert(ComplexF64, 0), convert(ComplexF64, complex(a,b))) + return ct +end + +function low_ComplexTPS(ta::TPS, tb::TPS, use::Descriptor) + ct = change(ta, use, type=ComplexTPS) + change!(ct, tb, 1, im) + return ct +end + +function low_ComplexTPS(ta::TPS, b::Real, use::Descriptor) + ct = change(ta, use, type=ComplexTPS) + mad_ctpsa_set0!(ct.tpsa, convert(ComplexF64, 1), convert(ComplexF64, complex(0,b))) + return ct +end + +function low_ComplexTPS(a::Real, tb::TPS, use::Descriptor) + ct = change(tb, use, type=ComplexTPS, scl2=im) + mad_ctpsa_set0!(ct.tpsa, convert(ComplexF64, 1), convert(ComplexF64, a)) + return ct +end + +function low_ComplexTPS(ta::TPS, tb::TPS, use::Union{TPS,ComplexTPS}) + return low_ComplexTPS(ta, tb, Descriptor(Base.unsafe_convert(Ptr{Desc}, unsafe_load(use.tpsa)))) +end + +function low_ComplexTPS(ta::TPS, b::Real, use::Union{TPS,ComplexTPS}) + return low_ComplexTPS(ta, b, Descriptor(Base.unsafe_convert(Ptr{Desc}, unsafe_load(use.tpsa)))) +end + +function low_ComplexTPS(a::Real, tb::TPS, use::Union{TPS,ComplexTPS}) + return low_ComplexTPS(a, tb, Descriptor(Base.unsafe_convert(Ptr{Desc}, unsafe_load(use.tpsa)))) +end \ No newline at end of file diff --git a/src/utils.jl b/src/utils.jl new file mode 100644 index 00000000..9f8b76cc --- /dev/null +++ b/src/utils.jl @@ -0,0 +1,150 @@ +numtype(t::TPS) = Float64 +numtype(ct::ComplexTPS) = ComplexF64 +numtype(::Type{TPS}) = Float64 +numtype(::Type{ComplexTPS}) = ComplexF64 + +lowtype(t::TPS) = Ptr{RTPSA} +lowtype(ct::ComplexTPS) = Ptr{CTPSA} +lowtype(::Type{TPS}) = Ptr{RTPSA} +lowtype(::Type{ComplexTPS}) = Ptr{CTPSA} + +getdesc(t::Union{TPS,ComplexTPS}) = Descriptor(Base.unsafe_convert(Ptr{Desc}, unsafe_load(t.tpsa).d)) +numvars(t::Union{TPS,ComplexTPS}) = unsafe_load(Base.unsafe_convert(Ptr{Desc}, unsafe_load(t.tpsa).d)).nv +numparams(t::Union{TPS,ComplexTPS}) = unsafe_load(Base.unsafe_convert(Ptr{Desc}, unsafe_load(t.tpsa).d)).np +numnn(t::Union{TPS,ComplexTPS}) = unsafe_load(Base.unsafe_convert(Ptr{Desc}, unsafe_load(t.tpsa).d)).nn +getdesc(d::Descriptor) = d +numvars(d::Descriptor) = unsafe_load(d.desc).nv +numparams(d::Descriptor) = unsafe_load(d.desc).np +numnn(d::Descriptor) = unsafe_load(d.desc).nn +getdesc(d::Nothing) = nothing + + + +const SMIndexType = Union{Vector{<:Pair{<:Integer,<:Integer}}, Tuple{Vararg{Pair{<:Integer,<:Integer}}}} +const MIndexType = Union{Vector{<:Integer}, Tuple{Vararg{Integer}}} +const TPSIndexType = Union{Integer, + MIndexType, + SMIndexType} + + +cycle!(t::Ptr{RTPSA}, i::Cint, n::Cint, m_::Vector{Cuchar}, v_::Ref{Cdouble}) = (@inline; mad_tpsa_cycle!(t, i, n, m_, v_)) +cycle!(t::Ptr{CTPSA}, i::Cint, n::Cint, m_::Vector{Cuchar}, v_::Ref{ComplexF64}) = (@inline; mad_ctpsa_cycle!(t, i, n, m_, v_)) + +# Generic function to make new copy of TPS with different descriptor +function change(t1::Union{TPS,ComplexTPS}, newd::Descriptor; type::Type=typeof(t1), scl2::Number=1) + # Quick check if actually changing + if Base.unsafe_convert(Ptr{Desc}, unsafe_load(t1.tpsa).d) == newd.desc + return type(t1) + end + + # THE NUMBER OF VARIABLES and PARAMETERS MUST AGREE!!! + unsafe_load(Base.unsafe_convert(Ptr{Desc}, unsafe_load(t1.tpsa).d)).nv == unsafe_load(newd.desc).nv || error("Number of variables in GTPSAs do not agree!") + unsafe_load(Base.unsafe_convert(Ptr{Desc}, unsafe_load(t1.tpsa).d)).np == unsafe_load(newd.desc).np || error("Number of parameters in GTPSAs do not agree!") + + t = type(use=newd) + change!(t, t1, 0, scl2) + return t +end + +function change!(t::Union{TPS,ComplexTPS},t1::Union{TPS,ComplexTPS}, scl1::Number=0, scl2::Number=1) + desc = unsafe_load(Base.unsafe_convert(Ptr{Desc}, unsafe_load(t1.tpsa).d)) + nv = desc.nv + np = desc.np + coef = Ref{numtype(t1)}() + mono = Vector{Cuchar}(undef, np+nv) + idx = cycle!(t1.tpsa, Cint(-1), np+nv, mono, coef) + while idx >= 0 + # if valid monomial in new descriptor: + if convert(Bool, mad_desc_isvalidm(Base.unsafe_convert(Ptr{Desc}, unsafe_load(t.tpsa).d), np+nv, mono)) + setm!(t.tpsa, np+nv, mono, convert(numtype(t), scl1), convert(numtype(t), scl2*coef[])) # set new tpsa + end + idx = cycle!(t1.tpsa, idx, np+nv, mono, coef) + end +end + +# Function to convert var=>ord, params=(param=>ord,) to low level sparse monomial format (varidx1, ord1, varidx2, ord2, paramidx, ordp1,...) +function pairs_to_sm(t::Union{TPS,ComplexTPS}, vars::Union{Vector{<:Pair{<:Integer, <:Integer}},Tuple{Vararg{Pair{<:Integer,<:Integer}}}}; params::Union{Vector{<:Pair{<:Integer,<:Integer}},Tuple{Vararg{<:Pair{<:Integer,<:Integer}}},Nothing}=nothing)::Tuple{Vector{Cint}, Cint} + # WE MUST Order THE VARIABLES !!! + nv = numvars(t) + numv = Cint(length(vars)) + if !isnothing(params) + nump = Cint(length(params)) + imin = min(minimum(x->x.first, vars,init=typemax(Int)), minimum(x->x.first+nv, params,init=typemax(Int))) + imax = max(maximum(x->x.first, vars,init=0), maximum(x->x.first+nv, params,init=0)) + else + nump = 0 + imin = minimum(x->x.first, vars,init=typemax(Int)) + imax = maximum(x->x.first, vars,init=0) + end + len = imax-imin+1 + sm = zeros(Cint, 2*len) + sm[1:2:end] = imin:imax + for i=1:numv + sm[2*(vars[i].first-imin+1)] = convert(Cint, vars[i].second) + end + for i=1:nump + sm[2*(params[i].first+nv-imin+1)] = convert(Cint, params[i].second) + end + + return sm, 2*len +end + +# Function to convert var=>ord, params=(param=>ord,) to monomial format (byte array of orders) +function pairs_to_m(t::Union{TPS,ComplexTPS}, vars::Union{Vector{<:Pair{<:Integer, <:Integer}},Tuple{Vararg{Pair{<:Integer,<:Integer}}}}; params::Union{Vector{<:Pair{<:Integer, <:Integer}},Tuple{Vararg{Pair{<:Integer,<:Integer}}}}=Pair{Int,Int}[],zero_mono=true)::Tuple{Vector{UInt8}, Cint} + nv = numvars(t) + n = Cint(0) + if isempty(params) + n = Cint(maximum(map(x->x.first, vars))) + else + n = Cint(maximum(map(x->x.first, params))) + nv + end + if zero_mono + ords = zeros(Cuchar, n) + else + ords = ones(Cuchar, n).*0xff + end + for var in vars + ords[var.first] = convert(Cuchar, var.second) + end + for param in params + ords[nv + param.first] = convert(Cuchar, param.second) + end + return ords, n +end + +# Prevent undefined behavior +# Until AbstractComplex is implemented, I make the ctor return error because this should never happen +# asumming I wrapped enough +#= +Complex(t1::TPS) = complex(t1) +Complex(t1::TPS, t2::TPS) = complex(t1, t2) +Complex(t1::TPS, a::Real) = complex(t1, a) +Complex(a::Real, t1::TPS) = complex(a, t1) +Complex{TPS}(t1::TPS) = complex(t1) +Complex{TPS}(t1::TPS, t2::TPS) = complex(t1, t2) +Complex{TPS}(t1::TPS, a::Real) = complex(t1, a) +Complex{TPS}(a::Real, t1::TPS) = complex(a, t1)=# +Complex(t1::TPS) = error("ComplexTPS can only be defined as an AbstractComplex type (to be implemented in Julia PR #35587). If this error was reached without explicitly attempting to create a Complex{TPS}, please submit an issue to GTPSA.jl with an example.") +Complex(t1::TPS, t2::TPS) = error("ComplexTPS can only be defined as an AbstractComplex type (to be implemented in Julia PR #35587). If this error was reached without explicitly attempting to create a Complex{TPS}, please submit an issue to GTPSA.jl with an example.") +Complex(t1::TPS, a::Real) = error("ComplexTPS can only be defined as an AbstractComplex type (to be implemented in Julia PR #35587). If this error was reached without explicitly attempting to create a Complex{TPS}, please submit an issue to GTPSA.jl with an example.") +Complex(a::Real, t1::TPS) = error("ComplexTPS can only be defined as an AbstractComplex type (to be implemented in Julia PR #35587). If this error was reached without explicitly attempting to create a Complex{TPS}, please submit an issue to GTPSA.jl with an example.") +Complex{TPS}(t1::TPS) = error("ComplexTPS can only be defined as an AbstractComplex type (to be implemented in Julia PR #35587). If this error was reached without explicitly attempting to create a Complex{TPS}, please submit an issue to GTPSA.jl with an example.") +Complex{TPS}(t1::TPS, t2::TPS) = error("ComplexTPS can only be defined as an AbstractComplex type (to be implemented in Julia PR #35587). If this error was reached without explicitly attempting to create a Complex{TPS}, please submit an issue to GTPSA.jl with an example.") +Complex{TPS}(t1::TPS, a::Real) = error("ComplexTPS can only be defined as an AbstractComplex type (to be implemented in Julia PR #35587). If this error was reached without explicitly attempting to create a Complex{TPS}, please submit an issue to GTPSA.jl with an example.") +Complex{TPS}(a::Real, t1::TPS) = error("ComplexTPS can only be defined as an AbstractComplex type (to be implemented in Julia PR #35587). If this error was reached without explicitly attempting to create a Complex{TPS}, please submit an issue to GTPSA.jl with an example.") + +promote_rule(::Type{TPS}, ::Union{Type{<:AbstractFloat}, Type{<:Integer}, Type{<:Rational}, Type{<:AbstractIrrational}}) = TPS +promote_rule(::Type{ComplexTPS}, ::Union{Type{Complex{<:Real}},Type{<:AbstractFloat}, Type{<:Integer}, Type{<:Rational}, Type{<:AbstractIrrational}}) = ComplexTPS +promote_rule(::Type{TPS}, ::Union{Type{ComplexTPS}, Type{Complex{<:Real}}}) = ComplexTPS + +# Handle bool which is special for some reason ++(t::TPS, z::Complex{Bool}) = t + Complex{Int}(z) ++(z::Complex{Bool}, t::TPS) = Complex{Int}(z) + t +-(t::TPS, z::Complex{Bool}) = t - Complex{Int}(z) +-(z::Complex{Bool}, t::TPS) = Complex{Int}(z) - t +*(t::TPS, z::Complex{Bool}) = t * Complex{Int}(z) +*(z::Complex{Bool}, t::TPS) = Complex{Int}(z) * t +/(t::TPS, z::Complex{Bool}) = t / Complex{Int}(z) +/(z::Complex{Bool}, t::TPS) = Complex{Int}(z) / t +^(t::TPS, z::Complex{Bool}) = t ^ Complex{Int}(z) +^(z::Complex{Bool}, t::TPS) = Complex{Int}(z) ^ t \ No newline at end of file From 052f7d11c5542b3bbbab1b55eefe3cc952b9a2e9 Mon Sep 17 00:00:00 2001 From: mattsignorelli Date: Tue, 2 Apr 2024 11:32:26 -0400 Subject: [PATCH 06/29] bug fix --- src/methods.jl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/methods.jl b/src/methods.jl index 9e6c2242..fe7e2d0d 100644 --- a/src/methods.jl +++ b/src/methods.jl @@ -2,12 +2,12 @@ eval!(na::Cint, ma::Vector{Ptr{RTPSA}}, nb::Cint, tb::Vector{Float64}, tc::Vector{Float64}) = mad_tpsa_eval!(na, ma, nb, tb, tc) eval!(na::Cint, ma::Vector{Ptr{CTPSA}}, nb::Cint, tb::Vector{ComplexF64}, tc::Vector{ComplexF64}) = mad_ctpsa_eval!(na, ma, nb, tb, tc) -function evaluate!(tc::Vector{<:Number}, m::Vector{<:Union{TPS,ComplexTPS}}, tb::Vector{<:Number}; work_low::Vector{lowtype(eltype(m))}=Vector{lowtype(eltype(m))}(undef, length(m))) +function evaluate!(tc::Vector{<:Number}, m::Vector{T}, tb::Vector{<:Number}; work_low::Vector{<:Union{Ptr{RTPSA},Ptr{CTPSA}}}=Vector{lowtype(T)}(undef, length(m))) where {T<:Union{TPS,ComplexTPS}} na = Cint(length(m)) nb = Cint(length(tb)) @assert na == nb "Vector lengths for TPSs and evaluation point disagree" @assert length(tc) == nb "Output vector length disagrees with input vector length" - + end @@ -17,7 +17,7 @@ end Evaluates `m` at the point `x`. """ -function evaluate(m::Vector{<:Union{TPS,ComplexTPS}, x::Vector{<:Number}) +function evaluate(m::Vector{<:Union{TPS,ComplexTPS}}, x::Vector{<:Number}) na = Cint(length(m)) ma = map(t->t.tpsa, m) nb = Cint(length(x)) From 75ba44119f4e006f2b60b2d1ff6928323e4df3ce Mon Sep 17 00:00:00 2001 From: mattsignorelli Date: Tue, 2 Apr 2024 15:42:40 -0400 Subject: [PATCH 07/29] Methods revamped + documented --- docs/src/man/a_toc.md | 2 +- docs/src/man/k_methods.md | 18 +- docs/src/man/o_all.md | 2 +- src/GTPSA.jl | 19 +- src/methods.jl | 738 +++++++++++++------------------------- src/operators.jl | 9 - 6 files changed, 270 insertions(+), 518 deletions(-) diff --git a/docs/src/man/a_toc.md b/docs/src/man/a_toc.md index 97ba6a5d..b2706977 100644 --- a/docs/src/man/a_toc.md +++ b/docs/src/man/a_toc.md @@ -9,7 +9,7 @@ 7. **[Monomial Indexing](@ref monoindex)**: Get/set individual monomial coefficients 8. **[`mono`](@ref mono)**: Creates a TPS corresponding to a specific monomial 9. **[Slicing and `par`](@ref slice)**: Indexing a specific polynomial within the TPS -10. **[TPS and Map Methods](@ref tpsmapmethods)**: Integrate, differentiate, poisson bracket, map (partial) inversion, etc. +10. **[TPS Methods](@ref tpsmethods)**: Integrate, differentiate, composition, evaluation, etc. 11. **[`@FastGTPSA`](@ref fastgtpsa)**: Speed up evaluation of expressions containing TPSs, transparent to other types 12. **[I/O](@ref io)**: Reading/writing TPSs 13. **[All Overloaded Functions](@ref all)**: List of all overloaded Base functions and more \ No newline at end of file diff --git a/docs/src/man/k_methods.md b/docs/src/man/k_methods.md index 923c5775..a799cb0c 100644 --- a/docs/src/man/k_methods.md +++ b/docs/src/man/k_methods.md @@ -1,19 +1,19 @@ -# [TPS and Map Methods](@id tpsmapmethods) +# [TPS Methods](@id tpsmethods) ```@docs clear! +complex! +compose! cutord +cutord! deriv +deriv! evaluate -exppb -fgrad -gethamiltonian +evaluate! getord -getvectorfield +getord! integ -lb -logpb -pb -ptinv +integ! scalar translate +translate! ``` \ No newline at end of file diff --git a/docs/src/man/o_all.md b/docs/src/man/o_all.md index 49f08e7a..f820cf59 100644 --- a/docs/src/man/o_all.md +++ b/docs/src/man/o_all.md @@ -15,7 +15,7 @@ complex, promote_rule, getindex, setindex!, ==, <, >, <=, >=, `GTPSA.jl` also provides the following functions NOT included in Base or any of the above packages: ``` -unit, sinhc, asinc, asinhc, polar, rect +unit, sinhc, asinc, asinhc, polar, rect ``` If there is a mathematical function in Base which you'd like and is not included in the above list, feel free to submit an [issue](https://github.com/bmad-sim/GTPSA.jl/issues). \ No newline at end of file diff --git a/src/GTPSA.jl b/src/GTPSA.jl index 6d410697..b1c2ce7f 100644 --- a/src/GTPSA.jl +++ b/src/GTPSA.jl @@ -80,6 +80,7 @@ export polar, rect, clear!, + complex!, # Monomial as TPS creators: vars, @@ -101,20 +102,12 @@ export # Methods: - evaluate, + evaluate, evaluate!, compose, - integ, ∫, - deriv, ∂, - getord, - cutord, - pb, - lb, - getvectorfield, - gethamiltonian, - exppb, - logpb, - fgrad, - ptinv, + integ, ∫, integ!, ∫!, + deriv, ∂, deriv!, ∂!, + getord, getord!, + cutord, cutord!, translate, par, scalar, diff --git a/src/methods.jl b/src/methods.jl index fe7e2d0d..5b80be48 100644 --- a/src/methods.jl +++ b/src/methods.jl @@ -1,65 +1,61 @@ -# --- Evaluate --- -eval!(na::Cint, ma::Vector{Ptr{RTPSA}}, nb::Cint, tb::Vector{Float64}, tc::Vector{Float64}) = mad_tpsa_eval!(na, ma, nb, tb, tc) -eval!(na::Cint, ma::Vector{Ptr{CTPSA}}, nb::Cint, tb::Vector{ComplexF64}, tc::Vector{ComplexF64}) = mad_ctpsa_eval!(na, ma, nb, tb, tc) - -function evaluate!(tc::Vector{<:Number}, m::Vector{T}, tb::Vector{<:Number}; work_low::Vector{<:Union{Ptr{RTPSA},Ptr{CTPSA}}}=Vector{lowtype(T)}(undef, length(m))) where {T<:Union{TPS,ComplexTPS}} - na = Cint(length(m)) - nb = Cint(length(tb)) - @assert na == nb "Vector lengths for TPSs and evaluation point disagree" - @assert length(tc) == nb "Output vector length disagrees with input vector length" - - -end +# --- clear --- +clear!(t::Ptr{RTPSA}) = mad_tpsa_clear!(t) +clear!(t::Ptr{CTPSA}) = mad_ctpsa_clear!(t) -# TPS: """ - evaluate(m::Vector{TPS}, x::Vector{<:Real})::Vector{Float64} + clear!(t::Union{TPS,ComplexTPS}) -Evaluates `m` at the point `x`. +Clears the TPS (sets all monomial coefficients to 0). """ -function evaluate(m::Vector{<:Union{TPS,ComplexTPS}}, x::Vector{<:Number}) - na = Cint(length(m)) - ma = map(t->t.tpsa, m) - nb = Cint(length(x)) - tb = convert(Vector{Float64}, x) - tc = Vector{Float64}(undef, nb) - mad_tpsa_eval!(na, ma, nb, tb, tc) - return tc +function clear!(t::Union{TPS,ComplexTPS}) + clear!(t.tpsa) end +# --- complex! --- + """ - evaluate(t1::TPS, x::Vector{<:Real})::Float64 + complex!(ct::ComplexTPS, t::TPS) -Evaluates `t1` at the point `x`. +Sets the pre-allocated `ComplexTPS` `ct` equal to `t`. """ -function evaluate(t1::TPS, x::Vector{<:Real})::Float64 - return evaluate([t1], x)[1] +function complex!(ct::ComplexTPS, t::TPS) + mad_ctpsa_cplx!(t.tpsa, Base.unsafe_convert(Ptr{RTPSA}, C_NULL), ct.tpsa) end +# --- Evaluate --- +eval!(na::Cint, ma::Vector{Ptr{RTPSA}}, nb::Cint, tb::Vector{Float64}, tc::Vector{Float64}) = mad_tpsa_eval!(na, ma, nb, tb, tc) +eval!(na::Cint, ma::Vector{Ptr{CTPSA}}, nb::Cint, tb::Vector{ComplexF64}, tc::Vector{ComplexF64}) = mad_ctpsa_eval!(na, ma, nb, tb, tc) -# ComplexTPS: """ - evaluate(m::Vector{ComplexTPS}, x::Vector{<:Number})::Vector{ComplexF64} + evaluate!(tc::Vector{<:Number}, m::Vector{T}, tb::Vector{<:Number}; work_low::Vector{<:Union{Ptr{RTPSA},Ptr{CTPSA}}}=Vector{lowtype(T)}(undef, length(m))) where {T<:Union{TPS,ComplexTPS}} -Evaluates `m` at the point `x`. +Evaluates the vector function `m` at the point `tb`, and fills `tc` with the result. +An optional container `work_low` can be provided for containing the low-level TPS +structs for zero allocations. """ -function evaluate(m::Vector{ComplexTPS}, x::Vector{<:Number})::Vector{ComplexF64} +function evaluate!(tc::Vector{<:Number}, m::Vector{T}, tb::Vector{<:Number}; work_low::Vector{<:Union{Ptr{RTPSA},Ptr{CTPSA}}}=Vector{lowtype(T)}(undef, length(m))) where {T<:Union{TPS,ComplexTPS}} na = Cint(length(m)) - ma = map(t->t.tpsa, m) - nb = Cint(length(x)) - tb = convert(Vector{ComplexF64}, x) - tc = Vector{ComplexF64}(undef, nb) - mad_ctpsa_eval!(na, ma, nb, tb, tc) - return tc + nb = Cint(length(tb)) + @assert na == nb "Vector lengths for TPSs and evaluation point disagree" + @assert length(tc) == nb "Output vector length disagrees with input vector length" + @assert length(work_low) == na "work_low vector length != input vector length" + @assert eltype(tc) == numtype(T) "Output vector eltype should be $(numtype(T)), received $(typeof(tc))" + + map!(t->t.tpsa, work_low, m) + eval!(na, work_low, nb, tb, tc) + return end """ - evaluate(ct1::ComplexTPS, x::Vector{<:Number})::ComplexF64 + evaluate(m::Vector{T}, tb::Vector{<:Number}) where {T<:Union{TPS,ComplexTPS}} -Evaluates `ct1` at the point `x`. +Evaluates the vector function `m` at the point `tb`. """ -function evaluate(ct1::ComplexTPS, x::Vector{<:Number})::ComplexF64 - return evaluate([ct1], x)[1] +function evaluate(m::Vector{T}, tb::Vector{<:Number}) where {T<:Union{TPS,ComplexTPS}} + na = Cint(length(m)) + tc = Vector{numtype(T)}(undef, na) + evaluate!(tc, m, tb) + return tc end # --- Integral --- @@ -67,6 +63,21 @@ end integ!(tpsa1::Ptr{RTPSA}, tpsa::Ptr{RTPSA}, var::Cint) = (@inline; mad_tpsa_integ!(tpsa1, tpsa, var)) integ!(ctpsa1::Ptr{CTPSA}, ctpsa::Ptr{CTPSA}, var::Cint) = (@inline; mad_ctpsa_integ!(ctpsa1, ctpsa, var)) +""" + integ!(t::T, t1::T, var::Integer=1) where {T<:Union{TPS,ComplexTPS}} + ∫!(t::T, t1::T, var::Integer=1) where {T<:Union{TPS,ComplexTPS}} + +Integrates `t1` wrt the variable `var` and fills `t` with the result. +Integration wrt parameters is not allowed, and integration wrt higher order +monomials is not currently supported. +""" +function integ!(t::T, t1::T, var::Integer=1) where {T<:Union{TPS,ComplexTPS}} + integ(t1.tpsa, t.tpsa, Cint(var)) + return +end + +∫! = integ! + """ integ(t1::Union{TPS, ComplexTPS}, var::Integer=1) ∫(t1::Union{TPS, ComplexTPS}, var::Integer=1) @@ -77,7 +88,7 @@ monomials is not currently supported. """ function integ(t1::Union{TPS, ComplexTPS}, var::Integer=1) t = zero(t1) - integ!(t1.tpsa, t.tpsa, Cint(var)) + integ!(t, t1, var) return t end @@ -91,16 +102,35 @@ derivm!(tpsa1::Ptr{RTPSA}, tpsa::Ptr{RTPSA}, n::Cint, ords::Vector{Cuchar}) = (@ derivm!(ctpsa1::Ptr{CTPSA}, ctpsa::Ptr{CTPSA}, n::Cint, ords::Vector{Cuchar}) = (@inline; mad_ctpsa_derivm!(ctpsa1, ctpsa, n, ords)) """ - deriv(t1::Union{TPS,ComplexTPS}, v::Union{Integer, Vector{<:Union{<:Pair{<:Integer,<:Integer},<:Integer}}, Nothing}=nothing; param::Union{Integer,Nothing}=nothing, params::Union{Vector{<:Pair{<:Integer,<:Integer}}, Nothing}=nothing) - ∂(t1::Union{TPS,ComplexTPS}, v::Union{Integer, Vector{<:Union{<:Pair{<:Integer,<:Integer},<:Integer}}, Nothing}=nothing; param::Union{Integer,Nothing}=nothing, params::Union{Vector{<:Pair{<:Integer,<:Integer}}, Nothing}=nothing) + deriv!(t::T, t1::T, v::Union{TPSIndexType, Nothing}=nothing; param::Union{Integer,Nothing}=nothing, params::Union{SMIndexType, Nothing}=nothing) where {T<:Union{TPS,ComplexTPS}} + ∂!(t::T, t1::T, v::Union{TPSIndexType, Nothing}=nothing; param::Union{Integer,Nothing}=nothing, params::Union{SMIndexType, Nothing}=nothing) where {T<:Union{TPS,ComplexTPS}} + +Differentiates `t1` wrt the variable/parameter specified by the variable/parameter index, or +alternatively any monomial specified by indexing-by-order OR indexing-by-sparse monomial, and +sets `t` equal to the result in-place. See the `deriv` documentation for examples. + +### Input +- `v` -- An integer (for variable index), vector/tuple of orders for each variable (for indexing-by-order), or vector/tuple of pairs (sparse monomial) +- `param` -- (Keyword argument, optional) An integer for the parameter index +- `params` -- (Keyword argument, optional) Vector/tuple of pairs for sparse-monomial indexing +""" +function deriv!(t::T, t1::T, v::Union{TPSIndexType, Nothing}=nothing; param::Union{Integer,Nothing}=nothing, params::Union{SMIndexType, Nothing}=nothing) where {T<:Union{TPS,ComplexTPS}} + low_deriv!(t, t1, v, param, params) +end + +∂! = deriv! + +""" + deriv(t1::Union{TPS,ComplexTPS}, v::Union{TPSIndexType, Nothing}=nothing; param::Union{Integer,Nothing}=nothing, params::Union{SMIndexType, Nothing}=nothing) + ∂(t1::Union{TPS,ComplexTPS}, v::Union{TPSIndexType, Nothing}=nothing; param::Union{Integer,Nothing}=nothing, params::Union{SMIndexType, Nothing}=nothing) Differentiates `t1` wrt the variable/parameter specified by the variable/parameter index, or alternatively any monomial specified by indexing-by-order OR indexing-by-sparse monomial. ### Input -- `v` -- An integer (for variable index), an array of orders for each variable (for indexing-by-order), or an array of pairs (sparse monomial) +- `v` -- An integer (for variable index), vector/tuple of orders for each variable (for indexing-by-order), or vector/tuple of pairs (sparse monomial) - `param` -- (Keyword argument, optional) An integer for the parameter index -- `params` -- (Keyword argument, optional) An array of pairs for sparse-monomial indexing +- `params` -- (Keyword argument, optional) Vector/tuple of pairs for sparse-monomial indexing # Examples: Variable/Parameter Index: ```julia-repl @@ -160,75 +190,72 @@ TPS: 1.0000000000000000e+00 0 0 0 ``` """ -function deriv(t1::Union{TPS,ComplexTPS}, v::Union{Integer, Vector{<:Union{<:Pair{<:Integer,<:Integer},<:Integer}}, Nothing}=nothing; param::Union{Integer,Nothing}=nothing, params::Union{Vector{<:Pair{<:Integer,<:Integer}}, Nothing}=nothing) - return low_deriv(t1, v, param, params) +function deriv(t1::Union{TPS,ComplexTPS}, v::Union{TPSIndexType, Nothing}=nothing; param::Union{Integer,Nothing}=nothing, params::Union{SMIndexType, Nothing}=nothing) + t = zero(t1) + low_deriv!(t, t1, v, param, params) + return t end # Variable/parameter: -function low_deriv(t1::Union{TPS,ComplexTPS}, v::Integer, param::Nothing, params::Nothing) - t = zero(t1) +function low_deriv!(t::T, t1::T, v::Integer, param::Nothing, params::Nothing) where {T<:Union{TPS,ComplexTPS}} deriv!(t1.tpsa, t.tpsa, convert(Cint, v)) - return t end -function low_deriv(t1::Union{TPS,ComplexTPS}, v::Nothing, param::Integer, params::Nothing) - t = zero(t1) - desc = unsafe_load(Base.unsafe_convert(Ptr{Desc}, unsafe_load(t1.tpsa).d)) - nv = desc.nv # TOTAL NUMBER OF VARS!!!! +function low_deriv!(t::T, t1::T, v::Nothing, param::Integer, params::Nothing) where {T<:Union{TPS,ComplexTPS}} + nv = numvars(t1) deriv!(t1.tpsa, t.tpsa, Cint(param)+nv) - return t end # Default to first variable if nothing passed: -function low_deriv(t1::Union{TPS,ComplexTPS}, v::Nothing, param::Nothing, params::Nothing) - return low_deriv(t1, 1, nothing, nothing) +function low_deriv!(t::T, t1::T, v::Nothing, param::Nothing, params::Nothing) where {T<:Union{TPS,ComplexTPS}} + low_deriv!(t1, 1, nothing, nothing) end # Monomial by order: -function low_deriv(t1::Union{TPS,ComplexTPS}, v::Vector{<:Integer}, param::Nothing, params::Nothing) - t = zero(t1) +function low_deriv!(t::T, t1::T, v::MIndexType, param::Nothing, params::Nothing) where {T<:Union{TPS,ComplexTPS}} derivm!(t1.tpsa, t.tpsa, Cint(length(v)), convert(Vector{Cuchar}, v)) - return t end # Monomial by sparse monomial: -function low_deriv(t1::Union{TPS,ComplexTPS}, v::Vector{<:Pair{<:Integer,<:Integer}}, param::Nothing, params::Vector{<:Pair{<:Integer,<:Integer}}) - t = zero(t1) +function low_deriv!(t::T, t1::T, v::SMIndexType, param::Nothing, params::SMIndexType) where {T<:Union{TPS,ComplexTPS}} # Need to create array of orders with length nv + np ords, n = pairs_to_m(t1,v,params=params) derivm!(t1.tpsa, t.tpsa, n, ords) - return t end -function low_deriv(t1::Union{TPS,ComplexTPS}, v::Vector{<:Pair{<:Integer,<:Integer}}, param::Nothing, params::Nothing) - t = zero(t1) +function low_deriv!(t::T, t1::T, v::SMIndexType, param::Nothing, params::Nothing) where {T<:Union{TPS,ComplexTPS}} # Need to create array of orders with length nv + np ords, n = pairs_to_m(t1,v) derivm!(t1.tpsa, t.tpsa, n, ords) - return t end -function low_deriv(t1::Union{TPS,ComplexTPS}, v::Nothing, param::Nothing, params::Vector{<:Pair{<:Integer,<:Integer}}) - t = zero(t1) +function low_deriv!(t::T, t1::T, v::Nothing, param::Nothing, params::SMIndexType) where {T<:Union{TPS,ComplexTPS}} # Need to create array of orders with length nv + np ords, n = pairs_to_m(t1,Pair{Int,Int}[],params=params) derivm!(t1.tpsa, t.tpsa, n, ords) - return t end # Throw error if no above use cases satisfied: -function low_deriv(t1::Union{TPS,ComplexTPS}, v, param, params) +function low_deriv(t::T, t1::T, v, param, params) where {T<:Union{TPS,ComplexTPS}} error("Invalid monomial specified. Please use ONE of variable/parameter index, index by order, or index by sparse monomial.") end ∂ = deriv -# --- getord and cutord --- +# --- getord --- # Low-level equivalent calls for TPS and ComplexTPS: getord!(tpsa1::Ptr{RTPSA}, tpsa::Ptr{RTPSA}, order::Cuchar) = (@inline; mad_tpsa_getord!(tpsa1, tpsa, order)) getord!(ctpsa1::Ptr{CTPSA}, ctpsa::Ptr{CTPSA}, order::Cuchar) = (@inline; mad_ctpsa_getord!(ctpsa1, ctpsa, order)) -cutord!(tpsa1::Ptr{RTPSA}, tpsa::Ptr{RTPSA}, order::Cint) = (@inline; mad_tpsa_cutord!(tpsa1, tpsa, order)) -cutord!(ctpsa1::Ptr{CTPSA}, ctpsa::Ptr{CTPSA}, order::Cint) = (@inline; mad_ctpsa_cutord!(ctpsa1, ctpsa, order)) + +""" + getord!(t::T, t1::T, order::Integer) where {T<:Union{TPS,ComplexTPS}} + +Extracts one homogenous polynomial from `t1` of the given order and +fills `t` with the result in-place. +""" +function getord!(t::T, t1::T, order::Integer) where {T<:Union{TPS,ComplexTPS}} + getord!(t1.tpsa, t.tpsa, Cuchar(order)) +end """ getord(t1::Union{TPS, ComplexTPS}, order::Integer) @@ -237,10 +264,25 @@ Extracts one homogenous polynomial from `t1` of the given order. """ function getord(t1::Union{TPS, ComplexTPS}, order::Integer) t = zero(t1) - getord!(t1.tpsa, t.tpsa, convert(Cuchar, order)) + getord!(t, t1, order) return t end +# --- cutord --- +cutord!(tpsa1::Ptr{RTPSA}, tpsa::Ptr{RTPSA}, order::Cint) = (@inline; mad_tpsa_cutord!(tpsa1, tpsa, order)) +cutord!(ctpsa1::Ptr{CTPSA}, ctpsa::Ptr{CTPSA}, order::Cint) = (@inline; mad_ctpsa_cutord!(ctpsa1, ctpsa, order)) + +""" + cutord!(t::T, t1::T, order::Integer) where {T<:Union{TPS,ComplexTPS}} + +Cuts out the monomials in `t1` at the given order and above. Or, if `order` +is negative, will cut monomials with orders at and below `abs(order)`. `t` +is filled in-place with the result. See the documentation for `cutord` for examples. +""" +function cutord!(t::T, t1::T, order::Integer) where {T<:Union{TPS,ComplexTPS}} + cutord!(t1.tpsa, t.tpsa, convert(Cint, order)) +end + """ cutord(t1::Union{TPS, ComplexTPS}, order::Integer) @@ -269,13 +311,12 @@ TPS: """ function cutord(t1::Union{TPS, ComplexTPS}, order::Integer) t = zero(t1) - cutord!(t1.tpsa, t.tpsa, convert(Cint, order)) + cutord!(t, t1, order) return t end # --- scalar --- - """ scalar(t::Union{TPS,ComplexTPS}) @@ -286,458 +327,185 @@ function scalar(t::Union{TPS,ComplexTPS}) return t[0] end +# --- composition --- +compose!(na::Cint, ma::Vector{Ptr{RTPSA}}, nb::Cint, mb::Vector{Ptr{RTPSA}}, mc::Vector{Ptr{RTPSA}}) = (@inline; mad_tpsa_compose!(na, ma, nb, mb, mc)) +compose!(na::Cint, ma::Vector{Ptr{CTPSA}}, nb::Cint, mb::Vector{Ptr{CTPSA}}, mc::Vector{Ptr{CTPSA}}) = (@inline; mad_ctpsa_compose!(na, ma, nb, mb, mc)) -# --- Poisson bracket --- -# Low-level calls -poisbra!(tpsa1::Ptr{RTPSA}, tpsa2::Ptr{RTPSA}, tpsa::Ptr{RTPSA}, nv::Cint) = (@inline; mad_tpsa_poisbra!(tpsa1, tpsa2, tpsa, nv)) -poisbra!(tpsa1::Ptr{RTPSA}, ctpsa1::Ptr{CTPSA}, ctpsa::Ptr{CTPSA}, nv::Cint) = (@inline; mad_ctpsa_poisbrat!(ctpsa1,tpsa1,ctpsa, nv)) -poisbra!(ctpsa1::Ptr{CTPSA}, tpsa1::Ptr{RTPSA}, ctpsa::Ptr{CTPSA}, nv::Cint) = (@inline; mad_ctpsa_tpoisbra!(tpsa1, ctpsa1, ctpsa, nv)) -poisbra!(ctpsa1::Ptr{CTPSA}, ctpsa2::Ptr{CTPSA}, ctpsa::Ptr{CTPSA}, nv::Cint) = (@inline; mad_ctpsa_poisbra!(ctpsa1,ctpsa2, ctpsa, nv)) - -""" - pb(f::Union{TPS, ComplexTPS}, g::Union{TPS, ComplexTPS}) - -Assuming the variables in the TPSA are canonically-conjugate, and ordered so that the canonically- -conjugate variables are consecutive (q₁, p₁, q₂, p₂, ...), computes the Poisson bracket -of the scalar functions `f` and `g`. The Poisson bracket of two functions `{f, g}` is defined as -`Σᵢ (∂f/∂qᵢ)(∂g/∂pᵢ) - (∂g/∂qᵢ)(∂f/∂pᵢ)`. - -# Examples -```julia-repl -julia> d = Descriptor(4,10); - -julia> x = vars(d); - -julia> f = (x[1]^2 + x[2]^2)/2 + (x[3]^2 + x[4]^2)/2; - -julia> pb(f,x[1]) -TPS: - Coefficient Order Exponent - -1.0000000000000000e+00 1 0 1 0 0 - - -julia> pb(f,x[2]) -TPS: - Coefficient Order Exponent - 1.0000000000000000e+00 1 1 0 0 0 - - -julia> pb(f,x[3]) -TPS: - Coefficient Order Exponent - -1.0000000000000000e+00 1 0 0 0 1 - - -julia> pb(f,x[4]) -TPS: - Coefficient Order Exponent - 1.0000000000000000e+00 1 0 0 1 0 -``` -""" -function pb(f::Union{TPS, ComplexTPS}, g::Union{TPS, ComplexTPS}) - t = promote_type(typeof(f),typeof(g))(use=f) - desc = unsafe_load(Base.unsafe_convert(Ptr{Desc}, unsafe_load(f.tpsa).d)) - poisbra!(f.tpsa,g.tpsa,t.tpsa, desc.nv) - return t -end - -# --- Lie bracket --- -liebra!(na::Cint, m1::Vector{Ptr{RTPSA}}, m2::Vector{Ptr{RTPSA}}, m3::Vector{Ptr{RTPSA}}) = (@inline; mad_tpsa_liebra!(na, m1, m2, m3)) -liebra!(na::Cint, m1::Vector{Ptr{CTPSA}}, m2::Vector{Ptr{CTPSA}}, m3::Vector{Ptr{CTPSA}}) = (@inline; mad_ctpsa_liebra!(na, m1, m2, m3)) - -""" - lb(A::Vector{<:Union{TPS,ComplexTPS}}, F::Vector{<:Union{TPS,ComplexTPS}}) - -Computes the Lie bracket of the vector functions `A` and `F`, defined over N variables as -`Σᵢᴺ Aᵢ (∂F/∂xᵢ) - Fᵢ (∂A/∂xᵢ)` - -# Example -```julia-repl -julia> d = Descriptor(2,10); x = vars(); - -julia> A = [-x[2], x[1]] -2-element Vector{TPS}: - Out Coefficient Order Exponent -------------------------------------------------- - 1: -1.0000000000000000e+00 1 0 1 -------------------------------------------------- - 2: 1.0000000000000000e+00 1 1 0 - - -julia> F = [-x[1]^2, 2*x[1]*x[2]] -2-element Vector{TPS}: - Out Coefficient Order Exponent -------------------------------------------------- - 1: -1.0000000000000000e+00 2 2 0 -------------------------------------------------- - 2: 2.0000000000000000e+00 2 1 1 - - -julia> lb(A,F) -2-element Vector{TPS}: - Out Coefficient Order Exponent -------------------------------------------------- - 1: 4.0000000000000000e+00 2 1 1 -------------------------------------------------- - 2: 3.0000000000000000e+00 2 2 0 - 2: -2.0000000000000000e+00 2 0 2 -``` -""" -function lb(A::Vector{<:Union{TPS,ComplexTPS}}, F::Vector{<:Union{TPS,ComplexTPS}}) - desc = unsafe_load(Base.unsafe_convert(Ptr{Desc}, unsafe_load(A[1].tpsa).d)) - if length(A) != desc.nv || length(F) != desc.nv - error("Vector length != number of variables in the GTPSA") - end - A1, F1 = promote(A, F) - m1 = map(t->t.tpsa, A1) - m2 = map(t->t.tpsa, F1) - mc = zero.(A1) - m3 = map(t->t.tpsa, mc) - GC.@preserve A1 F1 liebra!(Cint(length(A)), m1, m2, m3) - return mc -end - -# --- getvectorfield --- -vec2fld!(na::Cint, tpsa::Ptr{RTPSA}, m::Vector{Ptr{RTPSA}}) = (@inline; mad_tpsa_vec2fld!(na, tpsa, m)) -vec2fld!(na::Cint, ctpsa::Ptr{CTPSA}, m::Vector{Ptr{CTPSA}}) = (@inline; mad_ctpsa_vec2fld!(na, ctpsa, m)) - -""" - getvectorfield(h::Union{TPS,ComplexTPS})::Vector{<:typeof(h)} - -Assuming the variables in the TPSA are canonically-conjugate, and ordered so that the canonically- -conjugate variables are consecutive (q₁, p₁, q₂, p₂, ...), calculates the vector field (Hamilton's -equations) from the passed Hamiltonian, defined as `[∂h/∂p₁, -∂h/∂q₁, ...]` - -# Example -```julia-repl -julia> d = Descriptor(2,10); x = vars(); - -julia> h = (x[1]^2 + x[2]^2)/2 -TPS: - Coefficient Order Exponent - 5.0000000000000000e-01 2 2 0 - 5.0000000000000000e-01 2 0 2 - - -julia> getvectorfield(h) -2-element Vector{TPS}: - Out Coefficient Order Exponent -------------------------------------------------- - 1: -1.0000000000000000e+00 1 0 1 -------------------------------------------------- - 2: 1.0000000000000000e+00 1 1 0 -``` -""" -function getvectorfield(h::Union{TPS,ComplexTPS})::Vector{<:typeof(h)} - desc = unsafe_load(Base.unsafe_convert(Ptr{Desc}, unsafe_load(h.tpsa).d)) - na = desc.nv - mc = Vector{typeof(h)}(undef, na) - for i in eachindex(mc) - mc[i] = zero(h) - end - m = map(t->t.tpsa, mc) - vec2fld!(na, h.tpsa, m) - return mc -end - -# --- gethamiltonian --- -fld2vec!(na::Cint, ma::Vector{Ptr{RTPSA}}, tpsa::Ptr{RTPSA}) = (@inline; mad_tpsa_fld2vec!(na, ma, tpsa)) -fld2vec!(na::Cint, ma::Vector{Ptr{CTPSA}}, ctpsa::Ptr{CTPSA}) = (@inline; mad_ctpsa_fld2vec!(na, ma, ctpsa)) """ - gethamiltonian(F::Vector{<:Union{TPS,ComplexTPS}}) + compose!(m::Vector{<:Union{TPS,ComplexTPS}}, m2::Vector{<:Union{TPS,ComplexTPS}}, m1::Vector{<:Union{TPS,ComplexTPS}}; work_low::Union{Nothing,Tuple{Vararg{Vector{<:Union{Ptr{RTPSA},Ptr{CTPSA}}}}}}=nothing, work_prom::Union{Nothing,Tuple{Vararg{Vector{<:ComplexTPS}}}}=nothing) -Assuming the variables in the TPSA are canonically-conjugate, and ordered so that the canonically- -conjugate variables are consecutive (q₁, p₁, q₂, p₂, ...), this function calculates the Hamiltonian -from a vector field `F` that can be obtained from a Hamiltonian (e.g. by `getvectorfield`). Explicitly, -`∫ F₁ dp₁ - ∫ F₂ dq₁ + ... + ∫ F₂ₙ₋₁ dpₙ - ∫ F₂ₙ dqₙ ` +Composes the vector functions `m2 ∘ m1` and stores the result in-place in `m`. Promotion is allowed, provided +the output vector function `m` has the correct promoted type. -# Example -```julia-repl -julia> d = Descriptor(2,10); x = vars(); +For all compositions, 3 temporary vectors must be generated that contain Ptr{RTPSA} or Ptr{CTPSA} +for each TPS in the map (depending on output type), to pass to the low-level C composition function in GTPSA. +They are correspondingly referred to as `outx_low`, `m2x_low`, and `m1x_low`. These three temporaries containers +can be optionally passed as a tuple in `work_low`, and must satisfy the following requirements: -julia> h = (x[1]^2 + x[2]^2)/2 -TPS: - Coefficient Order Exponent - 5.0000000000000000e-01 2 2 0 - 5.0000000000000000e-01 2 0 2 +work_low[1] = outx_low # Length >= length(m) = length(m2) +work_low[2] = m2x_low # Length >= length(m2) = length(m) +work_low[3] = m1x_low # Length >= length(m1) +If promotion is occuring, then one of the input vectors must be promoted to `ComplexTPS`. A vector of pre-allocated +`ComplexTPS`s can optionally provided as the first argument in the `work_prom` tuple, and has the requirement: -julia> F = getvectorfield(h) -2-element Vector{TPS}: - Out Coefficient Order Exponent -------------------------------------------------- - 1: -1.0000000000000000e+00 1 0 1 -------------------------------------------------- - 2: 1.0000000000000000e+00 1 1 0 +If `eltype(m.x) != eltype(m1.x)` (then `m1` must be promoted): +work_prom[1] = m1x_prom # Length >= length(m1), Vector{ComplexTPS} +else if `eltype(m.x) != eltype(m2.x)` (then `m2` must be promoted): +work_prom[1] = m2x_prom # Length >= length(m2) = length(m), Vector{ComplexTPS} -julia> gethamiltonian(F) -TPS: - Coefficient Order Exponent - 5.0000000000000000e-01 2 2 0 - 5.0000000000000000e-01 2 0 2 -``` +Note that the `ComplexTPS`s in the vectors must be allocated and have the same `Descriptor`. """ -function gethamiltonian(F::Vector{<:Union{TPS,ComplexTPS}}) - descF = unsafe_load(Base.unsafe_convert(Ptr{Desc}, unsafe_load(F[1].tpsa).d)) - if length(F) != descF.nv - error("Vector length != number of variables in the GTPSA") - end - h = zero(F[1]) - m1 = map(t->t.tpsa, F) - fld2vec!(Cint(length(m)), m1, h.tpsa) - return h -end - - -# --- exp(F . grad) m --- -exppb!(na::Cint, ma::Vector{Ptr{RTPSA}}, mb::Vector{Ptr{RTPSA}}, mc::Vector{Ptr{RTPSA}}) = (@inline; mad_tpsa_exppb!(na, ma, mb, mc)) -exppb!(na::Cint, ma::Vector{Ptr{CTPSA}}, mb::Vector{Ptr{CTPSA}}, mc::Vector{Ptr{CTPSA}}) = (@inline; mad_ctpsa_exppb!(na, ma, mb, mc)) - -""" - exppb(F::Vector{<:Union{TPS,ComplexTPS}}, m::Vector{<:Union{TPS,ComplexTPS}}=vars(first(F))) - -Calculates `exp(F⋅∇)m = m + F⋅∇m + (F⋅∇)²m/2! + ...`. If `m` is not provided, it is assumed -to be the identity. - -# Example - -```julia-repl -julia> d = Descriptor(2,10); x = vars()[1]; p = vars()[2]; - -julia> time = 0.01; k = 2; m = 0.01; +function compose!(m::Vector{<:Union{TPS,ComplexTPS}}, m2::Vector{<:Union{TPS,ComplexTPS}}, m1::Vector{<:Union{TPS,ComplexTPS}}; work_low::Union{Nothing,Tuple{Vararg{Vector{<:Union{Ptr{RTPSA},Ptr{CTPSA}}}}}}=nothing, work_prom::Union{Nothing,Tuple{Vararg{Vector{<:ComplexTPS}}}}=nothing) + desc = getdesc(first(m)) + n = length(m) + n2 = length(m2) + n1 = length(m1) -julia> h = p^2/(2m) + 1/2*k*x^2; + @assert n == n2 "Incorrect output length, received length $(length(m)) but need $(length(m2))" + @assert numnn(first(m2)) == n1 "Not enough input arguments" + @assert !(m === m1) "Cannot compose!(m, m2, m1) with m === m1" + @assert eltype(m) == promote_type(eltype(m2),eltype(m1)) "Cannot compose: output vector type $(eltype(m)) must be $(promote_type(eltype(m2),eltype(m1)))" + outT = eltype(m) -julia> hf = getvectorfield(h); - -julia> map = exppb(-time*hf, [x, p]) -2-element Vector{TPS}: - Out Coefficient Order Exponent -------------------------------------------------- - 1: 9.9001665555952290e-01 1 1 0 - 1: 9.9666999841313930e-01 1 0 1 -------------------------------------------------- - 2: -1.9933399968262787e-02 1 1 0 - 2: 9.9001665555952378e-01 1 0 1 -``` -""" -function exppb(F::Vector{<:Union{TPS,ComplexTPS}}, m::Vector{<:Union{TPS,ComplexTPS}}=vars(first(F))) - descF = unsafe_load(Base.unsafe_convert(Ptr{Desc}, unsafe_load(F[1].tpsa).d)) - if length(F) != descF.nv - error("Vector length != number of variables in the GTPSA") + if !isnothing(work_low) + outx_low = work_low[1] + m2x_low = work_low[2] + m1x_low = work_low[3] + @assert length(outx_low) >= n "Incorrect length for work_low[1] = outx_low. Received $(length(outx_low)), should be >=$n" + @assert length(m2x_low) >= n2 "Incorrect length for work_low[2] = m2x_low. Received $(length(m2x_low)), should be >=$n2" + @assert length(m1x_low) >= n1 "Incorrect length for work_low[3] = m1x_low. Received $(length(m1x_low)), should be >=$n1" + else + outx_low = Vector{lowtype(outT)}(undef, n) + m2x_low = Vector{lowtype(outT)}(undef, n) + m1x_low = Vector{lowtype(outT)}(undef, n1) end - ma1, mb1 = promote(F, m) - m1 = map(t->t.tpsa, ma1) - m2 = map(t->t.tpsa, mb1) - mc = zero.(ma1) - m3 = map(t->t.tpsa, mc) - GC.@preserve ma1 mb1 exppb!(Cint(length(F)), m1, m2, m3) - return mc -end - -# --- logpb --- -logpb!(na::Cint, ma::Vector{Ptr{RTPSA}}, mb::Vector{Ptr{RTPSA}}, mc::Vector{Ptr{RTPSA}}) = (@inline; mad_tpsa_logpb!(na, ma, mb, mc)) -logpb!(na::Cint, ma::Vector{Ptr{CTPSA}}, mb::Vector{Ptr{CTPSA}}, mc::Vector{Ptr{CTPSA}}) = (@inline; mad_ctpsa_logpb!(na, ma, mb, mc)) - -""" - logpb(mf::Vector{<:Union{TPS,ComplexTPS}}, mi::Vector{<:Union{TPS,ComplexTPS}}=vars(first(F))) - -Given a final map `mf` and initial map `mi`, this function calculates the vector field `F` -such that `mf=exp(F⋅∇)mi`. If `mi` is not provided, it is assumed to be the identity. - -```julia-repl -julia> d = Descriptor(2,10); x = vars()[1]; p = vars()[2]; - -julia> time = 0.01; k = 2; m = 0.01; - -julia> h = p^2/(2m) + 1/2*k*x^2; -julia> hf = getvectorfield(h); - -julia> map = exppb(-time*hf); - -julia> logpb(map) == -time*hf -true -``` -""" -function logpb(mf::Vector{<:Union{TPS,ComplexTPS}}, mi::Vector{<:Union{TPS,ComplexTPS}}=vars(first(mf))) - desc = unsafe_load(Base.unsafe_convert(Ptr{Desc}, unsafe_load(mf[1].tpsa).d)) - if length(mf) != desc.nv || length(mi) != desc.nv - error("Vector length != number of variables in the GTPSA") + if !isnothing(work_prom) + if outT != eltype(m1) + m1x_prom = work_prom[1] + m2x_prom = nothing + @assert length(m1x_prom) >= n1 "Incorrect length for work_prom[1] = m1x_prom: Received $(length(m1x_prom)), should be >=$n1" + elseif outT != eltype(m2) + m1x_prom = nothing + m2x_prom = work_prom[1] + @assert length(m2x_prom) >= n "Incorrect length for work_prom[1] = m2x_prom: Received $(length(m2x_prom)), should be >=$n" + else + m1x_prom = nothing + m2x_prom = nothing + end + else + if outT != eltype(m1) + m1x_prom = Vector{ComplexTPS}(undef, n1) + for i=1:n1 # Allocate + @inbounds m1x_prom[i] = ComplexTPS(use=desc) + end + m2x_prom = nothing + elseif outT != eltype(m2) + m1x_prom = nothing + m2x_prom = Vector{ComplexTPS}(undef, n) + for i=1:n + @inbounds m2x_prom[i] = ComplexTPS(use=desc) + end + else + m1x_prom = nothing + m2x_prom = nothing + end end - ma1, mb1 = promote(mf, mi) - m1 = map(t->t.tpsa, ma1) - m2 = map(t->t.tpsa, mb1) - mc = zero.(ma1) - m3 = map(t->t.tpsa, mc) - GC.@preserve ma1 mb1 logpb!(Cint(length(mf)), m1, m2, m3) - return mc -end - -# --- F . grad --- -fgrad!(na::Cint, ma::Vector{Ptr{RTPSA}}, b::Ptr{RTPSA}, c::Ptr{RTPSA}) = (@inline; mad_tpsa_fgrad!(na, ma, b, c)) -fgrad!(na::Cint, ma::Vector{Ptr{CTPSA}}, b::Ptr{CTPSA}, c::Ptr{CTPSA}) = (@inline; mad_ctpsa_fgrad!(na, ma, b, c)) -""" - fgrad(F::Vector{<:Union{TPS,ComplexTPS}}, g::Union{TPS,ComplexTPS}) - -Calculates `F⋅∇g`. -""" -function fgrad(F::Vector{<:Union{TPS,ComplexTPS}}, g::Union{TPS,ComplexTPS}) - descF = unsafe_load(Base.unsafe_convert(Ptr{Desc}, unsafe_load(F[1].tpsa).d)) - if length(F) != descF.nv - error("Vector length != number of variables in the GTPSA") + # Do the composition, promoting if necessary + if outT != eltype(m1) + # Promote to ComplexTPS: + for i=1:n1 + @inbounds complex!(m1x_prom[i], m1[i]) + end + map!(t->t.tpsa, m1x_low, m1x_prom) + else + map!(t->t.tpsa, m1x_low, m1) end - type = promote_type(typeof(F[1]), typeof(g)) - ma1 = convert(Vector{type}, F) - b1 = convert(type, g) - m1 = map(t->t.tpsa, ma1) - c = zero(b1) - GC.@preserve ma1 fgrad!(Cint(length(ma)), m1, b1.tpsa, c.tpsa) - return c -end - -# --- mnrm --- -mnrm(na::Cint, ma::Vector{Ptr{RTPSA}})::Float64 = mad_tpsa_mnrm(na, ma) -mnrm(na::Cint, ma::Vector{Ptr{CTPSA}})::ComplexF64 = mad_ctpsa_mnrm(na, ma) - -#= -""" - norm(ma::Vector{<:Union{TPS,ComplexTPS}}) - -Calculates the norm of the map `ma`, defined as `sum(norm.(ma))` or the -sum of the absolute value of all coefficients in each TPS. -""" -function norm(ma::Vector{<:Union{TPS,ComplexTPS}}) - return mnrm(Cint(length(ma)), map(x->x.tpsa, ma)) -end -=# -# --- map inversion --- -minv!(na::Cint, ma::Vector{Ptr{RTPSA}}, mc::Vector{Ptr{RTPSA}}) = (@inline; mad_tpsa_minv!(na, ma, mc)) -minv!(na::Cint, ma::Vector{Ptr{CTPSA}}, mc::Vector{Ptr{CTPSA}}) = (@inline; mad_ctpsa_minv!(na, ma, mc)) - -""" - inv(ma::Vector{<:Union{TPS,ComplexTPS}}) - -Inverts the map `ma` such that `ma ∘ inv(ma) = 1` in the variables. - -# Example - -```julia-repl - -julia> d = Descriptor(2,10); x = vars()[1]; p = vars()[2]; - -julia> time = 0.01; k = 2; m = 0.01; - -julia> h = p^2/(2m) + 1/2*k*x^2; - -julia> hf = getvectorfield(h); -julia> map = exppb(-time*hf, [x, p]); - -julia> map ∘ inv(map) -2-element Vector{TPS}: - Out Coefficient Order Exponent -------------------------------------------------- - 1: 1.0000000000000000e+00 1 1 0 -------------------------------------------------- - 2: 1.0000000000000002e+00 1 0 1 -``` -""" -function inv(ma::Vector{<:Union{TPS,ComplexTPS}}) - desc = unsafe_load(Base.unsafe_convert(Ptr{Desc}, unsafe_load(ma[1].tpsa).d)) - if length(ma) != desc.nv - error("Map length != number of variables in the GTPSA") + if outT != eltype(m2) + # Promote to ComplexTPS: + for i=1:n + @inbounds complex!(m2x_prom[i], m2[i]) + end + map!(t->t.tpsa, m2x_low, m2x_prom) + else + map!(t->t.tpsa, m2x_low, m2) end - mc = zero.(ma) - ma1 = map(x->x.tpsa, ma) - mc1 = map(x->x.tpsa, mc) - minv!(Cint(length(ma)), ma1, mc1) - return mc -end -# --- partial inversion --- -pminv!(na::Cint, ma::Vector{Ptr{RTPSA}}, mc::Vector{Ptr{RTPSA}}, select::Vector{Cint}) = (@inline; mad_tpsa_pminv!(na, ma, mc, select)) -pminv!(na::Cint, ma::Vector{Ptr{CTPSA}}, mc::Vector{Ptr{CTPSA}}, select::Vector{Cint}) = (@inline; mad_ctpsa_pminv!(na, ma, mc, select)) + # go low + map!(t->t.tpsa, outx_low, m) -""" - ptinv(ma::Vector{<:Union{TPS,ComplexTPS}}, vars::Vector{<:Integer}) + GC.@preserve m1x_prom m2x_prom compose!(Cint(n), m2x_low, Cint(n1), m1x_low, outx_low) -Partially-inverts the map `ma`, inverting only the variables specified by index -in `vars`. -""" -function ptinv(ma::Vector{<:Union{TPS,ComplexTPS}}, vars::Vector{<:Integer}) - desc = unsafe_load(Base.unsafe_convert(Ptr{Desc}, unsafe_load(ma[1].tpsa).d)) - if length(ma) != desc.nv - error("Map length != number of variables in the GTPSA") - end - mc = zero.(ma) - ma1 = map(x->x.tpsa, ma) - mc1 = map(x->x.tpsa, mc) - na = Cint(length(ma)) - select = zeros(Cint, na) - select[vars] .= Cint(1) - pminv!(na, ma1, mc1, select) - return mc + return end -# --- composition --- -compose!(na::Cint, ma::Vector{Ptr{RTPSA}}, nb::Cint, mb::Vector{Ptr{RTPSA}}, mc::Vector{Ptr{RTPSA}}) = (@inline; mad_tpsa_compose!(na, ma, nb, mb, mc)) -compose!(na::Cint, ma::Vector{Ptr{CTPSA}}, nb::Cint, mb::Vector{Ptr{CTPSA}}, mc::Vector{Ptr{CTPSA}}) = (@inline; mad_ctpsa_compose!(na, ma, nb, mb, mc)) - function ∘(ma::Vector{<:Union{TPS,ComplexTPS}}, mb::Vector{<:Union{TPS,ComplexTPS}}) na = Cint(length(ma)) nb = Cint(length(mb)) # Ensure mb is length = input - desc = unsafe_load(Base.unsafe_convert(Ptr{Desc}, unsafe_load(ma[1].tpsa).d)) - if desc.nv + desc.np != nb + desc = getdesc(first(ma)) + if numnn(desc) != nb error("Not enough input arguments") end - ma1, mb1 = promote(ma, mb) - m1 = map(t->t.tpsa, ma1) - m2 = map(t->t.tpsa, mb1) - mc = Vector{typeof(ma1[1])}(undef, na) - for i in eachindex(mc) - mc[i] = zero(ma1[1]) + outT = promote_type(eltype(ma),eltype(mb)) + mc = Vector{outT}(undef, na) + for i=1:na + @inbounds mc[i] = outT(use=desc) end - m3 = map(t->t.tpsa, mc) - GC.@preserve ma1 mb1 compose!(na, m1, nb, m2, m3) + compose!(mc, ma, mb) return mc end compose = ∘ # --- translate --- +translate!(na::Cint, ma::Vector{Ptr{RTPSA}}, nb::Cint, tb::Vector{Float64}, mc::Vector{Ptr{RTPSA}}) = mad_tpsa_translate!(na, ma, nb, tb, mc) +translate!(na::Cint, ma::Vector{Ptr{CTPSA}}, nb::Cint, tb::Vector{ComplexF64}, mc::Vector{Ptr{CTPSA}}) = mad_ctpsa_translate!(na, ma, nb, tb, mc) + + """ - translate(m::Vector{TPS}, x::Vector{<:Real})::Vector{TPS} + translate!(mc::Vector{<:T}, ma::Vector{<:T}, tb::Vector{<:Number}) where {T<:Union{TPS,ComplexTPS}} + +Fills `ma` with the vector function equal to `ma` with its expansion point translated by `tb`. -Translates the expansion point of the Vector of TPSs `m` by `x`. +Two temporary vectors of either `Ptr{RTPSA}` or `Ptr{CTPSA}` must be created, or they can optionally +be passed as a tuple to the kwarg `work_low` where + +`ma_low` = low corresponding to `ma` = `work_low[1]` +`mb_low` = low corresponding to `mb` = `work_low[2]` """ -function translate(m::Vector{TPS}, x::Vector{<:Real})::Vector{TPS} - na = Cint(length(m)) - nb = Cint(length(x)) - tb = convert(Vector{Float64}, x) - ma1 = map(x->x.tpsa, m) - mc = zero.(m) - mc1 = map(x->x.tpsa, mc) - mad_tpsa_translate!(na, ma1, nb, tb, mc1) - return mc +function translate!(mc::Vector{<:T}, ma::Vector{<:T}, tb::Vector{<:Number}; work_low::Union{Nothing,Tuple{Vararg{Vector{<:Union{Ptr{RTPSA},Ptr{CTPSA}}}}}}=nothing) where {T<:Union{TPS,ComplexTPS}} + desc = getdesc(first(ma)) + nb = Cint(length(tb)) + na = Cint(length(ma)) + numnn(desc) == nb || error("Not enough input arguments") + length(mc) == na || error("Output vector length != input vector length") + eltype(tb) == numtype(T) || error("Translation vector must have eltype $(numtype(T))") + if !isnothing(work_low) + ma_low = work_low[1] + mc_low = work_low[2] + else + ma_low = map(t->t.tpsa, ma) + mc_low = map(t->t.tpsa, mc) + end + translate!(na, ma_low, nb, tb, mc_low) end """ - translate(m::Vector{ComplexTPS}, x::Vector{<:Number})::Vector{ComplexTPS} - -Translates the expansion point of the Vector of TPSs `m` by `x`. +Returns a vector function equal to `ma` with its expansion point translated by `tb` """ -function translate(m::Vector{ComplexTPS}, x::Vector{<:Number})::Vector{ComplexTPS} - na = Cint(length(m)) - nb = Cint(length(x)) - tb = convert(Vector{ComplexF64}, x) - ma1 = map(x->x.tpsa, m) - mc = zero.(m) - mc1 = map(x->x.tpsa, mc) - mad_ctpsa_translate!(na, ma1, nb, tb, mc1) +function translate(ma::Vector{<:T}, tb::Vector{<:Number}) where {T<:Union{TPS,ComplexTPS}} + desc = getdesc(first(ma)) + nc = length(ma) + mc = Vector{T}(undef, nc) + for i=1:nc + mc[i] = T(use=desc) + end + translate!(mc, ma, convert(Vector{numtype(T)}, tb)) return mc end \ No newline at end of file diff --git a/src/operators.jl b/src/operators.jl index 29eb1669..9be7bcd5 100644 --- a/src/operators.jl +++ b/src/operators.jl @@ -1,12 +1,3 @@ -# --- clear --- -function clear!(t::TPS) - mad_tpsa_clear!(t.tpsa) -end - -function clear!(t::ComplexTPS) - mad_ctpsa_clear!(t.tpsa) -end - # --- copy --- function copy!(t::TPS, t1::TPS) mad_tpsa_copy!(t1.tpsa, t.tpsa) From df5e27e5902f188b30a6beecd1f397ef72e8cc36 Mon Sep 17 00:00:00 2001 From: mattsignorelli Date: Tue, 2 Apr 2024 15:45:58 -0400 Subject: [PATCH 08/29] export compose and translate --- src/GTPSA.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/GTPSA.jl b/src/GTPSA.jl index b1c2ce7f..d791d978 100644 --- a/src/GTPSA.jl +++ b/src/GTPSA.jl @@ -103,12 +103,12 @@ export # Methods: evaluate, evaluate!, - compose, + compose, compose!, integ, ∫, integ!, ∫!, deriv, ∂, deriv!, ∂!, getord, getord!, cutord, cutord!, - translate, + translate, translate!, par, scalar, setGTPSA!, From 6756a5d386c90d265c52a5f221175505da924656 Mon Sep 17 00:00:00 2001 From: mattsignorelli Date: Tue, 2 Apr 2024 16:00:32 -0400 Subject: [PATCH 09/29] minor fixes --- docs/src/index.md | 3 +-- docs/src/man/j_slice.md | 4 ++-- src/methods.jl | 6 ++++-- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/docs/src/index.md b/docs/src/index.md index 372392d2..bba1b05c 100644 --- a/docs/src/index.md +++ b/docs/src/index.md @@ -11,8 +11,7 @@ See the [`benchmark/track.jl`](https://github.com/bmad-sim/GTPSA.jl/blob/main/be GTPSA provides several advantages over current Julia AD packages: 1. **Speed**: `GTPSA.jl` is significantly faster than `ForwardDiff.jl` for 2nd-order calculations and above, and has similar performance at 1st-order -2. **Custom Orders in Individual Variables**: Other packages use a single maximum order for all variables. With GTPSA, the -maximum order can be set differently for different variables. For example, computing the Taylor expansion of $f(x_1,x_2)$ to 2nd order in $x_1$ and 6th order in $x_2$ is possible +2. **Custom Orders in Individual Variables**: Other packages use a single maximum order for all variables. With GTPSA, the maximum order can be set differently for different variables. For example, computing the Taylor expansion of $f(x_1,x_2)$ to 2nd order in $x_1$ and 6th order in $x_2$ is possible 3. **Complex Numbers**: GTPSA natively supports complex numbers and allows for mixing of complex and real truncated power series 4. **Distinction Between State Variables and Parameters**: Distinguishing between dependent variables and parameters in the solution of a differential equation expressed as a power series in the dependent variables/parameters can be advantageous in analysis diff --git a/docs/src/man/j_slice.md b/docs/src/man/j_slice.md index 7ca23855..81ecf6e7 100644 --- a/docs/src/man/j_slice.md +++ b/docs/src/man/j_slice.md @@ -24,8 +24,8 @@ h = f[(1=>2, 3=>1, :)] # Colon position is irrelevant in slicing with sparse mo When indexing by monomial index, a colon simply needs to be included after the variable index, or just a colon if a parameter is specified: ```@repl slice -fx1 = f[1,:] -fk1 = f[:,param=2] +fx3 = f[3,:] +fk1 = f[:,param=1] ``` ## `par` diff --git a/src/methods.jl b/src/methods.jl index 5b80be48..19e9aa90 100644 --- a/src/methods.jl +++ b/src/methods.jl @@ -343,18 +343,20 @@ for each TPS in the map (depending on output type), to pass to the low-level C c They are correspondingly referred to as `outx_low`, `m2x_low`, and `m1x_low`. These three temporaries containers can be optionally passed as a tuple in `work_low`, and must satisfy the following requirements: +``` work_low[1] = outx_low # Length >= length(m) = length(m2) work_low[2] = m2x_low # Length >= length(m2) = length(m) work_low[3] = m1x_low # Length >= length(m1) +``` If promotion is occuring, then one of the input vectors must be promoted to `ComplexTPS`. A vector of pre-allocated `ComplexTPS`s can optionally provided as the first argument in the `work_prom` tuple, and has the requirement: If `eltype(m.x) != eltype(m1.x)` (then `m1` must be promoted): -work_prom[1] = m1x_prom # Length >= length(m1), Vector{ComplexTPS} +`work_prom[1] = m1x_prom # Length >= length(m1), Vector{ComplexTPS}` else if `eltype(m.x) != eltype(m2.x)` (then `m2` must be promoted): -work_prom[1] = m2x_prom # Length >= length(m2) = length(m), Vector{ComplexTPS} +`work_prom[1] = m2x_prom # Length >= length(m2) = length(m), Vector{ComplexTPS}` Note that the `ComplexTPS`s in the vectors must be allocated and have the same `Descriptor`. """ From b2239dd9fd8c607197e69468717d9c6ef2b8b9bd Mon Sep 17 00:00:00 2001 From: mattsignorelli <113714234+mattsignorelli@users.noreply.github.com> Date: Tue, 2 Apr 2024 16:04:51 -0400 Subject: [PATCH 10/29] Update Project.toml --- Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Project.toml b/Project.toml index 7a174804..49178759 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ name = "GTPSA" uuid = "b27dd330-f138-47c5-815b-40db9dd9b6e8" authors = ["Matt Signorelli"] -version = "0.4.0" +version = "0.5.0" [deps] GTPSA_jll = "a4739e29-4b97-5c0b-bbcf-46f08034c990" From eca82e32c6ee60546ecd72a3e61f2cb6329c19ea Mon Sep 17 00:00:00 2001 From: mattsignorelli Date: Tue, 2 Apr 2024 16:18:28 -0400 Subject: [PATCH 11/29] add empty getindex --- src/getset.jl | 1 + 1 file changed, 1 insertion(+) diff --git a/src/getset.jl b/src/getset.jl index 29aea9da..111a6013 100644 --- a/src/getset.jl +++ b/src/getset.jl @@ -68,6 +68,7 @@ end # To override Base number.jl getindex(t::Union{ComplexTPS, TPS}, idx::Integer) = lowget(t, idx, nothing, nothing) +getindex(t::Union{ComplexTPS, TPS}) = t # Flat index function lowget(t::Union{TPS,ComplexTPS}, i::Union{Nothing,Integer}, param::Union{Nothing,Integer}, params::Nothing) From 8c65336ccb6d70777231b70671c0d8f643c22c61 Mon Sep 17 00:00:00 2001 From: mattsignorelli Date: Tue, 2 Apr 2024 16:26:18 -0400 Subject: [PATCH 12/29] fixed nothing getset --- src/getset.jl | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/src/getset.jl b/src/getset.jl index 111a6013..da37cea0 100644 --- a/src/getset.jl +++ b/src/getset.jl @@ -16,11 +16,11 @@ end # Flat index function lowset!(t::Union{TPS,ComplexTPS}, v::Number, i::Union{Nothing,Integer}, param::Union{Nothing,Integer}, params::Nothing) - if !xor(isnothing(i), isnothing(param)) + if isnothing(i) && isnothing(param) + return + elseif !isnothing(i) && !isnothing(param) error("Invalid monomial index specified. Please use ONE of variable/parameter index, index by order, or index by sparse monomial.") - end - - if isnothing(param) + elseif isnothing(param) seti!(t.tpsa, Cint(i), (numtype(t))(0), (numtype(t))(v)) else nv = numvars(t) @@ -68,15 +68,14 @@ end # To override Base number.jl getindex(t::Union{ComplexTPS, TPS}, idx::Integer) = lowget(t, idx, nothing, nothing) -getindex(t::Union{ComplexTPS, TPS}) = t # Flat index function lowget(t::Union{TPS,ComplexTPS}, i::Union{Nothing,Integer}, param::Union{Nothing,Integer}, params::Nothing) - if !xor(isnothing(i), isnothing(param)) + if isnothing(i) && isnothing(param) + return t + elseif !isnothing(i) && !isnothing(param) error("Invalid monomial index specified. Please use ONE of variable/parameter index, index by order, or index by sparse monomial.") - end - - if isnothing(param) + elseif isnothing(param) return geti(t.tpsa, Cint(i)) else nv = numvars(t) From a4c9d80aac00dec6e6c7359bd77dbfc6099585fc Mon Sep 17 00:00:00 2001 From: mattsignorelli Date: Wed, 3 Apr 2024 15:19:18 -0400 Subject: [PATCH 13/29] added zeros and ones for allocated TPSs --- docs/src/man/o_all.md | 8 +++++--- src/GTPSA.jl | 2 ++ src/getset.jl | 16 ++++++++-------- src/operators.jl | 23 +++++++++++++++++++++++ 4 files changed, 38 insertions(+), 11 deletions(-) diff --git a/docs/src/man/o_all.md b/docs/src/man/o_all.md index f820cf59..77db353f 100644 --- a/docs/src/man/o_all.md +++ b/docs/src/man/o_all.md @@ -4,11 +4,13 @@ The following functions from Base have been overloaded for operations with `TPS` +, -, *, /, ^, ∘, inv, atan, hypot, abs, sqrt, exp, log, sin, cos, tan, csc, sec, cot, sinc, sinh, cosh, tanh, csch, sech, coth, asin, acos, atan, acsc, asec, acot, asinh, acosh, -atanh, acsch, asech, acoth, zero, one, real, imag, conj, angle, -complex, promote_rule, getindex, setindex!, ==, <, >, <=, >=, -!=, isequal, show, copy! +atanh, acsch, asech, acoth, zero, zeros, one, ones, real, imag, +conj, angle, complex, promote_rule, getindex, setindex!, ==, <, +>, <=, >=, !=, isequal, show, copy! ``` +`zeros` and `ones` are overloaded from Base so that allocated `TPS`/`ComplexTPS`s are placed in each element. If we didn't explicity overload these functions, every element would correspond to the exact same heap-allocated TPS, which is problematic when setting individual monomial coefficients of the same TPS. + `GTPSA.jl` overloads (and exports) the following functions from the corresponding packages: **`LinearAlgebra`**: `norm` **`SpecialFunctions`**: `erf`, `erfc` diff --git a/src/GTPSA.jl b/src/GTPSA.jl index d791d978..079d95b1 100644 --- a/src/GTPSA.jl +++ b/src/GTPSA.jl @@ -40,7 +40,9 @@ import Base: +, asech , acoth , zero , + zeros , one , + ones , real , imag , conj , diff --git a/src/getset.jl b/src/getset.jl index da37cea0..e63bb58f 100644 --- a/src/getset.jl +++ b/src/getset.jl @@ -356,7 +356,7 @@ function gradient(t::Union{TPS,ComplexTPS}; include_params=false) end """ - jacobian!(result::Matrix{<:Union{Float64,ComplexF64}}, m::Vector{<:Union{TPS,ComplexTPS}}; include_params=false) + jacobian!(result::Matrix{<:Union{Float64,ComplexF64}}, m::Union{Vector{<:Union{TPS,ComplexTPS}}, SubArray{<:Union{TPS,ComplexTPS},N,P,I,true}}; include_params=false) where {N,P,I} Extracts the first-order partial derivatives (evaluated at 0) from the Vector of TPSs. and fills the `result` matrix in-place. The partial derivatives wrt the parameters will @@ -371,7 +371,7 @@ in the TPSs. ### Output - `result` -- Preallocated matrix to fill with the Jacobian of `m` """ -function jacobian!(result::Matrix{<:Union{Float64,ComplexF64}}, m::Vector{<:Union{TPS,ComplexTPS}}; include_params=false) +function jacobian!(result::Matrix{<:Union{Float64,ComplexF64}}, m::Union{Vector{<:Union{TPS,ComplexTPS}}, SubArray{<:Union{TPS,ComplexTPS},N,P,I,true}}; include_params=false) where {N,P,I} n = numvars(first(m)) if include_params n += numparams(first(m)) @@ -390,7 +390,7 @@ function jacobian!(result::Matrix{<:Union{Float64,ComplexF64}}, m::Vector{<:Unio end """ - jacobian(m::Vector{<:Union{TPS,ComplexTPS}}; include_params=false) + jacobian(m::Union{Vector{<:Union{TPS,ComplexTPS}}, SubArray{<:Union{TPS,ComplexTPS},N,P,I,true}}; include_params=false) where {N,P,I} Extracts the first-order partial derivatives (evaluated at 0) from the Vector of TPSs. The partial derivatives wrt the parameters will also be extracted when the `include_params` @@ -404,7 +404,7 @@ the first-order monomial coefficients already in the TPSs. ### Output - `J` -- Jacobian of `m` """ -function jacobian(m::Vector{<:Union{TPS,ComplexTPS}}; include_params=false) +function jacobian(m::Union{Vector{<:Union{TPS,ComplexTPS}}, SubArray{<:Union{TPS,ComplexTPS},N,P,I,true}}; include_params=false) where {N,P,I} n = numvars(first(m)) if include_params n += numparams(first(m)) @@ -419,7 +419,7 @@ function jacobian(m::Vector{<:Union{TPS,ComplexTPS}}; include_params=false) end """ - jacobiant!(result::Matrix{<:Union{Float64,ComplexF64}}, m::Vector{<:Union{TPS,ComplexTPS}}; include_params=false) + jacobiant!(result::Matrix{<:Union{Float64,ComplexF64}}, m::Union{Vector{<:Union{TPS,ComplexTPS}}, SubArray{<:Union{TPS,ComplexTPS},N,P,I,true}}; include_params=false) where {N,P,I} Extracts the first-order partial derivatives (evaluated at 0) from the Vector of TPSs, as the transpose of the Jacobian. Because of Julia's column-major indexing vs. C's row-major, @@ -435,7 +435,7 @@ first-order monomial coefficients already in the TPSs and filling `result`. ### Output - `result` -- Preallocated matrix to fill with the transpose of the Jacobian of `m` """ -function jacobiant!(result::Matrix{<:Union{Float64,ComplexF64}}, m::Vector{<:Union{TPS,ComplexTPS}}; include_params=false) +function jacobiant!(result::Matrix{<:Union{Float64,ComplexF64}}, m::Union{Vector{<:Union{TPS,ComplexTPS}}, SubArray{<:Union{TPS,ComplexTPS},N,P,I,true}}; include_params=false) where {N,P,I} n = numvars(first(m)) if include_params n += numparams(first(m)) @@ -449,7 +449,7 @@ function jacobiant!(result::Matrix{<:Union{Float64,ComplexF64}}, m::Vector{<:Uni end """ - jacobiant(m::Vector{<:Union{TPS,ComplexTPS}}; include_params=false) + jacobiant(m::Union{Vector{<:Union{TPS,ComplexTPS}}, SubArray{<:Union{TPS,ComplexTPS},N,P,I,true}}; include_params=false) where {N,P,I} Extracts the first-order partial derivatives (evaluated at 0) from the Vector of TPSs, as the transpose of the Jacobian. Because of Julia's column-major indexing vs. C's row-major, @@ -465,7 +465,7 @@ first-order monomial coefficients already in the TPSs. ### Output - `Jt` -- Transpose of the Jacobian of `m` """ -function jacobiant(m::Vector{<:Union{TPS,ComplexTPS}}; include_params=false) +function jacobiant(m::Union{Vector{<:Union{TPS,ComplexTPS}}, SubArray{<:Union{TPS,ComplexTPS},N,P,I,true}}; include_params=false) where {N,P,I} n = numvars(first(m)) if include_params n += numparams(first(m)) diff --git a/src/operators.jl b/src/operators.jl index 9be7bcd5..35f2db95 100644 --- a/src/operators.jl +++ b/src/operators.jl @@ -29,6 +29,29 @@ function one(ct1::ComplexTPS)::ComplexTPS return ct end +# --- zeros and ones (taken from Base.array.jl) --- +# We overload this because we want each element of the array to be a separate allocated TPS +for (fname, felt) in ((:zeros, :zero), (:ones, :one)) + @eval begin + $fname(::Type{T}, dims::Base.DimOrInd...) where {T<:Union{TPS,ComplexTPS}} = $fname(T, dims) + $fname(::Type{T}, dims::NTuple{N, Union{Integer, Base.OneTo}}) where {T<:Union{TPS,ComplexTPS},N} = $fname(T, map(to_dim, dims)) + function $fname(::Type{T}, dims::NTuple{N, Integer}) where {T<:Union{TPS,ComplexTPS},N} + a = Array{T,N}(undef, dims) + for idx in eachindex(a) + a[idx] = $felt(T) + end + return a + end + function $fname(::Type{T}, dims::Tuple{}) where {T<:Union{TPS,ComplexTPS}} + a = Array{T}(undef) + for idx in eachindex(a) + a[idx] = $felt(T) + end + return a + end + end +end + # --- Unary --- # TPS: function +(t1::TPS)::TPS From e98038575bf7415d64a014f5e9e47d6bd830f0b2 Mon Sep 17 00:00:00 2001 From: mattsignorelli Date: Sat, 6 Apr 2024 10:02:05 -0400 Subject: [PATCH 14/29] fix getv complex --- src/low_level/ctpsa.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/low_level/ctpsa.jl b/src/low_level/ctpsa.jl index ce4cbe47..7969e999 100644 --- a/src/low_level/ctpsa.jl +++ b/src/low_level/ctpsa.jl @@ -1042,7 +1042,7 @@ end """ - mad_ctpsa_getv!(t::Ptr{CTPSA}, i::Cint, n::Cint, v::Vector{ComplexF64}) + mad_ctpsa_getv!(t::Ptr{CTPSA}, i::Cint, n::Cint, v::Union{Ptr{ComplexF64},Vector{ComplexF64}}) Vectorized getter of the coefficients for monomials with indices `i..i+n`. Useful for extracting the 1st order parts of a TPSA to construct a matrix (`i = 1`, `n = nv+np = nn`). @@ -1055,7 +1055,7 @@ a TPSA to construct a matrix (`i = 1`, `n = nv+np = nn`). ### Output - `v` -- Array of coefficients for monomials `i..i+n` """ -function mad_ctpsa_getv!(t::Ptr{CTPSA}, i::Cint, n::Cint, v::Vector{ComplexF64}) +function mad_ctpsa_getv!(t::Ptr{CTPSA}, i::Cint, n::Cint, v::Union{Ptr{ComplexF64},Vector{ComplexF64}}) @ccall MAD_TPSA.mad_ctpsa_getv(t::Ptr{CTPSA}, i::Cint, n::Cint, v::Ptr{ComplexF64})::Cvoid end From f700c617304db04a44b61b7a2daacadb9d49fcc4 Mon Sep 17 00:00:00 2001 From: mattsignorelli Date: Wed, 10 Apr 2024 16:21:03 -0400 Subject: [PATCH 15/29] bump patch --- Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Project.toml b/Project.toml index 49178759..e3bfc6b8 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ name = "GTPSA" uuid = "b27dd330-f138-47c5-815b-40db9dd9b6e8" authors = ["Matt Signorelli"] -version = "0.5.0" +version = "0.5.1" [deps] GTPSA_jll = "a4739e29-4b97-5c0b-bbcf-46f08034c990" From fba8920e2c30d47a91f4a4054362266e6b14222a Mon Sep 17 00:00:00 2001 From: mattsignorelli Date: Tue, 16 Apr 2024 10:05:24 -0400 Subject: [PATCH 16/29] loosened type requirements for grad/jacobian/hessian,fixed bug in jacobiant --- src/getset.jl | 97 +++++++++++++++++++++--------------------- src/low_level/ctpsa.jl | 4 +- src/low_level/rtpsa.jl | 2 +- 3 files changed, 52 insertions(+), 51 deletions(-) diff --git a/src/getset.jl b/src/getset.jl index e63bb58f..ff7806d7 100644 --- a/src/getset.jl +++ b/src/getset.jl @@ -300,11 +300,11 @@ function slice(t1::Union{TPS,ComplexTPS}, par_mono::Vector{Cuchar}, par_it=true) end # --- gradient, jacobian, hessian getters --- -getv!(t::Ptr{RTPSA}, i::Cint, n::Cint, v::Union{Ptr{Cdouble},Vector{Cdouble}}) = (@inline; mad_tpsa_getv!(t, i, n, v)) -getv!(t::Ptr{CTPSA}, i::Cint, n::Cint, v::Union{Ptr{ComplexF64},Vector{ComplexF64}}) = (@inline; mad_ctpsa_getv!(t, i, n, v)) +getv!(t::Ptr{RTPSA}, i::Cint, n::Cint, v) = (@inline; mad_tpsa_getv!(t, i, n, v)) +getv!(t::Ptr{CTPSA}, i::Cint, n::Cint, v) = (@inline; mad_ctpsa_getv!(t, i, n, v)) """ - gradient!(result::Vector{<:Union{Float64,ComplexF64}}, t::Union{TPS,ComplexTPS}; include_params=false) + gradient!(result, t::Union{TPS,ComplexTPS}; include_params=false) Extracts the first-order partial derivatives (evaluated at 0) from the TPS and fills the `result` vector in-place. The partial derivatives wrt the parameters will also be extracted @@ -317,9 +317,10 @@ in the TPS. - `include_params` -- (Optional) Extract partial derivatives wrt parameters. Default is false ### Output -- `result` -- Preallocated `Vector` to fill with the gradient of the TPS +- `result` -- Vector to fill with the gradient of the TPS, must be 1-based indexing """ -function gradient!(result::Vector{<:Union{Float64,ComplexF64}}, t::Union{TPS,ComplexTPS}; include_params=false) +function gradient!(result, t::Union{TPS,ComplexTPS}; include_params=false) + Base.require_one_based_indexing(result) n = numvars(t) if include_params n += numparams(t) @@ -328,6 +329,7 @@ function gradient!(result::Vector{<:Union{Float64,ComplexF64}}, t::Union{TPS,Com error("Incorrect size for result") end getv!(t.tpsa, Cint(1), n, result) + return end """ @@ -356,7 +358,7 @@ function gradient(t::Union{TPS,ComplexTPS}; include_params=false) end """ - jacobian!(result::Matrix{<:Union{Float64,ComplexF64}}, m::Union{Vector{<:Union{TPS,ComplexTPS}}, SubArray{<:Union{TPS,ComplexTPS},N,P,I,true}}; include_params=false) where {N,P,I} + jacobian!(result, m; include_params=false) Extracts the first-order partial derivatives (evaluated at 0) from the Vector of TPSs. and fills the `result` matrix in-place. The partial derivatives wrt the parameters will @@ -365,32 +367,33 @@ is not calculating anything - just extracting the first-order monomial coefficie in the TPSs. ### Input -- `m` -- `Vector` of TPSs. to extract the Jacobian from +- `m` -- Vector of TPSs to extract the Jacobian from, must be 1-based indexing - `include_params` -- (Optional) Extract partial derivatives wrt parameters. Default is false ### Output -- `result` -- Preallocated matrix to fill with the Jacobian of `m` +- `result` -- Matrix to fill with the Jacobian of `m`, must be 1-based indexing """ -function jacobian!(result::Matrix{<:Union{Float64,ComplexF64}}, m::Union{Vector{<:Union{TPS,ComplexTPS}}, SubArray{<:Union{TPS,ComplexTPS},N,P,I,true}}; include_params=false) where {N,P,I} +function jacobian!(result, m; include_params=false) + Base.require_one_based_indexing(result, m) n = numvars(first(m)) if include_params n += numparams(first(m)) end - if size(result)[2] != n + if size(result) != (length(m), n) error("Incorrect size for result") end - grad = Vector{numtype(first(m))}(undef, n) - # This is not fully in-place technically, bc Julia is column-major and - # filling each row in place without allocating temp would require row-major - # So there are allocations for the array grad - for i=1:length(m) - getv!(m[i].tpsa, Cint(1), n, grad) - result[i,:] = grad + + + for i=1:n + for j=1:length(m) + result[j,i] = geti(m[j].tpsa, Cint(i)) + end end + return end """ - jacobian(m::Union{Vector{<:Union{TPS,ComplexTPS}}, SubArray{<:Union{TPS,ComplexTPS},N,P,I,true}}; include_params=false) where {N,P,I} + jacobian(m; include_params=false) Extracts the first-order partial derivatives (evaluated at 0) from the Vector of TPSs. The partial derivatives wrt the parameters will also be extracted when the `include_params` @@ -398,49 +401,46 @@ flag is set to `true`. Note that this function is not calculating anything - jus the first-order monomial coefficients already in the TPSs. ### Input -- `m` -- `Vector` of TPSs. to extract the Jacobian from +- `m` -- Vector of TPSs to extract the Jacobian from, must be 1-based indexing - `include_params` -- (Optional) Extract partial derivatives wrt parameters. Default is false ### Output - `J` -- Jacobian of `m` """ -function jacobian(m::Union{Vector{<:Union{TPS,ComplexTPS}}, SubArray{<:Union{TPS,ComplexTPS},N,P,I,true}}; include_params=false) where {N,P,I} +function jacobian(m; include_params=false) + Base.require_one_based_indexing(m) n = numvars(first(m)) if include_params n += numparams(first(m)) end J = Matrix{numtype(first(m))}(undef, length(m), n) - grad = Vector{numtype(first(m))}(undef, n) - for i=1:length(m) - getv!(m[i].tpsa, Cint(1), n, grad) - J[i,:] = grad - end + jacobian!(J, m; include_params=include_params) return J end """ - jacobiant!(result::Matrix{<:Union{Float64,ComplexF64}}, m::Union{Vector{<:Union{TPS,ComplexTPS}}, SubArray{<:Union{TPS,ComplexTPS},N,P,I,true}}; include_params=false) where {N,P,I} + jacobiant!(result, m; include_params=false) Extracts the first-order partial derivatives (evaluated at 0) from the Vector of TPSs, -as the transpose of the Jacobian. Because of Julia's column-major indexing vs. C's row-major, -this routine will be slightly faster than using `jacobian!` if the transpose of the Jacobian is -needed. The partial derivatives wrt the parameters will also be extracted when the `include_params` -flag is set to `true`. Note that this function is not calculating anything - just extracting the -first-order monomial coefficients already in the TPSs and filling `result`. +as the transpose of the Jacobian. The partial derivatives wrt the parameters will also +be extracted when the `include_params` flag is set to `true`. Note that this function is +not calculating anything - just extracting the first-order monomial coefficients already +in the TPSs and filling `result`. ### Input -- `m` -- `Vector` of TPSs. to extract the Jacobian from +- `m` -- Vector of TPSs to extract the Jacobian from, must be 1-based indexing - `include_params` -- (Optional) Extract partial derivatives wrt parameters. Default is false ### Output -- `result` -- Preallocated matrix to fill with the transpose of the Jacobian of `m` +- `result` -- Matrix to fill with the transpose of the Jacobian of `m`, must be 1-based indexing """ -function jacobiant!(result::Matrix{<:Union{Float64,ComplexF64}}, m::Union{Vector{<:Union{TPS,ComplexTPS}}, SubArray{<:Union{TPS,ComplexTPS},N,P,I,true}}; include_params=false) where {N,P,I} +function jacobiant!(result, m; include_params=false) + Base.require_one_based_indexing(result, m) n = numvars(first(m)) if include_params n += numparams(first(m)) end - if size(result)[2] != n + if size(result) != (n, length(m)) error("Incorrect size for result") end for i=1:length(m) @@ -449,34 +449,34 @@ function jacobiant!(result::Matrix{<:Union{Float64,ComplexF64}}, m::Union{Vector end """ - jacobiant(m::Union{Vector{<:Union{TPS,ComplexTPS}}, SubArray{<:Union{TPS,ComplexTPS},N,P,I,true}}; include_params=false) where {N,P,I} + jacobiant(m; include_params=false) where {N,P,I} Extracts the first-order partial derivatives (evaluated at 0) from the Vector of TPSs, -as the transpose of the Jacobian. Because of Julia's column-major indexing vs. C's row-major, -this routine will be slightly faster than using `jacobian` if the transpose of the Jacobian is -needed. The partial derivatives wrt the parameters will also be extracted when the `include_params` -flag is set to `true`. Note that this function is not calculating anything - just extracting the -first-order monomial coefficients already in the TPSs. +as the transpose of the Jacobian. The partial derivatives wrt the parameters will also +be extracted when the `include_params` flag is set to `true`. Note that this function is +not calculating anything - just extracting the first-order monomial coefficients already +in the TPSs. ### Input -- `m` -- `Vector` of TPSs. to extract the Jacobian from +- `m` --`Vector of TPSs to extract the Jacobian from, must be 1-based indexing - `include_params` -- (Optional) Extract partial derivatives wrt parameters. Default is false ### Output - `Jt` -- Transpose of the Jacobian of `m` """ -function jacobiant(m::Union{Vector{<:Union{TPS,ComplexTPS}}, SubArray{<:Union{TPS,ComplexTPS},N,P,I,true}}; include_params=false) where {N,P,I} +function jacobiant(m; include_params=false) + Base.require_one_based_indexing(m) n = numvars(first(m)) if include_params n += numparams(first(m)) end - result = Matrix{numtype(first(m))}(undef, length(m), n) + result = Matrix{numtype(first(m))}(undef, n, length(m)) jacobiant!(result, m, include_params=include_params) return result end """ - hessian!(result::Matrix{<:Union{Float64,ComplexF64}},t::Union{TPS,ComplexTPS}; include_params=false) + hessian!(result,t::Union{TPS,ComplexTPS}; include_params=false) Extracts the second-order partial derivatives (evaluated at 0) from the TPS and fills the `result` matrix in-place. The partial derivatives wrt the parameters will @@ -489,9 +489,10 @@ in the TPS. - `include_params` -- (Optional) Extract partial derivatives wrt parameters. Default is false ### Output -- `result` -- Preallocated matrix to fill with the Hessian of the TPS +- `result` -- Matrix to fill with the Hessian of the TPS, must be 1-based indexing """ -function hessian!(result::Matrix{<:Union{Float64,ComplexF64}},t::Union{TPS,ComplexTPS}; include_params=false) +function hessian!(result,t::Union{TPS,ComplexTPS}; include_params=false) + Base.require_one_based_indexing(result) d = Base.unsafe_convert(Ptr{Desc}, unsafe_load(t.tpsa).d) desc = unsafe_load(d) n = desc.nv @@ -507,7 +508,7 @@ function hessian!(result::Matrix{<:Union{Float64,ComplexF64}},t::Union{TPS,Compl error("Hessian undefined for TPSA with at least one variable/parameter of order < 2") end end - result[:] .= 0. + result .= 0. idx = Cint(desc.nv+desc.np) maxidx = Cint(floor(n*(n+1)/2))+n v = Ref{numtype(t)}() diff --git a/src/low_level/ctpsa.jl b/src/low_level/ctpsa.jl index 7969e999..604cf0e7 100644 --- a/src/low_level/ctpsa.jl +++ b/src/low_level/ctpsa.jl @@ -1042,7 +1042,7 @@ end """ - mad_ctpsa_getv!(t::Ptr{CTPSA}, i::Cint, n::Cint, v::Union{Ptr{ComplexF64},Vector{ComplexF64}}) + mad_ctpsa_getv!(t::Ptr{CTPSA}, i::Cint, n::Cint, v) Vectorized getter of the coefficients for monomials with indices `i..i+n`. Useful for extracting the 1st order parts of a TPSA to construct a matrix (`i = 1`, `n = nv+np = nn`). @@ -1055,7 +1055,7 @@ a TPSA to construct a matrix (`i = 1`, `n = nv+np = nn`). ### Output - `v` -- Array of coefficients for monomials `i..i+n` """ -function mad_ctpsa_getv!(t::Ptr{CTPSA}, i::Cint, n::Cint, v::Union{Ptr{ComplexF64},Vector{ComplexF64}}) +function mad_ctpsa_getv!(t::Ptr{CTPSA}, i::Cint, n::Cint, v) @ccall MAD_TPSA.mad_ctpsa_getv(t::Ptr{CTPSA}, i::Cint, n::Cint, v::Ptr{ComplexF64})::Cvoid end diff --git a/src/low_level/rtpsa.jl b/src/low_level/rtpsa.jl index ae67ce45..11182a74 100644 --- a/src/low_level/rtpsa.jl +++ b/src/low_level/rtpsa.jl @@ -676,7 +676,7 @@ end """ - mad_tpsa_getv!(t::Ptr{RTPSA}, i::Cint, n::Cint, v::Vector{Cdouble}) + mad_tpsa_getv!(t::Ptr{RTPSA}, i::Cint, n::Cint, v) Vectorized getter of the coefficients for monomials with indices `i..i+n`. Useful for extracting the 1st order parts of a TPSA to construct a matrix (`i = 1`, `n = nv+np = nn`). From 5e5f235e99a490005611b7a22474d6fb9c7ab7ab Mon Sep 17 00:00:00 2001 From: mattsignorelli Date: Thu, 18 Apr 2024 14:30:56 -0400 Subject: [PATCH 17/29] clean up of basic operators, added in-place add,sub,mul,div --- docs/src/man/o_all.md | 4 +- src/GTPSA.jl | 6 +- src/operators.jl | 301 +++++++++++++----------------------------- src/utils.jl | 6 +- 4 files changed, 99 insertions(+), 218 deletions(-) diff --git a/docs/src/man/o_all.md b/docs/src/man/o_all.md index 77db353f..bd7fc9d8 100644 --- a/docs/src/man/o_all.md +++ b/docs/src/man/o_all.md @@ -12,12 +12,12 @@ conj, angle, complex, promote_rule, getindex, setindex!, ==, <, `zeros` and `ones` are overloaded from Base so that allocated `TPS`/`ComplexTPS`s are placed in each element. If we didn't explicity overload these functions, every element would correspond to the exact same heap-allocated TPS, which is problematic when setting individual monomial coefficients of the same TPS. `GTPSA.jl` overloads (and exports) the following functions from the corresponding packages: - **`LinearAlgebra`**: `norm` + **`LinearAlgebra`**: `norm`, `mul!` **`SpecialFunctions`**: `erf`, `erfc` `GTPSA.jl` also provides the following functions NOT included in Base or any of the above packages: ``` -unit, sinhc, asinc, asinhc, polar, rect +add!, sub!, div!, unit, sinhc, asinc, asinhc, polar, rect ``` If there is a mathematical function in Base which you'd like and is not included in the above list, feel free to submit an [issue](https://github.com/bmad-sim/GTPSA.jl/issues). \ No newline at end of file diff --git a/src/GTPSA.jl b/src/GTPSA.jl index 079d95b1..0c5fcb5e 100644 --- a/src/GTPSA.jl +++ b/src/GTPSA.jl @@ -62,7 +62,7 @@ import Base: +, show, copy! -import LinearAlgebra: norm +import LinearAlgebra: norm, mul! import SpecialFunctions: erf, erfc using GTPSA_jll, Printf, PrettyTables @@ -83,6 +83,10 @@ export rect, clear!, complex!, + add!, + sub!, + mul!, + div!, # Monomial as TPS creators: vars, diff --git a/src/operators.jl b/src/operators.jl index 35f2db95..cd64a228 100644 --- a/src/operators.jl +++ b/src/operators.jl @@ -3,6 +3,10 @@ function copy!(t::TPS, t1::TPS) mad_tpsa_copy!(t1.tpsa, t.tpsa) end +function copy!(ct::ComplexTPS, t1::TPS) + mad_ctpsa_cplx!(t1.tpsa, Base.unsafe_convert(Ptr{RTPSA}, C_NULL), ct.tpsa) +end + function copy!(ct::ComplexTPS, ct1::ComplexTPS) mad_ctpsa_copy!(ct1.tpsa, ct.tpsa) end @@ -249,255 +253,128 @@ function isequal(t1::TPS, ct1::ComplexTPS)::Bool return isequal(ct1, t1) end - # --- add --- -# TPS: -function +(t1::TPS, t2::TPS)::TPS - t = zero(t1) - mad_tpsa_add!(t1.tpsa, t2.tpsa, t.tpsa) - return t -end +# TPS, TPS: +add!(a::Ptr{RTPSA}, b::Ptr{RTPSA}, c::Ptr{RTPSA}) = mad_tpsa_add!(a, b, c) +add!(a::Ptr{CTPSA}, b::Ptr{CTPSA}, c::Ptr{CTPSA}) = mad_ctpsa_add!(a, b, c) +add!(a::Ptr{RTPSA}, b::Ptr{CTPSA}, c::Ptr{CTPSA}) = mad_ctpsa_addt!(b, a, c) +add!(a::Ptr{CTPSA}, b::Ptr{RTPSA}, c::Ptr{CTPSA}) = mad_ctpsa_addt!(a, b, c) -function +(t1::TPS, a::Real)::TPS - t = TPS(t1) - mad_tpsa_set0!(t.tpsa, 1., convert(Float64,a)) - return t -end - -function +(a::Real, t1::TPS)::TPS - return t1 + a -end - -# ComplexTPS: -function +(ct1::ComplexTPS, ct2::ComplexTPS)::ComplexTPS - ct = zero(ct1) - mad_ctpsa_add!(ct1.tpsa, ct2.tpsa, ct.tpsa) - return ct -end +add!(t::Union{TPS,ComplexTPS}, t1::Union{TPS,ComplexTPS}, t2::Union{TPS,ComplexTPS}) = add!(t1.tpsa, t2.tpsa, t.tpsa) -function +(ct1::ComplexTPS, a::Number)::ComplexTPS - ct = ComplexTPS(ct1) - mad_ctpsa_set0!(ct.tpsa, convert(ComplexF64, 1), convert(ComplexF64, a)) - return ct -end +# TPS, scalar: +set0!(t::Ptr{RTPSA}, a::Float64, b::Float64) = mad_tpsa_set0!(t, a, b) +set0!(t::Ptr{CTPSA}, a::ComplexF64, b::ComplexF64) = mad_ctpsa_set0!(t, a, b) -function +(a::Number, ct1::ComplexTPS)::ComplexTPS - return ct1 + a +function add!(t::Union{TPS,ComplexTPS}, t1::Union{TPS,ComplexTPS}, a::Number) + copy!(t, t1) + set0!(t.tpsa, convert(numtype(t), 1), convert(numtype(t), a)) end -# TPS to ComplexTPS promotion, w/o creating temp ComplexTPS: -function +(ct1::ComplexTPS, t1::TPS)::ComplexTPS - ct = zero(ct1) - mad_ctpsa_addt!(ct1.tpsa, t1.tpsa, ct.tpsa) - return ct -end +add!(t::Union{TPS,ComplexTPS}, a::Number, t1::Union{TPS,ComplexTPS}) = add!(t, t1, a) -function +(t1::TPS, ct1::ComplexTPS)::ComplexTPS - return ct1 + t1 +for t = ((TPS,TPS),(TPS,Real),(Real,TPS),(TPS,Complex),(Complex,TPS),(ComplexTPS,TPS),(TPS,ComplexTPS),(ComplexTPS,ComplexTPS),(ComplexTPS, Number), (Number, ComplexTPS)) +@eval begin +function +(t1::$t[1], t2::$t[2]) + use = $(t[1] == TPS || t[1] == ComplexTPS ? :t1 : :t2) + t = (promote_type(typeof(t1),typeof(t2)))(use=use) + add!(t, t1, t2) + return t end - -function +(t1::TPS, a::Complex)::ComplexTPS - ct = ComplexTPS(t1) - mad_ctpsa_set0!(ct.tpsa, convert(ComplexF64, 1), convert(ComplexF64, a)) - return ct end - -function +(a::Complex, t1::TPS)::ComplexTPS - return t1 + a end # --- sub --- -# TPS: -function -(t1::TPS, t2::TPS)::TPS - t = zero(t1) - mad_tpsa_sub!(t1.tpsa, t2.tpsa, t.tpsa) - return t -end - +# TPS, TPS: +sub!(a::Ptr{RTPSA}, b::Ptr{RTPSA}, c::Ptr{RTPSA}) = mad_tpsa_sub!(a, b, c) +sub!(a::Ptr{CTPSA}, b::Ptr{CTPSA}, c::Ptr{CTPSA}) = mad_ctpsa_sub!(a, b, c) +sub!(a::Ptr{CTPSA}, b::Ptr{RTPSA}, c::Ptr{CTPSA}) = mad_ctpsa_subt!(a, b, c) +sub!(a::Ptr{RTPSA}, b::Ptr{CTPSA}, c::Ptr{CTPSA}) = mad_ctpsa_tsub!(a, b, c) -function -(t1::TPS, a::Real)::TPS - t = TPS(t1) - mad_tpsa_set0!(t.tpsa, 1., convert(Float64, -a)) - return t -end +sub!(t::Union{TPS,ComplexTPS}, t1::Union{TPS,ComplexTPS}, t2::Union{TPS,ComplexTPS}) = sub!(t1.tpsa, t2.tpsa, t.tpsa) -function -(a::Real, t1::TPS)::TPS - t = zero(t1) - mad_tpsa_scl!(t1.tpsa, -1., t.tpsa) - mad_tpsa_set0!(t.tpsa, 1., convert(Float64, a)) - return t +# TPS, scalar: +scl!(a::Ptr{RTPSA}, v::Float64, c::Ptr{RTPSA}) = mad_tpsa_scl!(a, v, c) +scl!(a::Ptr{CTPSA}, v::ComplexF64, c::Ptr{CTPSA}) = mad_ctpsa_scl!(a, v, c) +function scl!(a::Ptr{RTPSA}, v::ComplexF64, c::Ptr{CTPSA}) + mad_ctpsa_cplx!(a, Base.unsafe_convert(Ptr{RTPSA},C_NULL), c) + scl!(c, v, c) end -# ComplexTPS: -function -(ct1::ComplexTPS, ct2::ComplexTPS)::ComplexTPS - ct = zero(ct1) - mad_ctpsa_sub!(ct1.tpsa, ct2.tpsa, ct.tpsa) - return ct -end - -function -(ct1::ComplexTPS, a::Number)::ComplexTPS - ct = ComplexTPS(ct1) - mad_ctpsa_set0!(ct.tpsa, convert(ComplexF64, 1), convert(ComplexF64, -a)) - return ct -end - -function -(a::Number, ct1::ComplexTPS)::ComplexTPS - ct = zero(ct1) - mad_ctpsa_scl!(ct1.tpsa, convert(ComplexF64, -1), ct.tpsa) - mad_ctpsa_set0!(ct.tpsa, convert(ComplexF64, 1), convert(ComplexF64,a)) - return ct -end +sub!(t::Union{TPS,ComplexTPS}, t1::Union{TPS,ComplexTPS}, a::Number) = add!(t, t1, -a) -# TPS to ComplexTPS promotion, w/o creating temp ComplexTPS: -function -(ct1::ComplexTPS, t1::TPS)::ComplexTPS - ct = zero(ct1) - mad_ctpsa_subt!(ct1.tpsa, t1.tpsa, ct.tpsa) - return ct +function sub!(t::Union{TPS,ComplexTPS}, a::Number, t1::Union{TPS,ComplexTPS}) + scl!(t1.tpsa, convert(numtype(t), -1.), t.tpsa) + set0!(t.tpsa, convert(numtype(t), 1.), convert(numtype(t), a)) end -function -(t1::TPS, ct1::ComplexTPS)::ComplexTPS - ct = zero(ct1) - mad_ctpsa_tsub!(t1.tpsa, ct1.tpsa, ct.tpsa) - return ct +for t = ((TPS,TPS),(TPS,Real),(Real,TPS),(TPS,Complex),(Complex,TPS),(ComplexTPS,TPS),(TPS,ComplexTPS),(ComplexTPS,ComplexTPS),(ComplexTPS, Number), (Number, ComplexTPS)) +@eval begin +function -(t1::$t[1], t2::$t[2]) + use = $(t[1] == TPS || t[1] == ComplexTPS ? :t1 : :t2) + t = (promote_type(typeof(t1),typeof(t2)))(use=use) + sub!(t, t1, t2) + return t end - -function -(t1::TPS, a::Complex)::ComplexTPS - ct = ComplexTPS(t1) - mad_ctpsa_set0!(ct.tpsa, convert(ComplexF64, 1), convert(ComplexF64, -a)) - return ct end - -function -(a::Complex, t1::TPS)::ComplexTPS - ct = ComplexTPS(t1) - mad_ctpsa_scl!(ct.tpsa, convert(ComplexF64, -1), ct.tpsa) - mad_ctpsa_set0!(ct.tpsa, convert(ComplexF64, 1), convert(ComplexF64,a)) - return ct end - # --- mul --- -# TPS: -function *(t1::TPS, t2::TPS)::TPS - t = zero(t1) - mad_tpsa_mul!(t1.tpsa, t2.tpsa, t.tpsa) +# TPS, TPS: +mul!(a::Ptr{RTPSA}, b::Ptr{RTPSA}, c::Ptr{RTPSA}) = mad_tpsa_mul!(a, b, c) +mul!(a::Ptr{CTPSA}, b::Ptr{CTPSA}, c::Ptr{CTPSA}) = mad_ctpsa_mul!(a, b, c) +mul!(a::Ptr{RTPSA}, b::Ptr{CTPSA}, c::Ptr{CTPSA}) = mad_ctpsa_mult!(b, a, c) +mul!(a::Ptr{CTPSA}, b::Ptr{RTPSA}, c::Ptr{CTPSA}) = mad_ctpsa_mult!(a, b, c) + +mul!(t::Union{TPS,ComplexTPS}, t1::Union{TPS,ComplexTPS}, t2::Union{TPS,ComplexTPS}) = mul!(t1.tpsa, t2.tpsa, t.tpsa) + +# TPS, scalar: +mul!(t::Union{TPS,ComplexTPS}, t1::Union{TPS,ComplexTPS}, a::Number) = scl!(t1.tpsa, convert(numtype(t), a), t.tpsa) +mul!(t::Union{TPS,ComplexTPS}, a::Number, t1::Union{TPS,ComplexTPS}) = mul!(t, t1, a) + +for t = ((TPS,TPS),(TPS,Real),(Real,TPS),(TPS,Complex),(Complex,TPS),(ComplexTPS,TPS),(TPS,ComplexTPS),(ComplexTPS,ComplexTPS),(ComplexTPS, Number), (Number, ComplexTPS)) +@eval begin +function *(t1::$t[1], t2::$t[2]) + use = $(t[1] == TPS || t[1] == ComplexTPS ? :t1 : :t2) + t = (promote_type(typeof(t1),typeof(t2)))(use=use) + mul!(t, t1, t2) return t end - -function *(t1::TPS, a::Real)::TPS - t = zero(t1) - mad_tpsa_scl!(t1.tpsa, convert(Float64, a), t.tpsa) - return t -end - -function *(a::Real, t1::TPS)::TPS - return t1 * a -end - -# ComplexTPS: -function *(ct1::ComplexTPS, ct2::ComplexTPS)::ComplexTPS - ct = zero(ct1) - mad_ctpsa_mul!(ct1.tpsa, ct2.tpsa, ct.tpsa) - return ct -end - -function *(ct1::ComplexTPS, a::Number)::ComplexTPS - ct = zero(ct1) - mad_ctpsa_scl!(ct1.tpsa, convert(ComplexF64,a), ct.tpsa) - return ct -end - -function *(a::Number, ct1::ComplexTPS)::ComplexTPS - return ct1 * a -end - -# TPS to ComplexTPS promotion, w/o creating temp ComplexTPS: -function *(ct1::ComplexTPS, t1::TPS)::ComplexTPS - ct = zero(ct1) - mad_ctpsa_mult!(ct1.tpsa, t1.tpsa, ct.tpsa) - return ct end - -function *(t1::TPS, ct1::ComplexTPS)::ComplexTPS - return ct1 * t1 -end - -function *(t1::TPS, a::Complex)::ComplexTPS - ct = ComplexTPS(t1) - mad_ctpsa_scl!(ct.tpsa, convert(ComplexF64,a), ct.tpsa) - return ct -end - -function *(a::Complex, t1::TPS)::ComplexTPS - return t1 * a end # --- div --- -# TPS: -function /(t1::TPS, t2::TPS)::TPS - t = zero(t1) - mad_tpsa_div!(t1.tpsa, t2.tpsa, t.tpsa) +div!(a::Ptr{RTPSA}, b::Ptr{RTPSA}, c::Ptr{RTPSA}) = mad_tpsa_div!(a, b, c) +div!(a::Ptr{CTPSA}, b::Ptr{CTPSA}, c::Ptr{CTPSA}) = mad_ctpsa_div!(a, b, c) +div!(a::Ptr{CTPSA}, b::Ptr{RTPSA}, c::Ptr{CTPSA}) = mad_ctpsa_divt!(a, b, c) +div!(a::Ptr{RTPSA}, b::Ptr{CTPSA}, c::Ptr{CTPSA}) = mad_ctpsa_tdiv!(a, b, c) + +div!(t::Union{TPS,ComplexTPS}, t1::Union{TPS,ComplexTPS}, t2::Union{TPS,ComplexTPS}) = div!(t1.tpsa, t2.tpsa, t.tpsa) + +# TPS, scalar: +inv!(a::Ptr{RTPSA}, v::Float64, c::Ptr{RTPSA}) = mad_tpsa_inv!(a, v, c) +inv!(a::Ptr{CTPSA}, v::ComplexF64, c::Ptr{CTPSA}) = mad_ctpsa_inv!(a, v, c) +function inv!(a::Ptr{RTPSA}, v::ComplexF64, c::Ptr{CTPSA}) + mad_ctpsa_cplx!(a, Base.unsafe_convert(Ptr{RTPSA}, C_NULL), c) + inv!(c, v, c) +end + +div!(t::Union{TPS,ComplexTPS}, t1::Union{TPS,ComplexTPS}, a::Number) = mul!(t, t1, 1/a) +div!(t::Union{TPS,ComplexTPS}, a::Number, t1::Union{TPS,ComplexTPS}) = inv!(t1.tpsa, convert(numtype(t), a), t.tpsa) + +for t = ((TPS,TPS),(TPS,Real),(Real,TPS),(TPS,Complex),(Complex,TPS),(ComplexTPS,TPS),(TPS,ComplexTPS),(ComplexTPS,ComplexTPS),(ComplexTPS, Number), (Number, ComplexTPS)) +@eval begin +function /(t1::$t[1], t2::$t[2]) + use = $(t[1] == TPS || t[1] == ComplexTPS ? :t1 : :t2) + t = (promote_type(typeof(t1),typeof(t2)))(use=use) + div!(t, t1, t2) return t end - -function /(t1::TPS, a::Real)::TPS - t = zero(t1) - mad_tpsa_scl!(t1.tpsa, convert(Float64, 1/a), t.tpsa) - return t end - -function /(a::Real, t1::TPS)::TPS - t = zero(t1) - mad_tpsa_inv!(t1.tpsa, convert(Float64,a), t.tpsa) - return t end -# ComplexTPS: -function /(ct1::ComplexTPS, ct2::ComplexTPS)::ComplexTPS - ct = zero(ct1) - mad_ctpsa_div!(ct1.tpsa, ct2.tpsa, ct.tpsa) - return ct -end - -function /(ct1::ComplexTPS, a::Number)::ComplexTPS - ct = zero(ct1) - mad_ctpsa_scl!(ct1.tpsa, convert(ComplexF64, 1/a), ct.tpsa) - return ct -end - -function /(a::Number, ct1::ComplexTPS)::ComplexTPS - ct = zero(ct1) - mad_ctpsa_inv!(ct1.tpsa, convert(ComplexF64, a), ct.tpsa) - return ct -end - -# TPS to ComplexTPS promotion, w/o creating temp ComplexTPS: -function /(ct1::ComplexTPS, t1::TPS)::ComplexTPS - ct = zero(ct1) - mad_ctpsa_divt!(ct1.tpsa, t1.tpsa, ct.tpsa) - return ct -end - -function /(t1::TPS, ct1::ComplexTPS)::ComplexTPS - ct = zero(ct1) - mad_ctpsa_tdiv!(t1.tpsa, ct1.tpsa, ct.tpsa) - return ct -end - -function /(t1::TPS, a::Complex)::ComplexTPS - ct = ComplexTPS(t1) - mad_ctpsa_scl!(ct.tpsa, convert(ComplexF64, 1/a), ct.tpsa) - return ct -end - -function /(a::Complex, t1::TPS)::ComplexTPS - ct = ComplexTPS(t1) - mad_ctpsa_inv!(ct.tpsa, convert(ComplexF64, a), ct.tpsa) - return ct -end - - # --- pow --- # TPS: function ^(t1::TPS, t2::TPS)::TPS diff --git a/src/utils.jl b/src/utils.jl index 9f8b76cc..5d556edb 100644 --- a/src/utils.jl +++ b/src/utils.jl @@ -133,9 +133,9 @@ Complex{TPS}(t1::TPS, t2::TPS) = error("ComplexTPS can only be defined as an Abs Complex{TPS}(t1::TPS, a::Real) = error("ComplexTPS can only be defined as an AbstractComplex type (to be implemented in Julia PR #35587). If this error was reached without explicitly attempting to create a Complex{TPS}, please submit an issue to GTPSA.jl with an example.") Complex{TPS}(a::Real, t1::TPS) = error("ComplexTPS can only be defined as an AbstractComplex type (to be implemented in Julia PR #35587). If this error was reached without explicitly attempting to create a Complex{TPS}, please submit an issue to GTPSA.jl with an example.") -promote_rule(::Type{TPS}, ::Union{Type{<:AbstractFloat}, Type{<:Integer}, Type{<:Rational}, Type{<:AbstractIrrational}}) = TPS -promote_rule(::Type{ComplexTPS}, ::Union{Type{Complex{<:Real}},Type{<:AbstractFloat}, Type{<:Integer}, Type{<:Rational}, Type{<:AbstractIrrational}}) = ComplexTPS -promote_rule(::Type{TPS}, ::Union{Type{ComplexTPS}, Type{Complex{<:Real}}}) = ComplexTPS +promote_rule(::Type{TPS}, ::Type{T}) where {T<:Real} = TPS #::Union{Type{<:AbstractFloat}, Type{<:Integer}, Type{<:Rational}, Type{<:AbstractIrrational}}) = TPS +promote_rule(::Type{ComplexTPS}, ::Type{T}) where {T<:Number} = ComplexTPS #::Union{Type{Complex{<:Real}},Type{<:AbstractFloat}, Type{<:Integer}, Type{<:Rational}, Type{<:AbstractIrrational}}) = ComplexTPS +promote_rule(::Type{TPS}, ::Type{T}) where {T<:Number}= ComplexTPS # Handle bool which is special for some reason +(t::TPS, z::Complex{Bool}) = t + Complex{Int}(z) From 362a520560a3fa9b96dec4da0716451b971dbae6 Mon Sep 17 00:00:00 2001 From: mattsignorelli <113714234+mattsignorelli@users.noreply.github.com> Date: Mon, 22 Apr 2024 08:42:08 -0400 Subject: [PATCH 18/29] Update compare_MAD.jl --- test/compare_MAD.jl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/compare_MAD.jl b/test/compare_MAD.jl index d88fbf4f..d7766c43 100644 --- a/test/compare_MAD.jl +++ b/test/compare_MAD.jl @@ -320,7 +320,7 @@ function compare_MAD() io = IOBuffer() try - Downloads.download("https://raw.githubusercontent.com/mattsignorelli/gtpsa/main/code/mad_mono.h", io) + Downloads.download("https://raw.githubusercontent.com/mattsignorelli/gtpsa/dev-tpsa-newlazy/code/mad_mono.h", io) println(io_out, "mad_mono.h downloaded.") catch e println(io_out, "Error downloading mad_mono.h") @@ -337,7 +337,7 @@ function compare_MAD() try - Downloads.download("https://raw.githubusercontent.com/mattsignorelli/gtpsa/main/code/mad_desc.h", io) + Downloads.download("https://raw.githubusercontent.com/mattsignorelli/gtpsa/dev-tpsa-newlazy/code/mad_desc.h", io) println(io_out, "mad_desc.h downloaded.") catch e println(io_out, "Error downloading mad_desc.h") @@ -354,7 +354,7 @@ function compare_MAD() try - Downloads.download("https://raw.githubusercontent.com/mattsignorelli/gtpsa/main/code/mad_tpsa.h", io) + Downloads.download("https://raw.githubusercontent.com/mattsignorelli/gtpsa/dev-tpsa-newlazy/code/mad_tpsa.h", io) println(io_out, "mad_tpsa.h downloaded.") catch e println(io_out, "Error downloading mad_tpsa.h") @@ -370,7 +370,7 @@ function compare_MAD() compare(fun_decs_c, fun_decs_jl) try - Downloads.download("https://raw.githubusercontent.com/mattsignorelli/gtpsa/main/code/mad_ctpsa.h", io) + Downloads.download("https://raw.githubusercontent.com/mattsignorelli/gtpsa/dev-tpsa-newlazy/code/mad_ctpsa.h", io) println(io_out, "mad_ctpsa.h downloaded.") catch e println(io_out, "Error downloading mad_ctpsa.h") From 5975751b4170a74e0468702cda02655e7422d0af Mon Sep 17 00:00:00 2001 From: Matt Signorelli Date: Mon, 22 Apr 2024 10:16:55 -0400 Subject: [PATCH 19/29] sneaky compare_MAD bug fixed --- test/compare_MAD.jl | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/test/compare_MAD.jl b/test/compare_MAD.jl index d7766c43..ef8e3b87 100644 --- a/test/compare_MAD.jl +++ b/test/compare_MAD.jl @@ -39,7 +39,7 @@ function compare(fun_decs_c, fun_decs_jl) names_jl = [x.name for x in funs_jl] #println.(names_jl) used = BitArray(undef, length(names_jl)) - + used .= 0 for fun_c in funs_c # println(io_out, "Checking $(fun_c.name)") if isempty(findall(x->x==fun_c.name, names_jl)) @@ -168,7 +168,11 @@ function get_c_fun_info(fun) continue end end - + + if isnothing(findfirst(" ", fun[1:curVarEnd])) + fun = strip(fun[curVarEnd+1:end]) + continue + end # Pointers in type will be added after parsing variable name type = fun[1:findfirst(" ", fun[1:curVarEnd])[1]-1] From 06dbc9710be4822ee8975df95e3c43b6ffc067cc Mon Sep 17 00:00:00 2001 From: Matt Signorelli Date: Mon, 22 Apr 2024 10:53:16 -0400 Subject: [PATCH 20/29] low-level agrees --- src/low_level/ctpsa.jl | 148 +++++++++++++---------------------------- src/low_level/desc.jl | 29 +++----- src/low_level/mono.jl | 11 +++ src/low_level/rtpsa.jl | 133 ++++++++++++++++++------------------ 4 files changed, 133 insertions(+), 188 deletions(-) diff --git a/src/low_level/ctpsa.jl b/src/low_level/ctpsa.jl index d333fa74..842f3fa5 100644 --- a/src/low_level/ctpsa.jl +++ b/src/low_level/ctpsa.jl @@ -3,25 +3,24 @@ This is a 1-to-1 struct for the C definition `ctpsa` (complex TPSA) in GTPSA. -### Fields -- `d::Ptr{Cvoid}` -- Pointer to `Desc` for this `CTPSA` -- `uid::Cint` -- Special user field for external use (and padding) -- `mo::Cuchar` -- max ord (allocated) +- `d::Ptr{Cvoid}` -- Ptr to tpsa descriptor - `lo::Cuchar` -- lowest used ord - `hi::Cuchar` -- highest used ord -- `nz::Culonglong` -- zero/nonzero homogenous polynomials. Note: Int64 if 64 bit compiled C code, else 32 bit -- `nam::NTuple{NAMSZ,Cuchar}` -- tpsa name max string length 16 NAMSZ +- `mo::Cuchar` -- max ord +- `ao::Cuchar` -- allocated order +- `uid::Cint` -- Special user field for external use (and padding) +- `nam::NTuple{NAMSZ,Cuchar}` -- ctpsa name max string length 15 chars NAMSZ - `coef::Ptr{ComplexF64}` -- warning: must be identical to ctpsa up to coef excluded """ struct CTPSA - d::Ptr{Cvoid} - uid::Cint - mo::Cuchar - lo::Cuchar - hi::Cuchar - nz::Culonglong - nam::NTuple{NAMSZ,Cuchar} - coef::Ptr{ComplexF64} + d::Ptr{Cvoid} + lo::Cuchar + hi::Cuchar + mo::Cuchar + ao::Cuchar + uid::Cint + nam::NTuple{NAMSZ,Cuchar} + coef::Ptr{ComplexF64} end """ @@ -127,6 +126,17 @@ function mad_ctpsa_len(t::Ptr{CTPSA})::Cint return ret end +""" + mad_ctpsa_mo!(t::Ptr{CTPSA}, mo_::Cuchar)::Cuchar + +??? + +""" +function mad_ctpsa_mo!(t::Ptr{CTPSA}, mo_::Cuchar)::Cuchar + ret = @ccall MAD_TPSA.mad_ctpsa_mo(t::Ptr{CTPSA}, mo_::Cuchar)::Cuchar + return ret +end + """ mad_ctpsa_nam(t::Ptr{CTPSA}, nam_::Cstring)::Cstring @@ -378,12 +388,12 @@ function mad_ctpsa_setval!(t::Ptr{CTPSA}, v::ComplexF64) end """ - mad_ctpsa_update!(t::Ptr{CTPSA}, eps_::Cdouble) + mad_ctpsa_update!(t::Ptr{CTPSA}) ??? """ -function mad_ctpsa_update!(t::Ptr{CTPSA}, eps_::Cdouble) - ret = @ccall MAD_TPSA.mad_ctpsa_update(t::Ptr{CTPSA}, eps_::Cdouble)::Bool +function mad_ctpsa_update!(t::Ptr{CTPSA}) + @ccall MAD_TPSA.mad_ctpsa_update(t::Ptr{CTPSA})::Cvoid end """ @@ -664,23 +674,6 @@ function mad_ctpsa_cycle!(t::Ptr{CTPSA}, i::Cint, n::Cint, m_::Vector{Cuchar}, v end -""" - mad_ctpsa_get0(t::Ptr{CTPSA})::ComplexF64 - -Gets the 0th order (scalar) value of the TPSA - -### Input -- `t` -- TPSA - -### Output -- `ret` -- Scalar value of TPSA -""" -function mad_ctpsa_get0(t::Ptr{CTPSA})::ComplexF64 - ret = @ccall MAD_TPSA.mad_ctpsa_get0(t::Ptr{CTPSA})::ComplexF64 - return ret -end - - """ mad_ctpsa_geti(t::Ptr{CTPSA}, i::Cint)::ComplexF64 @@ -756,21 +749,6 @@ function mad_ctpsa_getsm(t::Ptr{CTPSA}, n::Cint, m::Vector{Cint})::ComplexF64 end -""" - mad_ctpsa_set0!(t::Ptr{CTPSA}, a::ComplexF64, b::ComplexF64) - -Sets the 0th order coefficient (scalar part of TPSA) according to `coef[0] = a*coef[0] + b`. Does not modify other values in TPSA. - -### Input -- `t` -- TPSA -- `a` -- Scaling of current 0th order value -- `b` -- Constant added to current 0th order value -""" -function mad_ctpsa_set0!(t::Ptr{CTPSA}, a::ComplexF64, b::ComplexF64) - @ccall MAD_TPSA.mad_ctpsa_set0(t::Ptr{CTPSA}, a::ComplexF64, b::ComplexF64)::Cvoid -end - - """ mad_ctpsa_seti!(t::Ptr{CTPSA}, i::Cint, a::ComplexF64, b::ComplexF64) @@ -820,14 +798,6 @@ function mad_ctpsa_setm!(t::Ptr{CTPSA}, n::Cint, m::Vector{Cuchar}, a::ComplexF6 @ccall MAD_TPSA.mad_ctpsa_setm(t::Ptr{CTPSA}, n::Cint, m::Ptr{Cuchar}, a::ComplexF64, b::ComplexF64)::Cvoid end -""" - mad_ctpsa_cpy0!(t::Ptr{CTPSA}, r::Ptr{CTPSA}) - - ??? -""" -function mad_ctpsa_cpy0!(t::Ptr{CTPSA}, r::Ptr{CTPSA}) - @ccall MAD_TPSA.mad_ctpsa_cpy0(t::Ptr{CTPSA}, r::Ptr{CTPSA})::Cvoid -end """ mad_ctpsa_cpyi!(t::Ptr{CTPSA}, r::Ptr{CTPSA}, i::Cint) @@ -884,22 +854,6 @@ end # Accessors without complex-by-value -""" - mad_ctpsa_get0_r!(t::Ptr{CTPSA}, r::Ref{ComplexF64}) - -Gets the 0th order (scalar) value of the TPSA in place. - -### Input -- `t` -- TPSA - -### Output -- `r` -- Scalar value of TPSA -""" -function mad_ctpsa_get0_r!(t::Ptr{CTPSA}, r::Ref{ComplexF64}) - ret = @ccall MAD_TPSA.mad_ctpsa_get0_r(t::Ptr{CTPSA}, r::Ptr{ComplexF64})::Cvoid - return ret -end - """ mad_ctpsa_geti_r!(t::Ptr{CTPSA}, i::Cint, r::Ref{ComplexF64}) @@ -976,24 +930,6 @@ function mad_ctpsa_getsm_r!(t::Ptr{CTPSA}, n::Cint, m::Vector{Cint}, r::Ref{Comp end -""" - mad_ctpsa_set0_r!(t::Ptr{CTPSA}, a_re::Cdouble, a_im::Cdouble, b_re::Cdouble, b_im::Cdouble) - -Sets the 0th order coefficient (scalar part of TPSA) according to `coef[0] = a*coef[0] + b`. Does not modify other values in TPSA. -Equivalent to `mad_ctpsa_set0` but without complex-by-value arguments. - -### Input -- `t` -- TPSA -- `a_re` -- Real part of `a` -- `a_im` -- Imaginary part of `a` -- `b_re` -- Real part of `b` -- `b_im` -- Imaginary part of `b` -""" -function mad_ctpsa_set0_r!(t::Ptr{CTPSA}, a_re::Cdouble, a_im::Cdouble, b_re::Cdouble, b_im::Cdouble) - @ccall MAD_TPSA.mad_ctpsa_set0_r(t::Ptr{CTPSA}, a_re::Cdouble, a_im::Cdouble, b_re::Cdouble, b_im::Cdouble)::Cvoid -end - - """ mad_ctpsa_seti_r!(t::Ptr{CTPSA}, i::Cint, a_re::Cdouble, a_im::Cdouble, b_re::Cdouble, b_im::Cdouble) @@ -1086,7 +1022,6 @@ a TPSA to construct a matrix (`i = 1`, `n = nv+np = nn`). ### Output - `v` -- Array of coefficients for monomials `i..i+n` -- `ret` -- Copied length """ function mad_ctpsa_getv!(t::Ptr{CTPSA}, i::Cint, n::Cint, v) @ccall MAD_TPSA.mad_ctpsa_getv(t::Ptr{CTPSA}, i::Cint, n::Cint, v::Ptr{ComplexF64})::Cvoid @@ -1104,13 +1039,9 @@ Vectorized setter of the coefficients for monomials with indices `i..i+n`. Usefu - `i` -- Starting index of monomials to set coefficients - `n` -- Number of monomials to set coefficients of starting at `i` - `v` -- Array of coefficients for monomials `i..i+n` - -### Output -- `ret` -- Copied length """ -function mad_ctpsa_setv!(t::Ptr{CTPSA}, i::Cint, n::Cint, v::Vector{ComplexF64})::Cint - ret = @ccall MAD_TPSA.mad_ctpsa_setv(t::Ptr{CTPSA}, i::Cint, n::Cint, v::Ptr{ComplexF64})::Cint - return ret +function mad_ctpsa_setv!(t::Ptr{CTPSA}, i::Cint, n::Cint, v::Vector{ComplexF64}) + @ccall MAD_TPSA.mad_ctpsa_setv(t::Ptr{CTPSA}, i::Cint, n::Cint, v::Ptr{ComplexF64})::Cvoid end @@ -2934,7 +2865,7 @@ end """ - mad_ctpsa_debug(t::Ptr{CTPSA}, name_::Cstring, fnam_::Cstring, line_::Cint, stream_::Ptr{Cvoid}) + mad_ctpsa_debug(t::Ptr{CTPSA}, name_::Cstring, fnam_::Cstring, line_::Cint, stream_::Ptr{Cvoid})::Cint Prints TPSA with all information of data structure. @@ -2944,9 +2875,13 @@ Prints TPSA with all information of data structure. - `fnam_` -- (Optional) File name to print to - `line_` -- (Optional) Line number in file to start at - `stream_` -- (Optional) I/O stream to print to, default is `stdout` + +### Output +- `ret` -- ?? """ -function mad_ctpsa_debug(t::Ptr{CTPSA}, name_::Cstring, fnam_::Cstring, line_::Cint, stream_::Ptr{Cvoid}) - @ccall MAD_TPSA.mad_ctpsa_debug(t::Ptr{CTPSA}, name_::Cstring, fnam_::Cstring, line_::Cint, stream_::Ptr{Cvoid})::Cvoid +function mad_ctpsa_debug(t::Ptr{CTPSA}, name_::Cstring, fnam_::Cstring, line_::Cint, stream_::Ptr{Cvoid})::Cint + ret = @ccall MAD_TPSA.mad_ctpsa_debug(t::Ptr{CTPSA}, name_::Cstring, fnam_::Cstring, line_::Cint, stream_::Ptr{Cvoid})::Cint + return ret end """ @@ -2966,6 +2901,17 @@ function mad_ctpsa_isvalid(t::Ptr{CTPSA})::Bool end +""" + mad_ctpsa_density(t::Ptr{CTPSA}, eps::Cdouble)::Cdouble + +??? +""" +function mad_ctpsa_density(t::Ptr{CTPSA}, eps::Cdouble)::Cdouble + ret = @ccall MAD_TPSA.mad_ctpsa_density(t::Ptr{CTPSA}, eps::Cdouble)::Cdouble + return ret +end + + """ mad_ctpsa_init(t::Ptr{CTPSA}, d::Ptr{Desc}, mo::Cuchar)::Ptr{CTPSA} diff --git a/src/low_level/desc.jl b/src/low_level/desc.jl index 8f13fbcd..6131e7ce 100644 --- a/src/low_level/desc.jl +++ b/src/low_level/desc.jl @@ -11,25 +11,30 @@ the monomials, monomial indexing function, and pre-allocated permanent temporari - `nv::Cint` -- Number of variables - `np::Cint` -- Number of parameters - `mo::Cuchar` -- Max order of both variables AND parameters -- `po::Cuchar` -- Max order of parameterss -- `to::Cuchar` -- Global order of truncation. Note: `ord_t` in gtpsa is `typedef` for `unsigned char` (`Cuchar`) +- `po::Cuchar` -- Max order of parameters - `no::Ptr{Cuchar}` -- Array of orders of each variable (first `nv` entries) and parameters (last `np` entries), length `nn`. Note: In C this is `const` + - `uno::Cint` -- User provided array of orders of each variable/parameter (with `mad_desc_newvpo`) - `nth::Cint` -- Max number of threads or 1 - `nc::Cuint` -- Number of coefficients (max length of TPSA) + +- `shared::Ptr{Cint}` -- counter of shared desc (all tables below except prms) - `monos::Ptr{Cuchar}` -- 'Matrix' storing the monomials (sorted by variable) - `ords::Ptr{Cuchar}` -- Order of each monomial of `To` - `prms::Ptr{Cuchar}` -- Order of parameters in each monomial of `To` (zero = no parameters) - `To::Ptr{Ptr{Cuchar}}` -- Table by orders - pointers to monomials, sorted by order - `Tv::Ptr{Ptr{Cuchar}}` -- Table by vars - pointers to monomials, sorted by variable - `ocs::Ptr{Ptr{Cuchar}}` -- `ocs[t,i]` -> `o` in mul, compute `o` on thread `t 3 <= o <= mo` aterminated with 0 + - `ord2idx::Ptr{Cint}` -- Order to polynomial start index in `To` (i.e. in TPSA `coef`) - `tv2to::Ptr{Cint}` -- Lookup `tv`->`to` - `to2tv::Ptr{Cint}` -- Lookup `to`->`tv` - `H::Ptr{Cint}` -- Indexing matrix in `Tv` - `L::Ptr{Ptr{Cint}}` -- Multiplication indexes `L[oa,ob]`->`L_ord` `L_ord[ia,ib]`->`ic` - `L_idx::Ptr{Ptr{Ptr{Cint}}}` -- `L_idx[oa,ob]`->`[start] [split] [end]` idxs in `L` + - `size::Culonglong` -- Bytes used by `desc`. `Unsigned Long Int`: In 32 bit system is `Int32` but 64 bit is `Int64`. Using `Culonglong` assuming 64 bit + - `t::Ptr{Ptr{Cvoid}}` -- Temporary array contains 8 pointers to `RTPSA`s already initialized - `ct::Ptr{Ptr{Cvoid}}` -- Temporary array contains 8 pointers to `CTPSA`s already initialized - `ti::Ptr{Cint}` -- idx of tmp used by each thread (length = # threads) @@ -42,13 +47,13 @@ struct Desc np::Cint mo::Cuchar po::Cuchar - to::Cuchar no::Ptr{Cuchar} uno::Cint nth::Cint nc::Cuint + shared::Ptr{Cint} monos::Ptr{Cuchar} ords::Ptr{Cuchar} prms::Ptr{Cuchar} @@ -204,24 +209,6 @@ function mad_desc_maxlen(d::Ptr{Desc}, mo::Cuchar)::Cint end -""" - mad_desc_gtrunc!(d::Ptr{Desc}, to::Cuchar)::Cuchar - -Sets the global truncation order `to` of the TPSA, and returns the old global truncation order. - -### Input -- `d` -- Descriptor -- `to` -- New global truncation order - -### Output -- `oldto` -- Old global truncation order -""" -function mad_desc_gtrunc!(d::Ptr{Desc}, to::Cuchar)::Cuchar - oldto = @ccall MAD_TPSA.mad_desc_gtrunc(d::Ptr{Desc}, to::Cuchar)::Cuchar - return oldto -end - - """ mad_desc_isvalids(d::Ptr{Desc}, n::Cint, s::Cstring)::Bool diff --git a/src/low_level/mono.jl b/src/low_level/mono.jl index 06adb358..4211fc5c 100644 --- a/src/low_level/mono.jl +++ b/src/low_level/mono.jl @@ -163,6 +163,17 @@ function mad_mono_ordpf(n::Cint, a::Vector{Cuchar}, stp::Cint)::Cdouble end +""" + mad_mono_eqn(n::Cint, a::Vector{Cuchar}, b::Cuchar)::Bool + +??? +""" +function mad_mono_eqn(n::Cint, a::Vector{Cuchar}, b::Cuchar)::Bool + ret = @ccall MAD_TPSA.mad_mono_eqn(n::Cint, a::Ptr{Cuchar}, b::Cuchar)::Bool + return ret +end + + """ mad_mono_eq(n::Cint, a::Vector{Cuchar}, b::Vector{Cuchar})::Bool diff --git a/src/low_level/rtpsa.jl b/src/low_level/rtpsa.jl index 3161d61b..308558dd 100644 --- a/src/low_level/rtpsa.jl +++ b/src/low_level/rtpsa.jl @@ -5,21 +5,21 @@ This is a 1-to-1 struct for the C definition `tpsa` (real TPSA) in GTPSA. ### Fields - `d::Ptr{Cvoid}` -- Ptr to tpsa descriptor -- `uid::Cint` -- Special user field for external use (and padding) -- `mo::Cuchar` -- max ord (allocated) - `lo::Cuchar` -- lowest used ord - `hi::Cuchar` -- highest used ord -- `nz::Culonglong` -- zero/nonzero homogenous polynomials. Note: Int64 if 64 bit compiled C code, else 32 bit -- `nam::NTuple{NAMSZ,Cuchar}` -- tpsa name max string length 16 NAMSZ +- `mo::Cuchar` -- max ord +- `ao::Cuchar` -- allocated order +- `uid::Cint` -- Special user field for external use (and padding) +- `nam::NTuple{NAMSZ,Cuchar}` -- tpsa name max string length 15 chars NAMSZ - `coef::Ptr{Cdouble}` -- warning: must be identical to ctpsa up to coef excluded """ struct RTPSA - d::Ptr{Cvoid} - uid::Cint - mo::Cuchar + d::Ptr{Cvoid} lo::Cuchar - hi::Cuchar - nz::Culonglong + hi::Cuchar + mo::Cuchar + ao::Cuchar + uid::Cint nam::NTuple{NAMSZ,Cuchar} coef::Ptr{Cdouble} end @@ -128,6 +128,18 @@ function mad_tpsa_len(t::Ptr{RTPSA})::Cint end +""" + mad_tpsa_mo!(t::Ptr{RTPSA}, mo_::Cuchar)::Cuchar + +??? + +""" +function mad_tpsa_mo!(t::Ptr{RTPSA}, mo_::Cuchar)::Cuchar + ret = @ccall MAD_TPSA.mad_tpsa_mo(t::Ptr{RTPSA}, mo_::Cuchar)::Cuchar + return ret +end + + """ mad_tpsa_nam(t::Ptr{RTPSA}, nam_::Cstring)::Cstring @@ -345,12 +357,12 @@ function mad_tpsa_setval!(t::Ptr{RTPSA}, v::Cdouble) end """ - mad_tpsa_update!(t::Ptr{RTPSA}, eps_::Cdouble) + mad_tpsa_update!(t::Ptr{RTPSA}) ??? """ -function mad_tpsa_update!(t::Ptr{RTPSA}, eps_::Cdouble) - ret = @ccall MAD_TPSA.mad_tpsa_update(t::Ptr{RTPSA}, eps_::Cdouble)::Bool +function mad_tpsa_update!(t::Ptr{RTPSA}) + @ccall MAD_TPSA.mad_tpsa_update(t::Ptr{RTPSA})::Cvoid end @@ -489,23 +501,6 @@ function mad_tpsa_cycle!(t::Ptr{RTPSA}, i::Cint, n::Cint, m_::Vector{Cuchar}, v_ end -""" - mad_tpsa_get0(t::Ptr{RTPSA})::Cdouble - -Gets the 0th order (scalar) value of the TPSA - -### Input -- `t` -- TPSA - -### Output -- `ret` -- Scalar value of TPSA -""" -function mad_tpsa_get0(t::Ptr{RTPSA})::Cdouble - ret = @ccall MAD_TPSA.mad_tpsa_get0(t::Ptr{RTPSA})::Cdouble - return ret -end - - """ mad_tpsa_geti(t::Ptr{RTPSA}, i::Cint)::Cdouble @@ -581,20 +576,6 @@ function mad_tpsa_getsm(t::Ptr{RTPSA}, n::Cint, m::Vector{Cint})::Cdouble end -""" - mad_tpsa_set0!(t::Ptr{RTPSA}, a::Cdouble, b::Cdouble) - -Sets the 0th order coefficient (scalar part of TPSA) according to `coef[0] = a*coef[0] + b`. Does not modify other values in TPSA. - -### Input -- `t` -- TPSA -- `a` -- Scaling of current 0th order value -- `b` -- Constant added to current 0th order value -""" -function mad_tpsa_set0!(t::Ptr{RTPSA}, a::Cdouble, b::Cdouble) - @ccall MAD_TPSA.mad_tpsa_set0(t::Ptr{RTPSA}, a::Cdouble, b::Cdouble)::Cvoid -end - """ mad_tpsa_seti!(t::Ptr{RTPSA}, i::Cint, a::Cdouble, b::Cdouble) @@ -662,14 +643,6 @@ function mad_tpsa_setsm!(t::Ptr{RTPSA}, n::Cint, m::Vector{Cint}, a::Cdouble, b: @ccall MAD_TPSA.mad_tpsa_setsm(t::Ptr{RTPSA}, n::Cint, m::Ptr{Cint}, a::Cdouble, b::Cdouble)::Cvoid end -""" - mad_tpsa_cpy0!(t::Ptr{RTPSA}, r::Ptr{RTPSA}) - - ??? -""" -function mad_tpsa_cpy0!(t::Ptr{RTPSA}, r::Ptr{RTPSA}) - @ccall MAD_TPSA.mad_tpsa_cpy0(t::Ptr{RTPSA}, r::Ptr{RTPSA})::Cvoid -end """ mad_tpsa_cpyi!(t::Ptr{RTPSA}, r::Ptr{RTPSA}, i::Cint) @@ -709,7 +682,7 @@ end """ - mad_tpsa_getv!(t::Ptr{RTPSA}, i::Cint, n::Cint, v)::Cint + mad_tpsa_getv!(t::Ptr{RTPSA}, i::Cint, n::Cint, v) Vectorized getter of the coefficients for monomials with indices `i..i+n`. Useful for extracting the 1st order parts of @@ -722,15 +695,12 @@ a TPSA to construct a matrix (`i = 1`, `n = nv+np = nn`). ### Output - `v` -- Array of coefficients for monomials `i..i+n` -- `ret` -- Copied length """ -function mad_tpsa_getv!(t::Ptr{RTPSA}, i::Cint, n::Cint, v)::Cint - ret = @ccall MAD_TPSA.mad_tpsa_getv(t::Ptr{RTPSA}, i::Cint, n::Cint, v::Ptr{Cdouble})::Cint - return ret +function mad_tpsa_getv!(t::Ptr{RTPSA}, i::Cint, n::Cint, v) + @ccall MAD_TPSA.mad_tpsa_getv(t::Ptr{RTPSA}, i::Cint, n::Cint, v::Ptr{Cdouble})::Cvoid end - """ mad_tpsa_setv!(t::Ptr{RTPSA}, i::Cint, n::Cint, v::Vector{Cdouble}) @@ -741,13 +711,9 @@ Vectorized setter of the coefficients for monomials with indices `i..i+n`. Usefu - `i` -- Starting index of monomials to set coefficients - `n` -- Number of monomials to set coefficients of starting at `i` - `v` -- Array of coefficients for monomials `i..i+n` - -### Output -- `ret` -- Copied length """ function mad_tpsa_setv!(t::Ptr{RTPSA}, i::Cint, n::Cint, v::Vector{Cdouble}) - ret = @ccall MAD_TPSA.mad_tpsa_setv(t::Ptr{RTPSA}, i::Cint, n::Cint, v::Ptr{Cdouble})::Cint - return ret + @ccall MAD_TPSA.mad_tpsa_setv(t::Ptr{RTPSA}, i::Cint, n::Cint, v::Ptr{Cdouble})::Cvoid end @@ -2108,7 +2074,7 @@ end """ - mad_tpsa_debug(t::Ptr{RTPSA}, name_::Cstring, fnam_::Cstring, line_::Cint, stream_::Ptr{Cvoid}) + mad_tpsa_debug(t::Ptr{RTPSA}, name_::Cstring, fnam_::Cstring, line_::Cint, stream_::Ptr{Cvoid})::Cint Prints TPSA with all information of data structure. @@ -2118,11 +2084,35 @@ Prints TPSA with all information of data structure. - `fnam_` -- (Optional) File name to print to - `line_` -- (Optional) Line number in file to start at - `stream_` -- (Optional) I/O stream to print to, default is `stdout` + +### Output +- `ret` -- ?? """ -function mad_tpsa_debug(t::Ptr{RTPSA}, name_::Cstring, fnam_::Cstring, line_::Cint, stream_::Ptr{Cvoid}) - @ccall MAD_TPSA.mad_tpsa_debug(t::Ptr{RTPSA}, name_::Cstring, fnam_::Cstring, line_::Cint, stream_::Ptr{Cvoid})::Cvoid +function mad_tpsa_debug(t::Ptr{RTPSA}, name_::Cstring, fnam_::Cstring, line_::Cint, stream_::Ptr{Cvoid})::Cint + ret = @ccall MAD_TPSA.mad_tpsa_debug(t::Ptr{RTPSA}, name_::Cstring, fnam_::Cstring, line_::Cint, stream_::Ptr{Cvoid})::Cint + return ret end + +""" + mad_tpsa_prtdensity(stream_::Ptr{Cvoid}) + +??? +""" +function mad_tpsa_prtdensity(stream_::Ptr{Cvoid}) + @ccall MAD_TPSA.mad_tpsa_prtdensity(stream_::Ptr{Cvoid})::Cvoid +end + +""" + mad_tpsa_clrdensity!()::Cvoid + +??? +""" +function mad_tpsa_clrdensity!()::Cvoid + @ccall MAD_TPSA.mad_tpsa_clrdensity()::Cvoid +end + + """ mad_tpsa_isvalid(t::Ptr{RTPSA})::Bool @@ -2139,6 +2129,16 @@ function mad_tpsa_isvalid(t::Ptr{RTPSA})::Bool return ret end +""" + mad_tpsa_density(t::Ptr{RTPSA}, eps::Cdouble)::Cdouble + +??? +""" +function mad_tpsa_density(t::Ptr{RTPSA}, eps::Cdouble)::Cdouble + ret = @ccall MAD_TPSA.mad_tpsa_density(t::Ptr{RTPSA}, eps::Cdouble)::Cdouble + return ret +end + """ mad_tpsa_init(t::Ptr{RTPSA}, d::Ptr{Desc}, mo::Cuchar)::Ptr{RTPSA} @@ -2157,4 +2157,5 @@ the maximum order of the descriptor. `t` is modified in place and also returned. function mad_tpsa_init!(t::Ptr{RTPSA}, d::Ptr{Desc}, mo::Cuchar)::Ptr{RTPSA} t = @ccall MAD_TPSA.mad_tpsa_init(t::Ptr{RTPSA}, d::Ptr{Desc}, mo::Cuchar)::Ptr{RTPSA} return t -end \ No newline at end of file +end + From c61706c8d0ed3b00bb5716a0d1a04993be43f33e Mon Sep 17 00:00:00 2001 From: Matt Signorelli Date: Mon, 22 Apr 2024 11:05:07 -0400 Subject: [PATCH 21/29] tests passing --- test/runtests.jl | 2 -- 1 file changed, 2 deletions(-) diff --git a/test/runtests.jl b/test/runtests.jl index 0f58029b..c90dd1c0 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -1202,8 +1202,6 @@ end Comparing mad_tpsa.h to rtpsa.jl... mad_ctpsa.h downloaded. Comparing mad_ctpsa.h to ctpsa.jl... - mad_ctpsa_unit: Variable in C ctpsa_t* t => t::Ptr{CTPSA} not equal to Julia a::Ptr{CTPSA} - mad_ctpsa_unit: Variable in C ctpsa_t* r => r::Ptr{CTPSA} not equal to Julia c::Ptr{CTPSA} """ @test compare_MAD() == expected_out end From a6b0ba01962531b2c9e8927f6ea9a3c3e3c4b78f Mon Sep 17 00:00:00 2001 From: Matt Signorelli Date: Mon, 22 Apr 2024 11:05:22 -0400 Subject: [PATCH 22/29] tests passing: --- src/fast_gtpsa.jl | 36 ++++++++++++++++++------------------ src/operators.jl | 40 +++++++++++++++++++--------------------- src/tps.jl | 26 +++++++++++++------------- 3 files changed, 50 insertions(+), 52 deletions(-) diff --git a/src/fast_gtpsa.jl b/src/fast_gtpsa.jl index 87a22fdd..97fa7cb2 100644 --- a/src/fast_gtpsa.jl +++ b/src/fast_gtpsa.jl @@ -234,7 +234,7 @@ end function ±(t1::TPS, a::Real)::Ptr{RTPSA} tpsa = get_rtemp!(t1) mad_tpsa_copy!(t1.tpsa, tpsa) - mad_tpsa_set0!(tpsa, 1., convert(Float64,a)) + mad_tpsa_seti!(tpsa, Cint(0),1., convert(Float64,a)) return tpsa end @@ -258,7 +258,7 @@ function ±(tpsa1::Ptr{RTPSA},t1::TPS)::Ptr{RTPSA} end function ±(tpsa1::Ptr{RTPSA}, a::Real)::Ptr{RTPSA} - mad_tpsa_set0!(tpsa1, 1., convert(Float64,a)) + mad_tpsa_seti!(tpsa1, Cint(0), 1., convert(Float64,a)) return tpsa1 end @@ -276,7 +276,7 @@ end function ±(ct1::ComplexTPS, a::Number)::Ptr{CTPSA} ctpsa = get_ctemp!(ct1) mad_ctpsa_copy!(ct1.tpsa, ctpsa) - mad_ctpsa_set0!(ctpsa, convert(ComplexF64,1), convert(ComplexF64,a)) + mad_ctpsa_seti!(ctpsa, Cint(0), convert(ComplexF64,1), convert(ComplexF64,a)) return ctpsa end @@ -300,7 +300,7 @@ function ±(ctpsa1::Ptr{CTPSA}, ct1::ComplexTPS)::Ptr{CTPSA} end function ±(ctpsa1::Ptr{CTPSA}, a::Number)::Ptr{CTPSA} - mad_ctpsa_set0!(ctpsa1, convert(ComplexF64,1), convert(ComplexF64,a)) + mad_ctpsa_seti!(ctpsa1, Cint(0), convert(ComplexF64,1), convert(ComplexF64,a)) return ctpsa1 end @@ -323,7 +323,7 @@ end function ±(t1::TPS, a::Complex)::Ptr{CTPSA} ctpsa = get_ctemp!(t1) mad_ctpsa_cplx!(t1.tpsa, Base.unsafe_convert(Ptr{RTPSA}, C_NULL), ctpsa) - mad_ctpsa_set0!(ctpsa, convert(ComplexF64, 1), convert(ComplexF64, a)) + mad_ctpsa_seti!(ctpsa, Cint(0),convert(ComplexF64, 1), convert(ComplexF64, a)) return ctpsa end @@ -334,7 +334,7 @@ end function ±(tpsa1::Ptr{RTPSA}, a::Complex)::Ptr{CTPSA} ctpsa = get_ctemp_low!(tpsa1) mad_ctpsa_cplx!(tpsa1, Base.unsafe_convert(Ptr{RTPSA}, C_NULL), ctpsa) - mad_ctpsa_set0!(ctpsa, convert(ComplexF64, 1), convert(ComplexF64, a)) + mad_ctpsa_seti!(ctpsa, Cint(0),convert(ComplexF64, 1), convert(ComplexF64, a)) rel_rtemp!(tpsa1) return ctpsa end @@ -378,14 +378,14 @@ end function ∓(t1::TPS, a::Real)::Ptr{RTPSA} tpsa = get_rtemp!(t1) mad_tpsa_copy!(t1.tpsa, tpsa) - mad_tpsa_set0!(tpsa, 1., convert(Float64, -a)) + mad_tpsa_seti!(tpsa, Cint(0), 1., convert(Float64, -a)) return tpsa end function ∓(a::Real, t1::TPS)::Ptr{RTPSA} tpsa = get_rtemp!(t1) mad_tpsa_scl!(t1.tpsa, -1., tpsa) - mad_tpsa_set0!(tpsa, 1., convert(Float64, a)) + mad_tpsa_seti!(tpsa, Cint(0), 1., convert(Float64, a)) return tpsa end @@ -406,13 +406,13 @@ function ∓(tpsa1::Ptr{RTPSA}, t1::TPS)::Ptr{RTPSA} end function ∓(tpsa1::Ptr{RTPSA}, a::Real)::Ptr{RTPSA} - mad_tpsa_set0!(tpsa1, 1., convert(Float64, -a)) + mad_tpsa_seti!(tpsa1, Cint(0), 1., convert(Float64, -a)) return tpsa1 end function ∓(a::Real, tpsa1::Ptr{RTPSA})::Ptr{RTPSA} mad_tpsa_scl!(tpsa1, -1., tpsa1) - mad_tpsa_set0!(tpsa1, 1., convert(Float64, a)) + mad_tpsa_seti!(tpsa1, Cint(0), 1., convert(Float64, a)) return tpsa1 end @@ -426,14 +426,14 @@ end function ∓(ct1::ComplexTPS, a::Number)::Ptr{CTPSA} ctpsa = get_ctemp!(ct1) mad_ctpsa_copy!(ct1.tpsa, ctpsa) - mad_ctpsa_set0!(ctpsa, convert(ComplexF64, 1.), convert(ComplexF64, -a)) + mad_ctpsa_seti!(ctpsa, Cint(0), convert(ComplexF64, 1.), convert(ComplexF64, -a)) return ctpsa end function ∓(a::Number, ct1::ComplexTPS)::Ptr{CTPSA} ctpsa = get_ctemp!(ct1) mad_ctpsa_scl!(ct1.tpsa, convert(ComplexF64,-1.), ctpsa) - mad_ctpsa_set0!(ctpsa, convert(ComplexF64,1.), convert(ComplexF64, a)) + mad_ctpsa_seti!(ctpsa, Cint(0), convert(ComplexF64,1.), convert(ComplexF64, a)) return ctpsa end @@ -454,13 +454,13 @@ function ∓(ctpsa1::Ptr{CTPSA}, ct1::ComplexTPS)::Ptr{CTPSA} end function ∓(ctpsa1::Ptr{CTPSA}, a::Number)::Ptr{CTPSA} - mad_ctpsa_set0!(ctpsa1, convert(ComplexF64,1.), convert(ComplexF64, -a)) + mad_ctpsa_seti!(ctpsa1, Cint(0), convert(ComplexF64,1.), convert(ComplexF64, -a)) return ctpsa1 end function ∓(a::Number, ctpsa1::Ptr{CTPSA})::Ptr{CTPSA} mad_ctpsa_scl!(ctpsa1, convert(ComplexF64, -1.), ctpsa1) - mad_ctpsa_set0!(ctpsa1, convert(ComplexF64, 1.), convert(ComplexF64, a)) + mad_ctpsa_seti!(ctpsa1, Cint(0), convert(ComplexF64, 1.), convert(ComplexF64, a)) return ctpsa1 end @@ -480,7 +480,7 @@ end function ∓(t1::TPS, a::Complex)::Ptr{CTPSA} ctpsa = get_ctemp!(t1) mad_ctpsa_cplx!(t1.tpsa, Base.unsafe_convert(Ptr{RTPSA}, C_NULL), ctpsa) - mad_ctpsa_set0!(ctpsa, convert(ComplexF64, 1), convert(ComplexF64, -a)) + mad_ctpsa_seti!(ctpsa, Cint(0), convert(ComplexF64, 1), convert(ComplexF64, -a)) return ctpsa end @@ -488,7 +488,7 @@ function ∓(a::Complex, t1::TPS)::Ptr{CTPSA} ctpsa = get_ctemp!(t1) mad_ctpsa_cplx!(t1.tpsa, Base.unsafe_convert(Ptr{RTPSA}, C_NULL), ctpsa) mad_ctpsa_scl!(ctpsa, convert(ComplexF64, -1), ctpsa) - mad_ctpsa_set0!(ctpsa, convert(ComplexF64, 1), convert(ComplexF64,a)) + mad_ctpsa_seti!(ctpsa,Cint(0), convert(ComplexF64, 1), convert(ComplexF64,a)) return ctpsa end @@ -508,7 +508,7 @@ function ∓(tpsa1::Ptr{RTPSA}, a::Complex)::Ptr{CTPSA} ctpsa = get_ctemp_low!(tpsa1) mad_ctpsa_cplx!(tpsa1, Base.unsafe_convert(Ptr{RTPSA}, C_NULL), ctpsa) rel_temp!(tpsa1) - mad_ctpsa_set0!(ctpsa, convert(ComplexF64, 1), convert(ComplexF64, -a)) + mad_ctpsa_seti!(ctpsa, Cint(0), convert(ComplexF64, 1), convert(ComplexF64, -a)) return ctpsa end @@ -517,7 +517,7 @@ function ∓(a::Complex, tpsa1::Ptr{RTPSA})::Ptr{CTPSA} mad_ctpsa_cplx!(tpsa1, Base.unsafe_convert(Ptr{RTPSA}, C_NULL), ctpsa) rel_temp!(tpsa1) mad_ctpsa_scl!(ctpsa, convert(ComplexF64, -1), ctpsa) - mad_ctpsa_set0!(ctpsa, convert(ComplexF64, 1), convert(ComplexF64,a)) + mad_ctpsa_seti!(ctpsa, Cint(0), convert(ComplexF64, 1), convert(ComplexF64,a)) return ctpsa end function ∓(ctpsa1::Ptr{CTPSA}, t1::TPS)::Ptr{CTPSA} diff --git a/src/operators.jl b/src/operators.jl index cd64a228..19f5d33a 100644 --- a/src/operators.jl +++ b/src/operators.jl @@ -23,13 +23,13 @@ end # --- one --- function one(t1::TPS)::TPS t = TPS(mad_tpsa_new(t1.tpsa, MAD_TPSA_SAME)) - mad_tpsa_set0!(t.tpsa, 0.0, 1.0) + mad_tpsa_seti!(t.tpsa, Cint(0), 0.0, 1.0) return t end function one(ct1::ComplexTPS)::ComplexTPS ct = ComplexTPS(mad_ctpsa_new(ct1.tpsa, MAD_TPSA_SAME)) - mad_ctpsa_set0!(ct.tpsa, ComplexF64(0.0), ComplexF64(1.0)) + mad_ctpsa_seti!(ct.tpsa, Cint(0), ComplexF64(0.0), ComplexF64(1.0)) return ct end @@ -108,15 +108,15 @@ end # isequal, just as Dual Numbers. function <(t1::TPS, t2::TPS)::Bool - return mad_tpsa_get0(t1.tpsa) < mad_tpsa_get0(t2.tpsa) + return mad_tpsa_geti(t1.tpsa, Cint(0)) < mad_tpsa_geti(t2.tpsa, Cint(0)) end function <(t1::TPS, a::Real)::Bool - return mad_tpsa_get0(t1.tpsa) < a + return mad_tpsa_geti(t1.tpsa, Cint(0)) < a end function <(a::Real, t1::TPS)::Bool - return a < mad_tpsa_get0(t1.tpsa) + return a < mad_tpsa_geti(t1.tpsa, Cint(0)) end function >(t1::TPS, t2::TPS)::Bool @@ -132,15 +132,15 @@ function >(a::Real, t1::TPS)::Bool end function <=(t1::TPS, t2::TPS)::Bool - return mad_tpsa_get0(t1.tpsa) <= mad_tpsa_get0(t2.tpsa) + return mad_tpsa_geti(t1.tpsa, Cint(0)) <= mad_tpsa_geti(t2.tpsa, Cint(0)) end function <=(t1::TPS, a::Real)::Bool - return mad_tpsa_get0(t1.tpsa) <= a + return mad_tpsa_geti(t1.tpsa, Cint(0)) <= a end function <=(a::Real, t1::TPS)::Bool - return a <= mad_tpsa_get0(t1.tpsa) + return a <= mad_tpsa_geti(t1.tpsa, Cint(0)) end function >=(t1::TPS, t2::TPS)::Bool @@ -158,44 +158,44 @@ end # Note Complex numbers/TPSs have no defined >, < function ==(t1::TPS, t2::TPS)::Bool - return mad_tpsa_get0(t1.tpsa) == mad_tpsa_get0(t2.tpsa) + return mad_tpsa_geti(t1.tpsa, Cint(0)) == mad_tpsa_geti(t2.tpsa, Cint(0)) end function ==(t1::TPS, a::Number)::Bool - return mad_tpsa_get0(t1.tpsa) == a + return mad_tpsa_geti(t1.tpsa, Cint(0)) == a end function ==(a::Number,t1::TPS)::Bool - return mad_tpsa_get0(t1.tpsa) == a + return mad_tpsa_geti(t1.tpsa, Cint(0)) == a end # --- function ==(t1::TPS, a::Complex)::Bool - return mad_tpsa_get0(t1.tpsa) == a + return mad_tpsa_geti(t1.tpsa, Cint(0)) == a end function ==(a::Complex,t1::TPS)::Bool - return mad_tpsa_get0(t1.tpsa) == a + return mad_tpsa_geti(t1.tpsa, Cint(0)) == a end # --- function ==(ct1::ComplexTPS, ct2::ComplexTPS)::Bool - return mad_ctpsa_get0(ct1.tpsa) == mad_ctpsa_get0(ct2.tpsa) + return mad_ctpsa_geti(ct1.tpsa, Cint(0)) == mad_ctpsa_geti(ct2.tpsa, Cint(0)) end function ==(ct1::ComplexTPS, a::Number)::Bool - return mad_ctpsa_get0(ct1.tpsa) == a + return mad_ctpsa_geti(ct1.tpsa, Cint(0)) == a end function ==(a::Number, ct1::ComplexTPS)::Bool - return mad_ctpsa_get0(ct1.tpsa) == a + return mad_ctpsa_geti(ct1.tpsa, Cint(0)) == a end function ==(ct1::ComplexTPS, t1::TPS)::Bool - return mad_ctpsa_get0(ct1.tpsa) == mad_tpsa_get0(t1.tpsa) + return mad_ctpsa_geti(ct1.tpsa, Cint(0)) == mad_tpsa_geti(t1.tpsa, Cint(0)) end function ==(t1::TPS, ct1::ComplexTPS)::Bool @@ -263,12 +263,10 @@ add!(a::Ptr{CTPSA}, b::Ptr{RTPSA}, c::Ptr{CTPSA}) = mad_ctpsa_addt!(a, b, c) add!(t::Union{TPS,ComplexTPS}, t1::Union{TPS,ComplexTPS}, t2::Union{TPS,ComplexTPS}) = add!(t1.tpsa, t2.tpsa, t.tpsa) # TPS, scalar: -set0!(t::Ptr{RTPSA}, a::Float64, b::Float64) = mad_tpsa_set0!(t, a, b) -set0!(t::Ptr{CTPSA}, a::ComplexF64, b::ComplexF64) = mad_ctpsa_set0!(t, a, b) function add!(t::Union{TPS,ComplexTPS}, t1::Union{TPS,ComplexTPS}, a::Number) copy!(t, t1) - set0!(t.tpsa, convert(numtype(t), 1), convert(numtype(t), a)) + seti!(t.tpsa, Cint(0), convert(numtype(t), 1), convert(numtype(t), a)) end add!(t::Union{TPS,ComplexTPS}, a::Number, t1::Union{TPS,ComplexTPS}) = add!(t, t1, a) @@ -306,7 +304,7 @@ sub!(t::Union{TPS,ComplexTPS}, t1::Union{TPS,ComplexTPS}, a::Number) = add!(t, t function sub!(t::Union{TPS,ComplexTPS}, a::Number, t1::Union{TPS,ComplexTPS}) scl!(t1.tpsa, convert(numtype(t), -1.), t.tpsa) - set0!(t.tpsa, convert(numtype(t), 1.), convert(numtype(t), a)) + seti!(t.tpsa, Cint(0), convert(numtype(t), 1.), convert(numtype(t), a)) end for t = ((TPS,TPS),(TPS,Real),(Real,TPS),(TPS,Complex),(Complex,TPS),(ComplexTPS,TPS),(TPS,ComplexTPS),(ComplexTPS,ComplexTPS),(ComplexTPS, Number), (Number, ComplexTPS)) diff --git a/src/tps.jl b/src/tps.jl index b004043d..a506f254 100644 --- a/src/tps.jl +++ b/src/tps.jl @@ -75,19 +75,19 @@ end # --- promote real to TPS --- function low_TPS(a::Real, use::Nothing) t = TPS(mad_tpsa_newd(GTPSA.desc_current.desc, MAD_TPSA_DEFAULT)) - mad_tpsa_set0!(t.tpsa, convert(Float64, 0), convert(Float64,a)) + mad_tpsa_seti!(t.tpsa, Cint(0), convert(Float64, 0), convert(Float64,a)) return t end function low_TPS(a::Real, use::Union{TPS,ComplexTPS}) t = TPS(mad_tpsa_new(Base.unsafe_convert(Ptr{RTPSA}, use.tpsa), MAD_TPSA_SAME)) - mad_tpsa_set0!(t.tpsa, 0.0, convert(Float64,a)) + mad_tpsa_seti!(t.tpsa, Cint(0), 0.0, convert(Float64,a)) return t end function low_TPS(a::Real, use::Descriptor) t = TPS(mad_tpsa_newd(use.desc, MAD_TPSA_DEFAULT)) - mad_tpsa_set0!(t.tpsa, 0.0, convert(Float64,a)) + mad_tpsa_seti!(t.tpsa, Cint(0), 0.0, convert(Float64,a)) return t end @@ -156,19 +156,19 @@ end # --- promote number to ComplexTPS --- function low_ComplexTPS(a::Union{Real,Complex}, use::Nothing) ct = ComplexTPS(mad_ctpsa_newd(GTPSA.desc_current.desc, MAD_TPSA_DEFAULT)) - mad_ctpsa_set0!(ct.tpsa, convert(ComplexF64, 0), convert(ComplexF64,a)) + mad_ctpsa_seti!(ct.tpsa, Cint(0), convert(ComplexF64, 0), convert(ComplexF64,a)) return ct end function low_ComplexTPS(a::Union{Real,Complex}, use::Union{TPS,ComplexTPS}) ct = ComplexTPS(mad_ctpsa_new(Base.unsafe_convert(Ptr{CTPSA}, use.tpsa), MAD_TPSA_SAME)) - mad_ctpsa_set0!(ct.tpsa, convert(ComplexF64, 0), convert(ComplexF64,a)) + mad_ctpsa_seti!(ct.tpsa, Cint(0), convert(ComplexF64, 0), convert(ComplexF64,a)) return ct end function low_ComplexTPS(a::Union{Real,Complex}, use::Descriptor) ct = ComplexTPS(mad_ctpsa_newd(use.desc, MAD_TPSA_DEFAULT)) - mad_ctpsa_set0!(ct.tpsa, convert(ComplexF64, 0), convert(ComplexF64,a)) + mad_ctpsa_seti!(ct.tpsa, Cint(0), convert(ComplexF64, 0), convert(ComplexF64,a)) return ct end @@ -188,32 +188,32 @@ end function low_ComplexTPS(t1::TPS, a::Real, use::Nothing) ct = ComplexTPS(mad_ctpsa_new(Base.unsafe_convert(Ptr{CTPSA}, t1.tpsa), MAD_TPSA_SAME)) mad_ctpsa_cplx!(t1.tpsa, Base.unsafe_convert(Ptr{RTPSA}, C_NULL), ct.tpsa) - mad_ctpsa_set0!(ct.tpsa, convert(ComplexF64, 1), convert(ComplexF64, complex(0,a))) + mad_ctpsa_seti!(ct.tpsa, Cint(0), convert(ComplexF64, 1), convert(ComplexF64, complex(0,a))) return ct end function low_ComplexTPS(a::Real, t1::TPS, use::Nothing) ct = ComplexTPS(mad_ctpsa_new(Base.unsafe_convert(Ptr{CTPSA}, t1.tpsa), MAD_TPSA_SAME)) mad_ctpsa_cplx!(Base.unsafe_convert(Ptr{RTPSA}, C_NULL), t1.tpsa, ct.tpsa) - mad_ctpsa_set0!(ct.tpsa, convert(ComplexF64, 1), convert(ComplexF64, a)) + mad_ctpsa_seti!(ct.tpsa, Cint(0), convert(ComplexF64, 1), convert(ComplexF64, a)) return ct end function low_ComplexTPS(a::Real, b::Real, use::Nothing) ct = ComplexTPS(mad_ctpsa_newd(GTPSA.desc_current.desc, MAD_TPSA_DEFAULT)) - mad_ctpsa_set0!(ct.tpsa, convert(ComplexF64, 0), convert(ComplexF64, complex(a,b))) + mad_ctpsa_seti!(ct.tpsa, Cint(0), convert(ComplexF64, 0), convert(ComplexF64, complex(a,b))) return ct end function low_ComplexTPS(a::Real, b::Real, use::Descriptor) ct = ComplexTPS(mad_ctpsa_newd(use.desc, MAD_TPSA_DEFAULT)) - mad_ctpsa_set0!(ct.tpsa, convert(ComplexF64, 0), convert(ComplexF64, complex(a,b))) + mad_ctpsa_seti!(ct.tpsa, Cint(0), convert(ComplexF64, 0), convert(ComplexF64, complex(a,b))) return ct end function low_ComplexTPS(a::Real, b::Real, use::Union{TPS,ComplexTPS}) ct = ComplexTPS(mad_ctpsa_new(Base.unsafe_convert(Ptr{CTPSA}, use.tpsa), MAD_TPSA_SAME)) - mad_ctpsa_set0!(ct.tpsa, convert(ComplexF64, 0), convert(ComplexF64, complex(a,b))) + mad_ctpsa_seti!(ct.tpsa, Cint(0), convert(ComplexF64, 0), convert(ComplexF64, complex(a,b))) return ct end @@ -225,13 +225,13 @@ end function low_ComplexTPS(ta::TPS, b::Real, use::Descriptor) ct = change(ta, use, type=ComplexTPS) - mad_ctpsa_set0!(ct.tpsa, convert(ComplexF64, 1), convert(ComplexF64, complex(0,b))) + mad_ctpsa_seti!(ct.tpsa, Cint(0), convert(ComplexF64, 1), convert(ComplexF64, complex(0,b))) return ct end function low_ComplexTPS(a::Real, tb::TPS, use::Descriptor) ct = change(tb, use, type=ComplexTPS, scl2=im) - mad_ctpsa_set0!(ct.tpsa, convert(ComplexF64, 1), convert(ComplexF64, a)) + mad_ctpsa_seti!(ct.tpsa, Cint(0), convert(ComplexF64, 1), convert(ComplexF64, a)) return ct end From 6793df922d9216fcf9894cd1b723f9ee2b0e7923 Mon Sep 17 00:00:00 2001 From: Matt Signorelli Date: Thu, 25 Apr 2024 10:01:24 -0400 Subject: [PATCH 23/29] added vectorized get/set for linear indexing: --- docs/src/man/o_all.md | 2 +- src/GTPSA.jl | 3 ++- src/getset.jl | 28 +++++++++++++++++++++++----- 3 files changed, 26 insertions(+), 7 deletions(-) diff --git a/docs/src/man/o_all.md b/docs/src/man/o_all.md index bd7fc9d8..26d1de13 100644 --- a/docs/src/man/o_all.md +++ b/docs/src/man/o_all.md @@ -6,7 +6,7 @@ sin, cos, tan, csc, sec, cot, sinc, sinh, cosh, tanh, csch, sech, coth, asin, acos, atan, acsc, asec, acot, asinh, acosh, atanh, acsch, asech, acoth, zero, zeros, one, ones, real, imag, conj, angle, complex, promote_rule, getindex, setindex!, ==, <, ->, <=, >=, !=, isequal, show, copy! +>, <=, >=, !=, isequal, show, copy!, length ``` `zeros` and `ones` are overloaded from Base so that allocated `TPS`/`ComplexTPS`s are placed in each element. If we didn't explicity overload these functions, every element would correspond to the exact same heap-allocated TPS, which is problematic when setting individual monomial coefficients of the same TPS. diff --git a/src/GTPSA.jl b/src/GTPSA.jl index 0c5fcb5e..c64651ba 100644 --- a/src/GTPSA.jl +++ b/src/GTPSA.jl @@ -60,7 +60,8 @@ import Base: +, !=, isequal, show, - copy! + copy!, + length import LinearAlgebra: norm, mul! import SpecialFunctions: erf, erfc diff --git a/src/getset.jl b/src/getset.jl index ff7806d7..5030ad83 100644 --- a/src/getset.jl +++ b/src/getset.jl @@ -5,15 +5,14 @@ setm!(t::Ptr{RTPSA}, n::Cint, m::Vector{Cuchar}, a::Float64, b::Float64) = mad_t setm!(t::Ptr{CTPSA}, n::Cint, m::Vector{Cuchar}, a::ComplexF64, b::ComplexF64) = mad_ctpsa_setm!(t, n, m, a, b) setsm!(t::Ptr{RTPSA}, n::Cint, m::Vector{Cint}, a::Float64, b::Float64)= mad_tpsa_setsm!(t, n, m, a, b) setsm!(t::Ptr{CTPSA}, n::Cint, m::Vector{Cint}, a::ComplexF64, b::ComplexF64)= mad_ctpsa_setsm!(t, n, m, a, b) +setv!(t::Ptr{RTPSA}, i::Cint, n::Cint, v::Vector{Cdouble}) = mad_tpsa_setv!(t, i, n, v) +setv!(t::Ptr{CTPSA}, i::Cint, n::Cint, v::Vector{ComplexF64}) = mad_ctpsa_setv!(t, i, n, v) # All -function setindex!(t::Union{TPS,ComplexTPS}, v::Number, idx::Union{TPSIndexType,Nothing}=nothing; param::Union{Integer,Nothing}=nothing, params::Union{SMIndexType,Nothing}=nothing) +function setindex!(t::Union{TPS,ComplexTPS}, v::Union{AbstractVector{<:Number},Number}, idx::Union{TPSIndexType,AbstractVector{<:Integer},Nothing}=nothing; param::Union{Integer,Nothing}=nothing, params::Union{SMIndexType,Nothing}=nothing) lowset!(t, v, idx, param, params) end -# To override Base number.jl -#setindex!(t::Union{ComplexTPS, TPS}, v::Number, idx::Integer) = lowset!(t, v, tuple(idx), nothing, nothing) - # Flat index function lowset!(t::Union{TPS,ComplexTPS}, v::Number, i::Union{Nothing,Integer}, param::Union{Nothing,Integer}, params::Nothing) if isnothing(i) && isnothing(param) @@ -28,6 +27,15 @@ function lowset!(t::Union{TPS,ComplexTPS}, v::Number, i::Union{Nothing,Integer}, end end +# Flat index vectorized +function lowset!(t::Union{TPS,ComplexTPS}, v::AbstractVector{<:Number}, idxs::AbstractVector{<:Integer}, param::Nothing, params::Nothing) + Base.require_one_based_indexing(v,idxs) + length(v) == length(idxs) || throw(DimensionMismatch("Tried to assign $(length(v)) elements to $(length(idxs)) destinations")) + for i=1:length(idxs) + seti!(t.tpsa, Cint(idxs[i]), (numtype(t))(0),(numtype(t))(v[i])) + end +end + # Monomial function lowset!(t::Union{TPS,ComplexTPS}, v::Number, ords::MIndexType, param::Nothing, params::Nothing) setm!(t.tpsa, convert(Cint, length(ords)), collect(Cuchar, ords), (numtype(t))(0), (numtype(t))(v)) @@ -58,7 +66,7 @@ getsm(t::Ptr{RTPSA}, n::Cint, m::Vector{Cint})= mad_tpsa_getsm(t, n, m) getsm(t::Ptr{CTPSA}, n::Cint, m::Vector{Cint})= mad_ctpsa_getsm(t, n, m) # All -function getindex(t::Union{TPS,ComplexTPS}, idx::Union{TPSIndexType,Nothing}=nothing; param::Union{Integer,Nothing}=nothing, params::Union{SMIndexType,Nothing}=nothing) +function getindex(t::Union{TPS,ComplexTPS}, idx::Union{AbstractVector{<:Integer},TPSIndexType,Nothing}=nothing; param::Union{Integer,Nothing}=nothing, params::Union{SMIndexType,Nothing}=nothing) #println(typeof(t)) #println(typeof(idx)) #println(typeof(param)) @@ -83,6 +91,16 @@ function lowget(t::Union{TPS,ComplexTPS}, i::Union{Nothing,Integer}, param::Unio end end +# Flat index vectorized +function lowget(t::Union{TPS,ComplexTPS}, idxs::AbstractVector{<:Integer}, param::Nothing, params::Nothing) + Base.require_one_based_indexing(idxs) + v = Vector{numtype(t)}(undef, length(idxs)) + for i=1:length(idxs) + v[i] = geti(t.tpsa, Cint(idxs[i])) + end + return v +end + # Monomial function lowget(t::Union{TPS,ComplexTPS}, ords::MIndexType, param::Nothing, params::Nothing) return getm(t.tpsa, convert(Cint, length(ords)), collect(Cuchar, ords)) From 5f5b93a5b5d47b1cc25a42de7c09178204fb56c6 Mon Sep 17 00:00:00 2001 From: mattsignorelli Date: Thu, 25 Apr 2024 10:22:45 -0400 Subject: [PATCH 24/29] rand TPS generator implemented --- docs/src/man/o_all.md | 3 ++- src/GTPSA.jl | 5 ++++- src/getset.jl | 14 ++++++++++++++ src/operators.jl | 10 ++++++++++ 4 files changed, 30 insertions(+), 2 deletions(-) diff --git a/docs/src/man/o_all.md b/docs/src/man/o_all.md index 26d1de13..b9b619fa 100644 --- a/docs/src/man/o_all.md +++ b/docs/src/man/o_all.md @@ -6,7 +6,8 @@ sin, cos, tan, csc, sec, cot, sinc, sinh, cosh, tanh, csch, sech, coth, asin, acos, atan, acsc, asec, acot, asinh, acosh, atanh, acsch, asech, acoth, zero, zeros, one, ones, real, imag, conj, angle, complex, promote_rule, getindex, setindex!, ==, <, ->, <=, >=, !=, isequal, show, copy!, length +>, <=, >=, !=, isequal, show, copy!, length, lastindex, firstindex, +rand ``` `zeros` and `ones` are overloaded from Base so that allocated `TPS`/`ComplexTPS`s are placed in each element. If we didn't explicity overload these functions, every element would correspond to the exact same heap-allocated TPS, which is problematic when setting individual monomial coefficients of the same TPS. diff --git a/src/GTPSA.jl b/src/GTPSA.jl index c64651ba..e52eeca5 100644 --- a/src/GTPSA.jl +++ b/src/GTPSA.jl @@ -61,7 +61,10 @@ import Base: +, isequal, show, copy!, - length + length, + lastindex, + firstindex, + rand import LinearAlgebra: norm, mul! import SpecialFunctions: erf, erfc diff --git a/src/getset.jl b/src/getset.jl index 5030ad83..b3d575d7 100644 --- a/src/getset.jl +++ b/src/getset.jl @@ -120,6 +120,20 @@ end lowget(t, idx, param, params) = error("Invalid monomial index specified. Please use ONE of variable/parameter index, index by order, or index by sparse monomial.") +# --- length --- +len(t::Ptr{RTPSA}) = mad_tpsa_len(t) +len(t::Ptr{CTPSA}) = mad_ctpsa_len(t) + +""" + length(t::Union{TPS,ComplexTPS} + +Returns the maximum number of monomials (including the scalar part) +in the `TPS`/`ComplexTPS` given its `Descriptor`. +""" +length(t::Union{TPS,ComplexTPS}) = len(t.tpsa) + +firstindex(t::Union{TPS,ComplexTPS}) = 0 +lastindex(t::Union{TPS,ComplexTPS}) = length(t)-1 # --- Slicing (getter) --- diff --git a/src/operators.jl b/src/operators.jl index cd64a228..fd8c45dc 100644 --- a/src/operators.jl +++ b/src/operators.jl @@ -56,6 +56,16 @@ for (fname, felt) in ((:zeros, :zero), (:ones, :one)) end end +# --- rand --- +function rand(::Type{T}; use::Union{Descriptor,TPS,ComplexTPS}=GTPSA.desc_current) where {T<:Union{TPS,ComplexTPS}} + t = T(use=use) + len = length(t) + for i=0:len-1 + t[i] = rand(numtype(T)) + end + return t +end + # --- Unary --- # TPS: function +(t1::TPS)::TPS From 84ee72ce502b83dc58c645479140d34c68e2bbde Mon Sep 17 00:00:00 2001 From: mattsignorelli Date: Mon, 29 Apr 2024 14:35:34 -0400 Subject: [PATCH 25/29] random TPS generator --- src/operators.jl | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/operators.jl b/src/operators.jl index fd8c45dc..29039425 100644 --- a/src/operators.jl +++ b/src/operators.jl @@ -57,6 +57,11 @@ for (fname, felt) in ((:zeros, :zero), (:ones, :one)) end # --- rand --- +""" + rand(::Type{T}; use::Union{Descriptor,TPS,ComplexTPS}=GTPSA.desc_current) where {T<:Union{TPS,ComplexTPS}} + +Generate a `TPS`/`ComplexTPS` with all random coefficients. +""" function rand(::Type{T}; use::Union{Descriptor,TPS,ComplexTPS}=GTPSA.desc_current) where {T<:Union{TPS,ComplexTPS}} t = T(use=use) len = length(t) From f74bef037552ed56f27114e4693c4f57225082a5 Mon Sep 17 00:00:00 2001 From: mattsignorelli <113714234+mattsignorelli@users.noreply.github.com> Date: Mon, 29 Apr 2024 14:36:35 -0400 Subject: [PATCH 26/29] Update Project.toml --- Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Project.toml b/Project.toml index e3bfc6b8..ad62a961 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ name = "GTPSA" uuid = "b27dd330-f138-47c5-815b-40db9dd9b6e8" authors = ["Matt Signorelli"] -version = "0.5.1" +version = "0.5.2" [deps] GTPSA_jll = "a4739e29-4b97-5c0b-bbcf-46f08034c990" From 352062264d6478df8705783b73d30b7c800cf81e Mon Sep 17 00:00:00 2001 From: mattsignorelli Date: Fri, 3 May 2024 14:42:49 -0400 Subject: [PATCH 27/29] new GTPSA --- Project.toml | 4 +- README.md | 12 +- benchmark/track.jl | 75 +++--- docs/src/devel.md | 543 +++++++++++++++++++++-------------------- docs/src/index.md | 10 +- src/low_level/ctpsa.jl | 77 +++++- src/low_level/rtpsa.jl | 68 +++++- test/compare_MAD.jl | 15 +- 8 files changed, 463 insertions(+), 341 deletions(-) diff --git a/Project.toml b/Project.toml index e3bfc6b8..03f54a36 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ name = "GTPSA" uuid = "b27dd330-f138-47c5-815b-40db9dd9b6e8" authors = ["Matt Signorelli"] -version = "0.5.1" +version = "0.6" [deps] GTPSA_jll = "a4739e29-4b97-5c0b-bbcf-46f08034c990" @@ -11,7 +11,7 @@ Printf = "de0858da-6303-5e67-8744-51eddeeeb8d7" SpecialFunctions = "276daf66-3868-5448-9aa4-cd146d93841b" [compat] -GTPSA_jll = "1.2.1" +GTPSA_jll = "1.3" PrettyTables = "2" SpecialFunctions = "2.3.1" julia = "1.9" diff --git a/README.md b/README.md index 7a367de0..e82daf3a 100644 --- a/README.md +++ b/README.md @@ -4,18 +4,14 @@ [![Build Status](https://github.com/bmad-sim/GTPSA.jl/actions/workflows/CI.yml/badge.svg?branch=main)](https://github.com/bmad-sim/GTPSA.jl/actions/workflows/CI.yml?query=branch%3Amain) ## Overview - This package provides a full-featured Julia interface to the [Generalised Truncated Power Series Algebra (GTPSA) library](https://mad.web.cern.ch/mad/releases/madng/html/mad_mod_diffalg.html), which computes Taylor expansions, or Truncated Power Series (TPSs) of real and complex multivariable functions to arbitrary orders. -Truncated Power Series Algebra (TPSA) performs forward-mode automatic differentation (AD) similar to the dual-number implementation of `ForwardDiff.jl`. However, instead of nesting derivatives for higher orders, TPSA naturally extends to arbitary orders by directly using the power series expansions. This, paired with a highly optimized monomial indexing function/storage for propagating the partial derivatives, makes `GTPSA.jl` significantly faster for 2nd-order calculations and above (for 1st-order -calculations the performance is similar to `ForwardDiff.jl`). -See the [`benchmark/track.jl`](https://github.com/bmad-sim/GTPSA.jl/blob/main/benchmark/track.jl) example for a speed comparison of `GTPSA.jl` with `ForwardDiff.jl` in calculating the partial derivatives for a system with 58 inputs and 6 outputs. **In this example, GTPSA was nearly x3 faster than ForwardDiff to 2nd order, and x15 faster to 3rd order.** +Truncated Power Series Algebra (TPSA) performs forward-mode automatic differentation (AD) similar to the dual-number implementation of `ForwardDiff.jl`. However, instead of nesting derivatives for higher orders, TPSA naturally extends to arbitary orders by directly using the power series expansions. This, paired with a highly optimized monomial indexing function/storage for propagating the partial derivatives, makes `GTPSA.jl` significantly faster for 2nd-order calculations and above (for 1st-order calculations the performance is similar to `ForwardDiff.jl`).See the [`benchmark/track.jl`](https://github.com/bmad-sim/GTPSA.jl/blob/main/benchmark/track.jl) example for a speed comparison of `GTPSA.jl` with `ForwardDiff.jl` in calculating the partial derivatives for a system with 58 inputs and 6 outputs. **In this example, GTPSA was x3.3 faster than ForwardDiff to 2nd order, and x18.5 faster to 3rd order.** GTPSA provides several advantages over current Julia AD packages: -1. **Speed**: `GTPSA.jl` is significantly faster than `ForwardDiff.jl` for 2nd-order calculations and above, and has similar performance at 1st-order -2. **Custom Orders in Individual Variables**: Other packages use a single maximum order for all variables. With GTPSA, the -maximum order can be set differently for different variables. For example, computing the Taylor expansion of $f(x_1,x_2)$ to 2nd order in $x_1$ and 6th order in $x_2$ is possible +1. **Speed**: `GTPSA.jl` is significantly faster than `ForwardDiff.jl` for 2nd-order calculations and above, and has very similar performance at 1st-order +2. **Custom Orders in Individual Variables**: Other packages use a single maximum order for all variables. With GTPSA, the maximum order can be set differently for individual variables, as well as for a separate part of the monomial. For example, computing the Taylor expansion of $f(x_1,x_2)$ to 2nd order in $x_1$ and 6th order in $x_2$ is possible 3. **Complex Numbers**: GTPSA natively supports complex numbers and allows for mixing of complex and real truncated power series 4. **Distinction Between State Variables and Parameters**: Distinguishing between dependent variables and parameters in the solution of a differential equation expressed as a power series in the dependent variables/parameters can be advantageous in analysis @@ -42,7 +38,7 @@ x = vars() # Manipulate the TPSs as you would any other mathematical variable in Julia f = cos(x[1]) + im*sin(x[2]) -# This creates a new TPS called f +# f is a new ComplexTPS ``` Note that scalars do not need to be defined as TPSs when writing expressions. Running `print(f)` gives the output diff --git a/benchmark/track.jl b/benchmark/track.jl index 9d79c59a..caf6973a 100644 --- a/benchmark/track.jl +++ b/benchmark/track.jl @@ -2,34 +2,35 @@ using GTPSA using ForwardDiff using BenchmarkTools: @btime, @benchmark -# As of 02/19/2024 (Julia v1.10.1) on Mac M2 Ultra: Comparison with GTPSA for 58 inputs and 6 outputs +# As of 05/03/2024, Julia v1.10.2 on Mac M2 Ultra: Comparison with GTPSA for 58 inputs and 6 outputs +# Numbers calculated using BenchmarkTools.@btime # # 3rd Order --------------------------------------------------------- # Using the @FastGTPSA macro: -# GTPSA: 271.137 ms -# ForwardDiff: 4.004 s +# GTPSA: 227.111 ms +# ForwardDiff: 4.212 s # # Without the @FastGTPSA macro (including ForwardDiff as control): -# GTPSA: 415.567 ms -# ForwardDiff: 3.916 s +# GTPSA: 371.465 ms +# ForwardDiff: 4.096 s # # 2nd Order --------------------------------------------------------- # Using the @FastGTPSA macro: -# GTPSA: 8.599 ms -# ForwardDiff: 23.984 ms +# GTPSA: 7.024 ms +# ForwardDiff: 23.417 ms # # Without the @FastGTPSA macro (including ForwardDiff as control): -# GTPSA: 17.141 ms -# ForwardDiff: 23.391 ms +# GTPSA: 15.594 ms +# ForwardDiff: 23.318 ms # # 1st Order --------------------------------------------------------- # Using the @FastGTPSA macro: -# GTPSA: 327.458 μs -# ForwardDiff: 189.417 μs +# GTPSA: 280.542 μs +# ForwardDiff: 188.792 μs # # Without the @FastGTPSA macro (including ForwardDiff as control): -# GTPSA: 707.916 μs -# ForwardDiff: 161.833 μs +# GTPSA: 697.625 μs +# ForwardDiff: 161.125 μs # # Note that @FastGTPSA is transparent to all types except TPS/ComplexTPS, so it can be # inserted into functions while still maintaining generic code, as shown here @@ -38,13 +39,13 @@ function track_qf(z0, k1, hkick) z = Vector{promote_type(eltype(z0),typeof(k1),typeof(hkick))}(undef, length(z0)) lbend=0.1 - L = @FastGTPSA 0.5/(1.0+z0[6]) - h = @FastGTPSA -L*(z0[2]^2+k1*z0[1]^2+ z0[4]^2-k1*z0[3]^2)/(1.0+z0[6])/2.0 - z[1] = @FastGTPSA cos(sqrt(k1)*L)*z0[1]+1/sqrt(k1)*sin(sqrt(k1)*L)*z0[2] - z[2] = @FastGTPSA -sqrt(k1)*sin(sqrt(k1)*L)*z0[1]+cos(sqrt(k1)*L)*z0[2]+hkick+lbend*z0[6] - z[3] = @FastGTPSA cosh(sqrt(k1)*L)*z0[3]+1/sqrt(k1)*sinh(sqrt(k1)*L)*z0[4] - z[4] = @FastGTPSA sqrt(k1)*sinh(sqrt(k1)*L)*z0[3]+cosh(sqrt(k1)*L)*z0[4] - z[5] = @FastGTPSA z0[5]+h-lbend*z[1] + L = 0.5/(1.0+z0[6]) + h = -L*(z0[2]^2+k1*z0[1]^2+ z0[4]^2-k1*z0[3]^2)/(1.0+z0[6])/2.0 + z[1] = cos(sqrt(k1)*L)*z0[1]+1/sqrt(k1)*sin(sqrt(k1)*L)*z0[2] + z[2] = -sqrt(k1)*sin(sqrt(k1)*L)*z0[1]+cos(sqrt(k1)*L)*z0[2]+hkick+lbend*z0[6] + z[3] = cosh(sqrt(k1)*L)*z0[3]+1/sqrt(k1)*sinh(sqrt(k1)*L)*z0[4] + z[4] = sqrt(k1)*sinh(sqrt(k1)*L)*z0[3]+cosh(sqrt(k1)*L)*z0[4] + z[5] = z0[5]+h-lbend*z[1] z[6] = +z0[6] return z end @@ -52,13 +53,13 @@ end function track_qd(z0, k1, vkick) z = Vector{promote_type(eltype(z0),typeof(k1),typeof(vkick))}(undef, length(z0)) - L = @FastGTPSA 0.5/(1.0+z0[6]) - h = @FastGTPSA -L*(z0[2]^2-k1*z0[1]^2+z0[4]^2+k1*z0[3]^2)/(1.0+z0[6])/2.0 - z[1] = @FastGTPSA cosh(sqrt(k1)*L)*z0[1]+1/sqrt(k1)*sinh(sqrt(k1)*L)*z0[2] - z[2] = @FastGTPSA sqrt(k1)*sinh(sqrt(k1)*L)*z0[1]+cosh(sqrt(k1)*L)*z0[2] - z[3] = @FastGTPSA cos(sqrt(k1)*L)*z0[3]+1/sqrt(k1)*sin(sqrt(k1)*L)*z0[4] - z[4] = @FastGTPSA -sqrt(k1)*sin(sqrt(k1)*L)*z0[3]+cos(sqrt(k1)*L)*z0[4]+vkick - z[5] = @FastGTPSA z0[5]+h + L = 0.5/(1.0+z0[6]) + h = -L*(z0[2]^2-k1*z0[1]^2+z0[4]^2+k1*z0[3]^2)/(1.0+z0[6])/2.0 + z[1] = cosh(sqrt(k1)*L)*z0[1]+1/sqrt(k1)*sinh(sqrt(k1)*L)*z0[2] + z[2] = sqrt(k1)*sinh(sqrt(k1)*L)*z0[1]+cosh(sqrt(k1)*L)*z0[2] + z[3] = cos(sqrt(k1)*L)*z0[3]+1/sqrt(k1)*sin(sqrt(k1)*L)*z0[4] + z[4] = -sqrt(k1)*sin(sqrt(k1)*L)*z0[3]+cos(sqrt(k1)*L)*z0[4]+vkick + z[5] = z0[5]+h z[6] = +z0[6] return z end @@ -67,11 +68,11 @@ function track_drift(z0) z = Vector{eltype(z0)}(undef, length(z0)) L = 0.75 - z[1] = @FastGTPSA z0[1]+z0[2]*L/(1.0+z0[6]) + z[1] = z0[1]+z0[2]*L/(1.0+z0[6]) z[2] = +z0[2] - z[3] = @FastGTPSA z0[3]+z0[4]*L/(1.0+z0[6]) + z[3] = z0[3]+z0[4]*L/(1.0+z0[6]) z[4] = +z0[4] - z[5] = @FastGTPSA z0[5]-L*((z0[2]^2)+(z0[4]^2))/(1.0+z0[6])^2/2.0 + z[5] = z0[5]-L*((z0[2]^2)+(z0[4]^2))/(1.0+z0[6])^2/2.0 z[6] = +z0[6] return z end @@ -84,7 +85,7 @@ function track_cav(z0) z[3] = +z0[3] z[4] = +z0[4] z[5] = +z0[5] - z[6] = @FastGTPSA z0[6]+0.0001*z0[5] + z[6] = z0[6]+0.0001*z0[5] return z end @@ -92,9 +93,9 @@ function track_sextupole(z0, k2l) z = Vector{promote_type(eltype(z0),typeof(k2l))}(undef, length(z0)) z[1] = +z0[1] - z[2] = @FastGTPSA z0[2]-k2l*(z0[1]^2-z0[3]^2) + z[2] = z0[2]-k2l*(z0[1]^2-z0[3]^2) z[3] = +z0[3] - z[4] = @FastGTPSA z0[4]+k2l*2.0*z0[1]*z0[3] + z[4] = z0[4]+k2l*2.0*z0[1]*z0[3] z[5] = +z0[5] z[6] = +z0[6] return z @@ -119,7 +120,7 @@ function track_ring(z0, k1=0.36, k2l=1.2, kick=zeros(50)) end function benchmark_GTPSA() - d = Descriptor(6,2,52,2) + d = Descriptor(6,1,52,1) z = vars() k = params() map = track_ring(z, 0.36+k[1], 1.2+k[2], k[3:end]) @@ -129,10 +130,10 @@ end function benchmark_ForwardDiff() m(z) = track_ring([z[1], z[2], z[3], z[4], z[5], z[6]], 0.36+z[7], 1.2+z[8], z[9:end]) j = Array{Float64}(undef,6,58) - h = Array{Float64}(undef,348,58) + #h = Array{Float64}(undef,348,58) #c = Array{Float64}(undef,20184,58) ForwardDiff.jacobian!(j, m, zeros(58)) - ForwardDiff.jacobian!(h, z->ForwardDiff.jacobian(z->m(z), z), zeros(58)) + #ForwardDiff.jacobian!(h, z->ForwardDiff.jacobian(z->m(z), z), zeros(58)) #ForwardDiff.jacobian!(c, z->ForwardDiff.jacobian(z->ForwardDiff.jacobian(z->m(z), z), z), zeros(58)) - return j, h #, c + return j#, h#, c end diff --git a/docs/src/devel.md b/docs/src/devel.md index 4f597ba8..085acfb4 100644 --- a/docs/src/devel.md +++ b/docs/src/devel.md @@ -36,334 +36,349 @@ t1_jl = unsafe_load(Base.unsafe_convert(Ptr{Ptr{RTPSA}}, desc.t), 1) ## Monomial ```@docs -GTPSA.mad_mono_str! -GTPSA.mad_mono_prt! -GTPSA.mad_mono_fill! +GTPSA.mad_mono_add! +GTPSA.mad_mono_cat! +GTPSA.mad_mono_cmp GTPSA.mad_mono_copy! -GTPSA.mad_mono_min +GTPSA.mad_mono_eq +GTPSA.mad_mono_eqn +GTPSA.mad_mono_fill! +GTPSA.mad_mono_le +GTPSA.mad_mono_lt GTPSA.mad_mono_max +GTPSA.mad_mono_min GTPSA.mad_mono_ord GTPSA.mad_mono_ordp GTPSA.mad_mono_ordpf -GTPSA.mad_mono_eq -GTPSA.mad_mono_lt -GTPSA.mad_mono_le -GTPSA.mad_mono_cmp +GTPSA.mad_mono_print +GTPSA.mad_mono_prt! GTPSA.mad_mono_rcmp -GTPSA.mad_mono_add! -GTPSA.mad_mono_sub! -GTPSA.mad_mono_cat! GTPSA.mad_mono_rev! -GTPSA.mad_mono_print +GTPSA.mad_mono_str! +GTPSA.mad_mono_sub! ``` ## Desc ```@docs GTPSA.Desc -GTPSA.mad_desc_newv -GTPSA.mad_desc_newvp -GTPSA.mad_desc_newvpo GTPSA.mad_desc_del! GTPSA.mad_desc_getnv! -GTPSA.mad_desc_maxord -GTPSA.mad_desc_maxlen -GTPSA.mad_desc_gtrunc! -GTPSA.mad_desc_isvalids -GTPSA.mad_desc_isvalidm -GTPSA.mad_desc_isvalidsm -GTPSA.mad_desc_idxs GTPSA.mad_desc_idxm +GTPSA.mad_desc_idxs GTPSA.mad_desc_idxsm -GTPSA.mad_desc_nxtbyvar -GTPSA.mad_desc_nxtbyord -GTPSA.mad_desc_mono! GTPSA.mad_desc_info +GTPSA.mad_desc_isvalidm +GTPSA.mad_desc_isvalids +GTPSA.mad_desc_isvalidsm +GTPSA.mad_desc_maxlen +GTPSA.mad_desc_maxord +GTPSA.mad_desc_mono! +GTPSA.mad_desc_newv +GTPSA.mad_desc_newvp +GTPSA.mad_desc_newvpo +GTPSA.mad_desc_nxtbyord +GTPSA.mad_desc_nxtbyvar ``` ## RTPSA ```@docs GTPSA.RTPSA -GTPSA.mad_tpsa_newd -GTPSA.mad_tpsa_new -GTPSA.mad_tpsa_del! -GTPSA.mad_tpsa_desc -GTPSA.mad_tpsa_uid! -GTPSA.mad_tpsa_len -GTPSA.mad_tpsa_nam -GTPSA.mad_tpsa_ord -GTPSA.mad_tpsa_ordv -GTPSA.mad_tpsa_ordn -GTPSA.mad_tpsa_copy! -GTPSA.mad_tpsa_sclord! -GTPSA.mad_tpsa_getord! -GTPSA.mad_tpsa_cutord! -GTPSA.mad_tpsa_maxord! -GTPSA.mad_tpsa_convert! -GTPSA.mad_tpsa_setvar! -GTPSA.mad_tpsa_setval! -GTPSA.mad_tpsa_setnam! -GTPSA.mad_tpsa_clear! -GTPSA.mad_tpsa_isnul -GTPSA.mad_tpsa_mono! -GTPSA.mad_tpsa_idxs -GTPSA.mad_tpsa_idxm -GTPSA.mad_tpsa_idxsm -GTPSA.mad_tpsa_cycle! -GTPSA.mad_tpsa_get0 -GTPSA.mad_tpsa_geti -GTPSA.mad_tpsa_gets -GTPSA.mad_tpsa_getm -GTPSA.mad_tpsa_getsm -GTPSA.mad_tpsa_set0! -GTPSA.mad_tpsa_seti! -GTPSA.mad_tpsa_sets! -GTPSA.mad_tpsa_setm! -GTPSA.mad_tpsa_setsm! -GTPSA.mad_tpsa_getv! -GTPSA.mad_tpsa_setv! -GTPSA.mad_tpsa_equ -GTPSA.mad_tpsa_dif! -GTPSA.mad_tpsa_add! -GTPSA.mad_tpsa_sub! -GTPSA.mad_tpsa_mul! -GTPSA.mad_tpsa_div! -GTPSA.mad_tpsa_pow! -GTPSA.mad_tpsa_powi! -GTPSA.mad_tpsa_pown! -GTPSA.mad_tpsa_nrm GTPSA.mad_tpsa_abs! -GTPSA.mad_tpsa_sqrt! -GTPSA.mad_tpsa_exp! -GTPSA.mad_tpsa_log! -GTPSA.mad_tpsa_sincos! -GTPSA.mad_tpsa_sin! -GTPSA.mad_tpsa_cos! -GTPSA.mad_tpsa_tan! -GTPSA.mad_tpsa_cot! -GTPSA.mad_tpsa_sinc! -GTPSA.mad_tpsa_sincosh! -GTPSA.mad_tpsa_sinh! -GTPSA.mad_tpsa_cosh! -GTPSA.mad_tpsa_tanh! -GTPSA.mad_tpsa_coth! -GTPSA.mad_tpsa_sinhc! -GTPSA.mad_tpsa_asin! +GTPSA.mad_tpsa_acc! GTPSA.mad_tpsa_acos! -GTPSA.mad_tpsa_atan! +GTPSA.mad_tpsa_acosh! GTPSA.mad_tpsa_acot! +GTPSA.mad_tpsa_acoth! +GTPSA.mad_tpsa_add! +GTPSA.mad_tpsa_asin! GTPSA.mad_tpsa_asinc! GTPSA.mad_tpsa_asinh! -GTPSA.mad_tpsa_acosh! -GTPSA.mad_tpsa_atanh! -GTPSA.mad_tpsa_acoth! GTPSA.mad_tpsa_asinhc! -GTPSA.mad_tpsa_erf! -GTPSA.mad_tpsa_erfc! -GTPSA.mad_tpsa_acc! -GTPSA.mad_tpsa_scl! -GTPSA.mad_tpsa_inv! -GTPSA.mad_tpsa_invsqrt! -GTPSA.mad_tpsa_unit! +GTPSA.mad_tpsa_atan! GTPSA.mad_tpsa_atan2! -GTPSA.mad_tpsa_hypot! -GTPSA.mad_tpsa_hypot3! -GTPSA.mad_tpsa_integ! -GTPSA.mad_tpsa_deriv! -GTPSA.mad_tpsa_derivm! -GTPSA.mad_tpsa_poisbra! -GTPSA.mad_tpsa_taylor! +GTPSA.mad_tpsa_atanh! +GTPSA.mad_tpsa_ax2pby2pcz2! GTPSA.mad_tpsa_axpb! GTPSA.mad_tpsa_axpbypc! +GTPSA.mad_tpsa_axpsqrtbpcx2! GTPSA.mad_tpsa_axypb! -GTPSA.mad_tpsa_axypbzpc! GTPSA.mad_tpsa_axypbvwpc! -GTPSA.mad_tpsa_ax2pby2pcz2! -GTPSA.mad_tpsa_axpsqrtbpcx2! -GTPSA.mad_tpsa_logaxpsqrtbpcx2! -GTPSA.mad_tpsa_logxdy! -GTPSA.mad_tpsa_vec2fld! -GTPSA.mad_tpsa_fld2vec! +GTPSA.mad_tpsa_axypbzpc! +GTPSA.mad_tpsa_clear! +GTPSA.mad_tpsa_clrdensity! +GTPSA.mad_tpsa_clrord! +GTPSA.mad_tpsa_compose! +GTPSA.mad_tpsa_convert! +GTPSA.mad_tpsa_copy! +GTPSA.mad_tpsa_cos! +GTPSA.mad_tpsa_cosh! +GTPSA.mad_tpsa_cot! +GTPSA.mad_tpsa_coth! +GTPSA.mad_tpsa_cpyi! +GTPSA.mad_tpsa_cpym! +GTPSA.mad_tpsa_cpys! +GTPSA.mad_tpsa_cpysm! +GTPSA.mad_tpsa_cutord! +GTPSA.mad_tpsa_cycle! +GTPSA.mad_tpsa_debug +GTPSA.mad_tpsa_del! +GTPSA.mad_tpsa_density +GTPSA.mad_tpsa_deriv! +GTPSA.mad_tpsa_derivm! +GTPSA.mad_tpsa_desc +GTPSA.mad_tpsa_dif! +GTPSA.mad_tpsa_div! +GTPSA.mad_tpsa_equ +GTPSA.mad_tpsa_erf! +GTPSA.mad_tpsa_erfc! +GTPSA.mad_tpsa_eval! +GTPSA.mad_tpsa_exp! +GTPSA.mad_tpsa_exppb! GTPSA.mad_tpsa_fgrad! +GTPSA.mad_tpsa_fld2vec! +GTPSA.mad_tpsa_geti +GTPSA.mad_tpsa_getm +GTPSA.mad_tpsa_getord! +GTPSA.mad_tpsa_gets +GTPSA.mad_tpsa_getsm +GTPSA.mad_tpsa_getv! +GTPSA.mad_tpsa_hypot! +GTPSA.mad_tpsa_hypot3! +GTPSA.mad_tpsa_idxm +GTPSA.mad_tpsa_idxs +GTPSA.mad_tpsa_idxsm +GTPSA.mad_tpsa_init! +GTPSA.mad_tpsa_integ! +GTPSA.mad_tpsa_inv! +GTPSA.mad_tpsa_invsqrt! +GTPSA.mad_tpsa_isnul +GTPSA.mad_tpsa_isval +GTPSA.mad_tpsa_isvalid +GTPSA.mad_tpsa_len GTPSA.mad_tpsa_liebra! -GTPSA.mad_tpsa_exppb! +GTPSA.mad_tpsa_log! +GTPSA.mad_tpsa_logaxpsqrtbpcx2! GTPSA.mad_tpsa_logpb! -GTPSA.mad_tpsa_mnrm +GTPSA.mad_tpsa_logxdy! +GTPSA.mad_tpsa_maxord! +GTPSA.mad_tpsa_mconv! GTPSA.mad_tpsa_minv! +GTPSA.mad_tpsa_mnrm +GTPSA.mad_tpsa_mo! +GTPSA.mad_tpsa_mono! +GTPSA.mad_tpsa_mord +GTPSA.mad_tpsa_mul! +GTPSA.mad_tpsa_nam +GTPSA.mad_tpsa_new +GTPSA.mad_tpsa_newd +GTPSA.mad_tpsa_nrm +GTPSA.mad_tpsa_ord +GTPSA.mad_tpsa_ordv GTPSA.mad_tpsa_pminv! -GTPSA.mad_tpsa_compose! -GTPSA.mad_tpsa_translate! -GTPSA.mad_tpsa_eval! -GTPSA.mad_tpsa_mconv! +GTPSA.mad_tpsa_poisbra! +GTPSA.mad_tpsa_pow! +GTPSA.mad_tpsa_powi! +GTPSA.mad_tpsa_pown! GTPSA.mad_tpsa_print +GTPSA.mad_tpsa_prtdensity GTPSA.mad_tpsa_scan -GTPSA.mad_tpsa_scan_hdr GTPSA.mad_tpsa_scan_coef! -GTPSA.mad_tpsa_debug -GTPSA.mad_tpsa_isvalid -GTPSA.mad_tpsa_init! +GTPSA.mad_tpsa_scan_hdr +GTPSA.mad_tpsa_scl! +GTPSA.mad_tpsa_sclord! +GTPSA.mad_tpsa_seti! +GTPSA.mad_tpsa_setm! +GTPSA.mad_tpsa_setprm! +GTPSA.mad_tpsa_sets! +GTPSA.mad_tpsa_setsm! +GTPSA.mad_tpsa_setv! +GTPSA.mad_tpsa_setval! +GTPSA.mad_tpsa_setvar! +GTPSA.mad_tpsa_sin! +GTPSA.mad_tpsa_sinc! +GTPSA.mad_tpsa_sincos! +GTPSA.mad_tpsa_sincosh! +GTPSA.mad_tpsa_sinh! +GTPSA.mad_tpsa_sinhc! +GTPSA.mad_tpsa_sqrt! +GTPSA.mad_tpsa_sub! +GTPSA.mad_tpsa_tan! +GTPSA.mad_tpsa_tanh! +GTPSA.mad_tpsa_taylor! +GTPSA.mad_tpsa_translate! +GTPSA.mad_tpsa_uid! +GTPSA.mad_tpsa_unit! +GTPSA.mad_tpsa_update! +GTPSA.mad_tpsa_vec2fld! ``` # CTPSA ```@docs GTPSA.CTPSA -GTPSA.mad_ctpsa_newd -GTPSA.mad_ctpsa_new -GTPSA.mad_ctpsa_del! -GTPSA.mad_ctpsa_desc -GTPSA.mad_ctpsa_uid! -GTPSA.mad_ctpsa_len -GTPSA.mad_ctpsa_nam -GTPSA.mad_ctpsa_ord -GTPSA.mad_ctpsa_ordv -GTPSA.mad_ctpsa_ordn -GTPSA.mad_ctpsa_copy! -GTPSA.mad_ctpsa_sclord! -GTPSA.mad_ctpsa_getord! -GTPSA.mad_ctpsa_cutord! -GTPSA.mad_ctpsa_maxord -GTPSA.mad_ctpsa_convert! -GTPSA.mad_ctpsa_setvar! -GTPSA.mad_ctpsa_setvar_r! -GTPSA.mad_ctpsa_setval! -GTPSA.mad_ctpsa_setval_r! -GTPSA.mad_ctpsa_setnam! -GTPSA.mad_ctpsa_clear! -GTPSA.mad_ctpsa_isnul -GTPSA.mad_ctpsa_cplx! -GTPSA.mad_ctpsa_real! -GTPSA.mad_ctpsa_imag! +GTPSA.mad_ctpsa_acc! +GTPSA.mad_ctpsa_acc_r! +GTPSA.mad_ctpsa_acos! +GTPSA.mad_ctpsa_acosh! +GTPSA.mad_ctpsa_acot! +GTPSA.mad_ctpsa_acoth! +GTPSA.mad_ctpsa_add! +GTPSA.mad_ctpsa_addt! +GTPSA.mad_ctpsa_asin! +GTPSA.mad_ctpsa_asinc! +GTPSA.mad_ctpsa_asinh! +GTPSA.mad_ctpsa_asinhc! +GTPSA.mad_ctpsa_atan! +GTPSA.mad_ctpsa_atanh! +GTPSA.mad_ctpsa_ax2pby2pcz2! +GTPSA.mad_ctpsa_ax2pby2pcz2_r! +GTPSA.mad_ctpsa_axpb! +GTPSA.mad_ctpsa_axpb_r! +GTPSA.mad_ctpsa_axpbypc! +GTPSA.mad_ctpsa_axpbypc_r! +GTPSA.mad_ctpsa_axpsqrtbpcx2! +GTPSA.mad_ctpsa_axpsqrtbpcx2_r! +GTPSA.mad_ctpsa_axypb! +GTPSA.mad_ctpsa_axypb_r! +GTPSA.mad_ctpsa_axypbvwpc! +GTPSA.mad_ctpsa_axypbvwpc_r! +GTPSA.mad_ctpsa_axypbzpc! +GTPSA.mad_ctpsa_axypbzpc_r! GTPSA.mad_ctpsa_cabs! GTPSA.mad_ctpsa_carg! -GTPSA.mad_ctpsa_unit! -GTPSA.mad_ctpsa_rect! -GTPSA.mad_ctpsa_polar! -GTPSA.mad_ctpsa_mono! -GTPSA.mad_ctpsa_idxs -GTPSA.mad_ctpsa_idxm -GTPSA.mad_ctpsa_idxsm +GTPSA.mad_ctpsa_clear! +GTPSA.mad_ctpsa_clrord! +GTPSA.mad_ctpsa_compose! +GTPSA.mad_ctpsa_conj! +GTPSA.mad_ctpsa_convert! +GTPSA.mad_ctpsa_copy! +GTPSA.mad_ctpsa_cos! +GTPSA.mad_ctpsa_cosh! +GTPSA.mad_ctpsa_cot! +GTPSA.mad_ctpsa_coth! +GTPSA.mad_ctpsa_cplx! +GTPSA.mad_ctpsa_cpyi! +GTPSA.mad_ctpsa_cpym! +GTPSA.mad_ctpsa_cpys! +GTPSA.mad_ctpsa_cpysm! +GTPSA.mad_ctpsa_cutord! GTPSA.mad_ctpsa_cycle! -GTPSA.mad_ctpsa_get0 +GTPSA.mad_ctpsa_debug +GTPSA.mad_ctpsa_del! +GTPSA.mad_ctpsa_density +GTPSA.mad_ctpsa_deriv! +GTPSA.mad_ctpsa_derivm! +GTPSA.mad_ctpsa_desc +GTPSA.mad_ctpsa_dif! +GTPSA.mad_ctpsa_dift! +GTPSA.mad_ctpsa_div! +GTPSA.mad_ctpsa_divt! +GTPSA.mad_ctpsa_equ +GTPSA.mad_ctpsa_equt +GTPSA.mad_ctpsa_erf! +GTPSA.mad_ctpsa_erfc! +GTPSA.mad_ctpsa_eval! +GTPSA.mad_ctpsa_exp! +GTPSA.mad_ctpsa_exppb! +GTPSA.mad_ctpsa_fgrad! +GTPSA.mad_ctpsa_fld2vec! GTPSA.mad_ctpsa_geti -GTPSA.mad_ctpsa_gets -GTPSA.mad_ctpsa_getm -GTPSA.mad_ctpsa_getsm -GTPSA.mad_ctpsa_set0! -GTPSA.mad_ctpsa_seti! -GTPSA.mad_ctpsa_sets! -GTPSA.mad_ctpsa_setm! -GTPSA.mad_ctpsa_setsm! -GTPSA.mad_ctpsa_get0_r! GTPSA.mad_ctpsa_geti_r! -GTPSA.mad_ctpsa_gets_r! +GTPSA.mad_ctpsa_getm GTPSA.mad_ctpsa_getm_r! +GTPSA.mad_ctpsa_getord! +GTPSA.mad_ctpsa_gets +GTPSA.mad_ctpsa_gets_r! +GTPSA.mad_ctpsa_getsm GTPSA.mad_ctpsa_getsm_r! -GTPSA.mad_ctpsa_set0_r! -GTPSA.mad_ctpsa_seti_r! -GTPSA.mad_ctpsa_sets_r! -GTPSA.mad_ctpsa_setm_r! -GTPSA.mad_ctpsa_setsm_r! GTPSA.mad_ctpsa_getv! -GTPSA.mad_ctpsa_setv! -GTPSA.mad_ctpsa_equ -GTPSA.mad_ctpsa_dif! -GTPSA.mad_ctpsa_add! -GTPSA.mad_ctpsa_sub! +GTPSA.mad_ctpsa_hypot! +GTPSA.mad_ctpsa_hypot3! +GTPSA.mad_ctpsa_idxm +GTPSA.mad_ctpsa_idxs +GTPSA.mad_ctpsa_idxsm +GTPSA.mad_ctpsa_imag! +GTPSA.mad_ctpsa_init! +GTPSA.mad_ctpsa_integ! +GTPSA.mad_ctpsa_inv! +GTPSA.mad_ctpsa_inv_r! +GTPSA.mad_ctpsa_invsqrt! +GTPSA.mad_ctpsa_invsqrt_r! +GTPSA.mad_ctpsa_isnul +GTPSA.mad_ctpsa_isval +GTPSA.mad_ctpsa_isvalid +GTPSA.mad_ctpsa_len +GTPSA.mad_ctpsa_liebra! +GTPSA.mad_ctpsa_log! +GTPSA.mad_ctpsa_logaxpsqrtbpcx2! +GTPSA.mad_ctpsa_logaxpsqrtbpcx2_r! +GTPSA.mad_ctpsa_logpb! +GTPSA.mad_ctpsa_logxdy! +GTPSA.mad_ctpsa_maxord +GTPSA.mad_ctpsa_mconv! +GTPSA.mad_ctpsa_minv! +GTPSA.mad_ctpsa_mnrm +GTPSA.mad_ctpsa_mo! +GTPSA.mad_ctpsa_mono! +GTPSA.mad_ctpsa_mord GTPSA.mad_ctpsa_mul! -GTPSA.mad_ctpsa_div! +GTPSA.mad_ctpsa_mult! +GTPSA.mad_ctpsa_nam +GTPSA.mad_ctpsa_new +GTPSA.mad_ctpsa_newd +GTPSA.mad_ctpsa_nrm +GTPSA.mad_ctpsa_ord +GTPSA.mad_ctpsa_ordv +GTPSA.mad_ctpsa_pminv! +GTPSA.mad_ctpsa_poisbra! +GTPSA.mad_ctpsa_poisbrat! +GTPSA.mad_ctpsa_polar! GTPSA.mad_ctpsa_pow! GTPSA.mad_ctpsa_powi! GTPSA.mad_ctpsa_pown! GTPSA.mad_ctpsa_pown_r! -GTPSA.mad_ctpsa_equt -GTPSA.mad_ctpsa_dift! -GTPSA.mad_ctpsa_tdif! -GTPSA.mad_ctpsa_addt! -GTPSA.mad_ctpsa_subt! -GTPSA.mad_ctpsa_tsub! -GTPSA.mad_ctpsa_mult! -GTPSA.mad_ctpsa_divt! -GTPSA.mad_ctpsa_tdiv! GTPSA.mad_ctpsa_powt! -GTPSA.mad_ctpsa_tpow! -GTPSA.mad_ctpsa_nrm -GTPSA.mad_ctpsa_conj! -GTPSA.mad_ctpsa_sqrt! -GTPSA.mad_ctpsa_exp! -GTPSA.mad_ctpsa_log! -GTPSA.mad_ctpsa_sincos! +GTPSA.mad_ctpsa_print +GTPSA.mad_ctpsa_real! +GTPSA.mad_ctpsa_rect! +GTPSA.mad_ctpsa_scan +GTPSA.mad_ctpsa_scan_coef! +GTPSA.mad_ctpsa_scan_hdr +GTPSA.mad_ctpsa_scl! +GTPSA.mad_ctpsa_scl_r! +GTPSA.mad_ctpsa_sclord! +GTPSA.mad_ctpsa_seti! +GTPSA.mad_ctpsa_seti_r! +GTPSA.mad_ctpsa_setm! +GTPSA.mad_ctpsa_setm_r! +GTPSA.mad_ctpsa_setprm! +GTPSA.mad_ctpsa_setprm_r! +GTPSA.mad_ctpsa_sets! +GTPSA.mad_ctpsa_sets_r! +GTPSA.mad_ctpsa_setsm! +GTPSA.mad_ctpsa_setsm_r! +GTPSA.mad_ctpsa_setv! +GTPSA.mad_ctpsa_setval! +GTPSA.mad_ctpsa_setval_r! +GTPSA.mad_ctpsa_setvar! +GTPSA.mad_ctpsa_setvar_r! GTPSA.mad_ctpsa_sin! -GTPSA.mad_ctpsa_cos! -GTPSA.mad_ctpsa_tan! -GTPSA.mad_ctpsa_cot! GTPSA.mad_ctpsa_sinc! +GTPSA.mad_ctpsa_sincos! GTPSA.mad_ctpsa_sincosh! GTPSA.mad_ctpsa_sinh! -GTPSA.mad_ctpsa_cosh! -GTPSA.mad_ctpsa_tanh! -GTPSA.mad_ctpsa_coth! GTPSA.mad_ctpsa_sinhc! -GTPSA.mad_ctpsa_asin! -GTPSA.mad_ctpsa_acos! -GTPSA.mad_ctpsa_atan! -GTPSA.mad_ctpsa_acot! -GTPSA.mad_ctpsa_asinc! -GTPSA.mad_ctpsa_asinh! -GTPSA.mad_ctpsa_acosh! -GTPSA.mad_ctpsa_atanh! -GTPSA.mad_ctpsa_acoth! -GTPSA.mad_ctpsa_asinhc! -GTPSA.mad_ctpsa_erf! -GTPSA.mad_ctpsa_erfc! -GTPSA.mad_ctpsa_acc! -GTPSA.mad_ctpsa_scl! -GTPSA.mad_ctpsa_inv! -GTPSA.mad_ctpsa_invsqrt! -GTPSA.mad_ctpsa_hypot! -GTPSA.mad_ctpsa_hypot3! -GTPSA.mad_ctpsa_integ! -GTPSA.mad_ctpsa_deriv! -GTPSA.mad_ctpsa_derivm! -GTPSA.mad_ctpsa_poisbra! +GTPSA.mad_ctpsa_sqrt! +GTPSA.mad_ctpsa_sub! +GTPSA.mad_ctpsa_subt! +GTPSA.mad_ctpsa_tan! +GTPSA.mad_ctpsa_tanh! GTPSA.mad_ctpsa_taylor! -GTPSA.mad_ctpsa_poisbrat! +GTPSA.mad_ctpsa_tdif! +GTPSA.mad_ctpsa_tdiv! GTPSA.mad_ctpsa_tpoisbra! -GTPSA.mad_ctpsa_acc_r! -GTPSA.mad_ctpsa_scl_r! -GTPSA.mad_ctpsa_inv_r! -GTPSA.mad_ctpsa_invsqrt_r! -GTPSA.mad_ctpsa_axpb! -GTPSA.mad_ctpsa_axpbypc! -GTPSA.mad_ctpsa_axypb! -GTPSA.mad_ctpsa_axypbzpc! -GTPSA.mad_ctpsa_axypbvwpc! -GTPSA.mad_ctpsa_ax2pby2pcz2! -GTPSA.mad_ctpsa_axpsqrtbpcx2! -GTPSA.mad_ctpsa_logaxpsqrtbpcx2! -GTPSA.mad_ctpsa_logxdy! -GTPSA.mad_ctpsa_axpb_r! -GTPSA.mad_ctpsa_axpbypc_r! -GTPSA.mad_ctpsa_axypb_r! -GTPSA.mad_ctpsa_axypbzpc_r! -GTPSA.mad_ctpsa_axypbvwpc_r! -GTPSA.mad_ctpsa_ax2pby2pcz2_r! -GTPSA.mad_ctpsa_axpsqrtbpcx2_r! -GTPSA.mad_ctpsa_logaxpsqrtbpcx2_r! -GTPSA.mad_ctpsa_vec2fld! -GTPSA.mad_ctpsa_fld2vec! -GTPSA.mad_ctpsa_fgrad! -GTPSA.mad_ctpsa_liebra! -GTPSA.mad_ctpsa_exppb! -GTPSA.mad_ctpsa_logpb! -GTPSA.mad_ctpsa_mnrm -GTPSA.mad_ctpsa_minv! -GTPSA.mad_ctpsa_pminv! -GTPSA.mad_ctpsa_compose! +GTPSA.mad_ctpsa_tpow! GTPSA.mad_ctpsa_translate! -GTPSA.mad_ctpsa_eval! -GTPSA.mad_ctpsa_mconv! -GTPSA.mad_ctpsa_print -GTPSA.mad_ctpsa_scan -GTPSA.mad_ctpsa_scan_hdr -GTPSA.mad_ctpsa_scan_coef! -GTPSA.mad_ctpsa_debug -GTPSA.mad_ctpsa_isvalid -GTPSA.mad_ctpsa_init! +GTPSA.mad_ctpsa_tsub! +GTPSA.mad_ctpsa_uid! +GTPSA.mad_ctpsa_unit! +GTPSA.mad_ctpsa_update! +GTPSA.mad_ctpsa_vec2fld! ``` diff --git a/docs/src/index.md b/docs/src/index.md index bba1b05c..70aa3629 100644 --- a/docs/src/index.md +++ b/docs/src/index.md @@ -4,14 +4,12 @@ This package provides a full-featured Julia interface to the [Generalised Truncated Power Series Algebra (GTPSA) library](https://mad.web.cern.ch/mad/releases/madng/html/mad_mod_diffalg.html), which computes Taylor expansions, or Truncated Power Series (TPSs) of real and complex multivariable functions to arbitrary orders. -Truncated Power Series Algebra (TPSA) performs forward-mode automatic differentation (AD) similar to the dual-number implementation of `ForwardDiff.jl`. However, instead of nesting derivatives for higher orders, TPSA naturally extends to arbitary orders by directly using the power series expansions. This, paired with a highly optimized monomial indexing function/storage for propagating the partial derivatives, makes `GTPSA.jl` significantly faster for 2nd-order calculations and above (for 1st-order -calculations the performance is similar to `ForwardDiff.jl`). -See the [`benchmark/track.jl`](https://github.com/bmad-sim/GTPSA.jl/blob/main/benchmark/track.jl) example for a speed comparison of `GTPSA.jl` with `ForwardDiff.jl` in calculating the partial derivatives for a system with 58 inputs and 6 outputs. **In this example, GTPSA was nearly x3 faster than ForwardDiff to 2nd order, and x15 faster to 3rd order.** +Truncated Power Series Algebra (TPSA) performs forward-mode automatic differentation (AD) similar to the dual-number implementation of `ForwardDiff.jl`. However, instead of nesting derivatives for higher orders, TPSA naturally extends to arbitary orders by directly using the power series expansions. This, paired with a highly optimized monomial indexing function/storage for propagating the partial derivatives, makes `GTPSA.jl` significantly faster for 2nd-order calculations and above (for 1st-order calculations the performance is similar to `ForwardDiff.jl`).See the [`benchmark/track.jl`](https://github.com/bmad-sim/GTPSA.jl/blob/main/benchmark/track.jl) example for a speed comparison of `GTPSA.jl` with `ForwardDiff.jl` in calculating the partial derivatives for a system with 58 inputs and 6 outputs. **In this example, GTPSA was x3.3 faster than ForwardDiff to 2nd order, and x18.5 faster to 3rd order.** GTPSA provides several advantages over current Julia AD packages: -1. **Speed**: `GTPSA.jl` is significantly faster than `ForwardDiff.jl` for 2nd-order calculations and above, and has similar performance at 1st-order -2. **Custom Orders in Individual Variables**: Other packages use a single maximum order for all variables. With GTPSA, the maximum order can be set differently for different variables. For example, computing the Taylor expansion of $f(x_1,x_2)$ to 2nd order in $x_1$ and 6th order in $x_2$ is possible +1. **Speed**: `GTPSA.jl` is significantly faster than `ForwardDiff.jl` for 2nd-order calculations and above, and has very similar performance at 1st-order +2. **Custom Orders in Individual Variables**: Other packages use a single maximum order for all variables. With GTPSA, the maximum order can be set differently for individual variables, as well as for a separate part of the monomial. For example, computing the Taylor expansion of $f(x_1,x_2)$ to 2nd order in $x_1$ and 6th order in $x_2$ is possible 3. **Complex Numbers**: GTPSA natively supports complex numbers and allows for mixing of complex and real truncated power series 4. **Distinction Between State Variables and Parameters**: Distinguishing between dependent variables and parameters in the solution of a differential equation expressed as a power series in the dependent variables/parameters can be advantageous in analysis @@ -38,7 +36,7 @@ x = vars() # Manipulate the TPSs as you would any other mathematical variable in Julia f = cos(x[1]) + im*sin(x[2]) -# This creates a new TPS called f +# f is a new ComplexTPS ``` Note that scalars do not need to be defined as TPSs when writing expressions. Running `print(f)` gives the output diff --git a/src/low_level/ctpsa.jl b/src/low_level/ctpsa.jl index 842f3fa5..9d870d70 100644 --- a/src/low_level/ctpsa.jl +++ b/src/low_level/ctpsa.jl @@ -129,8 +129,15 @@ end """ mad_ctpsa_mo!(t::Ptr{CTPSA}, mo_::Cuchar)::Cuchar -??? +Sets the maximum order `mo` of the TPSA `t`, and returns the original `mo`. +`mo_` should be less than or equal to the allocated order `ao`. +### Input +- `t` -- TPSA +- `mo_` -- Maximum order to set the TPSA + +### Output +- `ret` -- Original `mo` of the TPSA """ function mad_ctpsa_mo!(t::Ptr{CTPSA}, mo_::Cuchar)::Cuchar ret = @ccall MAD_TPSA.mad_ctpsa_mo(t::Ptr{CTPSA}, mo_::Cuchar)::Cuchar @@ -263,7 +270,11 @@ end """ mad_ctpsa_clrord!(t::Ptr{CTPSA}, ord::Cuchar) - ??? +Clears all monomial coefficients of the TPSA at order `ord` + +### Input +- `t` -- TPSA +- `ord` -- Order to clear monomial coefficients """ function mad_ctpsa_clrord!(t::Ptr{CTPSA}, ord::Cuchar) @ccall MAD_TPSA.mad_ctpsa_clrord(t::Ptr{CTPSA}, ord::Cuchar)::Cvoid @@ -802,7 +813,13 @@ end """ mad_ctpsa_cpyi!(t::Ptr{CTPSA}, r::Ptr{CTPSA}, i::Cint) - ??? +Copies the monomial coefficient at index `i` in `t` into the +same monomial coefficient in `r` + +### Input +- `t` -- Source TPSA +- `r` -- Destination TPSA +- `i` -- Index of monomial """ function mad_ctpsa_cpyi!(t::Ptr{CTPSA}, r::Ptr{CTPSA}, i::Cint) @ccall MAD_TPSA.mad_ctpsa_cpyi(t::Ptr{CTPSA}, r::Ptr{CTPSA}, i::Cint)::Cvoid @@ -811,7 +828,14 @@ end """ mad_ctpsa_cpys!(t::Ptr{CTPSA}, r::Ptr{CTPSA}, n::Cint, s::Cstring) - ??? +Copies the monomial coefficient at the monomial-as-string-of-order +`s` in `t` into the same monomial coefficient in `r` + +### Input +- `t` -- Source TPSA +- `r` -- Destination TPSA +- `n` -- Length of string +- `s` -- Monomial as string """ function mad_ctpsa_cpys!(t::Ptr{CTPSA}, r::Ptr{CTPSA}, n::Cint, s::Cstring) @ccall MAD_TPSA.mad_ctpsa_cpys(t::Ptr{CTPSA}, r::Ptr{CTPSA}, n::Cint, s::Cstring)::Cvoid @@ -820,7 +844,14 @@ end """ mad_ctpsa_cpym!(t::Ptr{CTPSA}, r::Ptr{CTPSA}, n::Cint, m::Vector{Cuchar}) - ??? +Copies the monomial coefficient at the monomial-as-vector-of-orders +`m` in `t` into the same monomial coefficient in `r` + +### Input +- `t` -- Source TPSA +- `r` -- Destination TPSA +- `n` -- Length of monomial `m` +- `m` -- Monomial as vector of orders """ function mad_ctpsa_cpym!(t::Ptr{CTPSA}, r::Ptr{CTPSA}, n::Cint, m::Vector{Cuchar}) @ccall MAD_TPSA.mad_ctpsa_cpym(t::Ptr{CTPSA}, r::Ptr{CTPSA}, n::Cint, m::Ptr{Cuchar})::Cvoid @@ -829,7 +860,14 @@ end """ mad_ctpsa_cpysm!(t::Ptr{CTPSA}, r::Ptr{CTPSA}, n::Cint, m::Vector{Cint}) - ??? +Copies the monomial coefficient at the monomial-as-sparse-monomial +`m` in `t` into the same monomial coefficient in `r` + +### Input +- `t` -- Source TPSA +- `r` -- Destination TPSA +- `n` -- Length of sparse monomial `m` +- `m` -- Monomial as sparse-monomial """ function mad_ctpsa_cpysm!(t::Ptr{CTPSA}, r::Ptr{CTPSA}, n::Cint, m::Vector{Cint}) @ccall MAD_TPSA.mad_ctpsa_cpysm(t::Ptr{CTPSA}, r::Ptr{CTPSA}, n::Cint, m::Ptr{Cint})::Cvoid @@ -2649,7 +2687,16 @@ end """ mad_ctpsa_mord(na::Cint, ma::Vector{Ptr{CTPSA}}, hi::Bool)::Cuchar - ??? +If `hi` is false, getting the maximum `mo` among all TPSAs in `ma`. +If `hi` is `true`, gets the maximum `hi` of the map instead of `mo` + +### Input +- `na` -- Length of map `ma` +- `ma` -- Map (vector of TPSAs) +- `hi` -- If `true`, returns maximum `hi`, else returns maximum `mo` of the map + +### Output +- `ret` -- Maximum `hi` of the map if `hi` is `true`, else returns maximum `mo` of the map """ function mad_ctpsa_mord(na::Cint, ma::Vector{Ptr{CTPSA}}, hi::Bool)::Cuchar ret = @ccall MAD_TPSA.mad_ctpsa_mord(na::Cint, ma::Ptr{Ptr{CTPSA}}, hi::Bool)::Cuchar @@ -2884,6 +2931,22 @@ function mad_ctpsa_debug(t::Ptr{CTPSA}, name_::Cstring, fnam_::Cstring, line_::C return ret end +""" + mad_ctpsa_isval(t::Ptr{CTPSA})::Bool + +Sanity check of the TPSA integrity. + +### Input +- `t` -- TPSA to check if valid + +### Output +- `ret` -- True if valid TPSA, false otherwise +""" +function mad_ctpsa_isval(t::Ptr{CTPSA})::Bool + ret = @ccall MAD_TPSA.mad_ctpsa_isval(t::Ptr{CTPSA})::Bool + return ret +end + """ mad_ctpsa_isvalid(t::Ptr{CTPSA})::Bool diff --git a/src/low_level/rtpsa.jl b/src/low_level/rtpsa.jl index 308558dd..b64bdf3d 100644 --- a/src/low_level/rtpsa.jl +++ b/src/low_level/rtpsa.jl @@ -131,8 +131,15 @@ end """ mad_tpsa_mo!(t::Ptr{RTPSA}, mo_::Cuchar)::Cuchar -??? +Sets the maximum order `mo` of the TPSA `t`, and returns the original `mo`. +`mo_` should be less than or equal to the allocated order `ao`. + +### Input +- `t` -- TPSA +- `mo_` -- Maximum order to set the TPSA +### Output +- `ret` -- Original `mo` of the TPSA """ function mad_tpsa_mo!(t::Ptr{RTPSA}, mo_::Cuchar)::Cuchar ret = @ccall MAD_TPSA.mad_tpsa_mo(t::Ptr{RTPSA}, mo_::Cuchar)::Cuchar @@ -266,7 +273,11 @@ end """ mad_tpsa_clrord!(t::Ptr{RTPSA}, ord::Cuchar) - ??? +Clears all monomial coefficients of the TPSA at order `ord` + +### Input +- `t` -- TPSA +- `ord` -- Order to clear monomial coefficients """ function mad_tpsa_clrord!(t::Ptr{RTPSA}, ord::Cuchar) @ccall MAD_TPSA.mad_tpsa_clrord(t::Ptr{RTPSA}, ord::Cuchar)::Cvoid @@ -647,7 +658,13 @@ end """ mad_tpsa_cpyi!(t::Ptr{RTPSA}, r::Ptr{RTPSA}, i::Cint) - ??? +Copies the monomial coefficient at index `i` in `t` into the +same monomial coefficient in `r` + +### Input +- `t` -- Source TPSA +- `r` -- Destination TPSA +- `i` -- Index of monomial """ function mad_tpsa_cpyi!(t::Ptr{RTPSA}, r::Ptr{RTPSA}, i::Cint) @ccall MAD_TPSA.mad_tpsa_cpyi(t::Ptr{RTPSA}, r::Ptr{RTPSA}, i::Cint)::Cvoid @@ -656,7 +673,14 @@ end """ mad_tpsa_cpys!(t::Ptr{RTPSA}, r::Ptr{RTPSA}, n::Cint, s::Cstring) - ??? +Copies the monomial coefficient at the monomial-as-string-of-order +`s` in `t` into the same monomial coefficient in `r` + +### Input +- `t` -- Source TPSA +- `r` -- Destination TPSA +- `n` -- Length of string +- `s` -- Monomial as string """ function mad_tpsa_cpys!(t::Ptr{RTPSA}, r::Ptr{RTPSA}, n::Cint, s::Cstring) @ccall MAD_TPSA.mad_tpsa_cpys(t::Ptr{RTPSA}, r::Ptr{RTPSA}, n::Cint, s::Cstring)::Cvoid @@ -665,7 +689,14 @@ end """ mad_tpsa_cpym!(t::Ptr{RTPSA}, r::Ptr{RTPSA}, n::Cint, m::Vector{Cuchar}) - ??? +Copies the monomial coefficient at the monomial-as-vector-of-orders +`m` in `t` into the same monomial coefficient in `r` + +### Input +- `t` -- Source TPSA +- `r` -- Destination TPSA +- `n` -- Length of monomial `m` +- `m` -- Monomial as vector of orders """ function mad_tpsa_cpym!(t::Ptr{RTPSA}, r::Ptr{RTPSA}, n::Cint, m::Vector{Cuchar}) @ccall MAD_TPSA.mad_tpsa_cpym(t::Ptr{RTPSA}, r::Ptr{RTPSA}, n::Cint, m::Ptr{Cuchar})::Cvoid @@ -1858,7 +1889,16 @@ end """ mad_tpsa_mord(na::Cint, ma::Vector{Ptr{RTPSA}}, hi::Bool)::Cuchar - ??? +If `hi` is false, getting the maximum `mo` among all TPSAs in `ma`. +If `hi` is `true`, gets the maximum `hi` of the map instead of `mo` + +### Input +- `na` -- Length of map `ma` +- `ma` -- Map (vector of TPSAs) +- `hi` -- If `true`, returns maximum `hi`, else returns maximum `mo` of the map + +### Output +- `ret` -- Maximum `hi` of the map if `hi` is `true`, else returns maximum `mo` of the map """ function mad_tpsa_mord(na::Cint, ma::Vector{Ptr{RTPSA}}, hi::Bool)::Cuchar ret = @ccall MAD_TPSA.mad_tpsa_mord(na::Cint, ma::Ptr{Ptr{RTPSA}}, hi::Bool)::Cuchar @@ -2112,6 +2152,21 @@ function mad_tpsa_clrdensity!()::Cvoid @ccall MAD_TPSA.mad_tpsa_clrdensity()::Cvoid end +""" + mad_tpsa_isval(t::Ptr{RTPSA})::Bool + +Sanity check of the TPSA integrity. + +### Input +- `t` -- TPSA to check if valid + +### Output +- `ret` -- True if valid TPSA, false otherwise +""" +function mad_tpsa_isval(t::Ptr{RTPSA})::Bool + ret = @ccall MAD_TPSA.mad_tpsa_isval(t::Ptr{RTPSA})::Bool + return ret +end """ mad_tpsa_isvalid(t::Ptr{RTPSA})::Bool @@ -2129,6 +2184,7 @@ function mad_tpsa_isvalid(t::Ptr{RTPSA})::Bool return ret end + """ mad_tpsa_density(t::Ptr{RTPSA}, eps::Cdouble)::Cdouble diff --git a/test/compare_MAD.jl b/test/compare_MAD.jl index ef8e3b87..b8802296 100644 --- a/test/compare_MAD.jl +++ b/test/compare_MAD.jl @@ -1,13 +1,6 @@ # Julia script to compare current GTPSA.jl with latest # MAD_TPSA code from the MAD Git repo: # https://github.com/MethodicalAcceleratorDesign/MAD -# -# Known accepted disagreements: -# mad_ctpsa_equt: tol_ in GTPSA.jl is correct vs tol in mad_ctpsa.H -# mad_ctpsa_unit: C code has two equivalent function declarations with x and t. GTPSA.jl is correct -# mad_tpsa_ordv: Splats in Julia have names, C they do not, so script will show disagreements -# mad_ctpsa_ordv: Same as for mad_tpsa_ordv - using Downloads const io_out = IOBuffer() @@ -324,7 +317,7 @@ function compare_MAD() io = IOBuffer() try - Downloads.download("https://raw.githubusercontent.com/mattsignorelli/gtpsa/dev-tpsa-newlazy/code/mad_mono.h", io) + Downloads.download("https://raw.githubusercontent.com/mattsignorelli/gtpsa/main/code/mad_mono.h", io) println(io_out, "mad_mono.h downloaded.") catch e println(io_out, "Error downloading mad_mono.h") @@ -341,7 +334,7 @@ function compare_MAD() try - Downloads.download("https://raw.githubusercontent.com/mattsignorelli/gtpsa/dev-tpsa-newlazy/code/mad_desc.h", io) + Downloads.download("https://raw.githubusercontent.com/mattsignorelli/gtpsa/main/code/mad_desc.h", io) println(io_out, "mad_desc.h downloaded.") catch e println(io_out, "Error downloading mad_desc.h") @@ -358,7 +351,7 @@ function compare_MAD() try - Downloads.download("https://raw.githubusercontent.com/mattsignorelli/gtpsa/dev-tpsa-newlazy/code/mad_tpsa.h", io) + Downloads.download("https://raw.githubusercontent.com/mattsignorelli/gtpsa/main/code/mad_tpsa.h", io) println(io_out, "mad_tpsa.h downloaded.") catch e println(io_out, "Error downloading mad_tpsa.h") @@ -374,7 +367,7 @@ function compare_MAD() compare(fun_decs_c, fun_decs_jl) try - Downloads.download("https://raw.githubusercontent.com/mattsignorelli/gtpsa/dev-tpsa-newlazy/code/mad_ctpsa.h", io) + Downloads.download("https://raw.githubusercontent.com/mattsignorelli/gtpsa/main/code/mad_ctpsa.h", io) println(io_out, "mad_ctpsa.h downloaded.") catch e println(io_out, "Error downloading mad_ctpsa.h") From 6c9e55ed86310fd6c151ca021b617265cceb0607 Mon Sep 17 00:00:00 2001 From: mattsignorelli Date: Fri, 3 May 2024 14:49:47 -0400 Subject: [PATCH 28/29] update benchmark --- benchmark/track.jl | 48 +++++++++++++++++++++++----------------------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/benchmark/track.jl b/benchmark/track.jl index caf6973a..05c3add0 100644 --- a/benchmark/track.jl +++ b/benchmark/track.jl @@ -39,13 +39,13 @@ function track_qf(z0, k1, hkick) z = Vector{promote_type(eltype(z0),typeof(k1),typeof(hkick))}(undef, length(z0)) lbend=0.1 - L = 0.5/(1.0+z0[6]) - h = -L*(z0[2]^2+k1*z0[1]^2+ z0[4]^2-k1*z0[3]^2)/(1.0+z0[6])/2.0 - z[1] = cos(sqrt(k1)*L)*z0[1]+1/sqrt(k1)*sin(sqrt(k1)*L)*z0[2] - z[2] = -sqrt(k1)*sin(sqrt(k1)*L)*z0[1]+cos(sqrt(k1)*L)*z0[2]+hkick+lbend*z0[6] - z[3] = cosh(sqrt(k1)*L)*z0[3]+1/sqrt(k1)*sinh(sqrt(k1)*L)*z0[4] - z[4] = sqrt(k1)*sinh(sqrt(k1)*L)*z0[3]+cosh(sqrt(k1)*L)*z0[4] - z[5] = z0[5]+h-lbend*z[1] + L = @FastGTPSA 0.5/(1.0+z0[6]) + h = @FastGTPSA -L*(z0[2]^2+k1*z0[1]^2+ z0[4]^2-k1*z0[3]^2)/(1.0+z0[6])/2.0 + z[1] = @FastGTPSA cos(sqrt(k1)*L)*z0[1]+1/sqrt(k1)*sin(sqrt(k1)*L)*z0[2] + z[2] = @FastGTPSA -sqrt(k1)*sin(sqrt(k1)*L)*z0[1]+cos(sqrt(k1)*L)*z0[2]+hkick+lbend*z0[6] + z[3] = @FastGTPSA cosh(sqrt(k1)*L)*z0[3]+1/sqrt(k1)*sinh(sqrt(k1)*L)*z0[4] + z[4] = @FastGTPSA sqrt(k1)*sinh(sqrt(k1)*L)*z0[3]+cosh(sqrt(k1)*L)*z0[4] + z[5] = @FastGTPSA z0[5]+h-lbend*z[1] z[6] = +z0[6] return z end @@ -53,13 +53,13 @@ end function track_qd(z0, k1, vkick) z = Vector{promote_type(eltype(z0),typeof(k1),typeof(vkick))}(undef, length(z0)) - L = 0.5/(1.0+z0[6]) - h = -L*(z0[2]^2-k1*z0[1]^2+z0[4]^2+k1*z0[3]^2)/(1.0+z0[6])/2.0 - z[1] = cosh(sqrt(k1)*L)*z0[1]+1/sqrt(k1)*sinh(sqrt(k1)*L)*z0[2] - z[2] = sqrt(k1)*sinh(sqrt(k1)*L)*z0[1]+cosh(sqrt(k1)*L)*z0[2] - z[3] = cos(sqrt(k1)*L)*z0[3]+1/sqrt(k1)*sin(sqrt(k1)*L)*z0[4] - z[4] = -sqrt(k1)*sin(sqrt(k1)*L)*z0[3]+cos(sqrt(k1)*L)*z0[4]+vkick - z[5] = z0[5]+h + L = @FastGTPSA 0.5/(1.0+z0[6]) + h = @FastGTPSA -L*(z0[2]^2-k1*z0[1]^2+z0[4]^2+k1*z0[3]^2)/(1.0+z0[6])/2.0 + z[1] = @FastGTPSA cosh(sqrt(k1)*L)*z0[1]+1/sqrt(k1)*sinh(sqrt(k1)*L)*z0[2] + z[2] = @FastGTPSA sqrt(k1)*sinh(sqrt(k1)*L)*z0[1]+cosh(sqrt(k1)*L)*z0[2] + z[3] = @FastGTPSA cos(sqrt(k1)*L)*z0[3]+1/sqrt(k1)*sin(sqrt(k1)*L)*z0[4] + z[4] = @FastGTPSA -sqrt(k1)*sin(sqrt(k1)*L)*z0[3]+cos(sqrt(k1)*L)*z0[4]+vkick + z[5] = @FastGTPSA z0[5]+h z[6] = +z0[6] return z end @@ -68,11 +68,11 @@ function track_drift(z0) z = Vector{eltype(z0)}(undef, length(z0)) L = 0.75 - z[1] = z0[1]+z0[2]*L/(1.0+z0[6]) + z[1] = @FastGTPSA z0[1]+z0[2]*L/(1.0+z0[6]) z[2] = +z0[2] - z[3] = z0[3]+z0[4]*L/(1.0+z0[6]) + z[3] = @FastGTPSA z0[3]+z0[4]*L/(1.0+z0[6]) z[4] = +z0[4] - z[5] = z0[5]-L*((z0[2]^2)+(z0[4]^2))/(1.0+z0[6])^2/2.0 + z[5] = @FastGTPSA z0[5]-L*((z0[2]^2)+(z0[4]^2))/(1.0+z0[6])^2/2.0 z[6] = +z0[6] return z end @@ -85,7 +85,7 @@ function track_cav(z0) z[3] = +z0[3] z[4] = +z0[4] z[5] = +z0[5] - z[6] = z0[6]+0.0001*z0[5] + z[6] = @FastGTPSA z0[6]+0.0001*z0[5] return z end @@ -93,9 +93,9 @@ function track_sextupole(z0, k2l) z = Vector{promote_type(eltype(z0),typeof(k2l))}(undef, length(z0)) z[1] = +z0[1] - z[2] = z0[2]-k2l*(z0[1]^2-z0[3]^2) + z[2] = @FastGTPSA z0[2]-k2l*(z0[1]^2-z0[3]^2) z[3] = +z0[3] - z[4] = z0[4]+k2l*2.0*z0[1]*z0[3] + z[4] = @FastGTPSA z0[4]+k2l*2.0*z0[1]*z0[3] z[5] = +z0[5] z[6] = +z0[6] return z @@ -120,7 +120,7 @@ function track_ring(z0, k1=0.36, k2l=1.2, kick=zeros(50)) end function benchmark_GTPSA() - d = Descriptor(6,1,52,1) + d = Descriptor(6,2,52,2) z = vars() k = params() map = track_ring(z, 0.36+k[1], 1.2+k[2], k[3:end]) @@ -130,10 +130,10 @@ end function benchmark_ForwardDiff() m(z) = track_ring([z[1], z[2], z[3], z[4], z[5], z[6]], 0.36+z[7], 1.2+z[8], z[9:end]) j = Array{Float64}(undef,6,58) - #h = Array{Float64}(undef,348,58) + h = Array{Float64}(undef,348,58) #c = Array{Float64}(undef,20184,58) ForwardDiff.jacobian!(j, m, zeros(58)) - #ForwardDiff.jacobian!(h, z->ForwardDiff.jacobian(z->m(z), z), zeros(58)) + ForwardDiff.jacobian!(h, z->ForwardDiff.jacobian(z->m(z), z), zeros(58)) #ForwardDiff.jacobian!(c, z->ForwardDiff.jacobian(z->ForwardDiff.jacobian(z->m(z), z), z), zeros(58)) - return j#, h#, c + return j, h #, c end From 8ec55c474c06a325b82fe96e0f2943c1c78cc830 Mon Sep 17 00:00:00 2001 From: mattsignorelli Date: Fri, 3 May 2024 14:57:03 -0400 Subject: [PATCH 29/29] clearord --- docs/src/man/k_methods.md | 2 ++ docs/src/man/o_all.md | 2 +- src/GTPSA.jl | 1 + src/methods.jl | 24 ++++++++++++++++++++++++ 4 files changed, 28 insertions(+), 1 deletion(-) diff --git a/docs/src/man/k_methods.md b/docs/src/man/k_methods.md index a799cb0c..0979d428 100644 --- a/docs/src/man/k_methods.md +++ b/docs/src/man/k_methods.md @@ -1,5 +1,7 @@ # [TPS Methods](@id tpsmethods) ```@docs +clearord +clearord! clear! complex! compose! diff --git a/docs/src/man/o_all.md b/docs/src/man/o_all.md index b9b619fa..04e64adb 100644 --- a/docs/src/man/o_all.md +++ b/docs/src/man/o_all.md @@ -16,7 +16,7 @@ rand **`LinearAlgebra`**: `norm`, `mul!` **`SpecialFunctions`**: `erf`, `erfc` -`GTPSA.jl` also provides the following functions NOT included in Base or any of the above packages: +`GTPSA.jl` also provides the following functions NOT included in Base or any of the above packages (and not already documented in [TPS Methods](@ref tpsmethods)): ``` add!, sub!, div!, unit, sinhc, asinc, asinhc, polar, rect ``` diff --git a/src/GTPSA.jl b/src/GTPSA.jl index e52eeca5..8b42d024 100644 --- a/src/GTPSA.jl +++ b/src/GTPSA.jl @@ -118,6 +118,7 @@ export deriv, ∂, deriv!, ∂!, getord, getord!, cutord, cutord!, + clearord, clearord!, translate, translate!, par, scalar, diff --git a/src/methods.jl b/src/methods.jl index 19e9aa90..203e7735 100644 --- a/src/methods.jl +++ b/src/methods.jl @@ -315,6 +315,30 @@ function cutord(t1::Union{TPS, ComplexTPS}, order::Integer) return t end +# --- clearord! --- +clrord!(t::Ptr{RTPSA}, ord::Cuchar) = mad_tpsa_clrord!(t, ord) +clrord!(t::Ptr{CTPSA}, ord::Cuchar) = mad_ctpsa_clrord!(t, ord) + +""" + clearord!(t::Union{TPS,ComplexTPS}, order::Integer) + +Clears all monomial coefficients in `t` at order `order`. +""" +clearord!(t::Union{TPS,ComplexTPS}, order::Integer) = clrord!(t.tpsa, convert(Cuchar, order)) + +""" + clearord(t1::Union{TPS,ComplexTPS}, order::Integer) + +Returns a new TPS equal to `t1` but with all monomial coefficients +at the given `order` cleared (set equal to 0). +""" +function clearord(t1::Union{TPS,ComplexTPS}, order::Integer) + t = zero(t1) + copy!(t,t1) + clearord!(t,order) + return t +end + # --- scalar --- """