[libc] Provide Arm Optimized Routines for the LLVM libc project.
authorKristof Beyls <kristof.beyls@arm.com>
Mon, 16 Mar 2020 19:00:15 +0000 (12:00 -0700)
committerSiva Chandra Reddy <sivachandra@google.com>
Mon, 16 Mar 2020 19:19:31 +0000 (12:19 -0700)
This adds the Arm Optimized Routines (see
https://github.com/ARM-software/optimized-routines) source code under the
the LLVM license. The version of the code provided in this patch is v20.02
of the Arm Optimized Routines project.

This entire contribution is being committed as is even though it does
not currently fit the LLVM libc model and does not follow the LLVM
coding style. In the near future, implementations from this patch will be
moved over to their right place in the LLVM-libc tree. This will be done
over many small patches, all of which will go through the normal LLVM code
review process. See this libc-dev post for the plan:
http://lists.llvm.org/pipermail/libc-dev/2020-March/000044.html

Differential revision of the original upload: https://reviews.llvm.org/D75355

180 files changed:
libc/AOR_v20.02/Makefile [new file with mode: 0644]
libc/AOR_v20.02/config.mk.dist [new file with mode: 0644]
libc/AOR_v20.02/math/Dir.mk [new file with mode: 0644]
libc/AOR_v20.02/math/cosf.c [new file with mode: 0644]
libc/AOR_v20.02/math/exp.c [new file with mode: 0644]
libc/AOR_v20.02/math/exp2.c [new file with mode: 0644]
libc/AOR_v20.02/math/exp2f.c [new file with mode: 0644]
libc/AOR_v20.02/math/exp2f_data.c [new file with mode: 0644]
libc/AOR_v20.02/math/exp_data.c [new file with mode: 0644]
libc/AOR_v20.02/math/expf.c [new file with mode: 0644]
libc/AOR_v20.02/math/include/mathlib.h [new file with mode: 0644]
libc/AOR_v20.02/math/log.c [new file with mode: 0644]
libc/AOR_v20.02/math/log2.c [new file with mode: 0644]
libc/AOR_v20.02/math/log2_data.c [new file with mode: 0644]
libc/AOR_v20.02/math/log2f.c [new file with mode: 0644]
libc/AOR_v20.02/math/log2f_data.c [new file with mode: 0644]
libc/AOR_v20.02/math/log_data.c [new file with mode: 0644]
libc/AOR_v20.02/math/logf.c [new file with mode: 0644]
libc/AOR_v20.02/math/logf_data.c [new file with mode: 0644]
libc/AOR_v20.02/math/math_config.h [new file with mode: 0644]
libc/AOR_v20.02/math/math_err.c [new file with mode: 0644]
libc/AOR_v20.02/math/math_errf.c [new file with mode: 0644]
libc/AOR_v20.02/math/pow.c [new file with mode: 0644]
libc/AOR_v20.02/math/pow_log_data.c [new file with mode: 0644]
libc/AOR_v20.02/math/powf.c [new file with mode: 0644]
libc/AOR_v20.02/math/powf_log2_data.c [new file with mode: 0644]
libc/AOR_v20.02/math/s_cos.c [new file with mode: 0644]
libc/AOR_v20.02/math/s_cosf.c [new file with mode: 0644]
libc/AOR_v20.02/math/s_exp.c [new file with mode: 0644]
libc/AOR_v20.02/math/s_exp2f.c [new file with mode: 0644]
libc/AOR_v20.02/math/s_exp2f_1u.c [new file with mode: 0644]
libc/AOR_v20.02/math/s_expf.c [new file with mode: 0644]
libc/AOR_v20.02/math/s_expf_1u.c [new file with mode: 0644]
libc/AOR_v20.02/math/s_log.c [new file with mode: 0644]
libc/AOR_v20.02/math/s_logf.c [new file with mode: 0644]
libc/AOR_v20.02/math/s_pow.c [new file with mode: 0644]
libc/AOR_v20.02/math/s_powf.c [new file with mode: 0644]
libc/AOR_v20.02/math/s_sin.c [new file with mode: 0644]
libc/AOR_v20.02/math/s_sinf.c [new file with mode: 0644]
libc/AOR_v20.02/math/sincosf.c [new file with mode: 0644]
libc/AOR_v20.02/math/sincosf.h [new file with mode: 0644]
libc/AOR_v20.02/math/sincosf_data.c [new file with mode: 0644]
libc/AOR_v20.02/math/sinf.c [new file with mode: 0644]
libc/AOR_v20.02/math/test/mathbench.c [new file with mode: 0644]
libc/AOR_v20.02/math/test/mathtest.c [new file with mode: 0644]
libc/AOR_v20.02/math/test/rtest/dotest.c [new file with mode: 0644]
libc/AOR_v20.02/math/test/rtest/intern.h [new file with mode: 0644]
libc/AOR_v20.02/math/test/rtest/main.c [new file with mode: 0644]
libc/AOR_v20.02/math/test/rtest/random.c [new file with mode: 0644]
libc/AOR_v20.02/math/test/rtest/random.h [new file with mode: 0644]
libc/AOR_v20.02/math/test/rtest/semi.c [new file with mode: 0644]
libc/AOR_v20.02/math/test/rtest/semi.h [new file with mode: 0644]
libc/AOR_v20.02/math/test/rtest/types.h [new file with mode: 0644]
libc/AOR_v20.02/math/test/rtest/wrappers.c [new file with mode: 0644]
libc/AOR_v20.02/math/test/rtest/wrappers.h [new file with mode: 0644]
libc/AOR_v20.02/math/test/runulp.sh [new file with mode: 0755]
libc/AOR_v20.02/math/test/testcases/directed/cosf.tst [new file with mode: 0644]
libc/AOR_v20.02/math/test/testcases/directed/exp.tst [new file with mode: 0644]
libc/AOR_v20.02/math/test/testcases/directed/exp2.tst [new file with mode: 0644]
libc/AOR_v20.02/math/test/testcases/directed/exp2f.tst [new file with mode: 0644]
libc/AOR_v20.02/math/test/testcases/directed/expf.tst [new file with mode: 0644]
libc/AOR_v20.02/math/test/testcases/directed/log.tst [new file with mode: 0644]
libc/AOR_v20.02/math/test/testcases/directed/log2.tst [new file with mode: 0644]
libc/AOR_v20.02/math/test/testcases/directed/log2f.tst [new file with mode: 0644]
libc/AOR_v20.02/math/test/testcases/directed/logf.tst [new file with mode: 0644]
libc/AOR_v20.02/math/test/testcases/directed/pow.tst [new file with mode: 0644]
libc/AOR_v20.02/math/test/testcases/directed/powf.tst [new file with mode: 0644]
libc/AOR_v20.02/math/test/testcases/directed/sincosf.tst [new file with mode: 0644]
libc/AOR_v20.02/math/test/testcases/directed/sinf.tst [new file with mode: 0644]
libc/AOR_v20.02/math/test/testcases/random/double.tst [new file with mode: 0644]
libc/AOR_v20.02/math/test/testcases/random/float.tst [new file with mode: 0644]
libc/AOR_v20.02/math/test/traces/exp.txt [new file with mode: 0644]
libc/AOR_v20.02/math/test/traces/sincosf.txt [new file with mode: 0644]
libc/AOR_v20.02/math/test/ulp.c [new file with mode: 0644]
libc/AOR_v20.02/math/test/ulp.h [new file with mode: 0644]
libc/AOR_v20.02/math/tools/cos.sollya [new file with mode: 0644]
libc/AOR_v20.02/math/tools/exp.sollya [new file with mode: 0644]
libc/AOR_v20.02/math/tools/exp2.sollya [new file with mode: 0644]
libc/AOR_v20.02/math/tools/log.sollya [new file with mode: 0644]
libc/AOR_v20.02/math/tools/log2.sollya [new file with mode: 0644]
libc/AOR_v20.02/math/tools/log2_abs.sollya [new file with mode: 0644]
libc/AOR_v20.02/math/tools/log_abs.sollya [new file with mode: 0644]
libc/AOR_v20.02/math/tools/plot.py [new file with mode: 0755]
libc/AOR_v20.02/math/tools/remez.jl [new file with mode: 0755]
libc/AOR_v20.02/math/tools/sin.sollya [new file with mode: 0644]
libc/AOR_v20.02/math/tools/v_exp.sollya [new file with mode: 0644]
libc/AOR_v20.02/math/tools/v_log.sollya [new file with mode: 0644]
libc/AOR_v20.02/math/tools/v_sin.sollya [new file with mode: 0644]
libc/AOR_v20.02/math/v_cos.c [new file with mode: 0644]
libc/AOR_v20.02/math/v_cosf.c [new file with mode: 0644]
libc/AOR_v20.02/math/v_exp.c [new file with mode: 0644]
libc/AOR_v20.02/math/v_exp.h [new file with mode: 0644]
libc/AOR_v20.02/math/v_exp2f.c [new file with mode: 0644]
libc/AOR_v20.02/math/v_exp2f_1u.c [new file with mode: 0644]
libc/AOR_v20.02/math/v_exp_data.c [new file with mode: 0644]
libc/AOR_v20.02/math/v_expf.c [new file with mode: 0644]
libc/AOR_v20.02/math/v_expf_1u.c [new file with mode: 0644]
libc/AOR_v20.02/math/v_log.c [new file with mode: 0644]
libc/AOR_v20.02/math/v_log.h [new file with mode: 0644]
libc/AOR_v20.02/math/v_log_data.c [new file with mode: 0644]
libc/AOR_v20.02/math/v_logf.c [new file with mode: 0644]
libc/AOR_v20.02/math/v_math.h [new file with mode: 0644]
libc/AOR_v20.02/math/v_pow.c [new file with mode: 0644]
libc/AOR_v20.02/math/v_powf.c [new file with mode: 0644]
libc/AOR_v20.02/math/v_sin.c [new file with mode: 0644]
libc/AOR_v20.02/math/v_sinf.c [new file with mode: 0644]
libc/AOR_v20.02/math/vn_cos.c [new file with mode: 0644]
libc/AOR_v20.02/math/vn_cosf.c [new file with mode: 0644]
libc/AOR_v20.02/math/vn_exp.c [new file with mode: 0644]
libc/AOR_v20.02/math/vn_exp2f.c [new file with mode: 0644]
libc/AOR_v20.02/math/vn_exp2f_1u.c [new file with mode: 0644]
libc/AOR_v20.02/math/vn_expf.c [new file with mode: 0644]
libc/AOR_v20.02/math/vn_expf_1u.c [new file with mode: 0644]
libc/AOR_v20.02/math/vn_log.c [new file with mode: 0644]
libc/AOR_v20.02/math/vn_logf.c [new file with mode: 0644]
libc/AOR_v20.02/math/vn_pow.c [new file with mode: 0644]
libc/AOR_v20.02/math/vn_powf.c [new file with mode: 0644]
libc/AOR_v20.02/math/vn_sin.c [new file with mode: 0644]
libc/AOR_v20.02/math/vn_sinf.c [new file with mode: 0644]
libc/AOR_v20.02/networking/Dir.mk [new file with mode: 0644]
libc/AOR_v20.02/networking/aarch64/chksum_simd.c [new file with mode: 0644]
libc/AOR_v20.02/networking/arm/chksum_simd.c [new file with mode: 0644]
libc/AOR_v20.02/networking/chksum.c [new file with mode: 0644]
libc/AOR_v20.02/networking/chksum_common.h [new file with mode: 0644]
libc/AOR_v20.02/networking/include/networking.h [new file with mode: 0644]
libc/AOR_v20.02/networking/test/chksum.c [new file with mode: 0644]
libc/AOR_v20.02/string/Dir.mk [new file with mode: 0644]
libc/AOR_v20.02/string/aarch64/check-arch.S [new file with mode: 0644]
libc/AOR_v20.02/string/aarch64/memchr-sve.S [new file with mode: 0644]
libc/AOR_v20.02/string/aarch64/memchr.S [new file with mode: 0644]
libc/AOR_v20.02/string/aarch64/memcmp-sve.S [new file with mode: 0644]
libc/AOR_v20.02/string/aarch64/memcmp.S [new file with mode: 0644]
libc/AOR_v20.02/string/aarch64/memcpy-advsimd.S [new file with mode: 0644]
libc/AOR_v20.02/string/aarch64/memcpy.S [new file with mode: 0644]
libc/AOR_v20.02/string/aarch64/memset.S [new file with mode: 0644]
libc/AOR_v20.02/string/aarch64/stpcpy-sve.S [new file with mode: 0644]
libc/AOR_v20.02/string/aarch64/stpcpy.S [new file with mode: 0644]
libc/AOR_v20.02/string/aarch64/strchr-mte.S [new file with mode: 0644]
libc/AOR_v20.02/string/aarch64/strchr-sve.S [new file with mode: 0644]
libc/AOR_v20.02/string/aarch64/strchr.S [new file with mode: 0644]
libc/AOR_v20.02/string/aarch64/strchrnul-sve.S [new file with mode: 0644]
libc/AOR_v20.02/string/aarch64/strchrnul.S [new file with mode: 0644]
libc/AOR_v20.02/string/aarch64/strcmp-sve.S [new file with mode: 0644]
libc/AOR_v20.02/string/aarch64/strcmp.S [new file with mode: 0644]
libc/AOR_v20.02/string/aarch64/strcpy-sve.S [new file with mode: 0644]
libc/AOR_v20.02/string/aarch64/strcpy.S [new file with mode: 0644]
libc/AOR_v20.02/string/aarch64/strlen-mte.S [new file with mode: 0644]
libc/AOR_v20.02/string/aarch64/strlen-sve.S [new file with mode: 0644]
libc/AOR_v20.02/string/aarch64/strlen.S [new file with mode: 0644]
libc/AOR_v20.02/string/aarch64/strncmp-sve.S [new file with mode: 0644]
libc/AOR_v20.02/string/aarch64/strncmp.S [new file with mode: 0644]
libc/AOR_v20.02/string/aarch64/strnlen-sve.S [new file with mode: 0644]
libc/AOR_v20.02/string/aarch64/strnlen.S [new file with mode: 0644]
libc/AOR_v20.02/string/aarch64/strrchr-sve.S [new file with mode: 0644]
libc/AOR_v20.02/string/aarch64/strrchr.S [new file with mode: 0644]
libc/AOR_v20.02/string/arm/check-arch.S [new file with mode: 0644]
libc/AOR_v20.02/string/arm/memchr.S [new file with mode: 0644]
libc/AOR_v20.02/string/arm/memcpy.S [new file with mode: 0644]
libc/AOR_v20.02/string/arm/memset.S [new file with mode: 0644]
libc/AOR_v20.02/string/arm/strcmp-armv6m.S [new file with mode: 0644]
libc/AOR_v20.02/string/arm/strcmp.S [new file with mode: 0644]
libc/AOR_v20.02/string/arm/strcpy.c [new file with mode: 0644]
libc/AOR_v20.02/string/arm/strlen-armv6t2.S [new file with mode: 0644]
libc/AOR_v20.02/string/asmdefs.h [new file with mode: 0644]
libc/AOR_v20.02/string/include/stringlib.h [new file with mode: 0644]
libc/AOR_v20.02/string/test/memchr.c [new file with mode: 0644]
libc/AOR_v20.02/string/test/memcmp.c [new file with mode: 0644]
libc/AOR_v20.02/string/test/memcpy.c [new file with mode: 0644]
libc/AOR_v20.02/string/test/memmove.c [new file with mode: 0644]
libc/AOR_v20.02/string/test/memset.c [new file with mode: 0644]
libc/AOR_v20.02/string/test/stpcpy.c [new file with mode: 0644]
libc/AOR_v20.02/string/test/strchr.c [new file with mode: 0644]
libc/AOR_v20.02/string/test/strchrnul.c [new file with mode: 0644]
libc/AOR_v20.02/string/test/strcmp.c [new file with mode: 0644]
libc/AOR_v20.02/string/test/strcpy.c [new file with mode: 0644]
libc/AOR_v20.02/string/test/strlen.c [new file with mode: 0644]
libc/AOR_v20.02/string/test/strncmp.c [new file with mode: 0644]
libc/AOR_v20.02/string/test/strnlen.c [new file with mode: 0644]
libc/AOR_v20.02/string/test/strrchr.c [new file with mode: 0644]
libc/AOR_v20.02/string/x86_64/check-arch.S [new file with mode: 0644]

diff --git a/libc/AOR_v20.02/Makefile b/libc/AOR_v20.02/Makefile
new file mode 100644 (file)
index 0000000..53e0245
--- /dev/null
@@ -0,0 +1,90 @@
+# Makefile - requires GNU make
+#
+# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+# See https://llvm.org/LICENSE.txt for license information.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+srcdir = .
+prefix = /usr
+bindir = $(prefix)/bin
+libdir = $(prefix)/lib
+includedir = $(prefix)/include
+
+# Configure these in config.mk, do not make changes in this file.
+SUBS = math string networking
+HOST_CC = cc
+HOST_CFLAGS = -std=c99 -O2
+HOST_LDFLAGS =
+HOST_LDLIBS =
+EMULATOR =
+CPPFLAGS =
+CFLAGS = -std=c99 -O2
+CFLAGS_SHARED = -fPIC
+CFLAGS_ALL = -Ibuild/include $(CPPFLAGS) $(CFLAGS)
+LDFLAGS =
+LDLIBS =
+AR = $(CROSS_COMPILE)ar
+RANLIB = $(CROSS_COMPILE)ranlib
+INSTALL = install
+
+all:
+
+-include config.mk
+
+$(foreach sub,$(SUBS),$(eval include $(srcdir)/$(sub)/Dir.mk))
+
+# Required targets of subproject foo:
+#   all-foo
+#   check-foo
+#   clean-foo
+#   install-foo
+# Required make variables of subproject foo:
+#   foo-files: Built files (all in build/).
+# Make variables used by subproject foo:
+#   foo-...: Variables defined in foo/Dir.mk or by config.mk.
+
+all: $(SUBS:%=all-%)
+
+ALL_FILES = $(foreach sub,$(SUBS),$($(sub)-files))
+DIRS = $(sort $(patsubst %/,%,$(dir $(ALL_FILES))))
+$(ALL_FILES): | $(DIRS)
+$(DIRS):
+       mkdir -p $@
+
+$(filter %.os,$(ALL_FILES)): CFLAGS_ALL += $(CFLAGS_SHARED)
+
+build/%.o: $(srcdir)/%.S
+       $(CC) $(CFLAGS_ALL) -c -o $@ $<
+
+build/%.o: $(srcdir)/%.c
+       $(CC) $(CFLAGS_ALL) -c -o $@ $<
+
+build/%.os: $(srcdir)/%.S
+       $(CC) $(CFLAGS_ALL) -c -o $@ $<
+
+build/%.os: $(srcdir)/%.c
+       $(CC) $(CFLAGS_ALL) -c -o $@ $<
+
+clean: $(SUBS:%=clean-%)
+       rm -rf build
+
+distclean: clean
+       rm -f config.mk
+
+$(DESTDIR)$(bindir)/%: build/bin/%
+       $(INSTALL) -D $< $@
+
+$(DESTDIR)$(libdir)/%.so: build/lib/%.so
+       $(INSTALL) -D $< $@
+
+$(DESTDIR)$(libdir)/%: build/lib/%
+       $(INSTALL) -m 644 -D $< $@
+
+$(DESTDIR)$(includedir)/%: build/include/%
+       $(INSTALL) -m 644 -D $< $@
+
+install: $(SUBS:%=install-%)
+
+check: $(SUBS:%=check-%)
+
+.PHONY: all clean distclean install check
diff --git a/libc/AOR_v20.02/config.mk.dist b/libc/AOR_v20.02/config.mk.dist
new file mode 100644 (file)
index 0000000..240d4b6
--- /dev/null
@@ -0,0 +1,68 @@
+# Example config.mk
+#
+# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+# See https://llvm.org/LICENSE.txt for license information.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+# Subprojects to build
+SUBS = math string networking
+
+# Target architecture: aarch64, arm or x86_64
+ARCH = aarch64
+
+# Compiler for the target
+CC = $(CROSS_COMPILE)gcc
+CFLAGS = -std=c99 -pipe -O3
+CFLAGS += -Wall -Wno-missing-braces
+CFLAGS += -Werror=implicit-function-declaration
+
+# Used for test case generator that is executed on the host
+HOST_CC = gcc
+HOST_CFLAGS = -std=c99 -O2
+HOST_CFLAGS += -Wall -Wno-unused-function
+
+# Enable debug info.
+HOST_CFLAGS += -g
+CFLAGS += -g
+
+# Optimize the shared libraries on aarch64 assuming they fit in 1M.
+#CFLAGS_SHARED = -fPIC -mcmodel=tiny
+
+# Use for cross compilation with gcc.
+#CROSS_COMPILE = aarch64-none-linux-gnu-
+
+# Use with cross testing.
+#EMULATOR = qemu-aarch64-static
+#EMULATOR = sh -c 'scp $$1 user@host:/dir && ssh user@host /dir/"$$@"' --
+
+# Additional flags for subprojects.
+math-cflags =
+math-ldlibs =
+math-ulpflags =
+math-testflags =
+string-cflags =
+networking-cflags =
+
+# Use if mpfr is available on the target for ulp error checking.
+#math-ldlibs += -lmpfr -lgmp
+#math-cflags += -DUSE_MPFR
+
+# Use with gcc.
+math-cflags += -frounding-math -fexcess-precision=standard -fno-stack-protector
+math-cflags += -ffp-contract=fast -fno-math-errno
+
+# Use with clang.
+#math-cflags += -ffp-contract=fast
+
+# Disable vector math code
+#math-cflags += -DWANT_VMATH=0
+
+# Disable fenv checks
+#math-ulpflags = -q -f
+#math-testflags = -nostatus
+
+# Enable assertion checks.
+#networking-cflags += -DWANT_ASSERT
+
+# Avoid auto-vectorization of scalar code and unroll loops
+networking-cflags += -O2 -fno-tree-vectorize -funroll-loops
diff --git a/libc/AOR_v20.02/math/Dir.mk b/libc/AOR_v20.02/math/Dir.mk
new file mode 100644 (file)
index 0000000..6be9115
--- /dev/null
@@ -0,0 +1,111 @@
+# Makefile fragment - requires GNU make
+#
+# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+# See https://llvm.org/LICENSE.txt for license information.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+S := $(srcdir)/math
+B := build/math
+
+math-lib-srcs := $(wildcard $(S)/*.[cS])
+math-test-srcs := \
+       $(S)/test/mathtest.c \
+       $(S)/test/mathbench.c \
+       $(S)/test/ulp.c \
+
+math-test-host-srcs := $(wildcard $(S)/test/rtest/*.[cS])
+
+math-includes := $(patsubst $(S)/%,build/%,$(wildcard $(S)/include/*.h))
+
+math-libs := \
+       build/lib/libmathlib.so \
+       build/lib/libmathlib.a \
+
+math-tools := \
+       build/bin/mathtest \
+       build/bin/mathbench \
+       build/bin/mathbench_libc \
+       build/bin/runulp.sh \
+       build/bin/ulp \
+
+math-host-tools := \
+       build/bin/rtest \
+
+math-lib-objs := $(patsubst $(S)/%,$(B)/%.o,$(basename $(math-lib-srcs)))
+math-test-objs := $(patsubst $(S)/%,$(B)/%.o,$(basename $(math-test-srcs)))
+math-host-objs := $(patsubst $(S)/%,$(B)/%.o,$(basename $(math-test-host-srcs)))
+math-target-objs := $(math-lib-objs) $(math-test-objs)
+math-objs := $(math-target-objs) $(math-target-objs:%.o=%.os) $(math-host-objs)
+
+math-files := \
+       $(math-objs) \
+       $(math-libs) \
+       $(math-tools) \
+       $(math-host-tools) \
+       $(math-includes) \
+
+all-math: $(math-libs) $(math-tools) $(math-includes)
+
+$(math-objs): $(math-includes)
+$(math-objs): CFLAGS_ALL += $(math-cflags)
+$(B)/test/mathtest.o: CFLAGS_ALL += -fmath-errno
+$(math-host-objs): CC = $(HOST_CC)
+$(math-host-objs): CFLAGS_ALL = $(HOST_CFLAGS)
+
+$(B)/test/ulp.o: $(S)/test/ulp.h
+
+build/lib/libmathlib.so: $(math-lib-objs:%.o=%.os)
+       $(CC) $(CFLAGS_ALL) $(LDFLAGS) -shared -o $@ $^
+
+build/lib/libmathlib.a: $(math-lib-objs)
+       rm -f $@
+       $(AR) rc $@ $^
+       $(RANLIB) $@
+
+$(math-host-tools): HOST_LDLIBS += -lm -lmpfr -lmpc
+$(math-tools): LDLIBS += $(math-ldlibs) -lm
+
+build/bin/rtest: $(math-host-objs)
+       $(HOST_CC) $(HOST_CFLAGS) $(HOST_LDFLAGS) -o $@ $^ $(HOST_LDLIBS)
+
+build/bin/mathtest: $(B)/test/mathtest.o build/lib/libmathlib.a
+       $(CC) $(CFLAGS_ALL) $(LDFLAGS) -static -o $@ $^ $(LDLIBS)
+
+build/bin/mathbench: $(B)/test/mathbench.o build/lib/libmathlib.a
+       $(CC) $(CFLAGS_ALL) $(LDFLAGS) -static -o $@ $^ $(LDLIBS)
+
+# This is not ideal, but allows custom symbols in mathbench to get resolved.
+build/bin/mathbench_libc: $(B)/test/mathbench.o build/lib/libmathlib.a
+       $(CC) $(CFLAGS_ALL) $(LDFLAGS) -static -o $@ $< $(LDLIBS) -lc build/lib/libmathlib.a -lm
+
+build/bin/ulp: $(B)/test/ulp.o build/lib/libmathlib.a
+       $(CC) $(CFLAGS_ALL) $(LDFLAGS) -static -o $@ $^ $(LDLIBS)
+
+build/include/%.h: $(S)/include/%.h
+       cp $< $@
+
+build/bin/%.sh: $(S)/test/%.sh
+       cp $< $@
+
+math-tests := $(wildcard $(S)/test/testcases/directed/*.tst)
+math-rtests := $(wildcard $(S)/test/testcases/random/*.tst)
+
+check-math-test: $(math-tools)
+       cat $(math-tests) | $(EMULATOR) build/bin/mathtest $(math-testflags)
+
+check-math-rtest: $(math-host-tools) $(math-tools)
+       cat $(math-rtests) | build/bin/rtest | $(EMULATOR) build/bin/mathtest $(math-testflags)
+
+check-math-ulp: $(math-tools)
+       ULPFLAGS="$(math-ulpflags)" build/bin/runulp.sh $(EMULATOR)
+
+check-math: check-math-test check-math-rtest check-math-ulp
+
+install-math: \
+ $(math-libs:build/lib/%=$(DESTDIR)$(libdir)/%) \
+ $(math-includes:build/include/%=$(DESTDIR)$(includedir)/%)
+
+clean-math:
+       rm -f $(math-files)
+
+.PHONY: all-math check-math-test check-math-rtest check-math-ulp check-math install-math clean-math
diff --git a/libc/AOR_v20.02/math/cosf.c b/libc/AOR_v20.02/math/cosf.c
new file mode 100644 (file)
index 0000000..1ab98a1
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ * Single-precision cos function.
+ *
+ * Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+ * See https://llvm.org/LICENSE.txt for license information.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include <stdint.h>
+#include <math.h>
+#include "math_config.h"
+#include "sincosf.h"
+
+/* Fast cosf implementation.  Worst-case ULP is 0.5607, maximum relative
+   error is 0.5303 * 2^-23.  A single-step range reduction is used for
+   small values.  Large inputs have their range reduced using fast integer
+   arithmetic.  */
+float
+cosf (float y)
+{
+  double x = y;
+  double s;
+  int n;
+  const sincos_t *p = &__sincosf_table[0];
+
+  if (abstop12 (y) < abstop12 (pio4))
+    {
+      double x2 = x * x;
+
+      if (unlikely (abstop12 (y) < abstop12 (0x1p-12f)))
+       return 1.0f;
+
+      return sinf_poly (x, x2, p, 1);
+    }
+  else if (likely (abstop12 (y) < abstop12 (120.0f)))
+    {
+      x = reduce_fast (x, p, &n);
+
+      /* Setup the signs for sin and cos.  */
+      s = p->sign[n & 3];
+
+      if (n & 2)
+       p = &__sincosf_table[1];
+
+      return sinf_poly (x * s, x * x, p, n ^ 1);
+    }
+  else if (abstop12 (y) < abstop12 (INFINITY))
+    {
+      uint32_t xi = asuint (y);
+      int sign = xi >> 31;
+
+      x = reduce_large (xi, &n);
+
+      /* Setup signs for sin and cos - include original sign.  */
+      s = p->sign[(n + sign) & 3];
+
+      if ((n + sign) & 2)
+       p = &__sincosf_table[1];
+
+      return sinf_poly (x * s, x * x, p, n ^ 1);
+    }
+  else
+    return __math_invalidf (y);
+}
diff --git a/libc/AOR_v20.02/math/exp.c b/libc/AOR_v20.02/math/exp.c
new file mode 100644 (file)
index 0000000..d099602
--- /dev/null
@@ -0,0 +1,177 @@
+/*
+ * Double-precision e^x function.
+ *
+ * Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+ * See https://llvm.org/LICENSE.txt for license information.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include <float.h>
+#include <math.h>
+#include <stdint.h>
+#include "math_config.h"
+
+#define N (1 << EXP_TABLE_BITS)
+#define InvLn2N __exp_data.invln2N
+#define NegLn2hiN __exp_data.negln2hiN
+#define NegLn2loN __exp_data.negln2loN
+#define Shift __exp_data.shift
+#define T __exp_data.tab
+#define C2 __exp_data.poly[5 - EXP_POLY_ORDER]
+#define C3 __exp_data.poly[6 - EXP_POLY_ORDER]
+#define C4 __exp_data.poly[7 - EXP_POLY_ORDER]
+#define C5 __exp_data.poly[8 - EXP_POLY_ORDER]
+#define C6 __exp_data.poly[9 - EXP_POLY_ORDER]
+
+/* Handle cases that may overflow or underflow when computing the result that
+   is scale*(1+TMP) without intermediate rounding.  The bit representation of
+   scale is in SBITS, however it has a computed exponent that may have
+   overflown into the sign bit so that needs to be adjusted before using it as
+   a double.  (int32_t)KI is the k used in the argument reduction and exponent
+   adjustment of scale, positive k here means the result may overflow and
+   negative k means the result may underflow.  */
+static inline double
+specialcase (double_t tmp, uint64_t sbits, uint64_t ki)
+{
+  double_t scale, y;
+
+  if ((ki & 0x80000000) == 0)
+    {
+      /* k > 0, the exponent of scale might have overflowed by <= 460.  */
+      sbits -= 1009ull << 52;
+      scale = asdouble (sbits);
+      y = 0x1p1009 * (scale + scale * tmp);
+      return check_oflow (eval_as_double (y));
+    }
+  /* k < 0, need special care in the subnormal range.  */
+  sbits += 1022ull << 52;
+  scale = asdouble (sbits);
+  y = scale + scale * tmp;
+  if (y < 1.0)
+    {
+      /* Round y to the right precision before scaling it into the subnormal
+        range to avoid double rounding that can cause 0.5+E/2 ulp error where
+        E is the worst-case ulp error outside the subnormal range.  So this
+        is only useful if the goal is better than 1 ulp worst-case error.  */
+      double_t hi, lo;
+      lo = scale - y + scale * tmp;
+      hi = 1.0 + y;
+      lo = 1.0 - hi + y + lo;
+      y = eval_as_double (hi + lo) - 1.0;
+      /* Avoid -0.0 with downward rounding.  */
+      if (WANT_ROUNDING && y == 0.0)
+       y = 0.0;
+      /* The underflow exception needs to be signaled explicitly.  */
+      force_eval_double (opt_barrier_double (0x1p-1022) * 0x1p-1022);
+    }
+  y = 0x1p-1022 * y;
+  return check_uflow (eval_as_double (y));
+}
+
+/* Top 12 bits of a double (sign and exponent bits).  */
+static inline uint32_t
+top12 (double x)
+{
+  return asuint64 (x) >> 52;
+}
+
+/* Computes exp(x+xtail) where |xtail| < 2^-8/N and |xtail| <= |x|.
+   If hastail is 0 then xtail is assumed to be 0 too.  */
+static inline double
+exp_inline (double x, double xtail, int hastail)
+{
+  uint32_t abstop;
+  uint64_t ki, idx, top, sbits;
+  /* double_t for better performance on targets with FLT_EVAL_METHOD==2.  */
+  double_t kd, z, r, r2, scale, tail, tmp;
+
+  abstop = top12 (x) & 0x7ff;
+  if (unlikely (abstop - top12 (0x1p-54) >= top12 (512.0) - top12 (0x1p-54)))
+    {
+      if (abstop - top12 (0x1p-54) >= 0x80000000)
+       /* Avoid spurious underflow for tiny x.  */
+       /* Note: 0 is common input.  */
+       return WANT_ROUNDING ? 1.0 + x : 1.0;
+      if (abstop >= top12 (1024.0))
+       {
+         if (asuint64 (x) == asuint64 (-INFINITY))
+           return 0.0;
+         if (abstop >= top12 (INFINITY))
+           return 1.0 + x;
+         if (asuint64 (x) >> 63)
+           return __math_uflow (0);
+         else
+           return __math_oflow (0);
+       }
+      /* Large x is special cased below.  */
+      abstop = 0;
+    }
+
+  /* exp(x) = 2^(k/N) * exp(r), with exp(r) in [2^(-1/2N),2^(1/2N)].  */
+  /* x = ln2/N*k + r, with int k and r in [-ln2/2N, ln2/2N].  */
+  z = InvLn2N * x;
+#if TOINT_INTRINSICS
+  kd = roundtoint (z);
+  ki = converttoint (z);
+#elif EXP_USE_TOINT_NARROW
+  /* z - kd is in [-0.5-2^-16, 0.5] in all rounding modes.  */
+  kd = eval_as_double (z + Shift);
+  ki = asuint64 (kd) >> 16;
+  kd = (double_t) (int32_t) ki;
+#else
+  /* z - kd is in [-1, 1] in non-nearest rounding modes.  */
+  kd = eval_as_double (z + Shift);
+  ki = asuint64 (kd);
+  kd -= Shift;
+#endif
+  r = x + kd * NegLn2hiN + kd * NegLn2loN;
+  /* The code assumes 2^-200 < |xtail| < 2^-8/N.  */
+  if (hastail)
+    r += xtail;
+  /* 2^(k/N) ~= scale * (1 + tail).  */
+  idx = 2 * (ki % N);
+  top = ki << (52 - EXP_TABLE_BITS);
+  tail = asdouble (T[idx]);
+  /* This is only a valid scale when -1023*N < k < 1024*N.  */
+  sbits = T[idx + 1] + top;
+  /* exp(x) = 2^(k/N) * exp(r) ~= scale + scale * (tail + exp(r) - 1).  */
+  /* Evaluation is optimized assuming superscalar pipelined execution.  */
+  r2 = r * r;
+  /* Without fma the worst case error is 0.25/N ulp larger.  */
+  /* Worst case error is less than 0.5+1.11/N+(abs poly error * 2^53) ulp.  */
+#if EXP_POLY_ORDER == 4
+  tmp = tail + r + r2 * C2 + r * r2 * (C3 + r * C4);
+#elif EXP_POLY_ORDER == 5
+  tmp = tail + r + r2 * (C2 + r * C3) + r2 * r2 * (C4 + r * C5);
+#elif EXP_POLY_ORDER == 6
+  tmp = tail + r + r2 * (0.5 + r * C3) + r2 * r2 * (C4 + r * C5 + r2 * C6);
+#endif
+  if (unlikely (abstop == 0))
+    return specialcase (tmp, sbits, ki);
+  scale = asdouble (sbits);
+  /* Note: tmp == 0 or |tmp| > 2^-200 and scale > 2^-739, so there
+     is no spurious underflow here even without fma.  */
+  return eval_as_double (scale + scale * tmp);
+}
+
+double
+exp (double x)
+{
+  return exp_inline (x, 0, 0);
+}
+
+/* May be useful for implementing pow where more than double
+   precision input is needed.  */
+double
+__exp_dd (double x, double xtail)
+{
+  return exp_inline (x, xtail, 1);
+}
+#if USE_GLIBC_ABI
+strong_alias (exp, __exp_finite)
+hidden_alias (exp, __ieee754_exp)
+hidden_alias (__exp_dd, __exp1)
+# if LDBL_MANT_DIG == 53
+long double expl (long double x) { return exp (x); }
+# endif
+#endif
diff --git a/libc/AOR_v20.02/math/exp2.c b/libc/AOR_v20.02/math/exp2.c
new file mode 100644 (file)
index 0000000..53296ab
--- /dev/null
@@ -0,0 +1,144 @@
+/*
+ * Double-precision 2^x function.
+ *
+ * Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+ * See https://llvm.org/LICENSE.txt for license information.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include <float.h>
+#include <math.h>
+#include <stdint.h>
+#include "math_config.h"
+
+#define N (1 << EXP_TABLE_BITS)
+#define Shift __exp_data.exp2_shift
+#define T __exp_data.tab
+#define C1 __exp_data.exp2_poly[0]
+#define C2 __exp_data.exp2_poly[1]
+#define C3 __exp_data.exp2_poly[2]
+#define C4 __exp_data.exp2_poly[3]
+#define C5 __exp_data.exp2_poly[4]
+#define C6 __exp_data.exp2_poly[5]
+
+/* Handle cases that may overflow or underflow when computing the result that
+   is scale*(1+TMP) without intermediate rounding.  The bit representation of
+   scale is in SBITS, however it has a computed exponent that may have
+   overflown into the sign bit so that needs to be adjusted before using it as
+   a double.  (int32_t)KI is the k used in the argument reduction and exponent
+   adjustment of scale, positive k here means the result may overflow and
+   negative k means the result may underflow.  */
+static inline double
+specialcase (double_t tmp, uint64_t sbits, uint64_t ki)
+{
+  double_t scale, y;
+
+  if ((ki & 0x80000000) == 0)
+    {
+      /* k > 0, the exponent of scale might have overflowed by 1.  */
+      sbits -= 1ull << 52;
+      scale = asdouble (sbits);
+      y = 2 * (scale + scale * tmp);
+      return check_oflow (eval_as_double (y));
+    }
+  /* k < 0, need special care in the subnormal range.  */
+  sbits += 1022ull << 52;
+  scale = asdouble (sbits);
+  y = scale + scale * tmp;
+  if (y < 1.0)
+    {
+      /* Round y to the right precision before scaling it into the subnormal
+        range to avoid double rounding that can cause 0.5+E/2 ulp error where
+        E is the worst-case ulp error outside the subnormal range.  So this
+        is only useful if the goal is better than 1 ulp worst-case error.  */
+      double_t hi, lo;
+      lo = scale - y + scale * tmp;
+      hi = 1.0 + y;
+      lo = 1.0 - hi + y + lo;
+      y = eval_as_double (hi + lo) - 1.0;
+      /* Avoid -0.0 with downward rounding.  */
+      if (WANT_ROUNDING && y == 0.0)
+       y = 0.0;
+      /* The underflow exception needs to be signaled explicitly.  */
+      force_eval_double (opt_barrier_double (0x1p-1022) * 0x1p-1022);
+    }
+  y = 0x1p-1022 * y;
+  return check_uflow (eval_as_double (y));
+}
+
+/* Top 12 bits of a double (sign and exponent bits).  */
+static inline uint32_t
+top12 (double x)
+{
+  return asuint64 (x) >> 52;
+}
+
+double
+exp2 (double x)
+{
+  uint32_t abstop;
+  uint64_t ki, idx, top, sbits;
+  /* double_t for better performance on targets with FLT_EVAL_METHOD==2.  */
+  double_t kd, r, r2, scale, tail, tmp;
+
+  abstop = top12 (x) & 0x7ff;
+  if (unlikely (abstop - top12 (0x1p-54) >= top12 (512.0) - top12 (0x1p-54)))
+    {
+      if (abstop - top12 (0x1p-54) >= 0x80000000)
+       /* Avoid spurious underflow for tiny x.  */
+       /* Note: 0 is common input.  */
+       return WANT_ROUNDING ? 1.0 + x : 1.0;
+      if (abstop >= top12 (1024.0))
+       {
+         if (asuint64 (x) == asuint64 (-INFINITY))
+           return 0.0;
+         if (abstop >= top12 (INFINITY))
+           return 1.0 + x;
+         if (!(asuint64 (x) >> 63))
+           return __math_oflow (0);
+         else if (asuint64 (x) >= asuint64 (-1075.0))
+           return __math_uflow (0);
+       }
+      if (2 * asuint64 (x) > 2 * asuint64 (928.0))
+       /* Large x is special cased below.  */
+       abstop = 0;
+    }
+
+  /* exp2(x) = 2^(k/N) * 2^r, with 2^r in [2^(-1/2N),2^(1/2N)].  */
+  /* x = k/N + r, with int k and r in [-1/2N, 1/2N].  */
+  kd = eval_as_double (x + Shift);
+  ki = asuint64 (kd); /* k.  */
+  kd -= Shift; /* k/N for int k.  */
+  r = x - kd;
+  /* 2^(k/N) ~= scale * (1 + tail).  */
+  idx = 2 * (ki % N);
+  top = ki << (52 - EXP_TABLE_BITS);
+  tail = asdouble (T[idx]);
+  /* This is only a valid scale when -1023*N < k < 1024*N.  */
+  sbits = T[idx + 1] + top;
+  /* exp2(x) = 2^(k/N) * 2^r ~= scale + scale * (tail + 2^r - 1).  */
+  /* Evaluation is optimized assuming superscalar pipelined execution.  */
+  r2 = r * r;
+  /* Without fma the worst case error is 0.5/N ulp larger.  */
+  /* Worst case error is less than 0.5+0.86/N+(abs poly error * 2^53) ulp.  */
+#if EXP2_POLY_ORDER == 4
+  tmp = tail + r * C1 + r2 * C2 + r * r2 * (C3 + r * C4);
+#elif EXP2_POLY_ORDER == 5
+  tmp = tail + r * C1 + r2 * (C2 + r * C3) + r2 * r2 * (C4 + r * C5);
+#elif EXP2_POLY_ORDER == 6
+  tmp = tail + r * C1 + r2 * (0.5 + r * C3) + r2 * r2 * (C4 + r * C5 + r2 * C6);
+#endif
+  if (unlikely (abstop == 0))
+    return specialcase (tmp, sbits, ki);
+  scale = asdouble (sbits);
+  /* Note: tmp == 0 or |tmp| > 2^-65 and scale > 2^-928, so there
+     is no spurious underflow here even without fma.  */
+  return eval_as_double (scale + scale * tmp);
+}
+#if USE_GLIBC_ABI
+strong_alias (exp2, __exp2_finite)
+hidden_alias (exp2, __ieee754_exp2)
+# if LDBL_MANT_DIG == 53
+long double exp2l (long double x) { return exp2 (x); }
+# endif
+#endif
diff --git a/libc/AOR_v20.02/math/exp2f.c b/libc/AOR_v20.02/math/exp2f.c
new file mode 100644 (file)
index 0000000..4259e29
--- /dev/null
@@ -0,0 +1,81 @@
+/*
+ * Single-precision 2^x function.
+ *
+ * Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+ * See https://llvm.org/LICENSE.txt for license information.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include <math.h>
+#include <stdint.h>
+#include "math_config.h"
+
+/*
+EXP2F_TABLE_BITS = 5
+EXP2F_POLY_ORDER = 3
+
+ULP error: 0.502 (nearest rounding.)
+Relative error: 1.69 * 2^-34 in [-1/64, 1/64] (before rounding.)
+Wrong count: 168353 (all nearest rounding wrong results with fma.)
+Non-nearest ULP error: 1 (rounded ULP error)
+*/
+
+#define N (1 << EXP2F_TABLE_BITS)
+#define T __exp2f_data.tab
+#define C __exp2f_data.poly
+#define SHIFT __exp2f_data.shift_scaled
+
+static inline uint32_t
+top12 (float x)
+{
+  return asuint (x) >> 20;
+}
+
+float
+exp2f (float x)
+{
+  uint32_t abstop;
+  uint64_t ki, t;
+  /* double_t for better performance on targets with FLT_EVAL_METHOD==2.  */
+  double_t kd, xd, z, r, r2, y, s;
+
+  xd = (double_t) x;
+  abstop = top12 (x) & 0x7ff;
+  if (unlikely (abstop >= top12 (128.0f)))
+    {
+      /* |x| >= 128 or x is nan.  */
+      if (asuint (x) == asuint (-INFINITY))
+       return 0.0f;
+      if (abstop >= top12 (INFINITY))
+       return x + x;
+      if (x > 0.0f)
+       return __math_oflowf (0);
+      if (x <= -150.0f)
+       return __math_uflowf (0);
+#if WANT_ERRNO_UFLOW
+      if (x < -149.0f)
+       return __math_may_uflowf (0);
+#endif
+    }
+
+  /* x = k/N + r with r in [-1/(2N), 1/(2N)] and int k.  */
+  kd = eval_as_double (xd + SHIFT);
+  ki = asuint64 (kd);
+  kd -= SHIFT; /* k/N for int k.  */
+  r = xd - kd;
+
+  /* exp2(x) = 2^(k/N) * 2^r ~= s * (C0*r^3 + C1*r^2 + C2*r + 1) */
+  t = T[ki % N];
+  t += ki << (52 - EXP2F_TABLE_BITS);
+  s = asdouble (t);
+  z = C[0] * r + C[1];
+  r2 = r * r;
+  y = C[2] * r + 1;
+  y = z * r2 + y;
+  y = y * s;
+  return eval_as_float (y);
+}
+#if USE_GLIBC_ABI
+strong_alias (exp2f, __exp2f_finite)
+hidden_alias (exp2f, __ieee754_exp2f)
+#endif
diff --git a/libc/AOR_v20.02/math/exp2f_data.c b/libc/AOR_v20.02/math/exp2f_data.c
new file mode 100644 (file)
index 0000000..0630750
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+ * Shared data between expf, exp2f and powf.
+ *
+ * Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+ * See https://llvm.org/LICENSE.txt for license information.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "math_config.h"
+
+#define N (1 << EXP2F_TABLE_BITS)
+
+const struct exp2f_data __exp2f_data = {
+  /* tab[i] = uint(2^(i/N)) - (i << 52-BITS)
+     used for computing 2^(k/N) for an int |k| < 150 N as
+     double(tab[k%N] + (k << 52-BITS)) */
+  .tab = {
+#if N == 8
+0x3ff0000000000000, 0x3fef72b83c7d517b, 0x3fef06fe0a31b715, 0x3feebfdad5362a27,
+0x3feea09e667f3bcd, 0x3feeace5422aa0db, 0x3feee89f995ad3ad, 0x3fef5818dcfba487,
+#elif N == 16
+0x3ff0000000000000, 0x3fefb5586cf9890f, 0x3fef72b83c7d517b, 0x3fef387a6e756238,
+0x3fef06fe0a31b715, 0x3feedea64c123422, 0x3feebfdad5362a27, 0x3feeab07dd485429,
+0x3feea09e667f3bcd, 0x3feea11473eb0187, 0x3feeace5422aa0db, 0x3feec49182a3f090,
+0x3feee89f995ad3ad, 0x3fef199bdd85529c, 0x3fef5818dcfba487, 0x3fefa4afa2a490da,
+#elif N == 32
+0x3ff0000000000000, 0x3fefd9b0d3158574, 0x3fefb5586cf9890f, 0x3fef9301d0125b51,
+0x3fef72b83c7d517b, 0x3fef54873168b9aa, 0x3fef387a6e756238, 0x3fef1e9df51fdee1,
+0x3fef06fe0a31b715, 0x3feef1a7373aa9cb, 0x3feedea64c123422, 0x3feece086061892d,
+0x3feebfdad5362a27, 0x3feeb42b569d4f82, 0x3feeab07dd485429, 0x3feea47eb03a5585,
+0x3feea09e667f3bcd, 0x3fee9f75e8ec5f74, 0x3feea11473eb0187, 0x3feea589994cce13,
+0x3feeace5422aa0db, 0x3feeb737b0cdc5e5, 0x3feec49182a3f090, 0x3feed503b23e255d,
+0x3feee89f995ad3ad, 0x3feeff76f2fb5e47, 0x3fef199bdd85529c, 0x3fef3720dcef9069,
+0x3fef5818dcfba487, 0x3fef7c97337b9b5f, 0x3fefa4afa2a490da, 0x3fefd0765b6e4540,
+#elif N == 64
+0x3ff0000000000000, 0x3fefec9a3e778061, 0x3fefd9b0d3158574, 0x3fefc74518759bc8,
+0x3fefb5586cf9890f, 0x3fefa3ec32d3d1a2, 0x3fef9301d0125b51, 0x3fef829aaea92de0,
+0x3fef72b83c7d517b, 0x3fef635beb6fcb75, 0x3fef54873168b9aa, 0x3fef463b88628cd6,
+0x3fef387a6e756238, 0x3fef2b4565e27cdd, 0x3fef1e9df51fdee1, 0x3fef1285a6e4030b,
+0x3fef06fe0a31b715, 0x3feefc08b26416ff, 0x3feef1a7373aa9cb, 0x3feee7db34e59ff7,
+0x3feedea64c123422, 0x3feed60a21f72e2a, 0x3feece086061892d, 0x3feec6a2b5c13cd0,
+0x3feebfdad5362a27, 0x3feeb9b2769d2ca7, 0x3feeb42b569d4f82, 0x3feeaf4736b527da,
+0x3feeab07dd485429, 0x3feea76f15ad2148, 0x3feea47eb03a5585, 0x3feea23882552225,
+0x3feea09e667f3bcd, 0x3fee9fb23c651a2f, 0x3fee9f75e8ec5f74, 0x3fee9feb564267c9,
+0x3feea11473eb0187, 0x3feea2f336cf4e62, 0x3feea589994cce13, 0x3feea8d99b4492ed,
+0x3feeace5422aa0db, 0x3feeb1ae99157736, 0x3feeb737b0cdc5e5, 0x3feebd829fde4e50,
+0x3feec49182a3f090, 0x3feecc667b5de565, 0x3feed503b23e255d, 0x3feede6b5579fdbf,
+0x3feee89f995ad3ad, 0x3feef3a2b84f15fb, 0x3feeff76f2fb5e47, 0x3fef0c1e904bc1d2,
+0x3fef199bdd85529c, 0x3fef27f12e57d14b, 0x3fef3720dcef9069, 0x3fef472d4a07897c,
+0x3fef5818dcfba487, 0x3fef69e603db3285, 0x3fef7c97337b9b5f, 0x3fef902ee78b3ff6,
+0x3fefa4afa2a490da, 0x3fefba1bee615a27, 0x3fefd0765b6e4540, 0x3fefe7c1819e90d8,
+#endif
+  },
+  .shift_scaled = 0x1.8p+52 / N,
+  .poly = {
+#if N == 8
+  0x1.c6a00335106e2p-5, 0x1.ec0c313449f55p-3, 0x1.62e431111f69fp-1,
+#elif N == 16
+  0x1.c6ac6aa313963p-5, 0x1.ebfff4532d9bap-3, 0x1.62e43001bc49fp-1,
+#elif N == 32
+  0x1.c6af84b912394p-5, 0x1.ebfce50fac4f3p-3, 0x1.62e42ff0c52d6p-1,
+#elif N == 64
+  0x1.c6b04b4221b2ap-5, 0x1.ebfc213e184d7p-3, 0x1.62e42fefb5b7fp-1,
+#endif
+  },
+  .shift = 0x1.8p+52,
+  .invln2_scaled = 0x1.71547652b82fep+0 * N,
+  .poly_scaled = {
+#if N == 8
+  0x1.c6a00335106e2p-5/N/N/N, 0x1.ec0c313449f55p-3/N/N, 0x1.62e431111f69fp-1/N,
+#elif N == 16
+  0x1.c6ac6aa313963p-5/N/N/N, 0x1.ebfff4532d9bap-3/N/N, 0x1.62e43001bc49fp-1/N,
+#elif N == 32
+  0x1.c6af84b912394p-5/N/N/N, 0x1.ebfce50fac4f3p-3/N/N, 0x1.62e42ff0c52d6p-1/N,
+#elif N == 64
+  0x1.c6b04b4221b2ap-5/N/N/N, 0x1.ebfc213e184d7p-3/N/N, 0x1.62e42fefb5b7fp-1/N,
+#endif
+  },
+};
diff --git a/libc/AOR_v20.02/math/exp_data.c b/libc/AOR_v20.02/math/exp_data.c
new file mode 100644 (file)
index 0000000..682eee8
--- /dev/null
@@ -0,0 +1,1121 @@
+/*
+ * Shared data between exp, exp2 and pow.
+ *
+ * Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+ * See https://llvm.org/LICENSE.txt for license information.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "math_config.h"
+
+#define N (1 << EXP_TABLE_BITS)
+
+const struct exp_data __exp_data = {
+// N/ln2
+.invln2N = 0x1.71547652b82fep0 * N,
+// -ln2/N
+#if N == 64
+.negln2hiN = -0x1.62e42fefa0000p-7,
+.negln2loN = -0x1.cf79abc9e3b3ap-46,
+#elif N == 128
+.negln2hiN = -0x1.62e42fefa0000p-8,
+.negln2loN = -0x1.cf79abc9e3b3ap-47,
+#elif N == 256
+.negln2hiN = -0x1.62e42fefc0000p-9,
+.negln2loN = 0x1.c610ca86c3899p-45,
+#elif N == 512
+.negln2hiN = -0x1.62e42fef80000p-10,
+.negln2loN = -0x1.1cf79abc9e3b4p-45,
+#endif
+// Used for rounding when !TOINT_INTRINSICS
+#if EXP_USE_TOINT_NARROW
+.shift = 0x1800000000.8p0,
+#else
+.shift = 0x1.8p52,
+#endif
+// exp polynomial coefficients.
+.poly = {
+#if N == 64 && EXP_POLY_ORDER == 5 && !EXP_POLY_WIDE
+// abs error: 1.5543*2^-60
+// ulp error: 0.529 (0.533 without fma)
+// if |x| < ln2/128+eps
+// abs error if |x| < ln2/64: 1.7157*2^-50
+0x1.fffffffffdbcdp-2,
+0x1.555555555444cp-3,
+0x1.555573c6a9f7dp-5,
+0x1.1111266d28935p-7,
+#elif N == 64 && EXP_POLY_ORDER == 6 && EXP_POLY_WIDE
+// abs error: 1.6735*2^-64
+// ulp error: 0.518 (0.522 without fma)
+// if |x| < ln2/64
+0x1.5555555548f9ap-3,
+0x1.555555554bf5dp-5,
+0x1.11115b75f0f4dp-7,
+0x1.6c171a6b6303ep-10,
+#elif N == 128 && EXP_POLY_ORDER == 5 && !EXP_POLY_WIDE
+// abs error: 1.555*2^-66
+// ulp error: 0.509 (0.511 without fma)
+// if |x| < ln2/256+eps
+// abs error if |x| < ln2/256+0x1p-15: 1.09*2^-65
+// abs error if |x| < ln2/128: 1.7145*2^-56
+0x1.ffffffffffdbdp-2,
+0x1.555555555543cp-3,
+0x1.55555cf172b91p-5,
+0x1.1111167a4d017p-7,
+#elif N == 128 && EXP_POLY_ORDER == 5 && EXP_POLY_WIDE
+// abs error: 1.5542*2^-60
+// ulp error: 0.521 (0.523 without fma)
+// if |x| < ln2/128
+0x1.fffffffffdbcep-2,
+0x1.55555555543c2p-3,
+0x1.555573c64f2e3p-5,
+0x1.111126b4eff73p-7,
+#elif N == 128 && EXP_POLY_ORDER == 6 && EXP_POLY_WIDE
+// abs error: 1.6861*2^-71
+// ulp error: 0.509 (0.511 without fma)
+// if |x| < ln2/128
+0x1.55555555548fdp-3,
+0x1.555555555658fp-5,
+0x1.111123a859bb6p-7,
+0x1.6c16ba6920cabp-10,
+#elif N == 256 && EXP_POLY_ORDER == 4 && !EXP_POLY_WIDE
+// abs error: 1.43*2^-58
+// ulp error: 0.549 (0.550 without fma)
+// if |x| < ln2/512
+0x1p0, // unused
+0x1.fffffffffffd4p-2,
+0x1.5555571d6ef9p-3,
+0x1.5555576a5adcep-5,
+#elif N == 256 && EXP_POLY_ORDER == 5 && EXP_POLY_WIDE
+// abs error: 1.5547*2^-66
+// ulp error: 0.505 (0.506 without fma)
+// if |x| < ln2/256
+0x1.ffffffffffdbdp-2,
+0x1.555555555543cp-3,
+0x1.55555cf16e1edp-5,
+0x1.1111167a4b553p-7,
+#elif N == 512 && EXP_POLY_ORDER == 4 && !EXP_POLY_WIDE
+// abs error: 1.4300*2^-63
+// ulp error: 0.504
+// if |x| < ln2/1024
+// abs error if |x| < ln2/512: 1.0689*2^-55
+0x1p0, // unused
+0x1.ffffffffffffdp-2,
+0x1.555555c75bb6p-3,
+0x1.555555dec04a8p-5,
+#endif
+},
+.exp2_shift = 0x1.8p52 / N,
+// exp2 polynomial coefficients.
+.exp2_poly = {
+#if N == 64 && EXP2_POLY_ORDER == 6 && EXP2_POLY_WIDE
+// abs error: 1.3054*2^-63
+// ulp error: 0.515
+// if |x| < 1/64
+0x1.62e42fefa39efp-1,
+0x1.ebfbdff82c58fp-3,
+0x1.c6b08d7045cf1p-5,
+0x1.3b2ab6fb8fd0ep-7,
+0x1.5d884afec48d7p-10,
+0x1.43097dc684ae1p-13,
+#elif N == 128 && EXP2_POLY_ORDER == 5 && !EXP2_POLY_WIDE
+// abs error: 1.2195*2^-65
+// ulp error: 0.507 (0.511 without fma)
+// if |x| < 1/256
+// abs error if |x| < 1/128: 1.9941*2^-56
+0x1.62e42fefa39efp-1,
+0x1.ebfbdff82c424p-3,
+0x1.c6b08d70cf4b5p-5,
+0x1.3b2abd24650ccp-7,
+0x1.5d7e09b4e3a84p-10,
+#elif N == 256 && EXP2_POLY_ORDER == 5 && EXP2_POLY_WIDE
+// abs error: 1.2195*2^-65
+// ulp error: 0.504 (0.508 without fma)
+// if |x| < 1/256
+0x1.62e42fefa39efp-1,
+0x1.ebfbdff82c424p-3,
+0x1.c6b08d70cf4b5p-5,
+0x1.3b2abd24650ccp-7,
+0x1.5d7e09b4e3a84p-10,
+#elif N == 512 && EXP2_POLY_ORDER == 4 && !EXP2_POLY_WIDE
+// abs error: 1.4411*2^-64
+// ulp error: 0.5024 (0.5063 without fma)
+// if |x| < 1/1024
+// abs error if |x| < 1/512: 1.9430*2^-56
+0x1.62e42fefa39ecp-1,
+0x1.ebfbdff82c58bp-3,
+0x1.c6b08e46de41fp-5,
+0x1.3b2ab786ee1dap-7,
+#endif
+},
+// 2^(k/N) ~= H[k]*(1 + T[k]) for int k in [0,N)
+// tab[2*k] = asuint64(T[k])
+// tab[2*k+1] = asuint64(H[k]) - (k << 52)/N
+.tab = {
+#if N == 64
+0x0, 0x3ff0000000000000,
+0xbc7160139cd8dc5d, 0x3fefec9a3e778061,
+0x3c8cd2523567f613, 0x3fefd9b0d3158574,
+0x3c60f74e61e6c861, 0x3fefc74518759bc8,
+0x3c979aa65d837b6d, 0x3fefb5586cf9890f,
+0x3c3ebe3d702f9cd1, 0x3fefa3ec32d3d1a2,
+0xbc9556522a2fbd0e, 0x3fef9301d0125b51,
+0xbc91c923b9d5f416, 0x3fef829aaea92de0,
+0xbc801b15eaa59348, 0x3fef72b83c7d517b,
+0x3c8b898c3f1353bf, 0x3fef635beb6fcb75,
+0x3c9aecf73e3a2f60, 0x3fef54873168b9aa,
+0x3c8a6f4144a6c38d, 0x3fef463b88628cd6,
+0x3c968efde3a8a894, 0x3fef387a6e756238,
+0x3c80472b981fe7f2, 0x3fef2b4565e27cdd,
+0x3c82f7e16d09ab31, 0x3fef1e9df51fdee1,
+0x3c8b3782720c0ab4, 0x3fef1285a6e4030b,
+0x3c834d754db0abb6, 0x3fef06fe0a31b715,
+0x3c8fdd395dd3f84a, 0x3feefc08b26416ff,
+0xbc924aedcc4b5068, 0x3feef1a7373aa9cb,
+0xbc71d1e83e9436d2, 0x3feee7db34e59ff7,
+0x3c859f48a72a4c6d, 0x3feedea64c123422,
+0xbc58a78f4817895b, 0x3feed60a21f72e2a,
+0x3c4363ed60c2ac11, 0x3feece086061892d,
+0x3c6ecce1daa10379, 0x3feec6a2b5c13cd0,
+0x3c7690cebb7aafb0, 0x3feebfdad5362a27,
+0xbc8f94340071a38e, 0x3feeb9b2769d2ca7,
+0xbc78dec6bd0f385f, 0x3feeb42b569d4f82,
+0x3c93350518fdd78e, 0x3feeaf4736b527da,
+0x3c9063e1e21c5409, 0x3feeab07dd485429,
+0x3c9432e62b64c035, 0x3feea76f15ad2148,
+0xbc8c33c53bef4da8, 0x3feea47eb03a5585,
+0xbc93cedd78565858, 0x3feea23882552225,
+0xbc93b3efbf5e2228, 0x3feea09e667f3bcd,
+0xbc6367efb86da9ee, 0x3fee9fb23c651a2f,
+0xbc781f647e5a3ecf, 0x3fee9f75e8ec5f74,
+0xbc8619321e55e68a, 0x3fee9feb564267c9,
+0xbc7b32dcb94da51d, 0x3feea11473eb0187,
+0x3c65ebe1abd66c55, 0x3feea2f336cf4e62,
+0xbc9369b6f13b3734, 0x3feea589994cce13,
+0xbc94d450d872576e, 0x3feea8d99b4492ed,
+0x3c8db72fc1f0eab4, 0x3feeace5422aa0db,
+0x3c7bf68359f35f44, 0x3feeb1ae99157736,
+0xbc5da9b88b6c1e29, 0x3feeb737b0cdc5e5,
+0xbc92434322f4f9aa, 0x3feebd829fde4e50,
+0x3c71affc2b91ce27, 0x3feec49182a3f090,
+0xbc87c50422622263, 0x3feecc667b5de565,
+0xbc91bbd1d3bcbb15, 0x3feed503b23e255d,
+0x3c8469846e735ab3, 0x3feede6b5579fdbf,
+0x3c8c1a7792cb3387, 0x3feee89f995ad3ad,
+0xbc55c3d956dcaeba, 0x3feef3a2b84f15fb,
+0xbc68d6f438ad9334, 0x3feeff76f2fb5e47,
+0x3c74ffd70a5fddcd, 0x3fef0c1e904bc1d2,
+0x3c736eae30af0cb3, 0x3fef199bdd85529c,
+0x3c84e08fd10959ac, 0x3fef27f12e57d14b,
+0x3c676b2c6c921968, 0x3fef3720dcef9069,
+0xbc8fad5d3ffffa6f, 0x3fef472d4a07897c,
+0x3c74a385a63d07a7, 0x3fef5818dcfba487,
+0x3c8e5a50d5c192ac, 0x3fef69e603db3285,
+0xbc82d52107b43e1f, 0x3fef7c97337b9b5f,
+0x3c74b604603a88d3, 0x3fef902ee78b3ff6,
+0xbc8ff7128fd391f0, 0x3fefa4afa2a490da,
+0x3c8ec3bc41aa2008, 0x3fefba1bee615a27,
+0x3c8a64a931d185ee, 0x3fefd0765b6e4540,
+0x3c77893b4d91cd9d, 0x3fefe7c1819e90d8,
+#elif N == 128
+0x0, 0x3ff0000000000000,
+0x3c9b3b4f1a88bf6e, 0x3feff63da9fb3335,
+0xbc7160139cd8dc5d, 0x3fefec9a3e778061,
+0xbc905e7a108766d1, 0x3fefe315e86e7f85,
+0x3c8cd2523567f613, 0x3fefd9b0d3158574,
+0xbc8bce8023f98efa, 0x3fefd06b29ddf6de,
+0x3c60f74e61e6c861, 0x3fefc74518759bc8,
+0x3c90a3e45b33d399, 0x3fefbe3ecac6f383,
+0x3c979aa65d837b6d, 0x3fefb5586cf9890f,
+0x3c8eb51a92fdeffc, 0x3fefac922b7247f7,
+0x3c3ebe3d702f9cd1, 0x3fefa3ec32d3d1a2,
+0xbc6a033489906e0b, 0x3fef9b66affed31b,
+0xbc9556522a2fbd0e, 0x3fef9301d0125b51,
+0xbc5080ef8c4eea55, 0x3fef8abdc06c31cc,
+0xbc91c923b9d5f416, 0x3fef829aaea92de0,
+0x3c80d3e3e95c55af, 0x3fef7a98c8a58e51,
+0xbc801b15eaa59348, 0x3fef72b83c7d517b,
+0xbc8f1ff055de323d, 0x3fef6af9388c8dea,
+0x3c8b898c3f1353bf, 0x3fef635beb6fcb75,
+0xbc96d99c7611eb26, 0x3fef5be084045cd4,
+0x3c9aecf73e3a2f60, 0x3fef54873168b9aa,
+0xbc8fe782cb86389d, 0x3fef4d5022fcd91d,
+0x3c8a6f4144a6c38d, 0x3fef463b88628cd6,
+0x3c807a05b0e4047d, 0x3fef3f49917ddc96,
+0x3c968efde3a8a894, 0x3fef387a6e756238,
+0x3c875e18f274487d, 0x3fef31ce4fb2a63f,
+0x3c80472b981fe7f2, 0x3fef2b4565e27cdd,
+0xbc96b87b3f71085e, 0x3fef24dfe1f56381,
+0x3c82f7e16d09ab31, 0x3fef1e9df51fdee1,
+0xbc3d219b1a6fbffa, 0x3fef187fd0dad990,
+0x3c8b3782720c0ab4, 0x3fef1285a6e4030b,
+0x3c6e149289cecb8f, 0x3fef0cafa93e2f56,
+0x3c834d754db0abb6, 0x3fef06fe0a31b715,
+0x3c864201e2ac744c, 0x3fef0170fc4cd831,
+0x3c8fdd395dd3f84a, 0x3feefc08b26416ff,
+0xbc86a3803b8e5b04, 0x3feef6c55f929ff1,
+0xbc924aedcc4b5068, 0x3feef1a7373aa9cb,
+0xbc9907f81b512d8e, 0x3feeecae6d05d866,
+0xbc71d1e83e9436d2, 0x3feee7db34e59ff7,
+0xbc991919b3ce1b15, 0x3feee32dc313a8e5,
+0x3c859f48a72a4c6d, 0x3feedea64c123422,
+0xbc9312607a28698a, 0x3feeda4504ac801c,
+0xbc58a78f4817895b, 0x3feed60a21f72e2a,
+0xbc7c2c9b67499a1b, 0x3feed1f5d950a897,
+0x3c4363ed60c2ac11, 0x3feece086061892d,
+0x3c9666093b0664ef, 0x3feeca41ed1d0057,
+0x3c6ecce1daa10379, 0x3feec6a2b5c13cd0,
+0x3c93ff8e3f0f1230, 0x3feec32af0d7d3de,
+0x3c7690cebb7aafb0, 0x3feebfdad5362a27,
+0x3c931dbdeb54e077, 0x3feebcb299fddd0d,
+0xbc8f94340071a38e, 0x3feeb9b2769d2ca7,
+0xbc87deccdc93a349, 0x3feeb6daa2cf6642,
+0xbc78dec6bd0f385f, 0x3feeb42b569d4f82,
+0xbc861246ec7b5cf6, 0x3feeb1a4ca5d920f,
+0x3c93350518fdd78e, 0x3feeaf4736b527da,
+0x3c7b98b72f8a9b05, 0x3feead12d497c7fd,
+0x3c9063e1e21c5409, 0x3feeab07dd485429,
+0x3c34c7855019c6ea, 0x3feea9268a5946b7,
+0x3c9432e62b64c035, 0x3feea76f15ad2148,
+0xbc8ce44a6199769f, 0x3feea5e1b976dc09,
+0xbc8c33c53bef4da8, 0x3feea47eb03a5585,
+0xbc845378892be9ae, 0x3feea34634ccc320,
+0xbc93cedd78565858, 0x3feea23882552225,
+0x3c5710aa807e1964, 0x3feea155d44ca973,
+0xbc93b3efbf5e2228, 0x3feea09e667f3bcd,
+0xbc6a12ad8734b982, 0x3feea012750bdabf,
+0xbc6367efb86da9ee, 0x3fee9fb23c651a2f,
+0xbc80dc3d54e08851, 0x3fee9f7df9519484,
+0xbc781f647e5a3ecf, 0x3fee9f75e8ec5f74,
+0xbc86ee4ac08b7db0, 0x3fee9f9a48a58174,
+0xbc8619321e55e68a, 0x3fee9feb564267c9,
+0x3c909ccb5e09d4d3, 0x3feea0694fde5d3f,
+0xbc7b32dcb94da51d, 0x3feea11473eb0187,
+0x3c94ecfd5467c06b, 0x3feea1ed0130c132,
+0x3c65ebe1abd66c55, 0x3feea2f336cf4e62,
+0xbc88a1c52fb3cf42, 0x3feea427543e1a12,
+0xbc9369b6f13b3734, 0x3feea589994cce13,
+0xbc805e843a19ff1e, 0x3feea71a4623c7ad,
+0xbc94d450d872576e, 0x3feea8d99b4492ed,
+0x3c90ad675b0e8a00, 0x3feeaac7d98a6699,
+0x3c8db72fc1f0eab4, 0x3feeace5422aa0db,
+0xbc65b6609cc5e7ff, 0x3feeaf3216b5448c,
+0x3c7bf68359f35f44, 0x3feeb1ae99157736,
+0xbc93091fa71e3d83, 0x3feeb45b0b91ffc6,
+0xbc5da9b88b6c1e29, 0x3feeb737b0cdc5e5,
+0xbc6c23f97c90b959, 0x3feeba44cbc8520f,
+0xbc92434322f4f9aa, 0x3feebd829fde4e50,
+0xbc85ca6cd7668e4b, 0x3feec0f170ca07ba,
+0x3c71affc2b91ce27, 0x3feec49182a3f090,
+0x3c6dd235e10a73bb, 0x3feec86319e32323,
+0xbc87c50422622263, 0x3feecc667b5de565,
+0x3c8b1c86e3e231d5, 0x3feed09bec4a2d33,
+0xbc91bbd1d3bcbb15, 0x3feed503b23e255d,
+0x3c90cc319cee31d2, 0x3feed99e1330b358,
+0x3c8469846e735ab3, 0x3feede6b5579fdbf,
+0xbc82dfcd978e9db4, 0x3feee36bbfd3f37a,
+0x3c8c1a7792cb3387, 0x3feee89f995ad3ad,
+0xbc907b8f4ad1d9fa, 0x3feeee07298db666,
+0xbc55c3d956dcaeba, 0x3feef3a2b84f15fb,
+0xbc90a40e3da6f640, 0x3feef9728de5593a,
+0xbc68d6f438ad9334, 0x3feeff76f2fb5e47,
+0xbc91eee26b588a35, 0x3fef05b030a1064a,
+0x3c74ffd70a5fddcd, 0x3fef0c1e904bc1d2,
+0xbc91bdfbfa9298ac, 0x3fef12c25bd71e09,
+0x3c736eae30af0cb3, 0x3fef199bdd85529c,
+0x3c8ee3325c9ffd94, 0x3fef20ab5fffd07a,
+0x3c84e08fd10959ac, 0x3fef27f12e57d14b,
+0x3c63cdaf384e1a67, 0x3fef2f6d9406e7b5,
+0x3c676b2c6c921968, 0x3fef3720dcef9069,
+0xbc808a1883ccb5d2, 0x3fef3f0b555dc3fa,
+0xbc8fad5d3ffffa6f, 0x3fef472d4a07897c,
+0xbc900dae3875a949, 0x3fef4f87080d89f2,
+0x3c74a385a63d07a7, 0x3fef5818dcfba487,
+0xbc82919e2040220f, 0x3fef60e316c98398,
+0x3c8e5a50d5c192ac, 0x3fef69e603db3285,
+0x3c843a59ac016b4b, 0x3fef7321f301b460,
+0xbc82d52107b43e1f, 0x3fef7c97337b9b5f,
+0xbc892ab93b470dc9, 0x3fef864614f5a129,
+0x3c74b604603a88d3, 0x3fef902ee78b3ff6,
+0x3c83c5ec519d7271, 0x3fef9a51fbc74c83,
+0xbc8ff7128fd391f0, 0x3fefa4afa2a490da,
+0xbc8dae98e223747d, 0x3fefaf482d8e67f1,
+0x3c8ec3bc41aa2008, 0x3fefba1bee615a27,
+0x3c842b94c3a9eb32, 0x3fefc52b376bba97,
+0x3c8a64a931d185ee, 0x3fefd0765b6e4540,
+0xbc8e37bae43be3ed, 0x3fefdbfdad9cbe14,
+0x3c77893b4d91cd9d, 0x3fefe7c1819e90d8,
+0x3c5305c14160cc89, 0x3feff3c22b8f71f1,
+#elif N == 256
+0x0, 0x3ff0000000000000,
+0xbc84e82fc61851ac, 0x3feffb1afa5abcbf,
+0x3c9b3b4f1a88bf6e, 0x3feff63da9fb3335,
+0xbc82985dd8521d32, 0x3feff168143b0281,
+0xbc7160139cd8dc5d, 0x3fefec9a3e778061,
+0x3c651e617061bfbd, 0x3fefe7d42e11bbcc,
+0xbc905e7a108766d1, 0x3fefe315e86e7f85,
+0x3c845fad437fa426, 0x3fefde5f72f654b1,
+0x3c8cd2523567f613, 0x3fefd9b0d3158574,
+0xbc954529642b232f, 0x3fefd50a0e3c1f89,
+0xbc8bce8023f98efa, 0x3fefd06b29ddf6de,
+0x3c8293708ef5c32e, 0x3fefcbd42b72a836,
+0x3c60f74e61e6c861, 0x3fefc74518759bc8,
+0xbc95b9280905b2a4, 0x3fefc2bdf66607e0,
+0x3c90a3e45b33d399, 0x3fefbe3ecac6f383,
+0x3c84f31f32c4b7e7, 0x3fefb9c79b1f3919,
+0x3c979aa65d837b6d, 0x3fefb5586cf9890f,
+0x3c9407fb30d06420, 0x3fefb0f145e46c85,
+0x3c8eb51a92fdeffc, 0x3fefac922b7247f7,
+0xbc9a5d04b3b9911b, 0x3fefa83b23395dec,
+0x3c3ebe3d702f9cd1, 0x3fefa3ec32d3d1a2,
+0xbc937a01f0739546, 0x3fef9fa55fdfa9c5,
+0xbc6a033489906e0b, 0x3fef9b66affed31b,
+0x3c8b8268b04ef0a5, 0x3fef973028d7233e,
+0xbc9556522a2fbd0e, 0x3fef9301d0125b51,
+0xbc9ac46e44a2ebcc, 0x3fef8edbab5e2ab6,
+0xbc5080ef8c4eea55, 0x3fef8abdc06c31cc,
+0xbc65704e90c9f860, 0x3fef86a814f204ab,
+0xbc91c923b9d5f416, 0x3fef829aaea92de0,
+0xbc897cea57e46280, 0x3fef7e95934f312e,
+0x3c80d3e3e95c55af, 0x3fef7a98c8a58e51,
+0x3c56f01429e2b9d2, 0x3fef76a45471c3c2,
+0xbc801b15eaa59348, 0x3fef72b83c7d517b,
+0x3c6e653b2459034b, 0x3fef6ed48695bbc0,
+0xbc8f1ff055de323d, 0x3fef6af9388c8dea,
+0x3c92cc7ea345b7dc, 0x3fef672658375d2f,
+0x3c8b898c3f1353bf, 0x3fef635beb6fcb75,
+0x3c957bfb2876ea9e, 0x3fef5f99f8138a1c,
+0xbc96d99c7611eb26, 0x3fef5be084045cd4,
+0x3c8cdc1873af2155, 0x3fef582f95281c6b,
+0x3c9aecf73e3a2f60, 0x3fef54873168b9aa,
+0xbc9493684653a131, 0x3fef50e75eb44027,
+0xbc8fe782cb86389d, 0x3fef4d5022fcd91d,
+0xbc98e2899077520a, 0x3fef49c18438ce4d,
+0x3c8a6f4144a6c38d, 0x3fef463b88628cd6,
+0x3c9120fcd4f59273, 0x3fef42be3578a819,
+0x3c807a05b0e4047d, 0x3fef3f49917ddc96,
+0x3c89b788c188c9b8, 0x3fef3bdda27912d1,
+0x3c968efde3a8a894, 0x3fef387a6e756238,
+0x3c877afbca90ef84, 0x3fef351ffb82140a,
+0x3c875e18f274487d, 0x3fef31ce4fb2a63f,
+0x3c91512f082876ee, 0x3fef2e85711ece75,
+0x3c80472b981fe7f2, 0x3fef2b4565e27cdd,
+0x3c9a02f0c7d75ec6, 0x3fef280e341ddf29,
+0xbc96b87b3f71085e, 0x3fef24dfe1f56381,
+0xbc803297e78260bf, 0x3fef21ba7591bb70,
+0x3c82f7e16d09ab31, 0x3fef1e9df51fdee1,
+0xbc95b77e5ccd9fbf, 0x3fef1b8a66d10f13,
+0xbc3d219b1a6fbffa, 0x3fef187fd0dad990,
+0xbc91e75c40b4251e, 0x3fef157e39771b2f,
+0x3c8b3782720c0ab4, 0x3fef1285a6e4030b,
+0x3c98a911f1f7785a, 0x3fef0f961f641589,
+0x3c6e149289cecb8f, 0x3fef0cafa93e2f56,
+0xbc61e7c998db7dbb, 0x3fef09d24abd886b,
+0x3c834d754db0abb6, 0x3fef06fe0a31b715,
+0x3c85425c11faadf4, 0x3fef0432edeeb2fd,
+0x3c864201e2ac744c, 0x3fef0170fc4cd831,
+0xbc979517a03e2847, 0x3feefeb83ba8ea32,
+0x3c8fdd395dd3f84a, 0x3feefc08b26416ff,
+0xbc800e2a46da4bee, 0x3feef96266e3fa2d,
+0xbc86a3803b8e5b04, 0x3feef6c55f929ff1,
+0xbc87430803972b34, 0x3feef431a2de883b,
+0xbc924aedcc4b5068, 0x3feef1a7373aa9cb,
+0xbc954de30ae02d94, 0x3feeef26231e754a,
+0xbc9907f81b512d8e, 0x3feeecae6d05d866,
+0xbc94f2487e1c03ec, 0x3feeea401b7140ef,
+0xbc71d1e83e9436d2, 0x3feee7db34e59ff7,
+0x3c914a5432fcb2f4, 0x3feee57fbfec6cf4,
+0xbc991919b3ce1b15, 0x3feee32dc313a8e5,
+0x3c79c3bba5562a2f, 0x3feee0e544ede173,
+0x3c859f48a72a4c6d, 0x3feedea64c123422,
+0xbc85a71612e21658, 0x3feedc70df1c5175,
+0xbc9312607a28698a, 0x3feeda4504ac801c,
+0x3c86421f6f1d24d6, 0x3feed822c367a024,
+0xbc58a78f4817895b, 0x3feed60a21f72e2a,
+0xbc9348a6815fce65, 0x3feed3fb2709468a,
+0xbc7c2c9b67499a1b, 0x3feed1f5d950a897,
+0x3c835c43984d9871, 0x3feecffa3f84b9d4,
+0x3c4363ed60c2ac11, 0x3feece086061892d,
+0xbc632afc8d9473a0, 0x3feecc2042a7d232,
+0x3c9666093b0664ef, 0x3feeca41ed1d0057,
+0xbc95fc5e44de020e, 0x3feec86d668b3237,
+0x3c6ecce1daa10379, 0x3feec6a2b5c13cd0,
+0xbc7ea0148327c42f, 0x3feec4e1e192aed2,
+0x3c93ff8e3f0f1230, 0x3feec32af0d7d3de,
+0xbc7a843ad1a88022, 0x3feec17dea6db7d7,
+0x3c7690cebb7aafb0, 0x3feebfdad5362a27,
+0x3c892ca3bf144e63, 0x3feebe41b817c114,
+0x3c931dbdeb54e077, 0x3feebcb299fddd0d,
+0xbc902c99b04aa8b0, 0x3feebb2d81d8abff,
+0xbc8f94340071a38e, 0x3feeb9b2769d2ca7,
+0x3c73e34f67e67118, 0x3feeb8417f4531ee,
+0xbc87deccdc93a349, 0x3feeb6daa2cf6642,
+0xbc75a3b1197ba0f0, 0x3feeb57de83f4eef,
+0xbc78dec6bd0f385f, 0x3feeb42b569d4f82,
+0x3c81bd2888075068, 0x3feeb2e2f4f6ad27,
+0xbc861246ec7b5cf6, 0x3feeb1a4ca5d920f,
+0xbc896be8ae89ef8f, 0x3feeb070dde910d2,
+0x3c93350518fdd78e, 0x3feeaf4736b527da,
+0xbc88e6ac90348602, 0x3feeae27dbe2c4cf,
+0x3c7b98b72f8a9b05, 0x3feead12d497c7fd,
+0xbc91af7f1365c3ac, 0x3feeac0827ff07cc,
+0x3c9063e1e21c5409, 0x3feeab07dd485429,
+0xbc943a3540d1898a, 0x3feeaa11fba87a03,
+0x3c34c7855019c6ea, 0x3feea9268a5946b7,
+0xbc951f58ddaa8090, 0x3feea84590998b93,
+0x3c9432e62b64c035, 0x3feea76f15ad2148,
+0xbc82e1648e50a17c, 0x3feea6a320dceb71,
+0xbc8ce44a6199769f, 0x3feea5e1b976dc09,
+0x3c95f30eda98a575, 0x3feea52ae6cdf6f4,
+0xbc8c33c53bef4da8, 0x3feea47eb03a5585,
+0x3c917ecda8a72159, 0x3feea3dd1d1929fd,
+0xbc845378892be9ae, 0x3feea34634ccc320,
+0xbc9345f3cee1ae6e, 0x3feea2b9febc8fb7,
+0xbc93cedd78565858, 0x3feea23882552225,
+0xbc85c33fdf910406, 0x3feea1c1c70833f6,
+0x3c5710aa807e1964, 0x3feea155d44ca973,
+0x3c81079ab5789604, 0x3feea0f4b19e9538,
+0xbc93b3efbf5e2228, 0x3feea09e667f3bcd,
+0x3c727df161cd7778, 0x3feea052fa75173e,
+0xbc6a12ad8734b982, 0x3feea012750bdabf,
+0x3c93f9924a05b767, 0x3fee9fdcddd47645,
+0xbc6367efb86da9ee, 0x3fee9fb23c651a2f,
+0xbc87557939a8b5ef, 0x3fee9f9298593ae5,
+0xbc80dc3d54e08851, 0x3fee9f7df9519484,
+0x3c51ed2f56fa9d1a, 0x3fee9f7466f42e87,
+0xbc781f647e5a3ecf, 0x3fee9f75e8ec5f74,
+0xbc88e67a9006c909, 0x3fee9f8286ead08a,
+0xbc86ee4ac08b7db0, 0x3fee9f9a48a58174,
+0x3c86597566977ac8, 0x3fee9fbd35d7cbfd,
+0xbc8619321e55e68a, 0x3fee9feb564267c9,
+0x3c92c0b7028a5c3a, 0x3feea024b1ab6e09,
+0x3c909ccb5e09d4d3, 0x3feea0694fde5d3f,
+0x3c8a30faf49cc78c, 0x3feea0b938ac1cf6,
+0xbc7b32dcb94da51d, 0x3feea11473eb0187,
+0xbc92dad3519d7b5b, 0x3feea17b0976cfdb,
+0x3c94ecfd5467c06b, 0x3feea1ed0130c132,
+0x3c87d51410fd15c2, 0x3feea26a62ff86f0,
+0x3c65ebe1abd66c55, 0x3feea2f336cf4e62,
+0xbc760a3629969871, 0x3feea3878491c491,
+0xbc88a1c52fb3cf42, 0x3feea427543e1a12,
+0x3c8b18c6e3fdef5d, 0x3feea4d2add106d9,
+0xbc9369b6f13b3734, 0x3feea589994cce13,
+0x3c90ec1ddcb1390a, 0x3feea64c1eb941f7,
+0xbc805e843a19ff1e, 0x3feea71a4623c7ad,
+0xbc522cea4f3afa1e, 0x3feea7f4179f5b21,
+0xbc94d450d872576e, 0x3feea8d99b4492ed,
+0x3c7c88549b958471, 0x3feea9cad931a436,
+0x3c90ad675b0e8a00, 0x3feeaac7d98a6699,
+0x3c931143962f7877, 0x3feeabd0a478580f,
+0x3c8db72fc1f0eab4, 0x3feeace5422aa0db,
+0x3c93e9e96f112479, 0x3feeae05bad61778,
+0xbc65b6609cc5e7ff, 0x3feeaf3216b5448c,
+0xbc8dac42a4a38df0, 0x3feeb06a5e0866d9,
+0x3c7bf68359f35f44, 0x3feeb1ae99157736,
+0x3c8b99dd98b1ed84, 0x3feeb2fed0282c8a,
+0xbc93091fa71e3d83, 0x3feeb45b0b91ffc6,
+0xbc7885ad50cbb750, 0x3feeb5c353aa2fe2,
+0xbc5da9b88b6c1e29, 0x3feeb737b0cdc5e5,
+0xbc82d5e85f3e0301, 0x3feeb8b82b5f98e5,
+0xbc6c23f97c90b959, 0x3feeba44cbc8520f,
+0xbc51669428996971, 0x3feebbdd9a7670b3,
+0xbc92434322f4f9aa, 0x3feebd829fde4e50,
+0x3c71f2b2c1c4c014, 0x3feebf33e47a22a2,
+0xbc85ca6cd7668e4b, 0x3feec0f170ca07ba,
+0xbc9294f304f166b6, 0x3feec2bb4d53fe0d,
+0x3c71affc2b91ce27, 0x3feec49182a3f090,
+0xbc8a1e58414c07d3, 0x3feec674194bb8d5,
+0x3c6dd235e10a73bb, 0x3feec86319e32323,
+0xbc79740b58a20091, 0x3feeca5e8d07f29e,
+0xbc87c50422622263, 0x3feecc667b5de565,
+0x3c9165830a2b96c2, 0x3feece7aed8eb8bb,
+0x3c8b1c86e3e231d5, 0x3feed09bec4a2d33,
+0xbc903d5cbe27874b, 0x3feed2c980460ad8,
+0xbc91bbd1d3bcbb15, 0x3feed503b23e255d,
+0x3c5986178980fce0, 0x3feed74a8af46052,
+0x3c90cc319cee31d2, 0x3feed99e1330b358,
+0xbc89472975b1f2a5, 0x3feedbfe53c12e59,
+0x3c8469846e735ab3, 0x3feede6b5579fdbf,
+0x3c7d8157a34b7e7f, 0x3feee0e521356eba,
+0xbc82dfcd978e9db4, 0x3feee36bbfd3f37a,
+0x3c8c8a4e231ebb7d, 0x3feee5ff3a3c2774,
+0x3c8c1a7792cb3387, 0x3feee89f995ad3ad,
+0xbc888c8d11a142e5, 0x3feeeb4ce622f2ff,
+0xbc907b8f4ad1d9fa, 0x3feeee07298db666,
+0x3c889c2ea41433c7, 0x3feef0ce6c9a8952,
+0xbc55c3d956dcaeba, 0x3feef3a2b84f15fb,
+0xbc7274aedac8ff80, 0x3feef68415b749b1,
+0xbc90a40e3da6f640, 0x3feef9728de5593a,
+0x3c85c620ce76df06, 0x3feefc6e29f1c52a,
+0xbc68d6f438ad9334, 0x3feeff76f2fb5e47,
+0xbc8fda52e1b51e41, 0x3fef028cf22749e4,
+0xbc91eee26b588a35, 0x3fef05b030a1064a,
+0xbc32141a7b3e2cd8, 0x3fef08e0b79a6f1f,
+0x3c74ffd70a5fddcd, 0x3fef0c1e904bc1d2,
+0xbc302899507554e5, 0x3fef0f69c3f3a207,
+0xbc91bdfbfa9298ac, 0x3fef12c25bd71e09,
+0xbc80dda2d4c0010c, 0x3fef16286141b33d,
+0x3c736eae30af0cb3, 0x3fef199bdd85529c,
+0xbc8a007daadf8d68, 0x3fef1d1cd9fa652c,
+0x3c8ee3325c9ffd94, 0x3fef20ab5fffd07a,
+0x3c836909391181d3, 0x3fef244778fafb22,
+0x3c84e08fd10959ac, 0x3fef27f12e57d14b,
+0xbc811cd7dbdf9547, 0x3fef2ba88988c933,
+0x3c63cdaf384e1a67, 0x3fef2f6d9406e7b5,
+0xbc7ac28b7bef6621, 0x3fef33405751c4db,
+0x3c676b2c6c921968, 0x3fef3720dcef9069,
+0xbc7030587207b9e1, 0x3fef3b0f2e6d1675,
+0xbc808a1883ccb5d2, 0x3fef3f0b555dc3fa,
+0xbc8cc734592af7fc, 0x3fef43155b5bab74,
+0xbc8fad5d3ffffa6f, 0x3fef472d4a07897c,
+0x3c87752a44f587e8, 0x3fef4b532b08c968,
+0xbc900dae3875a949, 0x3fef4f87080d89f2,
+0x3c85b66fefeef52e, 0x3fef53c8eacaa1d6,
+0x3c74a385a63d07a7, 0x3fef5818dcfba487,
+0x3c5159d9d908a96e, 0x3fef5c76e862e6d3,
+0xbc82919e2040220f, 0x3fef60e316c98398,
+0x3c8c254d16117a68, 0x3fef655d71ff6075,
+0x3c8e5a50d5c192ac, 0x3fef69e603db3285,
+0xbc8d8c329fbd0e03, 0x3fef6e7cd63a8315,
+0x3c843a59ac016b4b, 0x3fef7321f301b460,
+0xbc8ea6e6fbd5f2a6, 0x3fef77d5641c0658,
+0xbc82d52107b43e1f, 0x3fef7c97337b9b5f,
+0xbc63e8e3eab2cbb4, 0x3fef81676b197d17,
+0xbc892ab93b470dc9, 0x3fef864614f5a129,
+0xbc8b7966cd0d2cd9, 0x3fef8b333b16ee12,
+0x3c74b604603a88d3, 0x3fef902ee78b3ff6,
+0xbc776caa4c2ff1cf, 0x3fef953924676d76,
+0x3c83c5ec519d7271, 0x3fef9a51fbc74c83,
+0xbc81d5fc525d9940, 0x3fef9f7977cdb740,
+0xbc8ff7128fd391f0, 0x3fefa4afa2a490da,
+0x3c855cd8aaea3d21, 0x3fefa9f4867cca6e,
+0xbc8dae98e223747d, 0x3fefaf482d8e67f1,
+0x3c8269947c2bed4a, 0x3fefb4aaa2188510,
+0x3c8ec3bc41aa2008, 0x3fefba1bee615a27,
+0xbc83b6137e9afe9e, 0x3fefbf9c1cb6412a,
+0x3c842b94c3a9eb32, 0x3fefc52b376bba97,
+0xbc69fa74878ba7c7, 0x3fefcac948dd7274,
+0x3c8a64a931d185ee, 0x3fefd0765b6e4540,
+0x3c901f3a75ee0efe, 0x3fefd632798844f8,
+0xbc8e37bae43be3ed, 0x3fefdbfdad9cbe14,
+0xbc516a9ce6ed84fa, 0x3fefe1d802243c89,
+0x3c77893b4d91cd9d, 0x3fefe7c1819e90d8,
+0xbc699c7db2effc76, 0x3fefedba3692d514,
+0x3c5305c14160cc89, 0x3feff3c22b8f71f1,
+0x3c64b458677f9840, 0x3feff9d96b2a23d9,
+#elif N == 512
+0x0, 0x3ff0000000000000,
+0xbc75d87ade1f60d5, 0x3feffd8c86da1c0a,
+0xbc84e82fc61851ac, 0x3feffb1afa5abcbf,
+0x3c9bffdaa7ac4bac, 0x3feff8ab5b2cbd11,
+0x3c9b3b4f1a88bf6e, 0x3feff63da9fb3335,
+0x3c75c18e5ae0563a, 0x3feff3d1e77170b4,
+0xbc82985dd8521d32, 0x3feff168143b0281,
+0xbc705b1125cf49a5, 0x3fefef003103b10e,
+0xbc7160139cd8dc5d, 0x3fefec9a3e778061,
+0x3c9f879abbff3f87, 0x3fefea363d42b027,
+0x3c651e617061bfbd, 0x3fefe7d42e11bbcc,
+0x3c9b14003824712a, 0x3fefe57411915a8a,
+0xbc905e7a108766d1, 0x3fefe315e86e7f85,
+0x3c61cbf0f38af658, 0x3fefe0b9b35659d8,
+0x3c845fad437fa426, 0x3fefde5f72f654b1,
+0xbc9a3316383dcbc5, 0x3fefdc0727fc1762,
+0x3c8cd2523567f613, 0x3fefd9b0d3158574,
+0x3c9901c9e0e797fd, 0x3fefd75c74f0bec2,
+0xbc954529642b232f, 0x3fefd50a0e3c1f89,
+0xbc89b3236d111646, 0x3fefd2b99fa6407c,
+0xbc8bce8023f98efa, 0x3fefd06b29ddf6de,
+0xbc8cb191be99b1b0, 0x3fefce1ead925493,
+0x3c8293708ef5c32e, 0x3fefcbd42b72a836,
+0xbc9acb71e83765b7, 0x3fefc98ba42e7d30,
+0x3c60f74e61e6c861, 0x3fefc74518759bc8,
+0x3c5cd3e58b03697e, 0x3fefc50088f8093f,
+0xbc95b9280905b2a4, 0x3fefc2bdf66607e0,
+0xbc8bfb07d4755452, 0x3fefc07d61701716,
+0x3c90a3e45b33d399, 0x3fefbe3ecac6f383,
+0x3c8aedeb3e7b14cd, 0x3fefbc02331b9715,
+0x3c84f31f32c4b7e7, 0x3fefb9c79b1f3919,
+0x3c9a8eb1f3d914b4, 0x3fefb78f03834e52,
+0x3c979aa65d837b6d, 0x3fefb5586cf9890f,
+0xbc85b9eb0402507b, 0x3fefb323d833d93f,
+0x3c9407fb30d06420, 0x3fefb0f145e46c85,
+0xbc93f0f225bbf3ee, 0x3fefaec0b6bdae53,
+0x3c8eb51a92fdeffc, 0x3fefac922b7247f7,
+0xbc9c3fe7282d1784, 0x3fefaa65a4b520ba,
+0xbc9a5d04b3b9911b, 0x3fefa83b23395dec,
+0x3c9c8be44bf4cde8, 0x3fefa612a7b26300,
+0x3c3ebe3d702f9cd1, 0x3fefa3ec32d3d1a2,
+0x3c820c5444c93c44, 0x3fefa1c7c55189c6,
+0xbc937a01f0739546, 0x3fef9fa55fdfa9c5,
+0xbc84c6baeb580d7a, 0x3fef9d8503328e6d,
+0xbc6a033489906e0b, 0x3fef9b66affed31b,
+0x3c8657aa1b0d9f83, 0x3fef994a66f951ce,
+0x3c8b8268b04ef0a5, 0x3fef973028d7233e,
+0x3c62f2c7fd6ee145, 0x3fef9517f64d9ef1,
+0xbc9556522a2fbd0e, 0x3fef9301d0125b51,
+0xbc6b0b2789925e90, 0x3fef90edb6db2dc1,
+0xbc9ac46e44a2ebcc, 0x3fef8edbab5e2ab6,
+0xbc93aad17d197fae, 0x3fef8ccbae51a5c8,
+0xbc5080ef8c4eea55, 0x3fef8abdc06c31cc,
+0xbc989c464a07ad70, 0x3fef88b1e264a0e9,
+0xbc65704e90c9f860, 0x3fef86a814f204ab,
+0xbc72c338fce197f4, 0x3fef84a058cbae1e,
+0xbc91c923b9d5f416, 0x3fef829aaea92de0,
+0xbc6dca724cea0eb6, 0x3fef809717425438,
+0xbc897cea57e46280, 0x3fef7e95934f312e,
+0x3c464770b955d34d, 0x3fef7c962388149e,
+0x3c80d3e3e95c55af, 0x3fef7a98c8a58e51,
+0xbc962811c114424f, 0x3fef789d83606e12,
+0x3c56f01429e2b9d2, 0x3fef76a45471c3c2,
+0x3c8ec58e74904dd4, 0x3fef74ad3c92df73,
+0xbc801b15eaa59348, 0x3fef72b83c7d517b,
+0x3c8d63b0ab2d5bbf, 0x3fef70c554eaea89,
+0x3c6e653b2459034b, 0x3fef6ed48695bbc0,
+0xbc9ca9effbeeac92, 0x3fef6ce5d23816c9,
+0xbc8f1ff055de323d, 0x3fef6af9388c8dea,
+0x3c8bda920de0f6e2, 0x3fef690eba4df41f,
+0x3c92cc7ea345b7dc, 0x3fef672658375d2f,
+0xbc9a597f9a5ff71c, 0x3fef654013041dc2,
+0x3c8b898c3f1353bf, 0x3fef635beb6fcb75,
+0x3c50835b125aa573, 0x3fef6179e2363cf8,
+0x3c957bfb2876ea9e, 0x3fef5f99f8138a1c,
+0x3c8aaa13d61aec1f, 0x3fef5dbc2dc40bf0,
+0xbc96d99c7611eb26, 0x3fef5be084045cd4,
+0x3c8a4f81aa7110bd, 0x3fef5a06fb91588f,
+0x3c8cdc1873af2155, 0x3fef582f95281c6b,
+0xbc6817fd6a313e3e, 0x3fef565a51860746,
+0x3c9aecf73e3a2f60, 0x3fef54873168b9aa,
+0xbc96236af85fd26a, 0x3fef52b6358e15e8,
+0xbc9493684653a131, 0x3fef50e75eb44027,
+0x3c7795eb4523abe7, 0x3fef4f1aad999e82,
+0xbc8fe782cb86389d, 0x3fef4d5022fcd91d,
+0x3c8fe58b91b40095, 0x3fef4b87bf9cda38,
+0xbc98e2899077520a, 0x3fef49c18438ce4d,
+0x3c91ecaa860c614a, 0x3fef47fd7190241e,
+0x3c8a6f4144a6c38d, 0x3fef463b88628cd6,
+0xbc3e45c83ba0bbcb, 0x3fef447bc96ffc18,
+0x3c9120fcd4f59273, 0x3fef42be3578a819,
+0xbc29fd3bea07b4ee, 0x3fef4102cd3d09b9,
+0x3c807a05b0e4047d, 0x3fef3f49917ddc96,
+0x3c87f1c7350e256d, 0x3fef3d9282fc1f27,
+0x3c89b788c188c9b8, 0x3fef3bdda27912d1,
+0x3c420dac6c124f4f, 0x3fef3a2af0b63bff,
+0x3c968efde3a8a894, 0x3fef387a6e756238,
+0xbc99501d09bc09fd, 0x3fef36cc1c78903a,
+0x3c877afbca90ef84, 0x3fef351ffb82140a,
+0x3c73baf864dc8675, 0x3fef33760c547f15,
+0x3c875e18f274487d, 0x3fef31ce4fb2a63f,
+0x3c91b0575c1eaf54, 0x3fef3028c65fa1ff,
+0x3c91512f082876ee, 0x3fef2e85711ece75,
+0xbc90364bc9ce33ab, 0x3fef2ce450b3cb82,
+0x3c80472b981fe7f2, 0x3fef2b4565e27cdd,
+0xbc7548165d85ed32, 0x3fef29a8b16f0a30,
+0x3c9a02f0c7d75ec6, 0x3fef280e341ddf29,
+0x3c7c3b977a68e32c, 0x3fef2675eeb3ab98,
+0xbc96b87b3f71085e, 0x3fef24dfe1f56381,
+0xbc93a255f697ecfe, 0x3fef234c0ea83f36,
+0xbc803297e78260bf, 0x3fef21ba7591bb70,
+0x3c8d2d19edc1e550, 0x3fef202b17779965,
+0x3c82f7e16d09ab31, 0x3fef1e9df51fdee1,
+0xbc76b2173113dd8c, 0x3fef1d130f50d65c,
+0xbc95b77e5ccd9fbf, 0x3fef1b8a66d10f13,
+0x3c811aa5f853590b, 0x3fef1a03fc675d1f,
+0xbc3d219b1a6fbffa, 0x3fef187fd0dad990,
+0x3c61d61a34c8aa02, 0x3fef16fde4f2e280,
+0xbc91e75c40b4251e, 0x3fef157e39771b2f,
+0xbc91f892bf6b286d, 0x3fef1400cf2f6c18,
+0x3c8b3782720c0ab4, 0x3fef1285a6e4030b,
+0x3c7590c65c20e680, 0x3fef110cc15d5346,
+0x3c98a911f1f7785a, 0x3fef0f961f641589,
+0x3c86fe320b5c1e9d, 0x3fef0e21c1c14833,
+0x3c6e149289cecb8f, 0x3fef0cafa93e2f56,
+0xbc903cd8b2f25790, 0x3fef0b3fd6a454d2,
+0xbc61e7c998db7dbb, 0x3fef09d24abd886b,
+0x3c7b3bf786a54a87, 0x3fef08670653dfe4,
+0x3c834d754db0abb6, 0x3fef06fe0a31b715,
+0x3c74bb6c41732885, 0x3fef05975721b004,
+0x3c85425c11faadf4, 0x3fef0432edeeb2fd,
+0xbc99d7399abb9a8b, 0x3fef02d0cf63eeac,
+0x3c864201e2ac744c, 0x3fef0170fc4cd831,
+0xbc5451d60c6ac9eb, 0x3fef001375752b40,
+0xbc979517a03e2847, 0x3feefeb83ba8ea32,
+0x3c8787a210ceafd9, 0x3feefd5f4fb45e20,
+0x3c8fdd395dd3f84a, 0x3feefc08b26416ff,
+0xbc888d1e4629943d, 0x3feefab46484ebb4,
+0xbc800e2a46da4bee, 0x3feef96266e3fa2d,
+0xbc93369c544088b6, 0x3feef812ba4ea77d,
+0xbc86a3803b8e5b04, 0x3feef6c55f929ff1,
+0x3c85373ce4eb6dfb, 0x3feef57a577dd72b,
+0xbc87430803972b34, 0x3feef431a2de883b,
+0x3c83adec8265a67f, 0x3feef2eb428335b4,
+0xbc924aedcc4b5068, 0x3feef1a7373aa9cb,
+0xbc835388bcac6bc5, 0x3feef06581d3f669,
+0xbc954de30ae02d94, 0x3feeef26231e754a,
+0x3c727cdb4e4b6640, 0x3feeede91be9c811,
+0xbc9907f81b512d8e, 0x3feeecae6d05d866,
+0x3c86c2696a26af35, 0x3feeeb761742d808,
+0xbc94f2487e1c03ec, 0x3feeea401b7140ef,
+0x3c888f6ff06b979a, 0x3feee90c7a61d55b,
+0xbc71d1e83e9436d2, 0x3feee7db34e59ff7,
+0xbc89d5efaabc2030, 0x3feee6ac4bcdf3ea,
+0x3c914a5432fcb2f4, 0x3feee57fbfec6cf4,
+0xbc76b8867f91c9d6, 0x3feee4559212ef89,
+0xbc991919b3ce1b15, 0x3feee32dc313a8e5,
+0x3c94c9c0b5157fe6, 0x3feee20853c10f28,
+0x3c79c3bba5562a2f, 0x3feee0e544ede173,
+0xbc62455345b51c8e, 0x3feedfc4976d27fa,
+0x3c859f48a72a4c6d, 0x3feedea64c123422,
+0xbc93331de45477d0, 0x3feedd8a63b0a09b,
+0xbc85a71612e21658, 0x3feedc70df1c5175,
+0xbc95f84d39b39b16, 0x3feedb59bf29743f,
+0xbc9312607a28698a, 0x3feeda4504ac801c,
+0xbc72ba4dc7c4d562, 0x3feed932b07a35df,
+0x3c86421f6f1d24d6, 0x3feed822c367a024,
+0xbc844f25dc02691f, 0x3feed7153e4a136a,
+0xbc58a78f4817895b, 0x3feed60a21f72e2a,
+0xbc888d328eb9b501, 0x3feed5016f44d8f5,
+0xbc9348a6815fce65, 0x3feed3fb2709468a,
+0x3c7f0bec42ddb15a, 0x3feed2f74a1af3f1,
+0xbc7c2c9b67499a1b, 0x3feed1f5d950a897,
+0xbc615f0a2b9cd452, 0x3feed0f6d5817663,
+0x3c835c43984d9871, 0x3feecffa3f84b9d4,
+0xbc8c2e465a919e1d, 0x3feecf0018321a1a,
+0x3c4363ed60c2ac11, 0x3feece086061892d,
+0xbc865dfd02bd08f1, 0x3feecd1318eb43ec,
+0xbc632afc8d9473a0, 0x3feecc2042a7d232,
+0xbc8e68cec89b1762, 0x3feecb2fde7006f4,
+0x3c9666093b0664ef, 0x3feeca41ed1d0057,
+0xbc48ae858eb682ca, 0x3feec9566f8827d0,
+0xbc95fc5e44de020e, 0x3feec86d668b3237,
+0x3c5dd71277c0915f, 0x3feec786d3001fe5,
+0x3c6ecce1daa10379, 0x3feec6a2b5c13cd0,
+0x3c92001325ecd7fb, 0x3feec5c10fa920a1,
+0xbc7ea0148327c42f, 0x3feec4e1e192aed2,
+0x3c65ace6e2870332, 0x3feec4052c5916c4,
+0x3c93ff8e3f0f1230, 0x3feec32af0d7d3de,
+0xbc9595c55690ffaf, 0x3feec2532feaada6,
+0xbc7a843ad1a88022, 0x3feec17dea6db7d7,
+0xbc8b401ba9fb5199, 0x3feec0ab213d5283,
+0x3c7690cebb7aafb0, 0x3feebfdad5362a27,
+0x3c6df82bf324cc57, 0x3feebf0d073537ca,
+0x3c892ca3bf144e63, 0x3feebe41b817c114,
+0x3c97cae38641c7bb, 0x3feebd78e8bb586b,
+0x3c931dbdeb54e077, 0x3feebcb299fddd0d,
+0x3c62d80c5c4a2b67, 0x3feebbeeccbd7b2a,
+0xbc902c99b04aa8b0, 0x3feebb2d81d8abff,
+0x3c8f39c10d12eaf0, 0x3feeba6eba2e35f0,
+0xbc8f94340071a38e, 0x3feeb9b2769d2ca7,
+0xbc80b582d74a55d9, 0x3feeb8f8b804f127,
+0x3c73e34f67e67118, 0x3feeb8417f4531ee,
+0xbc6b4e327ff434ca, 0x3feeb78ccd3deb0d,
+0xbc87deccdc93a349, 0x3feeb6daa2cf6642,
+0xbc592dca38593e20, 0x3feeb62b00da3b14,
+0xbc75a3b1197ba0f0, 0x3feeb57de83f4eef,
+0xbc85daca9994833e, 0x3feeb4d359dfd53d,
+0xbc78dec6bd0f385f, 0x3feeb42b569d4f82,
+0xbc980b4321bc6dae, 0x3feeb385df598d78,
+0x3c81bd2888075068, 0x3feeb2e2f4f6ad27,
+0xbc8390afec5241c5, 0x3feeb24298571b06,
+0xbc861246ec7b5cf6, 0x3feeb1a4ca5d920f,
+0x3c8f15cdafe7d586, 0x3feeb1098bed1bdf,
+0xbc896be8ae89ef8f, 0x3feeb070dde910d2,
+0xbc910aa91ae9b67f, 0x3feeafdac1351819,
+0x3c93350518fdd78e, 0x3feeaf4736b527da,
+0x3c957e1b67462375, 0x3feeaeb63f4d854c,
+0xbc88e6ac90348602, 0x3feeae27dbe2c4cf,
+0x3c8124d5051552a7, 0x3feead9c0d59ca07,
+0x3c7b98b72f8a9b05, 0x3feead12d497c7fd,
+0xbc3ca103952ecf1f, 0x3feeac8c32824135,
+0xbc91af7f1365c3ac, 0x3feeac0827ff07cc,
+0x3c773345c02a4fd6, 0x3feeab86b5f43d92,
+0x3c9063e1e21c5409, 0x3feeab07dd485429,
+0xbc909d2a0fce20f2, 0x3feeaa8b9ee20d1e,
+0xbc943a3540d1898a, 0x3feeaa11fba87a03,
+0xbc924f2cb4f81746, 0x3feea99af482fc8f,
+0x3c34c7855019c6ea, 0x3feea9268a5946b7,
+0xbc943592a0a9846b, 0x3feea8b4be135acc,
+0xbc951f58ddaa8090, 0x3feea84590998b93,
+0xbc956bc85d444f4f, 0x3feea7d902d47c65,
+0x3c9432e62b64c035, 0x3feea76f15ad2148,
+0x3c914d1e4218319f, 0x3feea707ca0cbf0f,
+0xbc82e1648e50a17c, 0x3feea6a320dceb71,
+0x3c971c93709313f4, 0x3feea6411b078d26,
+0xbc8ce44a6199769f, 0x3feea5e1b976dc09,
+0x3c7f88303b60d222, 0x3feea584fd15612a,
+0x3c95f30eda98a575, 0x3feea52ae6cdf6f4,
+0x3c70125ca18d4b5b, 0x3feea4d3778bc944,
+0xbc8c33c53bef4da8, 0x3feea47eb03a5585,
+0x3c9592ea73798b11, 0x3feea42c91c56acd,
+0x3c917ecda8a72159, 0x3feea3dd1d1929fd,
+0xbc9371d6d7d75739, 0x3feea390532205d8,
+0xbc845378892be9ae, 0x3feea34634ccc320,
+0xbc8ac05fd996f807, 0x3feea2fec30678b7,
+0xbc9345f3cee1ae6e, 0x3feea2b9febc8fb7,
+0xbc91f5067d03653a, 0x3feea277e8dcc390,
+0xbc93cedd78565858, 0x3feea23882552225,
+0x3c917339c86ce3ad, 0x3feea1fbcc140be7,
+0xbc85c33fdf910406, 0x3feea1c1c70833f6,
+0xbc77e66065ba2500, 0x3feea18a7420a036,
+0x3c5710aa807e1964, 0x3feea155d44ca973,
+0x3c964c827ee6b49a, 0x3feea123e87bfb7a,
+0x3c81079ab5789604, 0x3feea0f4b19e9538,
+0xbc928311a3c73480, 0x3feea0c830a4c8d4,
+0xbc93b3efbf5e2228, 0x3feea09e667f3bcd,
+0x3c882c79e185e981, 0x3feea077541ee718,
+0x3c727df161cd7778, 0x3feea052fa75173e,
+0xbc8b48cea80b043b, 0x3feea0315a736c75,
+0xbc6a12ad8734b982, 0x3feea012750bdabf,
+0xbc4f4863bc8e5180, 0x3fee9ff64b30aa09,
+0x3c93f9924a05b767, 0x3fee9fdcddd47645,
+0x3c954835dd4b7548, 0x3fee9fc62dea2f8a,
+0xbc6367efb86da9ee, 0x3fee9fb23c651a2f,
+0xbc8bf41f59b59f8a, 0x3fee9fa10a38cee8,
+0xbc87557939a8b5ef, 0x3fee9f9298593ae5,
+0xbc8f652fde52775c, 0x3fee9f86e7ba9fef,
+0xbc80dc3d54e08851, 0x3fee9f7df9519484,
+0xbc7b0300defbcf98, 0x3fee9f77ce1303f6,
+0x3c51ed2f56fa9d1a, 0x3fee9f7466f42e87,
+0xbc89dab646035dc0, 0x3fee9f73c4eaa988,
+0xbc781f647e5a3ecf, 0x3fee9f75e8ec5f74,
+0xbc91f0c230588dde, 0x3fee9f7ad3ef9011,
+0xbc88e67a9006c909, 0x3fee9f8286ead08a,
+0x3c9106450507a28c, 0x3fee9f8d02d50b8f,
+0xbc86ee4ac08b7db0, 0x3fee9f9a48a58174,
+0xbc9129729a10f3a0, 0x3fee9faa5953c849,
+0x3c86597566977ac8, 0x3fee9fbd35d7cbfd,
+0x3c781a70a5124f67, 0x3fee9fd2df29ce7c,
+0xbc8619321e55e68a, 0x3fee9feb564267c9,
+0x3c941626ea62646d, 0x3feea0069c1a861d,
+0x3c92c0b7028a5c3a, 0x3feea024b1ab6e09,
+0xbc940b9f54365b7c, 0x3feea04597eeba8f,
+0x3c909ccb5e09d4d3, 0x3feea0694fde5d3f,
+0x3c873455e0e826c1, 0x3feea08fda749e5d,
+0x3c8a30faf49cc78c, 0x3feea0b938ac1cf6,
+0x3c94f006ad874e3e, 0x3feea0e56b7fcf03,
+0xbc7b32dcb94da51d, 0x3feea11473eb0187,
+0xbc8f6d693d0973bb, 0x3feea14652e958aa,
+0xbc92dad3519d7b5b, 0x3feea17b0976cfdb,
+0x3c58c5ee2b7e7848, 0x3feea1b2988fb9ec,
+0x3c94ecfd5467c06b, 0x3feea1ed0130c132,
+0xbc88b25e045d207b, 0x3feea22a4456e7a3,
+0x3c87d51410fd15c2, 0x3feea26a62ff86f0,
+0xbc69cb3314060ca7, 0x3feea2ad5e2850ac,
+0x3c65ebe1abd66c55, 0x3feea2f336cf4e62,
+0x3c87a0b15d19e0bb, 0x3feea33bedf2e1b9,
+0xbc760a3629969871, 0x3feea3878491c491,
+0x3c94aa7212bfa73c, 0x3feea3d5fbab091f,
+0xbc88a1c52fb3cf42, 0x3feea427543e1a12,
+0xbc81e688272a8a12, 0x3feea47b8f4abaa9,
+0x3c8b18c6e3fdef5d, 0x3feea4d2add106d9,
+0x3c4ab7b7112ec9d5, 0x3feea52cb0d1736a,
+0xbc9369b6f13b3734, 0x3feea589994cce13,
+0x3c8a1e274eed4476, 0x3feea5e968443d9a,
+0x3c90ec1ddcb1390a, 0x3feea64c1eb941f7,
+0x3c94a533a59324da, 0x3feea6b1bdadb46d,
+0xbc805e843a19ff1e, 0x3feea71a4623c7ad,
+0x3c7a56d2760d087d, 0x3feea785b91e07f1,
+0xbc522cea4f3afa1e, 0x3feea7f4179f5b21,
+0x3c91682c1c6e8b05, 0x3feea86562ab00ec,
+0xbc94d450d872576e, 0x3feea8d99b4492ed,
+0x3c89ea99cf7a9591, 0x3feea950c27004c2,
+0x3c7c88549b958471, 0x3feea9cad931a436,
+0xbc59e57d8f92ff8e, 0x3feeaa47e08e1957,
+0x3c90ad675b0e8a00, 0x3feeaac7d98a6699,
+0x3c909b176e05a9cd, 0x3feeab4ac52be8f7,
+0x3c931143962f7877, 0x3feeabd0a478580f,
+0x3c711607f1952c95, 0x3feeac597875c644,
+0x3c8db72fc1f0eab4, 0x3feeace5422aa0db,
+0x3c869608f0f86431, 0x3feead74029db01e,
+0x3c93e9e96f112479, 0x3feeae05bad61778,
+0xbc7f1ced15c5c5c0, 0x3feeae9a6bdb5598,
+0xbc65b6609cc5e7ff, 0x3feeaf3216b5448c,
+0x3c614b97be3f7b4e, 0x3feeafccbc6c19e6,
+0xbc8dac42a4a38df0, 0x3feeb06a5e0866d9,
+0x3c81c1701c359530, 0x3feeb10afc931857,
+0x3c7bf68359f35f44, 0x3feeb1ae99157736,
+0xbc8edb1bf6809287, 0x3feeb2553499284b,
+0x3c8b99dd98b1ed84, 0x3feeb2fed0282c8a,
+0xbc8ba58ce7a736d3, 0x3feeb3ab6ccce12c,
+0xbc93091fa71e3d83, 0x3feeb45b0b91ffc6,
+0xbc93fc025e1db9ce, 0x3feeb50dad829e70,
+0xbc7885ad50cbb750, 0x3feeb5c353aa2fe2,
+0xbc8d737c7d71382e, 0x3feeb67bff148396,
+0xbc5da9b88b6c1e29, 0x3feeb737b0cdc5e5,
+0x3c6ae88c43905293, 0x3feeb7f669e2802b,
+0xbc82d5e85f3e0301, 0x3feeb8b82b5f98e5,
+0xbc93d1f7661fe51b, 0x3feeb97cf65253d1,
+0xbc6c23f97c90b959, 0x3feeba44cbc8520f,
+0x3c651b68797ffc1c, 0x3feebb0faccf9243,
+0xbc51669428996971, 0x3feebbdd9a7670b3,
+0x3c54579c5ceed70b, 0x3feebcae95cba768,
+0xbc92434322f4f9aa, 0x3feebd829fde4e50,
+0x3c87298413381667, 0x3feebe59b9bddb5b,
+0x3c71f2b2c1c4c014, 0x3feebf33e47a22a2,
+0xbc905000be64e965, 0x3feec01121235681,
+0xbc85ca6cd7668e4b, 0x3feec0f170ca07ba,
+0xbc89fb12e3454b73, 0x3feec1d4d47f2598,
+0xbc9294f304f166b6, 0x3feec2bb4d53fe0d,
+0x3c7be2a03697693b, 0x3feec3a4dc5a3dd3,
+0x3c71affc2b91ce27, 0x3feec49182a3f090,
+0x3c90622b15810eea, 0x3feec581414380f2,
+0xbc8a1e58414c07d3, 0x3feec674194bb8d5,
+0x3be9a5ecc875d327, 0x3feec76a0bcfc15e,
+0x3c6dd235e10a73bb, 0x3feec86319e32323,
+0x3c88ea486a3350ef, 0x3feec95f4499c647,
+0xbc79740b58a20091, 0x3feeca5e8d07f29e,
+0xbc7a2ee551d4c40f, 0x3feecb60f4424fcb,
+0xbc87c50422622263, 0x3feecc667b5de565,
+0x3c89c31f7e38028b, 0x3feecd6f23701b15,
+0x3c9165830a2b96c2, 0x3feece7aed8eb8bb,
+0xbc5fac13f4e005a3, 0x3feecf89dacfe68c,
+0x3c8b1c86e3e231d5, 0x3feed09bec4a2d33,
+0x3c7d8aced7162e89, 0x3feed1b1231475f7,
+0xbc903d5cbe27874b, 0x3feed2c980460ad8,
+0xbc848f50cea7269f, 0x3feed3e504f696b1,
+0xbc91bbd1d3bcbb15, 0x3feed503b23e255d,
+0x3c821eb9a08a0542, 0x3feed625893523d4,
+0x3c5986178980fce0, 0x3feed74a8af46052,
+0xbc6133a953131cfd, 0x3feed872b8950a73,
+0x3c90cc319cee31d2, 0x3feed99e1330b358,
+0x3c89e95e6f4a0ae4, 0x3feedacc9be14dca,
+0xbc89472975b1f2a5, 0x3feedbfe53c12e59,
+0xbc90260cf07cb311, 0x3feedd333beb0b7e,
+0x3c8469846e735ab3, 0x3feede6b5579fdbf,
+0x3c1bca400a7b939d, 0x3feedfa6a1897fd2,
+0x3c7d8157a34b7e7f, 0x3feee0e521356eba,
+0x3c9140bc34dfc19f, 0x3feee226d59a09ee,
+0xbc82dfcd978e9db4, 0x3feee36bbfd3f37a,
+0xbc8c9b1da461ab87, 0x3feee4b3e100301e,
+0x3c8c8a4e231ebb7d, 0x3feee5ff3a3c2774,
+0x3c8c115f23ebea8e, 0x3feee74dcca5a413,
+0x3c8c1a7792cb3387, 0x3feee89f995ad3ad,
+0xbc6dcab99f23f84e, 0x3feee9f4a17a4735,
+0xbc888c8d11a142e5, 0x3feeeb4ce622f2ff,
+0x3c60a43e8b7e4bfe, 0x3feeeca868742ee4,
+0xbc907b8f4ad1d9fa, 0x3feeee07298db666,
+0x3c915b1397075f04, 0x3feeef692a8fa8cd,
+0x3c889c2ea41433c7, 0x3feef0ce6c9a8952,
+0xbc839f7a1f04d2b0, 0x3feef236f0cf3f3a,
+0xbc55c3d956dcaeba, 0x3feef3a2b84f15fb,
+0xbc86a510f31e13e6, 0x3feef511c43bbd62,
+0xbc7274aedac8ff80, 0x3feef68415b749b1,
+0xbc92887ea88e7340, 0x3feef7f9ade433c6,
+0xbc90a40e3da6f640, 0x3feef9728de5593a,
+0xbc6e57ac604759ba, 0x3feefaeeb6ddfc87,
+0x3c85c620ce76df06, 0x3feefc6e29f1c52a,
+0x3c8e6c6db4f83226, 0x3feefdf0e844bfc6,
+0xbc68d6f438ad9334, 0x3feeff76f2fb5e47,
+0xbc8d1bf10460dba0, 0x3fef01004b3a7804,
+0xbc8fda52e1b51e41, 0x3fef028cf22749e4,
+0x3c8e5d80813dddfc, 0x3fef041ce8e77680,
+0xbc91eee26b588a35, 0x3fef05b030a1064a,
+0x3c8caff9640f2dcb, 0x3fef0746ca7a67a7,
+0xbc32141a7b3e2cd8, 0x3fef08e0b79a6f1f,
+0x3c7a77557fd62db3, 0x3fef0a7df9285775,
+0x3c74ffd70a5fddcd, 0x3fef0c1e904bc1d2,
+0xbc651ba6128db749, 0x3fef0dc27e2cb5e5,
+0xbc302899507554e5, 0x3fef0f69c3f3a207,
+0xbc7c0ffefdc5e251, 0x3fef111462c95b60,
+0xbc91bdfbfa9298ac, 0x3fef12c25bd71e09,
+0xbc8b6cd058bfd6fa, 0x3fef1473b0468d30,
+0xbc80dda2d4c0010c, 0x3fef16286141b33d,
+0x3c923759b8aca76d, 0x3fef17e06ff301f4,
+0x3c736eae30af0cb3, 0x3fef199bdd85529c,
+0xbc895498a73dac7d, 0x3fef1b5aab23e61e,
+0xbc8a007daadf8d68, 0x3fef1d1cd9fa652c,
+0x3c851de924583108, 0x3fef1ee26b34e065,
+0x3c8ee3325c9ffd94, 0x3fef20ab5fffd07a,
+0xbc8c5fe4051ba06c, 0x3fef2277b9881650,
+0x3c836909391181d3, 0x3fef244778fafb22,
+0xbc6d1816c0a9ac07, 0x3fef261a9f8630ad,
+0x3c84e08fd10959ac, 0x3fef27f12e57d14b,
+0xbc7af5c67c4e8235, 0x3fef29cb269e601f,
+0xbc811cd7dbdf9547, 0x3fef2ba88988c933,
+0xbc8304ef0045d575, 0x3fef2d89584661a1,
+0x3c63cdaf384e1a67, 0x3fef2f6d9406e7b5,
+0x3c8725f94f910375, 0x3fef31553dfa8313,
+0xbc7ac28b7bef6621, 0x3fef33405751c4db,
+0x3c7b53e99f9191e8, 0x3fef352ee13da7cb,
+0x3c676b2c6c921968, 0x3fef3720dcef9069,
+0xbc810a79e6d7e2b8, 0x3fef39164b994d23,
+0xbc7030587207b9e1, 0x3fef3b0f2e6d1675,
+0x3c840635f6d2a9c0, 0x3fef3d0b869d8f0f,
+0xbc808a1883ccb5d2, 0x3fef3f0b555dc3fa,
+0x3c549eeef9ec910c, 0x3fef410e9be12cb9,
+0xbc8cc734592af7fc, 0x3fef43155b5bab74,
+0xbc8335827ffb9dce, 0x3fef451f95018d17,
+0xbc8fad5d3ffffa6f, 0x3fef472d4a07897c,
+0x3c645563980ef762, 0x3fef493e7ba2c38c,
+0x3c87752a44f587e8, 0x3fef4b532b08c968,
+0xbc8cd0205eb2aab2, 0x3fef4d6b596f948c,
+0xbc900dae3875a949, 0x3fef4f87080d89f2,
+0xbc8aab80ceab2b4a, 0x3fef51a638197a3c,
+0x3c85b66fefeef52e, 0x3fef53c8eacaa1d6,
+0xbc8f870f40a8ba1b, 0x3fef55ef2158a91f,
+0x3c74a385a63d07a7, 0x3fef5818dcfba487,
+0x3c83c119f18464c5, 0x3fef5a461eec14be,
+0x3c5159d9d908a96e, 0x3fef5c76e862e6d3,
+0xbc5a628c2be4e7c7, 0x3fef5eab3a99745b,
+0xbc82919e2040220f, 0x3fef60e316c98398,
+0xbc72550d76be719a, 0x3fef631e7e2d479d,
+0x3c8c254d16117a68, 0x3fef655d71ff6075,
+0xbc82090274667d12, 0x3fef679ff37adb4a,
+0x3c8e5a50d5c192ac, 0x3fef69e603db3285,
+0x3c75f7d28150cac4, 0x3fef6c2fa45c4dfd,
+0xbc8d8c329fbd0e03, 0x3fef6e7cd63a8315,
+0x3c890de9296f4cd1, 0x3fef70cd9ab294e4,
+0x3c843a59ac016b4b, 0x3fef7321f301b460,
+0x3c832ff9978b34bc, 0x3fef7579e065807d,
+0xbc8ea6e6fbd5f2a6, 0x3fef77d5641c0658,
+0xbc7303b63dda1980, 0x3fef7a347f63c159,
+0xbc82d52107b43e1f, 0x3fef7c97337b9b5f,
+0xbc81f2ba385f2f95, 0x3fef7efd81a2ece1,
+0xbc63e8e3eab2cbb4, 0x3fef81676b197d17,
+0x3c768d9144ae12fc, 0x3fef83d4f11f8220,
+0xbc892ab93b470dc9, 0x3fef864614f5a129,
+0x3c853687f542403b, 0x3fef88bad7dcee90,
+0xbc8b7966cd0d2cd9, 0x3fef8b333b16ee12,
+0xbc736ed2de40b407, 0x3fef8daf3fe592e8,
+0x3c74b604603a88d3, 0x3fef902ee78b3ff6,
+0xbc614ef56c770f3b, 0x3fef92b2334ac7ee,
+0xbc776caa4c2ff1cf, 0x3fef953924676d76,
+0x3c8df7d1353d8e88, 0x3fef97c3bc24e350,
+0x3c83c5ec519d7271, 0x3fef9a51fbc74c83,
+0xbc850bed64091b8a, 0x3fef9ce3e4933c7e,
+0xbc81d5fc525d9940, 0x3fef9f7977cdb740,
+0x3c89d852381c317f, 0x3fefa212b6bc3181,
+0xbc8ff7128fd391f0, 0x3fefa4afa2a490da,
+0x3c68a00e3cca04c4, 0x3fefa7503ccd2be5,
+0x3c855cd8aaea3d21, 0x3fefa9f4867cca6e,
+0xbc5a1f25ce94cae7, 0x3fefac9c80faa594,
+0xbc8dae98e223747d, 0x3fefaf482d8e67f1,
+0xbc6fb5f3ee307976, 0x3fefb1f78d802dc2,
+0x3c8269947c2bed4a, 0x3fefb4aaa2188510,
+0x3c737e8ae802b851, 0x3fefb7616ca06dd6,
+0x3c8ec3bc41aa2008, 0x3fefba1bee615a27,
+0x3c875119560e34af, 0x3fefbcda28a52e59,
+0xbc83b6137e9afe9e, 0x3fefbf9c1cb6412a,
+0xbc7431c3840929c6, 0x3fefc261cbdf5be7,
+0x3c842b94c3a9eb32, 0x3fefc52b376bba97,
+0xbc8cb472d2e86b99, 0x3fefc7f860a70c22,
+0xbc69fa74878ba7c7, 0x3fefcac948dd7274,
+0x3c83f5df2fde16a8, 0x3fefcd9df15b82ac,
+0x3c8a64a931d185ee, 0x3fefd0765b6e4540,
+0x3c8eef18336b62e3, 0x3fefd35288633625,
+0x3c901f3a75ee0efe, 0x3fefd632798844f8,
+0x3c80d23f87b50a2a, 0x3fefd916302bd526,
+0xbc8e37bae43be3ed, 0x3fefdbfdad9cbe14,
+0x3c8302dee657c8e6, 0x3fefdee8f32a4b45,
+0xbc516a9ce6ed84fa, 0x3fefe1d802243c89,
+0xbc7b0caa080df170, 0x3fefe4cadbdac61d,
+0x3c77893b4d91cd9d, 0x3fefe7c1819e90d8,
+0x3c7617a9f2fd24e5, 0x3fefeabbf4c0ba54,
+0xbc699c7db2effc76, 0x3fefedba3692d514,
+0x3c75f103b8fd5ca7, 0x3feff0bc4866e8ad,
+0x3c5305c14160cc89, 0x3feff3c22b8f71f1,
+0x3c8e70b094fa075a, 0x3feff6cbe15f6314,
+0x3c64b458677f9840, 0x3feff9d96b2a23d9,
+0xbc72ec9a3e5d680a, 0x3feffceaca4391b6,
+#endif
+},
+};
diff --git a/libc/AOR_v20.02/math/expf.c b/libc/AOR_v20.02/math/expf.c
new file mode 100644 (file)
index 0000000..035cb45
--- /dev/null
@@ -0,0 +1,92 @@
+/*
+ * Single-precision e^x function.
+ *
+ * Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+ * See https://llvm.org/LICENSE.txt for license information.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include <math.h>
+#include <stdint.h>
+#include "math_config.h"
+
+/*
+EXP2F_TABLE_BITS = 5
+EXP2F_POLY_ORDER = 3
+
+ULP error: 0.502 (nearest rounding.)
+Relative error: 1.69 * 2^-34 in [-ln2/64, ln2/64] (before rounding.)
+Wrong count: 170635 (all nearest rounding wrong results with fma.)
+Non-nearest ULP error: 1 (rounded ULP error)
+*/
+
+#define N (1 << EXP2F_TABLE_BITS)
+#define InvLn2N __exp2f_data.invln2_scaled
+#define T __exp2f_data.tab
+#define C __exp2f_data.poly_scaled
+
+static inline uint32_t
+top12 (float x)
+{
+  return asuint (x) >> 20;
+}
+
+float
+expf (float x)
+{
+  uint32_t abstop;
+  uint64_t ki, t;
+  /* double_t for better performance on targets with FLT_EVAL_METHOD==2.  */
+  double_t kd, xd, z, r, r2, y, s;
+
+  xd = (double_t) x;
+  abstop = top12 (x) & 0x7ff;
+  if (unlikely (abstop >= top12 (88.0f)))
+    {
+      /* |x| >= 88 or x is nan.  */
+      if (asuint (x) == asuint (-INFINITY))
+       return 0.0f;
+      if (abstop >= top12 (INFINITY))
+       return x + x;
+      if (x > 0x1.62e42ep6f) /* x > log(0x1p128) ~= 88.72 */
+       return __math_oflowf (0);
+      if (x < -0x1.9fe368p6f) /* x < log(0x1p-150) ~= -103.97 */
+       return __math_uflowf (0);
+#if WANT_ERRNO_UFLOW
+      if (x < -0x1.9d1d9ep6f) /* x < log(0x1p-149) ~= -103.28 */
+       return __math_may_uflowf (0);
+#endif
+    }
+
+  /* x*N/Ln2 = k + r with r in [-1/2, 1/2] and int k.  */
+  z = InvLn2N * xd;
+
+  /* Round and convert z to int, the result is in [-150*N, 128*N] and
+     ideally nearest int is used, otherwise the magnitude of r can be
+     bigger which gives larger approximation error.  */
+#if TOINT_INTRINSICS
+  kd = roundtoint (z);
+  ki = converttoint (z);
+#else
+# define SHIFT __exp2f_data.shift
+  kd = eval_as_double (z + SHIFT);
+  ki = asuint64 (kd);
+  kd -= SHIFT;
+#endif
+  r = z - kd;
+
+  /* exp(x) = 2^(k/N) * 2^(r/N) ~= s * (C0*r^3 + C1*r^2 + C2*r + 1) */
+  t = T[ki % N];
+  t += ki << (52 - EXP2F_TABLE_BITS);
+  s = asdouble (t);
+  z = C[0] * r + C[1];
+  r2 = r * r;
+  y = C[2] * r + 1;
+  y = z * r2 + y;
+  y = y * s;
+  return eval_as_float (y);
+}
+#if USE_GLIBC_ABI
+strong_alias (expf, __expf_finite)
+hidden_alias (expf, __ieee754_expf)
+#endif
diff --git a/libc/AOR_v20.02/math/include/mathlib.h b/libc/AOR_v20.02/math/include/mathlib.h
new file mode 100644 (file)
index 0000000..4765ff4
--- /dev/null
@@ -0,0 +1,101 @@
+/*
+ * Public API.
+ *
+ * Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+ * See https://llvm.org/LICENSE.txt for license information.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef _MATHLIB_H
+#define _MATHLIB_H
+
+float expf (float);
+float exp2f (float);
+float logf (float);
+float log2f (float);
+float powf (float, float);
+float sinf (float);
+float cosf (float);
+void sincosf (float, float*, float*);
+
+double exp (double);
+double exp2 (double);
+double log (double);
+double log2 (double);
+double pow (double, double);
+
+/* Scalar functions using the vector algorithm with identical result.  */
+float __s_sinf (float);
+float __s_cosf (float);
+float __s_expf (float);
+float __s_expf_1u (float);
+float __s_exp2f (float);
+float __s_exp2f_1u (float);
+float __s_logf (float);
+float __s_powf (float, float);
+double __s_sin (double);
+double __s_cos (double);
+double __s_exp (double);
+double __s_log (double);
+double __s_pow (double, double);
+
+#if __aarch64__
+#if __GNUC__ >= 5
+typedef __Float32x4_t __f32x4_t;
+typedef __Float64x2_t __f64x2_t;
+#elif __clang_major__*100+__clang_minor__ >= 305
+typedef __attribute__((__neon_vector_type__(4))) float __f32x4_t;
+typedef __attribute__((__neon_vector_type__(2))) double __f64x2_t;
+#else
+#error Unsupported compiler
+#endif
+
+/* Vector functions following the base PCS.  */
+__f32x4_t __v_sinf (__f32x4_t);
+__f32x4_t __v_cosf (__f32x4_t);
+__f32x4_t __v_expf (__f32x4_t);
+__f32x4_t __v_expf_1u (__f32x4_t);
+__f32x4_t __v_exp2f (__f32x4_t);
+__f32x4_t __v_exp2f_1u (__f32x4_t);
+__f32x4_t __v_logf (__f32x4_t);
+__f32x4_t __v_powf (__f32x4_t, __f32x4_t);
+__f64x2_t __v_sin (__f64x2_t);
+__f64x2_t __v_cos (__f64x2_t);
+__f64x2_t __v_exp (__f64x2_t);
+__f64x2_t __v_log (__f64x2_t);
+__f64x2_t __v_pow (__f64x2_t, __f64x2_t);
+
+#if __GNUC__ >= 9 || __clang_major__ >= 8
+#define __vpcs __attribute__((__aarch64_vector_pcs__))
+
+/* Vector functions following the vector PCS.  */
+__vpcs __f32x4_t __vn_sinf (__f32x4_t);
+__vpcs __f32x4_t __vn_cosf (__f32x4_t);
+__vpcs __f32x4_t __vn_expf (__f32x4_t);
+__vpcs __f32x4_t __vn_expf_1u (__f32x4_t);
+__vpcs __f32x4_t __vn_exp2f (__f32x4_t);
+__vpcs __f32x4_t __vn_exp2f_1u (__f32x4_t);
+__vpcs __f32x4_t __vn_logf (__f32x4_t);
+__vpcs __f32x4_t __vn_powf (__f32x4_t, __f32x4_t);
+__vpcs __f64x2_t __vn_sin (__f64x2_t);
+__vpcs __f64x2_t __vn_cos (__f64x2_t);
+__vpcs __f64x2_t __vn_exp (__f64x2_t);
+__vpcs __f64x2_t __vn_log (__f64x2_t);
+__vpcs __f64x2_t __vn_pow (__f64x2_t, __f64x2_t);
+
+/* Vector functions following the vector PCS using ABI names.  */
+__vpcs __f32x4_t _ZGVnN4v_sinf (__f32x4_t);
+__vpcs __f32x4_t _ZGVnN4v_cosf (__f32x4_t);
+__vpcs __f32x4_t _ZGVnN4v_expf (__f32x4_t);
+__vpcs __f32x4_t _ZGVnN4v_exp2f (__f32x4_t);
+__vpcs __f32x4_t _ZGVnN4v_logf (__f32x4_t);
+__vpcs __f32x4_t _ZGVnN4vv_powf (__f32x4_t, __f32x4_t);
+__vpcs __f64x2_t _ZGVnN2v_sin (__f64x2_t);
+__vpcs __f64x2_t _ZGVnN2v_cos (__f64x2_t);
+__vpcs __f64x2_t _ZGVnN2v_exp (__f64x2_t);
+__vpcs __f64x2_t _ZGVnN2v_log (__f64x2_t);
+__vpcs __f64x2_t _ZGVnN2vv_pow (__f64x2_t, __f64x2_t);
+#endif
+#endif
+
+#endif
diff --git a/libc/AOR_v20.02/math/log.c b/libc/AOR_v20.02/math/log.c
new file mode 100644 (file)
index 0000000..c546b69
--- /dev/null
@@ -0,0 +1,163 @@
+/*
+ * Double-precision log(x) function.
+ *
+ * Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+ * See https://llvm.org/LICENSE.txt for license information.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include <float.h>
+#include <math.h>
+#include <stdint.h>
+#include "math_config.h"
+
+#define T __log_data.tab
+#define T2 __log_data.tab2
+#define B __log_data.poly1
+#define A __log_data.poly
+#define Ln2hi __log_data.ln2hi
+#define Ln2lo __log_data.ln2lo
+#define N (1 << LOG_TABLE_BITS)
+#define OFF 0x3fe6000000000000
+
+/* Top 16 bits of a double.  */
+static inline uint32_t
+top16 (double x)
+{
+  return asuint64 (x) >> 48;
+}
+
+double
+log (double x)
+{
+  /* double_t for better performance on targets with FLT_EVAL_METHOD==2.  */
+  double_t w, z, r, r2, r3, y, invc, logc, kd, hi, lo;
+  uint64_t ix, iz, tmp;
+  uint32_t top;
+  int k, i;
+
+  ix = asuint64 (x);
+  top = top16 (x);
+
+#if LOG_POLY1_ORDER == 10 || LOG_POLY1_ORDER == 11
+# define LO asuint64 (1.0 - 0x1p-5)
+# define HI asuint64 (1.0 + 0x1.1p-5)
+#elif LOG_POLY1_ORDER == 12
+# define LO asuint64 (1.0 - 0x1p-4)
+# define HI asuint64 (1.0 + 0x1.09p-4)
+#endif
+  if (unlikely (ix - LO < HI - LO))
+    {
+      /* Handle close to 1.0 inputs separately.  */
+      /* Fix sign of zero with downward rounding when x==1.  */
+      if (WANT_ROUNDING && unlikely (ix == asuint64 (1.0)))
+       return 0;
+      r = x - 1.0;
+      r2 = r * r;
+      r3 = r * r2;
+#if LOG_POLY1_ORDER == 10
+      /* Worst-case error is around 0.516 ULP.  */
+      y = r3 * (B[1] + r * B[2] + r2 * B[3]
+               + r3 * (B[4] + r * B[5] + r2 * B[6] + r3 * (B[7] + r * B[8])));
+      w = B[0] * r2; /* B[0] == -0.5.  */
+      hi = r + w;
+      y += r - hi + w;
+      y += hi;
+#elif LOG_POLY1_ORDER == 11
+      /* Worst-case error is around 0.516 ULP.  */
+      y = r3 * (B[1] + r * B[2]
+               + r2 * (B[3] + r * B[4] + r2 * B[5]
+                       + r3 * (B[6] + r * B[7] + r2 * B[8] + r3 * B[9])));
+      w = B[0] * r2; /* B[0] == -0.5.  */
+      hi = r + w;
+      y += r - hi + w;
+      y += hi;
+#elif LOG_POLY1_ORDER == 12
+      y = r3 * (B[1] + r * B[2] + r2 * B[3]
+               + r3 * (B[4] + r * B[5] + r2 * B[6]
+                       + r3 * (B[7] + r * B[8] + r2 * B[9] + r3 * B[10])));
+# if N <= 64
+      /* Worst-case error is around 0.532 ULP.  */
+      w = B[0] * r2; /* B[0] == -0.5.  */
+      hi = r + w;
+      y += r - hi + w;
+      y += hi;
+# else
+      /* Worst-case error is around 0.507 ULP.  */
+      w = r * 0x1p27;
+      double_t rhi = r + w - w;
+      double_t rlo = r - rhi;
+      w = rhi * rhi * B[0]; /* B[0] == -0.5.  */
+      hi = r + w;
+      lo = r - hi + w;
+      lo += B[0] * rlo * (rhi + r);
+      y += lo;
+      y += hi;
+# endif
+#endif
+      return eval_as_double (y);
+    }
+  if (unlikely (top - 0x0010 >= 0x7ff0 - 0x0010))
+    {
+      /* x < 0x1p-1022 or inf or nan.  */
+      if (ix * 2 == 0)
+       return __math_divzero (1);
+      if (ix == asuint64 (INFINITY)) /* log(inf) == inf.  */
+       return x;
+      if ((top & 0x8000) || (top & 0x7ff0) == 0x7ff0)
+       return __math_invalid (x);
+      /* x is subnormal, normalize it.  */
+      ix = asuint64 (x * 0x1p52);
+      ix -= 52ULL << 52;
+    }
+
+  /* x = 2^k z; where z is in range [OFF,2*OFF) and exact.
+     The range is split into N subintervals.
+     The ith subinterval contains z and c is near its center.  */
+  tmp = ix - OFF;
+  i = (tmp >> (52 - LOG_TABLE_BITS)) % N;
+  k = (int64_t) tmp >> 52; /* arithmetic shift */
+  iz = ix - (tmp & 0xfffULL << 52);
+  invc = T[i].invc;
+  logc = T[i].logc;
+  z = asdouble (iz);
+
+  /* log(x) = log1p(z/c-1) + log(c) + k*Ln2.  */
+  /* r ~= z/c - 1, |r| < 1/(2*N).  */
+#if HAVE_FAST_FMA
+  /* rounding error: 0x1p-55/N.  */
+  r = fma (z, invc, -1.0);
+#else
+  /* rounding error: 0x1p-55/N + 0x1p-66.  */
+  r = (z - T2[i].chi - T2[i].clo) * invc;
+#endif
+  kd = (double_t) k;
+
+  /* hi + lo = r + log(c) + k*Ln2.  */
+  w = kd * Ln2hi + logc;
+  hi = w + r;
+  lo = w - hi + r + kd * Ln2lo;
+
+  /* log(x) = lo + (log1p(r) - r) + hi.  */
+  r2 = r * r; /* rounding error: 0x1p-54/N^2.  */
+  /* Worst case error if |y| > 0x1p-5:
+     0.5 + 4.13/N + abs-poly-error*2^57 ULP (+ 0.002 ULP without fma)
+     Worst case error if |y| > 0x1p-4:
+     0.5 + 2.06/N + abs-poly-error*2^56 ULP (+ 0.001 ULP without fma).  */
+#if LOG_POLY_ORDER == 6
+  y = lo + r2 * A[0] + r * r2 * (A[1] + r * A[2] + r2 * (A[3] + r * A[4])) + hi;
+#elif LOG_POLY_ORDER == 7
+  y = lo
+      + r2 * (A[0] + r * A[1] + r2 * (A[2] + r * A[3])
+             + r2 * r2 * (A[4] + r * A[5]))
+      + hi;
+#endif
+  return eval_as_double (y);
+}
+#if USE_GLIBC_ABI
+strong_alias (log, __log_finite)
+hidden_alias (log, __ieee754_log)
+# if LDBL_MANT_DIG == 53
+long double logl (long double x) { return log (x); }
+# endif
+#endif
diff --git a/libc/AOR_v20.02/math/log2.c b/libc/AOR_v20.02/math/log2.c
new file mode 100644 (file)
index 0000000..a1e20b0
--- /dev/null
@@ -0,0 +1,142 @@
+/*
+ * Double-precision log2(x) function.
+ *
+ * Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+ * See https://llvm.org/LICENSE.txt for license information.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include <float.h>
+#include <math.h>
+#include <stdint.h>
+#include "math_config.h"
+
+#define T __log2_data.tab
+#define T2 __log2_data.tab2
+#define B __log2_data.poly1
+#define A __log2_data.poly
+#define InvLn2hi __log2_data.invln2hi
+#define InvLn2lo __log2_data.invln2lo
+#define N (1 << LOG2_TABLE_BITS)
+#define OFF 0x3fe6000000000000
+
+/* Top 16 bits of a double.  */
+static inline uint32_t
+top16 (double x)
+{
+  return asuint64 (x) >> 48;
+}
+
+double
+log2 (double x)
+{
+  /* double_t for better performance on targets with FLT_EVAL_METHOD==2.  */
+  double_t z, r, r2, r4, y, invc, logc, kd, hi, lo, t1, t2, t3, p;
+  uint64_t ix, iz, tmp;
+  uint32_t top;
+  int k, i;
+
+  ix = asuint64 (x);
+  top = top16 (x);
+
+#if LOG2_POLY1_ORDER == 11
+# define LO asuint64 (1.0 - 0x1.5b51p-5)
+# define HI asuint64 (1.0 + 0x1.6ab2p-5)
+#endif
+  if (unlikely (ix - LO < HI - LO))
+    {
+      /* Handle close to 1.0 inputs separately.  */
+      /* Fix sign of zero with downward rounding when x==1.  */
+      if (WANT_ROUNDING && unlikely (ix == asuint64 (1.0)))
+       return 0;
+      r = x - 1.0;
+#if HAVE_FAST_FMA
+      hi = r * InvLn2hi;
+      lo = r * InvLn2lo + fma (r, InvLn2hi, -hi);
+#else
+      double_t rhi, rlo;
+      rhi = asdouble (asuint64 (r) & -1ULL << 32);
+      rlo = r - rhi;
+      hi = rhi * InvLn2hi;
+      lo = rlo * InvLn2hi + r * InvLn2lo;
+#endif
+      r2 = r * r; /* rounding error: 0x1p-62.  */
+      r4 = r2 * r2;
+#if LOG2_POLY1_ORDER == 11
+      /* Worst-case error is less than 0.54 ULP (0.55 ULP without fma).  */
+      p = r2 * (B[0] + r * B[1]);
+      y = hi + p;
+      lo += hi - y + p;
+      lo += r4 * (B[2] + r * B[3] + r2 * (B[4] + r * B[5])
+                 + r4 * (B[6] + r * B[7] + r2 * (B[8] + r * B[9])));
+      y += lo;
+#endif
+      return eval_as_double (y);
+    }
+  if (unlikely (top - 0x0010 >= 0x7ff0 - 0x0010))
+    {
+      /* x < 0x1p-1022 or inf or nan.  */
+      if (ix * 2 == 0)
+       return __math_divzero (1);
+      if (ix == asuint64 (INFINITY)) /* log(inf) == inf.  */
+       return x;
+      if ((top & 0x8000) || (top & 0x7ff0) == 0x7ff0)
+       return __math_invalid (x);
+      /* x is subnormal, normalize it.  */
+      ix = asuint64 (x * 0x1p52);
+      ix -= 52ULL << 52;
+    }
+
+  /* x = 2^k z; where z is in range [OFF,2*OFF) and exact.
+     The range is split into N subintervals.
+     The ith subinterval contains z and c is near its center.  */
+  tmp = ix - OFF;
+  i = (tmp >> (52 - LOG2_TABLE_BITS)) % N;
+  k = (int64_t) tmp >> 52; /* arithmetic shift */
+  iz = ix - (tmp & 0xfffULL << 52);
+  invc = T[i].invc;
+  logc = T[i].logc;
+  z = asdouble (iz);
+  kd = (double_t) k;
+
+  /* log2(x) = log2(z/c) + log2(c) + k.  */
+  /* r ~= z/c - 1, |r| < 1/(2*N).  */
+#if HAVE_FAST_FMA
+  /* rounding error: 0x1p-55/N.  */
+  r = fma (z, invc, -1.0);
+  t1 = r * InvLn2hi;
+  t2 = r * InvLn2lo + fma (r, InvLn2hi, -t1);
+#else
+  double_t rhi, rlo;
+  /* rounding error: 0x1p-55/N + 0x1p-65.  */
+  r = (z - T2[i].chi - T2[i].clo) * invc;
+  rhi = asdouble (asuint64 (r) & -1ULL << 32);
+  rlo = r - rhi;
+  t1 = rhi * InvLn2hi;
+  t2 = rlo * InvLn2hi + r * InvLn2lo;
+#endif
+
+  /* hi + lo = r/ln2 + log2(c) + k.  */
+  t3 = kd + logc;
+  hi = t3 + t1;
+  lo = t3 - hi + t1 + t2;
+
+  /* log2(r+1) = r/ln2 + r^2*poly(r).  */
+  /* Evaluation is optimized assuming superscalar pipelined execution.  */
+  r2 = r * r; /* rounding error: 0x1p-54/N^2.  */
+  r4 = r2 * r2;
+#if LOG2_POLY_ORDER == 7
+  /* Worst-case error if |y| > 0x1p-4: 0.547 ULP (0.550 ULP without fma).
+     ~ 0.5 + 2/N/ln2 + abs-poly-error*0x1p56 ULP (+ 0.003 ULP without fma).  */
+  p = A[0] + r * A[1] + r2 * (A[2] + r * A[3]) + r4 * (A[4] + r * A[5]);
+  y = lo + r2 * p + hi;
+#endif
+  return eval_as_double (y);
+}
+#if USE_GLIBC_ABI
+strong_alias (log2, __log2_finite)
+hidden_alias (log2, __ieee754_log2)
+# if LDBL_MANT_DIG == 53
+long double log2l (long double x) { return log2 (x); }
+# endif
+#endif
diff --git a/libc/AOR_v20.02/math/log2_data.c b/libc/AOR_v20.02/math/log2_data.c
new file mode 100644 (file)
index 0000000..a487dbf
--- /dev/null
@@ -0,0 +1,210 @@
+/*
+ * Data for log2.
+ *
+ * Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+ * See https://llvm.org/LICENSE.txt for license information.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "math_config.h"
+
+#define N (1 << LOG2_TABLE_BITS)
+
+const struct log2_data __log2_data = {
+// First coefficient: 0x1.71547652b82fe1777d0ffda0d24p0
+.invln2hi = 0x1.7154765200000p+0,
+.invln2lo = 0x1.705fc2eefa200p-33,
+.poly1 = {
+#if LOG2_POLY1_ORDER == 11
+// relative error: 0x1.2fad8188p-63
+// in -0x1.5b51p-5 0x1.6ab2p-5
+-0x1.71547652b82fep-1,
+0x1.ec709dc3a03f7p-2,
+-0x1.71547652b7c3fp-2,
+0x1.2776c50f05be4p-2,
+-0x1.ec709dd768fe5p-3,
+0x1.a61761ec4e736p-3,
+-0x1.7153fbc64a79bp-3,
+0x1.484d154f01b4ap-3,
+-0x1.289e4a72c383cp-3,
+0x1.0b32f285aee66p-3,
+#endif
+},
+.poly = {
+#if N == 64 && LOG2_POLY_ORDER == 7
+// relative error: 0x1.a72c2bf8p-58
+// abs error: 0x1.67a552c8p-66
+// in -0x1.f45p-8 0x1.f45p-8
+-0x1.71547652b8339p-1,
+0x1.ec709dc3a04bep-2,
+-0x1.7154764702ffbp-2,
+0x1.2776c50034c48p-2,
+-0x1.ec7b328ea92bcp-3,
+0x1.a6225e117f92ep-3,
+#endif
+},
+/* Algorithm:
+
+       x = 2^k z
+       log2(x) = k + log2(c) + log2(z/c)
+       log2(z/c) = poly(z/c - 1)
+
+where z is in [1.6p-1; 1.6p0] which is split into N subintervals and z falls
+into the ith one, then table entries are computed as
+
+       tab[i].invc = 1/c
+       tab[i].logc = (double)log2(c)
+       tab2[i].chi = (double)c
+       tab2[i].clo = (double)(c - (double)c)
+
+where c is near the center of the subinterval and is chosen by trying +-2^29
+floating point invc candidates around 1/center and selecting one for which
+
+       1) the rounding error in 0x1.8p10 + logc is 0,
+       2) the rounding error in z - chi - clo is < 0x1p-64 and
+       3) the rounding error in (double)log2(c) is minimized (< 0x1p-68).
+
+Note: 1) ensures that k + logc can be computed without rounding error, 2)
+ensures that z/c - 1 can be computed as (z - chi - clo)*invc with close to a
+single rounding error when there is no fast fma for z*invc - 1, 3) ensures
+that logc + poly(z/c - 1) has small error, however near x == 1 when
+|log2(x)| < 0x1p-4, this is not enough so that is special cased.  */
+.tab = {
+#if N == 64
+{0x1.724286bb1acf8p+0, -0x1.1095feecdb000p-1},
+{0x1.6e1f766d2cca1p+0, -0x1.08494bd76d000p-1},
+{0x1.6a13d0e30d48ap+0, -0x1.00143aee8f800p-1},
+{0x1.661ec32d06c85p+0, -0x1.efec5360b4000p-2},
+{0x1.623fa951198f8p+0, -0x1.dfdd91ab7e000p-2},
+{0x1.5e75ba4cf026cp+0, -0x1.cffae0cc79000p-2},
+{0x1.5ac055a214fb8p+0, -0x1.c043811fda000p-2},
+{0x1.571ed0f166e1ep+0, -0x1.b0b67323ae000p-2},
+{0x1.53909590bf835p+0, -0x1.a152f5a2db000p-2},
+{0x1.5014fed61adddp+0, -0x1.9217f5af86000p-2},
+{0x1.4cab88e487bd0p+0, -0x1.8304db0719000p-2},
+{0x1.49539b4334feep+0, -0x1.74189f9a9e000p-2},
+{0x1.460cbdfafd569p+0, -0x1.6552bb5199000p-2},
+{0x1.42d664ee4b953p+0, -0x1.56b23a29b1000p-2},
+{0x1.3fb01111dd8a6p+0, -0x1.483650f5fa000p-2},
+{0x1.3c995b70c5836p+0, -0x1.39de937f6a000p-2},
+{0x1.3991c4ab6fd4ap+0, -0x1.2baa1538d6000p-2},
+{0x1.3698e0ce099b5p+0, -0x1.1d98340ca4000p-2},
+{0x1.33ae48213e7b2p+0, -0x1.0fa853a40e000p-2},
+{0x1.30d191985bdb1p+0, -0x1.01d9c32e73000p-2},
+{0x1.2e025cab271d7p+0, -0x1.e857da2fa6000p-3},
+{0x1.2b404cf13cd82p+0, -0x1.cd3c8633d8000p-3},
+{0x1.288b02c7ccb50p+0, -0x1.b26034c14a000p-3},
+{0x1.25e2263944de5p+0, -0x1.97c1c2f4fe000p-3},
+{0x1.234563d8615b1p+0, -0x1.7d6023f800000p-3},
+{0x1.20b46e33eaf38p+0, -0x1.633a71a05e000p-3},
+{0x1.1e2eefdcda3ddp+0, -0x1.494f5e9570000p-3},
+{0x1.1bb4a580b3930p+0, -0x1.2f9e424e0a000p-3},
+{0x1.19453847f2200p+0, -0x1.162595afdc000p-3},
+{0x1.16e06c0d5d73cp+0, -0x1.f9c9a75bd8000p-4},
+{0x1.1485f47b7e4c2p+0, -0x1.c7b575bf9c000p-4},
+{0x1.12358ad0085d1p+0, -0x1.960c60ff48000p-4},
+{0x1.0fef00f532227p+0, -0x1.64ce247b60000p-4},
+{0x1.0db2077d03a8fp+0, -0x1.33f78b2014000p-4},
+{0x1.0b7e6d65980d9p+0, -0x1.0387d1a42c000p-4},
+{0x1.0953efe7b408dp+0, -0x1.a6f9208b50000p-5},
+{0x1.07325cac53b83p+0, -0x1.47a954f770000p-5},
+{0x1.05197e40d1b5cp+0, -0x1.d23a8c50c0000p-6},
+{0x1.03091c1208ea2p+0, -0x1.16a2629780000p-6},
+{0x1.0101025b37e21p+0, -0x1.720f8d8e80000p-8},
+{0x1.fc07ef9caa76bp-1, 0x1.6fe53b1500000p-7},
+{0x1.f4465d3f6f184p-1, 0x1.11ccce10f8000p-5},
+{0x1.ecc079f84107fp-1, 0x1.c4dfc8c8b8000p-5},
+{0x1.e573a99975ae8p-1, 0x1.3aa321e574000p-4},
+{0x1.de5d6f0bd3de6p-1, 0x1.918a0d08b8000p-4},
+{0x1.d77b681ff38b3p-1, 0x1.e72e9da044000p-4},
+{0x1.d0cb5724de943p-1, 0x1.1dcd2507f6000p-3},
+{0x1.ca4b2dc0e7563p-1, 0x1.476ab03dea000p-3},
+{0x1.c3f8ee8d6cb51p-1, 0x1.7074377e22000p-3},
+{0x1.bdd2b4f020c4cp-1, 0x1.98ede8ba94000p-3},
+{0x1.b7d6c006015cap-1, 0x1.c0db86ad2e000p-3},
+{0x1.b20366e2e338fp-1, 0x1.e840aafcee000p-3},
+{0x1.ac57026295039p-1, 0x1.0790ab4678000p-2},
+{0x1.a6d01bc2731ddp-1, 0x1.1ac056801c000p-2},
+{0x1.a16d3bc3ff18bp-1, 0x1.2db11d4fee000p-2},
+{0x1.9c2d14967feadp-1, 0x1.406464ec58000p-2},
+{0x1.970e4f47c9902p-1, 0x1.52dbe093af000p-2},
+{0x1.920fb3982bcf2p-1, 0x1.651902050d000p-2},
+{0x1.8d30187f759f1p-1, 0x1.771d2cdeaf000p-2},
+{0x1.886e5ebb9f66dp-1, 0x1.88e9c857d9000p-2},
+{0x1.83c97b658b994p-1, 0x1.9a80155e16000p-2},
+{0x1.7f405ffc61022p-1, 0x1.abe186ed3d000p-2},
+{0x1.7ad22181415cap-1, 0x1.bd0f2aea0e000p-2},
+{0x1.767dcf99eff8cp-1, 0x1.ce0a43dbf4000p-2},
+#endif
+},
+#if !HAVE_FAST_FMA
+.tab2 = {
+# if N == 64
+{0x1.6200012b90a8ep-1, 0x1.904ab0644b605p-55},
+{0x1.66000045734a6p-1, 0x1.1ff9bea62f7a9p-57},
+{0x1.69fffc325f2c5p-1, 0x1.27ecfcb3c90bap-55},
+{0x1.6e00038b95a04p-1, 0x1.8ff8856739326p-55},
+{0x1.71fffe09994e3p-1, 0x1.afd40275f82b1p-55},
+{0x1.7600015590e1p-1, -0x1.2fd75b4238341p-56},
+{0x1.7a00012655bd5p-1, 0x1.808e67c242b76p-56},
+{0x1.7e0003259e9a6p-1, -0x1.208e426f622b7p-57},
+{0x1.81fffedb4b2d2p-1, -0x1.402461ea5c92fp-55},
+{0x1.860002dfafcc3p-1, 0x1.df7f4a2f29a1fp-57},
+{0x1.89ffff78c6b5p-1, -0x1.e0453094995fdp-55},
+{0x1.8e00039671566p-1, -0x1.a04f3bec77b45p-55},
+{0x1.91fffe2bf1745p-1, -0x1.7fa34400e203cp-56},
+{0x1.95fffcc5c9fd1p-1, -0x1.6ff8005a0695dp-56},
+{0x1.9a0003bba4767p-1, 0x1.0f8c4c4ec7e03p-56},
+{0x1.9dfffe7b92da5p-1, 0x1.e7fd9478c4602p-55},
+{0x1.a1fffd72efdafp-1, -0x1.a0c554dcdae7ep-57},
+{0x1.a5fffde04ff95p-1, 0x1.67da98ce9b26bp-55},
+{0x1.a9fffca5e8d2bp-1, -0x1.284c9b54c13dep-55},
+{0x1.adfffddad03eap-1, 0x1.812c8ea602e3cp-58},
+{0x1.b1ffff10d3d4dp-1, -0x1.efaddad27789cp-55},
+{0x1.b5fffce21165ap-1, 0x1.3cb1719c61237p-58},
+{0x1.b9fffd950e674p-1, 0x1.3f7d94194cep-56},
+{0x1.be000139ca8afp-1, 0x1.50ac4215d9bcp-56},
+{0x1.c20005b46df99p-1, 0x1.beea653e9c1c9p-57},
+{0x1.c600040b9f7aep-1, -0x1.c079f274a70d6p-56},
+{0x1.ca0006255fd8ap-1, -0x1.a0b4076e84c1fp-56},
+{0x1.cdfffd94c095dp-1, 0x1.8f933f99ab5d7p-55},
+{0x1.d1ffff975d6cfp-1, -0x1.82c08665fe1bep-58},
+{0x1.d5fffa2561c93p-1, -0x1.b04289bd295f3p-56},
+{0x1.d9fff9d228b0cp-1, 0x1.70251340fa236p-55},
+{0x1.de00065bc7e16p-1, -0x1.5011e16a4d80cp-56},
+{0x1.e200002f64791p-1, 0x1.9802f09ef62ep-55},
+{0x1.e600057d7a6d8p-1, -0x1.e0b75580cf7fap-56},
+{0x1.ea00027edc00cp-1, -0x1.c848309459811p-55},
+{0x1.ee0006cf5cb7cp-1, -0x1.f8027951576f4p-55},
+{0x1.f2000782b7dccp-1, -0x1.f81d97274538fp-55},
+{0x1.f6000260c450ap-1, -0x1.071002727ffdcp-59},
+{0x1.f9fffe88cd533p-1, -0x1.81bdce1fda8bp-58},
+{0x1.fdfffd50f8689p-1, 0x1.7f91acb918e6ep-55},
+{0x1.0200004292367p+0, 0x1.b7ff365324681p-54},
+{0x1.05fffe3e3d668p+0, 0x1.6fa08ddae957bp-55},
+{0x1.0a0000a85a757p+0, -0x1.7e2de80d3fb91p-58},
+{0x1.0e0001a5f3fccp+0, -0x1.1823305c5f014p-54},
+{0x1.11ffff8afbaf5p+0, -0x1.bfabb6680bac2p-55},
+{0x1.15fffe54d91adp+0, -0x1.d7f121737e7efp-54},
+{0x1.1a00011ac36e1p+0, 0x1.c000a0516f5ffp-54},
+{0x1.1e00019c84248p+0, -0x1.082fbe4da5dap-54},
+{0x1.220000ffe5e6ep+0, -0x1.8fdd04c9cfb43p-55},
+{0x1.26000269fd891p+0, 0x1.cfe2a7994d182p-55},
+{0x1.2a00029a6e6dap+0, -0x1.00273715e8bc5p-56},
+{0x1.2dfffe0293e39p+0, 0x1.b7c39dab2a6f9p-54},
+{0x1.31ffff7dcf082p+0, 0x1.df1336edc5254p-56},
+{0x1.35ffff05a8b6p+0, -0x1.e03564ccd31ebp-54},
+{0x1.3a0002e0eaeccp+0, 0x1.5f0e74bd3a477p-56},
+{0x1.3e000043bb236p+0, 0x1.c7dcb149d8833p-54},
+{0x1.4200002d187ffp+0, 0x1.e08afcf2d3d28p-56},
+{0x1.460000d387cb1p+0, 0x1.20837856599a6p-55},
+{0x1.4a00004569f89p+0, -0x1.9fa5c904fbcd2p-55},
+{0x1.4e000043543f3p+0, -0x1.81125ed175329p-56},
+{0x1.51fffcc027f0fp+0, 0x1.883d8847754dcp-54},
+{0x1.55ffffd87b36fp+0, -0x1.709e731d02807p-55},
+{0x1.59ffff21df7bap+0, 0x1.7f79f68727b02p-55},
+{0x1.5dfffebfc3481p+0, -0x1.180902e30e93ep-54},
+# endif
+},
+#endif /* !HAVE_FAST_FMA */
+};
diff --git a/libc/AOR_v20.02/math/log2f.c b/libc/AOR_v20.02/math/log2f.c
new file mode 100644 (file)
index 0000000..a43814f
--- /dev/null
@@ -0,0 +1,81 @@
+/*
+ * Single-precision log2 function.
+ *
+ * Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+ * See https://llvm.org/LICENSE.txt for license information.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include <math.h>
+#include <stdint.h>
+#include "math_config.h"
+
+/*
+LOG2F_TABLE_BITS = 4
+LOG2F_POLY_ORDER = 4
+
+ULP error: 0.752 (nearest rounding.)
+Relative error: 1.9 * 2^-26 (before rounding.)
+*/
+
+#define N (1 << LOG2F_TABLE_BITS)
+#define T __log2f_data.tab
+#define A __log2f_data.poly
+#define OFF 0x3f330000
+
+float
+log2f (float x)
+{
+  /* double_t for better performance on targets with FLT_EVAL_METHOD==2.  */
+  double_t z, r, r2, p, y, y0, invc, logc;
+  uint32_t ix, iz, top, tmp;
+  int k, i;
+
+  ix = asuint (x);
+#if WANT_ROUNDING
+  /* Fix sign of zero with downward rounding when x==1.  */
+  if (unlikely (ix == 0x3f800000))
+    return 0;
+#endif
+  if (unlikely (ix - 0x00800000 >= 0x7f800000 - 0x00800000))
+    {
+      /* x < 0x1p-126 or inf or nan.  */
+      if (ix * 2 == 0)
+       return __math_divzerof (1);
+      if (ix == 0x7f800000) /* log2(inf) == inf.  */
+       return x;
+      if ((ix & 0x80000000) || ix * 2 >= 0xff000000)
+       return __math_invalidf (x);
+      /* x is subnormal, normalize it.  */
+      ix = asuint (x * 0x1p23f);
+      ix -= 23 << 23;
+    }
+
+  /* x = 2^k z; where z is in range [OFF,2*OFF] and exact.
+     The range is split into N subintervals.
+     The ith subinterval contains z and c is near its center.  */
+  tmp = ix - OFF;
+  i = (tmp >> (23 - LOG2F_TABLE_BITS)) % N;
+  top = tmp & 0xff800000;
+  iz = ix - top;
+  k = (int32_t) tmp >> 23; /* arithmetic shift */
+  invc = T[i].invc;
+  logc = T[i].logc;
+  z = (double_t) asfloat (iz);
+
+  /* log2(x) = log1p(z/c-1)/ln2 + log2(c) + k */
+  r = z * invc - 1;
+  y0 = logc + (double_t) k;
+
+  /* Pipelined polynomial evaluation to approximate log1p(r)/ln2.  */
+  r2 = r * r;
+  y = A[1] * r + A[2];
+  y = A[0] * r2 + y;
+  p = A[3] * r + y0;
+  y = y * r2 + p;
+  return eval_as_float (y);
+}
+#if USE_GLIBC_ABI
+strong_alias (log2f, __log2f_finite)
+hidden_alias (log2f, __ieee754_log2f)
+#endif
diff --git a/libc/AOR_v20.02/math/log2f_data.c b/libc/AOR_v20.02/math/log2f_data.c
new file mode 100644 (file)
index 0000000..f8f270d
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * Data definition for log2f.
+ *
+ * Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+ * See https://llvm.org/LICENSE.txt for license information.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "math_config.h"
+
+const struct log2f_data __log2f_data = {
+  .tab = {
+  { 0x1.661ec79f8f3bep+0, -0x1.efec65b963019p-2 },
+  { 0x1.571ed4aaf883dp+0, -0x1.b0b6832d4fca4p-2 },
+  { 0x1.49539f0f010bp+0, -0x1.7418b0a1fb77bp-2 },
+  { 0x1.3c995b0b80385p+0, -0x1.39de91a6dcf7bp-2 },
+  { 0x1.30d190c8864a5p+0, -0x1.01d9bf3f2b631p-2 },
+  { 0x1.25e227b0b8eap+0, -0x1.97c1d1b3b7afp-3 },
+  { 0x1.1bb4a4a1a343fp+0, -0x1.2f9e393af3c9fp-3 },
+  { 0x1.12358f08ae5bap+0, -0x1.960cbbf788d5cp-4 },
+  { 0x1.0953f419900a7p+0, -0x1.a6f9db6475fcep-5 },
+  { 0x1p+0, 0x0p+0 },
+  { 0x1.e608cfd9a47acp-1, 0x1.338ca9f24f53dp-4 },
+  { 0x1.ca4b31f026aap-1, 0x1.476a9543891bap-3 },
+  { 0x1.b2036576afce6p-1, 0x1.e840b4ac4e4d2p-3 },
+  { 0x1.9c2d163a1aa2dp-1, 0x1.40645f0c6651cp-2 },
+  { 0x1.886e6037841edp-1, 0x1.88e9c2c1b9ff8p-2 },
+  { 0x1.767dcf5534862p-1, 0x1.ce0a44eb17bccp-2 },
+  },
+  .poly = {
+  -0x1.712b6f70a7e4dp-2, 0x1.ecabf496832ep-2, -0x1.715479ffae3dep-1,
+  0x1.715475f35c8b8p0,
+  }
+};
diff --git a/libc/AOR_v20.02/math/log_data.c b/libc/AOR_v20.02/math/log_data.c
new file mode 100644 (file)
index 0000000..26fc9df
--- /dev/null
@@ -0,0 +1,512 @@
+/*
+ * Data for log.
+ *
+ * Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+ * See https://llvm.org/LICENSE.txt for license information.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "math_config.h"
+
+#define N (1 << LOG_TABLE_BITS)
+
+const struct log_data __log_data = {
+.ln2hi = 0x1.62e42fefa3800p-1,
+.ln2lo = 0x1.ef35793c76730p-45,
+.poly1 = {
+#if LOG_POLY1_ORDER == 10
+// relative error: 0x1.32eccc6p-62
+// in -0x1p-5 0x1.1p-5 (|log(1+x)| > 0x1p-5 outside this interval)
+-0x1p-1,
+0x1.55555555554e5p-2,
+-0x1.0000000000af2p-2,
+0x1.9999999bbe436p-3,
+-0x1.55555537f9cdep-3,
+0x1.24922fc8127cfp-3,
+-0x1.0000b7d6bb612p-3,
+0x1.c806ee1ddbcafp-4,
+-0x1.972335a9c2d6ep-4,
+#elif LOG_POLY1_ORDER == 11
+// relative error: 0x1.52c8b708p-68
+// in -0x1p-5 0x1.1p-5 (|log(1+x)| > 0x1p-5 outside this interval)
+-0x1p-1,
+0x1.5555555555555p-2,
+-0x1.ffffffffffea9p-3,
+0x1.999999999c4d4p-3,
+-0x1.55555557f5541p-3,
+0x1.249248fbe33e4p-3,
+-0x1.ffffc9a3c825bp-4,
+0x1.c71e1f204435dp-4,
+-0x1.9a7f26377d06ep-4,
+0x1.71c30cf8f7364p-4,
+#elif LOG_POLY1_ORDER == 12
+// relative error: 0x1.c04d76cp-63
+// in -0x1p-4 0x1.09p-4 (|log(1+x)| > 0x1p-4 outside the interval)
+-0x1p-1,
+0x1.5555555555577p-2,
+-0x1.ffffffffffdcbp-3,
+0x1.999999995dd0cp-3,
+-0x1.55555556745a7p-3,
+0x1.24924a344de3p-3,
+-0x1.fffffa4423d65p-4,
+0x1.c7184282ad6cap-4,
+-0x1.999eb43b068ffp-4,
+0x1.78182f7afd085p-4,
+-0x1.5521375d145cdp-4,
+#endif
+},
+.poly = {
+#if N == 64 && LOG_POLY_ORDER == 7
+// relative error: 0x1.906eb8ap-58
+// abs error: 0x1.d2cad5a8p-67
+// in -0x1.fp-8 0x1.fp-8
+-0x1.0000000000027p-1,
+0x1.555555555556ap-2,
+-0x1.fffffff0440bap-3,
+0x1.99999991906c3p-3,
+-0x1.555c8d7e8201ep-3,
+0x1.24978c59151fap-3,
+#elif N == 128 && LOG_POLY_ORDER == 6
+// relative error: 0x1.926199e8p-56
+// abs error: 0x1.882ff33p-65
+// in -0x1.fp-9 0x1.fp-9
+-0x1.0000000000001p-1,
+0x1.555555551305bp-2,
+-0x1.fffffffeb459p-3,
+0x1.999b324f10111p-3,
+-0x1.55575e506c89fp-3,
+#elif N == 128 && LOG_POLY_ORDER == 7
+// relative error: 0x1.649fc4bp-64
+// abs error: 0x1.c3b5769p-74
+// in -0x1.fp-9 0x1.fp-9
+-0x1.0000000000001p-1,
+0x1.5555555555556p-2,
+-0x1.fffffffea1a8p-3,
+0x1.99999998e9139p-3,
+-0x1.555776801b968p-3,
+0x1.2493c29331a5cp-3,
+#endif
+},
+/* Algorithm:
+
+       x = 2^k z
+       log(x) = k ln2 + log(c) + log(z/c)
+       log(z/c) = poly(z/c - 1)
+
+where z is in [1.6p-1; 1.6p0] which is split into N subintervals and z falls
+into the ith one, then table entries are computed as
+
+       tab[i].invc = 1/c
+       tab[i].logc = (double)log(c)
+       tab2[i].chi = (double)c
+       tab2[i].clo = (double)(c - (double)c)
+
+where c is near the center of the subinterval and is chosen by trying +-2^29
+floating point invc candidates around 1/center and selecting one for which
+
+       1) the rounding error in 0x1.8p9 + logc is 0,
+       2) the rounding error in z - chi - clo is < 0x1p-66 and
+       3) the rounding error in (double)log(c) is minimized (< 0x1p-66).
+
+Note: 1) ensures that k*ln2hi + logc can be computed without rounding error,
+2) ensures that z/c - 1 can be computed as (z - chi - clo)*invc with close to
+a single rounding error when there is no fast fma for z*invc - 1, 3) ensures
+that logc + poly(z/c - 1) has small error, however near x == 1 when
+|log(x)| < 0x1p-4, this is not enough so that is special cased.  */
+.tab = {
+#if N == 64
+{0x1.7242886495cd8p+0, -0x1.79e267bdfe000p-2},
+{0x1.6e1f769340dc9p+0, -0x1.6e60ee0ecb000p-2},
+{0x1.6a13ccc8f195cp+0, -0x1.63002fdbf6000p-2},
+{0x1.661ec72e86f3ap+0, -0x1.57bf76c597000p-2},
+{0x1.623fa6c447b16p+0, -0x1.4c9e07f0d2000p-2},
+{0x1.5e75bbca31702p+0, -0x1.419b42f027000p-2},
+{0x1.5ac05655adb10p+0, -0x1.36b67660e6000p-2},
+{0x1.571ed3e940191p+0, -0x1.2bef0839e4800p-2},
+{0x1.539094ac0fbbfp+0, -0x1.21445727cb000p-2},
+{0x1.5015007e7fc42p+0, -0x1.16b5ca3c3d000p-2},
+{0x1.4cab877c31cf9p+0, -0x1.0c42d3805f800p-2},
+{0x1.49539e76a88d3p+0, -0x1.01eae61b60800p-2},
+{0x1.460cbc12211dap+0, -0x1.ef5adb9fb0000p-3},
+{0x1.42d6624debe3ap+0, -0x1.db13daab99000p-3},
+{0x1.3fb0144f0d462p+0, -0x1.c6ffbe896e000p-3},
+{0x1.3c995a1f9a9b4p+0, -0x1.b31d84722d000p-3},
+{0x1.3991c23952500p+0, -0x1.9f6c3cf6eb000p-3},
+{0x1.3698df35eaa14p+0, -0x1.8beafe7f13000p-3},
+{0x1.33ae463091760p+0, -0x1.7898db878d000p-3},
+{0x1.30d190aae3d72p+0, -0x1.6574efe4ec000p-3},
+{0x1.2e025c9203c89p+0, -0x1.527e620845000p-3},
+{0x1.2b404a7244988p+0, -0x1.3fb457d798000p-3},
+{0x1.288b01dc19544p+0, -0x1.2d1615a077000p-3},
+{0x1.25e2268085f69p+0, -0x1.1aa2b431e5000p-3},
+{0x1.23456812abb74p+0, -0x1.08598f1d2b000p-3},
+{0x1.20b4703174157p+0, -0x1.ec738fee40000p-4},
+{0x1.1e2ef308b4e9bp+0, -0x1.c885768862000p-4},
+{0x1.1bb4a36b70a3fp+0, -0x1.a4e75b6a46000p-4},
+{0x1.194538e960658p+0, -0x1.8197efba9a000p-4},
+{0x1.16e0692a10ac8p+0, -0x1.5e95ad734e000p-4},
+{0x1.1485f1ba1568bp+0, -0x1.3bdf67117c000p-4},
+{0x1.12358e123ed6fp+0, -0x1.1973b744f0000p-4},
+{0x1.0fef01de37c8dp+0, -0x1.eea33446bc000p-5},
+{0x1.0db20b82be414p+0, -0x1.aaef4ab304000p-5},
+{0x1.0b7e6f67f69b3p+0, -0x1.67c962fd2c000p-5},
+{0x1.0953f342fc108p+0, -0x1.252f29acf8000p-5},
+{0x1.0732604ec956bp+0, -0x1.c63d19e9c0000p-6},
+{0x1.051980117f9b0p+0, -0x1.432ab6a388000p-6},
+{0x1.03091aa6810f1p+0, -0x1.8244357f50000p-7},
+{0x1.01010152cf066p+0, -0x1.0080a711c0000p-8},
+{0x1.fc07ef6b6e30bp-1, 0x1.fe03018e80000p-8},
+{0x1.f4465aa1024afp-1, 0x1.7b91986450000p-6},
+{0x1.ecc07a8fd3f5ep-1, 0x1.39e88608c8000p-5},
+{0x1.e573ad856b537p-1, 0x1.b42dc6e624000p-5},
+{0x1.de5d6dc7b8057p-1, 0x1.165372ec20000p-4},
+{0x1.d77b6498bddf7p-1, 0x1.51b07a0170000p-4},
+{0x1.d0cb580315c0fp-1, 0x1.8c3465c7ea000p-4},
+{0x1.ca4b30d1cf449p-1, 0x1.c5e544a290000p-4},
+{0x1.c3f8ef4810d8ep-1, 0x1.fec91aa0a6000p-4},
+{0x1.bdd2b8b311f44p-1, 0x1.1b72acdc5c000p-3},
+{0x1.b7d6c2eeac054p-1, 0x1.371fc65a98000p-3},
+{0x1.b20363474c8f5p-1, 0x1.526e61c1aa000p-3},
+{0x1.ac570165eeab1p-1, 0x1.6d60ffc240000p-3},
+{0x1.a6d019f331df4p-1, 0x1.87fa08a013000p-3},
+{0x1.a16d3ebc9e3c3p-1, 0x1.a23bc630c3000p-3},
+{0x1.9c2d14567ef45p-1, 0x1.bc286a3512000p-3},
+{0x1.970e4efae9169p-1, 0x1.d5c2195697000p-3},
+{0x1.920fb3bd0b802p-1, 0x1.ef0ae132d3000p-3},
+{0x1.8d3018b58699ap-1, 0x1.040259974e000p-2},
+{0x1.886e5ff170ee6p-1, 0x1.1058bd40e2000p-2},
+{0x1.83c977ad35d27p-1, 0x1.1c898c1137800p-2},
+{0x1.7f405ed16c520p-1, 0x1.2895a3e65b000p-2},
+{0x1.7ad220d0335c4p-1, 0x1.347dd8f6bd000p-2},
+{0x1.767dce53474fdp-1, 0x1.4043083cb3800p-2},
+#elif N == 128
+{0x1.734f0c3e0de9fp+0, -0x1.7cc7f79e69000p-2},
+{0x1.713786a2ce91fp+0, -0x1.76feec20d0000p-2},
+{0x1.6f26008fab5a0p+0, -0x1.713e31351e000p-2},
+{0x1.6d1a61f138c7dp+0, -0x1.6b85b38287800p-2},
+{0x1.6b1490bc5b4d1p+0, -0x1.65d5590807800p-2},
+{0x1.69147332f0cbap+0, -0x1.602d076180000p-2},
+{0x1.6719f18224223p+0, -0x1.5a8ca86909000p-2},
+{0x1.6524f99a51ed9p+0, -0x1.54f4356035000p-2},
+{0x1.63356aa8f24c4p+0, -0x1.4f637c36b4000p-2},
+{0x1.614b36b9ddc14p+0, -0x1.49da7fda85000p-2},
+{0x1.5f66452c65c4cp+0, -0x1.445923989a800p-2},
+{0x1.5d867b5912c4fp+0, -0x1.3edf439b0b800p-2},
+{0x1.5babccb5b90dep+0, -0x1.396ce448f7000p-2},
+{0x1.59d61f2d91a78p+0, -0x1.3401e17bda000p-2},
+{0x1.5805612465687p+0, -0x1.2e9e2ef468000p-2},
+{0x1.56397cee76bd3p+0, -0x1.2941b3830e000p-2},
+{0x1.54725e2a77f93p+0, -0x1.23ec58cda8800p-2},
+{0x1.52aff42064583p+0, -0x1.1e9e129279000p-2},
+{0x1.50f22dbb2bddfp+0, -0x1.1956d2b48f800p-2},
+{0x1.4f38f4734ded7p+0, -0x1.141679ab9f800p-2},
+{0x1.4d843cfde2840p+0, -0x1.0edd094ef9800p-2},
+{0x1.4bd3ec078a3c8p+0, -0x1.09aa518db1000p-2},
+{0x1.4a27fc3e0258ap+0, -0x1.047e65263b800p-2},
+{0x1.4880524d48434p+0, -0x1.feb224586f000p-3},
+{0x1.46dce1b192d0bp+0, -0x1.f474a7517b000p-3},
+{0x1.453d9d3391854p+0, -0x1.ea4443d103000p-3},
+{0x1.43a2744b4845ap+0, -0x1.e020d44e9b000p-3},
+{0x1.420b54115f8fbp+0, -0x1.d60a22977f000p-3},
+{0x1.40782da3ef4b1p+0, -0x1.cc00104959000p-3},
+{0x1.3ee8f5d57fe8fp+0, -0x1.c202956891000p-3},
+{0x1.3d5d9a00b4ce9p+0, -0x1.b81178d811000p-3},
+{0x1.3bd60c010c12bp+0, -0x1.ae2c9ccd3d000p-3},
+{0x1.3a5242b75dab8p+0, -0x1.a45402e129000p-3},
+{0x1.38d22cd9fd002p+0, -0x1.9a877681df000p-3},
+{0x1.3755bc5847a1cp+0, -0x1.90c6d69483000p-3},
+{0x1.35dce49ad36e2p+0, -0x1.87120a645c000p-3},
+{0x1.34679984dd440p+0, -0x1.7d68fb4143000p-3},
+{0x1.32f5cceffcb24p+0, -0x1.73cb83c627000p-3},
+{0x1.3187775a10d49p+0, -0x1.6a39a9b376000p-3},
+{0x1.301c8373e3990p+0, -0x1.60b3154b7a000p-3},
+{0x1.2eb4ebb95f841p+0, -0x1.5737d76243000p-3},
+{0x1.2d50a0219a9d1p+0, -0x1.4dc7b8fc23000p-3},
+{0x1.2bef9a8b7fd2ap+0, -0x1.4462c51d20000p-3},
+{0x1.2a91c7a0c1babp+0, -0x1.3b08abc830000p-3},
+{0x1.293726014b530p+0, -0x1.31b996b490000p-3},
+{0x1.27dfa5757a1f5p+0, -0x1.2875490a44000p-3},
+{0x1.268b39b1d3bbfp+0, -0x1.1f3b9f879a000p-3},
+{0x1.2539d838ff5bdp+0, -0x1.160c8252ca000p-3},
+{0x1.23eb7aac9083bp+0, -0x1.0ce7f57f72000p-3},
+{0x1.22a012ba940b6p+0, -0x1.03cdc49fea000p-3},
+{0x1.2157996cc4132p+0, -0x1.f57bdbc4b8000p-4},
+{0x1.201201dd2fc9bp+0, -0x1.e370896404000p-4},
+{0x1.1ecf4494d480bp+0, -0x1.d17983ef94000p-4},
+{0x1.1d8f5528f6569p+0, -0x1.bf9674ed8a000p-4},
+{0x1.1c52311577e7cp+0, -0x1.adc79202f6000p-4},
+{0x1.1b17c74cb26e9p+0, -0x1.9c0c3e7288000p-4},
+{0x1.19e010c2c1ab6p+0, -0x1.8a646b372c000p-4},
+{0x1.18ab07bb670bdp+0, -0x1.78d01b3ac0000p-4},
+{0x1.1778a25efbcb6p+0, -0x1.674f145380000p-4},
+{0x1.1648d354c31dap+0, -0x1.55e0e6d878000p-4},
+{0x1.151b990275fddp+0, -0x1.4485cdea1e000p-4},
+{0x1.13f0ea432d24cp+0, -0x1.333d94d6aa000p-4},
+{0x1.12c8b7210f9dap+0, -0x1.22079f8c56000p-4},
+{0x1.11a3028ecb531p+0, -0x1.10e4698622000p-4},
+{0x1.107fbda8434afp+0, -0x1.ffa6c6ad20000p-5},
+{0x1.0f5ee0f4e6bb3p+0, -0x1.dda8d4a774000p-5},
+{0x1.0e4065d2a9fcep+0, -0x1.bbcece4850000p-5},
+{0x1.0d244632ca521p+0, -0x1.9a1894012c000p-5},
+{0x1.0c0a77ce2981ap+0, -0x1.788583302c000p-5},
+{0x1.0af2f83c636d1p+0, -0x1.5715e67d68000p-5},
+{0x1.09ddb98a01339p+0, -0x1.35c8a49658000p-5},
+{0x1.08cabaf52e7dfp+0, -0x1.149e364154000p-5},
+{0x1.07b9f2f4e28fbp+0, -0x1.e72c082eb8000p-6},
+{0x1.06ab58c358f19p+0, -0x1.a55f152528000p-6},
+{0x1.059eea5ecf92cp+0, -0x1.63d62cf818000p-6},
+{0x1.04949cdd12c90p+0, -0x1.228fb8caa0000p-6},
+{0x1.038c6c6f0ada9p+0, -0x1.c317b20f90000p-7},
+{0x1.02865137932a9p+0, -0x1.419355daa0000p-7},
+{0x1.0182427ea7348p+0, -0x1.81203c2ec0000p-8},
+{0x1.008040614b195p+0, -0x1.0040979240000p-9},
+{0x1.fe01ff726fa1ap-1, 0x1.feff384900000p-9},
+{0x1.fa11cc261ea74p-1, 0x1.7dc41353d0000p-7},
+{0x1.f6310b081992ep-1, 0x1.3cea3c4c28000p-6},
+{0x1.f25f63ceeadcdp-1, 0x1.b9fc114890000p-6},
+{0x1.ee9c8039113e7p-1, 0x1.1b0d8ce110000p-5},
+{0x1.eae8078cbb1abp-1, 0x1.58a5bd001c000p-5},
+{0x1.e741aa29d0c9bp-1, 0x1.95c8340d88000p-5},
+{0x1.e3a91830a99b5p-1, 0x1.d276aef578000p-5},
+{0x1.e01e009609a56p-1, 0x1.07598e598c000p-4},
+{0x1.dca01e577bb98p-1, 0x1.253f5e30d2000p-4},
+{0x1.d92f20b7c9103p-1, 0x1.42edd8b380000p-4},
+{0x1.d5cac66fb5ccep-1, 0x1.606598757c000p-4},
+{0x1.d272caa5ede9dp-1, 0x1.7da76356a0000p-4},
+{0x1.cf26e3e6b2ccdp-1, 0x1.9ab434e1c6000p-4},
+{0x1.cbe6da2a77902p-1, 0x1.b78c7bb0d6000p-4},
+{0x1.c8b266d37086dp-1, 0x1.d431332e72000p-4},
+{0x1.c5894bd5d5804p-1, 0x1.f0a3171de6000p-4},
+{0x1.c26b533bb9f8cp-1, 0x1.067152b914000p-3},
+{0x1.bf583eeece73fp-1, 0x1.147858292b000p-3},
+{0x1.bc4fd75db96c1p-1, 0x1.2266ecdca3000p-3},
+{0x1.b951e0c864a28p-1, 0x1.303d7a6c55000p-3},
+{0x1.b65e2c5ef3e2cp-1, 0x1.3dfc33c331000p-3},
+{0x1.b374867c9888bp-1, 0x1.4ba366b7a8000p-3},
+{0x1.b094b211d304ap-1, 0x1.5933928d1f000p-3},
+{0x1.adbe885f2ef7ep-1, 0x1.66acd2418f000p-3},
+{0x1.aaf1d31603da2p-1, 0x1.740f8ec669000p-3},
+{0x1.a82e63fd358a7p-1, 0x1.815c0f51af000p-3},
+{0x1.a5740ef09738bp-1, 0x1.8e92954f68000p-3},
+{0x1.a2c2a90ab4b27p-1, 0x1.9bb3602f84000p-3},
+{0x1.a01a01393f2d1p-1, 0x1.a8bed1c2c0000p-3},
+{0x1.9d79f24db3c1bp-1, 0x1.b5b515c01d000p-3},
+{0x1.9ae2505c7b190p-1, 0x1.c2967ccbcc000p-3},
+{0x1.9852ef297ce2fp-1, 0x1.cf635d5486000p-3},
+{0x1.95cbaeea44b75p-1, 0x1.dc1bd3446c000p-3},
+{0x1.934c69de74838p-1, 0x1.e8c01b8cfe000p-3},
+{0x1.90d4f2f6752e6p-1, 0x1.f5509c0179000p-3},
+{0x1.8e6528effd79dp-1, 0x1.00e6c121fb800p-2},
+{0x1.8bfce9fcc007cp-1, 0x1.071b80e93d000p-2},
+{0x1.899c0dabec30ep-1, 0x1.0d46b9e867000p-2},
+{0x1.87427aa2317fbp-1, 0x1.13687334bd000p-2},
+{0x1.84f00acb39a08p-1, 0x1.1980d67234800p-2},
+{0x1.82a49e8653e55p-1, 0x1.1f8ffe0cc8000p-2},
+{0x1.8060195f40260p-1, 0x1.2595fd7636800p-2},
+{0x1.7e22563e0a329p-1, 0x1.2b9300914a800p-2},
+{0x1.7beb377dcb5adp-1, 0x1.3187210436000p-2},
+{0x1.79baa679725c2p-1, 0x1.377266dec1800p-2},
+{0x1.77907f2170657p-1, 0x1.3d54ffbaf3000p-2},
+{0x1.756cadbd6130cp-1, 0x1.432eee32fe000p-2},
+#endif
+},
+#if !HAVE_FAST_FMA
+.tab2 = {
+# if N == 64
+{0x1.61ffff94c4fecp-1, -0x1.9fe4fc998f325p-56},
+{0x1.66000020377ddp-1, 0x1.e804c7a9519f2p-55},
+{0x1.6a00004c41678p-1, 0x1.902c675d9ecfep-55},
+{0x1.6dffff7384f87p-1, -0x1.2fd6b95e55043p-56},
+{0x1.720000b37216ep-1, 0x1.802bc8d437043p-55},
+{0x1.75ffffbeb3c9dp-1, 0x1.6047ad0a0d4e4p-57},
+{0x1.7a0000628daep-1, -0x1.e00434b49313dp-56},
+{0x1.7dffffd7abd1ap-1, -0x1.6015f8a083576p-56},
+{0x1.81ffffdf40c54p-1, 0x1.7f54bf76a42c9p-57},
+{0x1.860000f334e11p-1, 0x1.60054cb5344d7p-56},
+{0x1.8a0001238aca7p-1, 0x1.c03c9bd132f55p-57},
+{0x1.8dffffb81d212p-1, -0x1.001e519f2764fp-55},
+{0x1.92000086adc7cp-1, 0x1.1fe40f88f49c6p-55},
+{0x1.960000135d8eap-1, -0x1.f832268dc3095p-55},
+{0x1.99ffff9435acp-1, 0x1.7031d8b835edcp-56},
+{0x1.9e00003478565p-1, -0x1.0030b221ce3eep-58},
+{0x1.a20000b592948p-1, 0x1.8fd2f1dbd4639p-55},
+{0x1.a600000ad0bcfp-1, 0x1.901d6a974e6bep-55},
+{0x1.a9ffff55953a5p-1, 0x1.a07556192db98p-57},
+{0x1.adffff29ce03dp-1, -0x1.fff0717ec71c2p-56},
+{0x1.b1ffff34f3ac8p-1, 0x1.8005573de89d1p-57},
+{0x1.b60000894c55bp-1, -0x1.ff2fb51b044c7p-57},
+{0x1.b9fffef45ec7dp-1, -0x1.9ff7c4e8730fp-56},
+{0x1.be0000cda7b2ap-1, 0x1.57d058dbf3c1dp-55},
+{0x1.c1ffff2c57917p-1, 0x1.7e66d7e48dbc9p-58},
+{0x1.c60000ea5b82ap-1, -0x1.47f5e132ed4bep-55},
+{0x1.ca0001121ae98p-1, -0x1.40958c8d5e00ap-58},
+{0x1.ce0000f9241cbp-1, -0x1.7da063caa81c8p-59},
+{0x1.d1fffe8be95a4p-1, -0x1.82e3a411afcd9p-59},
+{0x1.d5ffff035932bp-1, -0x1.00f901b3fe87dp-58},
+{0x1.d9fffe8b54ba7p-1, 0x1.ffef55d6e3a4p-55},
+{0x1.de0000ad95d19p-1, 0x1.5feb2efd4c7c7p-55},
+{0x1.e1fffe925ce47p-1, 0x1.c8085484eaf08p-55},
+{0x1.e5fffe3ddf853p-1, -0x1.fd5ed02c5cadp-60},
+{0x1.e9fffed0a0e5fp-1, -0x1.a80aaef411586p-55},
+{0x1.ee00008f82eep-1, -0x1.b000aeaf97276p-55},
+{0x1.f20000a22d2f4p-1, -0x1.8f8906e13eba3p-56},
+{0x1.f5fffee35b57dp-1, 0x1.1fdd33b2d3714p-57},
+{0x1.fa00014eec3a6p-1, -0x1.3ee0b7a18c1a5p-58},
+{0x1.fdffff5daa89fp-1, -0x1.c1e24c8e3b503p-58},
+{0x1.0200005b93349p+0, -0x1.50197fe6bedcap-54},
+{0x1.05ffff9d597acp+0, 0x1.20160d062d0dcp-55},
+{0x1.0a00005687a63p+0, -0x1.27f3f9307696ep-54},
+{0x1.0dffff779164ep+0, 0x1.b7eb40bb9c4f4p-54},
+{0x1.12000044a0aa8p+0, 0x1.efbc914d512c4p-55},
+{0x1.16000069685bcp+0, -0x1.c0bea3eb2d82cp-57},
+{0x1.1a000093f0d78p+0, 0x1.1fecbf1e8c52p-54},
+{0x1.1dffffb2b1457p+0, -0x1.3fc91365637d6p-55},
+{0x1.2200008824a1p+0, -0x1.dff7e9feb578ap-54},
+{0x1.25ffffeef953p+0, -0x1.b00a61ec912f7p-55},
+{0x1.2a0000a1e7783p+0, 0x1.60048318b0483p-56},
+{0x1.2e0000853d4c7p+0, -0x1.77fbedf2c8cf3p-54},
+{0x1.320000324c55bp+0, 0x1.f81983997354fp-54},
+{0x1.360000594f796p+0, -0x1.cfe4beff900a9p-54},
+{0x1.3a0000a4c1c0fp+0, 0x1.07dbb2e268d0ep-54},
+{0x1.3e0000751c61bp+0, 0x1.80583ed1c566ep-56},
+{0x1.42000069e8a9fp+0, 0x1.f01f1edf82045p-54},
+{0x1.460000b5a1e34p+0, -0x1.dfdf0cf45c14ap-55},
+{0x1.4a0000187e513p+0, 0x1.401306b83a98dp-55},
+{0x1.4dffff3ba420bp+0, 0x1.9fc6539a6454ep-56},
+{0x1.51fffffe391c9p+0, -0x1.601ef3353ac83p-54},
+{0x1.560000e342455p+0, 0x1.3fb7fac8ac151p-55},
+{0x1.59ffffc39676fp+0, 0x1.4fe7dd6659cc2p-55},
+{0x1.5dfffff10ef42p+0, -0x1.48154cb592bcbp-54},
+# elif N == 128
+{0x1.61000014fb66bp-1, 0x1.e026c91425b3cp-56},
+{0x1.63000034db495p-1, 0x1.dbfea48005d41p-55},
+{0x1.650000d94d478p-1, 0x1.e7fa786d6a5b7p-55},
+{0x1.67000074e6fadp-1, 0x1.1fcea6b54254cp-57},
+{0x1.68ffffedf0faep-1, -0x1.c7e274c590efdp-56},
+{0x1.6b0000763c5bcp-1, -0x1.ac16848dcda01p-55},
+{0x1.6d0001e5cc1f6p-1, 0x1.33f1c9d499311p-55},
+{0x1.6efffeb05f63ep-1, -0x1.e80041ae22d53p-56},
+{0x1.710000e86978p-1, 0x1.bff6671097952p-56},
+{0x1.72ffffc67e912p-1, 0x1.c00e226bd8724p-55},
+{0x1.74fffdf81116ap-1, -0x1.e02916ef101d2p-57},
+{0x1.770000f679c9p-1, -0x1.7fc71cd549c74p-57},
+{0x1.78ffffa7ec835p-1, 0x1.1bec19ef50483p-55},
+{0x1.7affffe20c2e6p-1, -0x1.07e1729cc6465p-56},
+{0x1.7cfffed3fc9p-1, -0x1.08072087b8b1cp-55},
+{0x1.7efffe9261a76p-1, 0x1.dc0286d9df9aep-55},
+{0x1.81000049ca3e8p-1, 0x1.97fd251e54c33p-55},
+{0x1.8300017932c8fp-1, -0x1.afee9b630f381p-55},
+{0x1.850000633739cp-1, 0x1.9bfbf6b6535bcp-55},
+{0x1.87000204289c6p-1, -0x1.bbf65f3117b75p-55},
+{0x1.88fffebf57904p-1, -0x1.9006ea23dcb57p-55},
+{0x1.8b00022bc04dfp-1, -0x1.d00df38e04b0ap-56},
+{0x1.8cfffe50c1b8ap-1, -0x1.8007146ff9f05p-55},
+{0x1.8effffc918e43p-1, 0x1.3817bd07a7038p-55},
+{0x1.910001efa5fc7p-1, 0x1.93e9176dfb403p-55},
+{0x1.9300013467bb9p-1, 0x1.f804e4b980276p-56},
+{0x1.94fffe6ee076fp-1, -0x1.f7ef0d9ff622ep-55},
+{0x1.96fffde3c12d1p-1, -0x1.082aa962638bap-56},
+{0x1.98ffff4458a0dp-1, -0x1.7801b9164a8efp-55},
+{0x1.9afffdd982e3ep-1, -0x1.740e08a5a9337p-55},
+{0x1.9cfffed49fb66p-1, 0x1.fce08c19bep-60},
+{0x1.9f00020f19c51p-1, -0x1.a3faa27885b0ap-55},
+{0x1.a10001145b006p-1, 0x1.4ff489958da56p-56},
+{0x1.a300007bbf6fap-1, 0x1.cbeab8a2b6d18p-55},
+{0x1.a500010971d79p-1, 0x1.8fecadd78793p-55},
+{0x1.a70001df52e48p-1, -0x1.f41763dd8abdbp-55},
+{0x1.a90001c593352p-1, -0x1.ebf0284c27612p-55},
+{0x1.ab0002a4f3e4bp-1, -0x1.9fd043cff3f5fp-57},
+{0x1.acfffd7ae1ed1p-1, -0x1.23ee7129070b4p-55},
+{0x1.aefffee510478p-1, 0x1.a063ee00edea3p-57},
+{0x1.b0fffdb650d5bp-1, 0x1.a06c8381f0ab9p-58},
+{0x1.b2ffffeaaca57p-1, -0x1.9011e74233c1dp-56},
+{0x1.b4fffd995badcp-1, -0x1.9ff1068862a9fp-56},
+{0x1.b7000249e659cp-1, 0x1.aff45d0864f3ep-55},
+{0x1.b8ffff987164p-1, 0x1.cfe7796c2c3f9p-56},
+{0x1.bafffd204cb4fp-1, -0x1.3ff27eef22bc4p-57},
+{0x1.bcfffd2415c45p-1, -0x1.cffb7ee3bea21p-57},
+{0x1.beffff86309dfp-1, -0x1.14103972e0b5cp-55},
+{0x1.c0fffe1b57653p-1, 0x1.bc16494b76a19p-55},
+{0x1.c2ffff1fa57e3p-1, -0x1.4feef8d30c6edp-57},
+{0x1.c4fffdcbfe424p-1, -0x1.43f68bcec4775p-55},
+{0x1.c6fffed54b9f7p-1, 0x1.47ea3f053e0ecp-55},
+{0x1.c8fffeb998fd5p-1, 0x1.383068df992f1p-56},
+{0x1.cb0002125219ap-1, -0x1.8fd8e64180e04p-57},
+{0x1.ccfffdd94469cp-1, 0x1.e7ebe1cc7ea72p-55},
+{0x1.cefffeafdc476p-1, 0x1.ebe39ad9f88fep-55},
+{0x1.d1000169af82bp-1, 0x1.57d91a8b95a71p-56},
+{0x1.d30000d0ff71dp-1, 0x1.9c1906970c7dap-55},
+{0x1.d4fffea790fc4p-1, -0x1.80e37c558fe0cp-58},
+{0x1.d70002edc87e5p-1, -0x1.f80d64dc10f44p-56},
+{0x1.d900021dc82aap-1, -0x1.47c8f94fd5c5cp-56},
+{0x1.dafffd86b0283p-1, 0x1.c7f1dc521617ep-55},
+{0x1.dd000296c4739p-1, 0x1.8019eb2ffb153p-55},
+{0x1.defffe54490f5p-1, 0x1.e00d2c652cc89p-57},
+{0x1.e0fffcdabf694p-1, -0x1.f8340202d69d2p-56},
+{0x1.e2fffdb52c8ddp-1, 0x1.b00c1ca1b0864p-56},
+{0x1.e4ffff24216efp-1, 0x1.2ffa8b094ab51p-56},
+{0x1.e6fffe88a5e11p-1, -0x1.7f673b1efbe59p-58},
+{0x1.e9000119eff0dp-1, -0x1.4808d5e0bc801p-55},
+{0x1.eafffdfa51744p-1, 0x1.80006d54320b5p-56},
+{0x1.ed0001a127fa1p-1, -0x1.002f860565c92p-58},
+{0x1.ef00007babcc4p-1, -0x1.540445d35e611p-55},
+{0x1.f0ffff57a8d02p-1, -0x1.ffb3139ef9105p-59},
+{0x1.f30001ee58ac7p-1, 0x1.a81acf2731155p-55},
+{0x1.f4ffff5823494p-1, 0x1.a3f41d4d7c743p-55},
+{0x1.f6ffffca94c6bp-1, -0x1.202f41c987875p-57},
+{0x1.f8fffe1f9c441p-1, 0x1.77dd1f477e74bp-56},
+{0x1.fafffd2e0e37ep-1, -0x1.f01199a7ca331p-57},
+{0x1.fd0001c77e49ep-1, 0x1.181ee4bceacb1p-56},
+{0x1.feffff7e0c331p-1, -0x1.e05370170875ap-57},
+{0x1.00ffff465606ep+0, -0x1.a7ead491c0adap-55},
+{0x1.02ffff3867a58p+0, -0x1.77f69c3fcb2ep-54},
+{0x1.04ffffdfc0d17p+0, 0x1.7bffe34cb945bp-54},
+{0x1.0700003cd4d82p+0, 0x1.20083c0e456cbp-55},
+{0x1.08ffff9f2cbe8p+0, -0x1.dffdfbe37751ap-57},
+{0x1.0b000010cda65p+0, -0x1.13f7faee626ebp-54},
+{0x1.0d00001a4d338p+0, 0x1.07dfa79489ff7p-55},
+{0x1.0effffadafdfdp+0, -0x1.7040570d66bcp-56},
+{0x1.110000bbafd96p+0, 0x1.e80d4846d0b62p-55},
+{0x1.12ffffae5f45dp+0, 0x1.dbffa64fd36efp-54},
+{0x1.150000dd59ad9p+0, 0x1.a0077701250aep-54},
+{0x1.170000f21559ap+0, 0x1.dfdf9e2e3deeep-55},
+{0x1.18ffffc275426p+0, 0x1.10030dc3b7273p-54},
+{0x1.1b000123d3c59p+0, 0x1.97f7980030188p-54},
+{0x1.1cffff8299eb7p+0, -0x1.5f932ab9f8c67p-57},
+{0x1.1effff48ad4p+0, 0x1.37fbf9da75bebp-54},
+{0x1.210000c8b86a4p+0, 0x1.f806b91fd5b22p-54},
+{0x1.2300003854303p+0, 0x1.3ffc2eb9fbf33p-54},
+{0x1.24fffffbcf684p+0, 0x1.601e77e2e2e72p-56},
+{0x1.26ffff52921d9p+0, 0x1.ffcbb767f0c61p-56},
+{0x1.2900014933a3cp+0, -0x1.202ca3c02412bp-56},
+{0x1.2b00014556313p+0, -0x1.2808233f21f02p-54},
+{0x1.2cfffebfe523bp+0, -0x1.8ff7e384fdcf2p-55},
+{0x1.2f0000bb8ad96p+0, -0x1.5ff51503041c5p-55},
+{0x1.30ffffb7ae2afp+0, -0x1.10071885e289dp-55},
+{0x1.32ffffeac5f7fp+0, -0x1.1ff5d3fb7b715p-54},
+{0x1.350000ca66756p+0, 0x1.57f82228b82bdp-54},
+{0x1.3700011fbf721p+0, 0x1.000bac40dd5ccp-55},
+{0x1.38ffff9592fb9p+0, -0x1.43f9d2db2a751p-54},
+{0x1.3b00004ddd242p+0, 0x1.57f6b707638e1p-55},
+{0x1.3cffff5b2c957p+0, 0x1.a023a10bf1231p-56},
+{0x1.3efffeab0b418p+0, 0x1.87f6d66b152bp-54},
+{0x1.410001532aff4p+0, 0x1.7f8375f198524p-57},
+{0x1.4300017478b29p+0, 0x1.301e672dc5143p-55},
+{0x1.44fffe795b463p+0, 0x1.9ff69b8b2895ap-55},
+{0x1.46fffe80475ep+0, -0x1.5c0b19bc2f254p-54},
+{0x1.48fffef6fc1e7p+0, 0x1.b4009f23a2a72p-54},
+{0x1.4afffe5bea704p+0, -0x1.4ffb7bf0d7d45p-54},
+{0x1.4d000171027dep+0, -0x1.9c06471dc6a3dp-54},
+{0x1.4f0000ff03ee2p+0, 0x1.77f890b85531cp-54},
+{0x1.5100012dc4bd1p+0, 0x1.004657166a436p-57},
+{0x1.530001605277ap+0, -0x1.6bfcece233209p-54},
+{0x1.54fffecdb704cp+0, -0x1.902720505a1d7p-55},
+{0x1.56fffef5f54a9p+0, 0x1.bbfe60ec96412p-54},
+{0x1.5900017e61012p+0, 0x1.87ec581afef9p-55},
+{0x1.5b00003c93e92p+0, -0x1.f41080abf0ccp-54},
+{0x1.5d0001d4919bcp+0, -0x1.8812afb254729p-54},
+{0x1.5efffe7b87a89p+0, -0x1.47eb780ed6904p-54},
+#endif
+},
+#endif /* !HAVE_FAST_FMA */
+};
diff --git a/libc/AOR_v20.02/math/logf.c b/libc/AOR_v20.02/math/logf.c
new file mode 100644 (file)
index 0000000..5afe629
--- /dev/null
@@ -0,0 +1,80 @@
+/*
+ * Single-precision log function.
+ *
+ * Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+ * See https://llvm.org/LICENSE.txt for license information.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include <math.h>
+#include <stdint.h>
+#include "math_config.h"
+
+/*
+LOGF_TABLE_BITS = 4
+LOGF_POLY_ORDER = 4
+
+ULP error: 0.818 (nearest rounding.)
+Relative error: 1.957 * 2^-26 (before rounding.)
+*/
+
+#define T __logf_data.tab
+#define A __logf_data.poly
+#define Ln2 __logf_data.ln2
+#define N (1 << LOGF_TABLE_BITS)
+#define OFF 0x3f330000
+
+float
+logf (float x)
+{
+  /* double_t for better performance on targets with FLT_EVAL_METHOD==2.  */
+  double_t z, r, r2, y, y0, invc, logc;
+  uint32_t ix, iz, tmp;
+  int k, i;
+
+  ix = asuint (x);
+#if WANT_ROUNDING
+  /* Fix sign of zero with downward rounding when x==1.  */
+  if (unlikely (ix == 0x3f800000))
+    return 0;
+#endif
+  if (unlikely (ix - 0x00800000 >= 0x7f800000 - 0x00800000))
+    {
+      /* x < 0x1p-126 or inf or nan.  */
+      if (ix * 2 == 0)
+       return __math_divzerof (1);
+      if (ix == 0x7f800000) /* log(inf) == inf.  */
+       return x;
+      if ((ix & 0x80000000) || ix * 2 >= 0xff000000)
+       return __math_invalidf (x);
+      /* x is subnormal, normalize it.  */
+      ix = asuint (x * 0x1p23f);
+      ix -= 23 << 23;
+    }
+
+  /* x = 2^k z; where z is in range [OFF,2*OFF] and exact.
+     The range is split into N subintervals.
+     The ith subinterval contains z and c is near its center.  */
+  tmp = ix - OFF;
+  i = (tmp >> (23 - LOGF_TABLE_BITS)) % N;
+  k = (int32_t) tmp >> 23; /* arithmetic shift */
+  iz = ix - (tmp & 0x1ff << 23);
+  invc = T[i].invc;
+  logc = T[i].logc;
+  z = (double_t) asfloat (iz);
+
+  /* log(x) = log1p(z/c-1) + log(c) + k*Ln2 */
+  r = z * invc - 1;
+  y0 = logc + (double_t) k * Ln2;
+
+  /* Pipelined polynomial evaluation to approximate log1p(r).  */
+  r2 = r * r;
+  y = A[1] * r + A[2];
+  y = A[0] * r2 + y;
+  y = y * r2 + (y0 + r);
+  return eval_as_float (y);
+}
+#if USE_GLIBC_ABI
+strong_alias (logf, __logf_finite)
+hidden_alias (logf, __ieee754_logf)
+#endif
diff --git a/libc/AOR_v20.02/math/logf_data.c b/libc/AOR_v20.02/math/logf_data.c
new file mode 100644 (file)
index 0000000..e4de10f
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * Data definition for logf.
+ *
+ * Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+ * See https://llvm.org/LICENSE.txt for license information.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "math_config.h"
+
+const struct logf_data __logf_data = {
+  .tab = {
+  { 0x1.661ec79f8f3bep+0, -0x1.57bf7808caadep-2 },
+  { 0x1.571ed4aaf883dp+0, -0x1.2bef0a7c06ddbp-2 },
+  { 0x1.49539f0f010bp+0, -0x1.01eae7f513a67p-2 },
+  { 0x1.3c995b0b80385p+0, -0x1.b31d8a68224e9p-3 },
+  { 0x1.30d190c8864a5p+0, -0x1.6574f0ac07758p-3 },
+  { 0x1.25e227b0b8eap+0, -0x1.1aa2bc79c81p-3 },
+  { 0x1.1bb4a4a1a343fp+0, -0x1.a4e76ce8c0e5ep-4 },
+  { 0x1.12358f08ae5bap+0, -0x1.1973c5a611cccp-4 },
+  { 0x1.0953f419900a7p+0, -0x1.252f438e10c1ep-5 },
+  { 0x1p+0, 0x0p+0 },
+  { 0x1.e608cfd9a47acp-1, 0x1.aa5aa5df25984p-5 },
+  { 0x1.ca4b31f026aap-1, 0x1.c5e53aa362eb4p-4 },
+  { 0x1.b2036576afce6p-1, 0x1.526e57720db08p-3 },
+  { 0x1.9c2d163a1aa2dp-1, 0x1.bc2860d22477p-3 },
+  { 0x1.886e6037841edp-1, 0x1.1058bc8a07ee1p-2 },
+  { 0x1.767dcf5534862p-1, 0x1.4043057b6ee09p-2 },
+  },
+  .ln2 = 0x1.62e42fefa39efp-1,
+  .poly = {
+  -0x1.00ea348b88334p-2, 0x1.5575b0be00b6ap-2, -0x1.ffffef20a4123p-2,
+  }
+};
diff --git a/libc/AOR_v20.02/math/math_config.h b/libc/AOR_v20.02/math/math_config.h
new file mode 100644 (file)
index 0000000..ea2d59e
--- /dev/null
@@ -0,0 +1,420 @@
+/*
+ * Configuration for math routines.
+ *
+ * Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+ * See https://llvm.org/LICENSE.txt for license information.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef _MATH_CONFIG_H
+#define _MATH_CONFIG_H
+
+#include <math.h>
+#include <stdint.h>
+
+#ifndef WANT_ROUNDING
+/* If defined to 1, return correct results for special cases in non-nearest
+   rounding modes (logf (1.0f) returns 0.0f with FE_DOWNWARD rather than -0.0f).
+   This may be set to 0 if there is no fenv support or if math functions only
+   get called in round to nearest mode.  */
+# define WANT_ROUNDING 1
+#endif
+#ifndef WANT_ERRNO
+/* If defined to 1, set errno in math functions according to ISO C.  Many math
+   libraries do not set errno, so this is 0 by default.  It may need to be
+   set to 1 if math.h has (math_errhandling & MATH_ERRNO) != 0.  */
+# define WANT_ERRNO 0
+#endif
+#ifndef WANT_ERRNO_UFLOW
+/* Set errno to ERANGE if result underflows to 0 (in all rounding modes).  */
+# define WANT_ERRNO_UFLOW (WANT_ROUNDING && WANT_ERRNO)
+#endif
+
+/* Compiler can inline round as a single instruction.  */
+#ifndef HAVE_FAST_ROUND
+# if __aarch64__
+#   define HAVE_FAST_ROUND 1
+# else
+#   define HAVE_FAST_ROUND 0
+# endif
+#endif
+
+/* Compiler can inline lround, but not (long)round(x).  */
+#ifndef HAVE_FAST_LROUND
+# if __aarch64__ && (100*__GNUC__ + __GNUC_MINOR__) >= 408 && __NO_MATH_ERRNO__
+#   define HAVE_FAST_LROUND 1
+# else
+#   define HAVE_FAST_LROUND 0
+# endif
+#endif
+
+/* Compiler can inline fma as a single instruction.  */
+#ifndef HAVE_FAST_FMA
+# if defined FP_FAST_FMA || __aarch64__
+#   define HAVE_FAST_FMA 1
+# else
+#   define HAVE_FAST_FMA 0
+# endif
+#endif
+
+/* Provide *_finite symbols and some of the glibc hidden symbols
+   so libmathlib can be used with binaries compiled against glibc
+   to interpose math functions with both static and dynamic linking.  */
+#ifndef USE_GLIBC_ABI
+# if __GNUC__
+#   define USE_GLIBC_ABI 1
+# else
+#   define USE_GLIBC_ABI 0
+# endif
+#endif
+
+/* Optionally used extensions.  */
+#ifdef __GNUC__
+# define HIDDEN __attribute__ ((__visibility__ ("hidden")))
+# define NOINLINE __attribute__ ((noinline))
+# define UNUSED __attribute__ ((unused))
+# define likely(x) __builtin_expect (!!(x), 1)
+# define unlikely(x) __builtin_expect (x, 0)
+# if __GNUC__ >= 9
+#   define attribute_copy(f) __attribute__ ((copy (f)))
+# else
+#   define attribute_copy(f)
+# endif
+# define strong_alias(f, a) \
+  extern __typeof (f) a __attribute__ ((alias (#f))) attribute_copy (f);
+# define hidden_alias(f, a) \
+  extern __typeof (f) a __attribute__ ((alias (#f), visibility ("hidden"))) \
+  attribute_copy (f);
+#else
+# define HIDDEN
+# define NOINLINE
+# define UNUSED
+# define likely(x) (x)
+# define unlikely(x) (x)
+#endif
+
+#if HAVE_FAST_ROUND
+/* When set, the roundtoint and converttoint functions are provided with
+   the semantics documented below.  */
+# define TOINT_INTRINSICS 1
+
+/* Round x to nearest int in all rounding modes, ties have to be rounded
+   consistently with converttoint so the results match.  If the result
+   would be outside of [-2^31, 2^31-1] then the semantics is unspecified.  */
+static inline double_t
+roundtoint (double_t x)
+{
+  return round (x);
+}
+
+/* Convert x to nearest int in all rounding modes, ties have to be rounded
+   consistently with roundtoint.  If the result is not representible in an
+   int32_t then the semantics is unspecified.  */
+static inline int32_t
+converttoint (double_t x)
+{
+# if HAVE_FAST_LROUND
+  return lround (x);
+# else
+  return (long) round (x);
+# endif
+}
+#endif
+
+static inline uint32_t
+asuint (float f)
+{
+  union
+  {
+    float f;
+    uint32_t i;
+  } u = {f};
+  return u.i;
+}
+
+static inline float
+asfloat (uint32_t i)
+{
+  union
+  {
+    uint32_t i;
+    float f;
+  } u = {i};
+  return u.f;
+}
+
+static inline uint64_t
+asuint64 (double f)
+{
+  union
+  {
+    double f;
+    uint64_t i;
+  } u = {f};
+  return u.i;
+}
+
+static inline double
+asdouble (uint64_t i)
+{
+  union
+  {
+    uint64_t i;
+    double f;
+  } u = {i};
+  return u.f;
+}
+
+#ifndef IEEE_754_2008_SNAN
+# define IEEE_754_2008_SNAN 1
+#endif
+static inline int
+issignalingf_inline (float x)
+{
+  uint32_t ix = asuint (x);
+  if (!IEEE_754_2008_SNAN)
+    return (ix & 0x7fc00000) == 0x7fc00000;
+  return 2 * (ix ^ 0x00400000) > 2u * 0x7fc00000;
+}
+
+static inline int
+issignaling_inline (double x)
+{
+  uint64_t ix = asuint64 (x);
+  if (!IEEE_754_2008_SNAN)
+    return (ix & 0x7ff8000000000000) == 0x7ff8000000000000;
+  return 2 * (ix ^ 0x0008000000000000) > 2 * 0x7ff8000000000000ULL;
+}
+
+#if __aarch64__ && __GNUC__
+/* Prevent the optimization of a floating-point expression.  */
+static inline float
+opt_barrier_float (float x)
+{
+  __asm__ __volatile__ ("" : "+w" (x));
+  return x;
+}
+static inline double
+opt_barrier_double (double x)
+{
+  __asm__ __volatile__ ("" : "+w" (x));
+  return x;
+}
+/* Force the evaluation of a floating-point expression for its side-effect.  */
+static inline void
+force_eval_float (float x)
+{
+  __asm__ __volatile__ ("" : "+w" (x));
+}
+static inline void
+force_eval_double (double x)
+{
+  __asm__ __volatile__ ("" : "+w" (x));
+}
+#else
+static inline float
+opt_barrier_float (float x)
+{
+  volatile float y = x;
+  return y;
+}
+static inline double
+opt_barrier_double (double x)
+{
+  volatile double y = x;
+  return y;
+}
+static inline void
+force_eval_float (float x)
+{
+  volatile float y UNUSED = x;
+}
+static inline void
+force_eval_double (double x)
+{
+  volatile double y UNUSED = x;
+}
+#endif
+
+/* Evaluate an expression as the specified type, normally a type
+   cast should be enough, but compilers implement non-standard
+   excess-precision handling, so when FLT_EVAL_METHOD != 0 then
+   these functions may need to be customized.  */
+static inline float
+eval_as_float (float x)
+{
+  return x;
+}
+static inline double
+eval_as_double (double x)
+{
+  return x;
+}
+
+/* Error handling tail calls for special cases, with a sign argument.
+   The sign of the return value is set if the argument is non-zero.  */
+
+/* The result overflows.  */
+HIDDEN float __math_oflowf (uint32_t);
+/* The result underflows to 0 in nearest rounding mode.  */
+HIDDEN float __math_uflowf (uint32_t);
+/* The result underflows to 0 in some directed rounding mode only.  */
+HIDDEN float __math_may_uflowf (uint32_t);
+/* Division by zero.  */
+HIDDEN float __math_divzerof (uint32_t);
+/* The result overflows.  */
+HIDDEN double __math_oflow (uint32_t);
+/* The result underflows to 0 in nearest rounding mode.  */
+HIDDEN double __math_uflow (uint32_t);
+/* The result underflows to 0 in some directed rounding mode only.  */
+HIDDEN double __math_may_uflow (uint32_t);
+/* Division by zero.  */
+HIDDEN double __math_divzero (uint32_t);
+
+/* Error handling using input checking.  */
+
+/* Invalid input unless it is a quiet NaN.  */
+HIDDEN float __math_invalidf (float);
+/* Invalid input unless it is a quiet NaN.  */
+HIDDEN double __math_invalid (double);
+
+/* Error handling using output checking, only for errno setting.  */
+
+/* Check if the result overflowed to infinity.  */
+HIDDEN double __math_check_oflow (double);
+/* Check if the result underflowed to 0.  */
+HIDDEN double __math_check_uflow (double);
+
+/* Check if the result overflowed to infinity.  */
+static inline double
+check_oflow (double x)
+{
+  return WANT_ERRNO ? __math_check_oflow (x) : x;
+}
+
+/* Check if the result underflowed to 0.  */
+static inline double
+check_uflow (double x)
+{
+  return WANT_ERRNO ? __math_check_uflow (x) : x;
+}
+
+
+/* Shared between expf, exp2f and powf.  */
+#define EXP2F_TABLE_BITS 5
+#define EXP2F_POLY_ORDER 3
+extern const struct exp2f_data
+{
+  uint64_t tab[1 << EXP2F_TABLE_BITS];
+  double shift_scaled;
+  double poly[EXP2F_POLY_ORDER];
+  double shift;
+  double invln2_scaled;
+  double poly_scaled[EXP2F_POLY_ORDER];
+} __exp2f_data HIDDEN;
+
+#define LOGF_TABLE_BITS 4
+#define LOGF_POLY_ORDER 4
+extern const struct logf_data
+{
+  struct
+  {
+    double invc, logc;
+  } tab[1 << LOGF_TABLE_BITS];
+  double ln2;
+  double poly[LOGF_POLY_ORDER - 1]; /* First order coefficient is 1.  */
+} __logf_data HIDDEN;
+
+#define LOG2F_TABLE_BITS 4
+#define LOG2F_POLY_ORDER 4
+extern const struct log2f_data
+{
+  struct
+  {
+    double invc, logc;
+  } tab[1 << LOG2F_TABLE_BITS];
+  double poly[LOG2F_POLY_ORDER];
+} __log2f_data HIDDEN;
+
+#define POWF_LOG2_TABLE_BITS 4
+#define POWF_LOG2_POLY_ORDER 5
+#if TOINT_INTRINSICS
+# define POWF_SCALE_BITS EXP2F_TABLE_BITS
+#else
+# define POWF_SCALE_BITS 0
+#endif
+#define POWF_SCALE ((double) (1 << POWF_SCALE_BITS))
+extern const struct powf_log2_data
+{
+  struct
+  {
+    double invc, logc;
+  } tab[1 << POWF_LOG2_TABLE_BITS];
+  double poly[POWF_LOG2_POLY_ORDER];
+} __powf_log2_data HIDDEN;
+
+
+#define EXP_TABLE_BITS 7
+#define EXP_POLY_ORDER 5
+/* Use polynomial that is optimized for a wider input range.  This may be
+   needed for good precision in non-nearest rounding and !TOINT_INTRINSICS.  */
+#define EXP_POLY_WIDE 0
+/* Use close to nearest rounding toint when !TOINT_INTRINSICS.  This may be
+   needed for good precision in non-nearest rouning and !EXP_POLY_WIDE.  */
+#define EXP_USE_TOINT_NARROW 0
+#define EXP2_POLY_ORDER 5
+#define EXP2_POLY_WIDE 0
+extern const struct exp_data
+{
+  double invln2N;
+  double shift;
+  double negln2hiN;
+  double negln2loN;
+  double poly[4]; /* Last four coefficients.  */
+  double exp2_shift;
+  double exp2_poly[EXP2_POLY_ORDER];
+  uint64_t tab[2*(1 << EXP_TABLE_BITS)];
+} __exp_data HIDDEN;
+
+#define LOG_TABLE_BITS 7
+#define LOG_POLY_ORDER 6
+#define LOG_POLY1_ORDER 12
+extern const struct log_data
+{
+  double ln2hi;
+  double ln2lo;
+  double poly[LOG_POLY_ORDER - 1]; /* First coefficient is 1.  */
+  double poly1[LOG_POLY1_ORDER - 1];
+  struct {double invc, logc;} tab[1 << LOG_TABLE_BITS];
+#if !HAVE_FAST_FMA
+  struct {double chi, clo;} tab2[1 << LOG_TABLE_BITS];
+#endif
+} __log_data HIDDEN;
+
+#define LOG2_TABLE_BITS 6
+#define LOG2_POLY_ORDER 7
+#define LOG2_POLY1_ORDER 11
+extern const struct log2_data
+{
+  double invln2hi;
+  double invln2lo;
+  double poly[LOG2_POLY_ORDER - 1];
+  double poly1[LOG2_POLY1_ORDER - 1];
+  struct {double invc, logc;} tab[1 << LOG2_TABLE_BITS];
+#if !HAVE_FAST_FMA
+  struct {double chi, clo;} tab2[1 << LOG2_TABLE_BITS];
+#endif
+} __log2_data HIDDEN;
+
+#define POW_LOG_TABLE_BITS 7
+#define POW_LOG_POLY_ORDER 8
+extern const struct pow_log_data
+{
+  double ln2hi;
+  double ln2lo;
+  double poly[POW_LOG_POLY_ORDER - 1]; /* First coefficient is 1.  */
+  /* Note: the pad field is unused, but allows slightly faster indexing.  */
+  struct {double invc, pad, logc, logctail;} tab[1 << POW_LOG_TABLE_BITS];
+} __pow_log_data HIDDEN;
+
+#endif
diff --git a/libc/AOR_v20.02/math/math_err.c b/libc/AOR_v20.02/math/math_err.c
new file mode 100644 (file)
index 0000000..77d8a94
--- /dev/null
@@ -0,0 +1,81 @@
+/*
+ * Double-precision math error handling.
+ *
+ * Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+ * See https://llvm.org/LICENSE.txt for license information.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "math_config.h"
+
+#if WANT_ERRNO
+#include <errno.h>
+/* NOINLINE reduces code size and avoids making math functions non-leaf
+   when the error handling is inlined.  */
+NOINLINE static double
+with_errno (double y, int e)
+{
+  errno = e;
+  return y;
+}
+#else
+#define with_errno(x, e) (x)
+#endif
+
+/* NOINLINE reduces code size.  */
+NOINLINE static double
+xflow (uint32_t sign, double y)
+{
+  y = eval_as_double (opt_barrier_double (sign ? -y : y) * y);
+  return with_errno (y, ERANGE);
+}
+
+HIDDEN double
+__math_uflow (uint32_t sign)
+{
+  return xflow (sign, 0x1p-767);
+}
+
+#if WANT_ERRNO_UFLOW
+/* Underflows to zero in some non-nearest rounding mode, setting errno
+   is valid even if the result is non-zero, but in the subnormal range.  */
+HIDDEN double
+__math_may_uflow (uint32_t sign)
+{
+  return xflow (sign, 0x1.8p-538);
+}
+#endif
+
+HIDDEN double
+__math_oflow (uint32_t sign)
+{
+  return xflow (sign, 0x1p769);
+}
+
+HIDDEN double
+__math_divzero (uint32_t sign)
+{
+  double y = opt_barrier_double (sign ? -1.0 : 1.0) / 0.0;
+  return with_errno (y, ERANGE);
+}
+
+HIDDEN double
+__math_invalid (double x)
+{
+  double y = (x - x) / (x - x);
+  return isnan (x) ? y : with_errno (y, EDOM);
+}
+
+/* Check result and set errno if necessary.  */
+
+HIDDEN double
+__math_check_uflow (double y)
+{
+  return y == 0.0 ? with_errno (y, ERANGE) : y;
+}
+
+HIDDEN double
+__math_check_oflow (double y)
+{
+  return isinf (y) ? with_errno (y, ERANGE) : y;
+}
diff --git a/libc/AOR_v20.02/math/math_errf.c b/libc/AOR_v20.02/math/math_errf.c
new file mode 100644 (file)
index 0000000..0837463
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * Single-precision math error handling.
+ *
+ * Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+ * See https://llvm.org/LICENSE.txt for license information.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "math_config.h"
+
+#if WANT_ERRNO
+#include <errno.h>
+/* NOINLINE reduces code size and avoids making math functions non-leaf
+   when the error handling is inlined.  */
+NOINLINE static float
+with_errnof (float y, int e)
+{
+  errno = e;
+  return y;
+}
+#else
+#define with_errnof(x, e) (x)
+#endif
+
+/* NOINLINE reduces code size.  */
+NOINLINE static float
+xflowf (uint32_t sign, float y)
+{
+  y = eval_as_float (opt_barrier_float (sign ? -y : y) * y);
+  return with_errnof (y, ERANGE);
+}
+
+HIDDEN float
+__math_uflowf (uint32_t sign)
+{
+  return xflowf (sign, 0x1p-95f);
+}
+
+#if WANT_ERRNO_UFLOW
+/* Underflows to zero in some non-nearest rounding mode, setting errno
+   is valid even if the result is non-zero, but in the subnormal range.  */
+HIDDEN float
+__math_may_uflowf (uint32_t sign)
+{
+  return xflowf (sign, 0x1.4p-75f);
+}
+#endif
+
+HIDDEN float
+__math_oflowf (uint32_t sign)
+{
+  return xflowf (sign, 0x1p97f);
+}
+
+HIDDEN float
+__math_divzerof (uint32_t sign)
+{
+  float y = opt_barrier_float (sign ? -1.0f : 1.0f) / 0.0f;
+  return with_errnof (y, ERANGE);
+}
+
+HIDDEN float
+__math_invalidf (float x)
+{
+  float y = (x - x) / (x - x);
+  return isnan (x) ? y : with_errnof (y, EDOM);
+}
diff --git a/libc/AOR_v20.02/math/pow.c b/libc/AOR_v20.02/math/pow.c
new file mode 100644 (file)
index 0000000..acdb23d
--- /dev/null
@@ -0,0 +1,381 @@
+/*
+ * Double-precision x^y function.
+ *
+ * Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+ * See https://llvm.org/LICENSE.txt for license information.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include <float.h>
+#include <math.h>
+#include <stdint.h>
+#include "math_config.h"
+
+/*
+Worst-case error: 0.54 ULP (~= ulperr_exp + 1024*Ln2*relerr_log*2^53)
+relerr_log: 1.3 * 2^-68 (Relative error of log, 1.5 * 2^-68 without fma)
+ulperr_exp: 0.509 ULP (ULP error of exp, 0.511 ULP without fma)
+*/
+
+#define T __pow_log_data.tab
+#define A __pow_log_data.poly
+#define Ln2hi __pow_log_data.ln2hi
+#define Ln2lo __pow_log_data.ln2lo
+#define N (1 << POW_LOG_TABLE_BITS)
+#define OFF 0x3fe6955500000000
+
+/* Top 12 bits of a double (sign and exponent bits).  */
+static inline uint32_t
+top12 (double x)
+{
+  return asuint64 (x) >> 52;
+}
+
+/* Compute y+TAIL = log(x) where the rounded result is y and TAIL has about
+   additional 15 bits precision.  IX is the bit representation of x, but
+   normalized in the subnormal range using the sign bit for the exponent.  */
+static inline double_t
+log_inline (uint64_t ix, double_t *tail)
+{
+  /* double_t for better performance on targets with FLT_EVAL_METHOD==2.  */
+  double_t z, r, y, invc, logc, logctail, kd, hi, t1, t2, lo, lo1, lo2, p;
+  uint64_t iz, tmp;
+  int k, i;
+
+  /* x = 2^k z; where z is in range [OFF,2*OFF) and exact.
+     The range is split into N subintervals.
+     The ith subinterval contains z and c is near its center.  */
+  tmp = ix - OFF;
+  i = (tmp >> (52 - POW_LOG_TABLE_BITS)) % N;
+  k = (int64_t) tmp >> 52; /* arithmetic shift */
+  iz = ix - (tmp & 0xfffULL << 52);
+  z = asdouble (iz);
+  kd = (double_t) k;
+
+  /* log(x) = k*Ln2 + log(c) + log1p(z/c-1).  */
+  invc = T[i].invc;
+  logc = T[i].logc;
+  logctail = T[i].logctail;
+
+  /* Note: 1/c is j/N or j/N/2 where j is an integer in [N,2N) and
+     |z/c - 1| < 1/N, so r = z/c - 1 is exactly representible.  */
+#if HAVE_FAST_FMA
+  r = fma (z, invc, -1.0);
+#else
+  /* Split z such that rhi, rlo and rhi*rhi are exact and |rlo| <= |r|.  */
+  double_t zhi = asdouble ((iz + (1ULL << 31)) & (-1ULL << 32));
+  double_t zlo = z - zhi;
+  double_t rhi = zhi * invc - 1.0;
+  double_t rlo = zlo * invc;
+  r = rhi + rlo;
+#endif
+
+  /* k*Ln2 + log(c) + r.  */
+  t1 = kd * Ln2hi + logc;
+  t2 = t1 + r;
+  lo1 = kd * Ln2lo + logctail;
+  lo2 = t1 - t2 + r;
+
+  /* Evaluation is optimized assuming superscalar pipelined execution.  */
+  double_t ar, ar2, ar3, lo3, lo4;
+  ar = A[0] * r; /* A[0] = -0.5.  */
+  ar2 = r * ar;
+  ar3 = r * ar2;
+  /* k*Ln2 + log(c) + r + A[0]*r*r.  */
+#if HAVE_FAST_FMA
+  hi = t2 + ar2;
+  lo3 = fma (ar, r, -ar2);
+  lo4 = t2 - hi + ar2;
+#else
+  double_t arhi = A[0] * rhi;
+  double_t arhi2 = rhi * arhi;
+  hi = t2 + arhi2;
+  lo3 = rlo * (ar + arhi);
+  lo4 = t2 - hi + arhi2;
+#endif
+  /* p = log1p(r) - r - A[0]*r*r.  */
+#if POW_LOG_POLY_ORDER == 8
+  p = (ar3
+       * (A[1] + r * A[2] + ar2 * (A[3] + r * A[4] + ar2 * (A[5] + r * A[6]))));
+#endif
+  lo = lo1 + lo2 + lo3 + lo4 + p;
+  y = hi + lo;
+  *tail = hi - y + lo;
+  return y;
+}
+
+#undef N
+#undef T
+#define N (1 << EXP_TABLE_BITS)
+#define InvLn2N __exp_data.invln2N
+#define NegLn2hiN __exp_data.negln2hiN
+#define NegLn2loN __exp_data.negln2loN
+#define Shift __exp_data.shift
+#define T __exp_data.tab
+#define C2 __exp_data.poly[5 - EXP_POLY_ORDER]
+#define C3 __exp_data.poly[6 - EXP_POLY_ORDER]
+#define C4 __exp_data.poly[7 - EXP_POLY_ORDER]
+#define C5 __exp_data.poly[8 - EXP_POLY_ORDER]
+#define C6 __exp_data.poly[9 - EXP_POLY_ORDER]
+
+/* Handle cases that may overflow or underflow when computing the result that
+   is scale*(1+TMP) without intermediate rounding.  The bit representation of
+   scale is in SBITS, however it has a computed exponent that may have
+   overflown into the sign bit so that needs to be adjusted before using it as
+   a double.  (int32_t)KI is the k used in the argument reduction and exponent
+   adjustment of scale, positive k here means the result may overflow and
+   negative k means the result may underflow.  */
+static inline double
+specialcase (double_t tmp, uint64_t sbits, uint64_t ki)
+{
+  double_t scale, y;
+
+  if ((ki & 0x80000000) == 0)
+    {
+      /* k > 0, the exponent of scale might have overflowed by <= 460.  */
+      sbits -= 1009ull << 52;
+      scale = asdouble (sbits);
+      y = 0x1p1009 * (scale + scale * tmp);
+      return check_oflow (eval_as_double (y));
+    }
+  /* k < 0, need special care in the subnormal range.  */
+  sbits += 1022ull << 52;
+  /* Note: sbits is signed scale.  */
+  scale = asdouble (sbits);
+  y = scale + scale * tmp;
+  if (fabs (y) < 1.0)
+    {
+      /* Round y to the right precision before scaling it into the subnormal
+        range to avoid double rounding that can cause 0.5+E/2 ulp error where
+        E is the worst-case ulp error outside the subnormal range.  So this
+        is only useful if the goal is better than 1 ulp worst-case error.  */
+      double_t hi, lo, one = 1.0;
+      if (y < 0.0)
+       one = -1.0;
+      lo = scale - y + scale * tmp;
+      hi = one + y;
+      lo = one - hi + y + lo;
+      y = eval_as_double (hi + lo) - one;
+      /* Fix the sign of 0.  */
+      if (y == 0.0)
+       y = asdouble (sbits & 0x8000000000000000);
+      /* The underflow exception needs to be signaled explicitly.  */
+      force_eval_double (opt_barrier_double (0x1p-1022) * 0x1p-1022);
+    }
+  y = 0x1p-1022 * y;
+  return check_uflow (eval_as_double (y));
+}
+
+#define SIGN_BIAS (0x800 << EXP_TABLE_BITS)
+
+/* Computes sign*exp(x+xtail) where |xtail| < 2^-8/N and |xtail| <= |x|.
+   The sign_bias argument is SIGN_BIAS or 0 and sets the sign to -1 or 1.  */
+static inline double
+exp_inline (double_t x, double_t xtail, uint32_t sign_bias)
+{
+  uint32_t abstop;
+  uint64_t ki, idx, top, sbits;
+  /* double_t for better performance on targets with FLT_EVAL_METHOD==2.  */
+  double_t kd, z, r, r2, scale, tail, tmp;
+
+  abstop = top12 (x) & 0x7ff;
+  if (unlikely (abstop - top12 (0x1p-54) >= top12 (512.0) - top12 (0x1p-54)))
+    {
+      if (abstop - top12 (0x1p-54) >= 0x80000000)
+       {
+         /* Avoid spurious underflow for tiny x.  */
+         /* Note: 0 is common input.  */
+         double_t one = WANT_ROUNDING ? 1.0 + x : 1.0;
+         return sign_bias ? -one : one;
+       }
+      if (abstop >= top12 (1024.0))
+       {
+         /* Note: inf and nan are already handled.  */
+         if (asuint64 (x) >> 63)
+           return __math_uflow (sign_bias);
+         else
+           return __math_oflow (sign_bias);
+       }
+      /* Large x is special cased below.  */
+      abstop = 0;
+    }
+
+  /* exp(x) = 2^(k/N) * exp(r), with exp(r) in [2^(-1/2N),2^(1/2N)].  */
+  /* x = ln2/N*k + r, with int k and r in [-ln2/2N, ln2/2N].  */
+  z = InvLn2N * x;
+#if TOINT_INTRINSICS
+  kd = roundtoint (z);
+  ki = converttoint (z);
+#elif EXP_USE_TOINT_NARROW
+  /* z - kd is in [-0.5-2^-16, 0.5] in all rounding modes.  */
+  kd = eval_as_double (z + Shift);
+  ki = asuint64 (kd) >> 16;
+  kd = (double_t) (int32_t) ki;
+#else
+  /* z - kd is in [-1, 1] in non-nearest rounding modes.  */
+  kd = eval_as_double (z + Shift);
+  ki = asuint64 (kd);
+  kd -= Shift;
+#endif
+  r = x + kd * NegLn2hiN + kd * NegLn2loN;
+  /* The code assumes 2^-200 < |xtail| < 2^-8/N.  */
+  r += xtail;
+  /* 2^(k/N) ~= scale * (1 + tail).  */
+  idx = 2 * (ki % N);
+  top = (ki + sign_bias) << (52 - EXP_TABLE_BITS);
+  tail = asdouble (T[idx]);
+  /* This is only a valid scale when -1023*N < k < 1024*N.  */
+  sbits = T[idx + 1] + top;
+  /* exp(x) = 2^(k/N) * exp(r) ~= scale + scale * (tail + exp(r) - 1).  */
+  /* Evaluation is optimized assuming superscalar pipelined execution.  */
+  r2 = r * r;
+  /* Without fma the worst case error is 0.25/N ulp larger.  */
+  /* Worst case error is less than 0.5+1.11/N+(abs poly error * 2^53) ulp.  */
+#if EXP_POLY_ORDER == 4
+  tmp = tail + r + r2 * C2 + r * r2 * (C3 + r * C4);
+#elif EXP_POLY_ORDER == 5
+  tmp = tail + r + r2 * (C2 + r * C3) + r2 * r2 * (C4 + r * C5);
+#elif EXP_POLY_ORDER == 6
+  tmp = tail + r + r2 * (0.5 + r * C3) + r2 * r2 * (C4 + r * C5 + r2 * C6);
+#endif
+  if (unlikely (abstop == 0))
+    return specialcase (tmp, sbits, ki);
+  scale = asdouble (sbits);
+  /* Note: tmp == 0 or |tmp| > 2^-200 and scale > 2^-739, so there
+     is no spurious underflow here even without fma.  */
+  return eval_as_double (scale + scale * tmp);
+}
+
+/* Returns 0 if not int, 1 if odd int, 2 if even int.  The argument is
+   the bit representation of a non-zero finite floating-point value.  */
+static inline int
+checkint (uint64_t iy)
+{
+  int e = iy >> 52 & 0x7ff;
+  if (e < 0x3ff)
+    return 0;
+  if (e > 0x3ff + 52)
+    return 2;
+  if (iy & ((1ULL << (0x3ff + 52 - e)) - 1))
+    return 0;
+  if (iy & (1ULL << (0x3ff + 52 - e)))
+    return 1;
+  return 2;
+}
+
+/* Returns 1 if input is the bit representation of 0, infinity or nan.  */
+static inline int
+zeroinfnan (uint64_t i)
+{
+  return 2 * i - 1 >= 2 * asuint64 (INFINITY) - 1;
+}
+
+double
+pow (double x, double y)
+{
+  uint32_t sign_bias = 0;
+  uint64_t ix, iy;
+  uint32_t topx, topy;
+
+  ix = asuint64 (x);
+  iy = asuint64 (y);
+  topx = top12 (x);
+  topy = top12 (y);
+  if (unlikely (topx - 0x001 >= 0x7ff - 0x001
+               || (topy & 0x7ff) - 0x3be >= 0x43e - 0x3be))
+    {
+      /* Note: if |y| > 1075 * ln2 * 2^53 ~= 0x1.749p62 then pow(x,y) = inf/0
+        and if |y| < 2^-54 / 1075 ~= 0x1.e7b6p-65 then pow(x,y) = +-1.  */
+      /* Special cases: (x < 0x1p-126 or inf or nan) or
+        (|y| < 0x1p-65 or |y| >= 0x1p63 or nan).  */
+      if (unlikely (zeroinfnan (iy)))
+       {
+         if (2 * iy == 0)
+           return issignaling_inline (x) ? x + y : 1.0;
+         if (ix == asuint64 (1.0))
+           return issignaling_inline (y) ? x + y : 1.0;
+         if (2 * ix > 2 * asuint64 (INFINITY)
+             || 2 * iy > 2 * asuint64 (INFINITY))
+           return x + y;
+         if (2 * ix == 2 * asuint64 (1.0))
+           return 1.0;
+         if ((2 * ix < 2 * asuint64 (1.0)) == !(iy >> 63))
+           return 0.0; /* |x|<1 && y==inf or |x|>1 && y==-inf.  */
+         return y * y;
+       }
+      if (unlikely (zeroinfnan (ix)))
+       {
+         double_t x2 = x * x;
+         if (ix >> 63 && checkint (iy) == 1)
+           {
+             x2 = -x2;
+             sign_bias = 1;
+           }
+         if (WANT_ERRNO && 2 * ix == 0 && iy >> 63)
+           return __math_divzero (sign_bias);
+         /* Without the barrier some versions of clang hoist the 1/x2 and
+            thus division by zero exception can be signaled spuriously.  */
+         return iy >> 63 ? opt_barrier_double (1 / x2) : x2;
+       }
+      /* Here x and y are non-zero finite.  */
+      if (ix >> 63)
+       {
+         /* Finite x < 0.  */
+         int yint = checkint (iy);
+         if (yint == 0)
+           return __math_invalid (x);
+         if (yint == 1)
+           sign_bias = SIGN_BIAS;
+         ix &= 0x7fffffffffffffff;
+         topx &= 0x7ff;
+       }
+      if ((topy & 0x7ff) - 0x3be >= 0x43e - 0x3be)
+       {
+         /* Note: sign_bias == 0 here because y is not odd.  */
+         if (ix == asuint64 (1.0))
+           return 1.0;
+         if ((topy & 0x7ff) < 0x3be)
+           {
+             /* |y| < 2^-65, x^y ~= 1 + y*log(x).  */
+             if (WANT_ROUNDING)
+               return ix > asuint64 (1.0) ? 1.0 + y : 1.0 - y;
+             else
+               return 1.0;
+           }
+         return (ix > asuint64 (1.0)) == (topy < 0x800) ? __math_oflow (0)
+                                                        : __math_uflow (0);
+       }
+      if (topx == 0)
+       {
+         /* Normalize subnormal x so exponent becomes negative.  */
+         /* Without the barrier some versions of clang evalutate the mul
+            unconditionally causing spurious overflow exceptions.  */
+         ix = asuint64 (opt_barrier_double (x) * 0x1p52);
+         ix &= 0x7fffffffffffffff;
+         ix -= 52ULL << 52;
+       }
+    }
+
+  double_t lo;
+  double_t hi = log_inline (ix, &lo);
+  double_t ehi, elo;
+#if HAVE_FAST_FMA
+  ehi = y * hi;
+  elo = y * lo + fma (y, hi, -ehi);
+#else
+  double_t yhi = asdouble (iy & -1ULL << 27);
+  double_t ylo = y - yhi;
+  double_t lhi = asdouble (asuint64 (hi) & -1ULL << 27);
+  double_t llo = hi - lhi + lo;
+  ehi = yhi * lhi;
+  elo = ylo * lhi + y * llo; /* |elo| < |ehi| * 2^-25.  */
+#endif
+  return exp_inline (ehi, elo, sign_bias);
+}
+#if USE_GLIBC_ABI
+strong_alias (pow, __pow_finite)
+hidden_alias (pow, __ieee754_pow)
+# if LDBL_MANT_DIG == 53
+long double powl (long double x, long double y) { return pow (x, y); }
+# endif
+#endif
diff --git a/libc/AOR_v20.02/math/pow_log_data.c b/libc/AOR_v20.02/math/pow_log_data.c
new file mode 100644 (file)
index 0000000..445d605
--- /dev/null
@@ -0,0 +1,185 @@
+/*
+ * Data for the log part of pow.
+ *
+ * Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+ * See https://llvm.org/LICENSE.txt for license information.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "math_config.h"
+
+#define N (1 << POW_LOG_TABLE_BITS)
+
+const struct pow_log_data __pow_log_data = {
+.ln2hi = 0x1.62e42fefa3800p-1,
+.ln2lo = 0x1.ef35793c76730p-45,
+.poly = {
+#if N == 128 && POW_LOG_POLY_ORDER == 8
+// relative error: 0x1.11922ap-70
+// in -0x1.6bp-8 0x1.6bp-8
+// Coefficients are scaled to match the scaling during evaluation.
+-0x1p-1,
+0x1.555555555556p-2 * -2,
+-0x1.0000000000006p-2 * -2,
+0x1.999999959554ep-3 * 4,
+-0x1.555555529a47ap-3 * 4,
+0x1.2495b9b4845e9p-3 * -8,
+-0x1.0002b8b263fc3p-3 * -8,
+#endif
+},
+/* Algorithm:
+
+       x = 2^k z
+       log(x) = k ln2 + log(c) + log(z/c)
+       log(z/c) = poly(z/c - 1)
+
+where z is in [0x1.69555p-1; 0x1.69555p0] which is split into N subintervals
+and z falls into the ith one, then table entries are computed as
+
+       tab[i].invc = 1/c
+       tab[i].logc = round(0x1p43*log(c))/0x1p43
+       tab[i].logctail = (double)(log(c) - logc)
+
+where c is chosen near the center of the subinterval such that 1/c has only a
+few precision bits so z/c - 1 is exactly representible as double:
+
+       1/c = center < 1 ? round(N/center)/N : round(2*N/center)/N/2
+
+Note: |z/c - 1| < 1/N for the chosen c, |log(c) - logc - logctail| < 0x1p-97,
+the last few bits of logc are rounded away so k*ln2hi + logc has no rounding
+error and the interval for z is selected such that near x == 1, where log(x)
+is tiny, large cancellation error is avoided in logc + poly(z/c - 1).  */
+.tab = {
+#if N == 128
+#define A(a, b, c) {a, 0, b, c},
+A(0x1.6a00000000000p+0, -0x1.62c82f2b9c800p-2, 0x1.ab42428375680p-48)
+A(0x1.6800000000000p+0, -0x1.5d1bdbf580800p-2, -0x1.ca508d8e0f720p-46)
+A(0x1.6600000000000p+0, -0x1.5767717455800p-2, -0x1.362a4d5b6506dp-45)
+A(0x1.6400000000000p+0, -0x1.51aad872df800p-2, -0x1.684e49eb067d5p-49)
+A(0x1.6200000000000p+0, -0x1.4be5f95777800p-2, -0x1.41b6993293ee0p-47)
+A(0x1.6000000000000p+0, -0x1.4618bc21c6000p-2, 0x1.3d82f484c84ccp-46)
+A(0x1.5e00000000000p+0, -0x1.404308686a800p-2, 0x1.c42f3ed820b3ap-50)
+A(0x1.5c00000000000p+0, -0x1.3a64c55694800p-2, 0x1.0b1c686519460p-45)
+A(0x1.5a00000000000p+0, -0x1.347dd9a988000p-2, 0x1.5594dd4c58092p-45)
+A(0x1.5800000000000p+0, -0x1.2e8e2bae12000p-2, 0x1.67b1e99b72bd8p-45)
+A(0x1.5600000000000p+0, -0x1.2895a13de8800p-2, 0x1.5ca14b6cfb03fp-46)
+A(0x1.5600000000000p+0, -0x1.2895a13de8800p-2, 0x1.5ca14b6cfb03fp-46)
+A(0x1.5400000000000p+0, -0x1.22941fbcf7800p-2, -0x1.65a242853da76p-46)
+A(0x1.5200000000000p+0, -0x1.1c898c1699800p-2, -0x1.fafbc68e75404p-46)
+A(0x1.5000000000000p+0, -0x1.1675cababa800p-2, 0x1.f1fc63382a8f0p-46)
+A(0x1.4e00000000000p+0, -0x1.1058bf9ae4800p-2, -0x1.6a8c4fd055a66p-45)
+A(0x1.4c00000000000p+0, -0x1.0a324e2739000p-2, -0x1.c6bee7ef4030ep-47)
+A(0x1.4a00000000000p+0, -0x1.0402594b4d000p-2, -0x1.036b89ef42d7fp-48)
+A(0x1.4a00000000000p+0, -0x1.0402594b4d000p-2, -0x1.036b89ef42d7fp-48)
+A(0x1.4800000000000p+0, -0x1.fb9186d5e4000p-3, 0x1.d572aab993c87p-47)
+A(0x1.4600000000000p+0, -0x1.ef0adcbdc6000p-3, 0x1.b26b79c86af24p-45)
+A(0x1.4400000000000p+0, -0x1.e27076e2af000p-3, -0x1.72f4f543fff10p-46)
+A(0x1.4200000000000p+0, -0x1.d5c216b4fc000p-3, 0x1.1ba91bbca681bp-45)
+A(0x1.4000000000000p+0, -0x1.c8ff7c79aa000p-3, 0x1.7794f689f8434p-45)
+A(0x1.4000000000000p+0, -0x1.c8ff7c79aa000p-3, 0x1.7794f689f8434p-45)
+A(0x1.3e00000000000p+0, -0x1.bc286742d9000p-3, 0x1.94eb0318bb78fp-46)
+A(0x1.3c00000000000p+0, -0x1.af3c94e80c000p-3, 0x1.a4e633fcd9066p-52)
+A(0x1.3a00000000000p+0, -0x1.a23bc1fe2b000p-3, -0x1.58c64dc46c1eap-45)
+A(0x1.3a00000000000p+0, -0x1.a23bc1fe2b000p-3, -0x1.58c64dc46c1eap-45)
+A(0x1.3800000000000p+0, -0x1.9525a9cf45000p-3, -0x1.ad1d904c1d4e3p-45)
+A(0x1.3600000000000p+0, -0x1.87fa06520d000p-3, 0x1.bbdbf7fdbfa09p-45)
+A(0x1.3400000000000p+0, -0x1.7ab890210e000p-3, 0x1.bdb9072534a58p-45)
+A(0x1.3400000000000p+0, -0x1.7ab890210e000p-3, 0x1.bdb9072534a58p-45)
+A(0x1.3200000000000p+0, -0x1.6d60fe719d000p-3, -0x1.0e46aa3b2e266p-46)
+A(0x1.3000000000000p+0, -0x1.5ff3070a79000p-3, -0x1.e9e439f105039p-46)
+A(0x1.3000000000000p+0, -0x1.5ff3070a79000p-3, -0x1.e9e439f105039p-46)
+A(0x1.2e00000000000p+0, -0x1.526e5e3a1b000p-3, -0x1.0de8b90075b8fp-45)
+A(0x1.2c00000000000p+0, -0x1.44d2b6ccb8000p-3, 0x1.70cc16135783cp-46)
+A(0x1.2c00000000000p+0, -0x1.44d2b6ccb8000p-3, 0x1.70cc16135783cp-46)
+A(0x1.2a00000000000p+0, -0x1.371fc201e9000p-3, 0x1.178864d27543ap-48)
+A(0x1.2800000000000p+0, -0x1.29552f81ff000p-3, -0x1.48d301771c408p-45)
+A(0x1.2600000000000p+0, -0x1.1b72ad52f6000p-3, -0x1.e80a41811a396p-45)
+A(0x1.2600000000000p+0, -0x1.1b72ad52f6000p-3, -0x1.e80a41811a396p-45)
+A(0x1.2400000000000p+0, -0x1.0d77e7cd09000p-3, 0x1.a699688e85bf4p-47)
+A(0x1.2400000000000p+0, -0x1.0d77e7cd09000p-3, 0x1.a699688e85bf4p-47)
+A(0x1.2200000000000p+0, -0x1.fec9131dbe000p-4, -0x1.575545ca333f2p-45)
+A(0x1.2000000000000p+0, -0x1.e27076e2b0000p-4, 0x1.a342c2af0003cp-45)
+A(0x1.2000000000000p+0, -0x1.e27076e2b0000p-4, 0x1.a342c2af0003cp-45)
+A(0x1.1e00000000000p+0, -0x1.c5e548f5bc000p-4, -0x1.d0c57585fbe06p-46)
+A(0x1.1c00000000000p+0, -0x1.a926d3a4ae000p-4, 0x1.53935e85baac8p-45)
+A(0x1.1c00000000000p+0, -0x1.a926d3a4ae000p-4, 0x1.53935e85baac8p-45)
+A(0x1.1a00000000000p+0, -0x1.8c345d631a000p-4, 0x1.37c294d2f5668p-46)
+A(0x1.1a00000000000p+0, -0x1.8c345d631a000p-4, 0x1.37c294d2f5668p-46)
+A(0x1.1800000000000p+0, -0x1.6f0d28ae56000p-4, -0x1.69737c93373dap-45)
+A(0x1.1600000000000p+0, -0x1.51b073f062000p-4, 0x1.f025b61c65e57p-46)
+A(0x1.1600000000000p+0, -0x1.51b073f062000p-4, 0x1.f025b61c65e57p-46)
+A(0x1.1400000000000p+0, -0x1.341d7961be000p-4, 0x1.c5edaccf913dfp-45)
+A(0x1.1400000000000p+0, -0x1.341d7961be000p-4, 0x1.c5edaccf913dfp-45)
+A(0x1.1200000000000p+0, -0x1.16536eea38000p-4, 0x1.47c5e768fa309p-46)
+A(0x1.1000000000000p+0, -0x1.f0a30c0118000p-5, 0x1.d599e83368e91p-45)
+A(0x1.1000000000000p+0, -0x1.f0a30c0118000p-5, 0x1.d599e83368e91p-45)
+A(0x1.0e00000000000p+0, -0x1.b42dd71198000p-5, 0x1.c827ae5d6704cp-46)
+A(0x1.0e00000000000p+0, -0x1.b42dd71198000p-5, 0x1.c827ae5d6704cp-46)
+A(0x1.0c00000000000p+0, -0x1.77458f632c000p-5, -0x1.cfc4634f2a1eep-45)
+A(0x1.0c00000000000p+0, -0x1.77458f632c000p-5, -0x1.cfc4634f2a1eep-45)
+A(0x1.0a00000000000p+0, -0x1.39e87b9fec000p-5, 0x1.502b7f526feaap-48)
+A(0x1.0a00000000000p+0, -0x1.39e87b9fec000p-5, 0x1.502b7f526feaap-48)
+A(0x1.0800000000000p+0, -0x1.f829b0e780000p-6, -0x1.980267c7e09e4p-45)
+A(0x1.0800000000000p+0, -0x1.f829b0e780000p-6, -0x1.980267c7e09e4p-45)
+A(0x1.0600000000000p+0, -0x1.7b91b07d58000p-6, -0x1.88d5493faa639p-45)
+A(0x1.0400000000000p+0, -0x1.fc0a8b0fc0000p-7, -0x1.f1e7cf6d3a69cp-50)
+A(0x1.0400000000000p+0, -0x1.fc0a8b0fc0000p-7, -0x1.f1e7cf6d3a69cp-50)
+A(0x1.0200000000000p+0, -0x1.fe02a6b100000p-8, -0x1.9e23f0dda40e4p-46)
+A(0x1.0200000000000p+0, -0x1.fe02a6b100000p-8, -0x1.9e23f0dda40e4p-46)
+A(0x1.0000000000000p+0, 0x0.0000000000000p+0, 0x0.0000000000000p+0)
+A(0x1.0000000000000p+0, 0x0.0000000000000p+0, 0x0.0000000000000p+0)
+A(0x1.fc00000000000p-1, 0x1.0101575890000p-7, -0x1.0c76b999d2be8p-46)
+A(0x1.f800000000000p-1, 0x1.0205658938000p-6, -0x1.3dc5b06e2f7d2p-45)
+A(0x1.f400000000000p-1, 0x1.8492528c90000p-6, -0x1.aa0ba325a0c34p-45)
+A(0x1.f000000000000p-1, 0x1.0415d89e74000p-5, 0x1.111c05cf1d753p-47)
+A(0x1.ec00000000000p-1, 0x1.466aed42e0000p-5, -0x1.c167375bdfd28p-45)
+A(0x1.e800000000000p-1, 0x1.894aa149fc000p-5, -0x1.97995d05a267dp-46)
+A(0x1.e400000000000p-1, 0x1.ccb73cdddc000p-5, -0x1.a68f247d82807p-46)
+A(0x1.e200000000000p-1, 0x1.eea31c006c000p-5, -0x1.e113e4fc93b7bp-47)
+A(0x1.de00000000000p-1, 0x1.1973bd1466000p-4, -0x1.5325d560d9e9bp-45)
+A(0x1.da00000000000p-1, 0x1.3bdf5a7d1e000p-4, 0x1.cc85ea5db4ed7p-45)
+A(0x1.d600000000000p-1, 0x1.5e95a4d97a000p-4, -0x1.c69063c5d1d1ep-45)
+A(0x1.d400000000000p-1, 0x1.700d30aeac000p-4, 0x1.c1e8da99ded32p-49)
+A(0x1.d000000000000p-1, 0x1.9335e5d594000p-4, 0x1.3115c3abd47dap-45)
+A(0x1.cc00000000000p-1, 0x1.b6ac88dad6000p-4, -0x1.390802bf768e5p-46)
+A(0x1.ca00000000000p-1, 0x1.c885801bc4000p-4, 0x1.646d1c65aacd3p-45)
+A(0x1.c600000000000p-1, 0x1.ec739830a2000p-4, -0x1.dc068afe645e0p-45)
+A(0x1.c400000000000p-1, 0x1.fe89139dbe000p-4, -0x1.534d64fa10afdp-45)
+A(0x1.c000000000000p-1, 0x1.1178e8227e000p-3, 0x1.1ef78ce2d07f2p-45)
+A(0x1.be00000000000p-1, 0x1.1aa2b7e23f000p-3, 0x1.ca78e44389934p-45)
+A(0x1.ba00000000000p-1, 0x1.2d1610c868000p-3, 0x1.39d6ccb81b4a1p-47)
+A(0x1.b800000000000p-1, 0x1.365fcb0159000p-3, 0x1.62fa8234b7289p-51)
+A(0x1.b400000000000p-1, 0x1.4913d8333b000p-3, 0x1.5837954fdb678p-45)
+A(0x1.b200000000000p-1, 0x1.527e5e4a1b000p-3, 0x1.633e8e5697dc7p-45)
+A(0x1.ae00000000000p-1, 0x1.6574ebe8c1000p-3, 0x1.9cf8b2c3c2e78p-46)
+A(0x1.ac00000000000p-1, 0x1.6f0128b757000p-3, -0x1.5118de59c21e1p-45)
+A(0x1.aa00000000000p-1, 0x1.7898d85445000p-3, -0x1.c661070914305p-46)
+A(0x1.a600000000000p-1, 0x1.8beafeb390000p-3, -0x1.73d54aae92cd1p-47)
+A(0x1.a400000000000p-1, 0x1.95a5adcf70000p-3, 0x1.7f22858a0ff6fp-47)
+A(0x1.a000000000000p-1, 0x1.a93ed3c8ae000p-3, -0x1.8724350562169p-45)
+A(0x1.9e00000000000p-1, 0x1.b31d8575bd000p-3, -0x1.c358d4eace1aap-47)
+A(0x1.9c00000000000p-1, 0x1.bd087383be000p-3, -0x1.d4bc4595412b6p-45)
+A(0x1.9a00000000000p-1, 0x1.c6ffbc6f01000p-3, -0x1.1ec72c5962bd2p-48)
+A(0x1.9600000000000p-1, 0x1.db13db0d49000p-3, -0x1.aff2af715b035p-45)
+A(0x1.9400000000000p-1, 0x1.e530effe71000p-3, 0x1.212276041f430p-51)
+A(0x1.9200000000000p-1, 0x1.ef5ade4dd0000p-3, -0x1.a211565bb8e11p-51)
+A(0x1.9000000000000p-1, 0x1.f991c6cb3b000p-3, 0x1.bcbecca0cdf30p-46)
+A(0x1.8c00000000000p-1, 0x1.07138604d5800p-2, 0x1.89cdb16ed4e91p-48)
+A(0x1.8a00000000000p-1, 0x1.0c42d67616000p-2, 0x1.7188b163ceae9p-45)
+A(0x1.8800000000000p-1, 0x1.1178e8227e800p-2, -0x1.c210e63a5f01cp-45)
+A(0x1.8600000000000p-1, 0x1.16b5ccbacf800p-2, 0x1.b9acdf7a51681p-45)
+A(0x1.8400000000000p-1, 0x1.1bf99635a6800p-2, 0x1.ca6ed5147bdb7p-45)
+A(0x1.8200000000000p-1, 0x1.214456d0eb800p-2, 0x1.a87deba46baeap-47)
+A(0x1.7e00000000000p-1, 0x1.2bef07cdc9000p-2, 0x1.a9cfa4a5004f4p-45)
+A(0x1.7c00000000000p-1, 0x1.314f1e1d36000p-2, -0x1.8e27ad3213cb8p-45)
+A(0x1.7a00000000000p-1, 0x1.36b6776be1000p-2, 0x1.16ecdb0f177c8p-46)
+A(0x1.7800000000000p-1, 0x1.3c25277333000p-2, 0x1.83b54b606bd5cp-46)
+A(0x1.7600000000000p-1, 0x1.419b423d5e800p-2, 0x1.8e436ec90e09dp-47)
+A(0x1.7400000000000p-1, 0x1.4718dc271c800p-2, -0x1.f27ce0967d675p-45)
+A(0x1.7200000000000p-1, 0x1.4c9e09e173000p-2, -0x1.e20891b0ad8a4p-45)
+A(0x1.7000000000000p-1, 0x1.522ae0738a000p-2, 0x1.ebe708164c759p-45)
+A(0x1.6e00000000000p-1, 0x1.57bf753c8d000p-2, 0x1.fadedee5d40efp-46)
+A(0x1.6c00000000000p-1, 0x1.5d5bddf596000p-2, -0x1.a0b2a08a465dcp-47)
+#endif
+},
+};
diff --git a/libc/AOR_v20.02/math/powf.c b/libc/AOR_v20.02/math/powf.c
new file mode 100644 (file)
index 0000000..3cb70c0
--- /dev/null
@@ -0,0 +1,222 @@
+/*
+ * Single-precision pow function.
+ *
+ * Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+ * See https://llvm.org/LICENSE.txt for license information.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include <math.h>
+#include <stdint.h>
+#include "math_config.h"
+
+/*
+POWF_LOG2_POLY_ORDER = 5
+EXP2F_TABLE_BITS = 5
+
+ULP error: 0.82 (~ 0.5 + relerr*2^24)
+relerr: 1.27 * 2^-26 (Relative error ~= 128*Ln2*relerr_log2 + relerr_exp2)
+relerr_log2: 1.83 * 2^-33 (Relative error of logx.)
+relerr_exp2: 1.69 * 2^-34 (Relative error of exp2(ylogx).)
+*/
+
+#define N (1 << POWF_LOG2_TABLE_BITS)
+#define T __powf_log2_data.tab
+#define A __powf_log2_data.poly
+#define OFF 0x3f330000
+
+/* Subnormal input is normalized so ix has negative biased exponent.
+   Output is multiplied by N (POWF_SCALE) if TOINT_INTRINICS is set.  */
+static inline double_t
+log2_inline (uint32_t ix)
+{
+  /* double_t for better performance on targets with FLT_EVAL_METHOD==2.  */
+  double_t z, r, r2, r4, p, q, y, y0, invc, logc;
+  uint32_t iz, top, tmp;
+  int k, i;
+
+  /* x = 2^k z; where z is in range [OFF,2*OFF] and exact.
+     The range is split into N subintervals.
+     The ith subinterval contains z and c is near its center.  */
+  tmp = ix - OFF;
+  i = (tmp >> (23 - POWF_LOG2_TABLE_BITS)) % N;
+  top = tmp & 0xff800000;
+  iz = ix - top;
+  k = (int32_t) top >> (23 - POWF_SCALE_BITS); /* arithmetic shift */
+  invc = T[i].invc;
+  logc = T[i].logc;
+  z = (double_t) asfloat (iz);
+
+  /* log2(x) = log1p(z/c-1)/ln2 + log2(c) + k */
+  r = z * invc - 1;
+  y0 = logc + (double_t) k;
+
+  /* Pipelined polynomial evaluation to approximate log1p(r)/ln2.  */
+  r2 = r * r;
+  y = A[0] * r + A[1];
+  p = A[2] * r + A[3];
+  r4 = r2 * r2;
+  q = A[4] * r + y0;
+  q = p * r2 + q;
+  y = y * r4 + q;
+  return y;
+}
+
+#undef N
+#undef T
+#define N (1 << EXP2F_TABLE_BITS)
+#define T __exp2f_data.tab
+#define SIGN_BIAS (1 << (EXP2F_TABLE_BITS + 11))
+
+/* The output of log2 and thus the input of exp2 is either scaled by N
+   (in case of fast toint intrinsics) or not.  The unscaled xd must be
+   in [-1021,1023], sign_bias sets the sign of the result.  */
+static inline float
+exp2_inline (double_t xd, uint32_t sign_bias)
+{
+  uint64_t ki, ski, t;
+  /* double_t for better performance on targets with FLT_EVAL_METHOD==2.  */
+  double_t kd, z, r, r2, y, s;
+
+#if TOINT_INTRINSICS
+# define C __exp2f_data.poly_scaled
+  /* N*x = k + r with r in [-1/2, 1/2] */
+  kd = roundtoint (xd); /* k */
+  ki = converttoint (xd);
+#else
+# define C __exp2f_data.poly
+# define SHIFT __exp2f_data.shift_scaled
+  /* x = k/N + r with r in [-1/(2N), 1/(2N)] */
+  kd = eval_as_double (xd + SHIFT);
+  ki = asuint64 (kd);
+  kd -= SHIFT; /* k/N */
+#endif
+  r = xd - kd;
+
+  /* exp2(x) = 2^(k/N) * 2^r ~= s * (C0*r^3 + C1*r^2 + C2*r + 1) */
+  t = T[ki % N];
+  ski = ki + sign_bias;
+  t += ski << (52 - EXP2F_TABLE_BITS);
+  s = asdouble (t);
+  z = C[0] * r + C[1];
+  r2 = r * r;
+  y = C[2] * r + 1;
+  y = z * r2 + y;
+  y = y * s;
+  return eval_as_float (y);
+}
+
+/* Returns 0 if not int, 1 if odd int, 2 if even int.  The argument is
+   the bit representation of a non-zero finite floating-point value.  */
+static inline int
+checkint (uint32_t iy)
+{
+  int e = iy >> 23 & 0xff;
+  if (e < 0x7f)
+    return 0;
+  if (e > 0x7f + 23)
+    return 2;
+  if (iy & ((1 << (0x7f + 23 - e)) - 1))
+    return 0;
+  if (iy & (1 << (0x7f + 23 - e)))
+    return 1;
+  return 2;
+}
+
+static inline int
+zeroinfnan (uint32_t ix)
+{
+  return 2 * ix - 1 >= 2u * 0x7f800000 - 1;
+}
+
+float
+powf (float x, float y)
+{
+  uint32_t sign_bias = 0;
+  uint32_t ix, iy;
+
+  ix = asuint (x);
+  iy = asuint (y);
+  if (unlikely (ix - 0x00800000 >= 0x7f800000 - 0x00800000 || zeroinfnan (iy)))
+    {
+      /* Either (x < 0x1p-126 or inf or nan) or (y is 0 or inf or nan).  */
+      if (unlikely (zeroinfnan (iy)))
+       {
+         if (2 * iy == 0)
+           return issignalingf_inline (x) ? x + y : 1.0f;
+         if (ix == 0x3f800000)
+           return issignalingf_inline (y) ? x + y : 1.0f;
+         if (2 * ix > 2u * 0x7f800000 || 2 * iy > 2u * 0x7f800000)
+           return x + y;
+         if (2 * ix == 2 * 0x3f800000)
+           return 1.0f;
+         if ((2 * ix < 2 * 0x3f800000) == !(iy & 0x80000000))
+           return 0.0f; /* |x|<1 && y==inf or |x|>1 && y==-inf.  */
+         return y * y;
+       }
+      if (unlikely (zeroinfnan (ix)))
+       {
+         float_t x2 = x * x;
+         if (ix & 0x80000000 && checkint (iy) == 1)
+           {
+             x2 = -x2;
+             sign_bias = 1;
+           }
+#if WANT_ERRNO
+         if (2 * ix == 0 && iy & 0x80000000)
+           return __math_divzerof (sign_bias);
+#endif
+         /* Without the barrier some versions of clang hoist the 1/x2 and
+            thus division by zero exception can be signaled spuriously.  */
+         return iy & 0x80000000 ? opt_barrier_float (1 / x2) : x2;
+       }
+      /* x and y are non-zero finite.  */
+      if (ix & 0x80000000)
+       {
+         /* Finite x < 0.  */
+         int yint = checkint (iy);
+         if (yint == 0)
+           return __math_invalidf (x);
+         if (yint == 1)
+           sign_bias = SIGN_BIAS;
+         ix &= 0x7fffffff;
+       }
+      if (ix < 0x00800000)
+       {
+         /* Normalize subnormal x so exponent becomes negative.  */
+         ix = asuint (x * 0x1p23f);
+         ix &= 0x7fffffff;
+         ix -= 23 << 23;
+       }
+    }
+  double_t logx = log2_inline (ix);
+  double_t ylogx = y * logx; /* Note: cannot overflow, y is single prec.  */
+  if (unlikely ((asuint64 (ylogx) >> 47 & 0xffff)
+                >= asuint64 (126.0 * POWF_SCALE) >> 47))
+    {
+      /* |y*log(x)| >= 126.  */
+      if (ylogx > 0x1.fffffffd1d571p+6 * POWF_SCALE)
+       /* |x^y| > 0x1.ffffffp127.  */
+       return __math_oflowf (sign_bias);
+      if (WANT_ROUNDING && WANT_ERRNO
+         && ylogx > 0x1.fffffffa3aae2p+6 * POWF_SCALE)
+       /* |x^y| > 0x1.fffffep127, check if we round away from 0.  */
+       if ((!sign_bias
+            && eval_as_float (1.0f + opt_barrier_float (0x1p-25f)) != 1.0f)
+           || (sign_bias
+               && eval_as_float (-1.0f - opt_barrier_float (0x1p-25f))
+                    != -1.0f))
+         return __math_oflowf (sign_bias);
+      if (ylogx <= -150.0 * POWF_SCALE)
+       return __math_uflowf (sign_bias);
+#if WANT_ERRNO_UFLOW
+      if (ylogx < -149.0 * POWF_SCALE)
+       return __math_may_uflowf (sign_bias);
+#endif
+    }
+  return exp2_inline (ylogx, sign_bias);
+}
+#if USE_GLIBC_ABI
+strong_alias (powf, __powf_finite)
+hidden_alias (powf, __ieee754_powf)
+#endif
diff --git a/libc/AOR_v20.02/math/powf_log2_data.c b/libc/AOR_v20.02/math/powf_log2_data.c
new file mode 100644 (file)
index 0000000..d7c74b3
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * Data definition for powf.
+ *
+ * Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+ * See https://llvm.org/LICENSE.txt for license information.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "math_config.h"
+
+const struct powf_log2_data __powf_log2_data = {
+  .tab = {
+  { 0x1.661ec79f8f3bep+0, -0x1.efec65b963019p-2 * POWF_SCALE },
+  { 0x1.571ed4aaf883dp+0, -0x1.b0b6832d4fca4p-2 * POWF_SCALE },
+  { 0x1.49539f0f010bp+0, -0x1.7418b0a1fb77bp-2 * POWF_SCALE },
+  { 0x1.3c995b0b80385p+0, -0x1.39de91a6dcf7bp-2 * POWF_SCALE },
+  { 0x1.30d190c8864a5p+0, -0x1.01d9bf3f2b631p-2 * POWF_SCALE },
+  { 0x1.25e227b0b8eap+0, -0x1.97c1d1b3b7afp-3 * POWF_SCALE },
+  { 0x1.1bb4a4a1a343fp+0, -0x1.2f9e393af3c9fp-3 * POWF_SCALE },
+  { 0x1.12358f08ae5bap+0, -0x1.960cbbf788d5cp-4 * POWF_SCALE },
+  { 0x1.0953f419900a7p+0, -0x1.a6f9db6475fcep-5 * POWF_SCALE },
+  { 0x1p+0, 0x0p+0 * POWF_SCALE },
+  { 0x1.e608cfd9a47acp-1, 0x1.338ca9f24f53dp-4 * POWF_SCALE },
+  { 0x1.ca4b31f026aap-1, 0x1.476a9543891bap-3 * POWF_SCALE },
+  { 0x1.b2036576afce6p-1, 0x1.e840b4ac4e4d2p-3 * POWF_SCALE },
+  { 0x1.9c2d163a1aa2dp-1, 0x1.40645f0c6651cp-2 * POWF_SCALE },
+  { 0x1.886e6037841edp-1, 0x1.88e9c2c1b9ff8p-2 * POWF_SCALE },
+  { 0x1.767dcf5534862p-1, 0x1.ce0a44eb17bccp-2 * POWF_SCALE },
+  },
+  .poly = {
+  0x1.27616c9496e0bp-2 * POWF_SCALE, -0x1.71969a075c67ap-2 * POWF_SCALE,
+  0x1.ec70a6ca7baddp-2 * POWF_SCALE, -0x1.7154748bef6c8p-1 * POWF_SCALE,
+  0x1.71547652ab82bp0 * POWF_SCALE,
+  }
+};
diff --git a/libc/AOR_v20.02/math/s_cos.c b/libc/AOR_v20.02/math/s_cos.c
new file mode 100644 (file)
index 0000000..c0176c7
--- /dev/null
@@ -0,0 +1,7 @@
+/*
+ * Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+ * See https://llvm.org/LICENSE.txt for license information.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+#define SCALAR 1
+#include "v_cos.c"
diff --git a/libc/AOR_v20.02/math/s_cosf.c b/libc/AOR_v20.02/math/s_cosf.c
new file mode 100644 (file)
index 0000000..8bea8ec
--- /dev/null
@@ -0,0 +1,7 @@
+/*
+ * Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+ * See https://llvm.org/LICENSE.txt for license information.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+#define SCALAR 1
+#include "v_cosf.c"
diff --git a/libc/AOR_v20.02/math/s_exp.c b/libc/AOR_v20.02/math/s_exp.c
new file mode 100644 (file)
index 0000000..2c9dbe7
--- /dev/null
@@ -0,0 +1,7 @@
+/*
+ * Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+ * See https://llvm.org/LICENSE.txt for license information.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+#define SCALAR 1
+#include "v_exp.c"
diff --git a/libc/AOR_v20.02/math/s_exp2f.c b/libc/AOR_v20.02/math/s_exp2f.c
new file mode 100644 (file)
index 0000000..de56675
--- /dev/null
@@ -0,0 +1,7 @@
+/*
+ * Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+ * See https://llvm.org/LICENSE.txt for license information.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+#define SCALAR 1
+#include "v_exp2f.c"
diff --git a/libc/AOR_v20.02/math/s_exp2f_1u.c b/libc/AOR_v20.02/math/s_exp2f_1u.c
new file mode 100644 (file)
index 0000000..53d557f
--- /dev/null
@@ -0,0 +1,7 @@
+/*
+ * Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+ * See https://llvm.org/LICENSE.txt for license information.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+#define SCALAR 1
+#include "v_exp2f_1u.c"
diff --git a/libc/AOR_v20.02/math/s_expf.c b/libc/AOR_v20.02/math/s_expf.c
new file mode 100644 (file)
index 0000000..6340895
--- /dev/null
@@ -0,0 +1,7 @@
+/*
+ * Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+ * See https://llvm.org/LICENSE.txt for license information.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+#define SCALAR 1
+#include "v_expf.c"
diff --git a/libc/AOR_v20.02/math/s_expf_1u.c b/libc/AOR_v20.02/math/s_expf_1u.c
new file mode 100644 (file)
index 0000000..127ae3b
--- /dev/null
@@ -0,0 +1,7 @@
+/*
+ * Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+ * See https://llvm.org/LICENSE.txt for license information.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+#define SCALAR 1
+#include "v_expf_1u.c"
diff --git a/libc/AOR_v20.02/math/s_log.c b/libc/AOR_v20.02/math/s_log.c
new file mode 100644 (file)
index 0000000..22fd46c
--- /dev/null
@@ -0,0 +1,7 @@
+/*
+ * Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+ * See https://llvm.org/LICENSE.txt for license information.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+#define SCALAR 1
+#include "v_log.c"
diff --git a/libc/AOR_v20.02/math/s_logf.c b/libc/AOR_v20.02/math/s_logf.c
new file mode 100644 (file)
index 0000000..3066f38
--- /dev/null
@@ -0,0 +1,7 @@
+/*
+ * Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+ * See https://llvm.org/LICENSE.txt for license information.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+#define SCALAR 1
+#include "v_logf.c"
diff --git a/libc/AOR_v20.02/math/s_pow.c b/libc/AOR_v20.02/math/s_pow.c
new file mode 100644 (file)
index 0000000..bf0910b
--- /dev/null
@@ -0,0 +1,7 @@
+/*
+ * Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+ * See https://llvm.org/LICENSE.txt for license information.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+#define SCALAR 1
+#include "v_pow.c"
diff --git a/libc/AOR_v20.02/math/s_powf.c b/libc/AOR_v20.02/math/s_powf.c
new file mode 100644 (file)
index 0000000..48319a2
--- /dev/null
@@ -0,0 +1,7 @@
+/*
+ * Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+ * See https://llvm.org/LICENSE.txt for license information.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+#define SCALAR 1
+#include "v_powf.c"
diff --git a/libc/AOR_v20.02/math/s_sin.c b/libc/AOR_v20.02/math/s_sin.c
new file mode 100644 (file)
index 0000000..969714f
--- /dev/null
@@ -0,0 +1,7 @@
+/*
+ * Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+ * See https://llvm.org/LICENSE.txt for license information.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+#define SCALAR 1
+#include "v_sin.c"
diff --git a/libc/AOR_v20.02/math/s_sinf.c b/libc/AOR_v20.02/math/s_sinf.c
new file mode 100644 (file)
index 0000000..55d4567
--- /dev/null
@@ -0,0 +1,7 @@
+/*
+ * Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+ * See https://llvm.org/LICENSE.txt for license information.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+#define SCALAR 1
+#include "v_sinf.c"
diff --git a/libc/AOR_v20.02/math/sincosf.c b/libc/AOR_v20.02/math/sincosf.c
new file mode 100644 (file)
index 0000000..819b05b
--- /dev/null
@@ -0,0 +1,80 @@
+/*
+ * Single-precision sin/cos function.
+ *
+ * Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+ * See https://llvm.org/LICENSE.txt for license information.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include <stdint.h>
+#include <math.h>
+#include "math_config.h"
+#include "sincosf.h"
+
+/* Fast sincosf implementation.  Worst-case ULP is 0.5607, maximum relative
+   error is 0.5303 * 2^-23.  A single-step range reduction is used for
+   small values.  Large inputs have their range reduced using fast integer
+   arithmetic.  */
+void
+sincosf (float y, float *sinp, float *cosp)
+{
+  double x = y;
+  double s;
+  int n;
+  const sincos_t *p = &__sincosf_table[0];
+
+  if (abstop12 (y) < abstop12 (pio4))
+    {
+      double x2 = x * x;
+
+      if (unlikely (abstop12 (y) < abstop12 (0x1p-12f)))
+       {
+         if (unlikely (abstop12 (y) < abstop12 (0x1p-126f)))
+           /* Force underflow for tiny y.  */
+           force_eval_float (x2);
+         *sinp = y;
+         *cosp = 1.0f;
+         return;
+       }
+
+      sincosf_poly (x, x2, p, 0, sinp, cosp);
+    }
+  else if (abstop12 (y) < abstop12 (120.0f))
+    {
+      x = reduce_fast (x, p, &n);
+
+      /* Setup the signs for sin and cos.  */
+      s = p->sign[n & 3];
+
+      if (n & 2)
+       p = &__sincosf_table[1];
+
+      sincosf_poly (x * s, x * x, p, n, sinp, cosp);
+    }
+  else if (likely (abstop12 (y) < abstop12 (INFINITY)))
+    {
+      uint32_t xi = asuint (y);
+      int sign = xi >> 31;
+
+      x = reduce_large (xi, &n);
+
+      /* Setup signs for sin and cos - include original sign.  */
+      s = p->sign[(n + sign) & 3];
+
+      if ((n + sign) & 2)
+       p = &__sincosf_table[1];
+
+      sincosf_poly (x * s, x * x, p, n, sinp, cosp);
+    }
+  else
+    {
+      /* Return NaN if Inf or NaN for both sin and cos.  */
+      *sinp = *cosp = y - y;
+#if WANT_ERRNO
+      /* Needed to set errno for +-Inf, the add is a hack to work
+        around a gcc register allocation issue: just passing y
+        affects code generation in the fast path.  */
+      __math_invalidf (y + y);
+#endif
+    }
+}
diff --git a/libc/AOR_v20.02/math/sincosf.h b/libc/AOR_v20.02/math/sincosf.h
new file mode 100644 (file)
index 0000000..ef40d70
--- /dev/null
@@ -0,0 +1,154 @@
+/*
+ * Header for sinf, cosf and sincosf.
+ *
+ * Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+ * See https://llvm.org/LICENSE.txt for license information.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include <stdint.h>
+#include <math.h>
+#include "math_config.h"
+
+/* 2PI * 2^-64.  */
+static const double pi63 = 0x1.921FB54442D18p-62;
+/* PI / 4.  */
+static const double pio4 = 0x1.921FB54442D18p-1;
+
+/* The constants and polynomials for sine and cosine.  */
+typedef struct
+{
+  double sign[4];              /* Sign of sine in quadrants 0..3.  */
+  double hpi_inv;              /* 2 / PI ( * 2^24 if !TOINT_INTRINSICS).  */
+  double hpi;                  /* PI / 2.  */
+  double c0, c1, c2, c3, c4;   /* Cosine polynomial.  */
+  double s1, s2, s3;           /* Sine polynomial.  */
+} sincos_t;
+
+/* Polynomial data (the cosine polynomial is negated in the 2nd entry).  */
+extern const sincos_t __sincosf_table[2] HIDDEN;
+
+/* Table with 4/PI to 192 bit precision.  */
+extern const uint32_t __inv_pio4[] HIDDEN;
+
+/* Top 12 bits of the float representation with the sign bit cleared.  */
+static inline uint32_t
+abstop12 (float x)
+{
+  return (asuint (x) >> 20) & 0x7ff;
+}
+
+/* Compute the sine and cosine of inputs X and X2 (X squared), using the
+   polynomial P and store the results in SINP and COSP.  N is the quadrant,
+   if odd the cosine and sine polynomials are swapped.  */
+static inline void
+sincosf_poly (double x, double x2, const sincos_t *p, int n, float *sinp,
+             float *cosp)
+{
+  double x3, x4, x5, x6, s, c, c1, c2, s1;
+
+  x4 = x2 * x2;
+  x3 = x2 * x;
+  c2 = p->c3 + x2 * p->c4;
+  s1 = p->s2 + x2 * p->s3;
+
+  /* Swap sin/cos result based on quadrant.  */
+  float *tmp = (n & 1 ? cosp : sinp);
+  cosp = (n & 1 ? sinp : cosp);
+  sinp = tmp;
+
+  c1 = p->c0 + x2 * p->c1;
+  x5 = x3 * x2;
+  x6 = x4 * x2;
+
+  s = x + x3 * p->s1;
+  c = c1 + x4 * p->c2;
+
+  *sinp = s + x5 * s1;
+  *cosp = c + x6 * c2;
+}
+
+/* Return the sine of inputs X and X2 (X squared) using the polynomial P.
+   N is the quadrant, and if odd the cosine polynomial is used.  */
+static inline float
+sinf_poly (double x, double x2, const sincos_t *p, int n)
+{
+  double x3, x4, x6, x7, s, c, c1, c2, s1;
+
+  if ((n & 1) == 0)
+    {
+      x3 = x * x2;
+      s1 = p->s2 + x2 * p->s3;
+
+      x7 = x3 * x2;
+      s = x + x3 * p->s1;
+
+      return s + x7 * s1;
+    }
+  else
+    {
+      x4 = x2 * x2;
+      c2 = p->c3 + x2 * p->c4;
+      c1 = p->c0 + x2 * p->c1;
+
+      x6 = x4 * x2;
+      c = c1 + x4 * p->c2;
+
+      return c + x6 * c2;
+    }
+}
+
+/* Fast range reduction using single multiply-subtract.  Return the modulo of
+   X as a value between -PI/4 and PI/4 and store the quadrant in NP.
+   The values for PI/2 and 2/PI are accessed via P.  Since PI/2 as a double
+   is accurate to 55 bits and the worst-case cancellation happens at 6 * PI/4,
+   the result is accurate for |X| <= 120.0.  */
+static inline double
+reduce_fast (double x, const sincos_t *p, int *np)
+{
+  double r;
+#if TOINT_INTRINSICS
+  /* Use fast round and lround instructions when available.  */
+  r = x * p->hpi_inv;
+  *np = converttoint (r);
+  return x - roundtoint (r) * p->hpi;
+#else
+  /* Use scaled float to int conversion with explicit rounding.
+     hpi_inv is prescaled by 2^24 so the quadrant ends up in bits 24..31.
+     This avoids inaccuracies introduced by truncating negative values.  */
+  r = x * p->hpi_inv;
+  int n = ((int32_t)r + 0x800000) >> 24;
+  *np = n;
+  return x - n * p->hpi;
+#endif
+}
+
+/* Reduce the range of XI to a multiple of PI/2 using fast integer arithmetic.
+   XI is a reinterpreted float and must be >= 2.0f (the sign bit is ignored).
+   Return the modulo between -PI/4 and PI/4 and store the quadrant in NP.
+   Reduction uses a table of 4/PI with 192 bits of precision.  A 32x96->128 bit
+   multiply computes the exact 2.62-bit fixed-point modulo.  Since the result
+   can have at most 29 leading zeros after the binary point, the double
+   precision result is accurate to 33 bits.  */
+static inline double
+reduce_large (uint32_t xi, int *np)
+{
+  const uint32_t *arr = &__inv_pio4[(xi >> 26) & 15];
+  int shift = (xi >> 23) & 7;
+  uint64_t n, res0, res1, res2;
+
+  xi = (xi & 0xffffff) | 0x800000;
+  xi <<= shift;
+
+  res0 = xi * arr[0];
+  res1 = (uint64_t)xi * arr[4];
+  res2 = (uint64_t)xi * arr[8];
+  res0 = (res2 >> 32) | (res0 << 32);
+  res0 += res1;
+
+  n = (res0 + (1ULL << 61)) >> 62;
+  res0 -= n << 62;
+  double x = (int64_t)res0;
+  *np = n;
+  return x * pi63;
+}
diff --git a/libc/AOR_v20.02/math/sincosf_data.c b/libc/AOR_v20.02/math/sincosf_data.c
new file mode 100644 (file)
index 0000000..a3d5efd
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ * Data definition for sinf, cosf and sincosf.
+ *
+ * Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+ * See https://llvm.org/LICENSE.txt for license information.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include <stdint.h>
+#include <math.h>
+#include "math_config.h"
+#include "sincosf.h"
+
+/* The constants and polynomials for sine and cosine.  The 2nd entry
+   computes -cos (x) rather than cos (x) to get negation for free.  */
+const sincos_t __sincosf_table[2] =
+{
+  {
+    { 1.0, -1.0, -1.0, 1.0 },
+#if TOINT_INTRINSICS
+    0x1.45F306DC9C883p-1,
+#else
+    0x1.45F306DC9C883p+23,
+#endif
+    0x1.921FB54442D18p0,
+    0x1p0,
+    -0x1.ffffffd0c621cp-2,
+    0x1.55553e1068f19p-5,
+    -0x1.6c087e89a359dp-10,
+    0x1.99343027bf8c3p-16,
+    -0x1.555545995a603p-3,
+    0x1.1107605230bc4p-7,
+    -0x1.994eb3774cf24p-13
+  },
+  {
+    { 1.0, -1.0, -1.0, 1.0 },
+#if TOINT_INTRINSICS
+    0x1.45F306DC9C883p-1,
+#else
+    0x1.45F306DC9C883p+23,
+#endif
+    0x1.921FB54442D18p0,
+    -0x1p0,
+    0x1.ffffffd0c621cp-2,
+    -0x1.55553e1068f19p-5,
+    0x1.6c087e89a359dp-10,
+    -0x1.99343027bf8c3p-16,
+    -0x1.555545995a603p-3,
+    0x1.1107605230bc4p-7,
+    -0x1.994eb3774cf24p-13
+  }
+};
+
+/* Table with 4/PI to 192 bit precision.  To avoid unaligned accesses
+   only 8 new bits are added per entry, making the table 4 times larger.  */
+const uint32_t __inv_pio4[24] =
+{
+  0xa2,       0xa2f9,    0xa2f983,   0xa2f9836e,
+  0xf9836e4e, 0x836e4e44, 0x6e4e4415, 0x4e441529,
+  0x441529fc, 0x1529fc27, 0x29fc2757, 0xfc2757d1,
+  0x2757d1f5, 0x57d1f534, 0xd1f534dd, 0xf534ddc0,
+  0x34ddc0db, 0xddc0db62, 0xc0db6295, 0xdb629599,
+  0x6295993c, 0x95993c43, 0x993c4390, 0x3c439041
+};
diff --git a/libc/AOR_v20.02/math/sinf.c b/libc/AOR_v20.02/math/sinf.c
new file mode 100644 (file)
index 0000000..644b82d
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * Single-precision sin function.
+ *
+ * Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+ * See https://llvm.org/LICENSE.txt for license information.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include <math.h>
+#include "math_config.h"
+#include "sincosf.h"
+
+/* Fast sinf implementation.  Worst-case ULP is 0.5607, maximum relative
+   error is 0.5303 * 2^-23.  A single-step range reduction is used for
+   small values.  Large inputs have their range reduced using fast integer
+   arithmetic.  */
+float
+sinf (float y)
+{
+  double x = y;
+  double s;
+  int n;
+  const sincos_t *p = &__sincosf_table[0];
+
+  if (abstop12 (y) < abstop12 (pio4))
+    {
+      s = x * x;
+
+      if (unlikely (abstop12 (y) < abstop12 (0x1p-12f)))
+       {
+         if (unlikely (abstop12 (y) < abstop12 (0x1p-126f)))
+           /* Force underflow for tiny y.  */
+           force_eval_float (s);
+         return y;
+       }
+
+      return sinf_poly (x, s, p, 0);
+    }
+  else if (likely (abstop12 (y) < abstop12 (120.0f)))
+    {
+      x = reduce_fast (x, p, &n);
+
+      /* Setup the signs for sin and cos.  */
+      s = p->sign[n & 3];
+
+      if (n & 2)
+       p = &__sincosf_table[1];
+
+      return sinf_poly (x * s, x * x, p, n);
+    }
+  else if (abstop12 (y) < abstop12 (INFINITY))
+    {
+      uint32_t xi = asuint (y);
+      int sign = xi >> 31;
+
+      x = reduce_large (xi, &n);
+
+      /* Setup signs for sin and cos - include original sign.  */
+      s = p->sign[(n + sign) & 3];
+
+      if ((n + sign) & 2)
+       p = &__sincosf_table[1];
+
+      return sinf_poly (x * s, x * x, p, n);
+    }
+  else
+    return __math_invalidf (y);
+}
diff --git a/libc/AOR_v20.02/math/test/mathbench.c b/libc/AOR_v20.02/math/test/mathbench.c
new file mode 100644 (file)
index 0000000..a57eddb
--- /dev/null
@@ -0,0 +1,772 @@
+/*
+ * Microbenchmark for math functions.
+ *
+ * Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+ * See https://llvm.org/LICENSE.txt for license information.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#undef _GNU_SOURCE
+#define _GNU_SOURCE 1
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <time.h>
+#include <math.h>
+#include "mathlib.h"
+
+#ifndef WANT_VMATH
+/* Enable the build of vector math code.  */
+# define WANT_VMATH 1
+#endif
+
+/* Number of measurements, best result is reported.  */
+#define MEASURE 60
+/* Array size.  */
+#define N 8000
+/* Iterations over the array.  */
+#define ITER 125
+
+static double *Trace;
+static size_t trace_size;
+static double A[N];
+static float Af[N];
+static long measurecount = MEASURE;
+static long itercount = ITER;
+
+#if __aarch64__ && WANT_VMATH
+typedef __f64x2_t v_double;
+
+#define v_double_len() 2
+
+static inline v_double
+v_double_load (const double *p)
+{
+  return (v_double){p[0], p[1]};
+}
+
+static inline v_double
+v_double_dup (double x)
+{
+  return (v_double){x, x};
+}
+
+typedef __f32x4_t v_float;
+
+#define v_float_len() 4
+
+static inline v_float
+v_float_load (const float *p)
+{
+  return (v_float){p[0], p[1], p[2], p[3]};
+}
+
+static inline v_float
+v_float_dup (float x)
+{
+  return (v_float){x, x, x, x};
+}
+#else
+/* dummy definitions to make things compile.  */
+typedef double v_double;
+typedef float v_float;
+#define v_double_len(x) 1
+#define v_double_load(x) (x)[0]
+#define v_double_dup(x) (x)
+#define v_float_len(x) 1
+#define v_float_load(x) (x)[0]
+#define v_float_dup(x) (x)
+#endif
+
+static double
+dummy (double x)
+{
+  return x;
+}
+
+static float
+dummyf (float x)
+{
+  return x;
+}
+
+#if WANT_VMATH
+#if __aarch64__
+static v_double
+__v_dummy (v_double x)
+{
+  return x;
+}
+
+static v_float
+__v_dummyf (v_float x)
+{
+  return x;
+}
+
+#ifdef __vpcs
+__vpcs static v_double
+__vn_dummy (v_double x)
+{
+  return x;
+}
+
+__vpcs static v_float
+__vn_dummyf (v_float x)
+{
+  return x;
+}
+
+__vpcs static v_float
+xy__vn_powf (v_float x)
+{
+  return __vn_powf (x, x);
+}
+
+__vpcs static v_float
+xy_Z_powf (v_float x)
+{
+  return _ZGVnN4vv_powf (x, x);
+}
+
+__vpcs static v_double
+xy__vn_pow (v_double x)
+{
+  return __vn_pow (x, x);
+}
+
+__vpcs static v_double
+xy_Z_pow (v_double x)
+{
+  return _ZGVnN2vv_pow (x, x);
+}
+#endif
+
+static v_float
+xy__v_powf (v_float x)
+{
+  return __v_powf (x, x);
+}
+
+static v_double
+xy__v_pow (v_double x)
+{
+  return __v_pow (x, x);
+}
+#endif
+
+static float
+xy__s_powf (float x)
+{
+  return __s_powf (x, x);
+}
+
+static double
+xy__s_pow (double x)
+{
+  return __s_pow (x, x);
+}
+#endif
+
+static double
+xypow (double x)
+{
+  return pow (x, x);
+}
+
+static float
+xypowf (float x)
+{
+  return powf (x, x);
+}
+
+static double
+xpow (double x)
+{
+  return pow (x, 23.4);
+}
+
+static float
+xpowf (float x)
+{
+  return powf (x, 23.4f);
+}
+
+static double
+ypow (double x)
+{
+  return pow (2.34, x);
+}
+
+static float
+ypowf (float x)
+{
+  return powf (2.34f, x);
+}
+
+static float
+sincosf_wrap (float x)
+{
+  float s, c;
+  sincosf (x, &s, &c);
+  return s + c;
+}
+
+static const struct fun
+{
+  const char *name;
+  int prec;
+  int vec;
+  double lo;
+  double hi;
+  union
+  {
+    double (*d) (double);
+    float (*f) (float);
+    v_double (*vd) (v_double);
+    v_float (*vf) (v_float);
+#ifdef __vpcs
+    __vpcs v_double (*vnd) (v_double);
+    __vpcs v_float (*vnf) (v_float);
+#endif
+  } fun;
+} funtab[] = {
+#define D(func, lo, hi) {#func, 'd', 0, lo, hi, {.d = func}},
+#define F(func, lo, hi) {#func, 'f', 0, lo, hi, {.f = func}},
+#define VD(func, lo, hi) {#func, 'd', 'v', lo, hi, {.vd = func}},
+#define VF(func, lo, hi) {#func, 'f', 'v', lo, hi, {.vf = func}},
+#define VND(func, lo, hi) {#func, 'd', 'n', lo, hi, {.vnd = func}},
+#define VNF(func, lo, hi) {#func, 'f', 'n', lo, hi, {.vnf = func}},
+D (dummy, 1.0, 2.0)
+D (exp, -9.9, 9.9)
+D (exp, 0.5, 1.0)
+D (exp2, -9.9, 9.9)
+D (log, 0.01, 11.1)
+D (log, 0.999, 1.001)
+D (log2, 0.01, 11.1)
+D (log2, 0.999, 1.001)
+{"pow", 'd', 0, 0.01, 11.1, {.d = xypow}},
+D (xpow, 0.01, 11.1)
+D (ypow, -9.9, 9.9)
+
+F (dummyf, 1.0, 2.0)
+F (expf, -9.9, 9.9)
+F (exp2f, -9.9, 9.9)
+F (logf, 0.01, 11.1)
+F (log2f, 0.01, 11.1)
+{"powf", 'f', 0, 0.01, 11.1, {.f = xypowf}},
+F (xpowf, 0.01, 11.1)
+F (ypowf, -9.9, 9.9)
+{"sincosf", 'f', 0, 0.1, 0.7, {.f = sincosf_wrap}},
+{"sincosf", 'f', 0, 0.8, 3.1, {.f = sincosf_wrap}},
+{"sincosf", 'f', 0, -3.1, 3.1, {.f = sincosf_wrap}},
+{"sincosf", 'f', 0, 3.3, 33.3, {.f = sincosf_wrap}},
+{"sincosf", 'f', 0, 100, 1000, {.f = sincosf_wrap}},
+{"sincosf", 'f', 0, 1e6, 1e32, {.f = sincosf_wrap}},
+F (sinf, 0.1, 0.7)
+F (sinf, 0.8, 3.1)
+F (sinf, -3.1, 3.1)
+F (sinf, 3.3, 33.3)
+F (sinf, 100, 1000)
+F (sinf, 1e6, 1e32)
+F (cosf, 0.1, 0.7)
+F (cosf, 0.8, 3.1)
+F (cosf, -3.1, 3.1)
+F (cosf, 3.3, 33.3)
+F (cosf, 100, 1000)
+F (cosf, 1e6, 1e32)
+#if WANT_VMATH
+D (__s_sin, -3.1, 3.1)
+D (__s_cos, -3.1, 3.1)
+D (__s_exp, -9.9, 9.9)
+D (__s_log, 0.01, 11.1)
+{"__s_pow", 'd', 0, 0.01, 11.1, {.d = xy__s_pow}},
+F (__s_expf, -9.9, 9.9)
+F (__s_expf_1u, -9.9, 9.9)
+F (__s_exp2f, -9.9, 9.9)
+F (__s_exp2f_1u, -9.9, 9.9)
+F (__s_logf, 0.01, 11.1)
+{"__s_powf", 'f', 0, 0.01, 11.1, {.f = xy__s_powf}},
+F (__s_sinf, -3.1, 3.1)
+F (__s_cosf, -3.1, 3.1)
+#if __aarch64__
+VD (__v_dummy, 1.0, 2.0)
+VD (__v_sin, -3.1, 3.1)
+VD (__v_cos, -3.1, 3.1)
+VD (__v_exp, -9.9, 9.9)
+VD (__v_log, 0.01, 11.1)
+{"__v_pow", 'd', 'v', 0.01, 11.1, {.vd = xy__v_pow}},
+VF (__v_dummyf, 1.0, 2.0)
+VF (__v_expf, -9.9, 9.9)
+VF (__v_expf_1u, -9.9, 9.9)
+VF (__v_exp2f, -9.9, 9.9)
+VF (__v_exp2f_1u, -9.9, 9.9)
+VF (__v_logf, 0.01, 11.1)
+{"__v_powf", 'f', 'v', 0.01, 11.1, {.vf = xy__v_powf}},
+VF (__v_sinf, -3.1, 3.1)
+VF (__v_cosf, -3.1, 3.1)
+#ifdef __vpcs
+VND (__vn_dummy, 1.0, 2.0)
+VND (__vn_exp, -9.9, 9.9)
+VND (_ZGVnN2v_exp, -9.9, 9.9)
+VND (__vn_log, 0.01, 11.1)
+VND (_ZGVnN2v_log, 0.01, 11.1)
+{"__vn_pow", 'd', 'n', 0.01, 11.1, {.vnd = xy__vn_pow}},
+{"_ZGVnN2vv_pow", 'd', 'n', 0.01, 11.1, {.vnd = xy_Z_pow}},
+VND (__vn_sin, -3.1, 3.1)
+VND (_ZGVnN2v_sin, -3.1, 3.1)
+VND (__vn_cos, -3.1, 3.1)
+VND (_ZGVnN2v_cos, -3.1, 3.1)
+VNF (__vn_dummyf, 1.0, 2.0)
+VNF (__vn_expf, -9.9, 9.9)
+VNF (_ZGVnN4v_expf, -9.9, 9.9)
+VNF (__vn_expf_1u, -9.9, 9.9)
+VNF (__vn_exp2f, -9.9, 9.9)
+VNF (_ZGVnN4v_exp2f, -9.9, 9.9)
+VNF (__vn_exp2f_1u, -9.9, 9.9)
+VNF (__vn_logf, 0.01, 11.1)
+VNF (_ZGVnN4v_logf, 0.01, 11.1)
+{"__vn_powf", 'f', 'n', 0.01, 11.1, {.vnf = xy__vn_powf}},
+{"_ZGVnN4vv_powf", 'f', 'n', 0.01, 11.1, {.vnf = xy_Z_powf}},
+VNF (__vn_sinf, -3.1, 3.1)
+VNF (_ZGVnN4v_sinf, -3.1, 3.1)
+VNF (__vn_cosf, -3.1, 3.1)
+VNF (_ZGVnN4v_cosf, -3.1, 3.1)
+#endif
+#endif
+#endif
+{0},
+#undef F
+#undef D
+#undef VF
+#undef VD
+#undef VNF
+#undef VND
+};
+
+static void
+gen_linear (double lo, double hi)
+{
+  for (int i = 0; i < N; i++)
+    A[i] = (lo * (N - i) + hi * i) / N;
+}
+
+static void
+genf_linear (double lo, double hi)
+{
+  for (int i = 0; i < N; i++)
+    Af[i] = (float)(lo * (N - i) + hi * i) / N;
+}
+
+static inline double
+asdouble (uint64_t i)
+{
+  union
+  {
+    uint64_t i;
+    double f;
+  } u = {i};
+  return u.f;
+}
+
+static uint64_t seed = 0x0123456789abcdef;
+
+static double
+frand (double lo, double hi)
+{
+  seed = 6364136223846793005ULL * seed + 1;
+  return lo + (hi - lo) * (asdouble (seed >> 12 | 0x3ffULL << 52) - 1.0);
+}
+
+static void
+gen_rand (double lo, double hi)
+{
+  for (int i = 0; i < N; i++)
+    A[i] = frand (lo, hi);
+}
+
+static void
+genf_rand (double lo, double hi)
+{
+  for (int i = 0; i < N; i++)
+    Af[i] = (float)frand (lo, hi);
+}
+
+static void
+gen_trace (int index)
+{
+  for (int i = 0; i < N; i++)
+    A[i] = Trace[index + i];
+}
+
+static void
+genf_trace (int index)
+{
+  for (int i = 0; i < N; i++)
+    Af[i] = (float)Trace[index + i];
+}
+
+static void
+run_thruput (double f (double))
+{
+  for (int i = 0; i < N; i++)
+    f (A[i]);
+}
+
+static void
+runf_thruput (float f (float))
+{
+  for (int i = 0; i < N; i++)
+    f (Af[i]);
+}
+
+volatile double zero = 0;
+
+static void
+run_latency (double f (double))
+{
+  double z = zero;
+  double prev = z;
+  for (int i = 0; i < N; i++)
+    prev = f (A[i] + prev * z);
+}
+
+static void
+runf_latency (float f (float))
+{
+  float z = (float)zero;
+  float prev = z;
+  for (int i = 0; i < N; i++)
+    prev = f (Af[i] + prev * z);
+}
+
+static void
+run_v_thruput (v_double f (v_double))
+{
+  for (int i = 0; i < N; i += v_double_len ())
+    f (v_double_load (A+i));
+}
+
+static void
+runf_v_thruput (v_float f (v_float))
+{
+  for (int i = 0; i < N; i += v_float_len ())
+    f (v_float_load (Af+i));
+}
+
+static void
+run_v_latency (v_double f (v_double))
+{
+  v_double z = v_double_dup (zero);
+  v_double prev = z;
+  for (int i = 0; i < N; i += v_double_len ())
+    prev = f (v_double_load (A+i) + prev * z);
+}
+
+static void
+runf_v_latency (v_float f (v_float))
+{
+  v_float z = v_float_dup (zero);
+  v_float prev = z;
+  for (int i = 0; i < N; i += v_float_len ())
+    prev = f (v_float_load (Af+i) + prev * z);
+}
+
+#ifdef __vpcs
+static void
+run_vn_thruput (__vpcs v_double f (v_double))
+{
+  for (int i = 0; i < N; i += v_double_len ())
+    f (v_double_load (A+i));
+}
+
+static void
+runf_vn_thruput (__vpcs v_float f (v_float))
+{
+  for (int i = 0; i < N; i += v_float_len ())
+    f (v_float_load (Af+i));
+}
+
+static void
+run_vn_latency (__vpcs v_double f (v_double))
+{
+  v_double z = v_double_dup (zero);
+  v_double prev = z;
+  for (int i = 0; i < N; i += v_double_len ())
+    prev = f (v_double_load (A+i) + prev * z);
+}
+
+static void
+runf_vn_latency (__vpcs v_float f (v_float))
+{
+  v_float z = v_float_dup (zero);
+  v_float prev = z;
+  for (int i = 0; i < N; i += v_float_len ())
+    prev = f (v_float_load (Af+i) + prev * z);
+}
+#endif
+
+static uint64_t
+tic (void)
+{
+  struct timespec ts;
+  if (clock_gettime (CLOCK_REALTIME, &ts))
+    abort ();
+  return ts.tv_sec * 1000000000ULL + ts.tv_nsec;
+}
+
+#define TIMEIT(run, f) do { \
+  dt = -1; \
+  run (f); /* Warm up.  */ \
+  for (int j = 0; j < measurecount; j++) \
+    { \
+      uint64_t t0 = tic (); \
+      for (int i = 0; i < itercount; i++) \
+       run (f); \
+      uint64_t t1 = tic (); \
+      if (t1 - t0 < dt) \
+       dt = t1 - t0; \
+    } \
+} while (0)
+
+static void
+bench1 (const struct fun *f, int type, double lo, double hi)
+{
+  uint64_t dt = 0;
+  uint64_t ns100;
+  const char *s = type == 't' ? "rthruput" : "latency";
+  int vlen = 1;
+
+  if (f->vec && f->prec == 'd')
+    vlen = v_double_len();
+  else if (f->vec && f->prec == 'f')
+    vlen = v_float_len();
+
+  if (f->prec == 'd' && type == 't' && f->vec == 0)
+    TIMEIT (run_thruput, f->fun.d);
+  else if (f->prec == 'd' && type == 'l' && f->vec == 0)
+    TIMEIT (run_latency, f->fun.d);
+  else if (f->prec == 'f' && type == 't' && f->vec == 0)
+    TIMEIT (runf_thruput, f->fun.f);
+  else if (f->prec == 'f' && type == 'l' && f->vec == 0)
+    TIMEIT (runf_latency, f->fun.f);
+  else if (f->prec == 'd' && type == 't' && f->vec == 'v')
+    TIMEIT (run_v_thruput, f->fun.vd);
+  else if (f->prec == 'd' && type == 'l' && f->vec == 'v')
+    TIMEIT (run_v_latency, f->fun.vd);
+  else if (f->prec == 'f' && type == 't' && f->vec == 'v')
+    TIMEIT (runf_v_thruput, f->fun.vf);
+  else if (f->prec == 'f' && type == 'l' && f->vec == 'v')
+    TIMEIT (runf_v_latency, f->fun.vf);
+#ifdef __vpcs
+  else if (f->prec == 'd' && type == 't' && f->vec == 'n')
+    TIMEIT (run_vn_thruput, f->fun.vnd);
+  else if (f->prec == 'd' && type == 'l' && f->vec == 'n')
+    TIMEIT (run_vn_latency, f->fun.vnd);
+  else if (f->prec == 'f' && type == 't' && f->vec == 'n')
+    TIMEIT (runf_vn_thruput, f->fun.vnf);
+  else if (f->prec == 'f' && type == 'l' && f->vec == 'n')
+    TIMEIT (runf_vn_latency, f->fun.vnf);
+#endif
+
+  if (type == 't')
+    {
+      ns100 = (100 * dt + itercount * N / 2) / (itercount * N);
+      printf ("%9s %8s: %4u.%02u ns/elem %10llu ns in [%g %g]\n", f->name, s,
+             (unsigned) (ns100 / 100), (unsigned) (ns100 % 100),
+             (unsigned long long) dt, lo, hi);
+    }
+  else if (type == 'l')
+    {
+      ns100 = (100 * dt + itercount * N / vlen / 2) / (itercount * N / vlen);
+      printf ("%9s %8s: %4u.%02u ns/call %10llu ns in [%g %g]\n", f->name, s,
+             (unsigned) (ns100 / 100), (unsigned) (ns100 % 100),
+             (unsigned long long) dt, lo, hi);
+    }
+  fflush (stdout);
+}
+
+static void
+bench (const struct fun *f, double lo, double hi, int type, int gen)
+{
+  if (f->prec == 'd' && gen == 'r')
+    gen_rand (lo, hi);
+  else if (f->prec == 'd' && gen == 'l')
+    gen_linear (lo, hi);
+  else if (f->prec == 'd' && gen == 't')
+    gen_trace (0);
+  else if (f->prec == 'f' && gen == 'r')
+    genf_rand (lo, hi);
+  else if (f->prec == 'f' && gen == 'l')
+    genf_linear (lo, hi);
+  else if (f->prec == 'f' && gen == 't')
+    genf_trace (0);
+
+  if (gen == 't')
+    hi = trace_size / N;
+
+  if (type == 'b' || type == 't')
+    bench1 (f, 't', lo, hi);
+
+  if (type == 'b' || type == 'l')
+    bench1 (f, 'l', lo, hi);
+
+  for (int i = N; i < trace_size; i += N)
+    {
+      if (f->prec == 'd')
+       gen_trace (i);
+      else
+       genf_trace (i);
+
+      lo = i / N;
+      if (type == 'b' || type == 't')
+       bench1 (f, 't', lo, hi);
+
+      if (type == 'b' || type == 'l')
+       bench1 (f, 'l', lo, hi);
+    }
+}
+
+static void
+readtrace (const char *name)
+{
+       int n = 0;
+       FILE *f = strcmp (name, "-") == 0 ? stdin : fopen (name, "r");
+       if (!f)
+         {
+           printf ("openning \"%s\" failed: %m\n", name);
+           exit (1);
+         }
+       for (;;)
+         {
+           if (n >= trace_size)
+             {
+               trace_size += N;
+               Trace = realloc (Trace, trace_size * sizeof (Trace[0]));
+               if (Trace == NULL)
+                 {
+                   printf ("out of memory\n");
+                   exit (1);
+                 }
+             }
+           if (fscanf (f, "%lf", Trace + n) != 1)
+             break;
+           n++;
+         }
+       if (ferror (f) || n == 0)
+         {
+           printf ("reading \"%s\" failed: %m\n", name);
+           exit (1);
+         }
+       fclose (f);
+       if (n % N == 0)
+         trace_size = n;
+       for (int i = 0; n < trace_size; n++, i++)
+         Trace[n] = Trace[i];
+}
+
+static void
+usage (void)
+{
+  printf ("usage: ./mathbench [-g rand|linear|trace] [-t latency|thruput|both] "
+         "[-i low high] [-f tracefile] [-m measurements] [-c iterations] func "
+         "[func2 ..]\n");
+  printf ("func:\n");
+  printf ("%7s [run all benchmarks]\n", "all");
+  for (const struct fun *f = funtab; f->name; f++)
+    printf ("%7s [low: %g high: %g]\n", f->name, f->lo, f->hi);
+  exit (1);
+}
+
+int
+main (int argc, char *argv[])
+{
+  int usergen = 0, gen = 'r', type = 'b', all = 0;
+  double lo = 0, hi = 0;
+  const char *tracefile = "-";
+
+  argv++;
+  argc--;
+  for (;;)
+    {
+      if (argc <= 0)
+       usage ();
+      if (argv[0][0] != '-')
+       break;
+      else if (argc >= 3 && strcmp (argv[0], "-i") == 0)
+       {
+         usergen = 1;
+         lo = strtod (argv[1], 0);
+         hi = strtod (argv[2], 0);
+         argv += 3;
+         argc -= 3;
+       }
+      else if (argc >= 2 && strcmp (argv[0], "-m") == 0)
+       {
+         measurecount = strtol (argv[1], 0, 0);
+         argv += 2;
+         argc -= 2;
+       }
+      else if (argc >= 2 && strcmp (argv[0], "-c") == 0)
+       {
+         itercount = strtol (argv[1], 0, 0);
+         argv += 2;
+         argc -= 2;
+       }
+      else if (argc >= 2 && strcmp (argv[0], "-g") == 0)
+       {
+         gen = argv[1][0];
+         if (strchr ("rlt", gen) == 0)
+           usage ();
+         argv += 2;
+         argc -= 2;
+       }
+      else if (argc >= 2 && strcmp (argv[0], "-f") == 0)
+       {
+         gen = 't';  /* -f implies -g trace.  */
+         tracefile = argv[1];
+         argv += 2;
+         argc -= 2;
+       }
+      else if (argc >= 2 && strcmp (argv[0], "-t") == 0)
+       {
+         type = argv[1][0];
+         if (strchr ("ltb", type) == 0)
+           usage ();
+         argv += 2;
+         argc -= 2;
+       }
+      else
+       usage ();
+    }
+  if (gen == 't')
+    {
+      readtrace (tracefile);
+      lo = hi = 0;
+      usergen = 1;
+    }
+  while (argc > 0)
+    {
+      int found = 0;
+      all = strcmp (argv[0], "all") == 0;
+      for (const struct fun *f = funtab; f->name; f++)
+       if (all || strcmp (argv[0], f->name) == 0)
+         {
+           found = 1;
+           if (!usergen)
+             {
+               lo = f->lo;
+               hi = f->hi;
+             }
+           bench (f, lo, hi, type, gen);
+           if (usergen && !all)
+             break;
+         }
+      if (!found)
+       printf ("unknown function: %s\n", argv[0]);
+      argv++;
+      argc--;
+    }
+  return 0;
+}
diff --git a/libc/AOR_v20.02/math/test/mathtest.c b/libc/AOR_v20.02/math/test/mathtest.c
new file mode 100644 (file)
index 0000000..efe0a8a
--- /dev/null
@@ -0,0 +1,1702 @@
+/*
+ * mathtest.c - test rig for mathlib
+ *
+ * Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+ * See https://llvm.org/LICENSE.txt for license information.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <setjmp.h>
+#include <ctype.h>
+#include <math.h>
+#include <errno.h>
+#include <limits.h>
+#include <fenv.h>
+#include "mathlib.h"
+
+#ifndef math_errhandling
+# define math_errhandling 0
+#endif
+
+#ifdef __cplusplus
+ #define EXTERN_C extern "C"
+#else
+ #define EXTERN_C extern
+#endif
+
+#ifndef TRUE
+#define TRUE 1
+#endif
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+#ifdef IMPORT_SYMBOL
+#define STR2(x) #x
+#define STR(x) STR2(x)
+_Pragma(STR(import IMPORT_SYMBOL))
+#endif
+
+int dmsd, dlsd;
+int quiet = 0;
+int doround = 0;
+unsigned statusmask = FE_ALL_EXCEPT;
+
+#define EXTRABITS (12)
+#define ULPUNIT (1<<EXTRABITS)
+
+typedef int (*test) (void);
+
+/*
+  struct to hold info about a function (which could actually be a macro)
+*/
+typedef struct {
+    enum {
+        t_func, t_macro
+    } type;
+    enum {
+        at_d, at_s,      /* double or single precision float */
+        at_d2, at_s2,    /* same, but taking two args */
+        at_di, at_si,    /* double/single and an int */
+        at_dip, at_sip,  /* double/single and an int ptr */
+        at_ddp, at_ssp,  /* d/s and a d/s ptr */
+        at_dc, at_sc,    /* double or single precision complex */
+        at_dc2, at_sc2   /* same, but taking two args */
+    } argtype;
+    enum {
+        rt_d, rt_s, rt_i, /* double, single, int */
+        rt_dc, rt_sc,     /* double, single precision complex */
+        rt_d2, rt_s2      /* also use res2 */
+    } rettype;
+    union {
+        void* ptr;
+        double (*d_d_ptr)(double);
+        float (*s_s_ptr)(float);
+        int (*d_i_ptr)(double);
+        int (*s_i_ptr)(float);
+        double (*d2_d_ptr)(double, double);
+        float (*s2_s_ptr)(float, float);
+        double (*di_d_ptr)(double,int);
+        float (*si_s_ptr)(float,int);
+        double (*dip_d_ptr)(double,int*);
+        float (*sip_s_ptr)(float,int*);
+        double (*ddp_d_ptr)(double,double*);
+        float (*ssp_s_ptr)(float,float*);
+    } func;
+    enum {
+        m_none,
+        m_isfinite, m_isfinitef,
+        m_isgreater, m_isgreaterequal,
+        m_isgreaterequalf, m_isgreaterf,
+        m_isinf, m_isinff,
+        m_isless, m_islessequal,
+        m_islessequalf, m_islessf,
+        m_islessgreater, m_islessgreaterf,
+        m_isnan, m_isnanf,
+        m_isnormal, m_isnormalf,
+        m_isunordered, m_isunorderedf,
+        m_fpclassify, m_fpclassifyf,
+        m_signbit, m_signbitf,
+        /* not actually a macro, but makes things easier */
+        m_rred, m_rredf,
+        m_cadd, m_csub, m_cmul, m_cdiv,
+        m_caddf, m_csubf, m_cmulf, m_cdivf
+    } macro_name; /* only used if a macro/something that can't be done using func */
+    long long tolerance;
+    const char* name;
+} test_func;
+
+/* used in qsort */
+int compare_tfuncs(const void* a, const void* b) {
+    return strcmp(((test_func*)a)->name, ((test_func*)b)->name);
+}
+
+int is_double_argtype(int argtype) {
+    switch(argtype) {
+    case at_d:
+    case at_d2:
+    case at_dc:
+    case at_dc2:
+        return 1;
+    default:
+        return 0;
+    }
+}
+
+int is_single_argtype(int argtype) {
+    switch(argtype) {
+    case at_s:
+    case at_s2:
+    case at_sc:
+    case at_sc2:
+        return 1;
+    default:
+        return 0;
+    }
+}
+
+int is_double_rettype(int rettype) {
+    switch(rettype) {
+    case rt_d:
+    case rt_dc:
+    case rt_d2:
+        return 1;
+    default:
+        return 0;
+    }
+}
+
+int is_single_rettype(int rettype) {
+    switch(rettype) {
+    case rt_s:
+    case rt_sc:
+    case rt_s2:
+        return 1;
+    default:
+        return 0;
+    }
+}
+
+int is_complex_argtype(int argtype) {
+    switch(argtype) {
+    case at_dc:
+    case at_sc:
+    case at_dc2:
+    case at_sc2:
+        return 1;
+    default:
+        return 0;
+    }
+}
+
+int is_complex_rettype(int rettype) {
+    switch(rettype) {
+    case rt_dc:
+    case rt_sc:
+        return 1;
+    default:
+        return 0;
+    }
+}
+
+/*
+ * Special-case flags indicating that some functions' error
+ * tolerance handling is more complicated than a fixed relative
+ * error bound.
+ */
+#define ABSLOWERBOUND 0x4000000000000000LL
+#define PLUSMINUSPIO2 0x1000000000000000LL
+
+#define ARM_PREFIX(x) x
+
+#define TFUNC(arg,ret,name,tolerance) { t_func, arg, ret, (void*)&name, m_none, tolerance, #name }
+#define TFUNCARM(arg,ret,name,tolerance) { t_func, arg, ret, (void*)& ARM_PREFIX(name), m_none, tolerance, #name }
+#define MFUNC(arg,ret,name,tolerance) { t_macro, arg, ret, NULL, m_##name, tolerance, #name }
+
+/* sincosf wrappers for easier testing.  */
+static float sincosf_sinf(float x) { float s,c; sincosf(x, &s, &c); return s; }
+static float sincosf_cosf(float x) { float s,c; sincosf(x, &s, &c); return c; }
+
+test_func tfuncs[] = {
+    /* trigonometric */
+    TFUNC(at_d,rt_d, acos, 4*ULPUNIT),
+    TFUNC(at_d,rt_d, asin, 4*ULPUNIT),
+    TFUNC(at_d,rt_d, atan, 4*ULPUNIT),
+    TFUNC(at_d2,rt_d, atan2, 4*ULPUNIT),
+
+    TFUNC(at_d,rt_d, tan, 2*ULPUNIT),
+    TFUNC(at_d,rt_d, sin, 2*ULPUNIT),
+    TFUNC(at_d,rt_d, cos, 2*ULPUNIT),
+
+    TFUNC(at_s,rt_s, acosf, 4*ULPUNIT),
+    TFUNC(at_s,rt_s, asinf, 4*ULPUNIT),
+    TFUNC(at_s,rt_s, atanf, 4*ULPUNIT),
+    TFUNC(at_s2,rt_s, atan2f, 4*ULPUNIT),
+    TFUNCARM(at_s,rt_s, tanf, 4*ULPUNIT),
+    TFUNCARM(at_s,rt_s, sinf, 3*ULPUNIT/4),
+    TFUNCARM(at_s,rt_s, cosf, 3*ULPUNIT/4),
+    TFUNCARM(at_s,rt_s, sincosf_sinf, 3*ULPUNIT/4),
+    TFUNCARM(at_s,rt_s, sincosf_cosf, 3*ULPUNIT/4),
+
+    /* hyperbolic */
+    TFUNC(at_d, rt_d, atanh, 4*ULPUNIT),
+    TFUNC(at_d, rt_d, asinh, 4*ULPUNIT),
+    TFUNC(at_d, rt_d, acosh, 4*ULPUNIT),
+    TFUNC(at_d,rt_d, tanh, 4*ULPUNIT),
+    TFUNC(at_d,rt_d, sinh, 4*ULPUNIT),
+    TFUNC(at_d,rt_d, cosh, 4*ULPUNIT),
+
+    TFUNC(at_s, rt_s, atanhf, 4*ULPUNIT),
+    TFUNC(at_s, rt_s, asinhf, 4*ULPUNIT),
+    TFUNC(at_s, rt_s, acoshf, 4*ULPUNIT),
+    TFUNC(at_s,rt_s, tanhf, 4*ULPUNIT),
+    TFUNC(at_s,rt_s, sinhf, 4*ULPUNIT),
+    TFUNC(at_s,rt_s, coshf, 4*ULPUNIT),
+
+    /* exponential and logarithmic */
+    TFUNC(at_d,rt_d, log, 3*ULPUNIT/4),
+    TFUNC(at_d,rt_d, log10, 3*ULPUNIT),
+    TFUNC(at_d,rt_d, log2, 3*ULPUNIT/4),
+    TFUNC(at_d,rt_d, log1p, 2*ULPUNIT),
+    TFUNC(at_d,rt_d, exp, 3*ULPUNIT/4),
+    TFUNC(at_d,rt_d, exp2, 3*ULPUNIT/4),
+    TFUNC(at_d,rt_d, expm1, ULPUNIT),
+    TFUNCARM(at_s,rt_s, logf, ULPUNIT),
+    TFUNC(at_s,rt_s, log10f, 3*ULPUNIT),
+    TFUNCARM(at_s,rt_s, log2f, ULPUNIT),
+    TFUNC(at_s,rt_s, log1pf, 2*ULPUNIT),
+    TFUNCARM(at_s,rt_s, expf, 3*ULPUNIT/4),
+    TFUNCARM(at_s,rt_s, exp2f, 3*ULPUNIT/4),
+    TFUNC(at_s,rt_s, expm1f, ULPUNIT),
+
+    /* power */
+    TFUNC(at_d2,rt_d, pow, 3*ULPUNIT/4),
+    TFUNC(at_d,rt_d, sqrt, ULPUNIT/2),
+    TFUNC(at_d,rt_d, cbrt, 2*ULPUNIT),
+    TFUNC(at_d2, rt_d, hypot, 4*ULPUNIT),
+
+    TFUNCARM(at_s2,rt_s, powf, ULPUNIT),
+    TFUNC(at_s,rt_s, sqrtf, ULPUNIT/2),
+    TFUNC(at_s,rt_s, cbrtf, 2*ULPUNIT),
+    TFUNC(at_s2, rt_s, hypotf, 4*ULPUNIT),
+
+    /* error function */
+    TFUNC(at_d,rt_d, erf, 16*ULPUNIT),
+    TFUNC(at_s,rt_s, erff, 16*ULPUNIT),
+    TFUNC(at_d,rt_d, erfc, 16*ULPUNIT),
+    TFUNC(at_s,rt_s, erfcf, 16*ULPUNIT),
+
+    /* gamma functions */
+    TFUNC(at_d,rt_d, tgamma, 16*ULPUNIT),
+    TFUNC(at_s,rt_s, tgammaf, 16*ULPUNIT),
+    TFUNC(at_d,rt_d, lgamma, 16*ULPUNIT | ABSLOWERBOUND),
+    TFUNC(at_s,rt_s, lgammaf, 16*ULPUNIT | ABSLOWERBOUND),
+
+    TFUNC(at_d,rt_d, ceil, 0),
+    TFUNC(at_s,rt_s, ceilf, 0),
+    TFUNC(at_d2,rt_d, copysign, 0),
+    TFUNC(at_s2,rt_s, copysignf, 0),
+    TFUNC(at_d,rt_d, floor, 0),
+    TFUNC(at_s,rt_s, floorf, 0),
+    TFUNC(at_d2,rt_d, fmax, 0),
+    TFUNC(at_s2,rt_s, fmaxf, 0),
+    TFUNC(at_d2,rt_d, fmin, 0),
+    TFUNC(at_s2,rt_s, fminf, 0),
+    TFUNC(at_d2,rt_d, fmod, 0),
+    TFUNC(at_s2,rt_s, fmodf, 0),
+    MFUNC(at_d, rt_i, fpclassify, 0),
+    MFUNC(at_s, rt_i, fpclassifyf, 0),
+    TFUNC(at_dip,rt_d, frexp, 0),
+    TFUNC(at_sip,rt_s, frexpf, 0),
+    MFUNC(at_d, rt_i, isfinite, 0),
+    MFUNC(at_s, rt_i, isfinitef, 0),
+    MFUNC(at_d, rt_i, isgreater, 0),
+    MFUNC(at_d, rt_i, isgreaterequal, 0),
+    MFUNC(at_s, rt_i, isgreaterequalf, 0),
+    MFUNC(at_s, rt_i, isgreaterf, 0),
+    MFUNC(at_d, rt_i, isinf, 0),
+    MFUNC(at_s, rt_i, isinff, 0),
+    MFUNC(at_d, rt_i, isless, 0),
+    MFUNC(at_d, rt_i, islessequal, 0),
+    MFUNC(at_s, rt_i, islessequalf, 0),
+    MFUNC(at_s, rt_i, islessf, 0),
+    MFUNC(at_d, rt_i, islessgreater, 0),
+    MFUNC(at_s, rt_i, islessgreaterf, 0),
+    MFUNC(at_d, rt_i, isnan, 0),
+    MFUNC(at_s, rt_i, isnanf, 0),
+    MFUNC(at_d, rt_i, isnormal, 0),
+    MFUNC(at_s, rt_i, isnormalf, 0),
+    MFUNC(at_d, rt_i, isunordered, 0),
+    MFUNC(at_s, rt_i, isunorderedf, 0),
+    TFUNC(at_di,rt_d, ldexp, 0),
+    TFUNC(at_si,rt_s, ldexpf, 0),
+    TFUNC(at_ddp,rt_d2, modf, 0),
+    TFUNC(at_ssp,rt_s2, modff, 0),
+#ifndef BIGRANGERED
+    MFUNC(at_d, rt_d, rred, 2*ULPUNIT),
+#else
+    MFUNC(at_d, rt_d, m_rred, ULPUNIT),
+#endif
+    MFUNC(at_d, rt_i, signbit, 0),
+    MFUNC(at_s, rt_i, signbitf, 0),
+};
+
+/*
+ * keywords are: func size op1 op2 result res2 errno op1r op1i op2r op2i resultr resulti
+ * also we ignore: wrongresult wrongres2 wrongerrno
+ * op1 equivalent to op1r, same with op2 and result
+ */
+
+typedef struct {
+    test_func *func;
+    unsigned op1r[2]; /* real part, also used for non-complex numbers */
+    unsigned op1i[2]; /* imaginary part */
+    unsigned op2r[2];
+    unsigned op2i[2];
+    unsigned resultr[3];
+    unsigned resulti[3];
+    enum {
+        rc_none, rc_zero, rc_infinity, rc_nan, rc_finite
+    } resultc; /* special complex results, rc_none means use resultr and resulti as normal */
+    unsigned res2[2];
+    unsigned status;                   /* IEEE status return, if any */
+    unsigned maybestatus;             /* for optional status, or allowance for spurious */
+    int nresult;                       /* number of result words */
+    int in_err, in_err_limit;
+    int err;
+    int maybeerr;
+    int valid;
+    int comment;
+    int random;
+} testdetail;
+
+enum {                                 /* keywords */
+    k_errno, k_errno_in, k_error, k_func, k_maybeerror, k_maybestatus, k_op1, k_op1i, k_op1r, k_op2, k_op2i, k_op2r,
+    k_random, k_res2, k_result, k_resultc, k_resulti, k_resultr, k_status,
+    k_wrongres2, k_wrongresult, k_wrongstatus, k_wrongerrno
+};
+char *keywords[] = {
+    "errno", "errno_in", "error", "func", "maybeerror", "maybestatus", "op1", "op1i", "op1r", "op2", "op2i", "op2r",
+    "random", "res2", "result", "resultc", "resulti", "resultr", "status",
+    "wrongres2", "wrongresult", "wrongstatus", "wrongerrno"
+};
+
+enum {
+    e_0, e_EDOM, e_ERANGE,
+
+    /*
+     * This enum makes sure that we have the right number of errnos in the
+     * errno[] array
+     */
+    e_number_of_errnos
+};
+char *errnos[] = {
+    "0", "EDOM", "ERANGE"
+};
+
+enum {
+    e_none, e_divbyzero, e_domain, e_overflow, e_underflow
+};
+char *errors[] = {
+    "0", "divbyzero", "domain", "overflow", "underflow"
+};
+
+static int verbose, fo, strict;
+
+/* state toggled by random=on / random=off */
+static int randomstate;
+
+/* Canonify a double NaN: SNaNs all become 7FF00000.00000001 and QNaNs
+ * all become 7FF80000.00000001 */
+void canon_dNaN(unsigned a[2]) {
+    if ((a[0] & 0x7FF00000) != 0x7FF00000)
+        return;                        /* not Inf or NaN */
+    if (!(a[0] & 0xFFFFF) && !a[1])
+        return;                        /* Inf */
+    a[0] &= 0x7FF80000;                /* canonify top word */
+    a[1] = 0x00000001;                 /* canonify bottom word */
+}
+
+/* Canonify a single NaN: SNaNs all become 7F800001 and QNaNs
+ * all become 7FC00001. Returns classification of the NaN. */
+void canon_sNaN(unsigned a[1]) {
+    if ((a[0] & 0x7F800000) != 0x7F800000)
+        return;                        /* not Inf or NaN */
+    if (!(a[0] & 0x7FFFFF))
+        return;                        /* Inf */
+    a[0] &= 0x7FC00000;                /* canonify most bits */
+    a[0] |= 0x00000001;                /* canonify bottom bit */
+}
+
+/*
+ * Detect difficult operands for FO mode.
+ */
+int is_dhard(unsigned a[2])
+{
+    if ((a[0] & 0x7FF00000) == 0x7FF00000)
+        return TRUE;                   /* inf or NaN */
+    if ((a[0] & 0x7FF00000) == 0 &&
+        ((a[0] & 0x7FFFFFFF) | a[1]) != 0)
+        return TRUE;                   /* denormal */
+    return FALSE;
+}
+int is_shard(unsigned a[1])
+{
+    if ((a[0] & 0x7F800000) == 0x7F800000)
+        return TRUE;                   /* inf or NaN */
+    if ((a[0] & 0x7F800000) == 0 &&
+        (a[0] & 0x7FFFFFFF) != 0)
+        return TRUE;                   /* denormal */
+    return FALSE;
+}
+
+/*
+ * Normalise all zeroes into +0, for FO mode.
+ */
+void dnormzero(unsigned a[2])
+{
+    if (a[0] == 0x80000000 && a[1] == 0)
+        a[0] = 0;
+}
+void snormzero(unsigned a[1])
+{
+    if (a[0] == 0x80000000)
+        a[0] = 0;
+}
+
+static int find(char *word, char **array, int asize) {
+    int i, j;
+
+    asize /= sizeof(char *);
+
+    i = -1; j = asize;                 /* strictly between i and j */
+    while (j-i > 1) {
+        int k = (i+j) / 2;
+        int c = strcmp(word, array[k]);
+        if (c > 0)
+            i = k;
+        else if (c < 0)
+            j = k;
+        else                           /* found it! */
+            return k;
+    }
+    return -1;                         /* not found */
+}
+
+static test_func* find_testfunc(char *word) {
+    int i, j, asize;
+
+    asize = sizeof(tfuncs)/sizeof(test_func);
+
+    i = -1; j = asize;                 /* strictly between i and j */
+    while (j-i > 1) {
+        int k = (i+j) / 2;
+        int c = strcmp(word, tfuncs[k].name);
+        if (c > 0)
+            i = k;
+        else if (c < 0)
+            j = k;
+        else                           /* found it! */
+            return tfuncs + k;
+    }
+    return NULL;                         /* not found */
+}
+
+static long long calc_error(unsigned a[2], unsigned b[3], int shift, int rettype) {
+    unsigned r0, r1, r2;
+    int sign, carry;
+    long long result;
+
+    /*
+     * If either number is infinite, require exact equality. If
+     * either number is NaN, require that both are NaN. If either
+     * of these requirements is broken, return INT_MAX.
+     */
+    if (is_double_rettype(rettype)) {
+        if ((a[0] & 0x7FF00000) == 0x7FF00000 ||
+            (b[0] & 0x7FF00000) == 0x7FF00000) {
+            if (((a[0] & 0x800FFFFF) || a[1]) &&
+                ((b[0] & 0x800FFFFF) || b[1]) &&
+                (a[0] & 0x7FF00000) == 0x7FF00000 &&
+                (b[0] & 0x7FF00000) == 0x7FF00000)
+                return 0;              /* both NaN - OK */
+            if (!((a[0] & 0xFFFFF) || a[1]) &&
+                !((b[0] & 0xFFFFF) || b[1]) &&
+                a[0] == b[0])
+                return 0;              /* both same sign of Inf - OK */
+            return LLONG_MAX;
+        }
+    } else {
+        if ((a[0] & 0x7F800000) == 0x7F800000 ||
+            (b[0] & 0x7F800000) == 0x7F800000) {
+            if ((a[0] & 0x807FFFFF) &&
+                (b[0] & 0x807FFFFF) &&
+                (a[0] & 0x7F800000) == 0x7F800000 &&
+                (b[0] & 0x7F800000) == 0x7F800000)
+                return 0;              /* both NaN - OK */
+            if (!(a[0] & 0x7FFFFF) &&
+                !(b[0] & 0x7FFFFF) &&
+                a[0] == b[0])
+                return 0;              /* both same sign of Inf - OK */
+            return LLONG_MAX;
+        }
+    }
+
+    /*
+     * Both finite. Return INT_MAX if the signs differ.
+     */
+    if ((a[0] ^ b[0]) & 0x80000000)
+        return LLONG_MAX;
+
+    /*
+     * Now it's just straight multiple-word subtraction.
+     */
+    if (is_double_rettype(rettype)) {
+        r2 = -b[2]; carry = (r2 == 0);
+        r1 = a[1] + ~b[1] + carry; carry = (r1 < a[1] || (carry && r1 == a[1]));
+        r0 = a[0] + ~b[0] + carry;
+    } else {
+        r2 = -b[1]; carry = (r2 == 0);
+        r1 = a[0] + ~b[0] + carry; carry = (r1 < a[0] || (carry && r1 == a[0]));
+        r0 = ~0 + carry;
+    }
+
+    /*
+     * Forgive larger errors in specialised cases.
+     */
+    if (shift > 0) {
+        if (shift > 32*3)
+            return 0;                  /* all errors are forgiven! */
+        while (shift >= 32) {
+            r2 = r1;
+            r1 = r0;
+            r0 = -(r0 >> 31);
+            shift -= 32;
+        }
+
+        if (shift > 0) {
+            r2 = (r2 >> shift) | (r1 << (32-shift));
+            r1 = (r1 >> shift) | (r0 << (32-shift));
+            r0 = (r0 >> shift) | ((-(r0 >> 31)) << (32-shift));
+        }
+    }
+
+    if (r0 & 0x80000000) {
+        sign = 1;
+        r2 = ~r2; carry = (r2 == 0);
+        r1 = 0 + ~r1 + carry; carry = (carry && (r2 == 0));
+        r0 = 0 + ~r0 + carry;
+    } else {
+        sign = 0;
+    }
+
+    if (r0 >= (1LL<<(31-EXTRABITS)))
+        return LLONG_MAX;                /* many ulps out */
+
+    result = (r2 >> (32-EXTRABITS)) & (ULPUNIT-1);
+    result |= r1 << EXTRABITS;
+    result |= (long long)r0 << (32+EXTRABITS);
+    if (sign)
+        result = -result;
+    return result;
+}
+
+/* special named operands */
+
+typedef struct {
+    unsigned op1, op2;
+    char* name;
+} special_op;
+
+static special_op special_ops_double[] = {
+    {0x00000000,0x00000000,"0"},
+    {0x3FF00000,0x00000000,"1"},
+    {0x7FF00000,0x00000000,"inf"},
+    {0x7FF80000,0x00000001,"qnan"},
+    {0x7FF00000,0x00000001,"snan"},
+    {0x3ff921fb,0x54442d18,"pi2"},
+    {0x400921fb,0x54442d18,"pi"},
+    {0x3fe921fb,0x54442d18,"pi4"},
+    {0x4002d97c,0x7f3321d2,"3pi4"},
+};
+
+static special_op special_ops_float[] = {
+    {0x00000000,0,"0"},
+    {0x3f800000,0,"1"},
+    {0x7f800000,0,"inf"},
+    {0x7fc00000,0,"qnan"},
+    {0x7f800001,0,"snan"},
+    {0x3fc90fdb,0,"pi2"},
+    {0x40490fdb,0,"pi"},
+    {0x3f490fdb,0,"pi4"},
+    {0x4016cbe4,0,"3pi4"},
+};
+
+/*
+   This is what is returned by the below functions.
+   We need it to handle the sign of the number
+*/
+static special_op tmp_op = {0,0,0};
+
+special_op* find_special_op_from_op(unsigned op1, unsigned op2, int is_double) {
+    int i;
+    special_op* sop;
+    if(is_double) {
+        sop = special_ops_double;
+    } else {
+        sop = special_ops_float;
+    }
+    for(i = 0; i < sizeof(special_ops_double)/sizeof(special_op); i++) {
+        if(sop->op1 == (op1&0x7fffffff) && sop->op2 == op2) {
+            if(tmp_op.name) free(tmp_op.name);
+            tmp_op.name = malloc(strlen(sop->name)+2);
+            if(op1>>31) {
+                sprintf(tmp_op.name,"-%s",sop->name);
+            } else {
+                strcpy(tmp_op.name,sop->name);
+            }
+            return &tmp_op;
+        }
+        sop++;
+    }
+    return NULL;
+}
+
+special_op* find_special_op_from_name(const char* name, int is_double) {
+    int i, neg=0;
+    special_op* sop;
+    if(is_double) {
+        sop = special_ops_double;
+    } else {
+        sop = special_ops_float;
+    }
+    if(*name=='-') {
+        neg=1;
+        name++;
+    } else if(*name=='+') {
+        name++;
+    }
+    for(i = 0; i < sizeof(special_ops_double)/sizeof(special_op); i++) {
+        if(0 == strcmp(name,sop->name)) {
+            tmp_op.op1 = sop->op1;
+            if(neg) {
+                tmp_op.op1 |= 0x80000000;
+            }
+            tmp_op.op2 = sop->op2;
+            return &tmp_op;
+        }
+        sop++;
+    }
+    return NULL;
+}
+
+/*
+   helper function for the below
+   type=0 for single, 1 for double, 2 for no sop
+*/
+int do_op(char* q, unsigned* op, const char* name, int num, int sop_type) {
+    int i;
+    int n=num;
+    special_op* sop = NULL;
+    for(i = 0; i < num; i++) {
+        op[i] = 0;
+    }
+    if(sop_type<2) {
+        sop = find_special_op_from_name(q,sop_type);
+    }
+    if(sop != NULL) {
+        op[0] = sop->op1;
+        op[1] = sop->op2;
+    } else {
+        switch(num) {
+        case 1: n = sscanf(q, "%x", &op[0]); break;
+        case 2: n = sscanf(q, "%x.%x", &op[0], &op[1]); break;
+        case 3: n = sscanf(q, "%x.%x.%x", &op[0], &op[1], &op[2]); break;
+        default: return -1;
+        }
+    }
+    if (verbose) {
+        printf("%s=",name);
+        for (i = 0; (i < n); ++i) printf("%x.", op[i]);
+        printf(" (n=%d)\n", n);
+    }
+    return n;
+}
+
+testdetail parsetest(char *testbuf, testdetail oldtest) {
+    char *p; /* Current part of line: Option name */
+    char *q; /* Current part of line: Option value */
+    testdetail ret; /* What we return */
+    int k; /* Function enum from k_* */
+    int n; /* Used as returns for scanfs */
+    int argtype=2, rettype=2; /* for do_op */
+
+    /* clear ret */
+    memset(&ret, 0, sizeof(ret));
+
+    if (verbose) printf("Parsing line: %s\n", testbuf);
+    while (*testbuf && isspace(*testbuf)) testbuf++;
+    if (testbuf[0] == ';' || testbuf[0] == '#' || testbuf[0] == '!' ||
+        testbuf[0] == '>' || testbuf[0] == '\0') {
+        ret.comment = 1;
+        if (verbose) printf("Line is a comment\n");
+        return ret;
+    }
+    ret.comment = 0;
+
+    if (*testbuf == '+') {
+        if (oldtest.valid) {
+            ret = oldtest;             /* structure copy */
+        } else {
+            fprintf(stderr, "copy from invalid: ignored\n");
+        }
+        testbuf++;
+    }
+
+    ret.random = randomstate;
+
+    ret.in_err = 0;
+    ret.in_err_limit = e_number_of_errnos;
+
+    p = strtok(testbuf, " \t");
+    while (p != NULL) {
+        q = strchr(p, '=');
+        if (!q)
+            goto balderdash;
+        *q++ = '\0';
+        k = find(p, keywords, sizeof(keywords));
+        switch (k) {
+        case k_random:
+            randomstate = (!strcmp(q, "on"));
+            ret.comment = 1;
+            return ret;                /* otherwise ignore this line */
+        case k_func:
+            if (verbose) printf("func=%s ", q);
+            //ret.func = find(q, funcs, sizeof(funcs));
+            ret.func = find_testfunc(q);
+            if (ret.func == NULL)
+                {
+                    if (verbose) printf("(id=unknown)\n");
+                    goto balderdash;
+                }
+            if(is_single_argtype(ret.func->argtype))
+                argtype = 0;
+            else if(is_double_argtype(ret.func->argtype))
+                argtype = 1;
+            if(is_single_rettype(ret.func->rettype))
+                rettype = 0;
+            else if(is_double_rettype(ret.func->rettype))
+                rettype = 1;
+            //ret.size = sizes[ret.func];
+            if (verbose) printf("(name=%s) (size=%d)\n", ret.func->name, ret.func->argtype);
+            break;
+        case k_op1:
+        case k_op1r:
+            n = do_op(q,ret.op1r,"op1r",2,argtype);
+            if (n < 1)
+                goto balderdash;
+            break;
+        case k_op1i:
+            n = do_op(q,ret.op1i,"op1i",2,argtype);
+            if (n < 1)
+                goto balderdash;
+            break;
+        case k_op2:
+        case k_op2r:
+            n = do_op(q,ret.op2r,"op2r",2,argtype);
+            if (n < 1)
+                goto balderdash;
+            break;
+        case k_op2i:
+            n = do_op(q,ret.op2i,"op2i",2,argtype);
+            if (n < 1)
+                goto balderdash;
+            break;
+        case k_resultc:
+            puts(q);
+            if(strncmp(q,"inf",3)==0) {
+                ret.resultc = rc_infinity;
+            } else if(strcmp(q,"zero")==0) {
+                ret.resultc = rc_zero;
+            } else if(strcmp(q,"nan")==0) {
+                ret.resultc = rc_nan;
+            } else if(strcmp(q,"finite")==0) {
+                ret.resultc = rc_finite;
+            } else {
+                goto balderdash;
+            }
+            break;
+        case k_result:
+        case k_resultr:
+            n = (do_op)(q,ret.resultr,"resultr",3,rettype);
+            if (n < 1)
+                goto balderdash;
+            ret.nresult = n; /* assume real and imaginary have same no. words */
+            break;
+        case k_resulti:
+            n = do_op(q,ret.resulti,"resulti",3,rettype);
+            if (n < 1)
+                goto balderdash;
+            break;
+        case k_res2:
+            n = do_op(q,ret.res2,"res2",2,rettype);
+            if (n < 1)
+                goto balderdash;
+            break;
+        case k_status:
+            while (*q) {
+                if (*q == 'i') ret.status |= FE_INVALID;
+                if (*q == 'z') ret.status |= FE_DIVBYZERO;
+                if (*q == 'o') ret.status |= FE_OVERFLOW;
+                if (*q == 'u') ret.status |= FE_UNDERFLOW;
+                q++;
+            }
+            break;
+        case k_maybeerror:
+            n = find(q, errors, sizeof(errors));
+            if (n < 0)
+                goto balderdash;
+            if(math_errhandling&MATH_ERREXCEPT) {
+                switch(n) {
+                case e_domain: ret.maybestatus |= FE_INVALID; break;
+                case e_divbyzero: ret.maybestatus |= FE_DIVBYZERO; break;
+                case e_overflow: ret.maybestatus |= FE_OVERFLOW; break;
+                case e_underflow: ret.maybestatus |= FE_UNDERFLOW; break;
+                }
+            }
+            {
+                switch(n) {
+                case e_domain:
+                    ret.maybeerr = e_EDOM; break;
+                case e_divbyzero:
+                case e_overflow:
+                case e_underflow:
+                    ret.maybeerr = e_ERANGE; break;
+                }
+            }
+        case k_maybestatus:
+            while (*q) {
+                if (*q == 'i') ret.maybestatus |= FE_INVALID;
+                if (*q == 'z') ret.maybestatus |= FE_DIVBYZERO;
+                if (*q == 'o') ret.maybestatus |= FE_OVERFLOW;
+                if (*q == 'u') ret.maybestatus |= FE_UNDERFLOW;
+                q++;
+            }
+            break;
+        case k_error:
+            n = find(q, errors, sizeof(errors));
+            if (n < 0)
+                goto balderdash;
+            if(math_errhandling&MATH_ERREXCEPT) {
+                switch(n) {
+                case e_domain: ret.status |= FE_INVALID; break;
+                case e_divbyzero: ret.status |= FE_DIVBYZERO; break;
+                case e_overflow: ret.status |= FE_OVERFLOW; break;
+                case e_underflow: ret.status |= FE_UNDERFLOW; break;
+                }
+            }
+            if(math_errhandling&MATH_ERRNO) {
+                switch(n) {
+                case e_domain:
+                    ret.err = e_EDOM; break;
+                case e_divbyzero:
+                case e_overflow:
+                case e_underflow:
+                    ret.err = e_ERANGE; break;
+                }
+            }
+            if(!(math_errhandling&MATH_ERRNO)) {
+                switch(n) {
+                case e_domain:
+                    ret.maybeerr = e_EDOM; break;
+                case e_divbyzero:
+                case e_overflow:
+                case e_underflow:
+                    ret.maybeerr = e_ERANGE; break;
+                }
+            }
+            break;
+        case k_errno:
+            ret.err = find(q, errnos, sizeof(errnos));
+            if (ret.err < 0)
+                goto balderdash;
+            break;
+        case k_errno_in:
+            ret.in_err = find(q, errnos, sizeof(errnos));
+            if (ret.err < 0)
+                goto balderdash;
+            ret.in_err_limit = ret.in_err + 1;
+            break;
+        case k_wrongresult:
+        case k_wrongstatus:
+        case k_wrongres2:
+        case k_wrongerrno:
+            /* quietly ignore these keys */
+            break;
+        default:
+            goto balderdash;
+        }
+        p = strtok(NULL, " \t");
+    }
+    ret.valid = 1;
+    return ret;
+
+    /* come here from almost any error */
+ balderdash:
+    ret.valid = 0;
+    return ret;
+}
+
+typedef enum {
+    test_comment,                      /* deliberately not a test */
+    test_invalid,                      /* accidentally not a test */
+    test_decline,                      /* was a test, and wasn't run */
+    test_fail,                         /* was a test, and failed */
+    test_pass                          /* was a test, and passed */
+} testresult;
+
+char failtext[512];
+
+typedef union {
+    unsigned i[2];
+    double f;
+    double da[2];
+} dbl;
+
+typedef union {
+    unsigned i;
+    float f;
+    float da[2];
+} sgl;
+
+/* helper function for runtest */
+void print_error(int rettype, unsigned *result, char* text, char** failp) {
+    special_op *sop;
+    char *str;
+
+    if(result) {
+        *failp += sprintf(*failp," %s=",text);
+        sop = find_special_op_from_op(result[0],result[1],is_double_rettype(rettype));
+        if(sop) {
+            *failp += sprintf(*failp,"%s",sop->name);
+        } else {
+            if(is_double_rettype(rettype)) {
+                str="%08x.%08x";
+            } else {
+                str="%08x";
+            }
+            *failp += sprintf(*failp,str,result[0],result[1]);
+        }
+    }
+}
+
+
+void print_ulps_helper(const char *name, long long ulps, char** failp) {
+    if(ulps == LLONG_MAX) {
+        *failp += sprintf(*failp, " %s=HUGE", name);
+    } else {
+        *failp += sprintf(*failp, " %s=%.3f", name, (double)ulps / ULPUNIT);
+    }
+}
+
+/* for complex args make ulpsr or ulpsri = 0 to not print */
+void print_ulps(int rettype, long long ulpsr, long long ulpsi, char** failp) {
+    if(is_complex_rettype(rettype)) {
+        if (ulpsr) print_ulps_helper("ulpsr",ulpsr,failp);
+        if (ulpsi) print_ulps_helper("ulpsi",ulpsi,failp);
+    } else {
+        if (ulpsr) print_ulps_helper("ulps",ulpsr,failp);
+    }
+}
+
+int runtest(testdetail t) {
+    int err, status;
+
+    dbl d_arg1, d_arg2, d_res, d_res2;
+    sgl s_arg1, s_arg2, s_res, s_res2;
+
+    int deferred_decline = FALSE;
+    char *failp = failtext;
+
+    unsigned int intres=0;
+
+    int res2_adjust = 0;
+
+    if (t.comment)
+        return test_comment;
+    if (!t.valid)
+        return test_invalid;
+
+    /* Set IEEE status to mathlib-normal */
+    feclearexcept(FE_ALL_EXCEPT);
+
+    /* Deal with operands */
+#define DO_DOP(arg,op) arg.i[dmsd] = t.op[0]; arg.i[dlsd] = t.op[1]
+    DO_DOP(d_arg1,op1r);
+    DO_DOP(d_arg2,op2r);
+    s_arg1.i = t.op1r[0]; s_arg2.i = t.op2r[0];
+
+    /*
+     * Detect NaNs, infinities and denormals on input, and set a
+     * deferred decline flag if we're in FO mode.
+     *
+     * (We defer the decline rather than doing it immediately
+     * because even in FO mode the operation is not permitted to
+     * crash or tight-loop; so we _run_ the test, and then ignore
+     * all the results.)
+     */
+    if (fo) {
+        if (is_double_argtype(t.func->argtype) && is_dhard(t.op1r))
+            deferred_decline = TRUE;
+        if (t.func->argtype==at_d2 && is_dhard(t.op2r))
+            deferred_decline = TRUE;
+        if (is_single_argtype(t.func->argtype) && is_shard(t.op1r))
+            deferred_decline = TRUE;
+        if (t.func->argtype==at_s2 && is_shard(t.op2r))
+            deferred_decline = TRUE;
+        if (is_double_rettype(t.func->rettype) && is_dhard(t.resultr))
+            deferred_decline = TRUE;
+        if (t.func->rettype==rt_d2 && is_dhard(t.res2))
+            deferred_decline = TRUE;
+        if (is_single_argtype(t.func->rettype) && is_shard(t.resultr))
+            deferred_decline = TRUE;
+        if (t.func->rettype==rt_s2 && is_shard(t.res2))
+            deferred_decline = TRUE;
+        if (t.err == e_ERANGE)
+            deferred_decline = TRUE;
+    }
+
+    /*
+     * Perform the operation
+     */
+
+    errno = t.in_err == e_EDOM ? EDOM : t.in_err == e_ERANGE ? ERANGE : 0;
+    if (t.err == e_0)
+        t.err = t.in_err;
+    if (t.maybeerr == e_0)
+        t.maybeerr = t.in_err;
+
+    if(t.func->type == t_func) {
+        switch(t.func->argtype) {
+        case at_d: d_res.f = t.func->func.d_d_ptr(d_arg1.f); break;
+        case at_s: s_res.f = t.func->func.s_s_ptr(s_arg1.f); break;
+        case at_d2: d_res.f = t.func->func.d2_d_ptr(d_arg1.f, d_arg2.f); break;
+        case at_s2: s_res.f = t.func->func.s2_s_ptr(s_arg1.f, s_arg2.f); break;
+        case at_di: d_res.f = t.func->func.di_d_ptr(d_arg1.f, d_arg2.i[dmsd]); break;
+        case at_si: s_res.f = t.func->func.si_s_ptr(s_arg1.f, s_arg2.i); break;
+        case at_dip: d_res.f = t.func->func.dip_d_ptr(d_arg1.f, (int*)&intres); break;
+        case at_sip: s_res.f = t.func->func.sip_s_ptr(s_arg1.f, (int*)&intres); break;
+        case at_ddp: d_res.f = t.func->func.ddp_d_ptr(d_arg1.f, &d_res2.f); break;
+        case at_ssp: s_res.f = t.func->func.ssp_s_ptr(s_arg1.f, &s_res2.f); break;
+        default:
+            printf("unhandled function: %s\n",t.func->name);
+            return test_fail;
+        }
+    } else {
+        /* printf("macro: name=%s, num=%i, s1.i=0x%08x s1.f=%f\n",t.func->name, t.func->macro_name, s_arg1.i, (double)s_arg1.f); */
+        switch(t.func->macro_name) {
+        case m_isfinite: intres = isfinite(d_arg1.f); break;
+        case m_isinf: intres = isinf(d_arg1.f); break;
+        case m_isnan: intres = isnan(d_arg1.f); break;
+        case m_isnormal: intres = isnormal(d_arg1.f); break;
+        case m_signbit: intres = signbit(d_arg1.f); break;
+        case m_fpclassify: intres = fpclassify(d_arg1.f); break;
+        case m_isgreater: intres = isgreater(d_arg1.f, d_arg2.f); break;
+        case m_isgreaterequal: intres = isgreaterequal(d_arg1.f, d_arg2.f); break;
+        case m_isless: intres = isless(d_arg1.f, d_arg2.f); break;
+        case m_islessequal: intres = islessequal(d_arg1.f, d_arg2.f); break;
+        case m_islessgreater: intres = islessgreater(d_arg1.f, d_arg2.f); break;
+        case m_isunordered: intres = isunordered(d_arg1.f, d_arg2.f); break;
+
+        case m_isfinitef: intres = isfinite(s_arg1.f); break;
+        case m_isinff: intres = isinf(s_arg1.f); break;
+        case m_isnanf: intres = isnan(s_arg1.f); break;
+        case m_isnormalf: intres = isnormal(s_arg1.f); break;
+        case m_signbitf: intres = signbit(s_arg1.f); break;
+        case m_fpclassifyf: intres = fpclassify(s_arg1.f); break;
+        case m_isgreaterf: intres = isgreater(s_arg1.f, s_arg2.f); break;
+        case m_isgreaterequalf: intres = isgreaterequal(s_arg1.f, s_arg2.f); break;
+        case m_islessf: intres = isless(s_arg1.f, s_arg2.f); break;
+        case m_islessequalf: intres = islessequal(s_arg1.f, s_arg2.f); break;
+        case m_islessgreaterf: intres = islessgreater(s_arg1.f, s_arg2.f); break;
+        case m_isunorderedf: intres = isunordered(s_arg1.f, s_arg2.f); break;
+
+        default:
+            printf("unhandled macro: %s\n",t.func->name);
+            return test_fail;
+        }
+    }
+
+    /*
+     * Decline the test if the deferred decline flag was set above.
+     */
+    if (deferred_decline)
+        return test_decline;
+
+    /* printf("intres=%i\n",intres); */
+
+    /* Clear the fail text (indicating a pass unless we change it) */
+    failp[0] = '\0';
+
+    /* Check the IEEE status bits (except INX, which we disregard).
+     * We don't bother with this for complex numbers, because the
+     * complex functions are hard to get exactly right and we don't
+     * have to anyway (C99 annex G is only informative). */
+    if (!(is_complex_argtype(t.func->argtype) || is_complex_rettype(t.func->rettype))) {
+        status = fetestexcept(FE_INVALID|FE_DIVBYZERO|FE_OVERFLOW|FE_UNDERFLOW);
+        if ((status|t.maybestatus|~statusmask) != (t.status|t.maybestatus|~statusmask)) {
+            if (quiet) failtext[0]='x';
+            else {
+                failp += sprintf(failp,
+                                 " wrongstatus=%s%s%s%s%s",
+                                 (status & FE_INVALID ? "i" : ""),
+                                 (status & FE_DIVBYZERO ? "z" : ""),
+                                 (status & FE_OVERFLOW ? "o" : ""),
+                                 (status & FE_UNDERFLOW ? "u" : ""),
+                                 (status ? "" : "OK"));
+            }
+        }
+    }
+
+    /* Check the result */
+    {
+        unsigned resultr[2], resulti[2];
+        unsigned tresultr[3], tresulti[3], wres;
+
+        switch(t.func->rettype) {
+        case rt_d:
+        case rt_d2:
+            tresultr[0] = t.resultr[0];
+            tresultr[1] = t.resultr[1];
+            resultr[0] = d_res.i[dmsd]; resultr[1] = d_res.i[dlsd];
+            wres = 2;
+            break;
+        case rt_i:
+            tresultr[0] = t.resultr[0];
+            resultr[0] = intres;
+            wres = 1;
+            break;
+        case rt_s:
+        case rt_s2:
+            tresultr[0] = t.resultr[0];
+            resultr[0] = s_res.i;
+            wres = 1;
+            break;
+        default:
+            puts("unhandled rettype in runtest");
+            wres = 0;
+        }
+        if(t.resultc != rc_none) {
+            int err = 0;
+            switch(t.resultc) {
+            case rc_zero:
+                if(resultr[0] != 0 || resulti[0] != 0 ||
+                   (wres==2 && (resultr[1] != 0 || resulti[1] != 0))) {
+                    err = 1;
+                }
+                break;
+            case rc_infinity:
+                if(wres==1) {
+                    if(!((resultr[0]&0x7fffffff)==0x7f800000 ||
+                         (resulti[0]&0x7fffffff)==0x7f800000)) {
+                        err = 1;
+                    }
+                } else {
+                  if(!(((resultr[0]&0x7fffffff)==0x7ff00000 && resultr[1]==0) ||
+                       ((resulti[0]&0x7fffffff)==0x7ff00000 && resulti[1]==0))) {
+                        err = 1;
+                    }
+                }
+                break;
+            case rc_nan:
+                if(wres==1) {
+                    if(!((resultr[0]&0x7fffffff)>0x7f800000 ||
+                         (resulti[0]&0x7fffffff)>0x7f800000)) {
+                        err = 1;
+                    }
+                } else {
+                    canon_dNaN(resultr);
+                    canon_dNaN(resulti);
+                    if(!(((resultr[0]&0x7fffffff)>0x7ff00000 && resultr[1]==1) ||
+                         ((resulti[0]&0x7fffffff)>0x7ff00000 && resulti[1]==1))) {
+                        err = 1;
+                    }
+                }
+                break;
+            case rc_finite:
+                if(wres==1) {
+                    if(!((resultr[0]&0x7fffffff)<0x7f800000 ||
+                         (resulti[0]&0x7fffffff)<0x7f800000)) {
+                        err = 1;
+                    }
+                } else {
+                    if(!((resultr[0]&0x7fffffff)<0x7ff00000 ||
+                         (resulti[0]&0x7fffffff)<0x7ff00000)) {
+                        err = 1;
+                    }
+                }
+                break;
+            default:
+                break;
+            }
+            if(err) {
+                print_error(t.func->rettype,resultr,"wrongresultr",&failp);
+                print_error(t.func->rettype,resulti,"wrongresulti",&failp);
+            }
+        } else if (t.nresult > wres) {
+            /*
+             * The test case data has provided the result to more
+             * than double precision. Instead of testing exact
+             * equality, we test against our maximum error
+             * tolerance.
+             */
+            int rshift, ishift;
+            long long ulpsr, ulpsi, ulptolerance;
+
+            tresultr[wres] = t.resultr[wres] << (32-EXTRABITS);
+            tresulti[wres] = t.resulti[wres] << (32-EXTRABITS);
+            if(strict) {
+                ulptolerance = 4096; /* one ulp */
+            } else {
+                ulptolerance = t.func->tolerance;
+            }
+            rshift = ishift = 0;
+            if (ulptolerance & ABSLOWERBOUND) {
+                /*
+                 * Hack for the lgamma functions, which have an
+                 * error behaviour that can't conveniently be
+                 * characterised in pure ULPs. Really, we want to
+                 * say that the error in lgamma is "at most N ULPs,
+                 * or at most an absolute error of X, whichever is
+                 * larger", for appropriately chosen N,X. But since
+                 * these two functions are the only cases where it
+                 * arises, I haven't bothered to do it in a nice way
+                 * in the function table above.
+                 *
+                 * (The difficult cases arise with negative input
+                 * values such that |gamma(x)| is very near to 1; in
+                 * this situation implementations tend to separately
+                 * compute lgamma(|x|) and the log of the correction
+                 * term from the Euler reflection formula, and
+                 * subtract - which catastrophically loses
+                 * significance.)
+                 *
+                 * As far as I can tell, nobody cares about this:
+                 * GNU libm doesn't get those cases right either,
+                 * and OpenCL explicitly doesn't state a ULP error
+                 * limit for lgamma. So my guess is that this is
+                 * simply considered acceptable error behaviour for
+                 * this particular function, and hence I feel free
+                 * to allow for it here.
+                 */
+                ulptolerance &= ~ABSLOWERBOUND;
+                if (t.op1r[0] & 0x80000000) {
+                    if (t.func->rettype == rt_d)
+                        rshift = 0x400 - ((tresultr[0] >> 20) & 0x7ff);
+                    else if (t.func->rettype == rt_s)
+                        rshift = 0x80 - ((tresultr[0] >> 23) & 0xff);
+                    if (rshift < 0)
+                        rshift = 0;
+                }
+            }
+            if (ulptolerance & PLUSMINUSPIO2) {
+                ulptolerance &= ~PLUSMINUSPIO2;
+                /*
+                 * Hack for range reduction, which can reduce
+                 * borderline cases in the wrong direction, i.e.
+                 * return a value just outside one end of the interval
+                 * [-pi/4,+pi/4] when it could have returned a value
+                 * just inside the other end by subtracting an
+                 * adjacent multiple of pi/2.
+                 *
+                 * We tolerate this, up to a point, because the
+                 * trigonometric functions making use of the output of
+                 * rred can cope and because making the range reducer
+                 * do the exactly right thing in every case would be
+                 * more expensive.
+                 */
+                if (wres == 1) {
+                    /* Upper bound of overshoot derived in rredf.h */
+                    if ((resultr[0]&0x7FFFFFFF) <= 0x3f494b02 &&
+                        (resultr[0]&0x7FFFFFFF) > 0x3f490fda &&
+                        (resultr[0]&0x80000000) != (tresultr[0]&0x80000000)) {
+                        unsigned long long val;
+                        val = tresultr[0];
+                        val = (val << 32) | tresultr[1];
+                        /*
+                         * Compute the alternative permitted result by
+                         * subtracting from the sum of the extended
+                         * single-precision bit patterns of +pi/4 and
+                         * -pi/4. This is a horrible hack which only
+                         * works because we can be confident that
+                         * numbers in this range all have the same
+                         * exponent!
+                         */
+                        val = 0xfe921fb54442d184ULL - val;
+                        tresultr[0] = val >> 32;
+                        tresultr[1] = (val >> (32-EXTRABITS)) << (32-EXTRABITS);
+                        /*
+                         * Also, expect a correspondingly different
+                         * value of res2 as a result of this change.
+                         * The adjustment depends on whether we just
+                         * flipped the result from + to - or vice
+                         * versa.
+                         */
+                        if (resultr[0] & 0x80000000) {
+                            res2_adjust = +1;
+                        } else {
+                            res2_adjust = -1;
+                        }
+                    }
+                }
+            }
+            ulpsr = calc_error(resultr, tresultr, rshift, t.func->rettype);
+            if(is_complex_rettype(t.func->rettype)) {
+                ulpsi = calc_error(resulti, tresulti, ishift, t.func->rettype);
+            } else {
+                ulpsi = 0;
+            }
+            unsigned *rr = (ulpsr > ulptolerance || ulpsr < -ulptolerance) ? resultr : NULL;
+            unsigned *ri = (ulpsi > ulptolerance || ulpsi < -ulptolerance) ? resulti : NULL;
+/*             printf("tolerance=%i, ulpsr=%i, ulpsi=%i, rr=%p, ri=%p\n",ulptolerance,ulpsr,ulpsi,rr,ri); */
+            if (rr || ri) {
+                if (quiet) failtext[0]='x';
+                else {
+                    print_error(t.func->rettype,rr,"wrongresultr",&failp);
+                    print_error(t.func->rettype,ri,"wrongresulti",&failp);
+                    print_ulps(t.func->rettype,rr ? ulpsr : 0, ri ? ulpsi : 0,&failp);
+                }
+            }
+        } else {
+            if(is_complex_rettype(t.func->rettype))
+                /*
+                 * Complex functions are not fully supported,
+                 * this is unreachable, but prevents warnings.
+                 */
+                abort();
+            /*
+             * The test case data has provided the result in
+             * exactly the output precision. Therefore we must
+             * complain about _any_ violation.
+             */
+            switch(t.func->rettype) {
+            case rt_dc:
+                canon_dNaN(tresulti);
+                canon_dNaN(resulti);
+                if (fo) {
+                    dnormzero(tresulti);
+                    dnormzero(resulti);
+                }
+                /* deliberate fall-through */
+            case rt_d:
+                canon_dNaN(tresultr);
+                canon_dNaN(resultr);
+                if (fo) {
+                    dnormzero(tresultr);
+                    dnormzero(resultr);
+                }
+                break;
+            case rt_sc:
+                canon_sNaN(tresulti);
+                canon_sNaN(resulti);
+                if (fo) {
+                    snormzero(tresulti);
+                    snormzero(resulti);
+                }
+                /* deliberate fall-through */
+            case rt_s:
+                canon_sNaN(tresultr);
+                canon_sNaN(resultr);
+                if (fo) {
+                    snormzero(tresultr);
+                    snormzero(resultr);
+                }
+                break;
+            default:
+                break;
+            }
+            if(is_complex_rettype(t.func->rettype)) {
+                unsigned *rr, *ri;
+                if(resultr[0] != tresultr[0] ||
+                   (wres > 1 && resultr[1] != tresultr[1])) {
+                    rr = resultr;
+                } else {
+                    rr = NULL;
+                }
+                if(resulti[0] != tresulti[0] ||
+                   (wres > 1 && resulti[1] != tresulti[1])) {
+                    ri = resulti;
+                } else {
+                    ri = NULL;
+                }
+                if(rr || ri) {
+                    if (quiet) failtext[0]='x';
+                    print_error(t.func->rettype,rr,"wrongresultr",&failp);
+                    print_error(t.func->rettype,ri,"wrongresulti",&failp);
+                }
+            } else if (resultr[0] != tresultr[0] ||
+                       (wres > 1 && resultr[1] != tresultr[1])) {
+                if (quiet) failtext[0]='x';
+                print_error(t.func->rettype,resultr,"wrongresult",&failp);
+            }
+        }
+        /*
+         * Now test res2, for those functions (frexp, modf, rred)
+         * which use it.
+         */
+        if (t.func->func.ptr == &frexp || t.func->func.ptr == &frexpf ||
+            t.func->macro_name == m_rred || t.func->macro_name == m_rredf) {
+            unsigned tres2 = t.res2[0];
+            if (res2_adjust) {
+                /* Fix for range reduction, propagated from further up */
+                tres2 = (tres2 + res2_adjust) & 3;
+            }
+            if (tres2 != intres) {
+                if (quiet) failtext[0]='x';
+                else {
+                    failp += sprintf(failp,
+                                     " wrongres2=%08x", intres);
+                }
+            }
+        } else if (t.func->func.ptr == &modf || t.func->func.ptr == &modff) {
+            tresultr[0] = t.res2[0];
+            tresultr[1] = t.res2[1];
+            if (is_double_rettype(t.func->rettype)) {
+                canon_dNaN(tresultr);
+                resultr[0] = d_res2.i[dmsd];
+                resultr[1] = d_res2.i[dlsd];
+                canon_dNaN(resultr);
+                if (fo) {
+                    dnormzero(tresultr);
+                    dnormzero(resultr);
+                }
+            } else {
+                canon_sNaN(tresultr);
+                resultr[0] = s_res2.i;
+                resultr[1] = s_res2.i;
+                canon_sNaN(resultr);
+                if (fo) {
+                    snormzero(tresultr);
+                    snormzero(resultr);
+                }
+            }
+            if (resultr[0] != tresultr[0] ||
+                (wres > 1 && resultr[1] != tresultr[1])) {
+                if (quiet) failtext[0]='x';
+                else {
+                    if (is_double_rettype(t.func->rettype))
+                        failp += sprintf(failp, " wrongres2=%08x.%08x",
+                                         resultr[0], resultr[1]);
+                    else
+                        failp += sprintf(failp, " wrongres2=%08x",
+                                         resultr[0]);
+                }
+            }
+        }
+    }
+
+    /* Check errno */
+    err = (errno == EDOM ? e_EDOM : errno == ERANGE ? e_ERANGE : e_0);
+    if (err != t.err && err != t.maybeerr) {
+        if (quiet) failtext[0]='x';
+        else {
+            failp += sprintf(failp, " wrongerrno=%s expecterrno=%s ", errnos[err], errnos[t.err]);
+        }
+    }
+
+    return *failtext ? test_fail : test_pass;
+}
+
+int passed, failed, declined;
+
+void runtests(char *name, FILE *fp) {
+    char testbuf[512], linebuf[512];
+    int lineno = 1;
+    testdetail test;
+
+    test.valid = 0;
+
+    if (verbose) printf("runtests: %s\n", name);
+    while (fgets(testbuf, sizeof(testbuf), fp)) {
+        int res, print_errno;
+        testbuf[strcspn(testbuf, "\r\n")] = '\0';
+        strcpy(linebuf, testbuf);
+        test = parsetest(testbuf, test);
+        print_errno = 0;
+        while (test.in_err < test.in_err_limit) {
+            res = runtest(test);
+            if (res == test_pass) {
+                if (verbose)
+                    printf("%s:%d: pass\n", name, lineno);
+                ++passed;
+            } else if (res == test_decline) {
+                if (verbose)
+                    printf("%s:%d: declined\n", name, lineno);
+                ++declined;
+            } else if (res == test_fail) {
+                if (!quiet)
+                    printf("%s:%d: FAIL%s: %s%s%s%s\n", name, lineno,
+                           test.random ? " (random)" : "",
+                           linebuf,
+                           print_errno ? " errno_in=" : "",
+                           print_errno ? errnos[test.in_err] : "",
+                           failtext);
+                ++failed;
+            } else if (res == test_invalid) {
+                printf("%s:%d: malformed: %s\n", name, lineno, linebuf);
+                ++failed;
+            }
+            test.in_err++;
+            print_errno = 1;
+        }
+        lineno++;
+    }
+}
+
+int main(int ac, char **av) {
+    char **files;
+    int i, nfiles = 0;
+    dbl d;
+
+#ifdef MICROLIB
+    /*
+     * Invent argc and argv ourselves.
+     */
+    char *argv[256];
+    char args[256];
+    {
+        int sargs[2];
+        char *p;
+
+        ac = 0;
+
+        sargs[0]=(int)args;
+        sargs[1]=(int)sizeof(args);
+        if (!__semihost(0x15, sargs)) {
+            args[sizeof(args)-1] = '\0';   /* just in case */
+            p = args;
+            while (1) {
+                while (*p == ' ' || *p == '\t') p++;
+                if (!*p) break;
+                argv[ac++] = p;
+                while (*p && *p != ' ' && *p != '\t') p++;
+                if (*p) *p++ = '\0';
+            }
+        }
+
+        av = argv;
+    }
+#endif
+
+    /* Sort tfuncs */
+    qsort(tfuncs, sizeof(tfuncs)/sizeof(test_func), sizeof(test_func), &compare_tfuncs);
+
+    /*
+     * Autodetect the `double' endianness.
+     */
+    dmsd = 0;
+    d.f = 1.0;                       /* 0x3ff00000 / 0x00000000 */
+    if (d.i[dmsd] == 0) {
+        dmsd = 1;
+    }
+    /*
+     * Now dmsd denotes what the compiler thinks we're at. Let's
+     * check that it agrees with what the runtime thinks.
+     */
+    d.i[0] = d.i[1] = 0x11111111;/* a random +ve number */
+    d.f /= d.f;                    /* must now be one */
+    if (d.i[dmsd] == 0) {
+        fprintf(stderr, "YIKES! Compiler and runtime disagree on endianness"
+                " of `double'. Bailing out\n");
+        return 1;
+    }
+    dlsd = !dmsd;
+
+    /* default is terse */
+    verbose = 0;
+    fo = 0;
+    strict = 0;
+
+    files = (char **)malloc((ac+1) * sizeof(char *));
+    if (!files) {
+        fprintf(stderr, "initial malloc failed!\n");
+        return 1;
+    }
+#ifdef NOCMDLINE
+    files[nfiles++] = "testfile";
+#endif
+
+    while (--ac) {
+        char *p = *++av;
+        if (*p == '-') {
+            static char *options[] = {
+                "-fo",
+#if 0
+                "-noinexact",
+                "-noround",
+#endif
+                "-nostatus",
+                "-quiet",
+                "-strict",
+                "-v",
+                "-verbose",
+            };
+            enum {
+                op_fo,
+#if 0
+                op_noinexact,
+                op_noround,
+#endif
+                op_nostatus,
+                op_quiet,
+                op_strict,
+                op_v,
+                op_verbose,
+            };
+            switch (find(p, options, sizeof(options))) {
+            case op_quiet:
+                quiet = 1;
+                break;
+#if 0
+            case op_noinexact:
+                statusmask &= 0x0F;    /* remove bit 4 */
+                break;
+            case op_noround:
+                doround = 0;
+                break;
+#endif
+            case op_nostatus:        /* no status word => noinx,noround */
+                statusmask = 0;
+                doround = 0;
+                break;
+            case op_v:
+            case op_verbose:
+                verbose = 1;
+                break;
+            case op_fo:
+                fo = 1;
+                break;
+            case op_strict: /* tolerance is 1 ulp */
+                strict = 1;
+                break;
+            default:
+                fprintf(stderr, "unrecognised option: %s\n", p);
+                break;
+            }
+        } else {
+            files[nfiles++] = p;
+        }
+    }
+
+    passed = failed = declined = 0;
+
+    if (nfiles) {
+        for (i = 0; i < nfiles; i++) {
+            FILE *fp = fopen(files[i], "r");
+            if (!fp) {
+                fprintf(stderr, "Couldn't open %s\n", files[i]);
+            } else
+                runtests(files[i], fp);
+        }
+    } else
+        runtests("(stdin)", stdin);
+
+    printf("Completed. Passed %d, failed %d (total %d",
+           passed, failed, passed+failed);
+    if (declined)
+        printf(" plus %d declined", declined);
+    printf(")\n");
+    if (failed || passed == 0)
+        return 1;
+    printf("** TEST PASSED OK **\n");
+    return 0;
+}
+
+void undef_func() {
+    failed++;
+    puts("ERROR: undefined function called");
+}
diff --git a/libc/AOR_v20.02/math/test/rtest/dotest.c b/libc/AOR_v20.02/math/test/rtest/dotest.c
new file mode 100644 (file)
index 0000000..4327862
--- /dev/null
@@ -0,0 +1,2168 @@
+/*
+ * dotest.c - actually generate mathlib test cases
+ *
+ * Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+ * See https://llvm.org/LICENSE.txt for license information.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <assert.h>
+#include <limits.h>
+
+#include "semi.h"
+#include "intern.h"
+#include "random.h"
+
+#define MPFR_PREC 96 /* good enough for float or double + a few extra bits */
+
+extern int lib_fo, lib_no_arith, ntests;
+
+/*
+ * Prototypes.
+ */
+static void cases_biased(uint32 *, uint32, uint32);
+static void cases_biased_positive(uint32 *, uint32, uint32);
+static void cases_biased_float(uint32 *, uint32, uint32);
+static void cases_uniform(uint32 *, uint32, uint32);
+static void cases_uniform_positive(uint32 *, uint32, uint32);
+static void cases_uniform_float(uint32 *, uint32, uint32);
+static void cases_uniform_float_positive(uint32 *, uint32, uint32);
+static void log_cases(uint32 *, uint32, uint32);
+static void log_cases_float(uint32 *, uint32, uint32);
+static void log1p_cases(uint32 *, uint32, uint32);
+static void log1p_cases_float(uint32 *, uint32, uint32);
+static void minmax_cases(uint32 *, uint32, uint32);
+static void minmax_cases_float(uint32 *, uint32, uint32);
+static void atan2_cases(uint32 *, uint32, uint32);
+static void atan2_cases_float(uint32 *, uint32, uint32);
+static void pow_cases(uint32 *, uint32, uint32);
+static void pow_cases_float(uint32 *, uint32, uint32);
+static void rred_cases(uint32 *, uint32, uint32);
+static void rred_cases_float(uint32 *, uint32, uint32);
+static void cases_semi1(uint32 *, uint32, uint32);
+static void cases_semi1_float(uint32 *, uint32, uint32);
+static void cases_semi2(uint32 *, uint32, uint32);
+static void cases_semi2_float(uint32 *, uint32, uint32);
+static void cases_ldexp(uint32 *, uint32, uint32);
+static void cases_ldexp_float(uint32 *, uint32, uint32);
+
+static void complex_cases_uniform(uint32 *, uint32, uint32);
+static void complex_cases_uniform_float(uint32 *, uint32, uint32);
+static void complex_cases_biased(uint32 *, uint32, uint32);
+static void complex_cases_biased_float(uint32 *, uint32, uint32);
+static void complex_log_cases(uint32 *, uint32, uint32);
+static void complex_log_cases_float(uint32 *, uint32, uint32);
+static void complex_pow_cases(uint32 *, uint32, uint32);
+static void complex_pow_cases_float(uint32 *, uint32, uint32);
+static void complex_arithmetic_cases(uint32 *, uint32, uint32);
+static void complex_arithmetic_cases_float(uint32 *, uint32, uint32);
+
+static uint32 doubletop(int x, int scale);
+static uint32 floatval(int x, int scale);
+
+/*
+ * Convert back and forth between IEEE bit patterns and the
+ * mpfr_t/mpc_t types.
+ */
+static void set_mpfr_d(mpfr_t x, uint32 h, uint32 l)
+{
+    uint64_t hl = ((uint64_t)h << 32) | l;
+    uint32 exp = (hl >> 52) & 0x7ff;
+    int64_t mantissa = hl & (((uint64_t)1 << 52) - 1);
+    int sign = (hl >> 63) ? -1 : +1;
+    if (exp == 0x7ff) {
+        if (mantissa == 0)
+            mpfr_set_inf(x, sign);
+        else
+            mpfr_set_nan(x);
+    } else if (exp == 0 && mantissa == 0) {
+        mpfr_set_ui(x, 0, GMP_RNDN);
+        mpfr_setsign(x, x, sign < 0, GMP_RNDN);
+    } else {
+        if (exp != 0)
+            mantissa |= ((uint64_t)1 << 52);
+        else
+            exp++;
+        mpfr_set_sj_2exp(x, mantissa * sign, (int)exp - 0x3ff - 52, GMP_RNDN);
+    }
+}
+static void set_mpfr_f(mpfr_t x, uint32 f)
+{
+    uint32 exp = (f >> 23) & 0xff;
+    int32 mantissa = f & ((1 << 23) - 1);
+    int sign = (f >> 31) ? -1 : +1;
+    if (exp == 0xff) {
+        if (mantissa == 0)
+            mpfr_set_inf(x, sign);
+        else
+            mpfr_set_nan(x);
+    } else if (exp == 0 && mantissa == 0) {
+        mpfr_set_ui(x, 0, GMP_RNDN);
+        mpfr_setsign(x, x, sign < 0, GMP_RNDN);
+    } else {
+        if (exp != 0)
+            mantissa |= (1 << 23);
+        else
+            exp++;
+        mpfr_set_sj_2exp(x, mantissa * sign, (int)exp - 0x7f - 23, GMP_RNDN);
+    }
+}
+static void set_mpc_d(mpc_t z, uint32 rh, uint32 rl, uint32 ih, uint32 il)
+{
+    mpfr_t x, y;
+    mpfr_init2(x, MPFR_PREC);
+    mpfr_init2(y, MPFR_PREC);
+    set_mpfr_d(x, rh, rl);
+    set_mpfr_d(y, ih, il);
+    mpc_set_fr_fr(z, x, y, MPC_RNDNN);
+    mpfr_clear(x);
+    mpfr_clear(y);
+}
+static void set_mpc_f(mpc_t z, uint32 r, uint32 i)
+{
+    mpfr_t x, y;
+    mpfr_init2(x, MPFR_PREC);
+    mpfr_init2(y, MPFR_PREC);
+    set_mpfr_f(x, r);
+    set_mpfr_f(y, i);
+    mpc_set_fr_fr(z, x, y, MPC_RNDNN);
+    mpfr_clear(x);
+    mpfr_clear(y);
+}
+static void get_mpfr_d(const mpfr_t x, uint32 *h, uint32 *l, uint32 *extra)
+{
+    uint32_t sign, expfield, mantfield;
+    mpfr_t significand;
+    int exp;
+
+    if (mpfr_nan_p(x)) {
+        *h = 0x7ff80000;
+        *l = 0;
+        *extra = 0;
+        return;
+    }
+
+    sign = mpfr_signbit(x) ? 0x80000000U : 0;
+
+    if (mpfr_inf_p(x)) {
+        *h = 0x7ff00000 | sign;
+        *l = 0;
+        *extra = 0;
+        return;
+    }
+
+    if (mpfr_zero_p(x)) {
+        *h = 0x00000000 | sign;
+        *l = 0;
+        *extra = 0;
+        return;
+    }
+
+    mpfr_init2(significand, MPFR_PREC);
+    mpfr_set(significand, x, GMP_RNDN);
+    exp = mpfr_get_exp(significand);
+    mpfr_set_exp(significand, 0);
+
+    /* Now significand is in [1/2,1), and significand * 2^exp == x.
+     * So the IEEE exponent corresponding to exp==0 is 0x3fe. */
+    if (exp > 0x400) {
+        /* overflow to infinity anyway */
+        *h = 0x7ff00000 | sign;
+        *l = 0;
+        *extra = 0;
+        mpfr_clear(significand);
+        return;
+    }
+
+    if (exp <= -0x3fe || mpfr_zero_p(x))
+        exp = -0x3fd;       /* denormalise */
+    expfield = exp + 0x3fd; /* offset to cancel leading mantissa bit */
+
+    mpfr_div_2si(significand, x, exp - 21, GMP_RNDN);
+    mpfr_abs(significand, significand, GMP_RNDN);
+    mantfield = mpfr_get_ui(significand, GMP_RNDZ);
+    *h = sign + ((uint64_t)expfield << 20) + mantfield;
+    mpfr_sub_ui(significand, significand, mantfield, GMP_RNDN);
+    mpfr_mul_2ui(significand, significand, 32, GMP_RNDN);
+    mantfield = mpfr_get_ui(significand, GMP_RNDZ);
+    *l = mantfield;
+    mpfr_sub_ui(significand, significand, mantfield, GMP_RNDN);
+    mpfr_mul_2ui(significand, significand, 32, GMP_RNDN);
+    mantfield = mpfr_get_ui(significand, GMP_RNDZ);
+    *extra = mantfield;
+
+    mpfr_clear(significand);
+}
+static void get_mpfr_f(const mpfr_t x, uint32 *f, uint32 *extra)
+{
+    uint32_t sign, expfield, mantfield;
+    mpfr_t significand;
+    int exp;
+
+    if (mpfr_nan_p(x)) {
+        *f = 0x7fc00000;
+        *extra = 0;
+        return;
+    }
+
+    sign = mpfr_signbit(x) ? 0x80000000U : 0;
+
+    if (mpfr_inf_p(x)) {
+        *f = 0x7f800000 | sign;
+        *extra = 0;
+        return;
+    }
+
+    if (mpfr_zero_p(x)) {
+        *f = 0x00000000 | sign;
+        *extra = 0;
+        return;
+    }
+
+    mpfr_init2(significand, MPFR_PREC);
+    mpfr_set(significand, x, GMP_RNDN);
+    exp = mpfr_get_exp(significand);
+    mpfr_set_exp(significand, 0);
+
+    /* Now significand is in [1/2,1), and significand * 2^exp == x.
+     * So the IEEE exponent corresponding to exp==0 is 0x7e. */
+    if (exp > 0x80) {
+        /* overflow to infinity anyway */
+        *f = 0x7f800000 | sign;
+        *extra = 0;
+        mpfr_clear(significand);
+        return;
+    }
+
+    if (exp <= -0x7e || mpfr_zero_p(x))
+        exp = -0x7d;                   /* denormalise */
+    expfield = exp + 0x7d; /* offset to cancel leading mantissa bit */
+
+    mpfr_div_2si(significand, x, exp - 24, GMP_RNDN);
+    mpfr_abs(significand, significand, GMP_RNDN);
+    mantfield = mpfr_get_ui(significand, GMP_RNDZ);
+    *f = sign + ((uint64_t)expfield << 23) + mantfield;
+    mpfr_sub_ui(significand, significand, mantfield, GMP_RNDN);
+    mpfr_mul_2ui(significand, significand, 32, GMP_RNDN);
+    mantfield = mpfr_get_ui(significand, GMP_RNDZ);
+    *extra = mantfield;
+
+    mpfr_clear(significand);
+}
+static void get_mpc_d(const mpc_t z,
+                      uint32 *rh, uint32 *rl, uint32 *rextra,
+                      uint32 *ih, uint32 *il, uint32 *iextra)
+{
+    mpfr_t x, y;
+    mpfr_init2(x, MPFR_PREC);
+    mpfr_init2(y, MPFR_PREC);
+    mpc_real(x, z, GMP_RNDN);
+    mpc_imag(y, z, GMP_RNDN);
+    get_mpfr_d(x, rh, rl, rextra);
+    get_mpfr_d(y, ih, il, iextra);
+    mpfr_clear(x);
+    mpfr_clear(y);
+}
+static void get_mpc_f(const mpc_t z,
+                      uint32 *r, uint32 *rextra,
+                      uint32 *i, uint32 *iextra)
+{
+    mpfr_t x, y;
+    mpfr_init2(x, MPFR_PREC);
+    mpfr_init2(y, MPFR_PREC);
+    mpc_real(x, z, GMP_RNDN);
+    mpc_imag(y, z, GMP_RNDN);
+    get_mpfr_f(x, r, rextra);
+    get_mpfr_f(y, i, iextra);
+    mpfr_clear(x);
+    mpfr_clear(y);
+}
+
+/*
+ * Implementation of mathlib functions that aren't trivially
+ * implementable using an existing mpfr or mpc function.
+ */
+int test_rred(mpfr_t ret, const mpfr_t x, int *quadrant)
+{
+    mpfr_t halfpi;
+    long quo;
+    int status;
+
+    /*
+     * In the worst case of range reduction, we get an input of size
+     * around 2^1024, and must find its remainder mod pi, which means
+     * we need 1024 bits of pi at least. Plus, the remainder might
+     * happen to come out very very small if we're unlucky. How
+     * unlucky can we be? Well, conveniently, I once went through and
+     * actually worked that out using Paxson's modular minimisation
+     * algorithm, and it turns out that the smallest exponent you can
+     * get out of a nontrivial[1] double precision range reduction is
+     * 0x3c2, i.e. of the order of 2^-61. So we need 1024 bits of pi
+     * to get us down to the units digit, another 61 or so bits (say
+     * 64) to get down to the highest set bit of the output, and then
+     * some bits to make the actual mantissa big enough.
+     *
+     *   [1] of course the output of range reduction can have an
+     *   arbitrarily small exponent in the trivial case, where the
+     *   input is so small that it's the identity function. That
+     *   doesn't count.
+     */
+    mpfr_init2(halfpi, MPFR_PREC + 1024 + 64);
+    mpfr_const_pi(halfpi, GMP_RNDN);
+    mpfr_div_ui(halfpi, halfpi, 2, GMP_RNDN);
+
+    status = mpfr_remquo(ret, &quo, x, halfpi, GMP_RNDN);
+    *quadrant = quo & 3;
+
+    mpfr_clear(halfpi);
+
+    return status;
+}
+int test_lgamma(mpfr_t ret, const mpfr_t x, mpfr_rnd_t rnd)
+{
+    /*
+     * mpfr_lgamma takes an extra int * parameter to hold the output
+     * sign. We don't bother testing that, so this wrapper throws away
+     * the sign and hence fits into the same function prototype as all
+     * the other real->real mpfr functions.
+     *
+     * There is also mpfr_lngamma which has no sign output and hence
+     * has the right prototype already, but unfortunately it returns
+     * NaN in cases where gamma(x) < 0, so it's no use to us.
+     */
+    int sign;
+    return mpfr_lgamma(ret, &sign, x, rnd);
+}
+int test_cpow(mpc_t ret, const mpc_t x, const mpc_t y, mpc_rnd_t rnd)
+{
+    /*
+     * For complex pow, we must bump up the precision by a huge amount
+     * if we want it to get the really difficult cases right. (Not
+     * that we expect the library under test to be getting those cases
+     * right itself, but we'd at least like the test suite to report
+     * them as wrong for the _right reason_.)
+     *
+     * This works around a bug in mpc_pow(), fixed by r1455 in the MPC
+     * svn repository (2014-10-14) and expected to be in any MPC
+     * release after 1.0.2 (which was the latest release already made
+     * at the time of the fix). So as and when we update to an MPC
+     * with the fix in it, we could remove this workaround.
+     *
+     * For the reasons for choosing this amount of extra precision,
+     * see analysis in complex/cpownotes.txt for the rationale for the
+     * amount.
+     */
+    mpc_t xbig, ybig, retbig;
+    int status;
+
+    mpc_init2(xbig, 1034 + 53 + 60 + MPFR_PREC);
+    mpc_init2(ybig, 1034 + 53 + 60 + MPFR_PREC);
+    mpc_init2(retbig, 1034 + 53 + 60 + MPFR_PREC);
+
+    mpc_set(xbig, x, MPC_RNDNN);
+    mpc_set(ybig, y, MPC_RNDNN);
+    status = mpc_pow(retbig, xbig, ybig, rnd);
+    mpc_set(ret, retbig, rnd);
+
+    mpc_clear(xbig);
+    mpc_clear(ybig);
+    mpc_clear(retbig);
+
+    return status;
+}
+
+/*
+ * Identify 'hard' values (NaN, Inf, nonzero denormal) for deciding
+ * whether microlib will decline to run a test.
+ */
+#define is_shard(in) ( \
+    (((in)[0] & 0x7F800000) == 0x7F800000 || \
+     (((in)[0] & 0x7F800000) == 0 && ((in)[0]&0x7FFFFFFF) != 0)))
+
+#define is_dhard(in) ( \
+    (((in)[0] & 0x7FF00000) == 0x7FF00000 || \
+     (((in)[0] & 0x7FF00000) == 0 && (((in)[0] & 0xFFFFF) | (in)[1]) != 0)))
+
+/*
+ * Identify integers.
+ */
+int is_dinteger(uint32 *in)
+{
+    uint32 out[3];
+    if ((0x7FF00000 & ~in[0]) == 0)
+        return 0;                      /* not finite, hence not integer */
+    test_ceil(in, out);
+    return in[0] == out[0] && in[1] == out[1];
+}
+int is_sinteger(uint32 *in)
+{
+    uint32 out[3];
+    if ((0x7F800000 & ~in[0]) == 0)
+        return 0;                      /* not finite, hence not integer */
+    test_ceilf(in, out);
+    return in[0] == out[0];
+}
+
+/*
+ * Identify signalling NaNs.
+ */
+int is_dsnan(const uint32 *in)
+{
+    if ((in[0] & 0x7FF00000) != 0x7FF00000)
+        return 0;                      /* not the inf/nan exponent */
+    if ((in[0] << 12) == 0 && in[1] == 0)
+        return 0;                      /* inf */
+    if (in[0] & 0x00080000)
+        return 0;                      /* qnan */
+    return 1;
+}
+int is_ssnan(const uint32 *in)
+{
+    if ((in[0] & 0x7F800000) != 0x7F800000)
+        return 0;                      /* not the inf/nan exponent */
+    if ((in[0] << 9) == 0)
+        return 0;                      /* inf */
+    if (in[0] & 0x00400000)
+        return 0;                      /* qnan */
+    return 1;
+}
+int is_snan(const uint32 *in, int size)
+{
+    return size == 2 ? is_dsnan(in) : is_ssnan(in);
+}
+
+/*
+ * Wrapper functions called to fix up unusual results after the main
+ * test function has run.
+ */
+void universal_wrapper(wrapperctx *ctx)
+{
+    /*
+     * Any SNaN input gives rise to a QNaN output.
+     */
+    int op;
+    for (op = 0; op < wrapper_get_nops(ctx); op++) {
+        int size = wrapper_get_size(ctx, op);
+
+        if (!wrapper_is_complex(ctx, op) &&
+            is_snan(wrapper_get_ieee(ctx, op), size)) {
+            wrapper_set_nan(ctx);
+        }
+    }
+}
+
+Testable functions[] = {
+    /*
+     * Trig functions: sin, cos, tan. We test the core function
+     * between -16 and +16: we assume that range reduction exists
+     * and will be used for larger arguments, and we'll test that
+     * separately. Also we only go down to 2^-27 in magnitude,
+     * because below that sin(x)=tan(x)=x and cos(x)=1 as far as
+     * double precision can tell, which is boring.
+     */
+    {"sin", (funcptr)mpfr_sin, args1, {NULL},
+        cases_uniform, 0x3e400000, 0x40300000},
+    {"sinf", (funcptr)mpfr_sin, args1f, {NULL},
+        cases_uniform_float, 0x39800000, 0x41800000},
+    {"cos", (funcptr)mpfr_cos, args1, {NULL},
+        cases_uniform, 0x3e400000, 0x40300000},
+    {"cosf", (funcptr)mpfr_cos, args1f, {NULL},
+        cases_uniform_float, 0x39800000, 0x41800000},
+    {"tan", (funcptr)mpfr_tan, args1, {NULL},
+        cases_uniform, 0x3e400000, 0x40300000},
+    {"tanf", (funcptr)mpfr_tan, args1f, {NULL},
+        cases_uniform_float, 0x39800000, 0x41800000},
+    {"sincosf_sinf", (funcptr)mpfr_sin, args1f, {NULL},
+        cases_uniform_float, 0x39800000, 0x41800000},
+    {"sincosf_cosf", (funcptr)mpfr_cos, args1f, {NULL},
+        cases_uniform_float, 0x39800000, 0x41800000},
+    /*
+     * Inverse trig: asin, acos. Between 1 and -1, of course. acos
+     * goes down to 2^-54, asin to 2^-27.
+     */
+    {"asin", (funcptr)mpfr_asin, args1, {NULL},
+        cases_uniform, 0x3e400000, 0x3fefffff},
+    {"asinf", (funcptr)mpfr_asin, args1f, {NULL},
+        cases_uniform_float, 0x39800000, 0x3f7fffff},
+    {"acos", (funcptr)mpfr_acos, args1, {NULL},
+        cases_uniform, 0x3c900000, 0x3fefffff},
+    {"acosf", (funcptr)mpfr_acos, args1f, {NULL},
+        cases_uniform_float, 0x33800000, 0x3f7fffff},
+    /*
+     * Inverse trig: atan. atan is stable (in double prec) with
+     * argument magnitude past 2^53, so we'll test up to there.
+     * atan(x) is boringly just x below 2^-27.
+     */
+    {"atan", (funcptr)mpfr_atan, args1, {NULL},
+        cases_uniform, 0x3e400000, 0x43400000},
+    {"atanf", (funcptr)mpfr_atan, args1f, {NULL},
+        cases_uniform_float, 0x39800000, 0x4b800000},
+    /*
+     * atan2. Interesting cases arise when the exponents of the
+     * arguments differ by at most about 50.
+     */
+    {"atan2", (funcptr)mpfr_atan2, args2, {NULL},
+        atan2_cases, 0},
+    {"atan2f", (funcptr)mpfr_atan2, args2f, {NULL},
+        atan2_cases_float, 0},
+    /*
+     * The exponentials: exp, sinh, cosh. They overflow at around
+     * 710. exp and sinh are boring below 2^-54, cosh below 2^-27.
+     */
+    {"exp", (funcptr)mpfr_exp, args1, {NULL},
+        cases_uniform, 0x3c900000, 0x40878000},
+    {"expf", (funcptr)mpfr_exp, args1f, {NULL},
+        cases_uniform_float, 0x33800000, 0x42dc0000},
+    {"sinh", (funcptr)mpfr_sinh, args1, {NULL},
+        cases_uniform, 0x3c900000, 0x40878000},
+    {"sinhf", (funcptr)mpfr_sinh, args1f, {NULL},
+        cases_uniform_float, 0x33800000, 0x42dc0000},
+    {"cosh", (funcptr)mpfr_cosh, args1, {NULL},
+        cases_uniform, 0x3e400000, 0x40878000},
+    {"coshf", (funcptr)mpfr_cosh, args1f, {NULL},
+        cases_uniform_float, 0x39800000, 0x42dc0000},
+    /*
+     * tanh is stable past around 20. It's boring below 2^-27.
+     */
+    {"tanh", (funcptr)mpfr_tanh, args1, {NULL},
+        cases_uniform, 0x3e400000, 0x40340000},
+    {"tanhf", (funcptr)mpfr_tanh, args1f, {NULL},
+        cases_uniform, 0x39800000, 0x41100000},
+    /*
+     * log must be tested only on positive numbers, but can cover
+     * the whole range of positive nonzero finite numbers. It never
+     * gets boring.
+     */
+    {"log", (funcptr)mpfr_log, args1, {NULL}, log_cases, 0},
+    {"logf", (funcptr)mpfr_log, args1f, {NULL}, log_cases_float, 0},
+    {"log10", (funcptr)mpfr_log10, args1, {NULL}, log_cases, 0},
+    {"log10f", (funcptr)mpfr_log10, args1f, {NULL}, log_cases_float, 0},
+    /*
+     * pow.
+     */
+    {"pow", (funcptr)mpfr_pow, args2, {NULL}, pow_cases, 0},
+    {"powf", (funcptr)mpfr_pow, args2f, {NULL}, pow_cases_float, 0},
+    /*
+     * Trig range reduction. We are able to test this for all
+     * finite values, but will only bother for things between 2^-3
+     * and 2^+52.
+     */
+    {"rred", (funcptr)test_rred, rred, {NULL}, rred_cases, 0},
+    {"rredf", (funcptr)test_rred, rredf, {NULL}, rred_cases_float, 0},
+    /*
+     * Square and cube root.
+     */
+    {"sqrt", (funcptr)mpfr_sqrt, args1, {NULL}, log_cases, 0},
+    {"sqrtf", (funcptr)mpfr_sqrt, args1f, {NULL}, log_cases_float, 0},
+    {"cbrt", (funcptr)mpfr_cbrt, args1, {NULL}, log_cases, 0},
+    {"cbrtf", (funcptr)mpfr_cbrt, args1f, {NULL}, log_cases_float, 0},
+    {"hypot", (funcptr)mpfr_hypot, args2, {NULL}, atan2_cases, 0},
+    {"hypotf", (funcptr)mpfr_hypot, args2f, {NULL}, atan2_cases_float, 0},
+    /*
+     * Seminumerical functions.
+     */
+    {"ceil", (funcptr)test_ceil, semi1, {NULL}, cases_semi1},
+    {"ceilf", (funcptr)test_ceilf, semi1f, {NULL}, cases_semi1_float},
+    {"floor", (funcptr)test_floor, semi1, {NULL}, cases_semi1},
+    {"floorf", (funcptr)test_floorf, semi1f, {NULL}, cases_semi1_float},
+    {"fmod", (funcptr)test_fmod, semi2, {NULL}, cases_semi2},
+    {"fmodf", (funcptr)test_fmodf, semi2f, {NULL}, cases_semi2_float},
+    {"ldexp", (funcptr)test_ldexp, t_ldexp, {NULL}, cases_ldexp},
+    {"ldexpf", (funcptr)test_ldexpf, t_ldexpf, {NULL}, cases_ldexp_float},
+    {"frexp", (funcptr)test_frexp, t_frexp, {NULL}, cases_semi1},
+    {"frexpf", (funcptr)test_frexpf, t_frexpf, {NULL}, cases_semi1_float},
+    {"modf", (funcptr)test_modf, t_modf, {NULL}, cases_semi1},
+    {"modff", (funcptr)test_modff, t_modff, {NULL}, cases_semi1_float},
+
+    /*
+     * Classification and more semi-numericals
+     */
+    {"copysign", (funcptr)test_copysign, semi2, {NULL}, cases_semi2},
+    {"copysignf", (funcptr)test_copysignf, semi2f, {NULL}, cases_semi2_float},
+    {"isfinite", (funcptr)test_isfinite, classify, {NULL}, cases_uniform, 0, 0x7fffffff},
+    {"isfinitef", (funcptr)test_isfinitef, classifyf, {NULL}, cases_uniform_float, 0, 0x7fffffff},
+    {"isinf", (funcptr)test_isinf, classify, {NULL}, cases_uniform, 0, 0x7fffffff},
+    {"isinff", (funcptr)test_isinff, classifyf, {NULL}, cases_uniform_float, 0, 0x7fffffff},
+    {"isnan", (funcptr)test_isnan, classify, {NULL}, cases_uniform, 0, 0x7fffffff},
+    {"isnanf", (funcptr)test_isnanf, classifyf, {NULL}, cases_uniform_float, 0, 0x7fffffff},
+    {"isnormal", (funcptr)test_isnormal, classify, {NULL}, cases_uniform, 0, 0x7fffffff},
+    {"isnormalf", (funcptr)test_isnormalf, classifyf, {NULL}, cases_uniform_float, 0, 0x7fffffff},
+    {"signbit", (funcptr)test_signbit, classify, {NULL}, cases_uniform, 0, 0x7fffffff},
+    {"signbitf", (funcptr)test_signbitf, classifyf, {NULL}, cases_uniform_float, 0, 0x7fffffff},
+    {"fpclassify", (funcptr)test_fpclassify, classify, {NULL}, cases_uniform, 0, 0x7fffffff},
+    {"fpclassifyf", (funcptr)test_fpclassifyf, classifyf, {NULL}, cases_uniform_float, 0, 0x7fffffff},
+    /*
+     * Comparisons
+     */
+    {"isgreater", (funcptr)test_isgreater, compare, {NULL}, cases_uniform, 0, 0x7fffffff},
+    {"isgreaterequal", (funcptr)test_isgreaterequal, compare, {NULL}, cases_uniform, 0, 0x7fffffff},
+    {"isless", (funcptr)test_isless, compare, {NULL}, cases_uniform, 0, 0x7fffffff},
+    {"islessequal", (funcptr)test_islessequal, compare, {NULL}, cases_uniform, 0, 0x7fffffff},
+    {"islessgreater", (funcptr)test_islessgreater, compare, {NULL}, cases_uniform, 0, 0x7fffffff},
+    {"isunordered", (funcptr)test_isunordered, compare, {NULL}, cases_uniform, 0, 0x7fffffff},
+
+    {"isgreaterf", (funcptr)test_isgreaterf, comparef, {NULL}, cases_uniform_float, 0, 0x7fffffff},
+    {"isgreaterequalf", (funcptr)test_isgreaterequalf, comparef, {NULL}, cases_uniform_float, 0, 0x7fffffff},
+    {"islessf", (funcptr)test_islessf, comparef, {NULL}, cases_uniform_float, 0, 0x7fffffff},
+    {"islessequalf", (funcptr)test_islessequalf, comparef, {NULL}, cases_uniform_float, 0, 0x7fffffff},
+    {"islessgreaterf", (funcptr)test_islessgreaterf, comparef, {NULL}, cases_uniform_float, 0, 0x7fffffff},
+    {"isunorderedf", (funcptr)test_isunorderedf, comparef, {NULL}, cases_uniform_float, 0, 0x7fffffff},
+
+    /*
+     * Inverse Hyperbolic functions
+     */
+    {"atanh", (funcptr)mpfr_atanh, args1, {NULL}, cases_uniform, 0x3e400000, 0x3fefffff},
+    {"asinh", (funcptr)mpfr_asinh, args1, {NULL}, cases_uniform, 0x3e400000, 0x3fefffff},
+    {"acosh", (funcptr)mpfr_acosh, args1, {NULL}, cases_uniform_positive, 0x3ff00000, 0x7fefffff},
+
+    {"atanhf", (funcptr)mpfr_atanh, args1f, {NULL}, cases_uniform_float, 0x32000000, 0x3f7fffff},
+    {"asinhf", (funcptr)mpfr_asinh, args1f, {NULL}, cases_uniform_float, 0x32000000, 0x3f7fffff},
+    {"acoshf", (funcptr)mpfr_acosh, args1f, {NULL}, cases_uniform_float_positive, 0x3f800000, 0x7f800000},
+
+    /*
+     * Everything else (sitting in a section down here at the bottom
+     * because historically they were not tested because we didn't
+     * have reference implementations for them)
+     */
+    {"csin", (funcptr)mpc_sin, args1c, {NULL}, complex_cases_uniform, 0x3f000000, 0x40300000},
+    {"csinf", (funcptr)mpc_sin, args1fc, {NULL}, complex_cases_uniform_float, 0x38000000, 0x41800000},
+    {"ccos", (funcptr)mpc_cos, args1c, {NULL}, complex_cases_uniform, 0x3f000000, 0x40300000},
+    {"ccosf", (funcptr)mpc_cos, args1fc, {NULL}, complex_cases_uniform_float, 0x38000000, 0x41800000},
+    {"ctan", (funcptr)mpc_tan, args1c, {NULL}, complex_cases_uniform, 0x3f000000, 0x40300000},
+    {"ctanf", (funcptr)mpc_tan, args1fc, {NULL}, complex_cases_uniform_float, 0x38000000, 0x41800000},
+
+    {"casin", (funcptr)mpc_asin, args1c, {NULL}, complex_cases_uniform, 0x3f000000, 0x40300000},
+    {"casinf", (funcptr)mpc_asin, args1fc, {NULL}, complex_cases_uniform_float, 0x38000000, 0x41800000},
+    {"cacos", (funcptr)mpc_acos, args1c, {NULL}, complex_cases_uniform, 0x3f000000, 0x40300000},
+    {"cacosf", (funcptr)mpc_acos, args1fc, {NULL}, complex_cases_uniform_float, 0x38000000, 0x41800000},
+    {"catan", (funcptr)mpc_atan, args1c, {NULL}, complex_cases_uniform, 0x3f000000, 0x40300000},
+    {"catanf", (funcptr)mpc_atan, args1fc, {NULL}, complex_cases_uniform_float, 0x38000000, 0x41800000},
+
+    {"csinh", (funcptr)mpc_sinh, args1c, {NULL}, complex_cases_uniform, 0x3f000000, 0x40300000},
+    {"csinhf", (funcptr)mpc_sinh, args1fc, {NULL}, complex_cases_uniform_float, 0x38000000, 0x41800000},
+    {"ccosh", (funcptr)mpc_cosh, args1c, {NULL}, complex_cases_uniform, 0x3f000000, 0x40300000},
+    {"ccoshf", (funcptr)mpc_cosh, args1fc, {NULL}, complex_cases_uniform_float, 0x38000000, 0x41800000},
+    {"ctanh", (funcptr)mpc_tanh, args1c, {NULL}, complex_cases_uniform, 0x3f000000, 0x40300000},
+    {"ctanhf", (funcptr)mpc_tanh, args1fc, {NULL}, complex_cases_uniform_float, 0x38000000, 0x41800000},
+
+    {"casinh", (funcptr)mpc_asinh, args1c, {NULL}, complex_cases_uniform, 0x3f000000, 0x40300000},
+    {"casinhf", (funcptr)mpc_asinh, args1fc, {NULL}, complex_cases_uniform_float, 0x38000000, 0x41800000},
+    {"cacosh", (funcptr)mpc_acosh, args1c, {NULL}, complex_cases_uniform, 0x3f000000, 0x40300000},
+    {"cacoshf", (funcptr)mpc_acosh, args1fc, {NULL}, complex_cases_uniform_float, 0x38000000, 0x41800000},
+    {"catanh", (funcptr)mpc_atanh, args1c, {NULL}, complex_cases_uniform, 0x3f000000, 0x40300000},
+    {"catanhf", (funcptr)mpc_atanh, args1fc, {NULL}, complex_cases_uniform_float, 0x38000000, 0x41800000},
+
+    {"cexp", (funcptr)mpc_exp, args1c, {NULL}, complex_cases_uniform, 0x3c900000, 0x40862000},
+    {"cpow", (funcptr)test_cpow, args2c, {NULL}, complex_pow_cases, 0x3fc00000, 0x40000000},
+    {"clog", (funcptr)mpc_log, args1c, {NULL}, complex_log_cases, 0, 0},
+    {"csqrt", (funcptr)mpc_sqrt, args1c, {NULL}, complex_log_cases, 0, 0},
+
+    {"cexpf", (funcptr)mpc_exp, args1fc, {NULL}, complex_cases_uniform_float, 0x24800000, 0x42b00000},
+    {"cpowf", (funcptr)test_cpow, args2fc, {NULL}, complex_pow_cases_float, 0x3e000000, 0x41000000},
+    {"clogf", (funcptr)mpc_log, args1fc, {NULL}, complex_log_cases_float, 0, 0},
+    {"csqrtf", (funcptr)mpc_sqrt, args1fc, {NULL}, complex_log_cases_float, 0, 0},
+
+    {"cdiv", (funcptr)mpc_div, args2c, {NULL}, complex_arithmetic_cases, 0, 0},
+    {"cmul", (funcptr)mpc_mul, args2c, {NULL}, complex_arithmetic_cases, 0, 0},
+    {"cadd", (funcptr)mpc_add, args2c, {NULL}, complex_arithmetic_cases, 0, 0},
+    {"csub", (funcptr)mpc_sub, args2c, {NULL}, complex_arithmetic_cases, 0, 0},
+
+    {"cdivf", (funcptr)mpc_div, args2fc, {NULL}, complex_arithmetic_cases_float, 0, 0},
+    {"cmulf", (funcptr)mpc_mul, args2fc, {NULL}, complex_arithmetic_cases_float, 0, 0},
+    {"caddf", (funcptr)mpc_add, args2fc, {NULL}, complex_arithmetic_cases_float, 0, 0},
+    {"csubf", (funcptr)mpc_sub, args2fc, {NULL}, complex_arithmetic_cases_float, 0, 0},
+
+    {"cabsf", (funcptr)mpc_abs, args1fcr, {NULL}, complex_arithmetic_cases_float, 0, 0},
+    {"cabs", (funcptr)mpc_abs, args1cr, {NULL}, complex_arithmetic_cases, 0, 0},
+    {"cargf", (funcptr)mpc_arg, args1fcr, {NULL}, complex_arithmetic_cases_float, 0, 0},
+    {"carg", (funcptr)mpc_arg, args1cr, {NULL}, complex_arithmetic_cases, 0, 0},
+    {"cimagf", (funcptr)mpc_imag, args1fcr, {NULL}, complex_arithmetic_cases_float, 0, 0},
+    {"cimag", (funcptr)mpc_imag, args1cr, {NULL}, complex_arithmetic_cases, 0, 0},
+    {"conjf", (funcptr)mpc_conj, args1fc, {NULL}, complex_arithmetic_cases_float, 0, 0},
+    {"conj", (funcptr)mpc_conj, args1c, {NULL}, complex_arithmetic_cases, 0, 0},
+    {"cprojf", (funcptr)mpc_proj, args1fc, {NULL}, complex_arithmetic_cases_float, 0, 0},
+    {"cproj", (funcptr)mpc_proj, args1c, {NULL}, complex_arithmetic_cases, 0, 0},
+    {"crealf", (funcptr)mpc_real, args1fcr, {NULL}, complex_arithmetic_cases_float, 0, 0},
+    {"creal", (funcptr)mpc_real, args1cr, {NULL}, complex_arithmetic_cases, 0, 0},
+    {"erfcf", (funcptr)mpfr_erfc, args1f, {NULL}, cases_biased_float, 0x1e800000, 0x41000000},
+    {"erfc", (funcptr)mpfr_erfc, args1, {NULL}, cases_biased, 0x3bd00000, 0x403c0000},
+    {"erff", (funcptr)mpfr_erf, args1f, {NULL}, cases_biased_float, 0x03800000, 0x40700000},
+    {"erf", (funcptr)mpfr_erf, args1, {NULL}, cases_biased, 0x00800000, 0x40200000},
+    {"exp2f", (funcptr)mpfr_exp2, args1f, {NULL}, cases_uniform_float, 0x33800000, 0x43c00000},
+    {"exp2", (funcptr)mpfr_exp2, args1, {NULL}, cases_uniform, 0x3ca00000, 0x40a00000},
+    {"expm1f", (funcptr)mpfr_expm1, args1f, {NULL}, cases_uniform_float, 0x33000000, 0x43800000},
+    {"expm1", (funcptr)mpfr_expm1, args1, {NULL}, cases_uniform, 0x3c900000, 0x409c0000},
+    {"fmaxf", (funcptr)mpfr_max, args2f, {NULL}, minmax_cases_float, 0, 0x7f7fffff},
+    {"fmax", (funcptr)mpfr_max, args2, {NULL}, minmax_cases, 0, 0x7fefffff},
+    {"fminf", (funcptr)mpfr_min, args2f, {NULL}, minmax_cases_float, 0, 0x7f7fffff},
+    {"fmin", (funcptr)mpfr_min, args2, {NULL}, minmax_cases, 0, 0x7fefffff},
+    {"lgammaf", (funcptr)test_lgamma, args1f, {NULL}, cases_uniform_float, 0x01800000, 0x7f800000},
+    {"lgamma", (funcptr)test_lgamma, args1, {NULL}, cases_uniform, 0x00100000, 0x7ff00000},
+    {"log1pf", (funcptr)mpfr_log1p, args1f, {NULL}, log1p_cases_float, 0, 0},
+    {"log1p", (funcptr)mpfr_log1p, args1, {NULL}, log1p_cases, 0, 0},
+    {"log2f", (funcptr)mpfr_log2, args1f, {NULL}, log_cases_float, 0, 0},
+    {"log2", (funcptr)mpfr_log2, args1, {NULL}, log_cases, 0, 0},
+    {"tgammaf", (funcptr)mpfr_gamma, args1f, {NULL}, cases_uniform_float, 0x2f800000, 0x43000000},
+    {"tgamma", (funcptr)mpfr_gamma, args1, {NULL}, cases_uniform, 0x3c000000, 0x40800000},
+};
+
+const int nfunctions = ( sizeof(functions)/sizeof(*functions) );
+
+#define random_sign ( random_upto(1) ? 0x80000000 : 0 )
+
+static int iszero(uint32 *x) {
+    return !((x[0] & 0x7FFFFFFF) || x[1]);
+}
+
+
+static void complex_log_cases(uint32 *out, uint32 param1,
+                              uint32 param2) {
+    cases_uniform(out,0x00100000,0x7fefffff);
+    cases_uniform(out+2,0x00100000,0x7fefffff);
+}
+
+
+static void complex_log_cases_float(uint32 *out, uint32 param1,
+                                    uint32 param2) {
+    cases_uniform_float(out,0x00800000,0x7f7fffff);
+    cases_uniform_float(out+2,0x00800000,0x7f7fffff);
+}
+
+static void complex_cases_biased(uint32 *out, uint32 lowbound,
+                                 uint32 highbound) {
+    cases_biased(out,lowbound,highbound);
+    cases_biased(out+2,lowbound,highbound);
+}
+
+static void complex_cases_biased_float(uint32 *out, uint32 lowbound,
+                                       uint32 highbound) {
+    cases_biased_float(out,lowbound,highbound);
+    cases_biased_float(out+2,lowbound,highbound);
+}
+
+static void complex_cases_uniform(uint32 *out, uint32 lowbound,
+                                 uint32 highbound) {
+    cases_uniform(out,lowbound,highbound);
+    cases_uniform(out+2,lowbound,highbound);
+}
+
+static void complex_cases_uniform_float(uint32 *out, uint32 lowbound,
+                                       uint32 highbound) {
+    cases_uniform_float(out,lowbound,highbound);
+    cases_uniform(out+2,lowbound,highbound);
+}
+
+static void complex_pow_cases(uint32 *out, uint32 lowbound,
+                              uint32 highbound) {
+    /*
+     * Generating non-overflowing cases for complex pow:
+     *
+     * Our base has both parts within the range [1/2,2], and hence
+     * its magnitude is within [1/2,2*sqrt(2)]. The magnitude of its
+     * logarithm in base 2 is therefore at most the magnitude of
+     * (log2(2*sqrt(2)) + i*pi/log(2)), or in other words
+     * hypot(3/2,pi/log(2)) = 4.77. So the magnitude of the exponent
+     * input must be at most our output magnitude limit (as a power
+     * of two) divided by that.
+     *
+     * I also set the output magnitude limit a bit low, because we
+     * don't guarantee (and neither does glibc) to prevent internal
+     * overflow in cases where the output _magnitude_ overflows but
+     * scaling it back down by cos and sin of the argument brings it
+     * back in range.
+     */
+    cases_uniform(out,0x3fe00000, 0x40000000);
+    cases_uniform(out+2,0x3fe00000, 0x40000000);
+    cases_uniform(out+4,0x3f800000, 0x40600000);
+    cases_uniform(out+6,0x3f800000, 0x40600000);
+}
+
+static void complex_pow_cases_float(uint32 *out, uint32 lowbound,
+                                    uint32 highbound) {
+    /*
+     * Reasoning as above, though of course the detailed numbers are
+     * all different.
+     */
+    cases_uniform_float(out,0x3f000000, 0x40000000);
+    cases_uniform_float(out+2,0x3f000000, 0x40000000);
+    cases_uniform_float(out+4,0x3d600000, 0x41900000);
+    cases_uniform_float(out+6,0x3d600000, 0x41900000);
+}
+
+static void complex_arithmetic_cases(uint32 *out, uint32 lowbound,
+                                     uint32 highbound) {
+    cases_uniform(out,0,0x7fefffff);
+    cases_uniform(out+2,0,0x7fefffff);
+    cases_uniform(out+4,0,0x7fefffff);
+    cases_uniform(out+6,0,0x7fefffff);
+}
+
+static void complex_arithmetic_cases_float(uint32 *out, uint32 lowbound,
+                                           uint32 highbound) {
+    cases_uniform_float(out,0,0x7f7fffff);
+    cases_uniform_float(out+2,0,0x7f7fffff);
+    cases_uniform_float(out+4,0,0x7f7fffff);
+    cases_uniform_float(out+6,0,0x7f7fffff);
+}
+
+/*
+ * Included from fplib test suite, in a compact self-contained
+ * form.
+ */
+
+void float32_case(uint32 *ret) {
+    int n, bits;
+    uint32 f;
+    static int premax, preptr;
+    static uint32 *specifics = NULL;
+
+    if (!ret) {
+        if (specifics)
+            free(specifics);
+        specifics = NULL;
+        premax = preptr = 0;
+        return;
+    }
+
+    if (!specifics) {
+        int exps[] = {
+            -127, -126, -125, -24, -4, -3, -2, -1, 0, 1, 2, 3, 4,
+                24, 29, 30, 31, 32, 61, 62, 63, 64, 126, 127, 128
+        };
+        int sign, eptr;
+        uint32 se, j;
+        /*
+         * We want a cross product of:
+         *  - each of two sign bits (2)
+         *  - each of the above (unbiased) exponents (25)
+         *  - the following list of fraction parts:
+         *    * zero (1)
+         *    * all bits (1)
+         *    * one-bit-set (23)
+         *    * one-bit-clear (23)
+         *    * one-bit-and-above (20: 3 are duplicates)
+         *    * one-bit-and-below (20: 3 are duplicates)
+         *    (total 88)
+         *  (total 4400)
+         */
+        specifics = malloc(4400 * sizeof(*specifics));
+        preptr = 0;
+        for (sign = 0; sign <= 1; sign++) {
+            for (eptr = 0; eptr < sizeof(exps)/sizeof(*exps); eptr++) {
+                se = (sign ? 0x80000000 : 0) | ((exps[eptr]+127) << 23);
+                /*
+                 * Zero.
+                 */
+                specifics[preptr++] = se | 0;
+                /*
+                 * All bits.
+                 */
+                specifics[preptr++] = se | 0x7FFFFF;
+                /*
+                 * One-bit-set.
+                 */
+                for (j = 1; j && j <= 0x400000; j <<= 1)
+                    specifics[preptr++] = se | j;
+                /*
+                 * One-bit-clear.
+                 */
+                for (j = 1; j && j <= 0x400000; j <<= 1)
+                    specifics[preptr++] = se | (0x7FFFFF ^ j);
+                /*
+                 * One-bit-and-everything-below.
+                 */
+                for (j = 2; j && j <= 0x100000; j <<= 1)
+                    specifics[preptr++] = se | (2*j-1);
+                /*
+                 * One-bit-and-everything-above.
+                 */
+                for (j = 4; j && j <= 0x200000; j <<= 1)
+                    specifics[preptr++] = se | (0x7FFFFF ^ (j-1));
+                /*
+                 * Done.
+                 */
+            }
+        }
+        assert(preptr == 4400);
+        premax = preptr;
+    }
+
+    /*
+     * Decide whether to return a pre or a random case.
+     */
+    n = random32() % (premax+1);
+    if (n < preptr) {
+        /*
+         * Return pre[n].
+         */
+        uint32 t;
+        t = specifics[n];
+        specifics[n] = specifics[preptr-1];
+        specifics[preptr-1] = t;        /* (not really needed) */
+        preptr--;
+        *ret = t;
+    } else {
+        /*
+         * Random case.
+         * Sign and exponent:
+         *  - FIXME
+         * Significand:
+         *  - with prob 1/5, a totally random bit pattern
+         *  - with prob 1/5, all 1s down to some point and then random
+         *  - with prob 1/5, all 1s up to some point and then random
+         *  - with prob 1/5, all 0s down to some point and then random
+         *  - with prob 1/5, all 0s up to some point and then random
+         */
+        n = random32() % 5;
+        f = random32();                /* some random bits */
+        bits = random32() % 22 + 1;    /* 1-22 */
+        switch (n) {
+          case 0:
+            break;                     /* leave f alone */
+          case 1:
+            f |= (1<<bits)-1;
+            break;
+          case 2:
+            f &= ~((1<<bits)-1);
+            break;
+          case 3:
+            f |= ~((1<<bits)-1);
+            break;
+          case 4:
+            f &= (1<<bits)-1;
+            break;
+        }
+        f &= 0x7FFFFF;
+        f |= (random32() & 0xFF800000);/* FIXME - do better */
+        *ret = f;
+    }
+}
+static void float64_case(uint32 *ret) {
+    int n, bits;
+    uint32 f, g;
+    static int premax, preptr;
+    static uint32 (*specifics)[2] = NULL;
+
+    if (!ret) {
+        if (specifics)
+            free(specifics);
+        specifics = NULL;
+        premax = preptr = 0;
+        return;
+    }
+
+    if (!specifics) {
+        int exps[] = {
+            -1023, -1022, -1021, -129, -128, -127, -126, -53, -4, -3, -2,
+            -1, 0, 1, 2, 3, 4, 29, 30, 31, 32, 53, 61, 62, 63, 64, 127,
+            128, 129, 1022, 1023, 1024
+        };
+        int sign, eptr;
+        uint32 se, j;
+        /*
+         * We want a cross product of:
+         *  - each of two sign bits (2)
+         *  - each of the above (unbiased) exponents (32)
+         *  - the following list of fraction parts:
+         *    * zero (1)
+         *    * all bits (1)
+         *    * one-bit-set (52)
+         *    * one-bit-clear (52)
+         *    * one-bit-and-above (49: 3 are duplicates)
+         *    * one-bit-and-below (49: 3 are duplicates)
+         *    (total 204)
+         *  (total 13056)
+         */
+        specifics = malloc(13056 * sizeof(*specifics));
+        preptr = 0;
+        for (sign = 0; sign <= 1; sign++) {
+            for (eptr = 0; eptr < sizeof(exps)/sizeof(*exps); eptr++) {
+                se = (sign ? 0x80000000 : 0) | ((exps[eptr]+1023) << 20);
+                /*
+                 * Zero.
+                 */
+                specifics[preptr][0] = 0;
+                specifics[preptr][1] = 0;
+                specifics[preptr++][0] |= se;
+                /*
+                 * All bits.
+                 */
+                specifics[preptr][0] = 0xFFFFF;
+                specifics[preptr][1] = ~0;
+                specifics[preptr++][0] |= se;
+                /*
+                 * One-bit-set.
+                 */
+                for (j = 1; j && j <= 0x80000000; j <<= 1) {
+                    specifics[preptr][0] = 0;
+                    specifics[preptr][1] = j;
+                    specifics[preptr++][0] |= se;
+                    if (j & 0xFFFFF) {
+                        specifics[preptr][0] = j;
+                        specifics[preptr][1] = 0;
+                        specifics[preptr++][0] |= se;
+                    }
+                }
+                /*
+                 * One-bit-clear.
+                 */
+                for (j = 1; j && j <= 0x80000000; j <<= 1) {
+                    specifics[preptr][0] = 0xFFFFF;
+                    specifics[preptr][1] = ~j;
+                    specifics[preptr++][0] |= se;
+                    if (j & 0xFFFFF) {
+                        specifics[preptr][0] = 0xFFFFF ^ j;
+                        specifics[preptr][1] = ~0;
+                        specifics[preptr++][0] |= se;
+                    }
+                }
+                /*
+                 * One-bit-and-everything-below.
+                 */
+                for (j = 2; j && j <= 0x80000000; j <<= 1) {
+                    specifics[preptr][0] = 0;
+                    specifics[preptr][1] = 2*j-1;
+                    specifics[preptr++][0] |= se;
+                }
+                for (j = 1; j && j <= 0x20000; j <<= 1) {
+                    specifics[preptr][0] = 2*j-1;
+                    specifics[preptr][1] = ~0;
+                    specifics[preptr++][0] |= se;
+                }
+                /*
+                 * One-bit-and-everything-above.
+                 */
+                for (j = 4; j && j <= 0x80000000; j <<= 1) {
+                    specifics[preptr][0] = 0xFFFFF;
+                    specifics[preptr][1] = ~(j-1);
+                    specifics[preptr++][0] |= se;
+                }
+                for (j = 1; j && j <= 0x40000; j <<= 1) {
+                    specifics[preptr][0] = 0xFFFFF ^ (j-1);
+                    specifics[preptr][1] = 0;
+                    specifics[preptr++][0] |= se;
+                }
+                /*
+                 * Done.
+                 */
+            }
+        }
+        assert(preptr == 13056);
+        premax = preptr;
+    }
+
+    /*
+     * Decide whether to return a pre or a random case.
+     */
+    n = (uint32) random32() % (uint32) (premax+1);
+    if (n < preptr) {
+        /*
+         * Return pre[n].
+         */
+        uint32 t;
+        t = specifics[n][0];
+        specifics[n][0] = specifics[preptr-1][0];
+        specifics[preptr-1][0] = t;     /* (not really needed) */
+        ret[0] = t;
+        t = specifics[n][1];
+        specifics[n][1] = specifics[preptr-1][1];
+        specifics[preptr-1][1] = t;     /* (not really needed) */
+        ret[1] = t;
+        preptr--;
+    } else {
+        /*
+         * Random case.
+         * Sign and exponent:
+         *  - FIXME
+         * Significand:
+         *  - with prob 1/5, a totally random bit pattern
+         *  - with prob 1/5, all 1s down to some point and then random
+         *  - with prob 1/5, all 1s up to some point and then random
+         *  - with prob 1/5, all 0s down to some point and then random
+         *  - with prob 1/5, all 0s up to some point and then random
+         */
+        n = random32() % 5;
+        f = random32();                /* some random bits */
+        g = random32();                /* some random bits */
+        bits = random32() % 51 + 1;    /* 1-51 */
+        switch (n) {
+          case 0:
+            break;                     /* leave f alone */
+          case 1:
+            if (bits <= 32)
+                f |= (1<<bits)-1;
+            else {
+                bits -= 32;
+                g |= (1<<bits)-1;
+                f = ~0;
+            }
+            break;
+          case 2:
+            if (bits <= 32)
+                f &= ~((1<<bits)-1);
+            else {
+                bits -= 32;
+                g &= ~((1<<bits)-1);
+                f = 0;
+            }
+            break;
+          case 3:
+            if (bits <= 32)
+                g &= (1<<bits)-1;
+            else {
+                bits -= 32;
+                f &= (1<<bits)-1;
+                g = 0;
+            }
+            break;
+          case 4:
+            if (bits <= 32)
+                g |= ~((1<<bits)-1);
+            else {
+                bits -= 32;
+                f |= ~((1<<bits)-1);
+                g = ~0;
+            }
+            break;
+        }
+        g &= 0xFFFFF;
+        g |= (random32() & 0xFFF00000);/* FIXME - do better */
+        ret[0] = g;
+        ret[1] = f;
+    }
+}
+
+static void cases_biased(uint32 *out, uint32 lowbound,
+                          uint32 highbound) {
+    do {
+        out[0] = highbound - random_upto_biased(highbound-lowbound, 8);
+        out[1] = random_upto(0xFFFFFFFF);
+        out[0] |= random_sign;
+    } while (iszero(out));             /* rule out zero */
+}
+
+static void cases_biased_positive(uint32 *out, uint32 lowbound,
+                                  uint32 highbound) {
+    do {
+        out[0] = highbound - random_upto_biased(highbound-lowbound, 8);
+        out[1] = random_upto(0xFFFFFFFF);
+    } while (iszero(out));             /* rule out zero */
+}
+
+static void cases_biased_float(uint32 *out, uint32 lowbound,
+                               uint32 highbound) {
+    do {
+        out[0] = highbound - random_upto_biased(highbound-lowbound, 8);
+        out[1] = 0;
+        out[0] |= random_sign;
+    } while (iszero(out));             /* rule out zero */
+}
+
+static void cases_semi1(uint32 *out, uint32 param1,
+                        uint32 param2) {
+    float64_case(out);
+}
+
+static void cases_semi1_float(uint32 *out, uint32 param1,
+                              uint32 param2) {
+    float32_case(out);
+}
+
+static void cases_semi2(uint32 *out, uint32 param1,
+                        uint32 param2) {
+    float64_case(out);
+    float64_case(out+2);
+}
+
+static void cases_semi2_float(uint32 *out, uint32 param1,
+                        uint32 param2) {
+    float32_case(out);
+    float32_case(out+2);
+}
+
+static void cases_ldexp(uint32 *out, uint32 param1,
+                        uint32 param2) {
+    float64_case(out);
+    out[2] = random_upto(2048)-1024;
+}
+
+static void cases_ldexp_float(uint32 *out, uint32 param1,
+                              uint32 param2) {
+    float32_case(out);
+    out[2] = random_upto(256)-128;
+}
+
+static void cases_uniform(uint32 *out, uint32 lowbound,
+                          uint32 highbound) {
+    do {
+        out[0] = highbound - random_upto(highbound-lowbound);
+        out[1] = random_upto(0xFFFFFFFF);
+        out[0] |= random_sign;
+    } while (iszero(out));             /* rule out zero */
+}
+static void cases_uniform_float(uint32 *out, uint32 lowbound,
+                                uint32 highbound) {
+    do {
+        out[0] = highbound - random_upto(highbound-lowbound);
+        out[1] = 0;
+        out[0] |= random_sign;
+    } while (iszero(out));             /* rule out zero */
+}
+
+static void cases_uniform_positive(uint32 *out, uint32 lowbound,
+                                   uint32 highbound) {
+    do {
+        out[0] = highbound - random_upto(highbound-lowbound);
+        out[1] = random_upto(0xFFFFFFFF);
+    } while (iszero(out));             /* rule out zero */
+}
+static void cases_uniform_float_positive(uint32 *out, uint32 lowbound,
+                                         uint32 highbound) {
+    do {
+        out[0] = highbound - random_upto(highbound-lowbound);
+        out[1] = 0;
+    } while (iszero(out));             /* rule out zero */
+}
+
+
+static void log_cases(uint32 *out, uint32 param1,
+                      uint32 param2) {
+    do {
+        out[0] = random_upto(0x7FEFFFFF);
+        out[1] = random_upto(0xFFFFFFFF);
+    } while (iszero(out));             /* rule out zero */
+}
+
+static void log_cases_float(uint32 *out, uint32 param1,
+                            uint32 param2) {
+    do {
+        out[0] = random_upto(0x7F7FFFFF);
+        out[1] = 0;
+    } while (iszero(out));             /* rule out zero */
+}
+
+static void log1p_cases(uint32 *out, uint32 param1, uint32 param2)
+{
+    uint32 sign = random_sign;
+    if (sign == 0) {
+        cases_uniform_positive(out, 0x3c700000, 0x43400000);
+    } else {
+        cases_uniform_positive(out, 0x3c000000, 0x3ff00000);
+    }
+    out[0] |= sign;
+}
+
+static void log1p_cases_float(uint32 *out, uint32 param1, uint32 param2)
+{
+    uint32 sign = random_sign;
+    if (sign == 0) {
+        cases_uniform_float_positive(out, 0x32000000, 0x4c000000);
+    } else {
+        cases_uniform_float_positive(out, 0x30000000, 0x3f800000);
+    }
+    out[0] |= sign;
+}
+
+static void minmax_cases(uint32 *out, uint32 param1, uint32 param2)
+{
+    do {
+        out[0] = random_upto(0x7FEFFFFF);
+        out[1] = random_upto(0xFFFFFFFF);
+        out[0] |= random_sign;
+        out[2] = random_upto(0x7FEFFFFF);
+        out[3] = random_upto(0xFFFFFFFF);
+        out[2] |= random_sign;
+    } while (iszero(out));             /* rule out zero */
+}
+
+static void minmax_cases_float(uint32 *out, uint32 param1, uint32 param2)
+{
+    do {
+        out[0] = random_upto(0x7F7FFFFF);
+        out[1] = 0;
+        out[0] |= random_sign;
+        out[2] = random_upto(0x7F7FFFFF);
+        out[3] = 0;
+        out[2] |= random_sign;
+    } while (iszero(out));             /* rule out zero */
+}
+
+static void rred_cases(uint32 *out, uint32 param1,
+                       uint32 param2) {
+    do {
+        out[0] = ((0x3fc00000 + random_upto(0x036fffff)) |
+                  (random_upto(1) << 31));
+        out[1] = random_upto(0xFFFFFFFF);
+    } while (iszero(out));             /* rule out zero */
+}
+
+static void rred_cases_float(uint32 *out, uint32 param1,
+                             uint32 param2) {
+    do {
+        out[0] = ((0x3e000000 + random_upto(0x0cffffff)) |
+                  (random_upto(1) << 31));
+        out[1] = 0;                    /* for iszero */
+    } while (iszero(out));             /* rule out zero */
+}
+
+static void atan2_cases(uint32 *out, uint32 param1,
+                        uint32 param2) {
+    do {
+        int expdiff = random_upto(101)-51;
+        int swap;
+        if (expdiff < 0) {
+            expdiff = -expdiff;
+            swap = 2;
+        } else
+            swap = 0;
+        out[swap ^ 0] = random_upto(0x7FEFFFFF-((expdiff+1)<<20));
+        out[swap ^ 2] = random_upto(((expdiff+1)<<20)-1) + out[swap ^ 0];
+        out[1] = random_upto(0xFFFFFFFF);
+        out[3] = random_upto(0xFFFFFFFF);
+        out[0] |= random_sign;
+        out[2] |= random_sign;
+    } while (iszero(out) || iszero(out+2));/* rule out zero */
+}
+
+static void atan2_cases_float(uint32 *out, uint32 param1,
+                              uint32 param2) {
+    do {
+        int expdiff = random_upto(44)-22;
+        int swap;
+        if (expdiff < 0) {
+            expdiff = -expdiff;
+            swap = 2;
+        } else
+            swap = 0;
+        out[swap ^ 0] = random_upto(0x7F7FFFFF-((expdiff+1)<<23));
+        out[swap ^ 2] = random_upto(((expdiff+1)<<23)-1) + out[swap ^ 0];
+        out[0] |= random_sign;
+        out[2] |= random_sign;
+        out[1] = out[3] = 0;           /* for iszero */
+    } while (iszero(out) || iszero(out+2));/* rule out zero */
+}
+
+static void pow_cases(uint32 *out, uint32 param1,
+                      uint32 param2) {
+    /*
+     * Pick an exponent e (-0x33 to +0x7FE) for x, and here's the
+     * range of numbers we can use as y:
+     *
+     * For e < 0x3FE, the range is [-0x400/(0x3FE-e),+0x432/(0x3FE-e)]
+     * For e > 0x3FF, the range is [-0x432/(e-0x3FF),+0x400/(e-0x3FF)]
+     *
+     * For e == 0x3FE or e == 0x3FF, the range gets infinite at one
+     * end or the other, so we have to be cleverer: pick a number n
+     * of useful bits in the mantissa (1 thru 52, so 1 must imply
+     * 0x3ff00000.00000001 whereas 52 is anything at least as big
+     * as 0x3ff80000.00000000; for e == 0x3fe, 1 necessarily means
+     * 0x3fefffff.ffffffff and 52 is anything at most as big as
+     * 0x3fe80000.00000000). Then, as it happens, a sensible
+     * maximum power is 2^(63-n) for e == 0x3fe, and 2^(62-n) for
+     * e == 0x3ff.
+     *
+     * We inevitably get some overflows in approximating the log
+     * curves by these nasty step functions, but that's all right -
+     * we do want _some_ overflows to be tested.
+     *
+     * Having got that, then, it's just a matter of inventing a
+     * probability distribution for all of this.
+     */
+    int e, n;
+    uint32 dmin, dmax;
+    const uint32 pmin = 0x3e100000;
+
+    /*
+     * Generate exponents in a slightly biased fashion.
+     */
+    e = (random_upto(1) ?              /* is exponent small or big? */
+         0x3FE - random_upto_biased(0x431,2) :   /* small */
+         0x3FF + random_upto_biased(0x3FF,2));   /* big */
+
+    /*
+     * Now split into cases.
+     */
+    if (e < 0x3FE || e > 0x3FF) {
+        uint32 imin, imax;
+        if (e < 0x3FE)
+            imin = 0x40000 / (0x3FE - e), imax = 0x43200 / (0x3FE - e);
+        else
+            imin = 0x43200 / (e - 0x3FF), imax = 0x40000 / (e - 0x3FF);
+        /* Power range runs from -imin to imax. Now convert to doubles */
+        dmin = doubletop(imin, -8);
+        dmax = doubletop(imax, -8);
+        /* Compute the number of mantissa bits. */
+        n = (e > 0 ? 53 : 52+e);
+    } else {
+        /* Critical exponents. Generate a top bit index. */
+        n = 52 - random_upto_biased(51, 4);
+        if (e == 0x3FE)
+            dmax = 63 - n;
+        else
+            dmax = 62 - n;
+        dmax = (dmax << 20) + 0x3FF00000;
+        dmin = dmax;
+    }
+    /* Generate a mantissa. */
+    if (n <= 32) {
+        out[0] = 0;
+        out[1] = random_upto((1 << (n-1)) - 1) + (1 << (n-1));
+    } else if (n == 33) {
+        out[0] = 1;
+        out[1] = random_upto(0xFFFFFFFF);
+    } else if (n > 33) {
+        out[0] = random_upto((1 << (n-33)) - 1) + (1 << (n-33));
+        out[1] = random_upto(0xFFFFFFFF);
+    }
+    /* Negate the mantissa if e == 0x3FE. */
+    if (e == 0x3FE) {
+        out[1] = -out[1];
+        out[0] = -out[0];
+        if (out[1]) out[0]--;
+    }
+    /* Put the exponent on. */
+    out[0] &= 0xFFFFF;
+    out[0] |= ((e > 0 ? e : 0) << 20);
+    /* Generate a power. Powers don't go below 2^-30. */
+    if (random_upto(1)) {
+        /* Positive power */
+        out[2] = dmax - random_upto_biased(dmax-pmin, 10);
+    } else {
+        /* Negative power */
+        out[2] = (dmin - random_upto_biased(dmin-pmin, 10)) | 0x80000000;
+    }
+    out[3] = random_upto(0xFFFFFFFF);
+}
+static void pow_cases_float(uint32 *out, uint32 param1,
+                            uint32 param2) {
+    /*
+     * Pick an exponent e (-0x16 to +0xFE) for x, and here's the
+     * range of numbers we can use as y:
+     *
+     * For e < 0x7E, the range is [-0x80/(0x7E-e),+0x95/(0x7E-e)]
+     * For e > 0x7F, the range is [-0x95/(e-0x7F),+0x80/(e-0x7F)]
+     *
+     * For e == 0x7E or e == 0x7F, the range gets infinite at one
+     * end or the other, so we have to be cleverer: pick a number n
+     * of useful bits in the mantissa (1 thru 23, so 1 must imply
+     * 0x3f800001 whereas 23 is anything at least as big as
+     * 0x3fc00000; for e == 0x7e, 1 necessarily means 0x3f7fffff
+     * and 23 is anything at most as big as 0x3f400000). Then, as
+     * it happens, a sensible maximum power is 2^(31-n) for e ==
+     * 0x7e, and 2^(30-n) for e == 0x7f.
+     *
+     * We inevitably get some overflows in approximating the log
+     * curves by these nasty step functions, but that's all right -
+     * we do want _some_ overflows to be tested.
+     *
+     * Having got that, then, it's just a matter of inventing a
+     * probability distribution for all of this.
+     */
+    int e, n;
+    uint32 dmin, dmax;
+    const uint32 pmin = 0x38000000;
+
+    /*
+     * Generate exponents in a slightly biased fashion.
+     */
+    e = (random_upto(1) ?              /* is exponent small or big? */
+         0x7E - random_upto_biased(0x94,2) :   /* small */
+         0x7F + random_upto_biased(0x7f,2));   /* big */
+
+    /*
+     * Now split into cases.
+     */
+    if (e < 0x7E || e > 0x7F) {
+        uint32 imin, imax;
+        if (e < 0x7E)
+            imin = 0x8000 / (0x7e - e), imax = 0x9500 / (0x7e - e);
+        else
+            imin = 0x9500 / (e - 0x7f), imax = 0x8000 / (e - 0x7f);
+        /* Power range runs from -imin to imax. Now convert to doubles */
+        dmin = floatval(imin, -8);
+        dmax = floatval(imax, -8);
+        /* Compute the number of mantissa bits. */
+        n = (e > 0 ? 24 : 23+e);
+    } else {
+        /* Critical exponents. Generate a top bit index. */
+        n = 23 - random_upto_biased(22, 4);
+        if (e == 0x7E)
+            dmax = 31 - n;
+        else
+            dmax = 30 - n;
+        dmax = (dmax << 23) + 0x3F800000;
+        dmin = dmax;
+    }
+    /* Generate a mantissa. */
+    out[0] = random_upto((1 << (n-1)) - 1) + (1 << (n-1));
+    out[1] = 0;
+    /* Negate the mantissa if e == 0x7E. */
+    if (e == 0x7E) {
+        out[0] = -out[0];
+    }
+    /* Put the exponent on. */
+    out[0] &= 0x7FFFFF;
+    out[0] |= ((e > 0 ? e : 0) << 23);
+    /* Generate a power. Powers don't go below 2^-15. */
+    if (random_upto(1)) {
+        /* Positive power */
+        out[2] = dmax - random_upto_biased(dmax-pmin, 10);
+    } else {
+        /* Negative power */
+        out[2] = (dmin - random_upto_biased(dmin-pmin, 10)) | 0x80000000;
+    }
+    out[3] = 0;
+}
+
+void vet_for_decline(Testable *fn, uint32 *args, uint32 *result, int got_errno_in) {
+    int declined = 0;
+
+    switch (fn->type) {
+      case args1:
+      case rred:
+      case semi1:
+      case t_frexp:
+      case t_modf:
+      case classify:
+      case t_ldexp:
+        declined