Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 8 additions & 16 deletions src/TaylorInversion.jl
Original file line number Diff line number Diff line change
Expand Up @@ -16,24 +16,17 @@ struct InverseTaylor{N}
end
end

struct TaylorInverter{N}
f::Function
end

function TaylorInverter{N}() where {N}
f = create_expressions(N)
return TaylorInverter{N}(f)
end
struct TaylorInverter{N}; end

function invert(ti::TaylorInverter, a::Vector)
return ti.f([a])
return ti([a])
end

function invert(ti::TaylorInverter, taylor1::Taylor1)
order = taylor1.order
a = taylor1.coeffs[2:end]
substitution = Taylor1([-taylor1.coeffs[begin], 1], order)
return Taylor1([0; ti.f([a])], order)(substitution)
return Taylor1([0; ti([a])], order)(substitution)
end

function truncaterule(n, z)
Expand Down Expand Up @@ -89,7 +82,6 @@ function process(k::Int, an::Num, it::InverseTaylor, truncrule::Fixpoint)
end

function initial_substitution(it::InverseTaylor{N}) where {N}
@info "Intial substituion"
truncrule = truncaterule(N, it.z)
subbed = mapreduce(kan -> process(kan..., it, truncrule), +, enumerate(it.a)) |> expand

Expand All @@ -101,7 +93,6 @@ end

function further_substitution(it::InverseTaylor{N}, subbed::Num) where {N}
for i in 1:N
@info "Expanding term $i to create ivnersion expression"
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do I understand correctly that these @infos are removed for the sake of keeping the @generated function pure?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, printing is not allowed from inside generated functions.

divided = simplify(subbed / it.z)
subz = substitute(divided, Dict(it.z => 0))
it.B[i] = solve_for(subz ~ i == 1 ? 1 : 0, it.A[i]) |> simplify
Expand All @@ -111,13 +102,14 @@ function further_substitution(it::InverseTaylor{N}, subbed::Num) where {N}
return subbed
end

function create_expressions(n::Int)
it = InverseTaylor{n}()
@generated function (::TaylorInverter{N})(var"ˍ₋arg1") where {N}
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it necessary to switch from a regular function to a callable struct? If so, why exactly? And if not, why do you choose to do so anyway?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not necessary, but it's the easiest way to get around to it.

Copy link
Owner

@KeithWM KeithWM Nov 20, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

GIven the fact that the @generated macro induces a behaviour that might surprise people, I would quite appreciate some comments being added to this function. In particular:

  1. A comment on the name of the argument (var"_-arg1, not sure what the best place would be for this comment)
  2. A comment that the return value of this function as read "naively" is not what the function will return, but a string that will be evaluated when the code is lowered. That is, if I understand correctly what happens with a @generated function, kind of proving that it would be wise to document this (briefly, I understand we should not rewrite the Metaprogramming page of the Julia Docs.)
  3. Providing a docstring for this function that indicates the behaviour of the generated function. One of the (many) joys of Julia is it's innate readability, but with a generated function, this is somewhat hampered, for instance by the obscure argument name.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • A comment on the name of the argument (var"_-arg1, not sure what the best place would be for this comment)

It's the (Symbolics.jl) mangled name of the symbolic argument which is defined by this package. The argument name is the same as the argument name of the function that you eval'd

2. A comment that the return value of this function as read "naively" is not what the function will return, but a string that will be evaluated when the code is lowered.

The generator returns an AST.

obscure argument name.

The argument name is defined by this package when choosing the symbolic Num - if you change that, you get whatever symbol you want.

it = InverseTaylor{N}()
subbed = initial_substitution(it)
subbed = further_substitution(it, subbed)

f = build_function(it.B, [it.a])[1] # [1] because build function also provided an in-place version in [2]
return eval(f)
fdef = build_function(it.B, [it.a])[1] # [1] because build function also provided an in-place version in [2]
fbody = fdef.args[2]
return fbody
end

export TaylorInverter, invert
Expand Down