boostorg / boostorg/multiprecision
understanding precision policies
- Dominant language
- C++
- Stars
- 265
- Forks
- 128
- Avg merge
- 4h 48m
- Merged PRs (30d)
- 2
Description
I'm still working on understanding the policies implemented for mixed precision arithmetic. i'm at boost 1.81 as installed from homebrew on a mac M1.
I have the following code that *I think* doesn't produce expected results. Namely, I make two variables `x` and `y` at precision 50 and 60 respectively. Then I make a variable `z` at precision 70, and default precision is 70. Then I compute `x*y` with the various policies. For all of them, `z=x*y` leaves `z` with the precision it started with. Specifically, I think that for all policies except `preserve_target_precision` the precision of `z` should be `60` after. But in all cases the precision of `z` is the current default precision; the precision of the target does not depend on the precision of the operands.
Is this the expected behaviour? am I not correctly setting the policy? I used [the doc page on variable precision](https://www.boost.org/doc/libs/1_82_0/libs/multiprecision/doc/html/boost_multiprecision/tut/variable.html) as my guide, and I think what i have is correct.
---
test code:
```
BOOST_AUTO_TEST_CASE(arithmetic_precision_existing_variable)
{
mpfr_float::default_precision(50);
mpfr_float x("0.01234567890123456789012345678901234567890123456789");
BOOST_CHECK_EQUAL(x.precision(), 50);
mpfr_float::default_precision(60);
mpfr_float y("0.12345678901234567890123456789012345678901234567890123456789");
BOOST_CHECK_EQUAL(y.precision(), 60);
// make a variable at precision 70
mpfr_float::default_precision(70);
mpfr_float z1("0"), z2("0"), z3("0"), z4("0"), z5("0");
// then try to write into this existing variable with various policies
// All expressions are evaluated at the precision of the highest precision variable within the expression, and then rounded to the precision of the target variable upon assignment. The precision of other types (including related or component types - see preserve_component_precision/preserve_related_precision) contained within the expression are ignored. This option has the unfortunate side effect, that moves may become full deep copies.
mpfr_float::default_variable_precision_options(boost::multiprecision::variable_precision_options::preserve_target_precision);
z1 = x*y;
BOOST_CHECK_EQUAL(x.precision(), 50);
BOOST_CHECK_EQUAL(y.precision(), 60);
BOOST_CHECK_EQUAL(z1.precision(), 70);
// All expressions are evaluated at the precision of the highest precision variable within the expression, and that precision is preserved upon assignment. The precision of other types (including related or component types - see preserve_component_precision/preserve_related_precision) contained within the expression are ignored. Moves, are true moves not copies.
mpfr_float::default_variable_precision_options(boost::multiprecision::variable_precision_options::preserve_source_precision);
z2 = x*y;
BOOST_CHECK_EQUAL(x.precision(), 50);
BOOST_CHECK_EQUAL(y.precision(), 60);
BOOST_CHECK_EQUAL(z2.precision(), 60);
//All expressions are evaluated at the precision of the highest precision variable within the expression, and that precision is preserved upon assignment. If the expression contains component types then these are also considered when calculating the precision of the expression. Component types are the types which make up the two components of the number when dealing with interval or complex numbers. They are the same type as Num::value_type. Moves, are true moves not copies.
mpfr_float::default_variable_precision_options(boost::multiprecision::variable_precision_options::preserve_component_precision);
z3 = x*y;
BOOST_CHECK_EQUAL(x.precision(), 50);
BOOST_CHECK_EQUAL(y.precision(), 60);
BOOST_CHECK_EQUAL(z3.precision(), 60);
// All expressions are evaluated at the precision of the highest precision variable within the expression, and that precision is preserved upon assignment. If the expression contains component types then these are also considered when calculating the precision of the expression. In addition to component types, all related types are considered when evaluating the precision of the expression. Related types are considered to be instantiations of the same template, but with different parameters. So for example mpfr_float_100 would be a related type to mpfr_float, and all expressions containing an mpfr_float_100 variable would have at least 100 decimal digits of precision when evaluated as an mpfr_float expression. Moves, are true moves not copies.
mpfr_float::default_variable_precision_options(boost::multiprecision::variable_precision_options::preserve_related_precision);
z4 = x*y;
BOOST_CHECK_EQUAL(x.precision(), 50);
BOOST_CHECK_EQUAL(y.precision(), 60);
BOOST_CHECK_EQUAL(z4.precision(), 60);
// All expressions are evaluated at the precision of the highest precision variable within the expression, and that precision is preserved upon assignment. In addition to component and related types, all types are considered when evaluating the precision of the expression. For example, if the expression contains an mpz_int, then the precision of the expression will be sufficient to store all of the digits in the integer unchanged. This option should generally be used with extreme caution, as it can easily cause unintentional precision inflation. Moves, are true moves not copies.
mpfr_float::default_variable_precision_options(boost::multiprecision::variable_precision_options::preserve_all_precision);
z5 = x*y;
BOOST_CHECK_EQUAL(x.precision(), 50);
BOOST_CHECK_EQUAL(y.precision(), 60);
BOOST_CHECK_EQUAL(z5.precision(), 60);
}
```
Contributor guide
No contributing guide indexed for this repository
Research direction
Start with the variable-precision documentation linked in the issue and the supplied BOOST_AUTO_TEST_CASE(arithmetic_precision_existing_variable). Run this focused case to compare each policy's documented behavior with the observed target precision, then determine whether the result is expected or needs a regression test and implementation change.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- cpp
- Domain
- backend
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100