In general, you don’t have to do anything. It should just work according to promotion rules.
For example, if you have a function like…
julia> foo(x, y) = x + y
foo (generic function with 1 method)
julia> typeof(foo(1.0, 2.0))
Float64
julia> typeof(foo(1.0, big"2.0"))
BigFloat
There really isn’t a need to specify the precision that the function should run in but just let that be determined by the types of your input arguments.
Now, there is a small caveat when it comes to constants or anything hard coded within the function. Irrational constants like pi
should also work to some degree depending on how they are used.
julia> foo(x, y) = x*pi + y
foo (generic function with 1 method)
If you use pi
like this because it is an irrational constant it will do the multiplication with x
in the precision of x
so there really isn’t something you need to do.
But if you do anything like…
julia> foo(x, y) = sqrt(pi/2)*x + y
foo (generic function with 1 method)
You should be careful because now the sqrt(pi/2)
will always be done in Float64
precision and rounded before multiplying with x
. So if you do any operations that could round your intermediate results your final answer won’t be in the full precision. To avoid this, it is probably best to have some type parameter that depends on your input arguments and make sure every constant is promoted to that type… so something like
julia> function foo(x,y)
T = promote_type(typeof(x), typeof(y))
return sqrt(T(pi)/2) * x + y
end
foo (generic function with 1 method)
Will be generic enough to work in any precision.
julia> typeof(foo(1.2f0, 1.3f0))
Float32
julia> typeof(foo(1.2f0, 1.3))
Float64
julia> typeof(foo(1.2, 1.3))
Float64
julia> typeof(foo(1.2, big"1.3"))
BigFloat
julia> typeof(foo(Float16(1.2), Float16(1.3)))
Float16