Question:
By occupation, I was forced to work closely with the IEEE-754 format, during which I discovered that none of the compilers known to me (VC ++, Intel C ++, CLang, GCC (namely MinGW)) can convert some numbers in decimal notation (such as , 1.2345e67) to floating point format. All compilers that I have tested fail on simple tests when it is not obvious to the compiler how to round (up or down). Examples of such tests can be seen in this cpp file (the code is too long to post here). My question is: do you know of a compiler that will pass at least these simple tests ( everything from this file) without errors? If there is one, I will provide more complex tests. Just compile and run the program, it will print to the console what passed and what didn't. Whoever finds such a compiler, please name it in the answer.
Maybe someone wants to check the work of tests in other languages, I will be glad to know the result, only you first have to write a similar program based on these tests.
PS. If someone is interested in the reason for the fall, I explained it in one of my conversations (see video )
UPD : Tests against СLang (GCC passes them). The proposed tests comply with the C++ language standard (string and token length does not exceed 65535 characters). I still have a few dozen tests against CLang that completely destroy the compiler. All are related to long double (for example, give it the minimum denormalized number as input, it will fall). I have to admit, though, that for floats and doubles, CLang does pass all my tests, but often produces compile-time warnings where it shouldn't. In any case, this compiler also does not fully support the IEEE-754 format.
UPD2 : Tests that fail CLang and don't work in GCC (MinGW).
UPD3 : All tests are now on GitHub . Later, when I have clarity (or maybe someone finds my mistakes) on this issue, I will combine everything into one file for convenience.
Answer:
Base
Gcc 5.3.0, apparently passed:
$ gcc TestIEEE754Convertion.cpp
TestIEEE754Convertion.cpp:80:3: warning: floating constant truncated to zero [-Woverflow]
-2.470328229206232720882843964341106861825e-324,
^
TestIEEE754Convertion.cpp:19:3: warning: anonymous type with no linkage used to declare variable ‘<anonymous union> f32’ with linkage
} f32;
^
TestIEEE754Convertion.cpp:25:3: warning: anonymous type with no linkage used to declare variable ‘<anonymous union> f64’ with linkage
} f64;
^
$ ./a.out
::: Single precision :::
Right on test 0
Right on test 1
Right on test 2
Right on test 3
Right on test 4
Right on test 5
Right on test 6
Right on test 7
::: Double precision :::
Right on test 0
Right on test 1
Right on test 2
Right on test 3
Right on test 4
Right on test 5
Right on test 6
Right on test 7
Right on test 8
Right on test 9
Right on test 10
Right on test 11
Right on test 12
Right on test 13
Right on test 14
Right on test 15
Right on test 16
Right on test 17
Right on test 18
Right on test 19
Right on test 20
Right on test 21
Right on test 22
Right on test 23
Gcc 4.8.5:
$ ./a.out
::: Single precision :::
Right on test 0
Right on test 1
Right on test 2
Right on test 3
Right on test 4
Right on test 5
Right on test 6
Right on test 7
::: Double precision :::
Right on test 0
Right on test 1
Right on test 2
Right on test 3
Right on test 4
Right on test 5
Right on test 6
Right on test 7
Right on test 8
Right on test 9
Right on test 10
Error on test 11: 0x7fefffffffffffff != 0x7feffffffffffffe
Error on test 12: 0x7fefffffffffffff != 0x7feffffffffffffe
Right on test 13
Right on test 14
Right on test 15
Right on test 16
Right on test 17
Right on test 18
Right on test 19
Error on test 20: 0x8000000000000000 != 0x8000000000000001
Right on test 21
Right on test 22
Right on test 23
Gcc 4.9.3:
$ ./a.out
::: Single precision :::
Right on test 0
Right on test 1
Right on test 2
Right on test 3
Right on test 4
Right on test 5
Right on test 6
Right on test 7
::: Double precision :::
Right on test 0
Right on test 1
Right on test 2
Right on test 3
Right on test 4
Right on test 5
Right on test 6
Right on test 7
Right on test 8
Right on test 9
Right on test 10
Right on test 11
Right on test 12
Right on test 13
Right on test 14
Right on test 15
Right on test 16
Right on test 17
Right on test 18
Right on test 19
Right on test 20
Right on test 21
Right on test 22
Right on test 23
Hard 2
For UPD2 Gcc 5, well done too:
$ gcc TestIEEE754ConvertionHard2.cpp
$ ./a.out
OK
Gcc 4.8.5 – ERROR, Gcc 4.9.3 – OK
Hard 3
$ g++-5 -O0 ./TestIEEE754ConvertionHard3.cpp
./TestIEEE754ConvertionHard3.cpp:19:3: предупреждение: anonymous type with no linkage used to declare variable «<anonymous union> f32» with linkage
} f32;
^
./TestIEEE754ConvertionHard3.cpp:25:3: предупреждение: anonymous type with no linkage used to declare variable «<anonymous union> f64» with linkage
} f64;
^
$ ./a.out
::: Double precision :::
Right on test 0
Right on test 1
Right on test 2
Right on test 3
Right on test 4
Right on test 5
Right on test 6
Right on test 7
Right on test 8
Apparently passed. Gcc 4.9 – similar. Gcc 4.8 failed tests 5, 7, 8
Strict aliasing
By the way, I can confuse something, but are there such transformations:
#define TEST(HI, LO, F) f = F; if (*(((unsigned short int*)&f)+4) != HI || *(unsigned long long*)&f != LO) { printf ("ERROR"); return 1; }
do not violate the strict-aliasing rule? No, of course -Wstrict-aliasing -fstrict-aliasing
skips this place and the code works on working compilers. But somehow, a little, not on its own.