Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- ```
- /*
- * Sample code (t125.c) (added checking of __STDC__ and __STDC_IEC_559__)
- */
- #include <fenv.h>
- #include <stdio.h>
- #include <math.h>
- #include <stdint.h>
- #include <string.h>
- #include <stdlib.h>
- #if _MSC_VER && ! __clang__
- #pragma fenv_access (on)
- #else
- #pragma STDC FENV_ACCESS ON
- #endif
- void show_fe_exceptions(void)
- {
- printf("exceptions raised:");
- if (fetestexcept(FE_DIVBYZERO)) printf(" FE_DIVBYZERO");
- if (fetestexcept(FE_INEXACT)) printf(" FE_INEXACT");
- if (fetestexcept(FE_INVALID)) printf(" FE_INVALID");
- if (fetestexcept(FE_OVERFLOW)) printf(" FE_OVERFLOW");
- if (fetestexcept(FE_UNDERFLOW)) printf(" FE_UNDERFLOW");
- if (fetestexcept(FE_ALL_EXCEPT)==0) printf(" none");
- printf("\n");
- }
- /* based on https://github.com/google/flatbuffers/blob/4133a39df80546ff5269894a3961c7069fcd45d0/tests/test.cpp#L693 */
- #if TID == 32
- _Bool is_quiet_nan(float v)
- #elif TID == 64
- _Bool is_quiet_nan(double v)
- #else
- #error "unknown TID"
- #endif
- {
- #if TID == 32
- uint32_t qnan_base = 0x7FC00000u;
- uint32_t u;
- #elif TID == 64
- uint64_t qnan_base = 0x7FF8000000000000ul;
- uint64_t u;
- #else
- #error "unknown TID"
- #endif
- _Static_assert(sizeof(v) == sizeof(u), "unexpected");
- memcpy(&u, &v, sizeof(v));
- return ((u & qnan_base) == qnan_base);
- }
- #if TID == 32
- float xfma(float x, float y, float z) { return fmaf(x, y, z); }
- float xsqrt(float x) { return sqrtf(x); }
- #elif TID == 64
- double xfma(double x, double y, double z) { return fma(x, y, z); }
- double xsqrt(double x) { return sqrt(x); }
- #else
- #error "unknown TID"
- #endif
- int main(void)
- {
- volatile _Bool b;
- #if TID == 32
- QUAL float f = NAN;
- #elif TID == 64
- QUAL double f = NAN;
- #else
- #error "unknown TID"
- #endif
- #ifndef __STDC__
- printf("Does not ID itself as compliant to any C standard, exiting\n");
- exit(1);
- #elif __STDC__ == 1
- printf("Compliant to some C standard\n");
- #ifndef __STDC_VERSION__
- printf("C 1989\n");
- #else
- printf("C %ld\n", __STDC_VERSION__);
- #endif
- #endif
- #if __STDC_IEC_559__ == 1
- printf("Has IEC 60559 conformance\n");
- #else
- printf("Has no IEC 60559 conformance OR has IEC 60559 conformance but __STDC_IEC_559__ is not defined to 1\n");
- printf("Conclude that non-IEEE 754 conformant results may be produced, exiting\n");
- exit(1);
- #endif
- printf("f is %f\n", f);
- printf("f is quiet nan %d\n", is_quiet_nan(f));
- printf("NAN is quiet nan %d\n", is_quiet_nan(NAN));
- #define TEST(expr) \
- printf("%-25s => ", #expr); \
- feclearexcept(FE_ALL_EXCEPT); \
- b = (expr) != 0; \
- show_fe_exceptions();
- printf("\n");
- printf("C11, 5.2.4.2.2, p3:\n");
- printf("> A quiet NaN propagates through almost every arithmetic\n");
- printf("> operation without raising a floating-point exception; ...\n");
- TEST(f + f);
- TEST(f - f);
- TEST(f * f);
- TEST(f / f);
- TEST(xsqrt(f));
- TEST(xfma(f, f, f));
- TEST(NAN + NAN);
- TEST(NAN - NAN);
- TEST(NAN * NAN);
- TEST(NAN / NAN);
- TEST(xsqrt(NAN));
- TEST(xfma(NAN, NAN, NAN));
- printf("\n");
- printf("IEEE 754, 5.11, p4:\n");
- printf("> Programs that explicitly take account of the possibility of\n");
- printf("> quiet NaN operands may use the unordered-quiet predicates in\n");
- printf("> Table 5.3 which do not signal such an invalid operation exception.\n");
- TEST(f == f);
- TEST(f != f);
- TEST(f >= f);
- TEST(f <= f);
- TEST(f > f);
- TEST(f < f);
- TEST(NAN == NAN);
- TEST(NAN != NAN);
- TEST(NAN >= NAN);
- TEST(NAN <= NAN);
- TEST(NAN > NAN);
- TEST(NAN < NAN);
- return b ? 1 : 0;
- }
- ```
- Invocations (attention: many results):
- ```
- # clang
- # const float (baseline)
- $ clang t125.c -lm -std=c11 -ffp-model=strict -Wall -Wextra -pedantic -DQUAL=const -O3 -DTID=32 && ./a.out
- t125.c:11:14: warning: pragma STDC FENV_ACCESS ON is not supported, ignoring pragma [-Wunknown-pragmas]
- #pragma STDC FENV_ACCESS ON
- ^
- 1 warning generated.
- Compliant to some C standard
- C 201112
- Has IEC 60559 conformance
- f is nan
- f is quiet nan 1
- NAN is quiet nan 1
- C11, 5.2.4.2.2, p3:
- > A quiet NaN propagates through almost every arithmetic
- > operation without raising a floating-point exception; ...
- f + f => exceptions raised: none
- f - f => exceptions raised: none
- f * f => exceptions raised: none
- f / f => exceptions raised: none
- xsqrt(f) => exceptions raised: none
- xfma(f, f, f) => exceptions raised: none
- NAN + NAN => exceptions raised: none
- NAN - NAN => exceptions raised: none
- NAN * NAN => exceptions raised: none
- NAN / NAN => exceptions raised: none
- xsqrt(NAN) => exceptions raised: none
- xfma(NAN, NAN, NAN) => exceptions raised: none
- IEEE 754, 5.11, p4:
- > Programs that explicitly take account of the possibility of
- > quiet NaN operands may use the unordered-quiet predicates in
- > Table 5.3 which do not signal such an invalid operation exception.
- f == f => exceptions raised: none
- f != f => exceptions raised: none
- f >= f => exceptions raised: FE_INVALID
- f <= f => exceptions raised: FE_INVALID
- f > f => exceptions raised: FE_INVALID
- f < f => exceptions raised: FE_INVALID
- NAN == NAN => exceptions raised: none
- NAN != NAN => exceptions raised: none
- NAN >= NAN => exceptions raised: FE_INVALID
- NAN <= NAN => exceptions raised: FE_INVALID
- NAN > NAN => exceptions raised: FE_INVALID
- NAN < NAN => exceptions raised: FE_INVALID
- $ get_cmd() { cmd="clang t125.c -lm -std=c11 -ffp-model=strict -Wall -Wextra -pedantic \
- -O3 -Wfatal-errors -DQUAL=$QUAL1 -DTID=$TID1 && ./a.out > out1 && clang t125.c -lm \
- -std=c11 -ffp-model=strict -Wall -Wextra -pedantic -O3 -Wfatal-errors -DQUAL=$QUAL2 \
- -DTID=$TID2 && ./a.out > out2 && diff out1 out2" ; }
- # note: below we do not count `warning: pragma STDC FENV_ACCESS ON is not supported`
- # const float vs const double
- $ QUAL1=const TID1=32 QUAL2=const TID2=64 get_cmd ; eval $cmd
- <nothing>
- # const float vs volatile float
- $ QUAL1=const TID1=32 QUAL2=volatile TID2=32 get_cmd ; eval $cmd
- <nothing>
- # const float vs volatile double
- $ QUAL1=const TID1=32 QUAL2=volatile TID2=64 get_cmd ; eval $cmd
- <nothing>
- # const double vs volatile float
- $ QUAL1=const TID1=64 QUAL2=volatile TID2=32 get_cmd ; eval $cmd
- <nothing>
- # const double vs volatile double
- $ QUAL1=const TID1=64 QUAL2=volatile TID2=64 get_cmd ; eval $cmd
- <nothing>
- # volatile float vs volatile double
- $ QUAL1=volatile TID1=32 QUAL2=volatile TID2=64 get_cmd ; eval $cmd
- <nothing>
- # gcc
- # const float (baseline)
- $ gcc t125.c -lm -std=c11 -frounding-math -fsignaling-nans -Wall -Wextra -pedantic -O3 -DQUAL=const -DTID=32 && ./a.out
- t125.c:11: warning: ignoring ‘#pragma STDC FENV_ACCESS’ [-Wunknown-pragmas]
- 11 | #pragma STDC FENV_ACCESS ON
- |
- Compliant to some C standard
- C 201112
- Has IEC 60559 conformance
- f is nan
- f is quiet nan 1
- NAN is quiet nan 1
- C11, 5.2.4.2.2, p3:
- > A quiet NaN propagates through almost every arithmetic
- > operation without raising a floating-point exception; ...
- f + f => exceptions raised: none
- f - f => exceptions raised: none
- f * f => exceptions raised: none
- f / f => exceptions raised: none
- xsqrt(f) => exceptions raised: none
- xfma(f, f, f) => exceptions raised: none
- NAN + NAN => exceptions raised: none
- NAN - NAN => exceptions raised: none
- NAN * NAN => exceptions raised: none
- NAN / NAN => exceptions raised: none
- xsqrt(NAN) => exceptions raised: none
- xfma(NAN, NAN, NAN) => exceptions raised: none
- IEEE 754, 5.11, p4:
- > Programs that explicitly take account of the possibility of
- > quiet NaN operands may use the unordered-quiet predicates in
- > Table 5.3 which do not signal such an invalid operation exception.
- f == f => exceptions raised: none
- f != f => exceptions raised: none
- f >= f => exceptions raised: none
- f <= f => exceptions raised: none
- f > f => exceptions raised: none
- f < f => exceptions raised: none
- NAN == NAN => exceptions raised: none
- NAN != NAN => exceptions raised: none
- NAN >= NAN => exceptions raised: none
- NAN <= NAN => exceptions raised: none
- NAN > NAN => exceptions raised: none
- NAN < NAN => exceptions raised: none
- $ get_cmd() { cmd="gcc t125.c -lm -std=c11 -frounding-math -fsignaling-nans -Wall -Wextra -pedantic -O3 -DQUAL=$QUAL1 \
- -DTID=$TID1 && ./a.out > out1 && gcc t125.c -lm -std=c11 -frounding-math -fsignaling-nans -Wall -Wextra -pedantic -O3 \
- -DQUAL=$QUAL2 -DTID=$TID2 && ./a.out > out2 && diff out1 out2" ; }
- # note: below we do not count `warning: pragma STDC FENV_ACCESS ON is not supported`
- # const float vs const double
- $ QUAL1=const TID1=32 QUAL2=const TID2=64 get_cmd ; eval $cmd
- <nothing>
- # const float vs volatile float
- $ QUAL1=const TID1=32 QUAL2=volatile TID2=32 get_cmd ; eval $cmd
- 30,33c30,33
- < f >= f => exceptions raised: none
- < f <= f => exceptions raised: none
- < f > f => exceptions raised: none
- < f < f => exceptions raised: none
- ---
- > f >= f => exceptions raised: FE_INVALID
- > f <= f => exceptions raised: FE_INVALID
- > f > f => exceptions raised: FE_INVALID
- > f < f => exceptions raised: FE_INVALID
- # const float vs volatile double
- $ QUAL1=const TID1=32 QUAL2=volatile TID2=64 get_cmd ; eval $cmd
- 30,33c30,33
- < f >= f => exceptions raised: none
- < f <= f => exceptions raised: none
- < f > f => exceptions raised: none
- < f < f => exceptions raised: none
- ---
- > f >= f => exceptions raised: FE_INVALID
- > f <= f => exceptions raised: FE_INVALID
- > f > f => exceptions raised: FE_INVALID
- > f < f => exceptions raised: FE_INVALID
- # const double vs volatile float
- $ QUAL1=const TID1=64 QUAL2=volatile TID2=32 get_cmd ; eval $cmd
- 30,33c30,33
- < f >= f => exceptions raised: none
- < f <= f => exceptions raised: none
- < f > f => exceptions raised: none
- < f < f => exceptions raised: none
- ---
- > f >= f => exceptions raised: FE_INVALID
- > f <= f => exceptions raised: FE_INVALID
- > f > f => exceptions raised: FE_INVALID
- > f < f => exceptions raised: FE_INVALID
- # const double vs volatile double
- $ QUAL1=const TID1=64 QUAL2=volatile TID2=64 get_cmd ; eval $cmd
- 30,33c30,33
- < f >= f => exceptions raised: none
- < f <= f => exceptions raised: none
- < f > f => exceptions raised: none
- < f < f => exceptions raised: none
- ---
- > f >= f => exceptions raised: FE_INVALID
- > f <= f => exceptions raised: FE_INVALID
- > f > f => exceptions raised: FE_INVALID
- > f < f => exceptions raised: FE_INVALID
- # volatile float vs volatile double
- $ QUAL1=volatile TID1=32 QUAL2=volatile TID2=64 get_cmd ; eval $cmd
- <nothing>
- # cl
- # not on ubuntu
- dev0@dev0-VirtualBox:~/dev$ gcc --version
- gcc (Ubuntu 10.2.0-5ubuntu1~20.04) 10.2.0
- Copyright (C) 2020 Free Software Foundation, Inc.
- This is free software; see the source for copying conditions. There is NO
- warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- dev0@dev0-VirtualBox:~/dev$ clang --version
- Ubuntu clang version 11.0.0-2~ubuntu20.04.1
- Target: x86_64-pc-linux-gnu
- Thread model: posix
- InstalledDir: /usr/bin
- $ cl
- # not on ubuntu
- ```
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement