tricu

A lazy functional language based on Tree Calculus
Log | Files | Refs | README | LICENSE

float_ieee_host.c (1581B)


      1 /* Independent host reference for result words and exception flags.
      2  * Host NaNs provide quiet-class/flag checks; Python checks payload/sign policy.
      3  */
      4 #include <fenv.h>
      5 #include <float.h>
      6 #include <inttypes.h>
      7 #include <stdint.h>
      8 #include <stdio.h>
      9 #include <string.h>
     10 #pragma STDC FENV_ACCESS ON
     11 
     12 int main(void) {
     13     if (sizeof(double) != 8 || FLT_RADIX != 2 || DBL_MANT_DIG != 53 ||
     14         DBL_MIN_EXP != -1021 || DBL_MAX_EXP != 1024 || fesetround(FE_TONEAREST)) return 2;
     15     double one = 1.0;
     16     uint64_t one_bits;
     17     memcpy(&one_bits, &one, 8);
     18     if (one_bits != UINT64_C(0x3ff0000000000000)) return 3;
     19     unsigned op;
     20     uint64_t a, b;
     21     while (scanf("%u %" SCNx64 " %" SCNx64, &op, &a, &b) == 3) {
     22         volatile double left, right, result;
     23         memcpy((void *)&left, &a, 8);
     24         memcpy((void *)&right, &b, 8);
     25         if (feclearexcept(FE_ALL_EXCEPT)) return 4;
     26         switch (op) {
     27             case 0: result = left + right; break;
     28             case 1: result = left - right; break;
     29             case 2: result = left * right; break;
     30             case 3: result = left / right; break;
     31             default: return 5;
     32         }
     33         int raised = fetestexcept(FE_ALL_EXCEPT);
     34         unsigned flags = !!(raised & FE_INVALID) | (!!(raised & FE_DIVBYZERO) << 1) |
     35             (!!(raised & FE_OVERFLOW) << 2) | (!!(raised & FE_UNDERFLOW) << 3) |
     36             (!!(raised & FE_INEXACT) << 4);
     37         uint64_t bits;
     38         memcpy(&bits, (const void *)&result, 8);
     39         printf("%016" PRIx64 " %u\n", bits, flags);
     40     }
     41     return ferror(stdin) ? 6 : 0;
     42 }