`fmod` of `interval<long double>` can miss the true result
Maintainers usually reply within 1 day
Nobody has claimed this yet.
Assessment
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Newbie friendliness
- 76/100
Research direction
Read detail/c99sub_rounding_control.hpp, detail/ppc_rounding_control.hpp, and detail/sparc_rounding_control.hpp, then compare their to_int implementations with the Alpha and IA-64 backends mentioned in the issue. Reproduce the fmod example with interval<long double> and check that the result contains 0 after the change.
Written by the indexing model from the issue text.
Description
rounding_control<long double>::to_int calls rint, the double function, in three backends:
detail/c99sub_rounding_control.hpp, - Itsextern "C" { double rint(double); }is declared insidenamespace detail, so the templateto_int<T>always finds that one.detail/ppc_rounding_control.hppdetail/sparc_rounding_control.hpp
A long double with more than 53 significant bits is rounded to double before it is rounded to an integer. int_down and int_up then return wrong values, sometimes on the wrong side of the argument, and fmod, which uses int_down, returns an interval that does not contain the true result:
#include <boost/numeric/interval.hpp>
#include <iostream>
int main() {
typedef boost::numeric::interval<long double> I;
I r = fmod(I(1152921504606846977.0L), I(1)); // 2^60 + 1
std::cout << r.lower() << ' ' << r.upper() << '\n'; // must contain 0
}
It print 1 1 : godbolt
| Step | Expected | Actual |
|---|---|---|
x |
2^60 + 1 = 1152921504606846977, exact in long double (64-bit significand) |
same |
div_down(x, 1) |
1152921504606846977 (exact) | same |
to_int of that |
rintl(1152921504606846977) = 1152921504606846977 |
rint(double(1152921504606846977)): converting to double (53 bits) gives 1152921504606846976 = |
| 2^60 | ||
n = int_down(...) |
2^60 + 1 | 2^60 |
x - n * 1 |
1152921504606846977 − 1152921504606846977 = 0 | 1152921504606846977 − 1152921504606846976 = 1 |
result z |
[0, 0] |
[1, 1] |
The Alpha and IA-64 backends already declare rintl and use it in to_int(long double); doing the same in these three fixes it.
- Dominant language
- C++
- Stars
- 31
- Forks
- 49
- Avg merge
- 1d 4h
- Merged PRs (30d)
- 9
Getting set up
This project ships no dev container, Dockerfile or contributing guide, so setting up is up to you: start from its README, and see our first-contribution guide for the general steps.
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from boostorg/interval
-
Difficulty 2/5 1-3 hours Newbie friendliness 66/100
Maintainers usually reply within 1 day
-
Difficulty 4/5 3-5 days Newbie friendliness 35/100
boostorg/interval#44 · 1 comment ·
Maintainers usually reply within 1 day
-
Difficulty 5/5 Over a week Newbie friendliness 10/100
Maintainers usually reply within 1 day
-
Code behaves differently if compiled with MSVC vs GCCPossibly taken @reach2sayan claimed this 9 days ago. Open
Difficulty 5/5 Over a week Newbie friendliness 25/100
boostorg/interval#35 · 1 comment ·
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 45/100
Maintainers usually reply within 1 day
All issues in boostorg/interval
Similar issues
-
Status: Needs confirmation Status: Needs triage
Difficulty 2/5 1-3 hours Newbie friendliness 64/100
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
boykopovar/AnyPS5#12124 ·
Maintainers usually reply within 1 day
-
bug-unconfirmed
Difficulty 2/5 1-3 hours Newbie friendliness 82/100
Maintainers usually reply within 1 day
-
A-combat P-low S-ready-to-start task
Difficulty 2/5 1-3 hours Newbie friendliness 77/100
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 83/100
Maintainers usually reply within 1 day