Boost logo

Boost :

Subject: [boost] [multiprecision] Design question on variable precision types.
From: John Maddock (jz.maddock_at_[hidden])
Date: 2018-08-22 18:28:48


Folks,

I have a tricky design question that Boost.Multiprecision has been
dodging relating to variable precision types - these have just expanded
somewhat now that we support complex numbers via mpc as well as mpfr's
reals etc.

The basic use case is this:

We have a set of numbers at very high precision, some calculations are
performed on those directly, others we want to temporarily drop
precision, get an approximate answer and perhaps later refine it. 
Generally speaking, performance trumps everything, on a really long
running calculation 10-20% speedup can actually make a big difference
(in $$'s in some cases if the CPU time is from the cloud).

Up till now Boost.Multiprecision has been dodging this issue - it's
actually pretty hard to program in a sane and consistent way, so the
message has been "don't mix precisions" when using a type like
boost::multiprecision::mpfr_float - just set what default you want and
get on with it.  But we really should do better than that.

So... with the help of Danielle Brake I've been trying to nail this down
in develop, what we have at present is:

* Copy construction or move assignment copies the precision of the source.

* Regular assignment retains the precision of the target variable.

This is efficient in that assignment doesn't reallocate to a new
precision, and provides an easy way to up/down sample precision when
required.  But it breaks equality after assignment.  It does match what
MPC/MPFR do in mpfr_set etc though.

The fact that move assignment behaves differently from regular
assignment bother me too - it's too easy to write code that triggers
move semantics without noticing.  The trouble is, being able to assign
while retaining precision of source is sometimes useful too, so having
move-assign behave differently provides a useful back door, but maybe
one that's just too cute for it's own good?

And then.... we get on to arithmetic.

* Currently temporaries are created at current default precision.  So
it's easy to shoot yourself in the foot by not noticing that temporaries
are being created in an expression and not having the default precision
set correctly.  I actually think this one might be solvable, but it's a
huge job involving banning default constructors in all the backends to
our number types, and then catching all the cases where they might have
been used.

* What should happen in "a = expression", where the variable used in
"expression" are at different precision to a?  The uncontroversial
answer might be to adjust the result to the precision of a.  But hold
on... we have expression templates, and these can use variable a as
working space while evaluating the expression... so the change in
precision might occur *during* the computation and not after it.

* Should we try to ban mixed precision arithmetic altogether? It's a
tempting idea, but I can't see how to enforce it in code without also
banning mixed precision assignment.

Thanks for your consideration, John.

---
This email has been checked for viruses by Avast antivirus software.
https://www.avast.com/antivirus

Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk