Bug 5628 – std.math unittest disabled - roundoff error in pow() on SSE2

Status
RESOLVED
Resolution
FIXED
Severity
normal
Priority
P2
Component
phobos
Product
D
Version
D2
Platform
x86_64
OS
All
Creation time
2011-02-20T14:25:05Z
Last change time
2019-12-25T23:37:33Z
Keywords
pull
Assigned to
No Owner
Creator
Brad Roberts

Comments

Comment #0 by braddr — 2011-02-20T14:25:05Z
The test either takes an enormous amount of time or it goes into an infinite loop somewhere.
Comment #1 by braddr — 2011-04-30T22:21:19Z
Reduced test case: Must be built with debugging turned on, otherwise it doesn't loop: dmd -m64 -gc bug-pow.d module bug; real pow(real x, ubyte n) @trusted pure nothrow { real p = 1.0; ubyte m = n; switch (n) { default: } while (1) { if (n & 1) p *= x; n >>= 1; if (!n) break; x *= x; } return p; } int main() { immutable real x = 46; immutable ubyte three = 3; assert(pow(x,three) == x * x * x); return 0; } Extracted from std/math.d, function: typeof(Unqual!(F).init * Unqual!(G).init) pow(F, G)(F x, G n) @trusted pure nothrow if (isIntegral!(F) && isIntegral!(G)) And it's following unittest.
Comment #2 by braddr — 2012-01-01T21:24:28Z
The bug in comment 1 is fixed. There are 3 asserts left that fail w/in std.math: assert(pow(xd, neg2) == 1 / (x * x)); assert(pow(xf, neg8) == 1 / ((x * x) * (x * x) * (x * x) * (x * x))); assert(feqrel(real.min_normal/8,real.min_normal/17)==3); They're currently versioned out for x86_64
Comment #3 by clugdbug — 2013-04-09T02:28:41Z
The remaining bug in comment 2 is just a rounding error. The last bit of 1/ x*x is different when the intermediate values are 80 bit reals, vs when they are 64 bit doubles. It is a bug, but it's not a compiler bug, just a fairly minor Phobos one. Dropping severity to normal, and changing to Phobos.
Comment #4 by code — 2013-11-14T12:17:23Z
The test is wrong because of excess precision. To fix this bug we need to replace == with approxEqual and determine the allowed error, right?
Comment #5 by ibuclaw — 2013-11-29T04:10:40Z
(In reply to comment #4) > The test is wrong because of excess precision. > To fix this bug we need to replace == with approxEqual and determine the > allowed error, right? Right, I've come some other failing tests in gdc that I've had to tweak to allow an extra bit of rounding accuracy. feqrel() should do the trick with this.
Comment #6 by dlang-bugzilla — 2017-07-02T18:12:31Z
Here is the extracted test case from std.math: void main() { import std.math; immutable real x = 46; immutable float xf = x; immutable double xd = x; immutable short neg2 = -2; immutable long neg8 = -8; assert(pow(xd, neg2) == 1 / (x * x)); assert(pow(xf, neg8) == 1 / ((x * x) * (x * x) * (x * x) * (x * x))); }
Comment #7 by dlang-bot — 2019-12-15T10:41:04Z
@berni44 created dlang/phobos pull request #7321 "Fix Issue 5628 - std.math unittest disabled - roundoff error in pow()" fixing this issue: - Fix Issue 5628 - std.math unittest disabled - roundoff error in pow() on SSE2 https://github.com/dlang/phobos/pull/7321
Comment #8 by dlang-bot — 2019-12-25T23:37:33Z
dlang/phobos pull request #7321 "Fix Issue 5628 - std.math unittest disabled - roundoff error in pow()" was merged into master: - 7b9c47452152217dccc83ad8a35945ee472dda1a by Bernhard Seckinger: Fix Issue 5628 - std.math unittest disabled - roundoff error in pow() on SSE2 https://github.com/dlang/phobos/pull/7321