I need help creating a macro that makes Julia evaluate my floating point expressions as BigFloat

I need a macro that takes any expression matching r"-?[0-9]+\Q.\E[0-9]+", and encloses it in a BigFloat constructor. For example, a macro that receives the source code below:

@my_macro function f()
	sum = 0.0
	x = 902.4
	y = -47.1
	for i in 1:20
		sum += x^2 + 4.3*y
	end
	return sum
end

and returns the following:

function f()
	sum = BigFloat("0.0")
	x = BigFloat("902.4")
	y = BigFloat("-47.1")
	for i in 1:20
		sum += x^2 + BigFloat("4.3")*y
	end
	return sum
end

Does the ChangePrecision package come close enough?

2 Likes

postwalk from GitHub - FluxML/MacroTools.jl: MacroTools provides a library of tools for working with Julia code and expressions. is great for this:

julia> expr = quote
         function f()
               sum = 0.0
               x = 902.4
               y = -47.1
               for i in 1:20
                       sum += x^2 + 4.3*y
               end
               return sum
         end
       end;

julia> using MacroTools: postwalk

julia> postwalk(x -> x isa Float64 ? Expr(:call, :BigFloat, string(x)) : x, expr)
quote
    #= REPL[13]:2 =#
    function f()
        #= REPL[13]:3 =#
        sum = BigFloat("0.0")
        #= REPL[13]:4 =#
        x = BigFloat("902.4")
        #= REPL[13]:5 =#
        y = BigFloat("-47.1")
        #= REPL[13]:6 =#
        for i = 1:20
            #= REPL[13]:7 =#
            sum += x ^ 2 + BigFloat("4.3") * y
        end
        #= REPL[13]:9 =#
        return sum
    end
end

You would just need to write a macro that calls postwalk on its input.

2 Likes

I tried to download the package, but got an error:

(@v1.4) pkg> add https://github.com/stevengj/ChangePrecision.jl
   Updating git-repo `https://github.com/stevengj/ChangePrecision.jl`
ERROR: could not find project file in package at https://github.com/stevengj/ChangePrecision.jl

Thanks anyway.

Thank you, it worked

julia> using MacroTools: postwalk

julia> macro big_float_precision(expr)
               return postwalk(x -> x isa Float64 ? Expr(:call, :BigFloat, string(x)) : x, expr)
       end
@big_float_precision (macro with 1 method)

julia> @big_float_precision function f()
               sum = 0.0
               x = 902.4
               y = -47.1
               for i in 1:20
                       sum += x^2 + 4.3*y
               end
               return sum
       end
f (generic function with 1 method)

julia> typeof(f())
BigFloat
2 Likes