# \[ANN\] Arblib.jl

**URL:** <https://discourse.julialang.org/t/ann-arblib-jl/106160>\
**Category:** Package Announcements\
**Created:** [November 13, 2023, 7:25pm UTC](https://discourse.julialang.org/t/ann-arblib-jl/106160 "2023-11-13T19:25:23Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![joeldahne](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/joeldahne/32/45861_2.png) [@joeldahne](https://discourse.julialang.org/u/joeldahne)\
**Post date:** [November 13, 2023, 7:25pm UTC](https://discourse.julialang.org/t/ann-arblib-jl/106160/1 "2023-11-13T19:25:23Z")

</div>

# Arblib.jl

Hello everyone! I’m pleased to announce the release of [Arblib.jl](https://github.com/kalmarek/Arblib.jl) version 1.0.0! Arblib.jl is a wrapper of [Arb](https://flintlib.org/doc/index_arb.html), a library for rigorous, arbitrary precision, numerics based on ball arithmetic. Since a few months back Arb is a part of [FLINT](https://flintlib.org/), before it was a separate library.

The goal of Arblib.jl is supply a low lever wrapper of the methods in Arb, as well as a high level interface. The low level wrapper should allow for writing methods using mutability, and with performance very close to that of those written in C. The high level interface should make it easy to use in generic Julia code, similarly to how `BigFloat` is a wrapper around the MPFR library. In addition, it should be possible to seamlessly switch between the high level interface and the low level wrapper when needed.

There are already multiple other wrappers for Arb, including [Nemo](https://github.com/Nemocas/Nemo.jl) and [ArbNumerics.jl](https://github.com/JeffreySarnoff/ArbNumerics.jl). Compared to both of these Arblib.jl has a stronger focus on mutability and the low level wrapper. The high level interface of Nemo is also mostly focused on the [AbstractAlgebra.jl](https://github.com/Nemocas/AbstractAlgebra.jl) universe.

Version 0.1.0 of the package was released in October 2020, so it has been a long time in the making!

## Examples

Some examples of the high level interface:

```julia-repl
julia> using Arblib, SpecialFunctions

julia> sin(Arb(1)) + exp(Acb(5, 4))^2 # Some elementary functions
[-3204.01004684383875410045781564841032005656259070096652381237542043151155723 +/- 3.31e-72] + [21792.06557805986636823313294686313092865354316154564677314220247182417305111 +/- 4.65e-72]im

julia> besselj(Arb(π), Arb(1 // 2)) # Some special functions
[0.00175952799476796625069318818831373840939006931720588178138608727360903797650 +/- 5.61e-78]

julia> Arblib.integrate(sin, 0, 10) # Integrate sin from 0 to 10
[1.83907152907645245225886394782406483451993016513316854683595373104879258687 +/- 5.15e-75]

julia> Arblib.integrate(z -> 1/z, Acb(1, -5), Acb(1, 5)) # Integrate 1/z from 1 - 5i to 1 + 5i
[+/- 2.02e-75] + [2.74680153389003172172254385288992229730199919179940161793956671182574846633 +/- 2.83e-75]im

```

Compare computing \sqrt{x^2 + y^2} using mutable arithmetic with the default.

```julia-repl
julia> using Arblib, BenchmarkTools

julia> x = Arb(1 // 3)
[0.33333333333333333333333333333333333333333333333333333333333333333333333333333 +/- 4.78e-78]

julia> y = Arb(1 // 5)
[0.20000000000000000000000000000000000000000000000000000000000000000000000000000 +/- 3.89e-78]

julia> res = zero(x)
0

julia> f(x, y) = sqrt(x^2 + y^2)
f (generic function with 1 method)

julia> f!(res, x, y) = begin
           Arblib.sqr!(res, x)
           Arblib.fma!(res, res, y, y)
           return Arblib.sqrt!(res, res)
       end
f! (generic function with 1 method)

julia> @benchmark f($x, $y) samples=10000 evals=500
BenchmarkTools.Trial: 6390 samples with 500 evaluations.
 Range (min … max): 624.406 ns … 379.276 μs ┊ GC (min … max): 0.00% … 83.71%
 Time (median): 814.207 ns ┊ GC (median): 0.00%
 Time (mean ± σ): 1.552 μs ± 10.335 μs ┊ GC (mean ± σ): 22.72% ± 3.46%

   ▂▆█▆▃▂                                                       
  █████████▇▅▅▅▄▃▃▃▃▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▁▂▂▂▂▂▂▂▂▁▂▁▂▂▂▂▁▂▁▂▁▁▂▂▁▂ ▃
  624 ns Histogram: frequency by time 2.96 μs <

 Memory estimate: 448 bytes, allocs estimate: 8.

julia> @benchmark f!($res, $x, $y) samples=10000 evals=500
BenchmarkTools.Trial: 10000 samples with 500 evaluations.
 Range (min … max): 371.404 ns … 12.993 μs ┊ GC (min … max): 0.00% … 0.00%
 Time (median): 462.204 ns ┊ GC (median): 0.00%
 Time (mean ± σ): 499.765 ns ± 309.469 ns ┊ GC (mean ± σ): 0.00% ± 0.00%

    ▇▅▅ █▄▁▂▁▁ ▁                                              
  ▆▂███▇████████▆█▅▅▅▄▄▄▃▃▃▃▂▂▂▂▂▂▂▁▁▂▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ ▃
  371 ns Histogram: frequency by time 952 ns <

 Memory estimate: 0 bytes, allocs estimate: 0.

```

---

<div class="post-metadata">

**Author:** ![Palli](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/palli/32/3380_2.png) [@Palli](https://discourse.julialang.org/u/Palli)\
**Post date:** [November 13, 2023, 9:53pm UTC](https://discourse.julialang.org/t/ann-arblib-jl/106160/2 "2023-11-13T21:53:41Z")

</div>

> [@joeldahne](#):
>
> the release of [Arblib.jl](https://github.com/kalmarek/Arblib.jl) version 1.0.0!

Is this in practice not a breaking change? I.e. if you only define (real) numbers, and use the basic arithmetic operators? Also if you use more e.g. the complex type and all operation, at least defined in standard Julia? An SpecialFunctions.jl?

I see e.g. one (seemingly obscure exception):

> <https://github.com/kalmarek/Arblib.jl/pull/168>
>
> This PR removes the use of \`XLike\` types in several places. This leads to breaki…ng changes since the methods are no longer defined for structs and pointers. This is in line with making the high level interface more focused on the high level types. It depends on #167.
> 
> The most notable change is the change to \`isequal\` (and \`==\`) for structs. They no longer compare equal to other types, so an \`arb\_struct\` is never equal to an \`Arb\` even if the underlying struct is the same. This fixes earlier problems with \`isequal\` not being transitive. Before we had
> \`\`\`julia
> julia\> isequal(Mag().mag, Mag())
> true
> 
> julia\> isequal(Mag(), Arb())
> true
> 
> julia\> isequal(Arb(), Arb().arb)
> true
> 
> julia\> isequal(Mag().mag, Arb().arb)
> false
> \`\`\`
> whereas we now have
> \`\`\`julia
> julia\> isequal(Mag().mag, Mag())
> false
> 
> julia\> isequal(Mag(), Arb())
> true
> 
> julia\> isequal(Arb(), Arb().arb)
> false
> 
> julia\> isequal(Mag().mag, Arb().arb)
> false
> \`\`\`
> With this change the \`hash\` methods for structs have also been reworked. They no longer give the same hash as for the non-struct types.
> 
> Other changes are reduced usage of \`XLike\` in some constructors a few other methods. Some argument types have also been slightly simplified in the process.

I was looking at what’s actually breaking (in the underlying library):  
[https://flintlib.org/doc/history.html#flint-3-0](https://flintlib.org/doc/history.html#flint-3-0)

> The C++ interface (flintxx) has been removed. This interface is now maintained in the separate repository [GitHub - flintlib/flintxx: C++ interface to FLINT (maintenance only)](https://github.com/flintlib/flintxx) (Edgar Costa).

That’s of no concern to Julia(?).

There are also minor changes in the C interface, but you’re not exposed top that if you limit yourself to the Julia wrapper, I think. Though since it’s included fron FLINT\_jll, I think you could actually call the C interface bypassing the Julia interface (and nothing stopping that such can be done)

If you had used the old C interface, then that might also be breaking then, but there’s no good reason do do such?

@JeffreySarnoff  
Is the new version better in some sense, e.g. faster? Should it be used instead of ArbNumberics.jl (which still uses older Arb\_jll that should still work).

I believe it may add some features, I’m thinking e.g. if you had just used ArbFloat from it.

I suppose Arb.jl is a little lighter dependency if you don’t need the add-ons. Should ArbNumerics.j wrap your library rather than Arb\_jll (or FLINT\_jll)?

Do both libraries default to the same precision, that I believe may be the underlying default? Which is lower than for MPFR (but can be set to same or higher)?

Arblib (like ArbNumerics) should be faster than Julia’s BigFloat in almost all cases, even at the same precision, certainly always faster with its default.

Though absolute fastest (if you only need larger than Float64):

> **[GitHub - dzhang314/MultiFloats.jl: Fast extended-precision floating-point...](https://github.com/dzhang314/MultiFloats.jl)**
>
> Fast extended-precision floating-point arithmetic for Julia - GitHub - dzhang314/MultiFloats.jl: Fast extended-precision floating-point arithmetic for Julia

It only supports basic arithmetic (not trigonometric), should always be accurate if I understood correctly, though doesn’t propagate `NaN`s or `Inf`s.

---

<div class="post-metadata">

**Author:** ![ericphanson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ericphanson/32/215186_2.png) [@ericphanson](https://discourse.julialang.org/u/ericphanson)\
**Post date:** [November 13, 2023, 11:56pm UTC](https://discourse.julialang.org/t/ann-arblib-jl/106160/3 "2023-11-13T23:56:22Z")

</div>

Have you seen [GitHub - jump-dev/MutableArithmetics.jl: Interface for arithmetics on mutable types in Julia](https://github.com/jump-dev/MutableArithmetics.jl) btw? It can be used to use the mutable API for BigFloats more easily from high-level code (and also generically, i.e. the code doesn’t need to know it is working with BigFloats).

---

<div class="post-metadata">

**Author:** ![joeldahne](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/joeldahne/32/45861_2.png) [@joeldahne](https://discourse.julialang.org/u/joeldahne)\
**Post date:** [November 14, 2023, 8:17am UTC](https://discourse.julialang.org/t/ann-arblib-jl/106160/4 "2023-11-14T08:17:29Z")

</div>

> Is this in practice not a breaking change?

Do you mean compared to 0.6.2? There are only a few breaking changes in this case, the most prominent one is that we no longer overload `Base.contains`, `Base.union` and `Base.intersect`, see [this PR](https://github.com/kalmarek/Arblib.jl/pull/172). The [release notes](https://github.com/kalmarek/Arblib.jl/releases/tag/v1.0.0) mention a few other breaking changes, but they are mostly if one uses the lower level interface. The FLINT 3.0 change had essentially no breaking changes from the point of view of Arblib.jl!

> Is the new version better in some sense, e.g. faster? Should it be used instead of ArbNumberics.jl (which still uses older Arb\_jll that should still work).

I would not say that it is not better, nor faster, than ArbNumerics.jl (except if one counts some of the performance improvements from FLINT 3.0, but I believe it would be mostly straightforward to update ArbNumerics.jl to use FLINT 3.0). Some of the key differences from my point of view are

1. ArbNumerics.jl makes the `Arf` type (in ArbNumerics.jl it is `ArbFloat`) actually usable. Arblib.jl only wraps what is implemented in Arb and that is very limited.
2. The low level interface of Arblib.jl is useful, if one wants to go down that path. But for a lot of code this is not needed.
3. ArbNumerics.jl keeps the precision in the type, whereas Arblib.jl keeps it in the struct. This has different performance tradeoffs. If one mixes different precisions it is easier to make Arblib.jl type-stable.

> Do both libraries default to the same precision, that I believe may be the underlying default? Which is lower than for MPFR (but can be set to same or higher)?

Arblib.jl defaults to 256 bits of precision, so same as `BigFloat`. The Arb library itself has no default precision.

> Arblib (like ArbNumerics) should be faster than Julia’s BigFloat in almost all cases, even at the same precision, certainly always faster with its default.

Numerically I believe `Arb` is faster in the vast majority of cases. However, the way `BigFloat` is implemented in Julia tends to make them much faster for garbage collection. This makes it more important to use mutable arithmetic for `Arb`. For example

```julia-repl
julia> using Arblib, BenchmarkTools

julia> @benchmark sum($BigFloat, $(1:10000))
BenchmarkTools.Trial: 5374 samples with 1 evaluation.
 Range (min … max): 846.110 μs … 2.001 ms ┊ GC (min … max): 0.00% … 51.80%
 Time (median): 885.866 μs ┊ GC (median): 0.00%
 Time (mean ± σ): 927.640 μs ± 187.374 μs ┊ GC (mean ± σ): 4.17% ± 10.03%

  ▆██▇▆▃ ▂
  ███████▅▁▃▃▁▁▃▁▁▁▁▁▁▁▁▁▁▁▁▁▁▃▁▁▁▁▁▁▁▁▁▁▁▁▃▃▃▁▄▆▆▇▇▇▇▆▆▆█▇██▇█ █
  846 μs Histogram: log(frequency) by time 1.84 ms <

 Memory estimate: 1.98 MiB, allocs estimate: 39999.

julia> @benchmark sum($Arb, $(1:10000))
BenchmarkTools.Trial: 2544 samples with 1 evaluation.
 Range (min … max): 469.879 μs … 147.426 ms ┊ GC (min … max): 0.00% … 83.47%
 Time (median): 489.538 μs ┊ GC (median): 0.00%
 Time (mean ± σ): 1.968 ms ± 8.951 ms ┊ GC (mean ± σ): 40.59% ± 8.75%

  █                                                              
  █▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▇█ █
  470 μs Histogram: log(frequency) by time 50.3 ms <

 Memory estimate: 1.22 MiB, allocs estimate: 20001.

```

MultiFloats.jl is a great package! I have made use of it for linear algebra computations at slightly higher than `Float64` precision, with good results! But as you say it only implement basic arithmetic.

---

<div class="post-metadata">

**Author:** ![joeldahne](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/joeldahne/32/45861_2.png) [@joeldahne](https://discourse.julialang.org/u/joeldahne)\
**Post date:** [November 14, 2023, 8:23am UTC](https://discourse.julialang.org/t/ann-arblib-jl/106160/5 "2023-11-14T08:23:13Z")

</div>

> Have you seen [GitHub - jump-dev/MutableArithmetics.jl: Interface for arithmetics on mutable types in Julia](https://github.com/jump-dev/MutableArithmetics.jl) btw? It can be used to use the mutable API for BigFloats more easily from high-level code (and also generically, i.e. the code doesn’t need to know it is working with BigFloats).

Yes! Our goal is to add support for this in Arblib.jl eventually. This is mentioned briefly in the [documentation](https://kalmarek.github.io/Arblib.jl/stable/interface-mutable/) and there is an [issue](https://github.com/kalmarek/Arblib.jl/issues/118) about it as well. It is mostly a question of someone finding the time and motivation to get it done!

However, to be fully usable for Arblib.jl one would need an implementation also for elementary and special functions, like `sin` and `SpecialFunctions.besselj`. My understanding is that MutableArithmetics.jl currently only covers basic arithmetic.

---

<div class="post-metadata">

**Author:** ![nsajko](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nsajko/32/221187_2.png) [@nsajko](https://discourse.julialang.org/u/nsajko)\
**Post date:** [November 15, 2023, 12:06am UTC](https://discourse.julialang.org/t/ann-arblib-jl/106160/6 "2023-11-15T00:06:43Z")

</div>

> [@joeldahne](#):
>
> My understanding is that MutableArithmetics.jl currently only covers basic arithmetic.

MA is both an interface and several implementations of the interface. While the `BigFloat` implementation in MA doesn’t support transcendental functions as of yet, I think, there’s nothing stopping you from adding support for any mathematical function for the MA implementation for your own types. It is simply a matter of adding some methods.

---

<div class="post-metadata">

**Author:** ![joeldahne](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/joeldahne/32/45861_2.png) [@joeldahne](https://discourse.julialang.org/u/joeldahne)\
**Post date:** [November 15, 2023, 7:43am UTC](https://discourse.julialang.org/t/ann-arblib-jl/106160/7 "2023-11-15T07:43:46Z")

</div>

That’s good to know! I have yet to take a closer look at the implementation details.

---

<div class="post-metadata">

**Author:** ![nsajko](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nsajko/32/221187_2.png) [@nsajko](https://discourse.julialang.org/u/nsajko)\
**Post date:** [November 15, 2023, 11:20am UTC](https://discourse.julialang.org/t/ann-arblib-jl/106160/8 "2023-11-15T11:20:03Z")

</div>

I made a small PR to show what I mean: [proof of concept MutableArithmetics support by nsajko · Pull Request #178 · kalmarek/Arblib.jl · GitHub](https://github.com/kalmarek/Arblib.jl/pull/178)
