Public Interface
PrecisionCarriers.PrecisionCarrierBase.eltypePrecisionCarriers.epsilonsPrecisionCarriers.precifyPrecisionCarriers.reset_eps!PrecisionCarriers.significant_digitsPrecisionCarriers.@bench_epsilons
Types
PrecisionCarriers.PrecisionCarrier — TypePrecisionCarrier{AbstractFloat}A carrier type for floating points. Most math functions are overloaded for this type. Initialize it with some value (or see precify to convert an entire array or tuple type of numbers), do some arithmetic with your value(s), and finally, print it to check the number of accumulated epsilons of error.
julia> using PrecisionCarriers
julia> function unstable(x, N)
y = abs(x)
for i in 1:N y = sqrt(y) end
w = y
for i in 1:N w = w^2 end
return w
end
unstable (generic function with 1 method)
julia> unstable(precify(2), 5)
1.9999999999999964 <ε=8>
julia> unstable(precify(2), 10)
2.0000000000000235 <ε=53>
julia> unstable(precify(2), 20)
2.0000000001573586 <ε=354340>
julia> unstable(precify(2), 128)
1.0 <ε=4503599627370496>
A precision carrier of BigFloat is allowed, but is mostly useful for functions that only use it intermediately. Using a carrier of BigFloat as input for a function will simply result in always 0 ε error reported. Also note that in this case, epsilons is not implemented, because BigFloat does not have a type epsilon.
Macros
PrecisionCarriers.@bench_epsilons — Macro@bench_epsilons(call_expr, args...)Benchmark the epsilons of a given function call.
The first argument should be a function call, with variables from local context interpolated, and arguments that should be sampled defined in a ranges = begin ... end block. In the ranges block, every variable must be assigned a Tuple of a lower and an upper bound for values that should be sampled.
using PrecisionCarriers
foo(x, y) = sqrt(x^2 - y^2)
@bench_epsilons foo(1.0, y) ranges = begin
y = (0.5, 1.0)
end samples = 1000 epsilon_limit = 10Returned is an object containing information about the benchmark results that can be displayed to a terminal similar to BenchmarkTools' @benchmark.
Supported keyword arguments:
search_method: How the sampling should be done. Supported are::pseudo_random: Create pseudo-random sample points in the search space using Sobol.jl.:evenly_spaced: Creates an evenly spaced grid across all ranges:random: Randomly samples points in the given ranges.
:pseudo_random.samples: The number of samples taken. Default: 10000epsilon_limit: Results with epsilons larger than this will be stored together with the arguments that produced the imprecise result. Default: 1000keep_n_values: Maximum number of imprecise results that will be stored.
Functions
PrecisionCarriers.precify — Functionprecify([::Type{PrecisionCarrier{T}}], t::Any) where {T<:AbstractFloat}
precify([::Type{T}], t::Any) where {T<:AbstractFloat}Convert a number or container to a container of PrecisionCarriers. If no specific float type for the PrecisionCarrier is specified, the type of ts floats will be used.
julia> using PrecisionCarriers
julia> precify((0, 1.0, 2.0f0))
(0.0 <ε=0>, 1.0 <ε=0>, 2.0 <ε=0>)
julia> typeof(ans)
Tuple{PrecisionCarrier{Float64}, PrecisionCarrier{Float64}, PrecisionCarrier{Float32}}
julia> precify(PrecisionCarrier{Float32}, [0, 1.0, 2.0f0])
3-element Vector{PrecisionCarrier{Float32}}:
0.0 <ε=0>
1.0 <ε=0>
2.0 <ε=0>
PrecisionCarriers.epsilons — Functionepsilons(p::PrecisionCarrier{T})Return the number of epsilons of relative difference between p.big and p.x as an EpsT (Int64) value.
Returns EpsMax (typemax(Int64)) if the difference is infinite, for example when the float reports Inf and the BigT has a non-infinite value.
PrecisionCarriers.significant_digits — Functionsignificant_digits(p::PrecisionCarrier{T})Return the number of significant decimal digits currently carried by this PrecisionCarrier.
julia> using PrecisionCarriers
julia> function unstable(x, N)
y = abs(x)
for i in 1:N y = sqrt(y) end
w = y
for i in 1:N w = w^2 end
return w
end
unstable (generic function with 1 method)
julia> unstable(precify(0.5), 30)
0.4999999971854335 <ε=25351362>
julia> significant_digits(ans)
8.249558483913594PrecisionCarriers.reset_eps! — Functionreset_eps!(p::PrecisionCarrier{AbstractFloat})Reset the precision carrier to zero epsilons. Can be called on containers (AbstractArrays or Tuples) to reset all underlying PrecisionCarriers.
julia> using PrecisionCarriers
julia> function unstable(x, N)
y = abs(x)
for i in 1:N y = sqrt(y) end
w = y
for i in 1:N w = w^2 end
return w
end
unstable (generic function with 1 method)
julia> p = unstable(precify(1.5), 30)
1.4999996689838975 <ε=993842883>
julia> reset_eps!(p)
1.4999996689838975 <ε=0>Custom types can be overloaded by implementing a function dispatching the call downwards to all relevant members. Note that this is a muting operation and therefore requires mutability of the members.
function reset_eps!(x::Custom)
reset_eps!(x.v1)
reset_eps!(x.v2)
# ...
return x
endBase.eltype — FunctionBase.eltype(::PrecisionCarrier)Return the internally carried floating point type.