aboutsummaryrefslogtreecommitdiffstats
path: root/tests/fp/fp-test-log2.c
diff options
context:
space:
mode:
authorTimos Ampelikiotis <t.ampelikiotis@virtualopensystems.com>2023-10-10 11:40:56 +0000
committerTimos Ampelikiotis <t.ampelikiotis@virtualopensystems.com>2023-10-10 11:40:56 +0000
commite02cda008591317b1625707ff8e115a4841aa889 (patch)
treeaee302e3cf8b59ec2d32ec481be3d1afddfc8968 /tests/fp/fp-test-log2.c
parentcc668e6b7e0ffd8c9d130513d12053cf5eda1d3b (diff)
Introduce Virtio-loopback epsilon release:
Epsilon release introduces a new compatibility layer which make virtio-loopback design to work with QEMU and rust-vmm vhost-user backend without require any changes. Signed-off-by: Timos Ampelikiotis <t.ampelikiotis@virtualopensystems.com> Change-Id: I52e57563e08a7d0bdc002f8e928ee61ba0c53dd9
Diffstat (limited to 'tests/fp/fp-test-log2.c')
-rw-r--r--tests/fp/fp-test-log2.c118
1 files changed, 118 insertions, 0 deletions
diff --git a/tests/fp/fp-test-log2.c b/tests/fp/fp-test-log2.c
new file mode 100644
index 000000000..4eae93eb7
--- /dev/null
+++ b/tests/fp/fp-test-log2.c
@@ -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;
+}