qemu

FORK: QEMU emulator
git clone https://git.neptards.moe/neptards/qemu.git
Log | Files | Refs | Submodules | LICENSE

fp-test-log2.c (2775B)


      1 /*
      2  * fp-test-log2.c - test QEMU's softfloat log2
      3  *
      4  * Copyright (C) 2020, Linaro, Ltd.
      5  *
      6  * License: GNU GPL, version 2 or later.
      7  *   See the COPYING file in the top-level directory.
      8  */
      9 #ifndef HW_POISON_H
     10 #error Must define HW_POISON_H to work around TARGET_* poisoning
     11 #endif
     12 
     13 #include "qemu/osdep.h"
     14 #include "qemu/cutils.h"
     15 #include <math.h>
     16 #include "fpu/softfloat.h"
     17 
     18 typedef union {
     19     double d;
     20     float64 i;
     21 } ufloat64;
     22 
     23 static int errors;
     24 
     25 static void compare(ufloat64 test, ufloat64 real, ufloat64 soft, bool exact)
     26 {
     27     int msb;
     28     uint64_t ulp = UINT64_MAX;
     29 
     30     if (real.i == soft.i) {
     31         return;
     32     }
     33     msb = 63 - __builtin_clzll(real.i ^ soft.i);
     34 
     35     if (msb < 52) {
     36         if (real.i > soft.i) {
     37             ulp = real.i - soft.i;
     38         } else {
     39             ulp = soft.i - real.i;
     40         }
     41     }
     42 
     43     /* glibc allows 3 ulp error in its libm-test-ulps; allow 4 here */
     44     if (!exact && ulp <= 4) {
     45         return;
     46     }
     47 
     48     printf("test: %016" PRIx64 "  %+.13a\n"
     49            "  sf: %016" PRIx64 "  %+.13a\n"
     50            "libm: %016" PRIx64 "  %+.13a\n",
     51            test.i, test.d, soft.i, soft.d, real.i, real.d);
     52 
     53     if (msb == 63) {
     54         printf("Error in sign!\n\n");
     55     } else if (msb >= 52) {
     56         printf("Error in exponent: %d\n\n",
     57                (int)(soft.i >> 52) - (int)(real.i >> 52));
     58     } else {
     59         printf("Error in fraction: %" PRIu64 " ulp\n\n", ulp);
     60     }
     61 
     62     if (++errors == 20) {
     63         exit(1);
     64     }
     65 }
     66 
     67 int main(int ac, char **av)
     68 {
     69     ufloat64 test, real, soft;
     70     float_status qsf = {0};
     71     int i;
     72 
     73     set_float_rounding_mode(float_round_nearest_even, &qsf);
     74 
     75     test.d = 0.0;
     76     real.d = -__builtin_inf();
     77     soft.i = float64_log2(test.i, &qsf);
     78     compare(test, real, soft, true);
     79 
     80     test.d = 1.0;
     81     real.d = 0.0;
     82     soft.i = float64_log2(test.i, &qsf);
     83     compare(test, real, soft, true);
     84 
     85     test.d = 2.0;
     86     real.d = 1.0;
     87     soft.i = float64_log2(test.i, &qsf);
     88     compare(test, real, soft, true);
     89 
     90     test.d = 4.0;
     91     real.d = 2.0;
     92     soft.i = float64_log2(test.i, &qsf);
     93     compare(test, real, soft, true);
     94 
     95     test.d = 0x1p64;
     96     real.d = 64.0;
     97     soft.i = float64_log2(test.i, &qsf);
     98     compare(test, real, soft, true);
     99 
    100     test.d = __builtin_inf();
    101     real.d = __builtin_inf();
    102     soft.i = float64_log2(test.i, &qsf);
    103     compare(test, real, soft, true);
    104 
    105     for (i = 0; i < 10000; ++i) {
    106         test.d = drand48() + 1.0;    /* [1.0, 2.0) */
    107         real.d = log2(test.d);
    108         soft.i = float64_log2(test.i, &qsf);
    109         compare(test, real, soft, false);
    110 
    111         test.d = drand48() * 100;    /* [0.0, 100) */
    112         real.d = log2(test.d);
    113         soft.i = float64_log2(test.i, &qsf);
    114         compare(test, real, soft, false);
    115     }
    116 
    117     return 0;
    118 }