_at_evalpoly

I do not seem to understand the use of @evalpoly (doc)

julia> @evalpoly(3.0, 1)
ERROR: BoundsError: attempt to access (1,)
  at index [0]

julia> f(p) = @evalpoly(3.0, p)
ERROR: BoundsError: attempt to access (:p,)
  at index [0]

julia> f(p) = @evalpoly(1, p...)
ERROR: BoundsError: attempt to access (:(p...),)
  at index [0]

From what I understand, the first error comes from https://github.com/JuliaLang/julia/blob/e976e63cc791411b1e7d88b7ca705e87e10d8574/base/math.jl#L110.

As for the second and third, is there a way to delay the evaluation of the macro until p is passed to the function f? Or is this not the way the macro is intended to be used?

Thanks,
michele

The whole point of this macro is to inline the evaluation of a polynomial whose degree (and usually its coefficients) is known at compile time. This allows things like polynomial approximations of special-function implementations to be extremely efficient. Hence, the arguments must be an explicit list of coefficients.

(The case of a single coefficient, i.e. a degree-0 polynomial, is so pointless that we never implemented it. i.e. you might as well just write 1 instead of @evalpoly 3.0 1. We might as well implement it for completeness, I suppose.)

So, for example, if you knew that p was an array of length 4, you could do:

julia> f(p) = @evalpoly(1, p[1], p[2], p[3], p[4])
f (generic function with 1 method)

julia> f([2,3,4,5])
14

In practice, @evalpoly is mainly used in cases where the coefficients are compile-time constants as well, mainly in the implementation of special functions like erfinv and polygamma.

If you have an array p whose length is not known, there is no point in using a macro to evaluate the polynomial. It will need an explicit loop that is evaluated at runtime, rather than at compile-time as in @evalpoly.

At one point, I suggested that we have an evalpoly function for runtime evaluation of polynomials (RFC: add evalpoly function, mirroring @evalpoly macro by stevengj · Pull Request #7186 · JuliaLang/julia · GitHub), but there wasn’t much interest. In most such cases you probably want to use the Polynomials.jl package.

3 Likes

Thank you for the reply and the example.

I remember that at a certain point, you (most likely) implemented a horner method (or a macro) and I could not find it anymore. The @evalpoly is what came up when I searched the latest documentation for horner.

I completely agree with you that the evaluation of a 0th order polynomial is useless for the specialized cases of special functions.

I believe Stefan Karpinski addressed this specific macro at about 50m in the Julia - To Lisp or not to Lisp talk on YouTube.
Hope it helps.

3 Likes

Interesting presentation, @evalpoly macro aside. Thank you.

1 Like

My pleasure - but we should probably be thanking Stefan!
:+1:

-mrg