Bug 20951 – Wrong Decimal Literals Encoding

Status
NEW
Severity
critical
Priority
P2
Component
dmd
Product
D
Version
D2
Platform
All
OS
All
Creation time
2020-06-18T14:38:34Z
Last change time
2024-12-13T19:09:20Z
Keywords
pull, wrong-code
Assigned to
No Owner
Creator
Илья Ярошенко
See also
https://issues.dlang.org/show_bug.cgi?id=20972, https://issues.dlang.org/show_bug.cgi?id=5229
Moved to GitHub: dmd#19723 →

Comments

Comment #0 by ilyayaroshenko — 2020-06-18T14:38:34Z
Decimal literals are encoded incorrectly. They literals should be encoded using IEEE (bankers) round-half-to-even rule like in C, Rust, and others. Failed tests: assert(1.448997445238699 == 0x1.72f17f1f49aadp0); assert(2075e23 == 0xaba3d58a1f1a98p+32);
Comment #1 by kinke — 2020-06-18T21:51:17Z
Some context: At compile-time, i.e., inside the frontend, floating-point literals and CTFE values of *any precision* are represented using a type called real_t (see dmd.root.ctfloat), which is the host's `real` most of the time, except for gdc, which uses a host-independent high-precision software implementation AFAIK (so consistent behavior for cross-compilation too). So all literals are parsed as real_t (although there are precision-dependent over-/underflow checks), and CTFE calculations incl. some transcendental math functions are performed using the compiler's real_t type, regardless of whether the compile-time value is typed as a float, double or real. Iain has recently added a core.math.toPrec() function, I don't know if he had CTFE in mind for this and whether he changed something in the compiler as well.
Comment #2 by kinke — 2020-06-18T23:22:37Z
Oh, I forgot the reason for the broader overview - both assertions of the testcase are CTFE-optimized to `assert(false)` (see -vcg-ast).
Comment #3 by ilyayaroshenko — 2020-06-19T02:26:30Z
In C: ``` static double d = 2075e23; ``` is encoded as ``` .LCPI0_0: .quad 5000531031573652307 # double 2.0749999999999998E+26 ``` and ``` static double d = 2075e23L; // with L at the end ``` is encoded as ``` .LCPI0_0: .quad 5000531031573652308 # double 2.0750000000000002E+26 ``` as expected. In D we always have the last case which makes D a non-IEEE language, as well as non-C compatible. `toPrec` can't solve this issue.
Comment #4 by dlang-bot — 2020-07-07T23:21:42Z
@kinke created dlang/dmd pull request #11387 "Fix Issue 20951 - Don't use excess precision when parsing single- and double-precision literals" fixing this issue: - Fix Issue 20951 - Don't use excess precision when parsing single- and double-precision literals https://github.com/dlang/dmd/pull/11387
Comment #5 by ibuclaw — 2020-07-10T14:15:35Z
(In reply to kinke from comment #1) > Iain has recently added a core.math.toPrec() function, I don't know if he > had CTFE in mind for this and whether he changed something in the compiler > as well. toPrec was added precisely because CTFE does everything at the highest supported precision, even if you are only working with floats.
Comment #6 by ibuclaw — 2020-07-10T14:23:00Z
(In reply to Илья Ярошенко from comment #3) > In D we always have the last case which makes D a non-IEEE language, as well > as non-C compatible. `toPrec` can't solve this issue. I don't think we pretend to be a C-compatible language when it comes to floating point, so you can't use that argument. The same goes for IEEE during CTFE as well. This has been discussed relentlessly since at least 2012, the status-quo is not expected to change.
Comment #7 by robert.schadek — 2024-12-13T19:09:20Z
THIS ISSUE HAS BEEN MOVED TO GITHUB https://github.com/dlang/dmd/issues/19723 DO NOT COMMENT HERE ANYMORE, NOBODY WILL SEE IT, THIS ISSUE HAS BEEN MOVED TO GITHUB