Skip to content

Comments

Relax a few unittests for double-precision reals#5346

Merged
dlang-bot merged 1 commit intodlang:stablefrom
kinke:fixReal64
May 24, 2017
Merged

Relax a few unittests for double-precision reals#5346
dlang-bot merged 1 commit intodlang:stablefrom
kinke:fixReal64

Conversation

@kinke
Copy link
Contributor

@kinke kinke commented Apr 23, 2017

A loss-less roundtrip (to string <=> parse) apparently isn't guaranteed when using double-precision reals.

@kinke
Copy link
Contributor Author

kinke commented Apr 23, 2017

The issues were encountered with LDC for MSVC and ARM targets (double-precision reals).

@quickfur
Copy link
Member

LGTM. But I'll defer to someone with stronger grasp of floating-point semantics.

@tsbockman
Copy link
Contributor

Related: #4345

The round trip should be lossless; if it's not, why not fix it instead of relaxing the tests? Probably one or both of the conversion routines just isn't using enough decimal digits:

People generally assume that ceil(log10(pow(2.0, double.mant_dig))) == 16 is enough for a lossless round-trip, but actually ceil(log(pow(2.0, double.mant_dig - 1)) / log(10.0) + 1) == 18 are needed.

const json0 = JSONValue(num0);
const num1 = to!double(toJSON(json0));
version(Win32)
static if (realInDoublePrecision)
Copy link
Contributor

@tsbockman tsbockman Apr 25, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

By doing this you may be relaxing the test on platforms where it currently works, inviting regressions.

Copy link
Contributor Author

@kinke kinke Apr 25, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since when does DMD cover 64-bit reals? Most new Phobos releases come with a few new tests that fail exactly because they're not tested with 64-bit reals, so I keep on upstreaming relaxed unittests for LDC which actually supports and tests targets with double-precision reals.

If you consider the potential being-off-by-1-ulp as bug (for std.format and/or std.json?), the Win32 exception shouldn't have been here already in the first place. I'm just extending that exception to its true scope here.

Copy link
Contributor

@tsbockman tsbockman Apr 25, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a list online somewhere of which platforms have is(double == real)?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Afaik, we use it for the 32/64-bit MSVC targets (i.e., on Windows), PowerPC and 32-bit ARM and possibly others, although real is still a distinct type (mangling).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I run these tests on Android/ARM, which is one of the platforms where real is 64-bit, and can confirm that this one only fails because of variability in the last digit, and that this relaxation patch gets it to pass again.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a list online somewhere of which platforms have is(double == real)?

It would be easier to list those that don't. x86 (80-bit) and PPC (64-bit pair) for sure, I think IA64 (128-bit) is in that list too. Everyone else is a platform where real == double.

Copy link
Contributor Author

@kinke kinke Apr 26, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AArch64 has 128-bit quadruple reals. The PowerPC doubledouble is implemented in software AFAIK, that's why we use double-precision reals for PowerPC.

static if (realInDoublePrecision)
assert(test(-double.max / 2));
else
assert(test(-double.max));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the result of this test when it fails? What consequences could the failure have for the API user?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Answering my own question (from Relax std.json unittest some more): "test(-double.max) results in an overflow and thrown exception in std.conv.parse!(double, string)."

I guess that's not too bad; at least it doesn't just silently corrupt data.

Copy link
Contributor Author

@kinke kinke Apr 25, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This may have been a more severe issue (it's been a while since I relaxed them for LDC), I need to recheck.
Edit: Thanks for checking, didn't see your 2nd post before.

@tsbockman
Copy link
Contributor

The failure of test(-double.max) is caused by a logic bug in std.conv.parse which is not platform dependant. (I can reproduce it on my AMD64 machine with DMD just by replacing real with double in a few places.)

Please give me a chance to fix the root cause rather than weakening the std.json unittest.

@kinke
Copy link
Contributor Author

kinke commented Apr 26, 2017

Please give me a chance to fix the root cause rather than weakening the std.json unittest.

;) Sure, thanks!

@tsbockman
Copy link
Contributor

tsbockman commented May 17, 2017

Unfortunately, fixing std.conv.parse turned out to be more trouble than I expected.

  1. For decimal, getting a lossless round-trip without the use of a higher precision type seems difficult to impossible. (It should generally be within ~1 bit, though.)

  2. The double.max problem is fixable, but it seems to me that a principled solution requires manipulating the rounding mode, which I cannot get working reliably across all three major compilers.

  3. The whole function is kind of a mess, and should probably be re-written. I have done this, but I don't want to delay this trivial PR indefinitely waiting for it to be reviewed and merged. (Especially since I haven't even decided whether to submit my rewrite, at all.)

Given the above, I recommend that we go ahead and merge this as-is. (Sorry for the delay.)

@joakim-noah
Copy link
Contributor

ping, looks like this is ready to go.

Copy link
Contributor

@JackStouffer JackStouffer left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@JackStouffer
Copy link
Contributor

@kinke Can you please rebase onto master so that github picks up the fact that jenkins is no longer required for a merge?

A loss-less roundtrip (to string <=> parse) apparently isn't guaranteed
when using double-precision reals.
@dlang-bot dlang-bot merged commit 62a7e7c into dlang:stable May 24, 2017
@kinke kinke deleted the fixReal64 branch May 24, 2017 22:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants