4 ms·
There's platform and there's platform. I assume a POSIX platform, so I don't need to check for CHAR_BIT. My code won't work on some DSP with 64-bit chars, and I
by eesmith 6mo ago
There's platform and there's platform. I assume a POSIX platform, so I don't need to check for CHAR_BIT. My code won't work on some DSP with 64-bit chars, and I don't care enough to write that check.
Many of the tests I did back in the 1990s seem pointless now. Do you have checks for non-IEEE 754 math?
- shakna 6mo agoWell, last year clang did not define __STDC_IEC_559__, so assuming IEEE-754 math with most C compilers is a bad idea.
- eesmith 6mo agoDo you have checks for non-IEEE 754 math?
- shakna 6mo agoOkay, as the last wasn't obvious enough: C does not do IEEE 754 math. It is _all_ non-IEEE 754 math. That it isn't compliant is a compiler guarantee, in the current state of things. You may as well have an `assert(1)`.
- eesmith 6mo agoAnd as I wrote, "There's platform and there's platform." I don't support the full range of platforms that C supports. I assume 8 bit chars. I assume good hardware support for 754. I assume the compiler's documentation is correct when it says it map "double" to "binary64" and uses native operations. I assume if someone else compiles my code with non-754 flags, like fused multiply and add, then it's not a problem I need to worry about. For that matter, my code doesn't deal with NaNs or inf (other than input rejection tests) so I don't even need fully conformant 754.
- fc417fc802 6mo agoSo you don't test for it because your code doesn't use it. Which is fine, but says nothing about code which does depend on the relevant assumptions.
- eesmith 6mo agoI say nothing about code which can support when char is 64-bit because my entire point was that my definition of "platform" is far more restrictive than C's, and apparently yours. You wrote "I generally include various static asserts about basic platform assumptions." I pointed out "There's platform and there's platform.", and mentioned that I assume POSIX. So of course I don't test for CHAR_BIT as something other than 8. If you want to support non-POSIX platform, go for it! But adding tests for every single one of the places where the C spec allows implementation defined behavior and where all the compilers I used have the same implementation defined behavior and have done so for years or even decades, seems quixotic to me so I'm not doing to do it. And I doubt you have tests for every single one of those implementation-defined platform assumptions, because there are so many of them, and maintaining those tests when you don't have access to a platform with, say, 18-bit integers to test those tests, seems like it will end up with flawed tests.
- fc417fc802 6mo ago> maintaining those tests when you don't have access to a platform with, say, 18-bit integers to test those tests, seems like it will end up with flawed tests. No? I don't over generalize for features I don't use. I test to confirm the presence of the assumptions that I depend on. I want my code to fail to compile if my assumptions don't hold. I don't recall if I verify CHAR_BIT or not but it wouldn't surprise me if I did.
- shakna 6mo agoI can test for some of those. So I can support a broader range of platforms, than just "works for me". I can't support IEEE 754, so its simply irrelevant - so long as I know I cannot support it, and behaviour differs.
- fc417fc802 6mo agoI do, yes. I check that the compiler reports the desired properties and in cases where my code fails to compile because it does not I special case and manually test each property my code depends on. In my case that's primarily mantissa bit width for the sake of various utility functions that juggle raw FP bits. Even for "regular" architectures this turns out to be important for FP data types. Long double is an f128 on Emscripten but an f80 on x86_64 Clang, where f128 is provided as __float128. The last time I updated my code (admittedly quite a while ago) Clang version 17 did not (yet?) implement std::numeric_limits support for f128. Honestly there's no good reason not to test these sorts of assumptions when implementing low level utility functions because it's the sort of stuff you write once and then reuse everywhere forever.
- fc417fc802 6mo agoUsing C++ under Clang 17 and later (possibly earlier as well, I haven't checked) std::numeric_limits<T>::is_iec559 comes back as true for me for x86_64 on Debian as well as when compiling for Emscripten. Might it be due to your compiler flags? Or is this somehow related to a C/C++ divergence?
- eesmith 6mo agoIf I am not mistaken, is_iec559 concerns numerical representation, while __STDC_IEC_559__ is broader, and includes the behavior of numerical operations like 1.0/-0.0 and various functions. Huh. https://en.cppreference.com/w/c/23.html https://en.cppreference.com/w/c/23.html says the "Old feature-test macro" __STDC_IEC_559__ was deprecated in C23, in favor of __STDC_IEC_60559_BFP__ .
- shakna 6mo agoThe standard warns that macros and assertions can return true for this one, even if it isn't actually true. The warning, because that's what compilers currently do. Its one of the caveats of the C-family that developers are supposed to be aware of, but often aren't. It doesn't support IEEE 754 fully. There is a standard to do so, but no one has actually implemented it.
- fc417fc802 6mo agoI don't see any such caveat mentioned here? Is the linked page incomplete? https://en.cppreference.com/w/cpp/types/numeric_limits/is_iec559.html https://en.cppreference.com/w/cpp/types/numeric_limits/is_ie... Of course in my case what I'm actually concerned with is the behavior surrounding inf and NaN. Thankfully I've never been forced to write code that relied on subtle precision or rounding differences. If it ever comes up I'd hope to keep it to a platform independent fixed point library.
- shakna 6mo agoCPPReference is not the C++ standard. Its a wiki. It gets things wrong. It doesn't always give you the full information. Probably best not to rely on it, for things that matter. But, for example, LLVM does not fully support IEEE 754 [0]. And nor does GCC - who list it as unsupported, despite defining the macro and having partial support. [1] The biggest caveat is in Annex F of the C standard: > The C functions in the following table correspond to mathematical operations recommended by IEC 60559. However, correct rounding, which IEC 60559 specifies for its operations, is not required for the C functions in the table. The C++ standard [2] barely covers support, but if a type supports any of the properties of ISO 60559, then it gets is_iec559 - even if that support is _incomplete_. This paper [3] is a much deeper dive - but the current state for C++ is worse than C. Its underspecified. > When built with version 18.1.0 of the clang C++ compiler, without specifying any compiler options, the output is: > distance: 0.0999999 > proj_vector_y: -0.0799999 > Worse, if -march=skylake is passed to the clang C++ compiler, the output is: > distance: 0.1 > proj_vector_y: -0.08 [0] https://github.com/llvm/llvm-project/issues/17379 https://github.com/llvm/llvm-project/issues/17379 [1] https://www.gnu.org/software/gcc/projects/c-status.html https://www.gnu.org/software/gcc/projects/c-status.html [2] https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2023/n4950.pdf https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2023/n49... [3] https://isocpp.org/files/papers/P3375R2.html https://isocpp.org/files/papers/P3375R2.html