Last active
February 7, 2017 20:39
-
-
Save fcard/4b887503a6313c410292c243d7223717 to your computer and use it in GitHub Desktop.
Muladd macro revised
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| macro muladd(ex) | |
| esc(to_muladd(ex)) | |
| end | |
| function to_muladd(ex) | |
| is_add_operation(ex) || return ex | |
| all_operands = ex.args[2:end] | |
| mul_operands = filter(is_mul_operation, all_operands) | |
| odd_operands = filter(x->!is_mul_operation(x), all_operands) | |
| muladd_operands = collect(zip( | |
| to_muladd.((x->x.args[2]).(mul_operands)), | |
| to_muladd.((x->x.args[3]).(mul_operands)))) | |
| if isempty(odd_operands) | |
| to_be_muladded = muladd_operands[1:end-1] | |
| last_operation = :($(muladd_operands[end][1]) * $(muladd_operands[end][2])) | |
| else | |
| to_be_muladded = muladd_operands | |
| last_operation = make_addition(odd_operands) | |
| end | |
| foldr(last_operation, to_be_muladded) do xs, r | |
| :($(Base.muladd)($(xs[1]), $(xs[2]), $r)) | |
| end | |
| end | |
| is_operation(ex::Expr, op::Symbol) = ex.head == :call && !isempty(ex.args) && ex.args[1] == op | |
| is_operation(ex, op::Symbol) = false | |
| is_add_operation(ex) = is_operation(ex, :+) | |
| is_mul_operation(ex) = is_operation(ex, :*) | |
| make_addition(args) = length(args) == 1 ? args[1] : Expr(:call, :+, args...) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| using Base.Test | |
| macro test_muladd(expr, expected) | |
| esc( | |
| quote | |
| @test $(muladd_string(expected)) == $(string(macroexpand(:(@muladd($expr))))) | |
| @test @muladd($expr) == $expr | |
| end | |
| ) | |
| end | |
| function muladd_string(expr) | |
| replacement = replace(string(:($muladd(1,2,3))), r"^(..*?)\(.*\)$", s"\1") | |
| replace(string(expr), "muladd", replacement) | |
| end | |
| let a=1,b=2,c=3,d=4, x=10,y=20,z=30 | |
| @test_muladd (a*b) (a*b) | |
| @test_muladd (a*b + c*d) (muladd(a,b,c*d)) | |
| @test_muladd (a*b + c*d + x*y) (muladd(a,b, muladd(c,d, x*y))) | |
| @test_muladd (a*b + z*(c*d + x*y)) (muladd(a,b, z*(muladd(c,d,x*y)))) | |
| @test_muladd (a*b + c*d + z) (muladd(a,b, muladd(c, d, z))) | |
| end |
Author
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
^^^under MIT license