qemu/tests/tcg/i386/test-i386-snan-convert.c
<<
>>
Prefs
   1/* Test conversions of signaling NaNs to and from long double.  */
   2
   3#include <stdint.h>
   4#include <stdio.h>
   5
   6volatile float f_res;
   7volatile double d_res;
   8volatile long double ld_res;
   9
  10volatile float f_snan = __builtin_nansf("");
  11volatile double d_snan = __builtin_nans("");
  12volatile long double ld_snan = __builtin_nansl("");
  13
  14int issignaling_f(float x)
  15{
  16    union { float f; uint32_t u; } u = { .f = x };
  17    return (u.u & 0x7fffffff) > 0x7f800000 && (u.u & 0x400000) == 0;
  18}
  19
  20int issignaling_d(double x)
  21{
  22    union { double d; uint64_t u; } u = { .d = x };
  23    return (((u.u & UINT64_C(0x7fffffffffffffff)) >
  24            UINT64_C(0x7ff0000000000000)) &&
  25            (u.u & UINT64_C(0x8000000000000)) == 0);
  26}
  27
  28int issignaling_ld(long double x)
  29{
  30    union {
  31        long double ld;
  32        struct { uint64_t sig; uint16_t sign_exp; } s;
  33    } u = { .ld = x };
  34    return ((u.s.sign_exp & 0x7fff) == 0x7fff &&
  35            (u.s.sig >> 63) != 0 &&
  36            (u.s.sig & UINT64_C(0x4000000000000000)) == 0);
  37}
  38
  39int main(void)
  40{
  41    int ret = 0;
  42    ld_res = f_snan;
  43    if (issignaling_ld(ld_res)) {
  44        printf("FAIL: float -> long double\n");
  45        ret = 1;
  46    }
  47    ld_res = d_snan;
  48    if (issignaling_ld(ld_res)) {
  49        printf("FAIL: double -> long double\n");
  50        ret = 1;
  51    }
  52    f_res = ld_snan;
  53    if (issignaling_d(f_res)) {
  54        printf("FAIL: long double -> float\n");
  55        ret = 1;
  56    }
  57    d_res = ld_snan;
  58    if (issignaling_d(d_res)) {
  59        printf("FAIL: long double -> double\n");
  60        ret = 1;
  61    }
  62    return ret;
  63}
  64