Manual

using PrecisionCarriers

Precify

Create a PrecisionCarrier object from any floating point by using precify:

p = precify(1.0)
1.0 <ε=0>

By default, precify uses the type of the given floating point:

typeof(precify(1.0f0))
PrecisionCarrier{Float32}
typeof(precify(Float16(1.0)))
PrecisionCarrier{Float16}

One can also specify the type:

typeof(precify(Float32, 1.0))
PrecisionCarrier{Float32}

All of these versions also work on array and tuple types:

precify((1.0, Float32(2.0), Float16(3.0)))
(1.0 <ε=0>, 2.0 <ε=0>, 3.0 <ε=0>)

The interface can also easily be extended for custom types by dispatching to all relevant members:

struct A
    x::AbstractFloat
end

PrecisionCarriers.precify(T::Type{<:PrecisionCarrier}, a::A) = A(precify(a.x))

precify(A(1.0))
Main.A(1.0 <ε=0>)

Arithmetic and Precision Estimation

The resulting precified object can be used like a normal floating point number:

p = atan((p + 10)^2 * pi)
1.56816567264686 <ε=0>

When displaying the result, the number of epsilons (ε) is calculated. It represents the number of machine precision of the underlying floating point type, that it differs relative to the arbitrary precision calculation.

p = tan(p)
380.13271108437925 <ε=169>

The result is also color graded to draw attention to values that have precision problems.

The number of significant digits remaining in the type can be calculated by using significant_digits:

significant_digits(p)
13.423110853148748

Finally, the precision carried can be reset using reset_eps!:

reset_eps!(p)
380.13271108437925 <ε=0>

This page was generated using Literate.jl.