# \[ANN\] MPFR\_wrap.jl

**URL:** https://discourse.julialang.org/t/ann-mpfr-wrap-jl/41372
**Category:** Community
**Tags:** package, announcement
**Created:** [June 14, 2020, 2:13pm UTC](https://discourse.julialang.org/t/ann-mpfr-wrap-jl/41372 "2020-06-14T14:13:33Z")
**Posts on this page:** 12
**Page:** 1

<div class="post-metadata">

### Author: ![mzaffalon](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mzaffalon/32/214168_2.png) [@mzaffalon](https://discourse.julialang.org/u/mzaffalon)
#### Post date: [June 14, 2020, 2:13pm UTC](https://discourse.julialang.org/t/ann-mpfr-wrap-jl/41372/1 "2020-06-14T14:13:33Z")

</div>

Hello everyone,

I would like to announce [MPFR\_wrap.jl](https://github.com/mzaffalon/MPFR_wrap.jl), a set of wrappers around [MPFR](https://www.mpfr.org/), a multiple-precision floating-point library for in-place computation. `MPFR_wrap.jl` does not introduce new types and makes instead use of Julia’s `BigFloat`s.

# Example

Most operations defined in Base on `BigFloat`s however allocate temporary variables. Consider the computation of `sqrt(a+b)`: a new `BigFloat` is allocated to hold the result of `a+b`. Using `MPFR_wrap`, one can do

```julia-auto
add!(a, a, b) # a ← a + b
sqrt!(a, a) # a ← sqrt(a)

```

provided the content of `a` can be overwritten.

## Installation

The package is not registered yet: if you want to give it a try, at the package prompt (“]”), type

```julia-auto
(@v1.4) pkg> add https://github.com/mzaffalon/MPFR_wrap.jl

```

This is my first public module: feedback is welcome.

## Background

This module was born out of curiosity to implement the computation of pi using iterative methods as explained in [this review](https://www.davidhbailey.com/dhbpapers/pi-formulas.pdf) by David H. Bailey and to compare with the timings of table 3.

The in-place computation of pi to 100\_000 digits takes 130ms on my laptop, compared to 350ms using the operations defined in Base; a substantial difference between the two methods can be seen when one consider allocations: 400 kB compared to 12 **MB**.

Disclaimer: I am not an expert in the computation of pi.

---

<div class="post-metadata">

### Author: ![dpsanders](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dpsanders/32/3573_2.png) [@dpsanders](https://discourse.julialang.org/u/dpsanders)
#### Post date: [June 14, 2020, 2:45pm UTC](https://discourse.julialang.org/t/ann-mpfr-wrap-jl/41372/2 "2020-06-14T14:45:35Z")

</div>

Thanks for doing this!

I’m actually happy to see that the non-in-place versions that I get by just using `BigFloat` with a nice syntax are losing less than a factor of 3 in performance; I thought it might be much more than that.

---

<div class="post-metadata">

### Author: ![mzaffalon](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mzaffalon/32/214168_2.png) [@mzaffalon](https://discourse.julialang.org/u/mzaffalon)
#### Post date: [June 14, 2020, 2:48pm UTC](https://discourse.julialang.org/t/ann-mpfr-wrap-jl/41372/3 "2020-06-14T14:48:23Z")

</div>

This may have something to do with [this commit](https://github.com/JuliaLang/julia/commit/2644f79b7f795a2e3edb35bd326e9c8265d24464#diff-36e231a81085611e7c32e96cb6aa1491),

> Using that allows us to use our fast memory-pool gc and avoid adding finalizers and use the slow malloc/free functions. (and in some cases, some of it might even end up on the stack!)

although I haven’t tested it.

---

<div class="post-metadata">

### Author: ![dpsanders](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dpsanders/32/3573_2.png) [@dpsanders](https://discourse.julialang.org/u/dpsanders)
#### Post date: [June 14, 2020, 2:48pm UTC](https://discourse.julialang.org/t/ann-mpfr-wrap-jl/41372/4 "2020-06-14T14:48:44Z")

</div>

Now all you need is a macro that can convert code written with normal syntax like `a += b` into in-place code.

---

<div class="post-metadata">

### Author: ![mzaffalon](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mzaffalon/32/214168_2.png) [@mzaffalon](https://discourse.julialang.org/u/mzaffalon)
#### Post date: [June 14, 2020, 2:52pm UTC](https://discourse.julialang.org/t/ann-mpfr-wrap-jl/41372/5 "2020-06-14T14:52:39Z")

</div>

I have been wondering if `c ← a + b` and `a ← sqrt(a)` are a better idea, but this is above my pay grade.

With dot notation, I don’t know how to do `b ← a - b`.

---

<div class="post-metadata">

### Author: ![simeonschaub](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/simeonschaub/32/216566_2.png) [@simeonschaub](https://discourse.julialang.org/u/simeonschaub)
#### Post date: [June 14, 2020, 3:14pm UTC](https://discourse.julialang.org/t/ann-mpfr-wrap-jl/41372/6 "2020-06-14T15:14:50Z")

</div>

It would probably be possible to overload the broadcast machinery here, so that `a .+= b` would do inplace addition. That should even be possible with `sqrt`, although I am not 100% sure how robust such a solution would be overall.

---

<div class="post-metadata">

### Author: ![simeonschaub](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/simeonschaub/32/216566_2.png) [@simeonschaub](https://discourse.julialang.org/u/simeonschaub)
#### Post date: [June 14, 2020, 3:25pm UTC](https://discourse.julialang.org/t/ann-mpfr-wrap-jl/41372/7 "2020-06-14T15:25:59Z")

</div>

It’s fun to be a pirate! 🏴‍☠️ 😆

```julia
julia> using MPFR_wrap

julia> Base.copyto!(a::BigFloat, b::Base.Broadcast.Broadcasted{<:Any,<:Any,typeof(+)}) = add!(a, b.args...)

julia> big"1.2" .+= big"2.3"
3.5

```

---

<div class="post-metadata">

### Author: ![kristoffer.carlsson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kristoffer.carlsson/32/22_2.png) [@kristoffer.carlsson](https://discourse.julialang.org/u/kristoffer.carlsson)
#### Post date: [June 14, 2020, 4:24pm UTC](https://discourse.julialang.org/t/ann-mpfr-wrap-jl/41372/8 "2020-06-14T16:24:39Z")

</div>

> [@dpsanders](#):
>
> Now all you need is a macro that can convert code written with normal syntax like `a += b` into in-place code.

The problem is if you would write

```julia
c = a
a += b

```

since now `c` gets modified (since it is the same object as `a`).

---

<div class="post-metadata">

### Author: ![DNF](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dnf/32/10191_2.png) [@DNF](https://discourse.julialang.org/u/DNF)
#### Post date: [June 14, 2020, 4:47pm UTC](https://discourse.julialang.org/t/ann-mpfr-wrap-jl/41372/9 "2020-06-14T16:47:19Z")

</div>

This is quite nice!

> [@mzaffalon](#):
>
> ```julia
> add!(a, a, b) # a ← a + b
> sqrt!(a, a) # a ← sqrt(a)
> 
> ```

How about

```julia
add!(a, b) # same as add!(a, a, b) 
sqrt!(a) # same as sqrt!(a, a) 

```

?

---

<div class="post-metadata">

### Author: ![simeonschaub](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/simeonschaub/32/216566_2.png) [@simeonschaub](https://discourse.julialang.org/u/simeonschaub)
#### Post date: [June 14, 2020, 5:33pm UTC](https://discourse.julialang.org/t/ann-mpfr-wrap-jl/41372/10 "2020-06-14T17:33:01Z")

</div>

Taking the broadcasting idea a bit further:

```julia
using MPFR_wrap
using Base.Broadcast: Broadcasted

mutating!(::typeof(-), dest, x) = neg!(dest, x)
mutating!(::typeof(abs), dest, x) = abs!(dest, x)
for f in (
    :sqrt, :cbrt,
    :log, :log2, :log10, :log1p, :exp, :exp2, :exp10, :expm1,
    :cos, :sin, :tan, :sec, :csc, :cot, :acos, :asin, :atan,
    :cosh, :sinh, :tanh, :sech, :csch, :coth, :acosh, :asinh, :atanh,
)
    @eval mutating!(::typeof($f), dest, x) = $(Symbol(f, :!))(dest, x)
end

mutating!(::typeof(+), dest, x, y) = add!(dest, x, y)
mutating!(::typeof(-), dest, x, y) = sub!(dest, x, y)
mutating!(::typeof(*), dest, x, y) = mul!(dest, x, y)
mutating!(::typeof(/), dest, x, y) = div!(dest, x, y)
mutating!(::typeof(^), dest, x, y) = pow!(dest, x, y)

function Base.copyto!(dest::BigFloat, b::Broadcasted)
    dest_modified = false
    args = (
       if i isa Broadcasted
           copyto!(dest_modified ? zero(dest) : (dest_modified=true; dest), i)
       else
           i 
       end for i in b.args
    )
    return mutating!(b.f, dest, args...)
end

```

This should work for nested functions as well:

```julia
julia> big"0." .= sqrt.(big"9.") ./ cbrt.(big"8.")
1.5

```

---

<div class="post-metadata">

### Author: ![mzaffalon](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mzaffalon/32/214168_2.png) [@mzaffalon](https://discourse.julialang.org/u/mzaffalon)
#### Post date: [June 14, 2020, 6:27pm UTC](https://discourse.julialang.org/t/ann-mpfr-wrap-jl/41372/11 "2020-06-14T18:27:22Z")

</div>

I am mimicking MPFR’s API, which exposes `add!(c, a, b)`, `sqrt!(c, a)`.

Are you suggesting `add!(a, b)` to avoid typing twice the same variable?

---

<div class="post-metadata">

### Author: ![DNF](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dnf/32/10191_2.png) [@DNF](https://discourse.julialang.org/u/DNF)
#### Post date: [June 14, 2020, 6:43pm UTC](https://discourse.julialang.org/t/ann-mpfr-wrap-jl/41372/12 "2020-06-14T18:43:29Z")

</div>

Yes. I belive I’ve seen this pattern a few times, that there are two versions, `foo!(b, a)` and `foo!(a)`, equal to `foo!(a, a)`.
