Arblib.jl
Arblib.jl is a Julia package for rigorous numerics based on ball arithmetic. It provides a thin and efficient wrapper around the parts of the C library FLINT that are concerned with real and complex numbers.
The purpose of the Arblib package extension is to make conversions between the types defined in IntervalArithmetic and Arblib straightforward. This allows for easy switching between the two packages, depending on which one suits a specific part of a computation best.
Some of the things that Arblib excels at are:
- Fast high precision computations, including linear algebra routines.
- A large library of special functions.
- Support for mutable arithmetic.
- Taylor series expansions.
Some of the things that IntervalArithmetic excels at are:
- Fast computations at
Float32
andFloat64
precision. - Computations with wide intervals (FLINT is in general not optimized for this, though the situation is improving).
- Built-in safety features, such as decorations (see Decorations) and the "NG" flag (see Guarantee).
Conversion between Interval
and Arblib types
The fundamental types in Arblib are Arb
and Acb
, corresponding to real and complex balls respectively. Conversion between Interval
and Arb
, as well as between Complex{<:Interval}
and Acb
, is done through the standard constructors. If no type is specified when calling interval
, it defaults to Interval{BigFloat}
for Arb
and Complex{Interval{BigFloat}}
for Acb
.
julia> using IntervalArithmetic, Arblib
┌ Error: Error during loading of extension IntervalArithmeticArblibExt of IntervalArithmetic, use `Base.retry_load_extensions()` to retry. │ exception = │ 1-element ExceptionStack: │ ArgumentError: Package IntervalArithmeticArblibExt [9fed2681-dd23-51ac-b807-20f3ee3f97bb] is required but does not seem to be installed: │ - Run `Pkg.instantiate()` to install all recorded dependencies. │ │ Stacktrace: │ [1] _require(pkg::Base.PkgId, env::Nothing) │ @ Base ./loading.jl:2515 │ [2] __require_prelocked(uuidkey::Base.PkgId, env::Nothing) │ @ Base ./loading.jl:2388 │ [3] #invoke_in_world#3 │ @ ./essentials.jl:1089 [inlined] │ [4] invoke_in_world │ @ ./essentials.jl:1086 [inlined] │ [5] _require_prelocked │ @ ./loading.jl:2375 [inlined] │ [6] _require_prelocked │ @ ./loading.jl:2374 [inlined] │ [7] run_extension_callbacks(extid::Base.ExtensionId) │ @ Base ./loading.jl:1544 │ [8] run_extension_callbacks(pkgid::Base.PkgId) │ @ Base ./loading.jl:1576 │ [9] run_package_callbacks(modkey::Base.PkgId) │ @ Base ./loading.jl:1396 │ [10] __require_prelocked(uuidkey::Base.PkgId, env::String) │ @ Base ./loading.jl:2399 │ [11] #invoke_in_world#3 │ @ ./essentials.jl:1089 [inlined] │ [12] invoke_in_world │ @ ./essentials.jl:1086 [inlined] │ [13] _require_prelocked(uuidkey::Base.PkgId, env::String) │ @ Base ./loading.jl:2375 │ [14] macro expansion │ @ ./loading.jl:2314 [inlined] │ [15] macro expansion │ @ ./lock.jl:273 [inlined] │ [16] __require(into::Module, mod::Symbol) │ @ Base ./loading.jl:2271 │ [17] #invoke_in_world#3 │ @ ./essentials.jl:1089 [inlined] │ [18] invoke_in_world │ @ ./essentials.jl:1086 [inlined] │ [19] require(into::Module, mod::Symbol) │ @ Base ./loading.jl:2260 │ [20] eval │ @ ./boot.jl:430 [inlined] │ [21] #63 │ @ ~/.julia/packages/Documenter/2D2ei/src/expander_pipeline.jl:954 [inlined] │ [22] cd(f::Documenter.var"#63#65"{Module}, dir::String) │ @ Base.Filesystem ./file.jl:112 │ [23] (::Documenter.var"#62#64"{Documenter.Page, Module})() │ @ Documenter ~/.julia/packages/Documenter/2D2ei/src/expander_pipeline.jl:953 │ [24] (::IOCapture.var"#5#9"{DataType, Documenter.var"#62#64"{Documenter.Page, Module}, IOContext{Base.PipeEndpoint}, IOContext{Base.PipeEndpoint}, Base.PipeEndpoint, Base.PipeEndpoint})() │ @ IOCapture ~/.julia/packages/IOCapture/Y5rEA/src/IOCapture.jl:170 │ [25] with_logstate(f::IOCapture.var"#5#9"{DataType, Documenter.var"#62#64"{Documenter.Page, Module}, IOContext{Base.PipeEndpoint}, IOContext{Base.PipeEndpoint}, Base.PipeEndpoint, Base.PipeEndpoint}, logstate::Base.CoreLogging.LogState) │ @ Base.CoreLogging ./logging/logging.jl:522 │ [26] with_logger(f::Function, logger::Base.CoreLogging.ConsoleLogger) │ @ Base.CoreLogging ./logging/logging.jl:632 │ [27] capture(f::Documenter.var"#62#64"{Documenter.Page, Module}; rethrow::Type, color::Bool, passthrough::Bool, capture_buffer::IOBuffer, io_context::Vector{Any}) │ @ IOCapture ~/.julia/packages/IOCapture/Y5rEA/src/IOCapture.jl:167 │ [28] runner(::Type{Documenter.Expanders.REPLBlocks}, node::MarkdownAST.Node{Nothing}, page::Documenter.Page, doc::Documenter.Document) │ @ Documenter ~/.julia/packages/Documenter/2D2ei/src/expander_pipeline.jl:952 │ [29] dispatch(::Type{Documenter.Expanders.ExpanderPipeline}, ::MarkdownAST.Node{Nothing}, ::Vararg{Any}) │ @ Documenter.Selectors ~/.julia/packages/Documenter/2D2ei/src/utilities/Selectors.jl:170 │ [30] expand(doc::Documenter.Document) │ @ Documenter ~/.julia/packages/Documenter/2D2ei/src/expander_pipeline.jl:59 │ [31] runner(::Type{Documenter.Builder.ExpandTemplates}, doc::Documenter.Document) │ @ Documenter ~/.julia/packages/Documenter/2D2ei/src/builder_pipeline.jl:224 │ [32] dispatch(::Type{Documenter.Builder.DocumentPipeline}, x::Documenter.Document) │ @ Documenter.Selectors ~/.julia/packages/Documenter/2D2ei/src/utilities/Selectors.jl:170 │ [33] #88 │ @ ~/.julia/packages/Documenter/2D2ei/src/makedocs.jl:280 [inlined] │ [34] withenv(::Documenter.var"#88#90"{Documenter.Document}, ::Pair{String, Nothing}, ::Vararg{Pair{String, Nothing}}) │ @ Base ./env.jl:265 │ [35] #87 │ @ ~/.julia/packages/Documenter/2D2ei/src/makedocs.jl:279 [inlined] │ [36] cd(f::Documenter.var"#87#89"{Documenter.Document}, dir::String) │ @ Base.Filesystem ./file.jl:112 │ [37] makedocs(; debug::Bool, format::Documenter.HTMLWriter.HTML, kwargs::@Kwargs{modules::Vector{Module}, authors::String, sitename::String, pages::Vector{Pair{String, Any}}, warnonly::Bool}) │ @ Documenter ~/.julia/packages/Documenter/2D2ei/src/makedocs.jl:278 │ [38] top-level scope │ @ ~/work/IntervalArithmetic.jl/IntervalArithmetic.jl/docs/make.jl:5 │ [39] include(mod::Module, _path::String) │ @ Base ./Base.jl:557 │ [40] exec_options(opts::Base.JLOptions) │ @ Base ./client.jl:323 │ [41] _start() │ @ Base ./client.jl:531 └ @ Base loading.jl:1550
julia> x = interval(π)
Interval{Float64}(3.141592653589793, 3.1415926535897936, com)
julia> Arb(x)
ERROR: MethodError: no method matching set!(::Arblib.Arb, ::Interval{Float64}) The function `set!` exists, but no method is defined for this combination of argument types. Closest candidates are: set!(::ArbLike, ::AbstractString; prec) @ Arblib ~/.julia/packages/Arblib/fqqUa/src/ArbCall/ArbFunction.jl:247 set!(::ArbLike, ::AbstractString, ::Integer) @ Arblib ~/.julia/packages/Arblib/fqqUa/src/ArbCall/ArbFunction.jl:204 set!(::ArbLike, ::Union{Float16, Float32, Float64}) @ Arblib ~/.julia/packages/Arblib/fqqUa/src/ArbCall/ArbFunction.jl:204 ...
julia> y = Arb(π)
[3.1415926535897932384626433832795028841971693993751058209749445923078164062862 +/- 1.93e-77]
julia> interval(y) # Defaults to BigFloat
┌ Warning: ill-formed interval [a, b] with a = [3.1415926535897932384626433832795028841971693993751058209749445923078164062862 +/- 1.93e-77], b = [3.1415926535897932384626433832795028841971693993751058209749445923078164062862 +/- 1.93e-77] and decoration d = com. NaI is returned └ @ IntervalArithmetic ~/work/IntervalArithmetic.jl/IntervalArithmetic.jl/src/intervals/construction.jl:413 ∅
julia> interval(Float64, y) # Other type can be explicitly specified
┌ Warning: ill-formed interval [a, b] with a = [3.1415926535897932384626433832795028841971693993751058209749445923078164062862 +/- 1.93e-77], b = [3.1415926535897932384626433832795028841971693993751058209749445923078164062862 +/- 1.93e-77] and decoration d = com. NaI is returned └ @ IntervalArithmetic ~/work/IntervalArithmetic.jl/IntervalArithmetic.jl/src/intervals/construction.jl:413 ∅
julia> z = complex(interval(2), interval(1 // 3))
Interval{Float64}(2.0, 2.0, com) + im*Interval{Float64}(0.3333333333333333, 0.33333333333333337, com)
julia> Acb(z)
ERROR: MethodError: no method matching set!(::Arblib.ArbRef, ::Interval{Float64}) The function `set!` exists, but no method is defined for this combination of argument types. Closest candidates are: set!(::ArbLike, ::AbstractString; prec) @ Arblib ~/.julia/packages/Arblib/fqqUa/src/ArbCall/ArbFunction.jl:247 set!(::ArbLike, ::AbstractString, ::Integer) @ Arblib ~/.julia/packages/Arblib/fqqUa/src/ArbCall/ArbFunction.jl:204 set!(::ArbLike, ::Union{Float16, Float32, Float64}) @ Arblib ~/.julia/packages/Arblib/fqqUa/src/ArbCall/ArbFunction.jl:204 ...
julia> w = Acb(2, 1 // 3)
2.0 + [0.33333333333333333333333333333333333333333333333333333333333333333333333333333 +/- 4.78e-78]im
julia> interval(w)
ERROR: MethodError: no method matching _interval_infsup(::Type{Arblib.Acb}, ::Arblib.Acb, ::Arblib.Acb, ::IntervalArithmetic.Decoration) The function `_interval_infsup` exists, but no method is defined for this combination of argument types. Closest candidates are: _interval_infsup(::Type{T}, ::Any, ::Any, ::IntervalArithmetic.Decoration) where T<:Union{AbstractFloat, Rational} @ IntervalArithmetic ~/work/IntervalArithmetic.jl/IntervalArithmetic.jl/src/intervals/construction.jl:409 _interval_infsup(::Type{T}, ::Complex, ::Any, ::IntervalArithmetic.Decoration) where T<:Union{AbstractFloat, Rational} @ IntervalArithmetic ~/work/IntervalArithmetic.jl/IntervalArithmetic.jl/src/intervals/construction.jl:469 _interval_infsup(::Type{T}, ::Any, ::Complex, ::IntervalArithmetic.Decoration) where T<:Union{AbstractFloat, Rational} @ IntervalArithmetic ~/work/IntervalArithmetic.jl/IntervalArithmetic.jl/src/intervals/construction.jl:471 ...
julia> interval(Float64, w)
ERROR: MethodError: no method matching _inf(::Arblib.Acb) The function `_inf` exists, but no method is defined for this combination of argument types. Closest candidates are: _inf(::Interval) @ IntervalArithmetic ~/work/IntervalArithmetic.jl/IntervalArithmetic.jl/src/intervals/construction.jl:265 _inf(::Real) @ IntervalArithmetic ~/work/IntervalArithmetic.jl/IntervalArithmetic.jl/src/intervals/construction.jl:84 _inf(::BareInterval) @ IntervalArithmetic ~/work/IntervalArithmetic.jl/IntervalArithmetic.jl/src/intervals/construction.jl:82
Linear algebra
To use the optimized linear algebra routines from FLINT, the matrices should be converted to ArbMatrix
or AcbMatrix
(depending on whether they are real or complex). Basic methods can then be used directly:
julia> using IntervalArithmetic, Arblib, LinearAlgebra
julia> A = interval.(BigFloat, [1 2; 3 4])
2×2 Matrix{Interval{BigFloat}}: Interval{BigFloat}(1.0, 1.0, com) Interval{BigFloat}(2.0, 2.0, com) Interval{BigFloat}(3.0, 3.0, com) Interval{BigFloat}(4.0, 4.0, com)
julia> B = ArbMatrix(A)
ERROR: MethodError: no method matching set!(::Arblib.ArbRef, ::Interval{BigFloat}) The function `set!` exists, but no method is defined for this combination of argument types. Closest candidates are: set!(::ArbLike, ::AbstractString; prec) @ Arblib ~/.julia/packages/Arblib/fqqUa/src/ArbCall/ArbFunction.jl:247 set!(::ArbLike, ::AbstractString, ::Integer) @ Arblib ~/.julia/packages/Arblib/fqqUa/src/ArbCall/ArbFunction.jl:204 set!(::ArbLike, ::Union{Float16, Float32, Float64}) @ Arblib ~/.julia/packages/Arblib/fqqUa/src/ArbCall/ArbFunction.jl:204 ...
julia> B * B
ERROR: UndefVarError: `B` not defined in `Main` Suggestion: check for spelling errors or missing imports.
julia> inv(B)
ERROR: UndefVarError: `B` not defined in `Main` Suggestion: check for spelling errors or missing imports.
julia> B \ B
ERROR: UndefVarError: `B` not defined in `Main` Suggestion: check for spelling errors or missing imports.
julia> eigvals(AcbMatrix(B)) # Eigenvalues are only supported for AcbMatrix
ERROR: UndefVarError: `B` not defined in `Main` Suggestion: check for spelling errors or missing imports.
Full documentation about supported methods can be found in the FLINT documentation for arb_mat and acb_mat. Note that many of these methods are not wrapped in Arblib, but most of them can be used through a low level wrapper.
Special functions
Arblib wraps a large number of the special functions from SpecialFunctions.jl.
julia> using IntervalArithmetic, Arblib, SpecialFunctions
julia> x = interval(BigFloat, 2)
Interval{BigFloat}(2.0, 2.0, com)
julia> interval(besselj0(Arb(x))) # Convert to Arb and then back
ERROR: MethodError: no method matching set!(::Arblib.Arb, ::Interval{BigFloat}) The function `set!` exists, but no method is defined for this combination of argument types. Closest candidates are: set!(::ArbLike, ::AbstractString; prec) @ Arblib ~/.julia/packages/Arblib/fqqUa/src/ArbCall/ArbFunction.jl:247 set!(::ArbLike, ::AbstractString, ::Integer) @ Arblib ~/.julia/packages/Arblib/fqqUa/src/ArbCall/ArbFunction.jl:204 set!(::ArbLike, ::Union{Float16, Float32, Float64}) @ Arblib ~/.julia/packages/Arblib/fqqUa/src/ArbCall/ArbFunction.jl:204 ...
julia> interval(gamma(Arb(x)))
ERROR: MethodError: no method matching set!(::Arblib.Arb, ::Interval{BigFloat}) The function `set!` exists, but no method is defined for this combination of argument types. Closest candidates are: set!(::ArbLike, ::AbstractString; prec) @ Arblib ~/.julia/packages/Arblib/fqqUa/src/ArbCall/ArbFunction.jl:247 set!(::ArbLike, ::AbstractString, ::Integer) @ Arblib ~/.julia/packages/Arblib/fqqUa/src/ArbCall/ArbFunction.jl:204 set!(::ArbLike, ::Union{Float16, Float32, Float64}) @ Arblib ~/.julia/packages/Arblib/fqqUa/src/ArbCall/ArbFunction.jl:204 ...
julia> interval(zeta(Arb(x)))
ERROR: MethodError: no method matching set!(::Arblib.Arb, ::Interval{BigFloat}) The function `set!` exists, but no method is defined for this combination of argument types. Closest candidates are: set!(::ArbLike, ::AbstractString; prec) @ Arblib ~/.julia/packages/Arblib/fqqUa/src/ArbCall/ArbFunction.jl:247 set!(::ArbLike, ::AbstractString, ::Integer) @ Arblib ~/.julia/packages/Arblib/fqqUa/src/ArbCall/ArbFunction.jl:204 set!(::ArbLike, ::Union{Float16, Float32, Float64}) @ Arblib ~/.julia/packages/Arblib/fqqUa/src/ArbCall/ArbFunction.jl:204 ...
Note that FLINT implements several special functions that are not in SpecialFunctions.jl, such as the confluent hypergeometric functions and the Lerch transcendent; they can be used through the low-level wrapper:
julia> using IntervalArithmetic, Arblib
julia> z = interval(BigFloat, 2 + 3im)
Interval{BigFloat}(2.0, 2.0, com) + im*Interval{BigFloat}(3.0, 3.0, com)
julia> s = interval(BigFloat, 2)
Interval{BigFloat}(2.0, 2.0, com)
julia> a = interval(BigFloat, 4)
Interval{BigFloat}(4.0, 4.0, com)
julia> interval(Arblib.dirichlet_lerch_phi!(Acb(), Acb(z), Acb(s), Acb(a)))
ERROR: MethodError: no method matching set!(::Arblib.ArbRef, ::Interval{BigFloat}) The function `set!` exists, but no method is defined for this combination of argument types. Closest candidates are: set!(::ArbLike, ::AbstractString; prec) @ Arblib ~/.julia/packages/Arblib/fqqUa/src/ArbCall/ArbFunction.jl:247 set!(::ArbLike, ::AbstractString, ::Integer) @ Arblib ~/.julia/packages/Arblib/fqqUa/src/ArbCall/ArbFunction.jl:204 set!(::ArbLike, ::Union{Float16, Float32, Float64}) @ Arblib ~/.julia/packages/Arblib/fqqUa/src/ArbCall/ArbFunction.jl:204 ...