2 * fp-test-log2.c - test QEMU's softfloat log2
4 * Copyright (C) 2020, Linaro, Ltd.
6 * License: GNU GPL, version 2 or later.
7 * See the COPYING file in the top-level directory.
10 #error Must define HW_POISON_H to work around TARGET_* poisoning
13 #include "qemu/osdep.h"
14 #include "qemu/cutils.h"
16 #include "fpu/softfloat.h"
25 static void compare(ufloat64 test
, ufloat64 real
, ufloat64 soft
, bool exact
)
28 uint64_t ulp
= UINT64_MAX
;
30 if (real
.i
== soft
.i
) {
33 msb
= 63 - __builtin_clzll(real
.i
^ soft
.i
);
36 if (real
.i
> soft
.i
) {
37 ulp
= real
.i
- soft
.i
;
39 ulp
= soft
.i
- real
.i
;
43 /* glibc allows 3 ulp error in its libm-test-ulps; allow 4 here */
44 if (!exact
&& ulp
<= 4) {
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
);
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));
59 printf("Error in fraction: %" PRIu64
" ulp\n\n", ulp
);
67 int main(int ac
, char **av
)
69 ufloat64 test
, real
, soft
;
70 float_status qsf
= {0};
73 set_float_rounding_mode(float_round_nearest_even
, &qsf
);
76 real
.d
= -__builtin_inf();
77 soft
.i
= float64_log2(test
.i
, &qsf
);
78 compare(test
, real
, soft
, true);
82 soft
.i
= float64_log2(test
.i
, &qsf
);
83 compare(test
, real
, soft
, true);
87 soft
.i
= float64_log2(test
.i
, &qsf
);
88 compare(test
, real
, soft
, true);
92 soft
.i
= float64_log2(test
.i
, &qsf
);
93 compare(test
, real
, soft
, true);
97 soft
.i
= float64_log2(test
.i
, &qsf
);
98 compare(test
, real
, soft
, true);
100 test
.d
= __builtin_inf();
101 real
.d
= __builtin_inf();
102 soft
.i
= float64_log2(test
.i
, &qsf
);
103 compare(test
, real
, soft
, true);
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);
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);