Promote on ArbFloat issue?

I am trying to make sure that all of my ArbFloats are with the same precision.
I do not understand why promote works like that:

a = ArbFloat(2, digits=200)
typeof(a)
# ArbFloat{691}
typeof.(promote(a, ArbFloat(0.0)))
# (ArbFloat{128}, ArbFloat{128})

I would expect that ArbFloat(0.0) would be promoted to ArbFloat{691}. Why is it not so?

It is implemented to do so:

promote_rule(::Type{ArbFloat{P}},::Type{ArbFloat{Q}}) where {P,Q} = P<Q ? ArbFloat{P} : ArbFloat{Q}

in libarb\promote.jl

@JeffreySarnoff maybe willing to answer the reasoning about it.

1 Like

My guess is: results of operations on arguments with different precision should have the lowest precision of all the arguments. Everything else would pretend a precision which isn’t there.

1 Like

makes sense to me

1 Like

You’re right!
That does make sense.
I guess that I would like to have the lower precision number passed with zeros at the end.
For example, if I have something like this:

a=ArbFloat(0.2, bits=100)
b=ArbFloat(0.3, bits=1000)
function f(x, y)
    a, b = promote(a, b)
    a * b
end
f(a, b)

I would like a to be padded with zeros.

using ArbNumerics

const ArbFR = Union{ArbFloat, ArbReal}

promote_widen(a, b)  = promote(a, b)

function promote_widen(a::ArbFR, b::ArbFR)
   aprec, bprec = precision(a), precision(b)
   if aprec == bprec
      return a, b
   end
   if aprec < bprec
      a = typeof(b)(a)
   else
      b = typeof(a)(b)
   end
   a, b
end

function times(a, b)
     a, b = promote_widen(a, b)
     a * b
end

then

a = 0.3f0
b = 0.7
x = ArbFloat(0.3, bits = 50)
y = ArbFloat(0.7, bits = 100)

ab = times(a, b);
bx = times(b, x);
xy = times(x, y);

a = 0.3f0
b = 0.7
x = ArbFloat(0.3, bits = 50)
y = ArbFloat(0.7, bits = 100)

aa = times(a, a);
ab = times(a, b);
bx = times(b, x);
xy = times(x, y);

we obtain

julia> precision(aa), aa
(24, 0.09f0)

julia> precision(ab), ab
(53, 0.21000000834465027)

julia> precision(bx), bx
(50, 0.21)

julia> precision(xy), xy
(100, 0.209999999999999978905762532122)
1 Like