mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-07 17:53:56 -06:00
softfloat: Move floatN_log2 to softfloat-parts.c.inc
Rename to parts$N_log2. Though this is partly a ruse, since I do not believe the code will succeed for float128 without work. Which is ok for now, because we do not need this for more than float32 and float64. Since berkeley-testfloat-3 doesn't support log2, compare float64_log2 vs the system log2. Fix the errors for inputs near 1.0: test: 3ff00000000000b0 +0x1.00000000000b0p+0 sf: 3d2fa00000000000 +0x1.fa00000000000p-45 libm: 3d2fbd422b1bd36f +0x1.fbd422b1bd36fp-45 Error in fraction: 32170028290927 ulp test: 3feec24f6770b100 +0x1.ec24f6770b100p-1 sf: bfad3740d13c9ec0 -0x1.d3740d13c9ec0p-5 libm: bfad3740d13c9e98 -0x1.d3740d13c9e98p-5 Error in fraction: 40 ulp Reviewed-by: Alex Bennée <alex.bennee@linaro.org> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
parent
572c4d862f
commit
2fa3546c8f
4 changed files with 281 additions and 99 deletions
118
tests/fp/fp-test-log2.c
Normal file
118
tests/fp/fp-test-log2.c
Normal file
|
@ -0,0 +1,118 @@
|
|||
/*
|
||||
* fp-test-log2.c - test QEMU's softfloat log2
|
||||
*
|
||||
* Copyright (C) 2020, Linaro, Ltd.
|
||||
*
|
||||
* License: GNU GPL, version 2 or later.
|
||||
* See the COPYING file in the top-level directory.
|
||||
*/
|
||||
#ifndef HW_POISON_H
|
||||
#error Must define HW_POISON_H to work around TARGET_* poisoning
|
||||
#endif
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu/cutils.h"
|
||||
#include <math.h>
|
||||
#include "fpu/softfloat.h"
|
||||
|
||||
typedef union {
|
||||
double d;
|
||||
float64 i;
|
||||
} ufloat64;
|
||||
|
||||
static int errors;
|
||||
|
||||
static void compare(ufloat64 test, ufloat64 real, ufloat64 soft, bool exact)
|
||||
{
|
||||
int msb;
|
||||
uint64_t ulp = UINT64_MAX;
|
||||
|
||||
if (real.i == soft.i) {
|
||||
return;
|
||||
}
|
||||
msb = 63 - __builtin_clzll(real.i ^ soft.i);
|
||||
|
||||
if (msb < 52) {
|
||||
if (real.i > soft.i) {
|
||||
ulp = real.i - soft.i;
|
||||
} else {
|
||||
ulp = soft.i - real.i;
|
||||
}
|
||||
}
|
||||
|
||||
/* glibc allows 3 ulp error in its libm-test-ulps; allow 4 here */
|
||||
if (!exact && ulp <= 4) {
|
||||
return;
|
||||
}
|
||||
|
||||
printf("test: %016" PRIx64 " %+.13a\n"
|
||||
" sf: %016" PRIx64 " %+.13a\n"
|
||||
"libm: %016" PRIx64 " %+.13a\n",
|
||||
test.i, test.d, soft.i, soft.d, real.i, real.d);
|
||||
|
||||
if (msb == 63) {
|
||||
printf("Error in sign!\n\n");
|
||||
} else if (msb >= 52) {
|
||||
printf("Error in exponent: %d\n\n",
|
||||
(int)(soft.i >> 52) - (int)(real.i >> 52));
|
||||
} else {
|
||||
printf("Error in fraction: %" PRIu64 " ulp\n\n", ulp);
|
||||
}
|
||||
|
||||
if (++errors == 20) {
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
int main(int ac, char **av)
|
||||
{
|
||||
ufloat64 test, real, soft;
|
||||
float_status qsf = {0};
|
||||
int i;
|
||||
|
||||
set_float_rounding_mode(float_round_nearest_even, &qsf);
|
||||
|
||||
test.d = 0.0;
|
||||
real.d = -__builtin_inf();
|
||||
soft.i = float64_log2(test.i, &qsf);
|
||||
compare(test, real, soft, true);
|
||||
|
||||
test.d = 1.0;
|
||||
real.d = 0.0;
|
||||
soft.i = float64_log2(test.i, &qsf);
|
||||
compare(test, real, soft, true);
|
||||
|
||||
test.d = 2.0;
|
||||
real.d = 1.0;
|
||||
soft.i = float64_log2(test.i, &qsf);
|
||||
compare(test, real, soft, true);
|
||||
|
||||
test.d = 4.0;
|
||||
real.d = 2.0;
|
||||
soft.i = float64_log2(test.i, &qsf);
|
||||
compare(test, real, soft, true);
|
||||
|
||||
test.d = 0x1p64;
|
||||
real.d = 64.0;
|
||||
soft.i = float64_log2(test.i, &qsf);
|
||||
compare(test, real, soft, true);
|
||||
|
||||
test.d = __builtin_inf();
|
||||
real.d = __builtin_inf();
|
||||
soft.i = float64_log2(test.i, &qsf);
|
||||
compare(test, real, soft, true);
|
||||
|
||||
for (i = 0; i < 10000; ++i) {
|
||||
test.d = drand48() + 1.0; /* [1.0, 2.0) */
|
||||
real.d = log2(test.d);
|
||||
soft.i = float64_log2(test.i, &qsf);
|
||||
compare(test, real, soft, false);
|
||||
|
||||
test.d = drand48() * 100; /* [0.0, 100) */
|
||||
real.d = log2(test.d);
|
||||
soft.i = float64_log2(test.i, &qsf);
|
||||
compare(test, real, soft, false);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -634,3 +634,14 @@ fpbench = executable(
|
|||
include_directories: [sfinc, include_directories(tfdir)],
|
||||
c_args: fpcflags,
|
||||
)
|
||||
|
||||
fptestlog2 = executable(
|
||||
'fp-test-log2',
|
||||
['fp-test-log2.c', '../../fpu/softfloat.c'],
|
||||
link_with: [libsoftfloat],
|
||||
dependencies: [qemuutil],
|
||||
include_directories: [sfinc],
|
||||
c_args: fpcflags,
|
||||
)
|
||||
test('fp-test-log2', fptestlog2,
|
||||
suite: ['softfloat', 'softfloat-ops'])
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue