svn commit: r251835 - user/peterj
Peter Jeremy
peterj at FreeBSD.org
Mon Jun 17 08:49:09 UTC 2013
Author: peterj
Date: Mon Jun 17 08:49:08 2013
New Revision: 251835
URL: http://svnweb.freebsd.org/changeset/base/251835
Log:
Add a libm test tool that I developed as part of the FreeBSD numerics work.
This program tests libm exception conditions listed in WG14/N1256 G.6
against the set of float, double and long double functions this program
is linked against. Note that the libm can be incomplete - this program
uses dlfunc(3) to identify which functions are present.
It is intended to be portable across operating systems and architectures.
Added:
user/peterj/
user/peterj/README
user/peterj/ctest.c (contents, props changed)
Added: user/peterj/README
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ user/peterj/README Mon Jun 17 08:49:08 2013 (r251835)
@@ -0,0 +1,6 @@
+My odds & ends
+
+ctest.c test libm exception conditions listed in WG14/N1256 G.6
+ against a set of float, double and long double functions
+
+$FreeBSD$
Added: user/peterj/ctest.c
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ user/peterj/ctest.c Mon Jun 17 08:49:08 2013 (r251835)
@@ -0,0 +1,1241 @@
+/*-
+ * Copyright (c) 2012 Peter Jeremy <peterj at FreeBSD.ORG>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * This program tests libm exception conditions listed in WG14/N1256 G.6
+ * against the set of float, double and long double functions this program
+ * is linked against. Note that the libm can be incomplete - this program
+ * uses dlfunc(3) to identify which functions are present.
+ *
+ * It is intended to be portable across operating systems and architectures.
+ *
+ * Command line arguments:
+ * -v Verify that the various unions are the correct size and that the
+ * test table is sane rather than performing the tests.
+ * -r List each function being tested and the arguments being passed.
+ *
+ * Default: Only report missing functions and incorrect results.
+ */
+
+#ifdef __FreeBSD
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+#endif
+#include <stdint.h> /* for [u]intNN_t */
+#include <math.h>
+#include <complex.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#define __USE_GNU /* Linux is broken */
+#include <dlfcn.h>
+
+#ifndef __FreeBSD
+#define dlfunc(a,b) dlsym(a,b)
+#endif
+
+/* long doubles differ between architectures so define appropriate structures for each family */
+#if defined(__i386__) || defined(__amd64__)
+/* From FreeBSD: stable/8/lib/libc/amd64/_fpmath.h 175402 2008-01-17 16:39:07Z bde */
+#ifdef __amd64__
+union IEEEl2bits {
+ long double f;
+ struct Ieeel2bits {
+ uint32_t manl :32;
+ uint32_t manh :32;
+ uint32_t exp :15;
+ uint32_t sign :1;
+ uint32_t junkl :16;
+ uint32_t junkh :32;
+ } bits;
+ struct {
+ uint64_t man :64;
+ uint64_t expsign :16;
+ uint64_t junk :48;
+ } xbits;
+ uint64_t i;
+};
+#else
+union IEEEl2bits {
+ long double f;
+ struct Ieeel2bits {
+ uint32_t manl :32;
+ uint32_t manh :32;
+ uint32_t exp :15;
+ uint32_t sign :1;
+ uint32_t junkl :16;
+ } bits;
+ struct {
+ uint32_t manl :32;
+ uint32_t manh :32;
+ uint32_t expsign :16;
+ uint32_t junk :16;
+ } xbits;
+};
+#endif
+
+/* Unlike all the other formats, the units bit is explicit for x87 */
+#define L_ZERO PACK3(0x0000, 0x00000000U, 0x00000000U)
+#define L_ONE PACK3(0x3fff, 0x80000000U, 0x00000000U)
+#define L_INF PACK3(0x7fff, 0x80000000U, 0x00000000U)
+#define L_NAN PACK3(0x7fff, 0xc0000000U, 0x00000000U)
+#define L_PI_4 PACK3(0x3ffe, 0xc90fdaa2U, 0x2168c235U)
+#define L_PI_2 PACK3(0x3fff, 0xc90fdaa2U, 0x2168c235U)
+#define L_3PI_4 PACK3(0x4000, 0x96cbe3f9U, 0x990e91a8U)
+#define L_PI PACK3(0x4000, 0xc90fdaa2U, 0x2168c235U)
+
+/*
+ * On i386, sizeof(long double) is 12 but at least the Atom N270 only
+ * actually writes 10 bytes. Since the result validation is done
+ * using memcmp(), explicitly define the number of bytes to compare.
+ */
+#define sizeof_long_double 10
+#define INF_EXP 0x7fff
+#elif defined(__arm__)
+/* From FreeBSD: stable/8/lib/libc/arm/_fpmath.h 186461 2008-12-23 22:20:59Z marcel */
+/* Raspberry Pi is fully little-endian */
+union IEEEl2bits {
+ long double f;
+ struct Ieeel2bits {
+ uint32_t manl :32;
+ uint32_t manh :20;
+ uint32_t exp :11;
+ uint32_t sign :1;
+ } bits;
+ struct {
+ uint64_t man :52;
+ uint64_t expsign :12;
+ } xbits;
+ uint64_t i;
+};
+
+#define L_ZERO D_ZERO
+#define L_ONE D_ONE
+#define L_INF D_INF
+#define L_NAN D_NAN
+#define L_PI_4 D_PI_4
+#define L_PI_2 D_PI_2
+#define L_3PI_4 D_3PI_4
+#define L_PI D_PI
+
+#define sizeof_long_double sizeof(long double)
+#define INF_EXP 0x7ff
+#elif defined(__sparc)
+/* From FreeBSD: stable/8/lib/libc/sparc64/_fpmath.h 175459 2008-01-18 21:25:51Z das */
+#define FP_BIG_ENDIAN
+
+union IEEEl2bits {
+ long double f;
+ struct Ieeel2bits {
+ uint32_t sign :1;
+ uint32_t exp :15;
+ uint32_t manhh :16;
+ uint32_t manhl :32;
+ uint32_t manlh :32;
+ uint32_t manll :32;
+ } bits;
+ struct {
+ uint64_t expsign :16;
+ uint64_t manh :48;
+ uint64_t manl :64;
+ } xbits;
+ uint64_t i[2];
+};
+
+#define L_ZERO { 0, 0x0000, 0x0000, 0x00000000U, 0x00000000U, 0x00000000U }
+#define L_ONE { 0, 0x3fff, 0x0000, 0x00000000U, 0x00000000U, 0x00000000U }
+#define L_INF { 0, 0x7fff, 0x0000, 0x00000000U, 0x00000000U, 0x00000000U }
+#define L_NAN { 0, 0x7fff, 0x8000, 0x00000000U, 0x00000000U, 0x00000000U }
+#define L_PI_4 { 0, 0x3ffe, 0x921f, 0xb54442d1U, 0x8469898cU, 0xc51701b8U }
+#define L_PI_2 { 0, 0x3fff, 0x921f, 0xb54442d1U, 0x8469898cU, 0xc51701b8U }
+#define L_3PI_4 { 0, 0x4000, 0x2d97, 0xc7f3321dU, 0x234f2729U, 0x93d1414aU }
+#define L_PI { 0, 0x4000, 0x921f, 0xb54442d1U, 0x8469898cU, 0xc51701b8U }
+
+#define sizeof_long_double sizeof(long double)
+#define INF_EXP 0x7fff
+#endif
+
+/* float and double are consistent across all architectures apart from endianness */
+union IEEEf2bits {
+ float f;
+ uint32_t i;
+ struct Ieeef2bits {
+#ifndef FP_BIG_ENDIAN
+ uint32_t man :23;
+ uint32_t exp :8;
+ uint32_t sign :1;
+#else
+ uint32_t sign :1;
+ uint32_t exp :8;
+ uint32_t man :23;
+#endif
+ } bits;
+};
+
+union IEEEd2bits {
+ double f;
+ uint64_t i;
+ struct Ieeed2bits {
+#ifndef FP_BIG_ENDIAN
+ uint32_t manl :32;
+ uint32_t manh :20;
+ uint32_t exp :11;
+ uint32_t sign :1;
+#else /* _BIG_ENDIAN */
+ uint32_t sign :1;
+ uint32_t exp :11;
+ uint32_t manh :20;
+ uint32_t manl :32;
+#endif
+ } bits;
+ struct {
+#ifndef FP_BIG_ENDIAN
+ uint64_t man :52;
+ uint64_t expsign :12;
+#else /* _BIG_ENDIAN */
+ uint64_t expsign :12;
+ uint64_t man :52;
+#endif
+ } xbits;
+};
+
+typedef struct Ieeef2bits fbits;
+typedef struct Ieeed2bits dbits;
+typedef struct Ieeel2bits lbits;
+
+#ifdef FP_BIG_ENDIAN
+#define PACK2(exp, man) { 0, exp, man }
+#define PACK3(exp, manh, manl) { 0, exp, manh, manl }
+#else
+#define PACK2(exp, man) { man, exp }
+#define PACK3(exp, manh, manl) { manl, manh, exp }
+#endif
+
+#define F_ZERO PACK2(0x00, 0x000000)
+#define F_ONE PACK2(0x7f, 0x000000)
+#define F_INF PACK2(0xff, 0x000000)
+#define F_NAN PACK2(0xff, 0x400000)
+#define F_PI_4 PACK2(0x7e, 0x490fdb)
+#define F_PI_2 PACK2(0x7f, 0x490fdb)
+#define F_3PI_4 PACK2(0x80, 0x16cbe4)
+#define F_PI PACK2(0x80, 0x490fdb)
+
+#define D_ZERO PACK3(0x000, 0x00000, 0x00000000U)
+#define D_ONE PACK3(0x3ff, 0x00000, 0x00000000U)
+#define D_INF PACK3(0x7ff, 0x00000, 0x00000000U)
+#define D_NAN PACK3(0x7ff, 0x80000, 0x00000000U)
+#define D_PI_4 PACK3(0x3fe, 0x921fb, 0x54442d18U)
+#define D_PI_2 PACK3(0x3ff, 0x921fb, 0x54442d18U)
+#define D_3PI_4 PACK3(0x400, 0x2d97c, 0x7f3321d2U)
+#define D_PI PACK3(0x400, 0x921fb, 0x54442d18U)
+
+/*
+ * C99 specifies that complex numbers have the same representation as
+ * an array of two elements, where the first element is the real part
+ * and the second element is the imaginary part.
+ */
+typedef union {
+ float complex f;
+ union IEEEf2bits a[2];
+} float_complex;
+typedef union {
+ double complex f;
+ union IEEEd2bits a[2];
+} double_complex;
+typedef union {
+ long double complex f;
+ union IEEEl2bits a[2];
+} long_double_complex;
+#define REALPART(z) ((z).a[0])
+#define IMAGPART(z) ((z).a[1])
+
+typedef struct {
+ long_double_complex l;
+ double_complex d;
+ float_complex f;
+} fpblock;
+
+/*
+ * The following is a formal copy of WG14/N1256 G.6. The executable functions are
+ * found via dlfunc() using the name. The arguments and expected result are strings
+ * defining the value(s). These strings optionally begin with '+' or '-', indicating
+ * that the value has that sign, if neither is specified, the value can have either
+ * sign. 'x' and 'y' represent any finite value (including zero if this is not
+ * separately specified).
+ *
+ * The exceptions and special conditions fields are currently ignored.
+ *
+ * The table is terminated by a NULL name.
+ */
+const struct test_c_c {
+ const char *tname;
+ const char *tare, *taim; /* arguments */
+ const char *trre, *trim; /* expected result */
+ const char *texc; /* exceptions */
+ const char *spec; /* special conditions */
+} test_c_c[] = {
+ { "cacos", "0", "+0", "+π/2", "-0" },
+ { "cacos", "0", "-0", "+π/2", "+0" },
+ { "cacos", "0", "NaN", "+π/2", "NaN" },
+ { "cacos", "+Inf", "+Inf", "+π/4", "-Inf" },
+ { "cacos", "+Inf", "-Inf", "+π/4", "+Inf" },
+ { "cacos", "-Inf", "+Inf", "+3π/4", "-Inf" },
+ { "cacos", "-Inf", "-Inf", "+3π/4", "+Inf" },
+ { "cacos", "Inf", "NaN", "NaN", "Inf" },
+ { "cacos", "+Inf", "+y", "+0", "-Inf" },
+ { "cacos", "+Inf", "-y", "+0", "+Inf" },
+ { "cacos", "-Inf", "+y", "+π", "-Inf" },
+ { "cacos", "-Inf", "-y", "+π", "+Inf" },
+ { "cacos", "NaN", "+Inf", "NaN", "-Inf" },
+ { "cacos", "NaN", "-Inf", "NaN", "+Inf" },
+ { "cacos", "NaN", "NaN", "NaN", "NaN" },
+ { "cacos", "NaN", "y", "NaN", "NaN", "[inv]" },
+ { "cacos", "x", "+Inf", "+π/2", "-Inf" },
+ { "cacos", "x", "-Inf", "+π/2", "+Inf" },
+ { "cacos", "x", "NaN", "NaN", "NaN", "[inv]" },
+
+ { "cacosh", "0", "+0", "+0", "+π/2" },
+ { "cacosh", "0", "-0", "+0", "-π/2" },
+ { "cacosh", "+Inf", "+Inf", "+Inf", "+π/4" },
+ { "cacosh", "+Inf", "-Inf", "+Inf", "-π/4" },
+ { "cacosh", "-Inf", "+Inf", "+Inf", "+3π/4" },
+ { "cacosh", "-Inf", "-Inf", "+Inf", "-3π/4" },
+ { "cacosh", "Inf", "NaN", "+Inf", "NaN" },
+ { "cacosh", "+Inf", "+y", "+Inf", "+0" },
+ { "cacosh", "+Inf", "-y", "+Inf", "-0" },
+ { "cacosh", "-Inf", "+y", "+Inf", "+π" },
+ { "cacosh", "-Inf", "-y", "+Inf", "-π" },
+ { "cacosh", "NaN", "Inf", "+Inf", "NaN" },
+ { "cacosh", "NaN", "NaN", "NaN", "NaN" },
+ { "cacosh", "NaN", "y", "NaN", "NaN", "[inv]" },
+ { "cacosh", "x", "+Inf", "+Inf", "+π/2" },
+ { "cacosh", "x", "-Inf", "+Inf", "-π/2" },
+ { "cacosh", "x", "NaN", "NaN", "NaN", "[inv]" },
+
+ { "casin", "-0", "+0", "-0", "+0" },
+ { "casin", "+0", "+0", "+0", "+0" },
+ { "casin", "-0", "-0", "-0", "-0" },
+ { "casin", "+0", "-0", "+0", "-0" },
+ { "casin", "-Inf", "+Inf", "-π/4", "+Inf" },
+ { "casin", "+Inf", "+Inf", "+π/4", "+Inf" },
+ { "casin", "-Inf", "-Inf", "-π/4", "-Inf" },
+ { "casin", "+Inf", "-Inf", "+π/4", "-Inf" },
+ { "casin", "NaN", "+Inf", "NaN", "+Inf" },
+ { "casin", "NaN", "-Inf", "NaN", "-Inf" },
+ { "casin", "-y", "+Inf", "-0", "+Inf" },
+ { "casin", "+y", "+Inf", "+0", "+Inf" },
+ { "casin", "-y", "-Inf", "-0", "-Inf" },
+ { "casin", "+y", "-Inf", "+0", "-Inf" },
+ { "casin", "-0", "NaN", "-0", "NaN" },
+ { "casin", "+0", "NaN", "+0", "NaN" },
+ { "casin", "Inf", "NaN", "NaN", "Inf" },
+ { "casin", "NaN", "NaN", "NaN", "NaN" },
+ { "casin", "y", "NaN", "NaN", "NaN", "[inv]" },
+ { "casin", "-Inf", "+x", "-π/2", "+Inf" },
+ { "casin", "+Inf", "+x", "+π/2", "+Inf" },
+ { "casin", "-Inf", "-x", "-π/2", "-Inf" },
+ { "casin", "+Inf", "-x", "+π/2", "-Inf" },
+ { "casin", "NaN", "x", "NaN", "NaN", "[inv]" },
+
+ { "casinh", "+0", "+0", "+0", "+0" },
+ { "casinh", "+0", "-0", "+0", "-0" },
+ { "casinh", "-0", "+0", "-0", "+0" },
+ { "casinh", "-0", "-0", "-0", "-0" },
+ { "casinh", "+Inf", "+Inf", "+Inf", "+π/4" },
+ { "casinh", "+Inf", "-Inf", "+Inf", "-π/4" },
+ { "casinh", "-Inf", "+Inf", "-Inf", "+π/4" },
+ { "casinh", "-Inf", "-Inf", "-Inf", "-π/4" },
+ { "casinh", "+Inf", "NaN", "+Inf", "NaN" },
+ { "casinh", "-Inf", "NaN", "-Inf", "NaN" },
+ { "casinh", "+Inf", "+y", "+Inf", "+0" },
+ { "casinh", "+Inf", "-y", "+Inf", "-0" },
+ { "casinh", "-Inf", "+y", "-Inf", "+0" },
+ { "casinh", "-Inf", "-y", "-Inf", "-0" },
+ { "casinh", "NaN", "+0", "NaN", "+0" },
+ { "casinh", "NaN", "-0", "NaN", "-0" },
+ { "casinh", "NaN", "Inf", "Inf", "NaN" },
+ { "casinh", "NaN", "NaN", "NaN", "NaN" },
+ { "casinh", "NaN", "y", "NaN", "NaN", "[inv]" },
+ { "casinh", "+x", "+Inf", "+Inf", "+π/2" },
+ { "casinh", "+x", "-Inf", "+Inf", "-π/2" },
+ { "casinh", "-x", "+Inf", "-Inf", "+π/2" },
+ { "casinh", "-x", "-Inf", "-Inf", "-π/2" },
+ { "casinh", "x", "NaN", "NaN", "NaN", "[inv]" },
+
+ { "catan", "-0", "+0", "-0", "+0" },
+ { "catan", "+0", "+0", "+0", "+0" },
+ { "catan", "-0", "-0", "-0", "-0" },
+ { "catan", "+0", "-0", "+0", "-0" },
+ { "catan", "NaN", "+0", "NaN", "+0" },
+ { "catan", "NaN", "-0", "NaN", "-0" },
+ { "catan", "-0", "+1", "-0", "+Inf", "{div0}" },
+ { "catan", "+0", "+1", "+0", "+Inf", "{div0}" },
+ { "catan", "-0", "-1", "-0", "-Inf", "{div0}" },
+ { "catan", "+0", "-1", "+0", "-Inf", "{div0}" },
+ { "catan", "-Inf", "+Inf", "-π/2", "+0" },
+ { "catan", "+Inf", "+Inf", "+π/2", "+0" },
+ { "catan", "-Inf", "-Inf", "-π/2", "-0" },
+ { "catan", "+Inf", "-Inf", "+π/2", "-0" },
+ { "catan", "NaN", "+Inf", "NaN", "+0" },
+ { "catan", "NaN", "-Inf", "NaN", "-0" },
+ { "catan", "-y", "+Inf", "-π/2", "+0" },
+ { "catan", "+y", "+Inf", "+π/2", "+0" },
+ { "catan", "-Inf", "NaN", "-π/2", "0" },
+ { "catan", "+Inf", "NaN", "+π/2", "0" },
+ { "catan", "NaN", "NaN", "NaN", "NaN" },
+ { "catan", "y", "NaN", "NaN", "NaN", "[inv]" },
+ { "catan", "-Inf", "+x", "-π/2", "+0" },
+ { "catan", "+Inf", "+x", "+π/2", "+0" },
+ { "catan", "-Inf", "-x", "-π/2", "-0" },
+ { "catan", "+Inf", "-x", "+π/2", "-0" },
+ { "catan", "NaN", "x", "NaN", "NaN", "[inv]" },
+
+ { "catanh", "+0", "+0", "+0", "+0" },
+ { "catanh", "+0", "-0", "+0", "-0" },
+ { "catanh", "-0", "+0", "-0", "+0" },
+ { "catanh", "-0", "-0", "-0", "-0" },
+ { "catanh", "+0", "NaN", "+0", "NaN" },
+ { "catanh", "-0", "NaN", "-0", "NaN" },
+ { "catanh", "+1", "+0", "+Inf", "+0", "{div0}" },
+ { "catanh", "+1", "-0", "+Inf", "-0", "{div0}" },
+ { "catanh", "-1", "+0", "-Inf", "+0", "{div0}" },
+ { "catanh", "-1", "-0", "-Inf", "-0", "{div0}" },
+ { "catanh", "+Inf", "+Inf", "+0", "+π/2" },
+ { "catanh", "+Inf", "-Inf", "+0", "-π/2" },
+ { "catanh", "-Inf", "+Inf", "-0", "+π/2" },
+ { "catanh", "-Inf", "-Inf", "-0", "-π/2" },
+ { "catanh", "+Inf", "NaN", "+0", "NaN" },
+ { "catanh", "-Inf", "NaN", "-0", "NaN" },
+ { "catanh", "+Inf", "+y", "+0", "+π/2" },
+ { "catanh", "+Inf", "-y", "+0", "-π/2" },
+ { "catanh", "NaN", "+Inf", "0", "+π/2" },
+ { "catanh", "NaN", "-Inf", "0", "-π/2" },
+ { "catanh", "NaN", "NaN", "NaN", "NaN" },
+ { "catanh", "NaN", "y", "NaN", "NaN", "[inv]" },
+ { "catanh", "+x", "+Inf", "+0", "+π/2" },
+ { "catanh", "+x", "-Inf", "+0", "-π/2" },
+ { "catanh", "-x", "+Inf", "-0", "+π/2" },
+ { "catanh", "-x", "-Inf", "-0", "-π/2" },
+ { "catanh", "x", "NaN", "NaN", "NaN", "[inv]" },
+
+ { "ccos", "-0", "+0", "+1", "+0" },
+ { "ccos", "+0", "+0", "+1", "-0" },
+ { "ccos", "-0", "-0", "+1", "-0" },
+ { "ccos", "+0", "-0", "+1", "+0" },
+ { "ccos", "Inf", "0", "NaN", "0", "{inv}" },
+ { "ccos", "NaN", "0", "NaN", "0" },
+ { "ccos", "-0", "+Inf", "+Inf", "+0" },
+ { "ccos", "+0", "+Inf", "+Inf", "-0" },
+ { "ccos", "-0", "-Inf", "+Inf", "-0" },
+ { "ccos", "+0", "-Inf", "+Inf", "+0" },
+ { "ccos", "Inf", "Inf", "Inf", "NaN", "{inv}" },
+ { "ccos", "NaN", "Inf", "+Inf", "NaN" },
+ { "ccos", "x", "+Inf", "+Inf*cos(x)", "-Inf*sin(x)" },
+ { "ccos", "x", "-Inf", "+Inf*cos(x)", "+Inf*sin(x)" },
+ { "ccos", "0", "NaN", "NaN", "0" },
+ { "ccos", "NaN", "NaN", "NaN", "NaN" },
+ { "ccos", "y", "NaN", "NaN", "NaN", "[inv]" },
+ { "ccos", "Inf", "x", "NaN", "NaN", "{inv}" },
+ { "ccos", "NaN", "x", "NaN", "NaN", "[inv]" },
+
+ { "ccosh", "+0", "+0", "+1", "+0" },
+ { "ccosh", "-0", "+0", "+1", "-0" },
+ { "ccosh", "+0", "-0", "+1", "-0" },
+ { "ccosh", "-0", "-0", "+1", "+0" },
+ { "ccosh", "0", "Inf", "NaN", "0", "{inv}" },
+ { "ccosh", "0", "NaN", "NaN", "0" },
+ { "ccosh", "+Inf", "+0", "+Inf", "+0" },
+ { "ccosh", "+Inf", "-0", "+Inf", "-0" },
+ { "ccosh", "-Inf", "+0", "+Inf", "-0" },
+ { "ccosh", "-Inf", "-0", "+Inf", "+0" },
+ { "ccosh", "Inf", "Inf", "Inf", "NaN", "{inv}" },
+ { "ccosh", "Inf", "NaN", "+Inf", "NaN" },
+ { "ccosh", "+Inf", "y", "+Inf*cos(y)", "+Inf*sin(y)" },
+ { "ccosh", "-Inf", "y", "+Inf*cos(y)", "-Inf*sin(y)" },
+ { "ccosh", "NaN", "0", "NaN", "0" },
+ { "ccosh", "NaN", "NaN", "NaN", "NaN" },
+ { "ccosh", "NaN", "y", "NaN", "NaN", "[inv]" },
+ { "ccosh", "x", "Inf", "NaN", "NaN", "{inv}" },
+ { "ccosh", "x", "NaN", "NaN", "NaN", "[inv]" },
+
+ { "cexp", "0", "+0", "+1", "+0" },
+ { "cexp", "0", "-0", "+1", "-0" },
+ { "cexp", "+Inf", "+0", "+Inf", "+0" },
+ { "cexp", "+Inf", "-0", "+Inf", "-0" },
+ { "cexp", "+Inf", "Inf", "Inf", "NaN", "{inv}" },
+ { "cexp", "-Inf", "Inf", "0", "0" },
+ { "cexp", "+Inf", "NaN", "Inf", "NaN" },
+ { "cexp", "-Inf", "NaN", "0", "0" },
+ { "cexp", "+Inf", "y", "+Inf*cos(y)", "+Inf*sin(y)" },
+ { "cexp", "-Inf", "y", "+0*cos(y)", "+0*sin(y)" },
+ { "cexp", "NaN", "+0", "NaN", "+0" },
+ { "cexp", "NaN", "-0", "NaN", "-0" },
+ { "cexp", "NaN", "NaN", "NaN", "NaN" },
+ { "cexp", "NaN", "y", "NaN", "NaN", "[inv]" },
+ { "cexp", "x", "Inf", "NaN", "NaN", "{inv}" },
+ { "cexp", "x", "NaN", "NaN", "NaN", "[inv]" },
+
+ { "clog", "+0", "+0", "-Inf", "+0", "{div0}" },
+ { "clog", "+0", "-0", "-Inf", "-0", "{div0}" },
+ { "clog", "-0", "+0", "-Inf", "+π", "{div0}" },
+ { "clog", "-0", "-0", "-Inf", "-π", "{div0}" },
+ { "clog", "+Inf", "+Inf", "+Inf", "+π/4" },
+ { "clog", "+Inf", "-Inf", "+Inf", "-π/4" },
+ { "clog", "-Inf", "+Inf", "+Inf", "+3π/4" },
+ { "clog", "-Inf", "-Inf", "+Inf", "-3π/4" },
+ { "clog", "Inf", "NaN", "+Inf", "NaN" },
+ { "clog", "+Inf", "+y", "+Inf", "+0" },
+ { "clog", "+Inf", "-y", "+Inf", "-0" },
+ { "clog", "-Inf", "+y", "+Inf", "+π" },
+ { "clog", "-Inf", "-y", "+Inf", "-π" },
+ { "clog", "NaN", "Inf", "+Inf", "NaN" },
+ { "clog", "NaN", "NaN", "NaN", "NaN" },
+ { "clog", "NaN", "y", "NaN", "NaN", "[inv]" },
+ { "clog", "x", "+Inf", "+Inf", "+π/2" },
+ { "clog", "x", "-Inf", "+Inf", "-π/2" },
+ { "clog", "x", "NaN", "NaN", "NaN", "[inv]" },
+
+ { "csin", "-0", "+0", "-0", "+0" },
+ { "csin", "+0", "+0", "+0", "+0" },
+ { "csin", "-0", "-0", "-0", "-0" },
+ { "csin", "+0", "-0", "+0", "-0" },
+ { "csin", "Inf", "0", "NaN", "0", "{inv}" },
+ { "csin", "NaN", "0", "NaN", "0" },
+ { "csin", "-0", "+Inf", "-0", "+Inf" },
+ { "csin", "+0", "+Inf", "+0", "+Inf" },
+ { "csin", "-0", "-Inf", "-0", "-Inf" },
+ { "csin", "+0", "-Inf", "+0", "-Inf" },
+ { "csin", "Inf", "Inf", "NaN", "Inf", "{inv}" },
+ { "csin", "NaN", "Inf", "NaN", "Inf" },
+ { "csin", "x", "+Inf", "+Inf*sin(x)", "+Inf*cos(x)" },
+ { "csin", "x", "-Inf", "+Inf*sin(x)", "-Inf*cos(x)" },
+ { "csin", "-0", "NaN", "-0", "NaN" },
+ { "csin", "+0", "NaN", "+0", "NaN" },
+ { "csin", "NaN", "NaN", "NaN", "NaN" },
+ { "csin", "y", "NaN", "NaN", "NaN", "[inv]" },
+ { "csin", "Inf", "x", "NaN", "NaN", "{inv}" },
+ { "csin", "NaN", "x", "NaN", "NaN", "[inv]" },
+
+ { "csinh", "+0", "+0", "+0", "+0" },
+ { "csinh", "+0", "-0", "+0", "-0" },
+ { "csinh", "-0", "+0", "-0", "+0" },
+ { "csinh", "-0", "-0", "-0", "-0" },
+ { "csinh", "0", "Inf", "0", "NaN", "{inv}" },
+ { "csinh", "0", "NaN", "0", "NaN" },
+ { "csinh", "+Inf", "+0", "+Inf", "+0" },
+ { "csinh", "+Inf", "-0", "+Inf", "-0" },
+ { "csinh", "-Inf", "+0", "-Inf", "+0" },
+ { "csinh", "-Inf", "-0", "-Inf", "-0" },
+ { "csinh", "Inf", "Inf", "Inf", "NaN", "{inv}" },
+ { "csinh", "Inf", "NaN", "Inf", "NaN" },
+ { "csinh", "+Inf", "y", "+Inf*cos(y)", "+Inf*sin(y)" },
+ { "csinh", "-Inf", "y", "-Inf*cos(y)", "+Inf*sin(y)" },
+ { "csinh", "NaN", "+0", "NaN", "+0" },
+ { "csinh", "NaN", "-0", "NaN", "-0" },
+ { "csinh", "NaN", "NaN", "NaN", "NaN" },
+ { "csinh", "NaN", "y", "NaN", "NaN", "[inv]" },
+ { "csinh", "x", "Inf", "NaN", "NaN", "{inv}" },
+ { "csinh", "x", "NaN", "NaN", "NaN", "[inv]" },
+
+ { "csqrt", "0", "+0", "+0", "+0" },
+ { "csqrt", "0", "-0", "+0", "-0" },
+ { "csqrt", "+Inf", "NaN", "+Inf", "NaN" },
+ { "csqrt", "-Inf", "NaN", "NaN", "Inf" },
+ { "csqrt", "+Inf", "+y", "+Inf", "+0" },
+ { "csqrt", "+Inf", "-y", "+Inf", "-0" },
+ { "csqrt", "-Inf", "+y", "+0", "+Inf" },
+ { "csqrt", "-Inf", "-y", "+0", "-Inf" },
+ { "csqrt", "NaN", "+Inf", "+Inf", "+Inf" },
+ { "csqrt", "NaN", "-Inf", "+Inf", "-Inf" },
+ { "csqrt", "NaN", "NaN", "NaN", "NaN" },
+ { "csqrt", "NaN", "y", "NaN", "NaN", "[inv]" },
+ { "csqrt", "x", "+Inf", "+Inf", "+Inf" },
+ { "csqrt", "x", "-Inf", "+Inf", "-Inf" },
+ { "csqrt", "x", "NaN", "NaN", "NaN", "[inv]" },
+
+ { "ctan", "-0", "+0", "-0", "+0" },
+ { "ctan", "+0", "+0", "+0", "+0" },
+ { "ctan", "-0", "-0", "-0", "-0" },
+ { "ctan", "+0", "-0", "+0", "-0" },
+ { "ctan", "Inf", "+Inf", "0", "+1" },
+ { "ctan", "Inf", "-Inf", "0", "-1" },
+ { "ctan", "NaN", "+Inf", "0", "+1" },
+ { "ctan", "NaN", "-Inf", "0", "-1" },
+ { "ctan", "x", "+Inf", "+0*sin(2*x)", "+1" },
+ { "ctan", "x", "-Inf", "+0*sin(2*x)", "-1" },
+ { "ctan", "-0", "NaN", "-0", "NaN" },
+ { "ctan", "+0", "NaN", "+0", "NaN" },
+ { "ctan", "NaN", "NaN", "NaN", "NaN" },
+ { "ctan", "y", "NaN", "NaN", "NaN", "[inv]" },
+ { "ctan", "Inf", "x", "NaN", "NaN", "{inv}" },
+ { "ctan", "NaN", "x", "NaN", "NaN", "[inv]" },
+
+ { "ctanh", "+0", "+0", "+0", "+0" },
+ { "ctanh", "+0", "-0", "+0", "-0" },
+ { "ctanh", "-0", "+0", "-0", "+0" },
+ { "ctanh", "-0", "-0", "-0", "-0" },
+ { "ctanh", "+Inf", "Inf", "+1", "0" },
+ { "ctanh", "-Inf", "Inf", "-1", "0" },
+ { "ctanh", "+Inf", "NaN", "+1", "0" },
+ { "ctanh", "-Inf", "NaN", "-1", "0" },
+ { "ctanh", "+Inf", "y", "+1", "+0*sin(2*y)" },
+ { "ctanh", "-Inf", "y", "-1", "+0*sin(2*y)" },
+ { "ctanh", "NaN", "+0", "NaN", "+0" },
+ { "ctanh", "NaN", "-0", "NaN", "-0" },
+ { "ctanh", "NaN", "NaN", "NaN", "NaN" },
+ { "ctanh", "NaN", "y", "NaN", "NaN", "[inv]" },
+ { "ctanh", "x", "Inf", "NaN", "NaN", "{inv}" },
+ { "ctanh", "x", "NaN", "NaN", "NaN", "[inv]" },
+
+ { NULL }
+};
+
+/* argument/result string */
+enum T_VAL {
+ T_ZERO, T_FIN, T_INF, T_NAN, T_ONE, T_PI_4, T_PI_2, T_3PI_4, T_PI,
+ T_COSX, T_COSY, T_SINX, T_SIN2X, T_SINY, T_SIN2Y, T_OINV, T_DIV0, T_INV, T_UNK };
+
+/* Used to control state for iterating argument values */
+enum STATE {
+ S_COUNT = 32768, S_SSIN2X, S_SSINX, S_SSIN2Y, S_SSINY, S_SCOSX, S_SCOSY, S_NAN,
+ S_MASK = 0xffff, S_NEG = 0x80000, S_POS = 0x40000, S_MULT = 0x20000 };
+
+/* Map string name to enum and bit pattern of value */
+struct t_val {
+ const char *v_name; /* String name */
+ enum T_VAL v_val; /* Value */
+ fbits v_fval; /* float constant */
+ dbits v_dval; /* double constant */
+ lbits v_lval; /* long double constant */
+};
+
+/* Convert the name (without sign) to the constants */
+const struct t_val *
+mapname(const char *in)
+{
+ static const struct t_val t_map[] = {
+ { "0", T_ZERO, F_ZERO, D_ZERO, L_ZERO },
+ { "0*cos(y)", T_COSY, F_ZERO, D_ZERO, L_ZERO },
+ { "0*sin(2*y)", T_SIN2Y,F_ZERO, D_ZERO, L_ZERO },
+ { "0*sin(y)", T_SINY, F_ZERO, D_ZERO, L_ZERO },
+ { "0*cos(x)", T_COSX, F_ZERO, D_ZERO, L_ZERO },
+ { "0*sin(2*x)", T_SIN2X,F_ZERO, D_ZERO, L_ZERO },
+ { "0*sin(x)", T_SINX, F_ZERO, D_ZERO, L_ZERO },
+ { "1", T_ONE, F_ONE, D_ONE, L_ONE },
+ { "3π/4", T_3PI_4,F_3PI_4,D_3PI_4,L_3PI_4 },
+ { "Inf", T_INF, F_INF, D_INF, L_INF },
+ { "Inf*cos(y)", T_COSY, F_INF, D_INF, L_INF },
+ { "Inf*sin(y)", T_SINY, F_INF, D_INF, L_INF },
+ { "Inf*cos(x)", T_COSX, F_INF, D_INF, L_INF },
+ { "Inf*sin(x)", T_SINX, F_INF, D_INF, L_INF },
+ { "NaN", T_NAN, F_NAN, D_NAN, L_NAN },
+ { "[inv]", T_OINV },
+ { "x", T_FIN, F_3PI_4,D_3PI_4,L_3PI_4 },
+ { "y", T_FIN, F_3PI_4,D_3PI_4,L_3PI_4 },
+ { "{div0}", T_DIV0 },
+ { "{inv}", T_INV },
+ { "π", T_PI, F_PI, D_PI, L_PI },
+ { "π/2", T_PI_2, F_PI_2, D_PI_2, L_PI_2 },
+ { "π/4", T_PI_4, F_PI_4, D_PI_4, L_PI_4 },
+ { NULL, T_UNK }
+ };
+ int i;
+
+ for (i = 0; t_map[i].v_name != NULL; i++) {
+ if (strcmp(t_map[i].v_name, in) == 0)
+ break;
+ }
+ return (&t_map[i]);
+}
+
+/*
+ * vdecode() and do_validate() form partial sanity checks on the arguments
+ * and results in test_c_c
+ */
+int
+vdecode(const char *name, const char *n, int isarg)
+{
+ int sign;
+ int val;
+ int res;
+
+ sign = (*n == '+' || *n == '-') ? *n++ : 0;
+ val = mapname(n)->v_val;
+ if (val > (isarg ? T_NAN : T_SIN2Y)) {
+ printf("%s invalid %s '%s'\n", name, (isarg ? "arg" : "res"), n - !!sign);
+ return (0);
+ }
+ if (!isarg)
+ return (0);
+ res = 0;
+ if (sign != '-')
+ res |= val + 1;
+ if (sign != '+')
+ res |= (val + 5) << 8;
+ return (res);
+}
+
+/* validate test_c_c[] contents */
+void
+do_validate()
+{
+ const struct test_c_c *ep, *sp;
+ int res1, res2, res3, res4;
+ int64_t mask, val;
+
+ if (sizeof(float) != sizeof(struct Ieeef2bits) || sizeof(float) != sizeof(union IEEEf2bits) || sizeof(float complex) != sizeof(float_complex))
+ printf("float: %zu %zu %zu %zu %zu\n", sizeof(float), sizeof(struct Ieeef2bits), sizeof(union IEEEf2bits), sizeof(float complex), sizeof(float_complex));
+ if (sizeof(double) != sizeof(struct Ieeed2bits) || sizeof(double) != sizeof(union IEEEd2bits) || sizeof(double complex) != sizeof(double_complex))
+ printf("double: %zu %zu %zu %zu %zu\n", sizeof(double), sizeof(struct Ieeed2bits), sizeof(union IEEEd2bits), sizeof(double complex), sizeof(double_complex));
+ if (sizeof(long double) != sizeof(struct Ieeel2bits) || sizeof(long double) != sizeof(union IEEEl2bits) || sizeof(long double complex) != sizeof(long_double_complex))
+ printf("long double: %zu %zu %zu %zu %zu\n", sizeof(long double), sizeof(struct Ieeel2bits), sizeof(union IEEEl2bits), sizeof(long double complex), sizeof(long_double_complex));
+
+ for (ep = test_c_c; ep->tname != NULL; ) {
+ mask = 0;
+ for (sp = ep; ep->tname != NULL && !strcmp(ep->tname, sp->tname); ep++) {
+ res1 = vdecode(ep->tname, ep->tare, 1);
+ res3 = res1 >> 8;
+ res1 &= 0xff;
+ res2 = vdecode(ep->tname, ep->taim, 2);
+ res4 = res2 >> 8;
+ res2 &= 0xff;
+ vdecode(ep->tname, ep->trre, 0);
+ vdecode(ep->tname, ep->trim, 0);
+ val = 0;
+ if (res1 > 0) {
+ if (res2 > 0)
+ val |= (int64_t)1 << (res1 + res2 * 8 - 9);
+ if (res4 > 0)
+ val |= (int64_t)1 << (res1 + res4 * 8 - 9);
+ }
+ if (res3 > 0) {
+ if (res2 > 0)
+ val |= (int64_t)1 << (res3 + res2 * 8 - 9);
+ if (res4 > 0)
+ val |= (int64_t)1 << (res3 + res4 * 8 - 9);
+ }
+ if (val & mask)
+ printf("%s duplicate '%s,%s' 0x%016jx 0x%016jx %x %x %x %x\n",
+ ep->tname, ep->tare, ep->taim, (intmax_t)mask, (intmax_t)val, res1, res3, res2, res4);
+ mask |= val;
+ }
+ }
+}
+
+/*
+ * Lookup an argument or result string and initialise the state and value (in fp).
+ *
+ * n is the input string describing the argument or expectud result.
+ * state is used to return state information used to iterate through
+ * arguments or define result information, based on enum STATE
+ * fp is used to return the value associated with the input string. It contains
+ * float, double and long double complex numbers. A single invocation of
+ * decode will initialise either the real or imaginary parts of all 3.
+ * ixexp - zero if the input string is an argument, non-zero for result.
+ * ix is 0 for the real part or 1 for the imaginary part.
+ */
+int
+decode(const char *n, int *state, fpblock *fp, int isexp, int ix)
+{
+ const struct t_val *val;
+ int sign;
+
+
+ sign = (*n == '+' || *n == '-') ? *n++ : 0;
+ val = mapname(n);
+
+ fp->f.a[ix].bits = val->v_fval;
+ fp->d.a[ix].bits = val->v_dval;
+ fp->l.a[ix].bits = val->v_lval;
+
+ /* Reject values not allowed as arguments */
+ if (isexp == 0) {
+ switch (val->v_val) {
+ case T_FIN:
+ *state = S_MULT | S_COUNT |
+ ((sign == '+') ? S_POS : 0) |
+ ((sign == '-') ? S_NEG : 0);
+ if (sign == '-') {
+ fp->f.a[ix].bits.sign = 1;
+ fp->d.a[ix].bits.sign = 1;
+ fp->l.a[ix].bits.sign = 1;
+ }
+ return (0);
+
+ case T_NAN:
+ *state = S_MASK; /*#### expand to more NaNs later */
+ return (0);
+
+ case T_ZERO:
+ case T_INF:
+ case T_ONE:
+ break;
+
+ default:
+ return (1);
+ }
+
+ switch (sign) {
+ case '-':
+ fp->f.a[ix].bits.sign = 1;
+ fp->d.a[ix].bits.sign = 1;
+ fp->l.a[ix].bits.sign = 1;
+ /* Fall thru */
+ case '+':
+ *state = S_MASK;
+ break;
+ default:
+ *state = S_NEG;
+ break;
+ }
+ return (0);
+ }
+
+ /* Process expected results */
+ switch (val->v_val) {
+ case T_FIN:
+ case T_ZERO:
+ case T_INF:
+ case T_ONE:
+ case T_3PI_4:
+ case T_PI:
+ case T_PI_2:
+ case T_PI_4:
+ *state = 0;
+ break;
+
+ case T_NAN:
+ *state = S_NAN;
+ return (0);
+
+ case T_COSX:
+ *state = S_SCOSX;
+ break;
+
+ case T_COSY:
+ *state = S_SCOSY;
+ break;
+
+ case T_SIN2X:
+ *state = S_SSIN2X;
+ break;
+
+ case T_SINX:
+ *state = S_SSINX;
+ break;
+
+ case T_SIN2Y:
+ *state = S_SSIN2Y;
+ break;
+
+ case T_SINY:
+ *state = S_SSINY;
+ break;
+
+ case T_OINV:
+ case T_DIV0:
+ case T_INV:
+ case T_UNK:
+ default:
+ return (1);
+ }
+
+ switch (sign) {
+ case '-':
+ fp->f.a[ix].bits.sign = 1;
+ fp->d.a[ix].bits.sign = 1;
+ fp->l.a[ix].bits.sign = 1;
+ break;
+
+ case '+':
+ break;
+
+ default:
+ *state |= S_NEG;
+ break;
+ }
+
+ return (0);
+}
+
+/*
+ * Verify the real or imaginary part (defined by "ix") of a return value
+ * (in "act") matches the expected value (in "exp") for an input value "arg"
+ * in the given state. check() needs to be called twice (with the results of
+ * each or'd together) to check a complex result. "act" is forced positive
+ * so that printing it with %e does not include a sign. The actual sign is
+ * returned as part of the return value.
+ *
+ * Returns a variety of information as a bit pattern:
+ * 00000007 - Value mismatch bits - L/D/F
+ * 00000070 - Sign (0 == -ve) of the real L/D/F actual results
+ * 00000700 - Sign (0 == -ve) of the imaginary L/D/F actual results
+ * 00077000 - Pairs of bits (LLDDFF) indicating sign to be printed for the expected real result
+ * 07700000 - Pairs of bits (LLDDFF) indicating sign to be printed for the expected imaginary result
+ * For the latter two, bitpairs are an index into thu string "??+-"
+ */
+int
+check(const fpblock *arg, int ix, fpblock *act, const fpblock *exx, int state)
+{
+ int sf, sd, sl;
+ int asign, xsign;
+
+ asign = (act->f.a[ix].bits.sign << 3) |
+ (act->d.a[ix].bits.sign << 4) |
+ (act->l.a[ix].bits.sign << 5);
+ if (ix)
+ asign <<= 3;
+
+ /* Special case NaN */
+ if (state == S_NAN) {
+ return ((isnan(act->f.a[ix].f) ? 0 : 1) |
+ (isnan(act->d.a[ix].f) ? 0 : 2) |
+ (isnan(act->l.a[ix].f) ? 0 : 4) |
+ asign);
+ }
+
+ switch (state & S_MASK) {
+ default:
+ sf = sd = sl = 0;
+ break;
+
+ case S_SSIN2X:
+ sf = signbit(sinf(arg->f.a[0].f * 2.0f));
+ sd = signbit(sin(arg->d.a[0].f * 2.0));
+ sl = signbit(sinl(arg->l.a[0].f * 2.0l));
+ break;
+
+ case S_SSINX:
+ sf = signbit(sinf(arg->f.a[0].f));
+ sd = signbit(sin(arg->d.a[0].f));
+ sl = signbit(sinl(arg->l.a[0].f));
+ break;
+
+ case S_SSIN2Y:
+ sf = signbit(sinf(arg->f.a[1].f * 2.0f));
+ sd = signbit(sin(arg->d.a[1].f * 2.0));
+ sl = signbit(sinl(arg->l.a[1].f * 2.0l));
+ break;
+
+ case S_SSINY:
+ sf = signbit(sinf(arg->f.a[1].f));
+ sd = signbit(sin(arg->d.a[1].f));
+ sl = signbit(sinl(arg->l.a[1].f));
+ break;
+
+ case S_SCOSX:
+ sf = signbit(cosf(arg->f.a[0].f));
+ sd = signbit(cos(arg->d.a[0].f));
+ sl = signbit(cosl(arg->l.a[0].f));
+ break;
+
+ case S_SCOSY:
+ sf = signbit(cosf(arg->f.a[1].f));
+ sd = signbit(cos(arg->d.a[1].f));
+ sl = signbit(cosl(arg->l.a[1].f));
+ break;
+ }
+
+ /* Ignore sign bit if we don't care */
+ if (state & S_NEG) {
+ act->f.a[ix].bits.sign = 0;
+ act->d.a[ix].bits.sign = 0;
+ act->l.a[ix].bits.sign = 0;
+ xsign = 0;
+ } else {
+ /*
+ * s{f,d,l} indicates whether the signbit in the expected value should be
+ * inverted before comparison. To avoid altering it, flip the "actual"
+ * bit instead. The original signs are safely stored in asign.
+ */
+ if (sf)
+ act->f.a[ix].bits.sign = ~act->f.a[ix].bits.sign;
+ if (sd)
+ act->d.a[ix].bits.sign = ~act->d.a[ix].bits.sign;
+ if (sl)
+ act->l.a[ix].bits.sign = ~act->l.a[ix].bits.sign;
+
+ /* Calculate the sign to be displayed for the expected result */
+ xsign = 00052000 |
+ ((!!sf ^ exx->f.a[ix].bits.sign) << 9) |
+ ((!!sd ^ exx->d.a[ix].bits.sign) << 11) |
+ ((!!sl ^ exx->l.a[ix].bits.sign) << 13);
+ if (ix)
+ xsign <<= 6;
+ }
*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
More information about the svn-src-user
mailing list