# Horner rule

**URL:** <https://discourse.julialang.org/t/horner-rule/7504>\
**Category:** General Usage\
**Tags:** metaprogramming\
**Created:** [December 4, 2017, 6:29pm UTC](https://discourse.julialang.org/t/horner-rule/7504 "2017-12-04T18:29:09Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![Diger](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/diger/32/36786_2.png) [@Diger](https://discourse.julialang.org/u/Diger)\
**Post date:** [December 4, 2017, 6:29pm UTC](https://discourse.julialang.org/t/horner-rule/7504/1 "2017-12-04T18:29:09Z")

</div>

```julia
 macro horner(x, p...)
     ex = p[end]
     for i = length(p)-1:-1:1
         ex = :($(p[i]) + $x * $ex)
     end
     ex
 end

```

I was looking at this [https://github.com/JuliaLang/julia/pull/2987/commits/9c24795ac2918df7b8cba9bb129db8c535d321e8](https://github.com/JuliaLang/julia/pull/2987/commits/9c24795ac2918df7b8cba9bb129db8c535d321e8)  
and just want to know what

1. : infront of the bracket is for
2. $ is supposed to do?  
I mean in principle I could have also written it without : and $, but maybe they have some nice features ?

---

<div class="post-metadata">

**Author:** ![kristoffer.carlsson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kristoffer.carlsson/32/22_2.png) [@kristoffer.carlsson](https://discourse.julialang.org/u/kristoffer.carlsson)\
**Post date:** [December 4, 2017, 6:33pm UTC](https://discourse.julialang.org/t/horner-rule/7504/2 "2017-12-04T18:33:00Z")

</div>

See [https://docs.julialang.org/en/stable/manual/metaprogramming/#Interpolation-1](https://docs.julialang.org/en/stable/manual/metaprogramming/#Interpolation-1)

---

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [December 4, 2017, 6:33pm UTC](https://discourse.julialang.org/t/horner-rule/7504/3 "2017-12-04T18:33:02Z")

</div>

[https://docs.julialang.org/en/latest/manual/metaprogramming/](https://docs.julialang.org/en/latest/manual/metaprogramming/)

would be a good start. And please quote your code (`````).

---

<div class="post-metadata">

**Author:** ![Diger](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/diger/32/36786_2.png) [@Diger](https://discourse.julialang.org/u/Diger)\
**Post date:** [December 4, 2017, 6:35pm UTC](https://discourse.julialang.org/t/horner-rule/7504/4 "2017-12-04T18:35:31Z")

</div>

I dont see a difference. Did the quoting work for you?

Maybe not belonging to the topic, but why do people like to write long numbers like  
0.10501\_31152\_37334\_38116e-3

Does it nothing but a better overview of the number?

Thx for the answers btw!

---

<div class="post-metadata">

**Author:** ![mauro3](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mauro3/32/292_2.png) [@mauro3](https://discourse.julialang.org/u/mauro3)\
**Post date:** [December 4, 2017, 6:44pm UTC](https://discourse.julialang.org/t/horner-rule/7504/5 "2017-12-04T18:44:56Z")

</div>

Yes, just for readability. (You should keep one thread to one topic though).

---

<div class="post-metadata">

**Author:** ![dpsanders](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dpsanders/32/3573_2.png) [@dpsanders](https://discourse.julialang.org/u/dpsanders)\
**Post date:** [December 4, 2017, 6:47pm UTC](https://discourse.julialang.org/t/horner-rule/7504/6 "2017-12-04T18:47:37Z")

</div>

This uses metaprogramming to “unroll” the expression. Use `@macroexpand` to see the result.

---

<div class="post-metadata">

**Author:** ![Diger](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/diger/32/36786_2.png) [@Diger](https://discourse.julialang.org/u/Diger)\
**Post date:** [December 4, 2017, 6:50pm UTC](https://discourse.julialang.org/t/horner-rule/7504/7 "2017-12-04T18:50:19Z")

</div>

julia\> @macroexpand(ans)  
ERROR: UndefVarError: @macroexpand not defined

???

---

<div class="post-metadata">

**Author:** ![StefanKarpinski](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stefankarpinski/32/24_2.png) [@StefanKarpinski](https://discourse.julialang.org/u/StefanKarpinski)\
**Post date:** [December 4, 2017, 6:50pm UTC](https://discourse.julialang.org/t/horner-rule/7504/8 "2017-12-04T18:50:55Z")

</div>

Please quote your code – this has been requested repeatedly by multiple people.

---

<div class="post-metadata">

**Author:** ![Diger](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/diger/32/36786_2.png) [@Diger](https://discourse.julialang.org/u/Diger)\
**Post date:** [December 4, 2017, 6:51pm UTC](https://discourse.julialang.org/t/horner-rule/7504/9 "2017-12-04T18:51:17Z")

</div>

I did…but it does not work.

I used blockquote only for the code.

---

<div class="post-metadata">

**Author:** ![StefanKarpinski](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stefankarpinski/32/24_2.png) [@StefanKarpinski](https://discourse.julialang.org/u/StefanKarpinski)\
**Post date:** [December 4, 2017, 6:54pm UTC](https://discourse.julialang.org/t/horner-rule/7504/10 "2017-12-04T18:54:28Z")

</div>

[https://discuss.atom.io/t/quoting-code-as-code/8140](https://discuss.atom.io/t/quoting-code-as-code/8140)

---

<div class="post-metadata">

**Author:** ![dpsanders](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dpsanders/32/3573_2.png) [@dpsanders](https://discourse.julialang.org/u/dpsanders)\
**Post date:** [December 4, 2017, 6:55pm UTC](https://discourse.julialang.org/t/horner-rule/7504/11 "2017-12-04T18:55:47Z")

</div>

`@macroexpand` works since Julia 0.6. You feed it the macro code directly.  
It is strongly recommended to upgrade to Julia 0.6.

```julia
julia> @macroexpand Base.Math.@horner(5, 1, 2, 3, 4)
quote
    #19#t = 5
    (Base.Math.muladd)(#19#t, (Base.Math.muladd)(#19#t, (Base.Math.muladd)(#19#t, 4, 3), 2), 1)
end

```

---

<div class="post-metadata">

**Author:** ![Diger](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/diger/32/36786_2.png) [@Diger](https://discourse.julialang.org/u/Diger)\
**Post date:** [December 4, 2017, 7:04pm UTC](https://discourse.julialang.org/t/horner-rule/7504/12 "2017-12-04T19:04:38Z")

</div>

Sorry, but I don’t quite get what you mean:  
While `Base.Math.@horner(5, 1, 2, 3, 4)`  
just runs the macro and gives me 586  
pretyping @macroexpand then tells me  
`(Base.Math.muladd)`  
What does this tell me?

---

<div class="post-metadata">

**Author:** ![dpsanders](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dpsanders/32/3573_2.png) [@dpsanders](https://discourse.julialang.org/u/dpsanders)\
**Post date:** [December 4, 2017, 7:05pm UTC](https://discourse.julialang.org/t/horner-rule/7504/13 "2017-12-04T19:05:32Z")

</div>

That’s a problem with the syntax highlighting. It’s giving you  
`(Base.Math.muladd)(#19#t, (Base.Math.muladd)(#19#t, (Base.Math.muladd)(#19#t, 4, 3), 2), 1)`  
which is the code that the macro is producing.

---

<div class="post-metadata">

**Author:** ![Diger](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/diger/32/36786_2.png) [@Diger](https://discourse.julialang.org/u/Diger)\
**Post date:** [December 4, 2017, 7:07pm UTC](https://discourse.julialang.org/t/horner-rule/7504/14 "2017-12-04T19:07:19Z")

</div>

```julia
 macro horner(x, p...)
     ex = p[end]
     for i = length(p)-1:-1:1
         ex = :($(p[i]) + $x * $ex)
     end
     ex
 end

```

Wouldnt I expect it to show me this code? Maybe with numbers inserted?

What does #19#t stand for? (I guess the variable 5, but why is it called this way?)

---

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [December 4, 2017, 7:11pm UTC](https://discourse.julialang.org/t/horner-rule/7504/15 "2017-12-04T19:11:45Z")

</div>

> [@Diger](#):
>
> Wouldnt I expect it to show me this code? Maybe with numbers inserted?

It would really help if you read the documentation first, working through it carefully, then asked questions to fill in the holes.

---

<div class="post-metadata">

**Author:** ![Diger](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/diger/32/36786_2.png) [@Diger](https://discourse.julialang.org/u/Diger)\
**Post date:** [December 4, 2017, 7:15pm UTC](https://discourse.julialang.org/t/horner-rule/7504/16 "2017-12-04T19:15:00Z")

</div>

I am reading, but maybe you could show me the one crucial line telling me in [https://docs.julialang.org/en/stable/manual/metaprogramming/#Interpolation-1](https://docs.julialang.org/en/stable/manual/metaprogramming/#Interpolation-1) what the major advantage is doing it this way and not the “normal”

It just says it’s powerful…ok  
but why? I dont yet see it…

---

<div class="post-metadata">

**Author:** ![dpsanders](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dpsanders/32/3573_2.png) [@dpsanders](https://discourse.julialang.org/u/dpsanders)\
**Post date:** [December 4, 2017, 7:21pm UTC](https://discourse.julialang.org/t/horner-rule/7504/17 "2017-12-04T19:21:38Z")

</div>

What would the “normal” way be? Try that, and compare it to what the macro does, e.g. in terms of speed.

---

<div class="post-metadata">

**Author:** ![Diger](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/diger/32/36786_2.png) [@Diger](https://discourse.julialang.org/u/Diger)\
**Post date:** [December 4, 2017, 7:45pm UTC](https://discourse.julialang.org/t/horner-rule/7504/18 "2017-12-04T19:45:43Z")

</div>

```julia
macro horner01(x, p...)
    ex = p[end]
    for i = length(p)-1:-1:1
        ex = :($(p[i]) + $x * $ex)
    end
    ex
end

function horner02(x, p::Array)
    ex = p[end]
    for i = length(p)-1:-1:1
        ex = ((p[i]) + x * ex)
    end
    ex
end

setprecision(10^8)
x=big(9528)/10000

@time @horner01(x,4,3,2,1);
@time horner02(x,[4,3,2,1]);

```

So here it is not faster…Why should it be faster?

BTW: if I change function to macro it does not like this p::Array, why?

Also it is telling me

WARNING: Method definition @horner01(ANY\<:Any, Any…) in module Main at C:\Users\Diger\Documents\Julia\various math problems\compare horner.jl:2 overwritten at C:\Users\Diger\Documents\Julia\various math problems\compare horner.jl:2.  
WARNING: Method definition horner02(Any, Array{Int64, 1}) in module Main at C:\Users\Diger\Documents\Julia\various math problems\compare horner.jl:10 overwritten at C:\Users\Diger\Documents\Julia\various math problems\compare horner.jl:10.

even though I renamed the functions?!

---

<div class="post-metadata">

**Author:** ![kristoffer.carlsson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kristoffer.carlsson/32/22_2.png) [@kristoffer.carlsson](https://discourse.julialang.org/u/kristoffer.carlsson)\
**Post date:** [December 4, 2017, 8:03pm UTC](https://discourse.julialang.org/t/horner-rule/7504/19 "2017-12-04T20:03:22Z")

</div>

```julia
julia> using BenchmarkTools

julia> f(x) = Base.Math.@horner(x, 4, 3, 2, 1)
f (generic function with 1 method)

julia> @btime f(0.2)
  1.847 ns (0 allocations: 0 bytes)
4.688

julia> v = [4., 3., 2., 1.]
4-element Array{Float64,1}:
 4.0
 3.0
 2.0
 1.0

julia> function horner02(x, p::Array)
           ex = p[end]
           for i = length(p)-1:-1:1
               ex = ((p[i]) + x * ex)
           end
           ex
       end
horner02 (generic function with 1 method)

julia> @btime horner02(0.2, $v)
  12.850 ns (0 allocations: 0 bytes)
4.688

```

---

<div class="post-metadata">

**Author:** ![Diger](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/diger/32/36786_2.png) [@Diger](https://discourse.julialang.org/u/Diger)\
**Post date:** [December 4, 2017, 8:19pm UTC](https://discourse.julialang.org/t/horner-rule/7504/20 "2017-12-04T20:19:27Z")

</div>

I’m actually not really worried about 1ns or even 1000ns, but when I goes in the seconds range I’m…  
So repeating your first function

```julia
f(x) = Base.Math.@horner(x, 4, 3, 2, 1);
@time f(x);

```

where x is the bigfloat I defined before.  
This gives me sth like 4.2s as does the other.

Why do you prefer working with some external benchmarking package, rather than using what comes with julia?

[Next page](https://discourse.julialang.org/t/horner-rule/7504.md?page=2)
