--- /dev/null
+*.o
+*~
+*.a
+*.dll*
+*.so*
+*.dylib*
+*.pc
--- /dev/null
+JuliaLang <julia-dev@googlegroups.com> <julia-dev@googlegroups.com>
+JuliaLang <julia-dev@googlegroups.com> <julia-math@googlegroups.com>
+
+Jeff Bezanson <jeff.bezanson@gmail.com> <jeff.bezanson@gmail.com>
+Jeff Bezanson <jeff.bezanson@gmail.com> <bezanson@beagle.darwinproject.mit.edu>
+Jeff Bezanson <jeff.bezanson@gmail.com> <bezanson@caspian.caspian.mit.edu>
+Jeff Bezanson <jeff.bezanson@gmail.com> <bezanson@evolution.local>
+Jeff Bezanson <jeff.bezanson@gmail.com> <bezanson@mathstation045.mit.edu>
+Jeff Bezanson <jeff.bezanson@gmail.com> <bezanson@mathstation049.mit.edu>
+Jeff Bezanson <jeff.bezanson@gmail.com> <bezanson@mathstation186.mit.edu>
+Jeff Bezanson <jeff.bezanson@gmail.com> <bezanson@post.harvard.edu>
+Jeff Bezanson <jeff.bezanson@gmail.com> <bezanson@scooby-doo.csail.mit.edu>
+Jeff Bezanson <jeff.bezanson@gmail.com> <bezanson@shaggy.csail.mit.edu>
+Jeff Bezanson <jeff.bezanson@gmail.com> <jeff@lagann.(none)>
+Jeff Bezanson <jeff.bezanson@gmail.com> <julia@beowulf1.csail.mit.edu>
+Jeff Bezanson <jeff.bezanson@gmail.com> <vcloud@julia02.domain.local>
+
+Stefan Karpinski <stefan@karpinski.org> <stefan@karpinski.org>
+Stefan Karpinski <stefan@karpinski.org> <stefan.karpinski@gmail.com>
+Stefan Karpinski <stefan@karpinski.org> <stefan.karpinski@post.harvard.edu>
+
+Viral B. Shah <viral@mayin.org> <viral@mayin.org>
+Viral B. Shah <viral@mayin.org> <viral@beowulf1.csail.mit.edu>
+Viral B. Shah <viral@mayin.org> <viral@neumann.cs.ucsb.edu>
+Viral B. Shah <viral@mayin.org> <viral@ubuntu-VirtualBox.(none)>
+
+George Xing <gxing@mit.edu> <gxing@mit.edu>
+George Xing <gxing@mit.edu> <noobiecubie@gmail.com>
+
+Stephan Boyer <boyers@mit.edu> <boyers@mit.edu>
+Stephan Boyer <boyers@mit.edu> <stephan@julialang.xvm.mit.edu>
+Stephan Boyer <boyers@mit.edu> <stephan@ubuntu.(none)>
+Stephan Boyer <boyers@mit.edu> <stephan@ubuntu.ubuntu-domain>
+
+Giuseppe Zingales <giuseppe.pet.zingales@gmail.com> <giuseppe.pet.zingales@gmail.com>
+Giuseppe Zingales <giuseppe.pet.zingales@gmail.com> <g3@ubuntu.ubuntu-domain>
+
+Jameson Nash <jameson@mit.edu> <jameson@mit.edu>
+Jameson Nash <jameson@mit.edu> <vtjnash@comcast.net>
+Jameson Nash <jameson@mit.edu> <vtjnash@gmail.com>
+
+Alan Edelman <mit.edelman@gmail.com> <mit.edelman@gmail.com>
+
+PlayMyCode <joe@playmycode.com> <joe@playmycode.com>
+PlayMyCode <joe@playmycode.com> <hello@playmycode.com>
+
+Corey M. Hoffstein <corey@hoffstein.com> <corey@hoffstein.com>
+Corey M. Hoffstein <corey@hoffstein.com> <corey@newfoundresearch.com>
+
+Stefan Kroboth <stefan.kroboth@gmail.com> <stefan.kroboth@gmail.com>
+
+Tim Holy <tim.holy@gmail.com> <tim.holy@gmail.com>
+Tim Holy <tim.holy@gmail.com> <holy@wustl.edu>
+
+Patrick O'Leary <patrick.oleary@gmail.com> <patrick.oleary@gmail.com>
+
+Ivan Mantova <horphus@gmail.com> <horphus@gmail.com>
+
+Keno Fischer <kfischer@college.harvard.edu> <kfischer@college.harvard.edu>
+Keno Fischer <kfischer@college.harvard.edu> <kfischer+github@college.harvard.edu>
+Keno Fischer <kfischer@college.harvard.edu> <kenof@stanford.edu>
--- /dev/null
+# We require a full (virtual) machine to load the kernel module for
+# binfmt support, which is needed to test other architectures besides
+# x86 using qemu user emulation. (This will not work in a container.)
+sudo: required
+dist: trusty
+language: c
+
+script:
+ - make $FLAGS
+ - make check $FLAGS $TEST_FLAGS
+ - make clean && git status --ignored --porcelain && test -z "$(git status --ignored --porcelain)"
+
+matrix:
+ include:
+ - compiler: clang
+ os: linux
+ addons:
+ apt:
+ sources:
+ - ubuntu-toolchain-r-test
+ - llvm-toolchain-precise-3.7
+ packages:
+ - clang-3.7
+ env: FLAGS="CC=clang-3.7 CXX=clang++-3.7"
+
+ - os: osx
+ env: FLAGS="CC=clang"
+
+ - os: linux
+ env: FLAGS="CC=gcc"
+
+ - os: linux
+ env: FLAGS="CC=gcc ARCH=i686" # implies -m32 -march=i686
+ addons:
+ apt:
+ packages:
+ - gcc-multilib
+
+ - os: linux
+ env: FLAGS="CC=aarch64-linux-gnu-gcc" TEST_FLAGS="LDFLAGS=-static"
+ addons:
+ apt:
+ packages:
+ - gcc-aarch64-linux-gnu
+ - libc6-dev-arm64-cross
+ - qemu-user-static
+ - binfmt-support
+
+ - os: linux
+ env: FLAGS="CC=arm-linux-gnueabihf-gcc" TEST_FLAGS="LDFLAGS=-static"
+ addons:
+ apt:
+ packages:
+ - gcc-arm-linux-gnueabihf
+ - libc6-dev-armhf-cross
+ - qemu-user-static
+ - binfmt-support
+
+ # This works, but only if qemu-user-static is >= v2.4. This is not the
+ # case on the default trusty images, so we add a PPA that has qemu 2.5
+ - os: linux
+ env: FLAGS="CC=powerpc64le-linux-gnu-gcc" TEST_FLAGS="LDFLAGS=-static"
+ addons:
+ apt:
+ sources:
+ - sourceline: "ppa:gns3/qemu"
+ packages:
+ - gcc-powerpc64le-linux-gnu
+ - libc6-dev-ppc64el-cross
+ - qemu-user-static
+ - binfmt-support
+
+ - os: linux
+ env: FLAGS="CC=mips-linux-gnu-gcc" TEST_FLAGS="LDFLAGS=-static"
+ addons:
+ apt:
+ sources:
+ - sourceline: "deb http://archive.ubuntu.com/ubuntu/ xenial main universe"
+ packages:
+ - gcc-mips-linux-gnu
+ - libc6-dev-mips-cross
+ - qemu-user-binfmt
+
+ - os: linux
+ env: FLAGS="CC=mipsel-linux-gnu-gcc" TEST_FLAGS="LDFLAGS=-static"
+ addons:
+ apt:
+ sources:
+ - sourceline: "deb http://archive.ubuntu.com/ubuntu/ xenial main universe"
+ packages:
+ - gcc-mipsel-linux-gnu
+ - libc6-dev-mipsel-cross
+ - qemu-user-binfmt
+
+ - os: linux
+ env: FLAGS="CC=mips64el-linux-gnuabi64-gcc" TEST_FLAGS="LDFLAGS=-static"
+ addons:
+ apt:
+ sources:
+ - sourceline: "deb http://archive.ubuntu.com/ubuntu/ xenial main universe"
+ packages:
+ - gcc-mips64el-linux-gnuabi64
+ - libc6-dev-mips64el-cross
+ - qemu-user-binfmt
+notifications:
+ email: false
--- /dev/null
+## OpenLibm
+
+OpenLibm contains code that is covered by various licenses.
+
+The OpenLibm code derives from the FreeBSD msun and OpenBSD libm
+implementations, which in turn derives from FDLIBM 5.3. As a result, it
+has a number of fixes and updates that have accumulated over the years
+in msun, and also optimized assembly versions of many functions. These
+improvements are provided under the BSD and ISC licenses. The msun
+library also includes work placed under the public domain, which is
+noted in the individual files. Further work on making a standalone
+OpenLibm library from msun, as part of the Julia project is covered
+under the MIT license. The test files, test-double.c and test-float.c
+are under the LGPL.
+
+## Parts copyrighted by the Julia project (MIT License)
+
+> Copyright (c) 2011-14 The Julia Project.
+> https://github.com/JuliaLang/openlibm/graphs/contributors
+>
+> Permission is hereby granted, free of charge, to any person obtaining
+> a copy of this software and associated documentation files (the
+> "Software"), to deal in the Software without restriction, including
+> without limitation the rights to use, copy, modify, merge, publish,
+> distribute, sublicense, and/or sell copies of the Software, and to
+> permit persons to whom the Software is furnished to do so, subject to
+> the following conditions:
+>
+> The above copyright notice and this permission notice shall be
+> included in all copies or substantial portions of the Software.
+>
+> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+> EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+> MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+> NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+> LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+> OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+> WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+## Parts copyrighted by Stephen L. Moshier (ISC License)
+
+> Copyright (c) 2008 Stephen L. Moshier <steve@moshier.net>
+>
+> Permission to use, copy, modify, and distribute this software for any
+> purpose with or without fee is hereby granted, provided that the above
+> copyright notice and this permission notice appear in all copies.
+>
+> THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+> WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+> MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+> ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+> WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+> ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+> OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+## FREEBSD MSUN (FreeBSD/2-clause BSD/Simplified BSD License)
+
+> Copyright 1992-2011 The FreeBSD Project. All rights reserved.
+>
+> Redistribution and use in source and binary forms, with or without
+> modification, are permitted provided that the following conditions are
+> met:
+>
+> 1. Redistributions of source code must retain the above copyright
+> notice, this list of conditions and the following disclaimer.
+>
+> 2. Redistributions in binary form must reproduce the above copyright
+> notice, this list of conditions and the following disclaimer in the
+> documentation and/or other materials provided with the distribution.
+> THIS SOFTWARE IS PROVIDED BY THE FREEBSD PROJECT ``AS IS'' AND ANY
+> EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+> IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+> PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FREEBSD PROJECT OR
+> CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+> EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+> PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+> PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+> LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+> NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+> SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+>
+> The views and conclusions contained in the software and documentation
+> are those of the authors and should not be interpreted as representing
+> official policies, either expressed or implied, of the FreeBSD
+> Project.
+
+## FDLIBM
+
+> Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+>
+> Developed at SunPro, a Sun Microsystems, Inc. business.
+> Permission to use, copy, modify, and distribute this
+> software is freely granted, provided that this notice
+> is preserved.
+
+## Tests
+
+> Copyright (C) 1997, 1999 Free Software Foundation, Inc.
+> This file is part of the GNU C Library.
+> Contributed by Andreas Jaeger <aj@suse.de>, 1997.
+>
+> The GNU C Library is free software; you can redistribute it and/or
+> modify it under the terms of the GNU Lesser General Public
+> License as published by the Free Software Foundation; either
+> version 2.1 of the License, or (at your option) any later version.
+>
+> The GNU C Library is distributed in the hope that it will be useful,
+> but WITHOUT ANY WARRANTY; without even the implied warranty of
+> MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+> Lesser General Public License for more details.
+>
+> You should have received a copy of the GNU Lesser General Public
+> License along with the GNU C Library; if not, write to the Free
+> Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+> 02111-1307 USA.
--- /dev/null
+# -*- mode: makefile-gmake -*-
+
+# Default build rule for any Makefile in this project: all
+default: all
+
+OS := $(shell uname)
+# Do not forget to bump SOMINOR when changing VERSION,
+# and SOMAJOR when breaking ABI in a backward-incompatible way
+VERSION = 0.6.0
+SOMAJOR = 2
+SOMINOR = 5
+DESTDIR =
+prefix = /usr/local
+bindir = $(prefix)/bin
+libdir = $(prefix)/lib
+includedir = $(prefix)/include
+
+ifeq ($(OS), FreeBSD)
+pkgconfigdir = $(prefix)/libdata/pkgconfig
+else
+pkgconfigdir = $(libdir)/pkgconfig
+endif
+
+USEGCC = 1
+USECLANG = 0
+
+ifneq (,$(findstring $(OS),Darwin FreeBSD OpenBSD))
+USEGCC = 0
+USECLANG = 1
+endif
+
+AR = $(TOOLPREFIX)ar
+
+ifeq ($(USECLANG),1)
+USEGCC = 0
+CC = clang
+CFLAGS_add += -fno-builtin -fno-strict-aliasing
+endif
+
+ifeq ($(USEGCC),1)
+CC = $(TOOLPREFIX)gcc
+CFLAGS_add += -fno-gnu89-inline -fno-builtin
+endif
+
+ARCH ?= $(shell $(CC) -dumpmachine | sed "s/\([^-]*\).*$$/\1/")
+
+ifeq ($(ARCH),mingw32)
+$(error "the mingw32 compiler you are using fails the openblas testsuite. please see the Julia README.windows.md document for a replacement")
+endif
+
+# OS-specific stuff
+ifeq ($(findstring arm,$(ARCH)),arm)
+override ARCH := arm
+MARCH ?= armv7-a
+CFLAGS_add += -mhard-float
+endif
+ifeq ($(findstring powerpc,$(ARCH)),powerpc)
+override ARCH := powerpc
+endif
+ifeq ($(findstring ppc,$(ARCH)),ppc)
+override ARCH := powerpc
+endif
+ifneq ($(filter $(ARCH),i386 i486 i586 i686 i387 i487 i587 i687),)
+override ARCH := i387
+MARCH ?= i686
+endif
+ifeq ($(ARCH),x86_64)
+override ARCH := amd64
+endif
+ifeq ($(findstring mips,$(ARCH)),mips)
+override ARCH := mips
+endif
+
+# If CFLAGS does not contain a -O optimization flag, default to -O3
+ifeq ($(findstring -O,$(CFLAGS)),)
+CFLAGS_add += -O3
+endif
+
+ifneq (,$(findstring MINGW,$(OS)))
+override OS=WINNT
+endif
+
+#keep these if statements separate
+ifeq ($(OS), WINNT)
+SHLIB_EXT = dll
+SONAME_FLAG = -soname
+CFLAGS_add += -nodefaultlibs
+shlibdir = $(bindir)
+else
+ifeq ($(OS), Darwin)
+SHLIB_EXT = dylib
+SONAME_FLAG = -install_name
+else
+SHLIB_EXT = so
+SONAME_FLAG = -soname
+endif
+CFLAGS_add += -fPIC
+shlibdir = $(libdir)
+endif
+
+# Add `-march` to our CFLAGS if it's defined
+ifneq ($(MARCH),)
+CFLAGS_arch += -march=$(MARCH)
+endif
+
+ifeq ($(ARCH),i387)
+CFLAGS_arch += -m32
+SFLAGS_arch += -m32
+LDFLAGS_arch += -m32
+endif
+
+ifeq ($(ARCH),amd64)
+CFLAGS_arch += -m64
+SFLAGS_arch += -m64
+LDFLAGS_arch += -m64
+endif
+
+# Add our "arch"-related FLAGS in. We separate arch-related flags out so that
+# we can conveniently get at them for targets that don't want the rest of
+# *FLAGS_add, such as the testing Makefile targets
+CFLAGS_add += $(CFLAGS_arch)
+SFLAGS_add += $(SFLAGS_arch)
+LDFLAGS_add += $(LDFLAGS_arch)
+
+CFLAGS_add += -std=c99 -Wall -I$(OPENLIBM_HOME) -I$(OPENLIBM_HOME)/include -I$(OPENLIBM_HOME)/$(ARCH) -I$(OPENLIBM_HOME)/src -DASSEMBLER -D__BSD_VISIBLE -Wno-implicit-function-declaration
+ifneq ($(filter $(ARCH),i387 amd64 powerpc),)
+CFLAGS_add += -I$(OPENLIBM_HOME)/ld80
+else
+ifneq ($(filter $(ARCH),aarch64),)
+CFLAGS_add += -I$(OPENLIBM_HOME)/ld128
+endif
+endif
+
+
+%.c.o: %.c
+ $(CC) $(CPPFLAGS) $(CFLAGS) $(CFLAGS_add) -c $< -o $@
+
+%.S.o: %.S
+ $(CC) $(CPPFLAGS) $(SFLAGS) $(SFLAGS_add) $(filter -m% -B% -I% -D%,$(CFLAGS_add)) -c $< -o $@
+
+
+# Makefile debugging trick:
+# call print-VARIABLE to see the runtime value of any variable
+print-%:
+ @echo '$*=$($*)'
--- /dev/null
+OPENLIBM_HOME=$(abspath .)
+include ./Make.inc
+
+SUBDIRS = src $(ARCH) bsdsrc
+# Add ld80 directory on x86 and x64
+ifneq ($(filter $(ARCH),i387 amd64),)
+SUBDIRS += ld80
+else
+ifneq ($(filter $(ARCH),aarch64),)
+SUBDIRS += ld128
+else
+endif
+endif
+
+define INC_template
+TEST=test
+override CUR_SRCS = $(1)_SRCS
+include $(1)/Make.files
+SRCS += $$(addprefix $(1)/,$$($(1)_SRCS))
+endef
+
+DIR=test
+
+$(foreach dir,$(SUBDIRS),$(eval $(call INC_template,$(dir))))
+
+DUPLICATE_NAMES = $(filter $(patsubst %.S,%,$($(ARCH)_SRCS)),$(patsubst %.c,%,$(src_SRCS)))
+DUPLICATE_SRCS = $(addsuffix .c,$(DUPLICATE_NAMES))
+
+OBJS = $(patsubst %.f,%.f.o,\
+ $(patsubst %.S,%.S.o,\
+ $(patsubst %.c,%.c.o,$(filter-out $(addprefix src/,$(DUPLICATE_SRCS)),$(SRCS)))))
+
+# If we're on windows, don't do versioned shared libraries. Also, generate an import library
+# for the DLL. If we're on OSX, put the version number before the .dylib. Otherwise,
+# put it after.
+ifeq ($(OS), WINNT)
+OLM_MAJOR_MINOR_SHLIB_EXT := $(SHLIB_EXT)
+LDFLAGS_add += -Wl,--out-implib,libopenlibm.$(OLM_MAJOR_MINOR_SHLIB_EXT).a
+else
+ifeq ($(OS), Darwin)
+OLM_MAJOR_MINOR_SHLIB_EXT := $(SOMAJOR).$(SOMINOR).$(SHLIB_EXT)
+OLM_MAJOR_SHLIB_EXT := $(SOMAJOR).$(SHLIB_EXT)
+else
+OLM_MAJOR_MINOR_SHLIB_EXT := $(SHLIB_EXT).$(SOMAJOR).$(SOMINOR)
+OLM_MAJOR_SHLIB_EXT := $(SHLIB_EXT).$(SOMAJOR)
+endif
+endif
+
+.PHONY: all check test clean distclean \
+ install install-static install-shared install-pkgconfig install-headers
+
+all: libopenlibm.a libopenlibm.$(OLM_MAJOR_MINOR_SHLIB_EXT)
+
+check test: test/test-double test/test-float
+ test/test-double
+ test/test-float
+
+libopenlibm.a: $(OBJS)
+ $(AR) -rcs libopenlibm.a $(OBJS)
+
+libopenlibm.$(OLM_MAJOR_MINOR_SHLIB_EXT): $(OBJS)
+ $(CC) -shared $(OBJS) $(LDFLAGS) $(LDFLAGS_add) -Wl,$(SONAME_FLAG),libopenlibm.$(OLM_MAJOR_SHLIB_EXT) -o $@
+ifneq ($(OS),WINNT)
+ ln -sf $@ libopenlibm.$(OLM_MAJOR_SHLIB_EXT)
+ ln -sf $@ libopenlibm.$(SHLIB_EXT)
+endif
+
+test/test-double: libopenlibm.$(OLM_MAJOR_MINOR_SHLIB_EXT)
+ $(MAKE) -C test test-double
+
+test/test-float: libopenlibm.$(OLM_MAJOR_MINOR_SHLIB_EXT)
+ $(MAKE) -C test test-float
+
+clean:
+ rm -f aarch64/*.o amd64/*.o arm/*.o bsdsrc/*.o i387/*.o ld80/*.o ld128/*.o src/*.o powerpc/*.o mips/*.o
+ rm -f libopenlibm.a libopenlibm.*$(SHLIB_EXT)*
+ $(MAKE) -C test clean
+
+openlibm.pc: openlibm.pc.in Make.inc Makefile
+ echo "prefix=${prefix}" > openlibm.pc
+ echo "version=${VERSION}" >> openlibm.pc
+ cat openlibm.pc.in >> openlibm.pc
+
+install-static: libopenlibm.a
+ mkdir -p $(DESTDIR)$(libdir)
+ cp -RpP -f libopenlibm.a $(DESTDIR)$(libdir)/
+
+install-shared: libopenlibm.$(OLM_MAJOR_MINOR_SHLIB_EXT)
+ mkdir -p $(DESTDIR)$(shlibdir)
+ cp -RpP -f libopenlibm.*$(SHLIB_EXT)* $(DESTDIR)$(shlibdir)/
+
+install-pkgconfig: openlibm.pc
+ mkdir -p $(DESTDIR)$(pkgconfigdir)
+ cp -RpP -f openlibm.pc $(DESTDIR)$(pkgconfigdir)/
+
+install-headers:
+ mkdir -p $(DESTDIR)$(includedir)/openlibm
+ cp -RpP -f include/*.h $(DESTDIR)$(includedir)/openlibm
+ cp -RpP -f src/*.h $(DESTDIR)$(includedir)/openlibm
+
+install: install-static install-shared install-pkgconfig install-headers
--- /dev/null
+# OpenLibm
+
+[](https://travis-ci.org/JuliaLang/openlibm)
+[](https://ci.appveyor.com/project/ararslan/openlibm/branch/master)
+
+[OpenLibm](http://www.openlibm.org) is an effort to have a high quality, portable, standalone
+C mathematical library ([`libm`](http://en.wikipedia.org/wiki/libm)).
+It can be used standalone in applications and programming language
+implementations.
+
+The project was born out of a need to have a good `libm` for the
+[Julia programming langage](http://www.julialang.org) that worked
+consistently across compilers and operating systems, and in 32-bit and
+64-bit environments.
+
+## Platform support
+
+OpenLibm builds on Linux, Mac OS X, Windows, FreeBSD, OpenBSD, and DragonFly BSD.
+It builds with both GCC and clang. Although largely tested and widely
+used on x86 architectures, OpenLibm also supports ARM and
+PowerPC.
+
+## Build instructions
+
+1. Use GNU Make to build OpenLibm. This is `make` on most systems, but `gmake` on BSDs.
+2. Use `make USEGCC=1` to build with GCC. This is the default on
+ Linux and Windows.
+3. Use `make USECLANG=1` to build with clang. This is the default on OS X, FreeBSD,
+ and OpenBSD.
+4. Architectures are auto-detected. Use `make ARCH=i386` to force a
+ build for i386. Other supported architectures are i486, i586, and
+ i686. GCC 4.8 is the minimum requirement for correct codegen on
+ older 32-bit architectures.
+
+## Acknowledgements
+
+PowerPC support for openlibm was graciously sponsored by IBM.
--- /dev/null
+$(CUR_SRCS) = fenv.c
--- /dev/null
+/*-
+ * Copyright (c) 2004 David Schultz <das@FreeBSD.ORG>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: src/lib/msun/arm/fenv.c,v 1.3 2011/10/16 05:37:56 das Exp $
+ */
+
+#define __fenv_static
+#include <openlibm_fenv.h>
+
+#ifdef __GNUC_GNU_INLINE__
+#error "This file must be compiled with C99 'inline' semantics"
+#endif
+
+/*
+ * Hopefully the system ID byte is immutable, so it's valid to use
+ * this as a default environment.
+ */
+const fenv_t __fe_dfl_env = 0;
+
+extern inline int feclearexcept(int __excepts);
+extern inline int fegetexceptflag(fexcept_t *__flagp, int __excepts);
+extern inline int fesetexceptflag(const fexcept_t *__flagp, int __excepts);
+extern inline int feraiseexcept(int __excepts);
+extern inline int fetestexcept(int __excepts);
+extern inline int fegetround(void);
+extern inline int fesetround(int __round);
+extern inline int fegetenv(fenv_t *__envp);
+extern inline int feholdexcept(fenv_t *__envp);
+extern inline int fesetenv(const fenv_t *__envp);
+extern inline int feupdateenv(const fenv_t *__envp);
--- /dev/null
+$(CUR_SRCS) = fenv.c e_remainder.S e_remainderf.S e_remainderl.S \
+ e_sqrt.S e_sqrtf.S e_sqrtl.S \
+ s_llrint.S s_llrintf.S s_llrintl.S \
+ s_logbl.S s_lrint.S s_lrintf.S s_lrintl.S \
+ s_remquo.S s_remquof.S s_remquol.S \
+ s_rintl.S s_scalbn.S s_scalbnf.S s_scalbnl.S
--- /dev/null
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * William Jolitz.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: @(#)DEFS.h 5.1 (Berkeley) 4/23/90
+ * $FreeBSD: src/sys/amd64/include/asm.h,v 1.18 2007/08/22 04:26:07 jkoshy Exp $
+ */
+
+#ifndef _BSD_ASM_H_
+#define _BSD_ASM_H_
+
+#ifdef __APPLE__
+#include "../i387/osx_asm.h"
+#define CNAME(x) EXT(x)
+#else
+#include "bsd_cdefs.h"
+
+#ifdef PIC
+#define PIC_PLT(x) x@PLT
+#define PIC_GOT(x) x@GOTPCREL(%rip)
+#else
+#define PIC_PLT(x) x
+#define PIC_GOT(x) x
+#endif
+
+/*
+ * CNAME and HIDENAME manage the relationship between symbol names in C
+ * and the equivalent assembly language names. CNAME is given a name as
+ * it would be used in a C program. It expands to the equivalent assembly
+ * language name. HIDENAME is given an assembly-language name, and expands
+ * to a possibly-modified form that will be invisible to C programs.
+ */
+#define CNAME(csym) csym
+#define HIDENAME(asmsym) .asmsym
+
+#define _START_ENTRY .p2align 4,0x90
+
+#if defined(__ELF__)
+#define _ENTRY(x) .text; _START_ENTRY; \
+ .globl CNAME(x); .type CNAME(x),@function; CNAME(x):
+#define END(x) .size x, . - x
+
+#elif defined(_WIN32)
+#ifndef _MSC_VER
+#define END(x) .end
+#define _START_ENTRY_WIN .text; _START_ENTRY
+#else
+#define END(x) end
+#define _START_ENTRY_WIN .code; _START_ENTRY
+#endif
+#define _ENTRY(x) _START_ENTRY_WIN; \
+ .globl CNAME(x); .section .drectve; .ascii " -export:", #x; \
+ .section .text; .def CNAME(x); .scl 2; .type 32; .endef; CNAME(x):
+#endif
+
+#ifdef PROF
+#define ALTENTRY(x) _ENTRY(x); \
+ pushq %rbp; movq %rsp,%rbp; \
+ call PIC_PLT(HIDENAME(mcount)); \
+ popq %rbp; \
+ jmp 9f
+#define ENTRY(x) _ENTRY(x); \
+ pushq %rbp; movq %rsp,%rbp; \
+ call PIC_PLT(HIDENAME(mcount)); \
+ popq %rbp; \
+ 9:
+#else
+#define ALTENTRY(x) _ENTRY(x)
+#define ENTRY(x) _ENTRY(x)
+#endif
+
+
+#define RCSID(x) .text; .asciz x
+
+#undef __FBSDID
+#if !defined(lint) && !defined(STRIP_FBSDID)
+#define __FBSDID(s) .ident s
+#else
+#define __FBSDID(s) /* nothing */
+#endif /* not lint and not STRIP_FBSDID */
+
+#endif
+#endif /* !_BSD_ASM_H_ */
--- /dev/null
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * William Jolitz.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: @(#)npx.h 5.3 (Berkeley) 1/18/91
+ * $FreeBSD: src/sys/x86/include/fpu.h,v 1.1 2012/03/16 20:24:30 tijl Exp $
+ */
+
+/*
+ * Floating Point Data Structures and Constants
+ * W. Jolitz 1/90
+ */
+
+#ifndef _BSD_FPU_H_
+#define _BSD_FPU_H_
+
+#include "types-compat.h"
+
+/* Environment information of floating point unit. */
+struct env87 {
+ int32_t en_cw; /* control word (16bits) */
+ int32_t en_sw; /* status word (16bits) */
+ int32_t en_tw; /* tag word (16bits) */
+ int32_t en_fip; /* fp instruction pointer */
+ uint16_t en_fcs; /* fp code segment selector */
+ uint16_t en_opcode; /* opcode last executed (11 bits) */
+ int32_t en_foo; /* fp operand offset */
+ int32_t en_fos; /* fp operand segment selector */
+};
+
+/* Contents of each x87 floating point accumulator. */
+struct fpacc87 {
+ uint8_t fp_bytes[10];
+};
+
+/* Floating point context. (i386 fnsave/frstor) */
+struct save87 {
+ struct env87 sv_env; /* floating point control/status */
+ struct fpacc87 sv_ac[8]; /* accumulator contents, 0-7 */
+ uint8_t sv_pad0[4]; /* saved status word (now unused) */
+ /*
+ * Bogus padding for emulators. Emulators should use their own
+ * struct and arrange to store into this struct (ending here)
+ * before it is inspected for ptracing or for core dumps. Some
+ * emulators overwrite the whole struct. We have no good way of
+ * knowing how much padding to leave. Leave just enough for the
+ * GPL emulator's i387_union (176 bytes total).
+ */
+ uint8_t sv_pad[64]; /* padding; used by emulators */
+};
+
+/* Contents of each SSE extended accumulator. */
+struct xmmacc {
+ uint8_t xmm_bytes[16];
+};
+
+/* Contents of the upper 16 bytes of each AVX extended accumulator. */
+struct ymmacc {
+ uint8_t ymm_bytes[16];
+};
+
+/* Rename structs below depending on machine architecture. */
+#ifdef __i386__
+#define __envxmm32 envxmm
+#else
+#define __envxmm32 envxmm32
+#define __envxmm64 envxmm
+#endif
+
+struct __envxmm32 {
+ uint16_t en_cw; /* control word (16bits) */
+ uint16_t en_sw; /* status word (16bits) */
+ uint16_t en_tw; /* tag word (16bits) */
+ uint16_t en_opcode; /* opcode last executed (11 bits) */
+ uint32_t en_fip; /* fp instruction pointer */
+ uint16_t en_fcs; /* fp code segment selector */
+ uint16_t en_pad0; /* padding */
+ uint32_t en_foo; /* fp operand offset */
+ uint16_t en_fos; /* fp operand segment selector */
+ uint16_t en_pad1; /* padding */
+ uint32_t en_mxcsr; /* SSE control/status register */
+ uint32_t en_mxcsr_mask; /* valid bits in mxcsr */
+};
+
+struct __envxmm64 {
+ uint16_t en_cw; /* control word (16bits) */
+ uint16_t en_sw; /* status word (16bits) */
+ uint8_t en_tw; /* tag word (8bits) */
+ uint8_t en_zero;
+ uint16_t en_opcode; /* opcode last executed (11 bits ) */
+ uint64_t en_rip; /* fp instruction pointer */
+ uint64_t en_rdp; /* fp operand pointer */
+ uint32_t en_mxcsr; /* SSE control/status register */
+ uint32_t en_mxcsr_mask; /* valid bits in mxcsr */
+};
+
+/* Floating point context. (i386 fxsave/fxrstor) */
+struct savexmm {
+ struct __envxmm32 sv_env;
+ struct {
+ struct fpacc87 fp_acc;
+ uint8_t fp_pad[6]; /* padding */
+ } sv_fp[8];
+ struct xmmacc sv_xmm[8];
+ uint8_t sv_pad[224];
+} __attribute__ ((aligned(16)));
+
+#ifdef __i386__
+union savefpu {
+ struct save87 sv_87;
+ struct savexmm sv_xmm;
+};
+#else
+/* Floating point context. (amd64 fxsave/fxrstor) */
+struct savefpu {
+ struct __envxmm64 sv_env;
+ struct {
+ struct fpacc87 fp_acc;
+ uint8_t fp_pad[6]; /* padding */
+ } sv_fp[8];
+ struct xmmacc sv_xmm[16];
+ uint8_t sv_pad[96];
+} __attribute__ ((aligned(16)));
+#endif
+
+struct xstate_hdr {
+ uint64_t xstate_bv;
+ uint8_t xstate_rsrv0[16];
+ uint8_t xstate_rsrv[40];
+};
+
+struct savexmm_xstate {
+ struct xstate_hdr sx_hd;
+ struct ymmacc sx_ymm[16];
+};
+
+struct savexmm_ymm {
+ struct __envxmm32 sv_env;
+ struct {
+ struct fpacc87 fp_acc;
+ int8_t fp_pad[6]; /* padding */
+ } sv_fp[8];
+ struct xmmacc sv_xmm[16];
+ uint8_t sv_pad[96];
+ struct savexmm_xstate sv_xstate;
+} __attribute__ ((aligned(16)));
+
+struct savefpu_xstate {
+ struct xstate_hdr sx_hd;
+ struct ymmacc sx_ymm[16];
+};
+
+struct savefpu_ymm {
+ struct __envxmm64 sv_env;
+ struct {
+ struct fpacc87 fp_acc;
+ int8_t fp_pad[6]; /* padding */
+ } sv_fp[8];
+ struct xmmacc sv_xmm[16];
+ uint8_t sv_pad[96];
+ struct savefpu_xstate sv_xstate;
+} __attribute__ ((aligned(64)));
+
+#undef __envxmm32
+#undef __envxmm64
+
+/*
+ * The hardware default control word for i387's and later coprocessors is
+ * 0x37F, giving:
+ *
+ * round to nearest
+ * 64-bit precision
+ * all exceptions masked.
+ *
+ * FreeBSD/i386 uses 53 bit precision for things like fadd/fsub/fsqrt etc
+ * because of the difference between memory and fpu register stack arguments.
+ * If its using an intermediate fpu register, it has 80/64 bits to work
+ * with. If it uses memory, it has 64/53 bits to work with. However,
+ * gcc is aware of this and goes to a fair bit of trouble to make the
+ * best use of it.
+ *
+ * This is mostly academic for AMD64, because the ABI prefers the use
+ * SSE2 based math. For FreeBSD/amd64, we go with the default settings.
+ */
+#define __INITIAL_FPUCW__ 0x037F
+#define __INITIAL_FPUCW_I386__ 0x127F
+#define __INITIAL_NPXCW__ __INITIAL_FPUCW_I386__
+#define __INITIAL_MXCSR__ 0x1F80
+#define __INITIAL_MXCSR_MASK__ 0xFFBF
+
+#endif /* !_BSD_FPU_H_ */
--- /dev/null
+/*-
+ * Copyright (c) 2003 Peter Wemm.
+ * Copyright (c) 1990 Andrew Moore, Talke Studio
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: @(#) ieeefp.h 1.0 (Berkeley) 9/23/93
+ * $FreeBSD: src/sys/amd64/include/ieeefp.h,v 1.14 2005/04/12 23:12:00 jhb Exp $
+ */
+
+/*
+ * IEEE floating point type and constant definitions.
+ */
+
+#ifndef _BSD_IEEEFP_H_
+#define _BSD_IEEEFP_H_
+
+/*
+ * FP rounding modes
+ */
+typedef enum {
+ FP_RN=0, /* round to nearest */
+ FP_RM, /* round down to minus infinity */
+ FP_RP, /* round up to plus infinity */
+ FP_RZ /* truncate */
+} fp_rnd_t;
+
+/*
+ * FP precision modes
+ */
+typedef enum {
+ FP_PS=0, /* 24 bit (single-precision) */
+ FP_PRS, /* reserved */
+ FP_PD, /* 53 bit (double-precision) */
+ FP_PE /* 64 bit (extended-precision) */
+} fp_prec_t;
+
+#define fp_except_t int
+
+/*
+ * FP exception masks
+ */
+#define FP_X_INV 0x01 /* invalid operation */
+#define FP_X_DNML 0x02 /* denormal */
+#define FP_X_DZ 0x04 /* zero divide */
+#define FP_X_OFL 0x08 /* overflow */
+#define FP_X_UFL 0x10 /* underflow */
+#define FP_X_IMP 0x20 /* (im)precision */
+#define FP_X_STK 0x40 /* stack fault */
+
+/*
+ * FP registers
+ */
+#define FP_MSKS_REG 0 /* exception masks */
+#define FP_PRC_REG 0 /* precision */
+#define FP_RND_REG 0 /* direction */
+#define FP_STKY_REG 1 /* sticky flags */
+
+/*
+ * FP register bit field masks
+ */
+#define FP_MSKS_FLD 0x3f /* exception masks field */
+#define FP_PRC_FLD 0x300 /* precision control field */
+#define FP_RND_FLD 0xc00 /* round control field */
+#define FP_STKY_FLD 0x3f /* sticky flags field */
+
+/*
+ * SSE mxcsr register bit field masks
+ */
+#define SSE_STKY_FLD 0x3f /* exception flags */
+#define SSE_DAZ_FLD 0x40 /* Denormals are zero */
+#define SSE_MSKS_FLD 0x1f80 /* exception masks field */
+#define SSE_RND_FLD 0x6000 /* rounding control */
+#define SSE_FZ_FLD 0x8000 /* flush to zero on underflow */
+
+/*
+ * FP register bit field offsets
+ */
+#define FP_MSKS_OFF 0 /* exception masks offset */
+#define FP_PRC_OFF 8 /* precision control offset */
+#define FP_RND_OFF 10 /* round control offset */
+#define FP_STKY_OFF 0 /* sticky flags offset */
+
+/*
+ * SSE mxcsr register bit field offsets
+ */
+#define SSE_STKY_OFF 0 /* exception flags offset */
+#define SSE_DAZ_OFF 6 /* DAZ exception mask offset */
+#define SSE_MSKS_OFF 7 /* other exception masks offset */
+#define SSE_RND_OFF 13 /* rounding control offset */
+#define SSE_FZ_OFF 15 /* flush to zero offset */
+
+#if (defined(__GNUCLIKE_ASM) && defined(__CC_SUPPORTS___INLINE__)) || defined(_WIN32) \
+ && !defined(__cplusplus)
+
+#define __fldenv(addr) __asm __volatile("fldenv %0" : : "m" (*(addr)))
+#define __fnstenv(addr) __asm __volatile("fnstenv %0" : "=m" (*(addr)))
+#define __fldcw(addr) __asm __volatile("fldcw %0" : : "m" (*(addr)))
+#define __fnstcw(addr) __asm __volatile("fnstcw %0" : "=m" (*(addr)))
+#define __fnstsw(addr) __asm __volatile("fnstsw %0" : "=m" (*(addr)))
+#define __ldmxcsr(addr) __asm __volatile("ldmxcsr %0" : : "m" (*(addr)))
+#define __stmxcsr(addr) __asm __volatile("stmxcsr %0" : "=m" (*(addr)))
+
+/*
+ * General notes about conflicting SSE vs FP status bits.
+ * This code assumes that software will not fiddle with the control
+ * bits of the SSE and x87 in such a way to get them out of sync and
+ * still expect this to work. Break this at your peril.
+ * Because I based this on the i386 port, the x87 state is used for
+ * the fpget*() functions, and is shadowed into the SSE state for
+ * the fpset*() functions. For dual source fpget*() functions, I
+ * merge the two together. I think.
+ */
+
+/* Set rounding control */
+static __inline__ fp_rnd_t
+__fpgetround(void)
+{
+ unsigned short _cw;
+
+ __fnstcw(&_cw);
+ return ((_cw & FP_RND_FLD) >> FP_RND_OFF);
+}
+
+static __inline__ fp_rnd_t
+__fpsetround(fp_rnd_t _m)
+{
+ unsigned short _cw;
+ unsigned int _mxcsr;
+ fp_rnd_t _p;
+
+ __fnstcw(&_cw);
+ _p = (_cw & FP_RND_FLD) >> FP_RND_OFF;
+ _cw &= ~FP_RND_FLD;
+ _cw |= (_m << FP_RND_OFF) & FP_RND_FLD;
+ __fldcw(&_cw);
+ __stmxcsr(&_mxcsr);
+ _mxcsr &= ~SSE_RND_FLD;
+ _mxcsr |= (_m << SSE_RND_OFF) & SSE_RND_FLD;
+ __ldmxcsr(&_mxcsr);
+ return (_p);
+}
+
+/*
+ * Set precision for fadd/fsub/fsqrt etc x87 instructions
+ * There is no equivalent SSE mode or control.
+ */
+static __inline__ fp_prec_t
+__fpgetprec(void)
+{
+ unsigned short _cw;
+
+ __fnstcw(&_cw);
+ return ((_cw & FP_PRC_FLD) >> FP_PRC_OFF);
+}
+
+static __inline__ fp_prec_t
+__fpsetprec(fp_rnd_t _m)
+{
+ unsigned short _cw;
+ fp_prec_t _p;
+
+ __fnstcw(&_cw);
+ _p = (_cw & FP_PRC_FLD) >> FP_PRC_OFF;
+ _cw &= ~FP_PRC_FLD;
+ _cw |= (_m << FP_PRC_OFF) & FP_PRC_FLD;
+ __fldcw(&_cw);
+ return (_p);
+}
+
+/*
+ * Look at the exception masks
+ * Note that x87 masks are inverse of the fp*() functions
+ * API. ie: mask = 1 means disable for x87 and SSE, but
+ * for the fp*() api, mask = 1 means enabled.
+ */
+static __inline__ fp_except_t
+__fpgetmask(void)
+{
+ unsigned short _cw;
+
+ __fnstcw(&_cw);
+ return ((~_cw) & FP_MSKS_FLD);
+}
+
+static __inline__ fp_except_t
+__fpsetmask(fp_except_t _m)
+{
+ unsigned short _cw;
+ unsigned int _mxcsr;
+ fp_except_t _p;
+
+ __fnstcw(&_cw);
+ _p = (~_cw) & FP_MSKS_FLD;
+ _cw &= ~FP_MSKS_FLD;
+ _cw |= (~_m) & FP_MSKS_FLD;
+ __fldcw(&_cw);
+ __stmxcsr(&_mxcsr);
+ /* XXX should we clear non-ieee SSE_DAZ_FLD and SSE_FZ_FLD ? */
+ _mxcsr &= ~SSE_MSKS_FLD;
+ _mxcsr |= ((~_m) << SSE_MSKS_OFF) & SSE_MSKS_FLD;
+ __ldmxcsr(&_mxcsr);
+ return (_p);
+}
+
+/* See which sticky exceptions are pending, and reset them */
+static __inline__ fp_except_t
+__fpgetsticky(void)
+{
+ unsigned short _sw;
+ unsigned int _mxcsr;
+ fp_except_t _ex;
+
+ __fnstsw(&_sw);
+ _ex = _sw & FP_STKY_FLD;
+ __stmxcsr(&_mxcsr);
+ _ex |= _mxcsr & SSE_STKY_FLD;
+ return (_ex);
+}
+
+#endif /* __GNUCLIKE_ASM && __CC_SUPPORTS___INLINE__ && !__cplusplus */
+
+#if !defined(__IEEEFP_NOINLINES__) && !defined(__cplusplus) \
+ && defined(__GNUCLIKE_ASM) && defined(__CC_SUPPORTS___INLINE__)
+
+#define fpgetround() __fpgetround()
+#define fpsetround(_m) __fpsetround(_m)
+#define fpgetprec() __fpgetprec()
+#define fpsetprec(_m) __fpsetprec(_m)
+#define fpgetmask() __fpgetmask()
+#define fpsetmask(_m) __fpsetmask(_m)
+#define fpgetsticky() __fpgetsticky()
+
+/* Suppress prototypes in the MI header. */
+#define _IEEEFP_INLINED_ 1
+
+#else /* !__IEEEFP_NOINLINES__ && !__cplusplus && __GNUCLIKE_ASM
+ && __CC_SUPPORTS___INLINE__ */
+
+/* Augment the userland declarations */
+__BEGIN_DECLS
+extern fp_prec_t fpgetprec(void);
+extern fp_prec_t fpsetprec(fp_prec_t);
+__END_DECLS
+
+#endif /* !__IEEEFP_NOINLINES__ && !__cplusplus && __GNUCLIKE_ASM
+ && __CC_SUPPORTS___INLINE__ */
+
+#endif /* !_BSD_IEEEFP_H_ */
--- /dev/null
+/*
+ * Based on the i387 version written by:
+ * J.T. Conklin (jtc@netbsd.org)
+ * Public domain.
+ */
+
+#include <amd64/bsd_asm.h>
+
+//RCSID("from: FreeBSD: src/lib/msun/i387/e_remainder.S,v 1.8 2005/02/04 14:08:32 das Exp")
+//__FBSDID("$FreeBSD: src/lib/msun/amd64/e_remainder.S,v 1.2 2011/01/07 16:13:12 kib Exp $")
+
+ENTRY(remainder)
+ movsd %xmm0,-8(%rsp)
+ movsd %xmm1,-16(%rsp)
+ fldl -16(%rsp)
+ fldl -8(%rsp)
+1: fprem1
+ fstsw %ax
+ testw $0x400,%ax
+ jne 1b
+ fstpl -8(%rsp)
+ movsd -8(%rsp),%xmm0
+ fstp %st
+ ret
+
+
+/* Enable stack protection */
+#if defined(__ELF__)
+.section .note.GNU-stack,"",%progbits
+#endif
--- /dev/null
+/*
+ * Based on the i387 version written by J.T. Conklin <jtc@netbsd.org>.
+ * Public domain.
+ */
+
+#include <amd64/bsd_asm.h>
+
+//RCSID("from: $NetBSD: e_remainderf.S,v 1.2 1995/05/08 23:49:47 jtc Exp $")
+//__FBSDID("$FreeBSD: src/lib/msun/amd64/e_remainderf.S,v 1.2 2011/01/07 16:13:12 kib Exp $")
+
+ENTRY(remainderf)
+ movss %xmm0,-4(%rsp)
+ movss %xmm1,-8(%rsp)
+ flds -8(%rsp)
+ flds -4(%rsp)
+1: fprem1
+ fstsw %ax
+ testw $0x400,%ax
+ jne 1b
+ fstps -4(%rsp)
+ movss -4(%rsp),%xmm0
+ fstp %st
+ ret
+
+
+/* Enable stack protection */
+#if defined(__ELF__)
+.section .note.GNU-stack,"",%progbits
+#endif
--- /dev/null
+/*
+ * Based on the i387 version written by:
+ * J.T. Conklin (jtc@netbsd.org)
+ * Public domain.
+ */
+
+#include <amd64/bsd_asm.h>
+
+//__FBSDID("$FreeBSD: src/lib/msun/amd64/e_remainderl.S,v 1.2 2011/01/07 16:13:12 kib Exp $")
+
+ENTRY(remainderl)
+#ifndef _WIN64
+ fldt 24(%rsp)
+ fldt 8(%rsp)
+#else
+ fldt (%r8)
+ fldt (%rdx)
+#endif
+1: fprem1
+ fstsw %ax
+ testw $0x400,%ax
+ jne 1b
+ fstp %st(1)
+#ifdef _WIN64
+ mov %rcx,%rax
+ movq $0x0,0x8(%rcx)
+ fstpt (%rcx)
+#endif
+ ret
+
+
+/* Enable stack protection */
+#if defined(__ELF__)
+.section .note.GNU-stack,"",%progbits
+#endif
--- /dev/null
+/*-
+ * Copyright (c) 2005 David Schultz <das@FreeBSD.ORG>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <amd64/bsd_asm.h>
+//__FBSDID("$FreeBSD: src/lib/msun/amd64/e_sqrt.S,v 1.4 2011/01/07 16:13:12 kib Exp $")
+
+ENTRY(sqrt)
+ sqrtsd %xmm0, %xmm0
+ ret
+END(sqrt)
+
+
+
+/* Enable stack protection */
+#if defined(__ELF__)
+.section .note.GNU-stack,"",%progbits
+#endif
--- /dev/null
+/*-
+ * Copyright (c) 2005 David Schultz <das@FreeBSD.ORG>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <amd64/bsd_asm.h>
+//__FBSDID("$FreeBSD: src/lib/msun/amd64/e_sqrtf.S,v 1.3 2011/01/07 16:13:12 kib Exp $")
+
+ENTRY(sqrtf)
+ sqrtss %xmm0, %xmm0
+ ret
+END(sqrtf)
+
+
+/* Enable stack protection */
+#if defined(__ELF__)
+.section .note.GNU-stack,"",%progbits
+#endif
--- /dev/null
+/*-
+ * Copyright (c) 2008 David Schultz <das@FreeBSD.ORG>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <amd64/bsd_asm.h>
+//__FBSDID("$FreeBSD: src/lib/msun/amd64/e_sqrtl.S,v 1.2 2011/01/07 16:13:12 kib Exp $")
+
+ENTRY(sqrtl)
+#ifndef _WIN64
+ fldt 8(%rsp)
+ fsqrt
+#else
+ fldt (%rdx)
+ fsqrt
+ mov %rcx,%rax
+ movq $0x0,0x8(%rcx)
+ fstpt (%rcx)
+#endif
+ ret
+
+/* Enable stack protection */
+#if defined(__ELF__)
+.section .note.GNU-stack,"",%progbits
+#endif
--- /dev/null
+/*-
+ * Copyright (c) 2004-2005 David Schultz <das@FreeBSD.ORG>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: src/lib/msun/amd64/fenv.c,v 1.8 2011/10/21 06:25:31 das Exp $
+ */
+
+#include "bsd_fpu.h"
+#include "math_private.h"
+
+#ifdef _WIN32
+#define __fenv_static OLM_DLLEXPORT
+#endif
+#include <openlibm_fenv.h>
+
+#ifdef __GNUC_GNU_INLINE__
+#error "This file must be compiled with C99 'inline' semantics"
+#endif
+
+const fenv_t __fe_dfl_env = {
+ { 0xffff0000 | __INITIAL_FPUCW__,
+ 0xffff0000,
+ 0xffffffff,
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff }
+ },
+ __INITIAL_MXCSR__
+};
+
+extern inline OLM_DLLEXPORT int feclearexcept(int __excepts);
+extern inline OLM_DLLEXPORT int fegetexceptflag(fexcept_t *__flagp, int __excepts);
+
+OLM_DLLEXPORT int
+fesetexceptflag(const fexcept_t *flagp, int excepts)
+{
+ fenv_t env;
+
+ __fnstenv(&env.__x87);
+ env.__x87.__status &= ~excepts;
+ env.__x87.__status |= *flagp & excepts;
+ __fldenv(env.__x87);
+
+ __stmxcsr(&env.__mxcsr);
+ env.__mxcsr &= ~excepts;
+ env.__mxcsr |= *flagp & excepts;
+ __ldmxcsr(env.__mxcsr);
+
+ return (0);
+}
+
+OLM_DLLEXPORT int
+feraiseexcept(int excepts)
+{
+ fexcept_t ex = excepts;
+
+ fesetexceptflag(&ex, excepts);
+ __fwait();
+ return (0);
+}
+
+extern inline OLM_DLLEXPORT int fetestexcept(int __excepts);
+extern inline OLM_DLLEXPORT int fegetround(void);
+extern inline OLM_DLLEXPORT int fesetround(int __round);
+
+OLM_DLLEXPORT int
+fegetenv(fenv_t *envp)
+{
+
+ __fnstenv(&envp->__x87);
+ __stmxcsr(&envp->__mxcsr);
+ /*
+ * fnstenv masks all exceptions, so we need to restore the
+ * control word to avoid this side effect.
+ */
+ __fldcw(envp->__x87.__control);
+ return (0);
+}
+
+OLM_DLLEXPORT int
+feholdexcept(fenv_t *envp)
+{
+ uint32_t mxcsr;
+
+ __stmxcsr(&mxcsr);
+ __fnstenv(&envp->__x87);
+ __fnclex();
+ envp->__mxcsr = mxcsr;
+ mxcsr &= ~FE_ALL_EXCEPT;
+ mxcsr |= FE_ALL_EXCEPT << _SSE_EMASK_SHIFT;
+ __ldmxcsr(mxcsr);
+ return (0);
+}
+
+extern inline OLM_DLLEXPORT int fesetenv(const fenv_t *__envp);
+
+OLM_DLLEXPORT int
+feupdateenv(const fenv_t *envp)
+{
+ uint32_t mxcsr;
+ uint16_t status;
+
+ __fnstsw(&status);
+ __stmxcsr(&mxcsr);
+ fesetenv(envp);
+ feraiseexcept((mxcsr | status) & FE_ALL_EXCEPT);
+ return (0);
+}
+
+int
+feenableexcept(int mask)
+{
+ uint32_t mxcsr, omask;
+ uint16_t control;
+
+ mask &= FE_ALL_EXCEPT;
+ __fnstcw(&control);
+ __stmxcsr(&mxcsr);
+ omask = ~(control | mxcsr >> _SSE_EMASK_SHIFT) & FE_ALL_EXCEPT;
+ control &= ~mask;
+ __fldcw(control);
+ mxcsr &= ~(mask << _SSE_EMASK_SHIFT);
+ __ldmxcsr(mxcsr);
+ return (omask);
+}
+
+int
+fedisableexcept(int mask)
+{
+ uint32_t mxcsr, omask;
+ uint16_t control;
+
+ mask &= FE_ALL_EXCEPT;
+ __fnstcw(&control);
+ __stmxcsr(&mxcsr);
+ omask = ~(control | mxcsr >> _SSE_EMASK_SHIFT) & FE_ALL_EXCEPT;
+ control |= mask;
+ __fldcw(control);
+ mxcsr |= mask << _SSE_EMASK_SHIFT;
+ __ldmxcsr(mxcsr);
+ return (omask);
+}
--- /dev/null
+#include <amd64/bsd_asm.h>
+//__FBSDID("$FreeBSD: src/lib/msun/amd64/s_llrint.S,v 1.3 2011/02/04 21:54:06 kib Exp $")
+
+ENTRY(llrint)
+ cvtsd2si %xmm0, %rax
+ ret
+END(llrint)
+
+/* Enable stack protection */
+#if defined(__ELF__)
+.section .note.GNU-stack,"",%progbits
+#endif
--- /dev/null
+#include <amd64/bsd_asm.h>
+//__FBSDID("$FreeBSD: src/lib/msun/amd64/s_llrintf.S,v 1.3 2011/02/04 21:54:06 kib Exp $")
+
+ENTRY(llrintf)
+ cvtss2si %xmm0, %rax
+ ret
+END(llrintf)
+
+/* Enable stack protection */
+#if defined(__ELF__)
+.section .note.GNU-stack,"",%progbits
+#endif
--- /dev/null
+/*-
+ * Copyright (c) 2005 David Schultz <das@FreeBSD.ORG>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <amd64/bsd_asm.h>
+//__FBSDID("$FreeBSD: src/lib/msun/amd64/s_llrintl.S,v 1.2 2011/01/07 16:13:12 kib Exp $");
+
+ENTRY(llrintl)
+#ifndef _WIN64
+ fldt 8(%rsp)
+#else
+ fldt (%rcx)
+#endif
+ subq $8,%rsp
+ fistpll (%rsp)
+ popq %rax
+ ret
+
+
+/* Enable stack protection */
+#if defined(__ELF__)
+.section .note.GNU-stack,"",%progbits
+#endif
--- /dev/null
+/*
+ * Written by:
+ * J.T. Conklin (jtc@netbsd.org)
+ * Public domain.
+ */
+
+#include <amd64/bsd_asm.h>
+//__FBSDID("$FreeBSD: src/lib/msun/amd64/s_logbl.S,v 1.4 2011/01/07 16:13:12 kib Exp $")
+
+ENTRY(logbl)
+#ifndef _WIN64
+ fldt 8(%rsp)
+#else
+ fldt (%rdx)
+#endif
+ fxtract
+ fstp %st
+#ifdef _WIN64
+ mov %rcx,%rax
+ movq $0x0,0x8(%rcx)
+ fstpt (%rcx)
+#endif
+ ret
+
+
+/* Enable stack protection */
+#if defined(__ELF__)
+.section .note.GNU-stack,"",%progbits
+#endif
--- /dev/null
+/*-
+ * Copyright (c) 2005 David Schultz <das@FreeBSD.ORG>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <amd64/bsd_asm.h>
+
+//__FBSDID("$FreeBSD: src/lib/msun/amd64/s_lrint.S,v 1.3 2011/01/07 16:13:12 kib Exp $")
+
+ENTRY(lrint)
+#ifndef _WIN64
+ cvtsd2si %xmm0, %rax
+#else
+ cvtsd2si %xmm0, %eax
+#endif
+ ret
+END(lrint)
+
+
+/* Enable stack protection */
+#if defined(__ELF__)
+.section .note.GNU-stack,"",%progbits
+#endif
--- /dev/null
+/*-
+ * Copyright (c) 2005 David Schultz <das@FreeBSD.ORG>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <amd64/bsd_asm.h>
+
+//__FBSDID("$FreeBSD: src/lib/msun/amd64/s_lrintf.S,v 1.3 2011/01/07 16:13:12 kib Exp $")
+
+ENTRY(lrintf)
+#ifndef _WIN64
+ cvtss2si %xmm0, %rax
+#else
+ cvtss2si %xmm0, %eax
+#endif
+ ret
+END(lrintf)
+
+
+/* Enable stack protection */
+#if defined(__ELF__)
+.section .note.GNU-stack,"",%progbits
+#endif
--- /dev/null
+/*-
+ * Copyright (c) 2008 David Schultz <das@FreeBSD.ORG>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <amd64/bsd_asm.h>
+//__FBSDID("$FreeBSD: src/lib/msun/amd64/s_lrintl.S,v 1.2 2011/01/07 16:13:12 kib Exp $");
+
+ENTRY(lrintl)
+#ifndef _WIN64
+ fldt 8(%rsp)
+#else
+ fldt (%rcx)
+#endif
+ subq $8,%rsp
+ fistpll (%rsp)
+ popq %rax
+ ret
+
+
+/* Enable stack protection */
+#if defined(__ELF__)
+.section .note.GNU-stack,"",%progbits
+#endif
--- /dev/null
+/*-
+ * Copyright (c) 2005 David Schultz <das@FreeBSD.ORG>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Based on public-domain remainder routine by J.T. Conklin <jtc@NetBSD.org>.
+ */
+
+#include <amd64/bsd_asm.h>
+//__FBSDID("$FreeBSD: src/lib/msun/amd64/s_remquo.S,v 1.3 2011/01/07 16:13:12 kib Exp $");
+
+ENTRY(remquo)
+ movsd %xmm0,-8(%rsp)
+ movsd %xmm1,-16(%rsp)
+ fldl -16(%rsp)
+ fldl -8(%rsp)
+1: fprem1
+ fstsw %ax
+ btw $10,%ax
+ jc 1b
+ fstp %st(1)
+/* Extract the three low-order bits of the quotient from C0,C3,C1. */
+ shrl $6,%eax
+ movl %eax,%ecx
+ andl $0x108,%eax
+ rorl $7,%eax
+ orl %eax,%ecx
+ roll $4,%eax
+ orl %ecx,%eax
+ andl $7,%eax
+/* Negate the quotient bits if x*y<0. Avoid using an unpredictable branch. */
+ movl -12(%rsp),%ecx
+ xorl -4(%rsp),%ecx
+ sarl $16,%ecx
+ sarl $16,%ecx
+ xorl %ecx,%eax
+ andl $1,%ecx
+ addl %ecx,%eax
+/* Store the quotient and return. */
+#ifndef _WIN64
+ movl %eax,(%rdi)
+#else
+ movl %eax,(%r8)
+#endif
+ fstpl -8(%rsp)
+ movsd -8(%rsp),%xmm0
+ ret
+END(remquo)
+
+
+/* Enable stack protection */
+#if defined(__ELF__)
+.section .note.GNU-stack,"",%progbits
+#endif
--- /dev/null
+/*-
+ * Copyright (c) 2005 David Schultz <das@FreeBSD.ORG>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Based on public-domain remainder routine by J.T. Conklin <jtc@NetBSD.org>.
+ */
+
+#include <amd64/bsd_asm.h>
+//__FBSDID("$FreeBSD: src/lib/msun/amd64/s_remquof.S,v 1.3 2011/01/07 16:13:12 kib Exp $");
+
+ENTRY(remquof)
+ movss %xmm0,-4(%rsp)
+ movss %xmm1,-8(%rsp)
+ flds -8(%rsp)
+ flds -4(%rsp)
+1: fprem1
+ fstsw %ax
+ btw $10,%ax
+ jc 1b
+ fstp %st(1)
+/* Extract the three low-order bits of the quotient from C0,C3,C1. */
+ shrl $6,%eax
+ movl %eax,%ecx
+ andl $0x108,%eax
+ rorl $7,%eax
+ orl %eax,%ecx
+ roll $4,%eax
+ orl %ecx,%eax
+ andl $7,%eax
+/* Negate the quotient bits if x*y<0. Avoid using an unpredictable branch. */
+ movl -8(%rsp),%ecx
+ xorl -4(%rsp),%ecx
+ sarl $16,%ecx
+ sarl $16,%ecx
+ xorl %ecx,%eax
+ andl $1,%ecx
+ addl %ecx,%eax
+/* Store the quotient and return. */
+#ifndef _WIN64
+ movl %eax,(%rdi)
+#else
+ movl %eax,(%r8)
+#endif
+ fstps -4(%rsp)
+ movss -4(%rsp),%xmm0
+ ret
+END(remquof)
+
+
+/* Enable stack protection */
+#if defined(__ELF__)
+.section .note.GNU-stack,"",%progbits
+#endif
--- /dev/null
+/*-
+ * Copyright (c) 2005-2008 David Schultz <das@FreeBSD.ORG>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Based on public-domain remainder routine by J.T. Conklin <jtc@NetBSD.org>.
+ */
+
+#include <amd64/bsd_asm.h>
+//__FBSDID("$FreeBSD: src/lib/msun/amd64/s_remquol.S,v 1.2 2011/01/07 16:13:12 kib Exp $");
+
+ENTRY(remquol)
+#ifndef _WIN64
+ fldt 24(%rsp)
+ fldt 8(%rsp)
+#else
+ fldt (%r8)
+ fldt (%rdx)
+ mov %rcx,%r8
+#endif
+1: fprem1
+ fstsw %ax
+ btw $10,%ax
+ jc 1b
+ fstp %st(1)
+/* Extract the three low-order bits of the quotient from C0,C3,C1. */
+ shrl $6,%eax
+ movl %eax,%ecx
+ andl $0x108,%eax
+ rorl $7,%eax
+ orl %eax,%ecx
+ roll $4,%eax
+ orl %ecx,%eax
+ andl $7,%eax
+/* Negate the quotient bits if x*y<0. Avoid using an unpredictable branch. */
+ movl 32(%rsp),%ecx
+ xorl 16(%rsp),%ecx
+ movsx %cx,%ecx
+ sarl $16,%ecx
+ sarl $16,%ecx
+ xorl %ecx,%eax
+ andl $1,%ecx
+ addl %ecx,%eax
+/* Store the quotient and return. */
+#ifndef _WIN64
+ movl %eax,(%rdi)
+#else
+ movl %eax,(%r9)
+ mov %r8,%rax
+ movq $0x0,0x8(%r8)
+ fstpt (%r8)
+#endif
+ ret
+
+
+/* Enable stack protection */
+#if defined(__ELF__)
+.section .note.GNU-stack,"",%progbits
+#endif
--- /dev/null
+/*
+ * Written by:
+ * J.T. Conklin (jtc@netbsd.org)
+ * Public domain.
+ */
+
+#include <amd64/bsd_asm.h>
+
+ENTRY(rintl)
+#ifndef _WIN64
+ fldt 8(%rsp)
+ frndint
+#else
+ fldt (%rdx)
+ frndint
+ mov %rcx,%rax
+ movq $0x0,0x8(%rcx)
+ fstpt (%rcx)
+#endif
+ ret
+
+
+/* Enable stack protection */
+#if defined(__ELF__)
+.section .note.GNU-stack,"",%progbits
+#endif
--- /dev/null
+/*-
+ * Copyright (c) 2005 David Schultz <das@FreeBSD.ORG>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <amd64/bsd_asm.h>
+//__FBSDID("$FreeBSD: src/lib/msun/amd64/s_scalbn.S,v 1.3 2011/01/07 16:13:12 kib Exp $")
+
+ENTRY(scalbn)
+ movsd %xmm0,-8(%rsp)
+#ifndef _WIN64
+ movl %edi,-12(%rsp)
+#else
+ movl %edx,-12(%rsp)
+#endif
+ fildl -12(%rsp)
+ fldl -8(%rsp)
+ fscale
+ fstp %st(1)
+ fstpl -8(%rsp)
+ movsd -8(%rsp),%xmm0
+ ret
+#ifndef _WIN64
+END(scalbn)
+.globl CNAME(ldexp)
+#else
+.globl CNAME(ldexp); .section .drectve; .ascii " -export:ldexp"
+#endif
+.set CNAME(ldexp),CNAME(scalbn)
+
+/* Enable stack protection */
+#if defined(__ELF__)
+.section .note.GNU-stack,"",%progbits
+#endif
--- /dev/null
+/*-
+ * Copyright (c) 2005 David Schultz <das@FreeBSD.ORG>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <amd64/bsd_asm.h>
+//__FBSDID("$FreeBSD: src/lib/msun/amd64/s_scalbnf.S,v 1.4 2011/01/07 16:13:12 kib Exp $")
+
+ENTRY(scalbnf)
+ movss %xmm0,-8(%rsp)
+#ifndef _WIN64
+ movl %edi,-4(%rsp)
+#else
+ movl %edx,-4(%rsp)
+#endif
+ fildl -4(%rsp)
+ flds -8(%rsp)
+ fscale
+ fstp %st(1)
+ fstps -8(%rsp)
+ movss -8(%rsp),%xmm0
+ ret
+#ifndef _WIN64
+END(scalbnf)
+.globl CNAME(ldexpf)
+#else
+.globl CNAME(ldexpf); .section .drectve; .ascii " -export:ldexpf"
+#endif
+.set CNAME(ldexpf),CNAME(scalbnf)
+
+/* Enable stack protection */
+#if defined(__ELF__)
+.section .note.GNU-stack,"",%progbits
+#endif
--- /dev/null
+/*
+ * Based on code written by J.T. Conklin <jtc@netbsd.org>.
+ * Public domain.
+ */
+
+#include <amd64/bsd_asm.h>
+//__FBSDID("$FreeBSD: src/lib/msun/amd64/s_scalbnl.S,v 1.3 2011/01/07 16:13:12 kib Exp $")
+/* //RCSID("$NetBSD: s_scalbnf.S,v 1.4 1999/01/02 05:15:40 kristerw Exp $") */
+
+ENTRY(scalbnl)
+#ifndef _WIN64
+ movl %edi,-4(%rsp)
+ fildl -4(%rsp)
+ fldt 8(%rsp)
+#else
+ mov %r8,%rax
+ movl %eax,-4(%rsp)
+ fildl -4(%rsp)
+ fldt (%rdx)
+#endif
+ fscale
+ fstp %st(1)
+#ifdef _WIN64
+ mov %rcx,%rax
+ movq $0x0,0x8(%rcx)
+ fstpt (%rcx)
+#endif
+ ret
+#ifndef _WIN64
+END(scalbnl)
+.globl CNAME(ldexpl)
+#else
+.globl CNAME(ldexpl); .section .drectve; .ascii " -export:ldexpl"
+#endif
+.set CNAME(ldexpl),CNAME(scalbnl)
+
+/* Enable stack protection */
+#if defined(__ELF__)
+.section .note.GNU-stack,"",%progbits
+#endif
--- /dev/null
+environment:
+ matrix:
+ - ARCH: "x86_64"
+
+branches:
+ only:
+ - master
+ - /release-.*/
+
+skip_commits:
+ message: /\[av skip\]/
+
+notifications:
+ - provider: Email
+ on_build_success: false
+ on_build_failure: false
+ on_build_status_changed: false
+
+init:
+ - git config --global core.autocrlf input
+
+build_script:
+ - ps: if ($env:APPVEYOR_PULL_REQUEST_NUMBER -and $env:APPVEYOR_BUILD_NUMBER -ne ((Invoke-RestMethod `
+ https://ci.appveyor.com/api/projects/$env:APPVEYOR_ACCOUNT_NAME/$env:APPVEYOR_PROJECT_SLUG/history?recordsNumber=50).builds | `
+ Where-Object pullRequestId -eq $env:APPVEYOR_PULL_REQUEST_NUMBER)[0].buildNumber) { `
+ throw "There are newer queued builds for this pull request, failing early." }
+ - if %ARCH%==i686 ( set EXCEPT=dwarf ) else set EXCEPT=seh
+ - if %ARCH%==i686 ( set MINGW=mingw32 ) else set MINGW=mingw64
+ - set PATH=C:\MinGW-w64\%ARCH%-6.3.0-posix-%EXCEPT%-rt_v5-rev1\%MINGW%\bin;%PATH%
+ - mingw32-make.exe ARCH=%ARCH% CC=%ARCH%-w64-mingw32-gcc
+ - mingw32-make.exe test ARCH=%ARCH% CC=%ARCH%-w64-mingw32-gcc
+
+on_finish:
+ # Uncomment the following line for interactive debugging, which
+ # will print login data for a temporary remote session after the
+ # build. This requires an RDP version 6 client, e.g., FreeRDP.
+ #- ps: $blockRdp = $true; iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1'))
--- /dev/null
+$(CUR_SRCS) = fenv.c
--- /dev/null
+/*-
+ * Copyright (c) 2004 David Schultz <das@FreeBSD.ORG>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: src/lib/msun/arm/fenv.c,v 1.3 2011/10/16 05:37:56 das Exp $
+ */
+
+#define __fenv_static
+#include <openlibm_fenv.h>
+
+#ifdef __GNUC_GNU_INLINE__
+#error "This file must be compiled with C99 'inline' semantics"
+#endif
+
+/*
+ * Hopefully the system ID byte is immutable, so it's valid to use
+ * this as a default environment.
+ */
+const fenv_t __fe_dfl_env = 0;
+
+extern inline int feclearexcept(int __excepts);
+extern inline int fegetexceptflag(fexcept_t *__flagp, int __excepts);
+extern inline int fesetexceptflag(const fexcept_t *__flagp, int __excepts);
+extern inline int feraiseexcept(int __excepts);
+extern inline int fetestexcept(int __excepts);
+extern inline int fegetround(void);
+extern inline int fesetround(int __round);
+extern inline int fegetenv(fenv_t *__envp);
+extern inline int feholdexcept(fenv_t *__envp);
+extern inline int fesetenv(const fenv_t *__envp);
+extern inline int feupdateenv(const fenv_t *__envp);
--- /dev/null
+$(CUR_SRCS) += b_exp.c b_log.c b_tgamma.c
--- /dev/null
+/*
+ * Copyright (c) 1985, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* @(#)exp.c 8.1 (Berkeley) 6/4/93 */
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/bsdsrc/b_exp.c,v 1.9 2011/10/16 05:37:20 das Exp $");
+
+#include <openlibm_math.h>
+
+/* EXP(X)
+ * RETURN THE EXPONENTIAL OF X
+ * DOUBLE PRECISION (IEEE 53 bits, VAX D FORMAT 56 BITS)
+ * CODED IN C BY K.C. NG, 1/19/85;
+ * REVISED BY K.C. NG on 2/6/85, 2/15/85, 3/7/85, 3/24/85, 4/16/85, 6/14/86.
+ *
+ * Required system supported functions:
+ * scalb(x,n)
+ * copysign(x,y)
+ * finite(x)
+ *
+ * Method:
+ * 1. Argument Reduction: given the input x, find r and integer k such
+ * that
+ * x = k*ln2 + r, |r| <= 0.5*ln2 .
+ * r will be represented as r := z+c for better accuracy.
+ *
+ * 2. Compute exp(r) by
+ *
+ * exp(r) = 1 + r + r*R1/(2-R1),
+ * where
+ * R1 = x - x^2*(p1+x^2*(p2+x^2*(p3+x^2*(p4+p5*x^2)))).
+ *
+ * 3. exp(x) = 2^k * exp(r) .
+ *
+ * Special cases:
+ * exp(INF) is INF, exp(NaN) is NaN;
+ * exp(-INF)= 0;
+ * for finite argument, only exp(0)=1 is exact.
+ *
+ * Accuracy:
+ * exp(x) returns the exponential of x nearly rounded. In a test run
+ * with 1,156,000 random arguments on a VAX, the maximum observed
+ * error was 0.869 ulps (units in the last place).
+ */
+
+#include "mathimpl.h"
+
+static const double p1 = 0x1.555555555553ep-3;
+static const double p2 = -0x1.6c16c16bebd93p-9;
+static const double p3 = 0x1.1566aaf25de2cp-14;
+static const double p4 = -0x1.bbd41c5d26bf1p-20;
+static const double p5 = 0x1.6376972bea4d0p-25;
+static const double ln2hi = 0x1.62e42fee00000p-1;
+static const double ln2lo = 0x1.a39ef35793c76p-33;
+static const double lnhuge = 0x1.6602b15b7ecf2p9;
+static const double lntiny = -0x1.77af8ebeae354p9;
+static const double invln2 = 0x1.71547652b82fep0;
+
+#if 0
+OLM_DLLEXPORT double exp(x)
+double x;
+{
+ double z,hi,lo,c;
+ int k;
+
+#if !defined(vax)&&!defined(tahoe)
+ if(x!=x) return(x); /* x is NaN */
+#endif /* !defined(vax)&&!defined(tahoe) */
+ if( x <= lnhuge ) {
+ if( x >= lntiny ) {
+
+ /* argument reduction : x --> x - k*ln2 */
+
+ k=invln2*x+copysign(0.5,x); /* k=NINT(x/ln2) */
+
+ /* express x-k*ln2 as hi-lo and let x=hi-lo rounded */
+
+ hi=x-k*ln2hi;
+ x=hi-(lo=k*ln2lo);
+
+ /* return 2^k*[1+x+x*c/(2+c)] */
+ z=x*x;
+ c= x - z*(p1+z*(p2+z*(p3+z*(p4+z*p5))));
+ return scalb(1.0+(hi-(lo-(x*c)/(2.0-c))),k);
+
+ }
+ /* end of x > lntiny */
+
+ else
+ /* exp(-big#) underflows to zero */
+ if(finite(x)) return(scalb(1.0,-5000));
+
+ /* exp(-INF) is zero */
+ else return(0.0);
+ }
+ /* end of x < lnhuge */
+
+ else
+ /* exp(INF) is INF, exp(+big#) overflows to INF */
+ return( finite(x) ? scalb(1.0,5000) : x);
+}
+#endif
+
+/* returns exp(r = x + c) for |c| < |x| with no overlap. */
+
+double __exp__D(x, c)
+double x, c;
+{
+ double z,hi,lo;
+ int k;
+
+ if (x != x) /* x is NaN */
+ return(x);
+ if ( x <= lnhuge ) {
+ if ( x >= lntiny ) {
+
+ /* argument reduction : x --> x - k*ln2 */
+ z = invln2*x;
+ k = z + copysign(.5, x);
+
+ /* express (x+c)-k*ln2 as hi-lo and let x=hi-lo rounded */
+
+ hi=(x-k*ln2hi); /* Exact. */
+ x= hi - (lo = k*ln2lo-c);
+ /* return 2^k*[1+x+x*c/(2+c)] */
+ z=x*x;
+ c= x - z*(p1+z*(p2+z*(p3+z*(p4+z*p5))));
+ c = (x*c)/(2.0-c);
+
+ return scalbn(1.+(hi-(lo - c)), k);
+ }
+ /* end of x > lntiny */
+
+ else
+ /* exp(-big#) underflows to zero */
+ if(isfinite(x)) return(scalbn(1.0,-5000));
+
+ /* exp(-INF) is zero */
+ else return(0.0);
+ }
+ /* end of x < lnhuge */
+
+ else
+ /* exp(INF) is INF, exp(+big#) overflows to INF */
+ return( isfinite(x) ? scalbn(1.0,5000) : x);
+}
--- /dev/null
+/*
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* @(#)log.c 8.2 (Berkeley) 11/30/93 */
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/bsdsrc/b_log.c,v 1.9 2008/02/22 02:26:51 das Exp $");
+
+#include <openlibm_math.h>
+
+#include "mathimpl.h"
+
+/* Table-driven natural logarithm.
+ *
+ * This code was derived, with minor modifications, from:
+ * Peter Tang, "Table-Driven Implementation of the
+ * Logarithm in IEEE Floating-Point arithmetic." ACM Trans.
+ * Math Software, vol 16. no 4, pp 378-400, Dec 1990).
+ *
+ * Calculates log(2^m*F*(1+f/F)), |f/j| <= 1/256,
+ * where F = j/128 for j an integer in [0, 128].
+ *
+ * log(2^m) = log2_hi*m + log2_tail*m
+ * since m is an integer, the dominant term is exact.
+ * m has at most 10 digits (for subnormal numbers),
+ * and log2_hi has 11 trailing zero bits.
+ *
+ * log(F) = logF_hi[j] + logF_lo[j] is in tabular form in log_table.h
+ * logF_hi[] + 512 is exact.
+ *
+ * log(1+f/F) = 2*f/(2*F + f) + 1/12 * (2*f/(2*F + f))**3 + ...
+ * the leading term is calculated to extra precision in two
+ * parts, the larger of which adds exactly to the dominant
+ * m and F terms.
+ * There are two cases:
+ * 1. when m, j are non-zero (m | j), use absolute
+ * precision for the leading term.
+ * 2. when m = j = 0, |1-x| < 1/256, and log(x) ~= (x-1).
+ * In this case, use a relative precision of 24 bits.
+ * (This is done differently in the original paper)
+ *
+ * Special cases:
+ * 0 return signalling -Inf
+ * neg return signalling NaN
+ * +Inf return +Inf
+*/
+
+#define N 128
+
+/* Table of log(Fj) = logF_head[j] + logF_tail[j], for Fj = 1+j/128.
+ * Used for generation of extend precision logarithms.
+ * The constant 35184372088832 is 2^45, so the divide is exact.
+ * It ensures correct reading of logF_head, even for inaccurate
+ * decimal-to-binary conversion routines. (Everybody gets the
+ * right answer for integers less than 2^53.)
+ * Values for log(F) were generated using error < 10^-57 absolute
+ * with the bc -l package.
+*/
+static double A1 = .08333333333333178827;
+static double A2 = .01250000000377174923;
+static double A3 = .002232139987919447809;
+static double A4 = .0004348877777076145742;
+
+static double logF_head[N+1] = {
+ 0.,
+ .007782140442060381246,
+ .015504186535963526694,
+ .023167059281547608406,
+ .030771658666765233647,
+ .038318864302141264488,
+ .045809536031242714670,
+ .053244514518837604555,
+ .060624621816486978786,
+ .067950661908525944454,
+ .075223421237524235039,
+ .082443669210988446138,
+ .089612158689760690322,
+ .096729626458454731618,
+ .103796793681567578460,
+ .110814366340264314203,
+ .117783035656430001836,
+ .124703478501032805070,
+ .131576357788617315236,
+ .138402322859292326029,
+ .145182009844575077295,
+ .151916042025732167530,
+ .158605030176659056451,
+ .165249572895390883786,
+ .171850256926518341060,
+ .178407657472689606947,
+ .184922338493834104156,
+ .191394852999565046047,
+ .197825743329758552135,
+ .204215541428766300668,
+ .210564769107350002741,
+ .216873938300523150246,
+ .223143551314024080056,
+ .229374101064877322642,
+ .235566071312860003672,
+ .241719936886966024758,
+ .247836163904594286577,
+ .253915209980732470285,
+ .259957524436686071567,
+ .265963548496984003577,
+ .271933715484010463114,
+ .277868451003087102435,
+ .283768173130738432519,
+ .289633292582948342896,
+ .295464212893421063199,
+ .301261330578199704177,
+ .307025035294827830512,
+ .312755710004239517729,
+ .318453731118097493890,
+ .324119468654316733591,
+ .329753286372579168528,
+ .335355541920762334484,
+ .340926586970454081892,
+ .346466767346100823488,
+ .351976423156884266063,
+ .357455888922231679316,
+ .362905493689140712376,
+ .368325561158599157352,
+ .373716409793814818840,
+ .379078352934811846353,
+ .384411698910298582632,
+ .389716751140440464951,
+ .394993808240542421117,
+ .400243164127459749579,
+ .405465108107819105498,
+ .410659924985338875558,
+ .415827895143593195825,
+ .420969294644237379543,
+ .426084395310681429691,
+ .431173464818130014464,
+ .436236766774527495726,
+ .441274560805140936281,
+ .446287102628048160113,
+ .451274644139630254358,
+ .456237433481874177232,
+ .461175715122408291790,
+ .466089729924533457960,
+ .470979715219073113985,
+ .475845904869856894947,
+ .480688529345570714212,
+ .485507815781602403149,
+ .490303988045525329653,
+ .495077266798034543171,
+ .499827869556611403822,
+ .504556010751912253908,
+ .509261901790523552335,
+ .513945751101346104405,
+ .518607764208354637958,
+ .523248143765158602036,
+ .527867089620485785417,
+ .532464798869114019908,
+ .537041465897345915436,
+ .541597282432121573947,
+ .546132437597407260909,
+ .550647117952394182793,
+ .555141507540611200965,
+ .559615787935399566777,
+ .564070138285387656651,
+ .568504735352689749561,
+ .572919753562018740922,
+ .577315365035246941260,
+ .581691739635061821900,
+ .586049045003164792433,
+ .590387446602107957005,
+ .594707107746216934174,
+ .599008189645246602594,
+ .603290851438941899687,
+ .607555250224322662688,
+ .611801541106615331955,
+ .616029877215623855590,
+ .620240409751204424537,
+ .624433288012369303032,
+ .628608659422752680256,
+ .632766669570628437213,
+ .636907462236194987781,
+ .641031179420679109171,
+ .645137961373620782978,
+ .649227946625615004450,
+ .653301272011958644725,
+ .657358072709030238911,
+ .661398482245203922502,
+ .665422632544505177065,
+ .669430653942981734871,
+ .673422675212350441142,
+ .677398823590920073911,
+ .681359224807238206267,
+ .685304003098281100392,
+ .689233281238557538017,
+ .693147180560117703862
+};
+
+static double logF_tail[N+1] = {
+ 0.,
+ -.00000000000000543229938420049,
+ .00000000000000172745674997061,
+ -.00000000000001323017818229233,
+ -.00000000000001154527628289872,
+ -.00000000000000466529469958300,
+ .00000000000005148849572685810,
+ -.00000000000002532168943117445,
+ -.00000000000005213620639136504,
+ -.00000000000001819506003016881,
+ .00000000000006329065958724544,
+ .00000000000008614512936087814,
+ -.00000000000007355770219435028,
+ .00000000000009638067658552277,
+ .00000000000007598636597194141,
+ .00000000000002579999128306990,
+ -.00000000000004654729747598444,
+ -.00000000000007556920687451336,
+ .00000000000010195735223708472,
+ -.00000000000017319034406422306,
+ -.00000000000007718001336828098,
+ .00000000000010980754099855238,
+ -.00000000000002047235780046195,
+ -.00000000000008372091099235912,
+ .00000000000014088127937111135,
+ .00000000000012869017157588257,
+ .00000000000017788850778198106,
+ .00000000000006440856150696891,
+ .00000000000016132822667240822,
+ -.00000000000007540916511956188,
+ -.00000000000000036507188831790,
+ .00000000000009120937249914984,
+ .00000000000018567570959796010,
+ -.00000000000003149265065191483,
+ -.00000000000009309459495196889,
+ .00000000000017914338601329117,
+ -.00000000000001302979717330866,
+ .00000000000023097385217586939,
+ .00000000000023999540484211737,
+ .00000000000015393776174455408,
+ -.00000000000036870428315837678,
+ .00000000000036920375082080089,
+ -.00000000000009383417223663699,
+ .00000000000009433398189512690,
+ .00000000000041481318704258568,
+ -.00000000000003792316480209314,
+ .00000000000008403156304792424,
+ -.00000000000034262934348285429,
+ .00000000000043712191957429145,
+ -.00000000000010475750058776541,
+ -.00000000000011118671389559323,
+ .00000000000037549577257259853,
+ .00000000000013912841212197565,
+ .00000000000010775743037572640,
+ .00000000000029391859187648000,
+ -.00000000000042790509060060774,
+ .00000000000022774076114039555,
+ .00000000000010849569622967912,
+ -.00000000000023073801945705758,
+ .00000000000015761203773969435,
+ .00000000000003345710269544082,
+ -.00000000000041525158063436123,
+ .00000000000032655698896907146,
+ -.00000000000044704265010452446,
+ .00000000000034527647952039772,
+ -.00000000000007048962392109746,
+ .00000000000011776978751369214,
+ -.00000000000010774341461609578,
+ .00000000000021863343293215910,
+ .00000000000024132639491333131,
+ .00000000000039057462209830700,
+ -.00000000000026570679203560751,
+ .00000000000037135141919592021,
+ -.00000000000017166921336082431,
+ -.00000000000028658285157914353,
+ -.00000000000023812542263446809,
+ .00000000000006576659768580062,
+ -.00000000000028210143846181267,
+ .00000000000010701931762114254,
+ .00000000000018119346366441110,
+ .00000000000009840465278232627,
+ -.00000000000033149150282752542,
+ -.00000000000018302857356041668,
+ -.00000000000016207400156744949,
+ .00000000000048303314949553201,
+ -.00000000000071560553172382115,
+ .00000000000088821239518571855,
+ -.00000000000030900580513238244,
+ -.00000000000061076551972851496,
+ .00000000000035659969663347830,
+ .00000000000035782396591276383,
+ -.00000000000046226087001544578,
+ .00000000000062279762917225156,
+ .00000000000072838947272065741,
+ .00000000000026809646615211673,
+ -.00000000000010960825046059278,
+ .00000000000002311949383800537,
+ -.00000000000058469058005299247,
+ -.00000000000002103748251144494,
+ -.00000000000023323182945587408,
+ -.00000000000042333694288141916,
+ -.00000000000043933937969737844,
+ .00000000000041341647073835565,
+ .00000000000006841763641591466,
+ .00000000000047585534004430641,
+ .00000000000083679678674757695,
+ -.00000000000085763734646658640,
+ .00000000000021913281229340092,
+ -.00000000000062242842536431148,
+ -.00000000000010983594325438430,
+ .00000000000065310431377633651,
+ -.00000000000047580199021710769,
+ -.00000000000037854251265457040,
+ .00000000000040939233218678664,
+ .00000000000087424383914858291,
+ .00000000000025218188456842882,
+ -.00000000000003608131360422557,
+ -.00000000000050518555924280902,
+ .00000000000078699403323355317,
+ -.00000000000067020876961949060,
+ .00000000000016108575753932458,
+ .00000000000058527188436251509,
+ -.00000000000035246757297904791,
+ -.00000000000018372084495629058,
+ .00000000000088606689813494916,
+ .00000000000066486268071468700,
+ .00000000000063831615170646519,
+ .00000000000025144230728376072,
+ -.00000000000017239444525614834
+};
+
+#if 0
+OLM_DLLEXPORT double
+#ifdef _ANSI_SOURCE
+log(double x)
+#else
+log(x) double x;
+#endif
+{
+ int m, j;
+ double F, f, g, q, u, u2, v, zero = 0.0, one = 1.0;
+ volatile double u1;
+
+ /* Catch special cases */
+ if (x <= 0)
+ if (x == zero) /* log(0) = -Inf */
+ return (-one/zero);
+ else /* log(neg) = NaN */
+ return (zero/zero);
+ else if (!finite(x))
+ return (x+x); /* x = NaN, Inf */
+
+ /* Argument reduction: 1 <= g < 2; x/2^m = g; */
+ /* y = F*(1 + f/F) for |f| <= 2^-8 */
+
+ m = logb(x);
+ g = ldexp(x, -m);
+ if (m == -1022) {
+ j = logb(g), m += j;
+ g = ldexp(g, -j);
+ }
+ j = N*(g-1) + .5;
+ F = (1.0/N) * j + 1; /* F*128 is an integer in [128, 512] */
+ f = g - F;
+
+ /* Approximate expansion for log(1+f/F) ~= u + q */
+ g = 1/(2*F+f);
+ u = 2*f*g;
+ v = u*u;
+ q = u*v*(A1 + v*(A2 + v*(A3 + v*A4)));
+
+ /* case 1: u1 = u rounded to 2^-43 absolute. Since u < 2^-8,
+ * u1 has at most 35 bits, and F*u1 is exact, as F has < 8 bits.
+ * It also adds exactly to |m*log2_hi + log_F_head[j] | < 750
+ */
+ if (m | j)
+ u1 = u + 513, u1 -= 513;
+
+ /* case 2: |1-x| < 1/256. The m- and j- dependent terms are zero;
+ * u1 = u to 24 bits.
+ */
+ else
+ u1 = u, TRUNC(u1);
+ u2 = (2.0*(f - F*u1) - u1*f) * g;
+ /* u1 + u2 = 2f/(2F+f) to extra precision. */
+
+ /* log(x) = log(2^m*F*(1+f/F)) = */
+ /* (m*log2_hi+logF_head[j]+u1) + (m*log2_lo+logF_tail[j]+q); */
+ /* (exact) + (tiny) */
+
+ u1 += m*logF_head[N] + logF_head[j]; /* exact */
+ u2 = (u2 + logF_tail[j]) + q; /* tiny */
+ u2 += logF_tail[N]*m;
+ return (u1 + u2);
+}
+#endif
+
+/*
+ * Extra precision variant, returning struct {double a, b;};
+ * log(x) = a+b to 63 bits, with a rounded to 26 bits.
+ */
+struct Double
+#ifdef _ANSI_SOURCE
+__log__D(double x)
+#else
+__log__D(x) double x;
+#endif
+{
+ int m, j;
+ double F, f, g, q, u, v, u2;
+ volatile double u1;
+ struct Double r;
+
+ /* Argument reduction: 1 <= g < 2; x/2^m = g; */
+ /* y = F*(1 + f/F) for |f| <= 2^-8 */
+
+ m = logb(x);
+ g = ldexp(x, -m);
+ if (m == -1022) {
+ j = logb(g), m += j;
+ g = ldexp(g, -j);
+ }
+ j = N*(g-1) + .5;
+ F = (1.0/N) * j + 1;
+ f = g - F;
+
+ g = 1/(2*F+f);
+ u = 2*f*g;
+ v = u*u;
+ q = u*v*(A1 + v*(A2 + v*(A3 + v*A4)));
+ if (m | j)
+ u1 = u + 513, u1 -= 513;
+ else
+ u1 = u, TRUNC(u1);
+ u2 = (2.0*(f - F*u1) - u1*f) * g;
+
+ u1 += m*logF_head[N] + logF_head[j];
+
+ u2 += logF_tail[j]; u2 += q;
+ u2 += logF_tail[N]*m;
+ r.a = u1 + u2; /* Only difference is here */
+ TRUNC(r.a);
+ r.b = (u1 - r.a) + u2;
+ return (r);
+}
--- /dev/null
+/*-
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* @(#)gamma.c 8.1 (Berkeley) 6/4/93 */
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/bsdsrc/b_tgamma.c,v 1.10 2008/02/22 02:26:51 das Exp $");
+
+/*
+ * This code by P. McIlroy, Oct 1992;
+ *
+ * The financial support of UUNET Communications Services is greatfully
+ * acknowledged.
+ */
+
+#include <openlibm_math.h>
+
+#include "mathimpl.h"
+
+/* METHOD:
+ * x < 0: Use reflection formula, G(x) = pi/(sin(pi*x)*x*G(x))
+ * At negative integers, return NaN and raise invalid.
+ *
+ * x < 6.5:
+ * Use argument reduction G(x+1) = xG(x) to reach the
+ * range [1.066124,2.066124]. Use a rational
+ * approximation centered at the minimum (x0+1) to
+ * ensure monotonicity.
+ *
+ * x >= 6.5: Use the asymptotic approximation (Stirling's formula)
+ * adjusted for equal-ripples:
+ *
+ * log(G(x)) ~= (x-.5)*(log(x)-1) + .5(log(2*pi)-1) + 1/x*P(1/(x*x))
+ *
+ * Keep extra precision in multiplying (x-.5)(log(x)-1), to
+ * avoid premature round-off.
+ *
+ * Special values:
+ * -Inf: return NaN and raise invalid;
+ * negative integer: return NaN and raise invalid;
+ * other x ~< 177.79: return +-0 and raise underflow;
+ * +-0: return +-Inf and raise divide-by-zero;
+ * finite x ~> 171.63: return +Inf and raise overflow;
+ * +Inf: return +Inf;
+ * NaN: return NaN.
+ *
+ * Accuracy: tgamma(x) is accurate to within
+ * x > 0: error provably < 0.9ulp.
+ * Maximum observed in 1,000,000 trials was .87ulp.
+ * x < 0:
+ * Maximum observed error < 4ulp in 1,000,000 trials.
+ */
+
+static double neg_gam(double);
+static double small_gam(double);
+static double smaller_gam(double);
+static struct Double large_gam(double);
+static struct Double ratfun_gam(double, double);
+
+/*
+ * Rational approximation, A0 + x*x*P(x)/Q(x), on the interval
+ * [1.066.., 2.066..] accurate to 4.25e-19.
+ */
+#define LEFT -.3955078125 /* left boundary for rat. approx */
+#define x0 .461632144968362356785 /* xmin - 1 */
+
+#define a0_hi 0.88560319441088874992
+#define a0_lo -.00000000000000004996427036469019695
+#define P0 6.21389571821820863029017800727e-01
+#define P1 2.65757198651533466104979197553e-01
+#define P2 5.53859446429917461063308081748e-03
+#define P3 1.38456698304096573887145282811e-03
+#define P4 2.40659950032711365819348969808e-03
+#define Q0 1.45019531250000000000000000000e+00
+#define Q1 1.06258521948016171343454061571e+00
+#define Q2 -2.07474561943859936441469926649e-01
+#define Q3 -1.46734131782005422506287573015e-01
+#define Q4 3.07878176156175520361557573779e-02
+#define Q5 5.12449347980666221336054633184e-03
+#define Q6 -1.76012741431666995019222898833e-03
+#define Q7 9.35021023573788935372153030556e-05
+#define Q8 6.13275507472443958924745652239e-06
+/*
+ * Constants for large x approximation (x in [6, Inf])
+ * (Accurate to 2.8*10^-19 absolute)
+ */
+#define lns2pi_hi 0.418945312500000
+#define lns2pi_lo -.000006779295327258219670263595
+#define Pa0 8.33333333333333148296162562474e-02
+#define Pa1 -2.77777777774548123579378966497e-03
+#define Pa2 7.93650778754435631476282786423e-04
+#define Pa3 -5.95235082566672847950717262222e-04
+#define Pa4 8.41428560346653702135821806252e-04
+#define Pa5 -1.89773526463879200348872089421e-03
+#define Pa6 5.69394463439411649408050664078e-03
+#define Pa7 -1.44705562421428915453880392761e-02
+
+static const double zero = 0., one = 1.0, tiny = 1e-300;
+
+OLM_DLLEXPORT double
+tgamma(x)
+ double x;
+{
+ struct Double u;
+
+ if (isgreaterequal(x, 6)) {
+ if(x > 171.63)
+ return (x / zero);
+ u = large_gam(x);
+ return(__exp__D(u.a, u.b));
+ } else if (isgreaterequal(x, 1.0 + LEFT + x0))
+ return (small_gam(x));
+ else if (isgreater(x, 1.e-17))
+ return (smaller_gam(x));
+ else if (isgreater(x, -1.e-17)) {
+ if (x != 0.0)
+ u.a = one - tiny; /* raise inexact */
+ return (one/x);
+ } else if (!isfinite(x))
+ return (x - x); /* x is NaN or -Inf */
+ else
+ return (neg_gam(x));
+}
+/*
+ * Accurate to max(ulp(1/128) absolute, 2^-66 relative) error.
+ */
+static struct Double
+large_gam(x)
+ double x;
+{
+ double z, p;
+ struct Double t, u, v;
+
+ z = one/(x*x);
+ p = Pa0+z*(Pa1+z*(Pa2+z*(Pa3+z*(Pa4+z*(Pa5+z*(Pa6+z*Pa7))))));
+ p = p/x;
+
+ u = __log__D(x);
+ u.a -= one;
+ v.a = (x -= .5);
+ TRUNC(v.a);
+ v.b = x - v.a;
+ t.a = v.a*u.a; /* t = (x-.5)*(log(x)-1) */
+ t.b = v.b*u.a + x*u.b;
+ /* return t.a + t.b + lns2pi_hi + lns2pi_lo + p */
+ t.b += lns2pi_lo; t.b += p;
+ u.a = lns2pi_hi + t.b; u.a += t.a;
+ u.b = t.a - u.a;
+ u.b += lns2pi_hi; u.b += t.b;
+ return (u);
+}
+/*
+ * Good to < 1 ulp. (provably .90 ulp; .87 ulp on 1,000,000 runs.)
+ * It also has correct monotonicity.
+ */
+static double
+small_gam(x)
+ double x;
+{
+ double y, ym1, t;
+ struct Double yy, r;
+ y = x - one;
+ ym1 = y - one;
+ if (y <= 1.0 + (LEFT + x0)) {
+ yy = ratfun_gam(y - x0, 0);
+ return (yy.a + yy.b);
+ }
+ r.a = y;
+ TRUNC(r.a);
+ yy.a = r.a - one;
+ y = ym1;
+ yy.b = r.b = y - yy.a;
+ /* Argument reduction: G(x+1) = x*G(x) */
+ for (ym1 = y-one; ym1 > LEFT + x0; y = ym1--, yy.a--) {
+ t = r.a*yy.a;
+ r.b = r.a*yy.b + y*r.b;
+ r.a = t;
+ TRUNC(r.a);
+ r.b += (t - r.a);
+ }
+ /* Return r*tgamma(y). */
+ yy = ratfun_gam(y - x0, 0);
+ y = r.b*(yy.a + yy.b) + r.a*yy.b;
+ y += yy.a*r.a;
+ return (y);
+}
+/*
+ * Good on (0, 1+x0+LEFT]. Accurate to 1ulp.
+ */
+static double
+smaller_gam(x)
+ double x;
+{
+ double t, d;
+ struct Double r, xx;
+ if (x < x0 + LEFT) {
+ t = x, TRUNC(t);
+ d = (t+x)*(x-t);
+ t *= t;
+ xx.a = (t + x), TRUNC(xx.a);
+ xx.b = x - xx.a; xx.b += t; xx.b += d;
+ t = (one-x0); t += x;
+ d = (one-x0); d -= t; d += x;
+ x = xx.a + xx.b;
+ } else {
+ xx.a = x, TRUNC(xx.a);
+ xx.b = x - xx.a;
+ t = x - x0;
+ d = (-x0 -t); d += x;
+ }
+ r = ratfun_gam(t, d);
+ d = r.a/x, TRUNC(d);
+ r.a -= d*xx.a; r.a -= d*xx.b; r.a += r.b;
+ return (d + r.a/x);
+}
+/*
+ * returns (z+c)^2 * P(z)/Q(z) + a0
+ */
+static struct Double
+ratfun_gam(z, c)
+ double z, c;
+{
+ double p, q;
+ struct Double r, t;
+
+ q = Q0 +z*(Q1+z*(Q2+z*(Q3+z*(Q4+z*(Q5+z*(Q6+z*(Q7+z*Q8)))))));
+ p = P0 + z*(P1 + z*(P2 + z*(P3 + z*P4)));
+
+ /* return r.a + r.b = a0 + (z+c)^2*p/q, with r.a truncated to 26 bits. */
+ p = p/q;
+ t.a = z, TRUNC(t.a); /* t ~= z + c */
+ t.b = (z - t.a) + c;
+ t.b *= (t.a + z);
+ q = (t.a *= t.a); /* t = (z+c)^2 */
+ TRUNC(t.a);
+ t.b += (q - t.a);
+ r.a = p, TRUNC(r.a); /* r = P/Q */
+ r.b = p - r.a;
+ t.b = t.b*p + t.a*r.b + a0_lo;
+ t.a *= r.a; /* t = (z+c)^2*(P/Q) */
+ r.a = t.a + a0_hi, TRUNC(r.a);
+ r.b = ((a0_hi-r.a) + t.a) + t.b;
+ return (r); /* r = a0 + t */
+}
+
+static double
+neg_gam(x)
+ double x;
+{
+ int sgn = 1;
+ struct Double lg, lsine;
+ double y, z;
+
+ y = ceil(x);
+ if (y == x) /* Negative integer. */
+ return ((x - x) / zero);
+ z = y - x;
+ if (z > 0.5)
+ z = one - z;
+ y = 0.5 * y;
+ if (y == ceil(y))
+ sgn = -1;
+ if (z < .25)
+ z = sin(M_PI*z);
+ else
+ z = cos(M_PI*(0.5-z));
+ /* Special case: G(1-x) = Inf; G(x) may be nonzero. */
+ if (x < -170) {
+ if (x < -190)
+ return ((double)sgn*tiny*tiny);
+ y = one - x; /* exact: 128 < |x| < 255 */
+ lg = large_gam(y);
+ lsine = __log__D(M_PI/z); /* = TRUNC(log(u)) + small */
+ lg.a -= lsine.a; /* exact (opposite signs) */
+ lg.b -= lsine.b;
+ y = -(lg.a + lg.b);
+ z = (y + lg.a) + lg.b;
+ y = __exp__D(y, z);
+ if (sgn < 0) y = -y;
+ return (y);
+ }
+ y = one-x;
+ if (one-y == x)
+ y = tgamma(y);
+ else /* 1-x is inexact */
+ y = -x*tgamma(-x);
+ if (sgn < 0) y = -y;
+ return (M_PI / (y*z));
+}
--- /dev/null
+/*
+ * Copyright (c) 1988, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)mathimpl.h 8.1 (Berkeley) 6/4/93
+ * $FreeBSD: src/lib/msun/bsdsrc/mathimpl.h,v 1.7 2005/11/18 05:03:12 bde Exp $
+ */
+
+#ifndef _MATHIMPL_H_
+#define _MATHIMPL_H_
+
+#include "cdefs-compat.h"
+#include "math_private.h"
+
+/*
+ * TRUNC() is a macro that sets the trailing 27 bits in the mantissa of an
+ * IEEE double variable to zero. It must be expression-like for syntactic
+ * reasons, and we implement this expression using an inline function
+ * instead of a pure macro to avoid depending on the gcc feature of
+ * statement-expressions.
+ */
+#define TRUNC(d) (_b_trunc(&(d)))
+
+static __inline void
+_b_trunc(volatile double *_dp)
+{
+ //VBS
+ //u_int32_t _lw;
+ u_int32_t _lw;
+
+ GET_LOW_WORD(_lw, *_dp);
+ SET_LOW_WORD(*_dp, _lw & 0xf8000000);
+}
+
+struct Double {
+ double a;
+ double b;
+};
+
+/*
+ * Functions internal to the math package, yet not static.
+ */
+double __exp__D(double, double);
+struct Double __log__D(double);
+
+#endif /* !_MATHIMPL_H_ */
--- /dev/null
+$(CUR_SRCS) = e_exp.S e_fmod.S e_log.S e_log10.S \
+ e_remainder.S e_sqrt.S s_ceil.S s_copysign.S \
+ s_floor.S s_llrint.S s_logb.S s_lrint.S \
+ s_remquo.S s_rint.S s_tan.S s_trunc.S
+
+ifneq ($(OS), WINNT)
+$(CUR_SRCS) += s_scalbn.S s_scalbnf.S s_scalbnl.S
+endif
+
+# float counterparts
+$(CUR_SRCS)+= e_log10f.S e_logf.S e_remainderf.S \
+ e_sqrtf.S s_ceilf.S s_copysignf.S s_floorf.S \
+ s_llrintf.S s_logbf.S s_lrintf.S \
+ s_remquof.S s_rintf.S s_truncf.S
+
+# long double counterparts
+$(CUR_SRCS)+= e_remainderl.S e_sqrtl.S s_ceill.S s_copysignl.S \
+ s_floorl.S s_llrintl.S \
+ s_logbl.S s_lrintl.S s_remquol.S s_rintl.S s_truncl.S
+
+$(CUR_SRCS)+= fenv.c
--- /dev/null
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * William Jolitz.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: @(#)DEFS.h 5.1 (Berkeley) 4/23/90
+ * $FreeBSD: src/sys/i386/include/asm.h,v 1.14 2007/08/22 04:26:07 jkoshy Exp $
+ */
+
+#ifndef _MACHINE_ASM_H_
+#define _MACHINE_ASM_H_
+
+#if defined(__APPLE__)
+#include "osx_asm.h"
+#define CNAME(x) EXT(x)
+#else
+#include "cdefs-compat.h"
+
+#ifdef PIC
+#define PIC_PROLOGUE \
+ pushl %ebx; \
+ call 1f; \
+1: \
+ popl %ebx; \
+ addl $_GLOBAL_OFFSET_TABLE_+[.-1b],%ebx
+#define PIC_EPILOGUE \
+ popl %ebx
+#define PIC_PLT(x) x@PLT
+#define PIC_GOT(x) x@GOT(%ebx)
+#else
+#define PIC_PROLOGUE
+#define PIC_EPILOGUE
+#define PIC_PLT(x) x
+#define PIC_GOT(x) x
+#endif
+
+/*
+ * CNAME and HIDENAME manage the relationship between symbol names in C
+ * and the equivalent assembly language names. CNAME is given a name as
+ * it would be used in a C program. It expands to the equivalent assembly
+ * language name. HIDENAME is given an assembly-language name, and expands
+ * to a possibly-modified form that will be invisible to C programs.
+ */
+
+
+/* XXX should use .p2align 4,0x90 for -m486. */
+#define _START_ENTRY .p2align 2,0x90
+
+#if defined(__ELF__)
+#define CNAME(csym) csym
+#define HIDENAME(asmsym) .asmsym
+#define _ENTRY(x) .text; _START_ENTRY; \
+ .globl CNAME(x); .type CNAME(x),@function; CNAME(x):
+#define END(x) .size x, . - x
+#elif defined(_WIN32)
+#ifndef _MSC_VER
+#define END(x) .end
+#define _START_ENTRY_WIN .text; _START_ENTRY
+#else
+#define END(x) end
+#define _START_ENTRY_WIN .code; _START_ENTRY
+#endif
+#define CNAME(csym) _##csym
+#define HIDENAME(asmsym) .asmsym
+#define _ENTRY(x) _START_ENTRY_WIN; \
+ .globl CNAME(x); .section .drectve; .ascii " -export:", #x; \
+ .section .text; .def CNAME(x); .scl 2; .type 32; .endef; CNAME(x):
+#endif
+
+#ifdef PROF
+#define ALTENTRY(x) _ENTRY(x); \
+ pushl %ebp; movl %esp,%ebp; \
+ call PIC_PLT(HIDENAME(mcount)); \
+ popl %ebp; \
+ jmp 9f
+#define ENTRY(x) _ENTRY(x); \
+ pushl %ebp; movl %esp,%ebp; \
+ call PIC_PLT(HIDENAME(mcount)); \
+ popl %ebp; \
+ 9:
+#else
+#define ALTENTRY(x) _ENTRY(x)
+#define ENTRY(x) _ENTRY(x)
+#endif
+
+#define RCSID(x) .text; .asciz x
+
+#undef __FBSDID
+#define __FBSDID(s) /* nothing */
+
+#endif
+#endif /* !_MACHINE_ASM_H_ */
--- /dev/null
+/*-
+ * Copyright (c) 2003 Peter Wemm.
+ * Copyright (c) 1990 Andrew Moore, Talke Studio
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: @(#) ieeefp.h 1.0 (Berkeley) 9/23/93
+ * $FreeBSD$
+ */
+
+#ifndef _MACHINE_IEEEFP_H_
+#define _MACHINE_IEEEFP_H_
+
+/*
+ * Deprecated historical FPU control interface
+ *
+ * IEEE floating point type, constant and function definitions.
+ * XXX: FP*FLD and FP*OFF are undocumented pollution.
+ */
+
+/* VBS
+
+#ifndef _SYS_CDEFS_H_
+#error this file needs sys/cdefs.h as a prerequisite
+#endif
+
+*/
+
+/*
+ * Rounding modes.
+ */
+typedef enum {
+ FP_RN=0, /* round to nearest */
+ FP_RM, /* round down towards minus infinity */
+ FP_RP, /* round up towards plus infinity */
+ FP_RZ /* truncate */
+} fp_rnd_t;
+
+/*
+ * Precision (i.e., rounding precision) modes.
+ */
+typedef enum {
+ FP_PS=0, /* 24 bit (single-precision) */
+ FP_PRS, /* reserved */
+ FP_PD, /* 53 bit (double-precision) */
+ FP_PE /* 64 bit (extended-precision) */
+} fp_prec_t;
+
+#define fp_except_t int
+
+/*
+ * Exception bit masks.
+ */
+#define FP_X_INV 0x01 /* invalid operation */
+#define FP_X_DNML 0x02 /* denormal */
+#define FP_X_DZ 0x04 /* zero divide */
+#define FP_X_OFL 0x08 /* overflow */
+#define FP_X_UFL 0x10 /* underflow */
+#define FP_X_IMP 0x20 /* (im)precision */
+#define FP_X_STK 0x40 /* stack fault */
+
+/*
+ * FPU control word bit-field masks.
+ */
+#define FP_MSKS_FLD 0x3f /* exception masks field */
+#define FP_PRC_FLD 0x300 /* precision control field */
+#define FP_RND_FLD 0xc00 /* rounding control field */
+
+/*
+ * FPU status word bit-field masks.
+ */
+#define FP_STKY_FLD 0x3f /* sticky flags field */
+
+/*
+ * FPU control word bit-field offsets (shift counts).
+ */
+#define FP_MSKS_OFF 0 /* exception masks offset */
+#define FP_PRC_OFF 8 /* precision control offset */
+#define FP_RND_OFF 10 /* rounding control offset */
+
+/*
+ * FPU status word bit-field offsets (shift counts).
+ */
+#define FP_STKY_OFF 0 /* sticky flags offset */
+
+//VBS
+//#ifdef __GNUCLIKE_ASM
+
+#define __fldcw(addr) __asm __volatile("fldcw %0" : : "m" (*(addr)))
+#define __fldenv(addr) __asm __volatile("fldenv %0" : : "m" (*(addr)))
+#define __fnclex() __asm __volatile("fnclex")
+#define __fnstcw(addr) __asm __volatile("fnstcw %0" : "=m" (*(addr)))
+#define __fnstenv(addr) __asm __volatile("fnstenv %0" : "=m" (*(addr)))
+#define __fnstsw(addr) __asm __volatile("fnstsw %0" : "=m" (*(addr)))
+
+/*
+ * Load the control word. Be careful not to trap if there is a currently
+ * unmasked exception (ones that will become freshly unmasked are not a
+ * problem). This case must be handled by a save/restore of the
+ * environment or even of the full x87 state. Accessing the environment
+ * is very inefficient, so only do it when necessary.
+ */
+static __inline void
+__fnldcw(unsigned short _cw, unsigned short _newcw)
+{
+ struct {
+ unsigned _cw;
+ unsigned _other[6];
+ } _env;
+ unsigned short _sw;
+
+ if ((_cw & FP_MSKS_FLD) != FP_MSKS_FLD) {
+ __fnstsw(&_sw);
+ if (((_sw & ~_cw) & FP_STKY_FLD) != 0) {
+ __fnstenv(&_env);
+ _env._cw = _newcw;
+ __fldenv(&_env);
+ return;
+ }
+ }
+ __fldcw(&_newcw);
+}
+
+static __inline fp_rnd_t
+fpgetround(void)
+{
+ unsigned short _cw;
+
+ __fnstcw(&_cw);
+ return ((fp_rnd_t)((_cw & FP_RND_FLD) >> FP_RND_OFF));
+}
+
+static __inline fp_rnd_t
+fpsetround(fp_rnd_t _m)
+{
+ fp_rnd_t _p;
+ unsigned short _cw, _newcw;
+
+ __fnstcw(&_cw);
+ _p = (fp_rnd_t)((_cw & FP_RND_FLD) >> FP_RND_OFF);
+ _newcw = _cw & ~FP_RND_FLD;
+ _newcw |= (_m << FP_RND_OFF) & FP_RND_FLD;
+ __fnldcw(_cw, _newcw);
+ return (_p);
+}
+
+//static __inline fp_prec_t
+OLM_DLLEXPORT fp_prec_t
+fpgetprec(void)
+{
+ unsigned short _cw;
+
+ __fnstcw(&_cw);
+ return ((fp_prec_t)((_cw & FP_PRC_FLD) >> FP_PRC_OFF));
+}
+
+//static __inline fp_prec_t
+OLM_DLLEXPORT fp_prec_t
+fpsetprec(fp_prec_t _m)
+{
+ fp_prec_t _p;
+ unsigned short _cw, _newcw;
+
+ __fnstcw(&_cw);
+ _p = (fp_prec_t)((_cw & FP_PRC_FLD) >> FP_PRC_OFF);
+ _newcw = _cw & ~FP_PRC_FLD;
+ _newcw |= (_m << FP_PRC_OFF) & FP_PRC_FLD;
+ __fnldcw(_cw, _newcw);
+ return (_p);
+}
+
+/*
+ * Get or set the exception mask.
+ * Note that the x87 mask bits are inverted by the API -- a mask bit of 1
+ * means disable for x87 and SSE, but for fp*mask() it means enable.
+ */
+
+static __inline fp_except_t
+fpgetmask(void)
+{
+ unsigned short _cw;
+
+ __fnstcw(&_cw);
+ return ((~_cw & FP_MSKS_FLD) >> FP_MSKS_OFF);
+}
+
+static __inline fp_except_t
+fpsetmask(fp_except_t _m)
+{
+ fp_except_t _p;
+ unsigned short _cw, _newcw;
+
+ __fnstcw(&_cw);
+ _p = (~_cw & FP_MSKS_FLD) >> FP_MSKS_OFF;
+ _newcw = _cw & ~FP_MSKS_FLD;
+ _newcw |= (~_m << FP_MSKS_OFF) & FP_MSKS_FLD;
+ __fnldcw(_cw, _newcw);
+ return (_p);
+}
+
+static __inline fp_except_t
+fpgetsticky(void)
+{
+ unsigned _ex;
+ unsigned short _sw;
+
+ __fnstsw(&_sw);
+ _ex = (_sw & FP_STKY_FLD) >> FP_STKY_OFF;
+ return ((fp_except_t)_ex);
+}
+
+static __inline fp_except_t
+fpresetsticky(fp_except_t _m)
+{
+ struct {
+ unsigned _cw;
+ unsigned _sw;
+ unsigned _other[5];
+ } _env;
+ fp_except_t _p;
+
+ _m &= FP_STKY_FLD >> FP_STKY_OFF;
+ _p = fpgetsticky();
+ if ((_p & ~_m) == _p)
+ return (_p);
+ if ((_p & ~_m) == 0) {
+ __fnclex();
+ return (_p);
+ }
+ __fnstenv(&_env);
+ _env._sw &= ~_m;
+ __fldenv(&_env);
+ return (_p);
+}
+
+//#endif /* __GNUCLIKE_ASM */
+
+#endif /* !_MACHINE_IEEEFP_H_ */
--- /dev/null
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * William Jolitz.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: @(#)npx.h 5.3 (Berkeley) 1/18/91
+ * $FreeBSD: src/sys/i386/include/npx.h,v 1.29.2.1 2006/07/01 00:57:55 davidxu Exp $
+ */
+
+/*
+ * 287/387 NPX Coprocessor Data Structures and Constants
+ * W. Jolitz 1/90
+ */
+
+#ifndef _MACHINE_NPX_H_
+#define _MACHINE_NPX_H_
+
+/* Environment information of floating point unit */
+struct env87 {
+ long en_cw; /* control word (16bits) */
+ long en_sw; /* status word (16bits) */
+ long en_tw; /* tag word (16bits) */
+ long en_fip; /* floating point instruction pointer */
+ unsigned short en_fcs; /* floating code segment selector */
+ unsigned short en_opcode; /* opcode last executed (11 bits ) */
+ long en_foo; /* floating operand offset */
+ long en_fos; /* floating operand segment selector */
+};
+
+/* Contents of each floating point accumulator */
+struct fpacc87 {
+#ifdef dontdef /* too unportable */
+ unsigned long fp_mantlo; /* mantissa low (31:0) */
+ unsigned long fp_manthi; /* mantissa high (63:32) */
+ int fp_exp:15; /* exponent */
+ int fp_sgn:1; /* mantissa sign */
+#else
+ unsigned char fp_bytes[10];
+#endif
+};
+
+/* Floating point context */
+struct save87 {
+ struct env87 sv_env; /* floating point control/status */
+ struct fpacc87 sv_ac[8]; /* accumulator contents, 0-7 */
+ unsigned char sv_pad0[4]; /* padding for (now unused) saved status word */
+ /*
+ * Bogus padding for emulators. Emulators should use their own
+ * struct and arrange to store into this struct (ending here)
+ * before it is inspected for ptracing or for core dumps. Some
+ * emulators overwrite the whole struct. We have no good way of
+ * knowing how much padding to leave. Leave just enough for the
+ * GPL emulator's i387_union (176 bytes total).
+ */
+ unsigned char sv_pad[64]; /* padding; used by emulators */
+};
+
+struct envxmm {
+ uint16_t en_cw; /* control word (16bits) */
+ uint16_t en_sw; /* status word (16bits) */
+ uint16_t en_tw; /* tag word (16bits) */
+ uint16_t en_opcode; /* opcode last executed (11 bits ) */
+ uint32_t en_fip; /* floating point instruction pointer */
+ uint16_t en_fcs; /* floating code segment selector */
+ uint16_t en_pad0; /* padding */
+ uint32_t en_foo; /* floating operand offset */
+ uint16_t en_fos; /* floating operand segment selector */
+ uint16_t en_pad1; /* padding */
+ uint32_t en_mxcsr; /* SSE sontorol/status register */
+ uint32_t en_mxcsr_mask; /* valid bits in mxcsr */
+};
+
+/* Contents of each SSE extended accumulator */
+struct xmmacc {
+ unsigned char xmm_bytes[16];
+};
+
+struct savexmm {
+ struct envxmm sv_env;
+ struct {
+ struct fpacc87 fp_acc;
+ unsigned char fp_pad[6]; /* padding */
+ } sv_fp[8];
+ struct xmmacc sv_xmm[8];
+ unsigned char sv_pad[224];
+} __attribute__((__aligned__(16)));
+
+union savefpu {
+ struct save87 sv_87;
+ struct savexmm sv_xmm;
+};
+
+/*
+ * The hardware default control word for i387's and later coprocessors is
+ * 0x37F, giving:
+ *
+ * round to nearest
+ * 64-bit precision
+ * all exceptions masked.
+ *
+ * We modify the affine mode bit and precision bits in this to give:
+ *
+ * affine mode for 287's (if they work at all) (1 in bitfield 1<<12)
+ * 53-bit precision (2 in bitfield 3<<8)
+ *
+ * 64-bit precision often gives bad results with high level languages
+ * because it makes the results of calculations depend on whether
+ * intermediate values are stored in memory or in FPU registers.
+ */
+#define __INITIAL_NPXCW__ 0x127F
+#define __INITIAL_MXCSR__ 0x1F80
+
+#ifdef _KERNEL
+
+#define IO_NPX 0x0F0 /* Numeric Coprocessor */
+#define IO_NPXSIZE 16 /* 80387/80487 NPX registers */
+
+#define IRQ_NPX 13
+
+/* full reset on some systems, NOP on others */
+#define npx_full_reset() outb(IO_NPX + 1, 0)
+
+int npxdna(void);
+void npxdrop(void);
+void npxexit(struct thread *td);
+int npxformat(void);
+int npxgetregs(struct thread *td, union savefpu *addr);
+void npxinit(unsigned short control);
+void npxsave(union savefpu *addr);
+void npxsetregs(struct thread *td, union savefpu *addr);
+int npxtrap(void);
+#endif
+
+#endif /* !_MACHINE_NPX_H_ */
\ No newline at end of file
--- /dev/null
+/*
+ * Written by:
+ * J.T. Conklin (jtc@netbsd.org)
+ * Public domain.
+ */
+
+#include <i387/bsd_asm.h>
+
+/* e^x = 2^(x * log2(e)) */
+
+ENTRY(exp)
+ /*
+ * If x is +-Inf, then the subtraction would give Inf-Inf = NaN.
+ * Avoid this. Also avoid it if x is NaN for convenience.
+ */
+ movl 8(%esp),%eax
+ andl $0x7fffffff,%eax
+ cmpl $0x7ff00000,%eax
+ jae x_Inf_or_NaN
+
+ fldl 4(%esp)
+
+ /*
+ * Extended precision is needed to reduce the maximum error from
+ * hundreds of ulps to less than 1 ulp. Switch to it if necessary.
+ * We may as well set the rounding mode to to-nearest and mask traps
+ * if we switch.
+ */
+ fstcw 4(%esp)
+ movl 4(%esp),%eax
+ andl $0x0300,%eax
+ cmpl $0x0300,%eax /* RC == 0 && PC == 3? */
+ je 1f /* jump if mode is good */
+ movl $0x137f,8(%esp)
+ fldcw 8(%esp)
+1:
+ fldl2e
+ fmulp /* x * log2(e) */
+ fst %st(1)
+ frndint /* int(x * log2(e)) */
+ fst %st(2)
+ fsubrp /* fract(x * log2(e)) */
+ f2xm1 /* 2^(fract(x * log2(e))) - 1 */
+ fld1
+ faddp /* 2^(fract(x * log2(e))) */
+ fscale /* e^x */
+ fstp %st(1)
+ je 1f
+ fldcw 4(%esp)
+1:
+ ret
+
+x_Inf_or_NaN:
+ /*
+ * Return 0 if x is -Inf. Otherwise just return x; when x is Inf
+ * this gives Inf, and when x is a NaN this gives the same result
+ * as (x + x) (x quieted).
+ */
+ cmpl $0xfff00000,8(%esp)
+ jne x_not_minus_Inf
+ cmpl $0,4(%esp)
+ jne x_not_minus_Inf
+ fldz
+ ret
+
+x_not_minus_Inf:
+ fldl 4(%esp)
+ ret
+END(exp)
+
+ //
+
+/* Enable stack protection */
+#if defined(__ELF__)
+.section .note.GNU-stack,"",%progbits
+#endif
--- /dev/null
+/*
+ * Written by:
+ * J.T. Conklin (jtc@netbsd.org)
+ * Public domain.
+ */
+
+#include <i387/bsd_asm.h>
+//__FBSDID("$FreeBSD: src/lib/msun/i387/e_fmod.S,v 1.11 2011/01/07 16:13:12 kib Exp $")
+
+ENTRY(fmod)
+ fldl 12(%esp)
+ fldl 4(%esp)
+1: fprem
+ fstsw %ax
+ sahf
+ jp 1b
+ fstp %st(1)
+ ret
+END(fmod)
+
+
+/* Enable stack protection */
+#if defined(__ELF__)
+.section .note.GNU-stack,"",%progbits
+#endif
--- /dev/null
+/*
+ * Written by:
+ * J.T. Conklin (jtc@netbsd.org)
+ * Public domain.
+ */
+
+#include <i387/bsd_asm.h>
+//__FBSDID("$FreeBSD: src/lib/msun/i387/e_log.S,v 1.10 2011/01/07 16:13:12 kib Exp $")
+
+ENTRY(log)
+ fldln2
+ fldl 4(%esp)
+ fyl2x
+ ret
+END(log)
+
+
+/* Enable stack protection */
+#if defined(__ELF__)
+.section .note.GNU-stack,"",%progbits
+#endif
--- /dev/null
+/*
+ * Written by:
+ * J.T. Conklin (jtc@netbsd.org)
+ * Public domain.
+ */
+
+#include <i387/bsd_asm.h>
+//__FBSDID("$FreeBSD: src/lib/msun/i387/e_log10.S,v 1.10 2011/01/07 16:13:12 kib Exp $")
+
+ENTRY(log10)
+ fldlg2
+ fldl 4(%esp)
+ fyl2x
+ ret
+END(log10)
+
+
+/* Enable stack protection */
+#if defined(__ELF__)
+.section .note.GNU-stack,"",%progbits
+#endif
--- /dev/null
+/*
+ * Written by J.T. Conklin <jtc@netbsd.org>.
+ * Public domain.
+ */
+
+#include <i387/bsd_asm.h>
+
+//__FBSDID("$FreeBSD: src/lib/msun/i387/e_log10f.S,v 1.4 2011/01/07 16:13:12 kib Exp $");
+/* RCSID("$NetBSD: e_log10f.S,v 1.1 1996/07/03 16:50:22 jtc Exp $") */
+
+ENTRY(log10f)
+ fldlg2
+ flds 4(%esp)
+ fyl2x
+ ret
+END(log10f)
+
+
+/* Enable stack protection */
+#if defined(__ELF__)
+.section .note.GNU-stack,"",%progbits
+#endif
--- /dev/null
+/*
+ * Written by J.T. Conklin <jtc@netbsd.org>.
+ * Public domain.
+ */
+
+#include <i387/bsd_asm.h>
+
+//__FBSDID("$FreeBSD: src/lib/msun/i387/e_logf.S,v 1.3 2011/01/07 16:13:12 kib Exp $");
+/* RCSID("$NetBSD: e_logf.S,v 1.2 1996/07/06 00:15:45 jtc Exp $") */
+
+ENTRY(logf)
+ fldln2
+ flds 4(%esp)
+ fyl2x
+ ret
+
+
+/* Enable stack protection */
+#if defined(__ELF__)
+.section .note.GNU-stack,"",%progbits
+#endif
--- /dev/null
+/*
+ * Written by:
+ * J.T. Conklin (jtc@netbsd.org)
+ * Public domain.
+ */
+
+#include <i387/bsd_asm.h>
+//__FBSDID("$FreeBSD: src/lib/msun/i387/e_remainder.S,v 1.11 2011/01/07 16:13:12 kib Exp $")
+
+ENTRY(remainder)
+ fldl 12(%esp)
+ fldl 4(%esp)
+1: fprem1
+ fstsw %ax
+ sahf
+ jp 1b
+ fstp %st(1)
+ ret
+END(remainder)
+
+
+/* Enable stack protection */
+#if defined(__ELF__)
+.section .note.GNU-stack,"",%progbits
+#endif
--- /dev/null
+/*
+ * Written by J.T. Conklin <jtc@netbsd.org>.
+ * Public domain.
+ */
+
+#include <i387/bsd_asm.h>
+
+//__FBSDID("$FreeBSD: src/lib/msun/i387/e_remainderf.S,v 1.4 2011/01/07 16:13:12 kib Exp $");
+/* RCSID("$NetBSD: e_remainderf.S,v 1.2 1995/05/08 23:49:47 jtc Exp $") */
+
+ENTRY(remainderf)
+ flds 8(%esp)
+ flds 4(%esp)
+1: fprem1
+ fstsw %ax
+ sahf
+ jp 1b
+ fstp %st(1)
+ ret
+END(remainderf)
+
+
+/* Enable stack protection */
+#if defined(__ELF__)
+.section .note.GNU-stack,"",%progbits
+#endif
--- /dev/null
+/*
+ * Written by:
+ * J.T. Conklin (jtc@netbsd.org)
+ * Public domain.
+ */
+
+#include <i387/bsd_asm.h>
+
+//__FBSDID("$FreeBSD: src/lib/msun/i387/e_remainderl.S,v 1.2 2011/01/07 16:13:12 kib Exp $")
+
+ENTRY(remainderl)
+ fldt 16(%esp)
+ fldt 4(%esp)
+1: fprem1
+ fstsw %ax
+ sahf
+ jp 1b
+ fstp %st(1)
+ ret
+
+
+/* Enable stack protection */
+#if defined(__ELF__)
+.section .note.GNU-stack,"",%progbits
+#endif
--- /dev/null
+/*
+ * Written by:
+ * J.T. Conklin (jtc@netbsd.org)
+ * Public domain.
+ */
+
+#include <i387/bsd_asm.h>
+//__FBSDID("$FreeBSD: src/lib/msun/i387/e_sqrt.S,v 1.10 2011/01/07 16:13:12 kib Exp $")
+
+ENTRY(sqrt)
+ fldl 4(%esp)
+ fsqrt
+ ret
+END(sqrt)
+
+
+/* Enable stack protection */
+#if defined(__ELF__)
+.section .note.GNU-stack,"",%progbits
+#endif
--- /dev/null
+/*
+ * Written by J.T. Conklin <jtc@netbsd.org>.
+ * Public domain.
+ */
+
+#include <i387/bsd_asm.h>
+
+//__FBSDID("$FreeBSD: src/lib/msun/i387/e_sqrtf.S,v 1.4 2011/01/07 16:13:12 kib Exp $");
+/* RCSID("$NetBSD: e_sqrtf.S,v 1.2 1995/05/08 23:50:14 jtc Exp $") */
+
+ENTRY(sqrtf)
+ flds 4(%esp)
+ fsqrt
+ ret
+END(sqrtf)
+
+
+/* Enable stack protection */
+#if defined(__ELF__)
+.section .note.GNU-stack,"",%progbits
+#endif
--- /dev/null
+/*
+ * Written by:
+ * J.T. Conklin (jtc@netbsd.org)
+ * Public domain.
+ */
+
+#include <i387/bsd_asm.h>
+//__FBSDID("$FreeBSD: src/lib/msun/i387/e_sqrtl.S,v 1.3 2011/01/07 16:13:12 kib Exp $")
+
+ENTRY(sqrtl)
+ fldt 4(%esp)
+ fsqrt
+ ret
+
+
+/* Enable stack protection */
+#if defined(__ELF__)
+.section .note.GNU-stack,"",%progbits
+#endif
--- /dev/null
+/*-
+ * Copyright (c) 2004-2005 David Schultz <das@FreeBSD.ORG>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: src/lib/msun/i387/fenv.c,v 1.8 2011/10/21 06:25:31 das Exp $
+ */
+
+#include "cdefs-compat.h"
+#include "types-compat.h"
+#include "math_private.h"
+#include "i387/bsd_npx.h"
+
+#define __fenv_static
+#include <openlibm_fenv.h>
+
+#ifdef __GNUC_GNU_INLINE__
+#error "This file must be compiled with C99 'inline' semantics"
+#endif
+
+const fenv_t __fe_dfl_env = {
+ __INITIAL_NPXCW__,
+ 0x0000,
+ 0x0000,
+ 0x1f80,
+ 0xffffffff,
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff }
+};
+
+enum __sse_support __has_sse =
+#ifdef __SSE__
+ __SSE_YES;
+#else
+ __SSE_UNK;
+#endif
+
+#define getfl(x) __asm __volatile("pushfl\n\tpopl %0" : "=mr" (*(x)))
+#define setfl(x) __asm __volatile("pushl %0\n\tpopfl" : : "g" (x))
+#define cpuid_dx(x) __asm __volatile("pushl %%ebx\n\tmovl $1, %%eax\n\t" \
+ "cpuid\n\tpopl %%ebx" \
+ : "=d" (*(x)) : : "eax", "ecx")
+
+/*
+ * Test for SSE support on this processor. We need to do this because
+ * we need to use ldmxcsr/stmxcsr to get correct results if any part
+ * of the program was compiled to use SSE floating-point, but we can't
+ * use SSE on older processors.
+ */
+int
+__test_sse(void)
+{
+ int flag, nflag;
+ int dx_features;
+
+ /* Am I a 486? */
+ getfl(&flag);
+ nflag = flag ^ 0x200000;
+ setfl(nflag);
+ getfl(&nflag);
+ if (flag != nflag) {
+ /* Not a 486, so CPUID should work. */
+ cpuid_dx(&dx_features);
+ if (dx_features & 0x2000000) {
+ __has_sse = __SSE_YES;
+ return (1);
+ }
+ }
+ __has_sse = __SSE_NO;
+ return (0);
+}
+
+extern inline OLM_DLLEXPORT int feclearexcept(int __excepts);
+extern inline OLM_DLLEXPORT int fegetexceptflag(fexcept_t *__flagp, int __excepts);
+
+OLM_DLLEXPORT int
+fesetexceptflag(const fexcept_t *flagp, int excepts)
+{
+ fenv_t env;
+ uint32_t mxcsr;
+
+ __fnstenv(&env);
+ env.__status &= ~excepts;
+ env.__status |= *flagp & excepts;
+ __fldenv(env);
+
+ if (__HAS_SSE()) {
+ __stmxcsr(&mxcsr);
+ mxcsr &= ~excepts;
+ mxcsr |= *flagp & excepts;
+ __ldmxcsr(mxcsr);
+ }
+
+ return (0);
+}
+
+OLM_DLLEXPORT int
+feraiseexcept(int excepts)
+{
+ fexcept_t ex = excepts;
+
+ fesetexceptflag(&ex, excepts);
+ __fwait();
+ return (0);
+}
+
+extern inline OLM_DLLEXPORT int fetestexcept(int __excepts);
+extern inline OLM_DLLEXPORT int fegetround(void);
+extern inline OLM_DLLEXPORT int fesetround(int __round);
+
+int
+fegetenv(fenv_t *envp)
+{
+ uint32_t mxcsr;
+
+ __fnstenv(envp);
+ /*
+ * fnstenv masks all exceptions, so we need to restore
+ * the old control word to avoid this side effect.
+ */
+ __fldcw(envp->__control);
+ if (__HAS_SSE()) {
+ __stmxcsr(&mxcsr);
+ __set_mxcsr(*envp, mxcsr);
+ }
+ return (0);
+}
+
+int
+feholdexcept(fenv_t *envp)
+{
+ uint32_t mxcsr;
+
+ __fnstenv(envp);
+ __fnclex();
+ if (__HAS_SSE()) {
+ __stmxcsr(&mxcsr);
+ __set_mxcsr(*envp, mxcsr);
+ mxcsr &= ~FE_ALL_EXCEPT;
+ mxcsr |= FE_ALL_EXCEPT << _SSE_EMASK_SHIFT;
+ __ldmxcsr(mxcsr);
+ }
+ return (0);
+}
+
+extern inline OLM_DLLEXPORT int fesetenv(const fenv_t *__envp);
+
+OLM_DLLEXPORT int
+feupdateenv(const fenv_t *envp)
+{
+ uint32_t mxcsr;
+ uint16_t status;
+
+ __fnstsw(&status);
+ if (__HAS_SSE())
+ __stmxcsr(&mxcsr);
+ else
+ mxcsr = 0;
+ fesetenv(envp);
+ feraiseexcept((mxcsr | status) & FE_ALL_EXCEPT);
+ return (0);
+}
+
+int
+feenableexcept(int mask)
+{
+ uint32_t mxcsr, omask;
+ uint16_t control;
+
+ mask &= FE_ALL_EXCEPT;
+ __fnstcw(&control);
+ if (__HAS_SSE())
+ __stmxcsr(&mxcsr);
+ else
+ mxcsr = 0;
+ omask = ~(control | mxcsr >> _SSE_EMASK_SHIFT) & FE_ALL_EXCEPT;
+ control &= ~mask;
+ __fldcw(control);
+ if (__HAS_SSE()) {
+ mxcsr &= ~(mask << _SSE_EMASK_SHIFT);
+ __ldmxcsr(mxcsr);
+ }
+ return (omask);
+}
+
+int
+fedisableexcept(int mask)
+{
+ uint32_t mxcsr, omask;
+ uint16_t control;
+
+ mask &= FE_ALL_EXCEPT;
+ __fnstcw(&control);
+ if (__HAS_SSE())
+ __stmxcsr(&mxcsr);
+ else
+ mxcsr = 0;
+ omask = ~(control | mxcsr >> _SSE_EMASK_SHIFT) & FE_ALL_EXCEPT;
+ control |= mask;
+ __fldcw(control);
+ if (__HAS_SSE()) {
+ mxcsr |= mask << _SSE_EMASK_SHIFT;
+ __ldmxcsr(mxcsr);
+ }
+ return (omask);
+}
--- /dev/null
+/*-
+ * Copyright (c) 2008 David Schultz <das@FreeBSD.ORG>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+//__FBSDID("$FreeBSD: src/lib/msun/i387/invtrig.c,v 1.1 2008/08/02 03:56:22 das Exp $");
+
+#include <stdint.h>
+
+#define STRUCT_DECLS
+#include "invtrig.h"
+
+/*
+ * asinl() and acosl()
+ */
+const LONGDOUBLE
+pS0 = { 0xaaaaaaaaaaaaaaa8ULL, 0x3ffcU }, /* 1.66666666666666666631e-01L */
+pS1 = { 0xd5271b6699b48bfaULL, 0xbffdU }, /* -4.16313987993683104320e-01L */
+pS2 = { 0xbcf67ca9e9f669cfULL, 0x3ffdU }, /* 3.69068046323246813704e-01L */
+pS3 = { 0x8b7baa3d15f9830dULL, 0xbffcU }, /* -1.36213932016738603108e-01L */
+pS4 = { 0x92154b093a3bff1cULL, 0x3ff9U }, /* 1.78324189708471965733e-02L */
+pS5 = { 0xe5dd76401964508cULL, 0xbff2U }, /* -2.19216428382605211588e-04L */
+pS6 = { 0xee69c5b0fdb76951ULL, 0xbfedU }, /* -7.10526623669075243183e-06L */
+qS1 = { 0xbcaa2159c01436a0ULL, 0xc000U }, /* -2.94788392796209867269e+00L */
+qS2 = { 0xd17a73d1e1564c29ULL, 0x4000U }, /* 3.27309890266528636716e+00L */
+qS3 = { 0xd767e411c9cf4c2cULL, 0xbfffU }, /* -1.68285799854822427013e+00L */
+qS4 = { 0xc809c0dfb9b0d0b7ULL, 0x3ffdU }, /* 3.90699412641738801874e-01L */
+qS5 = { 0x80c3a2197c8ced57ULL, 0xbffaU }; /* -3.14365703596053263322e-02L */
+
+/*
+ * atanl()
+ */
+const LONGDOUBLE atanhi[] = {
+ { 0xed63382b0dda7b45ULL, 0x3ffdU }, /* 4.63647609000806116202e-01L */
+ { 0xc90fdaa22168c235ULL, 0x3ffeU }, /* 7.85398163397448309628e-01L */
+ { 0xfb985e940fb4d900ULL, 0x3ffeU }, /* 9.82793723247329067960e-01L */
+ { 0xc90fdaa22168c235ULL, 0x3fffU }, /* 1.57079632679489661926e+00L */
+};
+
+const LONGDOUBLE atanlo[] = {
+ { 0xdfc88bd978751a07ULL, 0x3fbcU }, /* 1.18469937025062860669e-20L */
+ { 0xece675d1fc8f8cbbULL, 0xbfbcU }, /* -1.25413940316708300586e-20L */
+ { 0xf10f5e197793c283ULL, 0x3fbdU }, /* 2.55232234165405176172e-20L */
+ { 0xece675d1fc8f8cbbULL, 0xbfbdU }, /* -2.50827880633416601173e-20L */
+};
+
+const LONGDOUBLE aT[] = {
+ { 0xaaaaaaaaaaaaaa9fULL, 0x3ffdU }, /* 3.33333333333333333017e-01L */
+ { 0xcccccccccccc62bcULL, 0xbffcU }, /* -1.99999999999999632011e-01L */
+ { 0x9249249248b81e3fULL, 0x3ffcU }, /* 1.42857142857046531280e-01L */
+ { 0xe38e38e3316f3de5ULL, 0xbffbU }, /* -1.11111111100562372733e-01L */
+ { 0xba2e8b8dc280726aULL, 0x3ffbU }, /* 9.09090902935647302252e-02L */
+ { 0x9d89d5b4c6847ec4ULL, 0xbffbU }, /* -7.69230552476207730353e-02L */
+ { 0x8888461d3099c677ULL, 0x3ffbU }, /* 6.66661718042406260546e-02L */
+ { 0xf0e8ee0f5328dc29ULL, 0xbffaU }, /* -5.88158892835030888692e-02L */
+ { 0xd73ea84d24bae54aULL, 0x3ffaU }, /* 5.25499891539726639379e-02L */
+ { 0xc08fa381dcd9213aULL, 0xbffaU }, /* -4.70119845393155721494e-02L */
+ { 0xa54a26f4095f2a3aULL, 0x3ffaU }, /* 4.03539201366454414072e-02L */
+ { 0xeea2d8d059ef3ad6ULL, 0xbff9U }, /* -2.91303858419364158725e-02L */
+ { 0xcc82292ab894b051ULL, 0x3ff8U }, /* 1.24822046299269234080e-02L */
+};
+
+const LONGDOUBLE
+pi_lo = { 0xece675d1fc8f8cbbULL, 0xbfbeU }; /* -5.01655761266833202345e-20L */
--- /dev/null
+/*
+ * Written by:
+ * J.T. Conklin (jtc@netbsd.org)
+ * Public domain.
+ */
+
+#include <i387/bsd_asm.h>
+
+ENTRY(ceil)
+ pushl %ebp
+ movl %esp,%ebp
+ subl $8,%esp
+
+ fstcw -4(%ebp) /* store fpu control word */
+ movw -4(%ebp),%dx
+ orw $0x0800,%dx /* round towards +oo */
+ andw $0xfbff,%dx
+ movw %dx,-8(%ebp)
+ fldcw -8(%ebp) /* load modfied control word */
+
+ fldl 8(%ebp); /* round */
+ frndint
+
+ fldcw -4(%ebp) /* restore original control word */
+
+ leave
+ ret
+END(ceil)
+
+
+/* Enable stack protection */
+#if defined(__ELF__)
+.section .note.GNU-stack,"",%progbits
+#endif
--- /dev/null
+/*
+ * Written by J.T. Conklin <jtc@netbsd.org>.
+ * Public domain.
+ */
+
+#include <i387/bsd_asm.h>
+
+//__FBSDID("$FreeBSD: src/lib/msun/i387/s_ceilf.S,v 1.4 2011/01/07 16:13:12 kib Exp $");
+/* RCSID("$NetBSD: s_ceilf.S,v 1.3 1995/05/08 23:52:44 jtc Exp $") */
+
+ENTRY(ceilf)
+ pushl %ebp
+ movl %esp,%ebp
+ subl $8,%esp
+
+ fstcw -4(%ebp) /* store fpu control word */
+ movw -4(%ebp),%dx
+ orw $0x0800,%dx /* round towards +oo */
+ andw $0xfbff,%dx
+ movw %dx,-8(%ebp)
+ fldcw -8(%ebp) /* load modfied control word */
+
+ flds 8(%ebp); /* round */
+ frndint
+
+ fldcw -4(%ebp) /* restore original control word */
+
+ leave
+ ret
+END(ceilf)
+
+
+/* Enable stack protection */
+#if defined(__ELF__)
+.section .note.GNU-stack,"",%progbits
+#endif
--- /dev/null
+/*
+ * Based on code written by J.T. Conklin <jtc@NetBSD.org>.
+ * Public domain.
+ */
+
+#include <i387/bsd_asm.h>
+//__FBSDID("$FreeBSD: src/lib/msun/i387/s_ceill.S,v 1.3 2011/01/07 16:13:12 kib Exp $")
+
+ENTRY(ceill)
+ pushl %ebp
+ movl %esp,%ebp
+ subl $8,%esp
+
+ fstcw -4(%ebp) /* store fpu control word */
+ movw -4(%ebp),%dx
+ orw $0x0800,%dx /* round towards +oo */
+ andw $0xfbff,%dx
+ movw %dx,-8(%ebp)
+ fldcw -8(%ebp) /* load modfied control word */
+
+ fldt 8(%ebp) /* round */
+ frndint
+
+ fldcw -4(%ebp) /* restore original control word */
+
+ leave
+ ret
+END(ceill)
+
+
+/* Enable stack protection */
+#if defined(__ELF__)
+.section .note.GNU-stack,"",%progbits
+#endif
--- /dev/null
+/*
+ * Written by:
+ * J.T. Conklin (jtc@netbsd.org)
+ * Public domain.
+ */
+
+#include <i387/bsd_asm.h>
+//__FBSDID("$FreeBSD: src/lib/msun/i387/s_copysign.S,v 1.9 2011/01/07 16:13:12 kib Exp $")
+
+ENTRY(copysign)
+ movl 16(%esp),%edx
+ andl $0x80000000,%edx
+ movl 8(%esp),%eax
+ andl $0x7fffffff,%eax
+ orl %edx,%eax
+ movl %eax,8(%esp)
+ fldl 4(%esp)
+ ret
+END(copysign)
+
+
+/* Enable stack protection */
+#if defined(__ELF__)
+.section .note.GNU-stack,"",%progbits
+#endif
--- /dev/null
+/*
+ * Written by J.T. Conklin <jtc@netbsd.org>.
+ * Public domain.
+ */
+
+#include <i387/bsd_asm.h>
+
+//__FBSDID("$FreeBSD: src/lib/msun/i387/s_copysignf.S,v 1.3 2011/01/07 16:13:12 kib Exp $");
+/* RCSID("$NetBSD: s_copysignf.S,v 1.3 1995/05/08 23:53:25 jtc Exp $") */
+
+ENTRY(copysignf)
+ movl 8(%esp),%edx
+ andl $0x80000000,%edx
+ movl 4(%esp),%eax
+ andl $0x7fffffff,%eax
+ orl %edx,%eax
+ movl %eax,4(%esp)
+ flds 4(%esp)
+ ret
+END(copysignf)
+
+
+/* Enable stack protection */
+#if defined(__ELF__)
+.section .note.GNU-stack,"",%progbits
+#endif
--- /dev/null
+/*
+ * Based on code written by J.T. Conklin <jtc@NetBSD.org>.
+ * Public domain.
+ */
+
+#include <i387/bsd_asm.h>
+//__FBSDID("$FreeBSD: src/lib/msun/i387/s_copysignl.S,v 1.3 2011/01/07 16:13:12 kib Exp $")
+
+ENTRY(copysignl)
+ movl 24(%esp),%edx
+ andl $0x8000,%edx
+ movl 12(%esp),%eax
+ andl $0x7fff,%eax
+ orl %edx,%eax
+ movl %eax,12(%esp)
+ fldt 4(%esp)
+ ret
+END(copysignl)
+
+
+/* Enable stack protection */
+#if defined(__ELF__)
+.section .note.GNU-stack,"",%progbits
+#endif
--- /dev/null
+/*
+ * Written by:
+ * J.T. Conklin (jtc@netbsd.org)
+ * Public domain.
+ */
+
+#include <i387/bsd_asm.h>
+//__FBSDID("$FreeBSD: src/lib/msun/i387/s_cos.S,v 1.9 2011/01/07 16:13:12 kib Exp $")
+
+ENTRY(cos)
+ fldl 4(%esp)
+ fcos
+ fnstsw %ax
+ andw $0x400,%ax
+ jnz 1f
+ ret
+1: fldpi
+ fadd %st(0)
+ fxch %st(1)
+2: fprem1
+ fnstsw %ax
+ andw $0x400,%ax
+ jnz 2b
+ fstp %st(1)
+ fcos
+ ret
+END(cos)
+
+
+/* Enable stack protection */
+#if defined(__ELF__)
+.section .note.GNU-stack,"",%progbits
+#endif
--- /dev/null
+/*
+ * Written by:
+ * J.T. Conklin (jtc@netbsd.org)
+ * Public domain.
+ */
+
+#include <i387/bsd_asm.h>
+//__FBSDID("$FreeBSD: src/lib/msun/i387/s_floor.S,v 1.10 2011/01/07 16:13:12 kib Exp $")
+
+ENTRY(floor)
+ pushl %ebp
+ movl %esp,%ebp
+ subl $8,%esp
+
+ fstcw -4(%ebp) /* store fpu control word */
+ movw -4(%ebp),%dx
+ orw $0x0400,%dx /* round towards -oo */
+ andw $0xf7ff,%dx
+ movw %dx,-8(%ebp)
+ fldcw -8(%ebp) /* load modfied control word */
+
+ fldl 8(%ebp); /* round */
+ frndint
+
+ fldcw -4(%ebp) /* restore original control word */
+
+ leave
+ ret
+END(floor)
+
+
+/* Enable stack protection */
+#if defined(__ELF__)
+.section .note.GNU-stack,"",%progbits
+#endif
--- /dev/null
+/*
+ * Written by J.T. Conklin <jtc@netbsd.org>.
+ * Public domain.
+ */
+
+#include <i387/bsd_asm.h>
+
+//__FBSDID("$FreeBSD: src/lib/msun/i387/s_floorf.S,v 1.4 2011/01/07 16:13:12 kib Exp $");
+/* RCSID("$NetBSD: s_floorf.S,v 1.3 1995/05/09 00:04:32 jtc Exp $") */
+
+ENTRY(floorf)
+ pushl %ebp
+ movl %esp,%ebp
+ subl $8,%esp
+
+ fstcw -4(%ebp) /* store fpu control word */
+ movw -4(%ebp),%dx
+ orw $0x0400,%dx /* round towards -oo */
+ andw $0xf7ff,%dx
+ movw %dx,-8(%ebp)
+ fldcw -8(%ebp) /* load modfied control word */
+
+ flds 8(%ebp); /* round */
+ frndint
+
+ fldcw -4(%ebp) /* restore original control word */
+
+ leave
+ ret
+END(floorf)
+
+
+/* Enable stack protection */
+#if defined(__ELF__)
+.section .note.GNU-stack,"",%progbits
+#endif
--- /dev/null
+/*
+ * Based on code written by J.T. Conklin <jtc@NetBSD.org>.
+ * Public domain.
+ */
+
+#include <i387/bsd_asm.h>
+//__FBSDID("$FreeBSD: src/lib/msun/i387/s_floorl.S,v 1.3 2011/01/07 16:13:12 kib Exp $")
+
+ENTRY(floorl)
+ pushl %ebp
+ movl %esp,%ebp
+ subl $8,%esp
+
+ fstcw -4(%ebp) /* store fpu control word */
+ movw -4(%ebp),%dx
+ orw $0x0400,%dx /* round towards -oo */
+ andw $0xf7ff,%dx
+ movw %dx,-8(%ebp)
+ fldcw -8(%ebp) /* load modfied control word */
+
+ fldt 8(%ebp) /* round */
+ frndint
+
+ fldcw -4(%ebp) /* restore original control word */
+
+ leave
+ ret
+END(floorl)
+
+
+/* Enable stack protection */
+#if defined(__ELF__)
+.section .note.GNU-stack,"",%progbits
+#endif
--- /dev/null
+/*-
+ * Copyright (c) 2005 David Schultz <das@FreeBSD.ORG>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <i387/bsd_asm.h>
+//__FBSDID("$FreeBSD: src/lib/msun/i387/s_llrint.S,v 1.3 2011/01/07 16:13:12 kib Exp $");
+
+ENTRY(llrint)
+ fldl 4(%esp)
+ subl $8,%esp
+ fistpll (%esp)
+ popl %eax
+ popl %edx
+ ret
+END(llrint)
+
+
+/* Enable stack protection */
+#if defined(__ELF__)
+.section .note.GNU-stack,"",%progbits
+#endif
--- /dev/null
+/*-
+ * Copyright (c) 2005 David Schultz <das@FreeBSD.ORG>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <i387/bsd_asm.h>
+//__FBSDID("$FreeBSD: src/lib/msun/i387/s_llrintf.S,v 1.3 2011/01/07 16:13:12 kib Exp $")
+
+ENTRY(llrintf)
+ flds 4(%esp)
+ subl $8,%esp
+ fistpll (%esp)
+ popl %eax
+ popl %edx
+ ret
+END(llrintf)
+
+
+/* Enable stack protection */
+#if defined(__ELF__)
+.section .note.GNU-stack,"",%progbits
+#endif
--- /dev/null
+/*-
+ * Copyright (c) 2005 David Schultz <das@FreeBSD.ORG>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <i387/bsd_asm.h>
+//__FBSDID("$FreeBSD: src/lib/msun/i387/s_llrintl.S,v 1.2 2011/01/07 16:13:12 kib Exp $");
+
+ENTRY(llrintl)
+ fldt 4(%esp)
+ subl $8,%esp
+ fistpll (%esp)
+ popl %eax
+ popl %edx
+ ret
+
+
+/* Enable stack protection */
+#if defined(__ELF__)
+.section .note.GNU-stack,"",%progbits
+#endif
--- /dev/null
+/*
+ * Written by:
+ * J.T. Conklin (jtc@netbsd.org)
+ * Public domain.
+ */
+
+#include <i387/bsd_asm.h>
+//__FBSDID("$FreeBSD: src/lib/msun/i387/s_logb.S,v 1.10 2011/01/07 16:13:12 kib Exp $")
+
+ENTRY(logb)
+ fldl 4(%esp)
+ fxtract
+ fstp %st
+ ret
+END(logb)
+
+
+/* Enable stack protection */
+#if defined(__ELF__)
+.section .note.GNU-stack,"",%progbits
+#endif
--- /dev/null
+/*
+ * Written by J.T. Conklin <jtc@netbsd.org>.
+ * Public domain.
+ */
+
+#include <i387/bsd_asm.h>
+
+//__FBSDID("$FreeBSD: src/lib/msun/i387/s_logbf.S,v 1.3 2011/01/07 16:13:12 kib Exp $");
+/* RCSID("$NetBSD: s_logbf.S,v 1.3 1995/05/09 00:15:12 jtc Exp $") */
+
+ENTRY(logbf)
+ flds 4(%esp)
+ fxtract
+ fstp %st
+ ret
+END(logbf)
+
+
+/* Enable stack protection */
+#if defined(__ELF__)
+.section .note.GNU-stack,"",%progbits
+#endif
--- /dev/null
+/*
+ * Written by:
+ * J.T. Conklin (jtc@netbsd.org)
+ * Public domain.
+ */
+
+#include <i387/bsd_asm.h>
+//__FBSDID("$FreeBSD: src/lib/msun/i387/s_logbl.S,v 1.3 2011/01/07 16:13:12 kib Exp $")
+
+ENTRY(logbl)
+ fldt 4(%esp)
+ fxtract
+ fstp %st
+ ret
+
+
+/* Enable stack protection */
+#if defined(__ELF__)
+.section .note.GNU-stack,"",%progbits
+#endif
--- /dev/null
+/*-
+ * Copyright (c) 2005 David Schultz <das@FreeBSD.ORG>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <i387/bsd_asm.h>
+//__FBSDID("$FreeBSD: src/lib/msun/i387/s_lrint.S,v 1.3 2011/01/07 16:13:12 kib Exp $");
+
+ENTRY(lrint)
+ fldl 4(%esp)
+ subl $4,%esp
+ fistpl (%esp)
+ popl %eax
+ ret
+END(lrint)
+
+
+/* Enable stack protection */
+#if defined(__ELF__)
+.section .note.GNU-stack,"",%progbits
+#endif
--- /dev/null
+/*-
+ * Copyright (c) 2005 David Schultz <das@FreeBSD.ORG>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <i387/bsd_asm.h>
+//__FBSDID("$FreeBSD: src/lib/msun/i387/s_lrintf.S,v 1.3 2011/01/07 16:13:12 kib Exp $")
+
+ENTRY(lrintf)
+ flds 4(%esp)
+ subl $4,%esp
+ fistpl (%esp)
+ popl %eax
+ ret
+END(lrintf)
+
+
+/* Enable stack protection */
+#if defined(__ELF__)
+.section .note.GNU-stack,"",%progbits
+#endif
--- /dev/null
+/*-
+ * Copyright (c) 2008 David Schultz <das@FreeBSD.ORG>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <i387/bsd_asm.h>
+//__FBSDID("$FreeBSD: src/lib/msun/i387/s_lrintl.S,v 1.2 2011/01/07 16:13:12 kib Exp $");
+
+ENTRY(lrintl)
+ fldt 4(%esp)
+ subl $4,%esp
+ fistpl (%esp)
+ popl %eax
+ ret
+
+
+/* Enable stack protection */
+#if defined(__ELF__)
+.section .note.GNU-stack,"",%progbits
+#endif
--- /dev/null
+/*-
+ * Copyright (c) 2005 David Schultz <das@FreeBSD.ORG>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Based on public-domain remainder routine by J.T. Conklin <jtc@NetBSD.org>.
+ */
+
+#include <i387/bsd_asm.h>
+//__FBSDID("$FreeBSD: src/lib/msun/i387/s_remquo.S,v 1.3 2011/01/07 16:13:12 kib Exp $");
+
+ENTRY(remquo)
+ fldl 12(%esp)
+ fldl 4(%esp)
+1: fprem1
+ fstsw %ax
+ sahf
+ jp 1b
+ fstp %st(1)
+/* Extract the three low-order bits of the quotient from C0,C3,C1. */
+ shrl $6,%eax
+ movl %eax,%ecx
+ andl $0x108,%eax
+ rorl $7,%eax
+ orl %eax,%ecx
+ roll $4,%eax
+ orl %ecx,%eax
+ andl $7,%eax
+/* Negate the quotient bits if x*y<0. Avoid using an unpredictable branch. */
+ movl 16(%esp),%ecx
+ xorl 8(%esp),%ecx
+ sarl $16,%ecx
+ sarl $16,%ecx
+ xorl %ecx,%eax
+ andl $1,%ecx
+ addl %ecx,%eax
+/* Store the quotient and return. */
+ movl 20(%esp),%ecx
+ movl %eax,(%ecx)
+ ret
+END(remquo)
+
+
+/* Enable stack protection */
+#if defined(__ELF__)
+.section .note.GNU-stack,"",%progbits
+#endif
--- /dev/null
+/*-
+ * Copyright (c) 2005 David Schultz <das@FreeBSD.ORG>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Based on public-domain remainder routine by J.T. Conklin <jtc@NetBSD.org>.
+ */
+
+#include <i387/bsd_asm.h>
+//__FBSDID("$FreeBSD: src/lib/msun/i387/s_remquof.S,v 1.3 2011/01/07 16:13:12 kib Exp $");
+
+ENTRY(remquof)
+ flds 8(%esp)
+ flds 4(%esp)
+1: fprem1
+ fstsw %ax
+ sahf
+ jp 1b
+ fstp %st(1)
+/* Extract the three low-order bits of the quotient from C0,C3,C1. */
+ shrl $6,%eax
+ movl %eax,%ecx
+ andl $0x108,%eax
+ rorl $7,%eax
+ orl %eax,%ecx
+ roll $4,%eax
+ orl %ecx,%eax
+ andl $7,%eax
+/* Negate the quotient bits if x*y<0. Avoid using an unpredictable branch. */
+ movl 8(%esp),%ecx
+ xorl 4(%esp),%ecx
+ sarl $16,%ecx
+ sarl $16,%ecx
+ xorl %ecx,%eax
+ andl $1,%ecx
+ addl %ecx,%eax
+/* Store the quotient and return. */
+ movl 12(%esp),%ecx
+ movl %eax,(%ecx)
+ ret
+END(remquof)
+
+
+/* Enable stack protection */
+#if defined(__ELF__)
+.section .note.GNU-stack,"",%progbits
+#endif
--- /dev/null
+/*-
+ * Copyright (c) 2005-2008 David Schultz <das@FreeBSD.ORG>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Based on public-domain remainder routine by J.T. Conklin <jtc@NetBSD.org>.
+ */
+
+#include <i387/bsd_asm.h>
+//__FBSDID("$FreeBSD: src/lib/msun/i387/s_remquol.S,v 1.2 2011/01/07 16:13:12 kib Exp $");
+
+ENTRY(remquol)
+ fldt 16(%esp)
+ fldt 4(%esp)
+1: fprem1
+ fstsw %ax
+ sahf
+ jp 1b
+ fstp %st(1)
+/* Extract the three low-order bits of the quotient from C0,C3,C1. */
+ shrl $6,%eax
+ movl %eax,%ecx
+ andl $0x108,%eax
+ rorl $7,%eax
+ orl %eax,%ecx
+ roll $4,%eax
+ orl %ecx,%eax
+ andl $7,%eax
+/* Negate the quotient bits if x*y<0. Avoid using an unpredictable branch. */
+ movl 24(%esp),%ecx
+ xorl 12(%esp),%ecx
+ movsx %cx,%ecx
+ sarl $16,%ecx
+ sarl $16,%ecx
+ xorl %ecx,%eax
+ andl $1,%ecx
+ addl %ecx,%eax
+/* Store the quotient and return. */
+ movl 28(%esp),%ecx
+ movl %eax,(%ecx)
+ ret
+
+
+/* Enable stack protection */
+#if defined(__ELF__)
+.section .note.GNU-stack,"",%progbits
+#endif
--- /dev/null
+/*
+ * Written by:
+ * J.T. Conklin (jtc@netbsd.org)
+ * Public domain.
+ */
+
+#include <i387/bsd_asm.h>
+//__FBSDID("$FreeBSD: src/lib/msun/i387/s_rint.S,v 1.9 2011/01/07 16:13:12 kib Exp $")
+
+ENTRY(rint)
+ fldl 4(%esp)
+ frndint
+ ret
+END(rint)
+
+
+/* Enable stack protection */
+#if defined(__ELF__)
+.section .note.GNU-stack,"",%progbits
+#endif
--- /dev/null
+/*
+ * Written by J.T. Conklin <jtc@netbsd.org>.
+ * Public domain.
+ */
+
+#include <i387/bsd_asm.h>
+
+//__FBSDID("$FreeBSD: src/lib/msun/i387/s_rintf.S,v 1.3 2011/01/07 16:13:12 kib Exp $");
+/* RCSID("$NetBSD: s_rintf.S,v 1.3 1995/05/09 00:17:22 jtc Exp $") */
+
+ENTRY(rintf)
+ flds 4(%esp)
+ frndint
+ ret
+END(rintf)
+
+
+/* Enable stack protection */
+#if defined(__ELF__)
+.section .note.GNU-stack,"",%progbits
+#endif
--- /dev/null
+/*
+ * Written by:
+ * J.T. Conklin (jtc@netbsd.org)
+ * Public domain.
+ */
+
+#include <i387/bsd_asm.h>
+//__FBSDID("$FreeBSD: src/lib/msun/i387/s_rintl.S,v 1.3 2011/01/07 16:13:12 kib Exp $")
+
+ENTRY(rintl)
+ fldt 4(%esp)
+ frndint
+ ret
+
+
+/* Enable stack protection */
+#if defined(__ELF__)
+.section .note.GNU-stack,"",%progbits
+#endif
--- /dev/null
+/*
+ * Written by:
+ * J.T. Conklin (jtc@netbsd.org)
+ * Public domain.
+ */
+
+#include <i387/bsd_asm.h>
+//__FBSDID("$FreeBSD: src/lib/msun/i387/s_scalbn.S,v 1.10 2011/01/07 16:13:12 kib Exp $")
+
+ENTRY(scalbn)
+ fildl 12(%esp)
+ fldl 4(%esp)
+ fscale
+ fstp %st(1)
+ ret
+END(scalbn)
+
+.globl CNAME(ldexp)
+.set CNAME(ldexp),CNAME(scalbn)
+/* Enable stack protection */
+#if defined(__ELF__)
+.section .note.GNU-stack,"",%progbits
+#endif
--- /dev/null
+/*
+ * Written by J.T. Conklin <jtc@netbsd.org>.
+ * Public domain.
+ */
+
+#include <i387/bsd_asm.h>
+
+//__FBSDID("$FreeBSD: src/lib/msun/i387/s_scalbnf.S,v 1.4 2011/01/07 16:13:12 kib Exp $");
+/* RCSID("$NetBSD: s_scalbnf.S,v 1.4 1999/01/02 05:15:40 kristerw Exp $") */
+
+ENTRY(scalbnf)
+ fildl 8(%esp)
+ flds 4(%esp)
+ fscale
+ fstp %st(1) /* bug fix for fp stack overflow */
+ ret
+END(scalbnf)
+
+.globl CNAME(ldexpf)
+.set CNAME(ldexpf),CNAME(scalbnf)
+
+
+/* Enable stack protection */
+#if defined(__ELF__)
+.section .note.GNU-stack,"",%progbits
+#endif
--- /dev/null
+/*
+ * Written by J.T. Conklin <jtc@netbsd.org>.
+ * Public domain.
+ */
+
+#include <i387/bsd_asm.h>
+
+//__FBSDID("$FreeBSD: src/lib/msun/i387/s_scalbnl.S,v 1.3 2011/01/07 16:13:12 kib Exp $");
+/* RCSID("$NetBSD: s_scalbnf.S,v 1.4 1999/01/02 05:15:40 kristerw Exp $") */
+
+ENTRY(scalbnl)
+ fildl 16(%esp)
+ fldt 4(%esp)
+ fscale
+ fstp %st(1)
+ ret
+END(scalbnl)
+
+.globl CNAME(ldexpl)
+.set CNAME(ldexpl),CNAME(scalbnl)
+
+
+/* Enable stack protection */
+#if defined(__ELF__)
+.section .note.GNU-stack,"",%progbits
+#endif
--- /dev/null
+/*
+ * Written by:
+ * J.T. Conklin (jtc@netbsd.org)
+ * Public domain.
+ */
+
+#include <i387/bsd_asm.h>
+//__FBSDID("$FreeBSD: src/lib/msun/i387/s_sin.S,v 1.9 2011/01/07 16:13:12 kib Exp $")
+
+ENTRY(sin)
+ fldl 4(%esp)
+ fsin
+ fnstsw %ax
+ andw $0x400,%ax
+ jnz 1f
+ ret
+1: fldpi
+ fadd %st(0)
+ fxch %st(1)
+2: fprem1
+ fnstsw %ax
+ andw $0x400,%ax
+ jnz 2b
+ fstp %st(1)
+ fsin
+ ret
+END(sin)
+
+
+/* Enable stack protection */
+#if defined(__ELF__)
+.section .note.GNU-stack,"",%progbits
+#endif
--- /dev/null
+/*
+ * Written by:
+ * J.T. Conklin (jtc@netbsd.org)
+ * Public domain.
+ */
+
+#include <i387/bsd_asm.h>
+//__FBSDID("$FreeBSD: src/lib/msun/i387/s_tan.S,v 1.9 2011/01/07 16:13:12 kib Exp $")
+
+ENTRY(tan)
+ fldl 4(%esp)
+ fptan
+ fnstsw %ax
+ andw $0x400,%ax
+ jnz 1f
+ fstp %st(0)
+ ret
+1: fldpi
+ fadd %st(0)
+ fxch %st(1)
+2: fprem1
+ fstsw %ax
+ andw $0x400,%ax
+ jnz 2b
+ fstp %st(1)
+ fptan
+ fstp %st(0)
+ ret
+END(tan)
+
+
+/* Enable stack protection */
+#if defined(__ELF__)
+.section .note.GNU-stack,"",%progbits
+#endif
--- /dev/null
+/*
+ * Based on code written by J.T. Conklin <jtc@NetBSD.org>.
+ * Public domain.
+ */
+
+#include <i387/bsd_asm.h>
+//__FBSDID("$FreeBSD: src/lib/msun/i387/s_trunc.S,v 1.3 2011/01/07 16:13:12 kib Exp $")
+
+ENTRY(trunc)
+ pushl %ebp
+ movl %esp,%ebp
+ subl $8,%esp
+
+ fstcw -4(%ebp) /* store fpu control word */
+ movw -4(%ebp),%dx
+ orw $0x0c00,%dx /* round towards -oo */
+ movw %dx,-8(%ebp)
+ fldcw -8(%ebp) /* load modfied control word */
+
+ fldl 8(%ebp) /* round */
+ frndint
+
+ fldcw -4(%ebp) /* restore original control word */
+
+ leave
+ ret
+END(trunc)
+
+
+/* Enable stack protection */
+#if defined(__ELF__)
+.section .note.GNU-stack,"",%progbits
+#endif
--- /dev/null
+/*
+ * Based on code written by J.T. Conklin <jtc@NetBSD.org>.
+ * Public domain.
+ */
+
+#include <i387/bsd_asm.h>
+//__FBSDID("$FreeBSD: src/lib/msun/i387/s_truncf.S,v 1.4 2011/01/07 16:13:12 kib Exp $")
+
+ENTRY(truncf)
+ pushl %ebp
+ movl %esp,%ebp
+ subl $8,%esp
+
+ fstcw -4(%ebp) /* store fpu control word */
+ movw -4(%ebp),%dx
+ orw $0x0c00,%dx /* round towards -oo */
+ movw %dx,-8(%ebp)
+ fldcw -8(%ebp) /* load modfied control word */
+
+ flds 8(%ebp) /* round */
+ frndint
+
+ fldcw -4(%ebp) /* restore original control word */
+
+ leave
+ ret
+END(truncf)
+
+
+/* Enable stack protection */
+#if defined(__ELF__)
+.section .note.GNU-stack,"",%progbits
+#endif
--- /dev/null
+/*
+ * Based on code written by J.T. Conklin <jtc@NetBSD.org>.
+ * Public domain.
+ */
+
+#include <i387/bsd_asm.h>
+//__FBSDID("$FreeBSD: src/lib/msun/i387/s_truncl.S,v 1.3 2011/01/07 16:13:12 kib Exp $")
+
+ENTRY(truncl)
+ pushl %ebp
+ movl %esp,%ebp
+ subl $8,%esp
+
+ fstcw -4(%ebp) /* store fpu control word */
+ movw -4(%ebp),%dx
+ orw $0x0c00,%dx /* round towards -oo */
+ movw %dx,-8(%ebp)
+ fldcw -8(%ebp) /* load modfied control word */
+
+ fldt 8(%ebp) /* round */
+ frndint
+
+ fldcw -4(%ebp) /* restore original control word */
+
+ leave
+ ret
+END(truncl)
+
+
+/* Enable stack protection */
+#if defined(__ELF__)
+.section .note.GNU-stack,"",%progbits
+#endif
--- /dev/null
+#ifndef OPENLIBM_H
+#define OPENLIBM_H
+
+#include <openlibm_complex.h>
+#include <openlibm_fenv.h>
+#include <openlibm_math.h>
+
+#endif /* !OPENLIBM_H */
--- /dev/null
+/* $OpenBSD: complex.h,v 1.5 2014/03/16 18:38:30 guenther Exp $ */
+/*
+ * Copyright (c) 2008 Martynas Venckus <martynas@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifdef OPENLIBM_USE_HOST_COMPLEX_H
+#include <complex.h>
+#else /* !OPENLIBM_USE_HOST_COMPLEX_H */
+
+#ifndef OPENLIBM_COMPLEX_H
+#define OPENLIBM_COMPLEX_H
+
+#define complex _Complex
+
+#define _Complex_I 1.0fi
+#define I _Complex_I
+
+/*
+ * Macros that can be used to construct complex values.
+ *
+ * The C99 standard intends x+I*y to be used for this, but x+I*y is
+ * currently unusable in general since gcc introduces many overflow,
+ * underflow, sign and efficiency bugs by rewriting I*y as
+ * (0.0+I)*(y+0.0*I) and laboriously computing the full complex product.
+ * In particular, I*Inf is corrupted to NaN+I*Inf, and I*-0 is corrupted
+ * to -0.0+I*0.0.
+ *
+ * In C11, a CMPLX(x,y) macro was added to circumvent this limitation,
+ * and gcc 4.7 added a __builtin_complex feature to simplify implementation
+ * of CMPLX in libc, so we can take advantage of these features if they
+ * are available. Clang simply allows complex values to be constructed
+ * using a compound literal.
+ *
+ * If __builtin_complex is not available, resort to using inline
+ * functions instead. These can unfortunately not be used to construct
+ * compile-time constants.
+ *
+ * C99 specifies that complex numbers have the same representation as
+ * an array of two elements, where the first element is the real part
+ * and the second element is the imaginary part.
+ */
+
+#ifdef __clang__
+# define CMPLXF(x, y) ((float complex){x, y})
+# define CMPLX(x, y) ((double complex){x, y})
+# define CMPLXL(x, y) ((long double complex){x, y})
+#elif (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7)) && !defined(__INTEL_COMPILER)
+# define CMPLXF(x,y) __builtin_complex ((float) (x), (float) (y))
+# define CMPLX(x,y) __builtin_complex ((double) (x), (double) (y))
+# define CMPLXL(x,y) __builtin_complex ((long double) (x), (long double) (y))
+#else
+static inline float complex
+CMPLXF(float x, float y)
+{
+ union {
+ float a[2];
+ float complex f;
+ } z = {{ x, y }};
+
+ return (z.f);
+}
+
+static inline double complex
+CMPLX(double x, double y)
+{
+ union {
+ double a[2];
+ double complex f;
+ } z = {{ x, y }};
+
+ return (z.f);
+}
+
+static inline long double complex
+CMPLXL(long double x, long double y)
+{
+ union {
+ long double a[2];
+ long double complex f;
+ } z = {{ x, y }};
+
+ return (z.f);
+}
+#endif
+
+/*
+ * Double versions of C99 functions
+ */
+double complex cacos(double complex);
+double complex casin(double complex);
+double complex catan(double complex);
+double complex ccos(double complex);
+double complex csin(double complex);
+double complex ctan(double complex);
+double complex cacosh(double complex);
+double complex casinh(double complex);
+double complex catanh(double complex);
+double complex ccosh(double complex);
+double complex csinh(double complex);
+double complex ctanh(double complex);
+double complex cexp(double complex);
+double complex clog(double complex);
+double cabs(double complex);
+double complex cpow(double complex, double complex);
+double complex csqrt(double complex);
+double carg(double complex);
+double cimag(double complex);
+double complex conj(double complex);
+double complex cproj(double complex);
+double creal(double complex);
+
+/*
+ * Float versions of C99 functions
+ */
+float complex cacosf(float complex);
+float complex casinf(float complex);
+float complex catanf(float complex);
+float complex ccosf(float complex);
+float complex csinf(float complex);
+float complex ctanf(float complex);
+float complex cacoshf(float complex);
+float complex casinhf(float complex);
+float complex catanhf(float complex);
+float complex ccoshf(float complex);
+float complex csinhf(float complex);
+float complex ctanhf(float complex);
+float complex cexpf(float complex);
+float complex clogf(float complex);
+float cabsf(float complex);
+float complex cpowf(float complex, float complex);
+float complex csqrtf(float complex);
+float cargf(float complex);
+float cimagf(float complex);
+float complex conjf(float complex);
+float complex cprojf(float complex);
+float crealf(float complex);
+
+/*
+ * Long double versions of C99 functions
+ */
+long double complex cacosl(long double complex);
+long double complex casinl(long double complex);
+long double complex catanl(long double complex);
+long double complex ccosl(long double complex);
+long double complex csinl(long double complex);
+long double complex ctanl(long double complex);
+long double complex cacoshl(long double complex);
+long double complex casinhl(long double complex);
+long double complex catanhl(long double complex);
+long double complex ccoshl(long double complex);
+long double complex csinhl(long double complex);
+long double complex ctanhl(long double complex);
+long double complex cexpl(long double complex);
+long double complex clogl(long double complex);
+long double cabsl(long double complex);
+long double complex cpowl(long double complex,
+ long double complex);
+long double complex csqrtl(long double complex);
+long double cargl(long double complex);
+long double cimagl(long double complex);
+long double complex conjl(long double complex);
+long double complex cprojl(long double complex);
+long double creall(long double complex);
+
+#endif /* !OPENLIBM_COMPLEX_H */
+
+#endif /* OPENLIBM_USE_HOST_COMPLEX_H */
--- /dev/null
+#ifdef OPENLIBM_USE_HOST_FENV_H
+#include <fenv.h>
+#else /* !OPENLIBM_USE_HOST_FENV_H */
+
+#if defined(__aarch64__) || defined(__arm__)
+#include <openlibm_fenv_arm.h>
+#elif defined(__x86_64__)
+#include <openlibm_fenv_amd64.h>
+#elif defined(__i386__)
+#include <openlibm_fenv_i387.h>
+#elif defined(__powerpc__)
+#include <openlibm_fenv_powerpc.h>
+#elif defined(__mips__)
+#include <openlibm_fenv_mips.h>
+#else
+#error "Unsupported platform"
+#endif
+
+#endif /* OPENLIBM_USE_HOST_FENV_H */
--- /dev/null
+/*-
+ * Copyright (c) 2004-2005 David Schultz <das@FreeBSD.ORG>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: src/lib/msun/amd64/fenv.h,v 1.8 2011/10/10 15:43:09 das Exp $
+ */
+
+#ifndef _FENV_H_
+#define _FENV_H_
+
+#include "cdefs-compat.h"
+#include "types-compat.h"
+
+#include "math_private.h"
+
+#ifndef __fenv_static
+#define __fenv_static static
+#endif
+
+typedef struct {
+ struct {
+ uint32_t __control;
+ uint32_t __status;
+ uint32_t __tag;
+ char __other[16];
+ } __x87;
+ uint32_t __mxcsr;
+} fenv_t;
+
+typedef uint16_t fexcept_t;
+
+/* Exception flags */
+#define FE_INVALID 0x01
+#define FE_DENORMAL 0x02
+#define FE_DIVBYZERO 0x04
+#define FE_OVERFLOW 0x08
+#define FE_UNDERFLOW 0x10
+#define FE_INEXACT 0x20
+#define FE_ALL_EXCEPT (FE_DIVBYZERO | FE_DENORMAL | FE_INEXACT | \
+ FE_INVALID | FE_OVERFLOW | FE_UNDERFLOW)
+
+/* Rounding modes */
+#define FE_TONEAREST 0x0000
+#define FE_DOWNWARD 0x0400
+#define FE_UPWARD 0x0800
+#define FE_TOWARDZERO 0x0c00
+#define _ROUND_MASK (FE_TONEAREST | FE_DOWNWARD | \
+ FE_UPWARD | FE_TOWARDZERO)
+
+/*
+ * As compared to the x87 control word, the SSE unit's control word
+ * has the rounding control bits offset by 3 and the exception mask
+ * bits offset by 7.
+ */
+#define _SSE_ROUND_SHIFT 3
+#define _SSE_EMASK_SHIFT 7
+
+__BEGIN_DECLS
+
+/* Default floating-point environment */
+extern const fenv_t __fe_dfl_env;
+#define FE_DFL_ENV (&__fe_dfl_env)
+
+#define __fldcw(__cw) __asm __volatile("fldcw %0" : : "m" (__cw))
+#define __fldenv(__env) __asm __volatile("fldenv %0" : : "m" (__env))
+#define __fldenvx(__env) __asm __volatile("fldenv %0" : : "m" (__env) \
+ : "st", "st(1)", "st(2)", "st(3)", "st(4)", \
+ "st(5)", "st(6)", "st(7)")
+#define __fnclex() __asm __volatile("fnclex")
+#define __fnstenv(__env) __asm __volatile("fnstenv %0" : "=m" (*(__env)))
+#define __fnstcw(__cw) __asm __volatile("fnstcw %0" : "=m" (*(__cw)))
+#define __fnstsw(__sw) __asm __volatile("fnstsw %0" : "=am" (*(__sw)))
+#define __fwait() __asm __volatile("fwait")
+#define __ldmxcsr(__csr) __asm __volatile("ldmxcsr %0" : : "m" (__csr))
+#define __stmxcsr(__csr) __asm __volatile("stmxcsr %0" : "=m" (*(__csr)))
+
+__fenv_static __attribute__((always_inline)) inline int
+feclearexcept(int __excepts)
+{
+ fenv_t __env;
+
+ if (__excepts == FE_ALL_EXCEPT) {
+ __fnclex();
+ } else {
+ __fnstenv(&__env.__x87);
+ __env.__x87.__status &= ~__excepts;
+ __fldenv(__env.__x87);
+ }
+ __stmxcsr(&__env.__mxcsr);
+ __env.__mxcsr &= ~__excepts;
+ __ldmxcsr(__env.__mxcsr);
+ return (0);
+}
+
+__fenv_static inline int
+fegetexceptflag(fexcept_t *__flagp, int __excepts)
+{
+ uint32_t __mxcsr;
+ uint16_t __status;
+
+ __stmxcsr(&__mxcsr);
+ __fnstsw(&__status);
+ *__flagp = (__mxcsr | __status) & __excepts;
+ return (0);
+}
+
+OLM_DLLEXPORT int fesetexceptflag(const fexcept_t *__flagp, int __excepts);
+OLM_DLLEXPORT int feraiseexcept(int __excepts);
+
+__fenv_static __attribute__((always_inline)) inline int
+fetestexcept(int __excepts)
+{
+ uint32_t __mxcsr;
+ uint16_t __status;
+
+ __stmxcsr(&__mxcsr);
+ __fnstsw(&__status);
+ return ((__status | __mxcsr) & __excepts);
+}
+
+__fenv_static inline int
+fegetround(void)
+{
+ uint16_t __control;
+
+ /*
+ * We assume that the x87 and the SSE unit agree on the
+ * rounding mode. Reading the control word on the x87 turns
+ * out to be about 5 times faster than reading it on the SSE
+ * unit on an Opteron 244.
+ */
+ __fnstcw(&__control);
+ return (__control & _ROUND_MASK);
+}
+
+__fenv_static inline int
+fesetround(int __round)
+{
+ uint32_t __mxcsr;
+ uint16_t __control;
+
+ if (__round & ~_ROUND_MASK)
+ return (-1);
+
+ __fnstcw(&__control);
+ __control &= ~_ROUND_MASK;
+ __control |= __round;
+ __fldcw(__control);
+
+ __stmxcsr(&__mxcsr);
+ __mxcsr &= ~(_ROUND_MASK << _SSE_ROUND_SHIFT);
+ __mxcsr |= __round << _SSE_ROUND_SHIFT;
+ __ldmxcsr(__mxcsr);
+
+ return (0);
+}
+
+OLM_DLLEXPORT int fegetenv(fenv_t *__envp);
+OLM_DLLEXPORT int feholdexcept(fenv_t *__envp);
+
+__fenv_static inline int
+fesetenv(const fenv_t *__envp)
+{
+
+ /*
+ * XXX Using fldenvx() instead of fldenv() tells the compiler that this
+ * instruction clobbers the i387 register stack. This happens because
+ * we restore the tag word from the saved environment. Normally, this
+ * would happen anyway and we wouldn't care, because the ABI allows
+ * function calls to clobber the i387 regs. However, fesetenv() is
+ * inlined, so we need to be more careful.
+ */
+ __fldenvx(__envp->__x87);
+ __ldmxcsr(__envp->__mxcsr);
+ return (0);
+}
+
+OLM_DLLEXPORT int feupdateenv(const fenv_t *__envp);
+
+#if __BSD_VISIBLE
+
+OLM_DLLEXPORT int feenableexcept(int __mask);
+OLM_DLLEXPORT int fedisableexcept(int __mask);
+
+/* We currently provide no external definition of fegetexcept(). */
+static inline int
+fegetexcept(void)
+{
+ uint16_t __control;
+
+ /*
+ * We assume that the masks for the x87 and the SSE unit are
+ * the same.
+ */
+ __fnstcw(&__control);
+ return (~__control & FE_ALL_EXCEPT);
+}
+
+#endif /* __BSD_VISIBLE */
+
+__END_DECLS
+
+#endif /* !_FENV_H_ */
--- /dev/null
+/*-
+ * Copyright (c) 2004-2005 David Schultz <das@FreeBSD.ORG>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: src/lib/msun/arm/fenv.h,v 1.6 2011/10/10 15:43:09 das Exp $
+ */
+
+#ifndef _FENV_H_
+#define _FENV_H_
+
+#include <stdint.h>
+
+#include "cdefs-compat.h"
+
+#ifndef __fenv_static
+#define __fenv_static static
+#endif
+
+typedef uint32_t fenv_t;
+typedef uint32_t fexcept_t;
+
+/* Exception flags */
+#define FE_INVALID 0x0001
+#define FE_DIVBYZERO 0x0002
+#define FE_OVERFLOW 0x0004
+#define FE_UNDERFLOW 0x0008
+#define FE_INEXACT 0x0010
+#define FE_ALL_EXCEPT (FE_DIVBYZERO | FE_INEXACT | \
+ FE_INVALID | FE_OVERFLOW | FE_UNDERFLOW)
+
+/* Rounding modes */
+#define FE_TONEAREST 0x0000
+#define FE_TOWARDZERO 0x0001
+#define FE_UPWARD 0x0002
+#define FE_DOWNWARD 0x0003
+#define _ROUND_MASK (FE_TONEAREST | FE_DOWNWARD | \
+ FE_UPWARD | FE_TOWARDZERO)
+__BEGIN_DECLS
+
+/* Default floating-point environment */
+extern const fenv_t __fe_dfl_env;
+#define FE_DFL_ENV (&__fe_dfl_env)
+
+/* We need to be able to map status flag positions to mask flag positions */
+#define _FPUSW_SHIFT 16
+#define _ENABLE_MASK (FE_ALL_EXCEPT << _FPUSW_SHIFT)
+
+#if defined(__aarch64__)
+#define __rfs(__fpsr) __asm __volatile("mrs %0,fpsr" : "=r" (*(__fpsr)))
+#define __wfs(__fpsr) __asm __volatile("msr fpsr,%0" : : "r" (__fpsr))
+/* Test for hardware support for ARM floating point operations, explicitly
+checking for float and double support, see "ARM C Language Extensions", 6.5.1 */
+#elif defined(__ARM_FP) && (__ARM_FP & 0x0C) != 0
+#define __rfs(__fpsr) __asm __volatile("vmrs %0,fpscr" : "=&r" (*(__fpsr)))
+#define __wfs(__fpsr) __asm __volatile("vmsr fpscr,%0" : : "r" (__fpsr))
+#else
+#define __rfs(__fpsr) (*(__fpsr) = 0)
+#define __wfs(__fpsr)
+#endif
+
+__fenv_static inline int
+feclearexcept(int __excepts)
+{
+ fexcept_t __fpsr;
+
+ __rfs(&__fpsr);
+ __fpsr &= ~__excepts;
+ __wfs(__fpsr);
+ return (0);
+}
+
+__fenv_static inline int
+fegetexceptflag(fexcept_t *__flagp, int __excepts)
+{
+ fexcept_t __fpsr;
+
+ __rfs(&__fpsr);
+ *__flagp = __fpsr & __excepts;
+ return (0);
+}
+
+__fenv_static inline int
+fesetexceptflag(const fexcept_t *__flagp, int __excepts)
+{
+ fexcept_t __fpsr;
+
+ __rfs(&__fpsr);
+ __fpsr &= ~__excepts;
+ __fpsr |= *__flagp & __excepts;
+ __wfs(__fpsr);
+ return (0);
+}
+
+__fenv_static inline int
+feraiseexcept(int __excepts)
+{
+ fexcept_t __ex = __excepts;
+
+ fesetexceptflag(&__ex, __excepts); /* XXX */
+ return (0);
+}
+
+__fenv_static inline int
+fetestexcept(int __excepts)
+{
+ fexcept_t __fpsr;
+
+ __rfs(&__fpsr);
+ return (__fpsr & __excepts);
+}
+
+__fenv_static inline int
+fegetround(void)
+{
+
+ /*
+ * Apparently, the rounding mode is specified as part of the
+ * instruction format on ARM, so the dynamic rounding mode is
+ * indeterminate. Some FPUs may differ.
+ */
+ return (-1);
+}
+
+__fenv_static inline int
+fesetround(int __round)
+{
+
+ return (-1);
+}
+
+__fenv_static inline int
+fegetenv(fenv_t *__envp)
+{
+
+ __rfs(__envp);
+ return (0);
+}
+
+__fenv_static inline int
+feholdexcept(fenv_t *__envp)
+{
+ fenv_t __env;
+
+ __rfs(&__env);
+ *__envp = __env;
+ __env &= ~(FE_ALL_EXCEPT | _ENABLE_MASK);
+ __wfs(__env);
+ return (0);
+}
+
+__fenv_static inline int
+fesetenv(const fenv_t *__envp)
+{
+
+ __wfs(*__envp);
+ return (0);
+}
+
+__fenv_static inline int
+feupdateenv(const fenv_t *__envp)
+{
+ fexcept_t __fpsr;
+
+ __rfs(&__fpsr);
+ __wfs(*__envp);
+ feraiseexcept(__fpsr & FE_ALL_EXCEPT);
+ return (0);
+}
+
+#if __BSD_VISIBLE
+
+/* We currently provide no external definitions of the functions below. */
+
+static inline int
+feenableexcept(int __mask)
+{
+ fenv_t __old_fpsr, __new_fpsr;
+
+ __rfs(&__old_fpsr);
+ __new_fpsr = __old_fpsr | (__mask & FE_ALL_EXCEPT) << _FPUSW_SHIFT;
+ __wfs(__new_fpsr);
+ return ((__old_fpsr >> _FPUSW_SHIFT) & FE_ALL_EXCEPT);
+}
+
+static inline int
+fedisableexcept(int __mask)
+{
+ fenv_t __old_fpsr, __new_fpsr;
+
+ __rfs(&__old_fpsr);
+ __new_fpsr = __old_fpsr & ~((__mask & FE_ALL_EXCEPT) << _FPUSW_SHIFT);
+ __wfs(__new_fpsr);
+ return ((__old_fpsr >> _FPUSW_SHIFT) & FE_ALL_EXCEPT);
+}
+
+static inline int
+fegetexcept(void)
+{
+ fenv_t __fpsr;
+
+ __rfs(&__fpsr);
+ return ((__fpsr & _ENABLE_MASK) >> _FPUSW_SHIFT);
+}
+
+#endif /* __BSD_VISIBLE */
+
+__END_DECLS
+
+#endif /* !_FENV_H_ */
--- /dev/null
+/*-
+ * Copyright (c) 2004-2005 David Schultz <das@FreeBSD.ORG>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: src/lib/msun/i387/fenv.h,v 1.8 2011/10/10 15:43:09 das Exp $
+ */
+
+#ifndef _FENV_H_
+#define _FENV_H_
+
+#include "cdefs-compat.h"
+#include "types-compat.h"
+
+#ifndef __fenv_static
+#define __fenv_static static
+#endif
+
+/*
+ * To preserve binary compatibility with FreeBSD 5.3, we pack the
+ * mxcsr into some reserved fields, rather than changing sizeof(fenv_t).
+ */
+typedef struct {
+ uint16_t __control;
+ uint16_t __mxcsr_hi;
+ uint16_t __status;
+ uint16_t __mxcsr_lo;
+ uint32_t __tag;
+ char __other[16];
+} fenv_t;
+
+#define __get_mxcsr(env) (((env).__mxcsr_hi << 16) | \
+ ((env).__mxcsr_lo))
+#define __set_mxcsr(env, x) do { \
+ (env).__mxcsr_hi = (uint32_t)(x) >> 16; \
+ (env).__mxcsr_lo = (uint16_t)(x); \
+} while (0)
+
+typedef uint16_t fexcept_t;
+
+/* Exception flags */
+#define FE_INVALID 0x01
+#define FE_DENORMAL 0x02
+#define FE_DIVBYZERO 0x04
+#define FE_OVERFLOW 0x08
+#define FE_UNDERFLOW 0x10
+#define FE_INEXACT 0x20
+#define FE_ALL_EXCEPT (FE_DIVBYZERO | FE_DENORMAL | FE_INEXACT | \
+ FE_INVALID | FE_OVERFLOW | FE_UNDERFLOW)
+
+/* Rounding modes */
+#define FE_TONEAREST 0x0000
+#define FE_DOWNWARD 0x0400
+#define FE_UPWARD 0x0800
+#define FE_TOWARDZERO 0x0c00
+#define _ROUND_MASK (FE_TONEAREST | FE_DOWNWARD | \
+ FE_UPWARD | FE_TOWARDZERO)
+
+/*
+ * As compared to the x87 control word, the SSE unit's control word
+ * has the rounding control bits offset by 3 and the exception mask
+ * bits offset by 7.
+ */
+#define _SSE_ROUND_SHIFT 3
+#define _SSE_EMASK_SHIFT 7
+
+__BEGIN_DECLS
+
+/* After testing for SSE support once, we cache the result in __has_sse. */
+enum __sse_support { __SSE_YES, __SSE_NO, __SSE_UNK };
+extern enum __sse_support __has_sse;
+int __test_sse(void);
+#ifdef __SSE__
+#define __HAS_SSE() 1
+#else
+#define __HAS_SSE() (__has_sse == __SSE_YES || \
+ (__has_sse == __SSE_UNK && __test_sse()))
+#endif
+
+/* Default floating-point environment */
+extern const fenv_t __fe_dfl_env;
+#define FE_DFL_ENV (&__fe_dfl_env)
+
+#define __fldcw(__cw) __asm __volatile("fldcw %0" : : "m" (__cw))
+#define __fldenv(__env) __asm __volatile("fldenv %0" : : "m" (__env))
+#define __fldenvx(__env) __asm __volatile("fldenv %0" : : "m" (__env) \
+ : "st", "st(1)", "st(2)", "st(3)", "st(4)", \
+ "st(5)", "st(6)", "st(7)")
+#define __fnclex() __asm __volatile("fnclex")
+#define __fnstenv(__env) __asm __volatile("fnstenv %0" : "=m" (*(__env)))
+#define __fnstcw(__cw) __asm __volatile("fnstcw %0" : "=m" (*(__cw)))
+#define __fnstsw(__sw) __asm __volatile("fnstsw %0" : "=am" (*(__sw)))
+#define __fwait() __asm __volatile("fwait")
+#define __ldmxcsr(__csr) __asm __volatile("ldmxcsr %0" : : "m" (__csr))
+#define __stmxcsr(__csr) __asm __volatile("stmxcsr %0" : "=m" (*(__csr)))
+
+__fenv_static inline int
+feclearexcept(int __excepts)
+{
+ fenv_t __env;
+ uint32_t __mxcsr;
+
+ if (__excepts == FE_ALL_EXCEPT) {
+ __fnclex();
+ } else {
+ __fnstenv(&__env);
+ __env.__status &= ~__excepts;
+ __fldenv(__env);
+ }
+ if (__HAS_SSE()) {
+ __stmxcsr(&__mxcsr);
+ __mxcsr &= ~__excepts;
+ __ldmxcsr(__mxcsr);
+ }
+ return (0);
+}
+
+__fenv_static inline int
+fegetexceptflag(fexcept_t *__flagp, int __excepts)
+{
+ uint32_t __mxcsr;
+ uint16_t __status;
+
+ __fnstsw(&__status);
+ if (__HAS_SSE())
+ __stmxcsr(&__mxcsr);
+ else
+ __mxcsr = 0;
+ *__flagp = (__mxcsr | __status) & __excepts;
+ return (0);
+}
+
+int fesetexceptflag(const fexcept_t *__flagp, int __excepts);
+int feraiseexcept(int __excepts);
+
+__fenv_static inline int
+fetestexcept(int __excepts)
+{
+ uint32_t __mxcsr;
+ uint16_t __status;
+
+ __fnstsw(&__status);
+ if (__HAS_SSE())
+ __stmxcsr(&__mxcsr);
+ else
+ __mxcsr = 0;
+ return ((__status | __mxcsr) & __excepts);
+}
+
+__fenv_static inline int
+fegetround(void)
+{
+ uint16_t __control;
+
+ /*
+ * We assume that the x87 and the SSE unit agree on the
+ * rounding mode. Reading the control word on the x87 turns
+ * out to be about 5 times faster than reading it on the SSE
+ * unit on an Opteron 244.
+ */
+ __fnstcw(&__control);
+ return (__control & _ROUND_MASK);
+}
+
+__fenv_static inline int
+fesetround(int __round)
+{
+ uint32_t __mxcsr;
+ uint16_t __control;
+
+ if (__round & ~_ROUND_MASK)
+ return (-1);
+
+ __fnstcw(&__control);
+ __control &= ~_ROUND_MASK;
+ __control |= __round;
+ __fldcw(__control);
+
+ if (__HAS_SSE()) {
+ __stmxcsr(&__mxcsr);
+ __mxcsr &= ~(_ROUND_MASK << _SSE_ROUND_SHIFT);
+ __mxcsr |= __round << _SSE_ROUND_SHIFT;
+ __ldmxcsr(__mxcsr);
+ }
+
+ return (0);
+}
+
+int fegetenv(fenv_t *__envp);
+int feholdexcept(fenv_t *__envp);
+
+__fenv_static inline int
+fesetenv(const fenv_t *__envp)
+{
+ fenv_t __env = *__envp;
+ uint32_t __mxcsr;
+
+ __mxcsr = __get_mxcsr(__env);
+ __set_mxcsr(__env, 0xffffffff);
+ /*
+ * XXX Using fldenvx() instead of fldenv() tells the compiler that this
+ * instruction clobbers the i387 register stack. This happens because
+ * we restore the tag word from the saved environment. Normally, this
+ * would happen anyway and we wouldn't care, because the ABI allows
+ * function calls to clobber the i387 regs. However, fesetenv() is
+ * inlined, so we need to be more careful.
+ */
+ __fldenvx(__env);
+ if (__HAS_SSE())
+ __ldmxcsr(__mxcsr);
+ return (0);
+}
+
+int feupdateenv(const fenv_t *__envp);
+
+#if __BSD_VISIBLE
+
+int feenableexcept(int __mask);
+int fedisableexcept(int __mask);
+
+/* We currently provide no external definition of fegetexcept(). */
+static inline int
+fegetexcept(void)
+{
+ uint16_t __control;
+
+ /*
+ * We assume that the masks for the x87 and the SSE unit are
+ * the same.
+ */
+ __fnstcw(&__control);
+ return (~__control & FE_ALL_EXCEPT);
+}
+
+#endif /* __BSD_VISIBLE */
+
+__END_DECLS
+
+#endif /* !_FENV_H_ */
--- /dev/null
+/*-
+ * Copyright (c) 2004-2005 David Schultz <das@FreeBSD.ORG>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _FENV_H_
+#define _FENV_H_
+
+#include <stdint.h>
+#include "cdefs-compat.h"
+
+#ifndef __fenv_static
+#define __fenv_static static
+#endif
+
+typedef uint32_t fenv_t;
+typedef uint32_t fexcept_t;
+
+/* Exception flags */
+#ifdef __mips_soft_float
+#define _FPUSW_SHIFT 16
+#define FE_INVALID 0x0001
+#define FE_DIVBYZERO 0x0002
+#define FE_OVERFLOW 0x0004
+#define FE_UNDERFLOW 0x0008
+#define FE_INEXACT 0x0010
+#else
+#define _FCSR_CAUSE_SHIFT 10
+#define FE_INVALID 0x0040
+#define FE_DIVBYZERO 0x0020
+#define FE_OVERFLOW 0x0010
+#define FE_UNDERFLOW 0x0008
+#define FE_INEXACT 0x0004
+#endif
+#define FE_ALL_EXCEPT (FE_DIVBYZERO | FE_INEXACT | \
+ FE_INVALID | FE_OVERFLOW | FE_UNDERFLOW)
+
+/* Rounding modes */
+#define FE_TONEAREST 0x0000
+#define FE_TOWARDZERO 0x0001
+#define FE_UPWARD 0x0002
+#define FE_DOWNWARD 0x0003
+#define _ROUND_MASK (FE_TONEAREST | FE_DOWNWARD | \
+ FE_UPWARD | FE_TOWARDZERO)
+__BEGIN_DECLS
+
+/* Default floating-point environment */
+extern const fenv_t __fe_dfl_env;
+#define FE_DFL_ENV (&__fe_dfl_env)
+
+/* We need to be able to map status flag positions to mask flag positions */
+#define _ENABLE_SHIFT 5
+#define _ENABLE_MASK (FE_ALL_EXCEPT << _ENABLE_SHIFT)
+
+#ifndef __mips_soft_float
+#define __cfc1(__fcsr) __asm __volatile("cfc1 %0, $31" : "=r" (__fcsr))
+#define __ctc1(__fcsr) __asm __volatile("ctc1 %0, $31" :: "r" (__fcsr))
+#endif
+
+#ifdef __mips_soft_float
+int feclearexcept(int __excepts);
+int fegetexceptflag(fexcept_t *__flagp, int __excepts);
+int fesetexceptflag(const fexcept_t *__flagp, int __excepts);
+int feraiseexcept(int __excepts);
+int fetestexcept(int __excepts);
+int fegetround(void);
+int fesetround(int __round);
+int fegetenv(fenv_t *__envp);
+int feholdexcept(fenv_t *__envp);
+int fesetenv(const fenv_t *__envp);
+int feupdateenv(const fenv_t *__envp);
+#else
+__fenv_static inline int
+feclearexcept(int __excepts)
+{
+ fexcept_t fcsr;
+
+ __excepts &= FE_ALL_EXCEPT;
+ __cfc1(fcsr);
+ fcsr &= ~(__excepts | (__excepts << _FCSR_CAUSE_SHIFT));
+ __ctc1(fcsr);
+
+ return (0);
+}
+
+__fenv_static inline int
+fegetexceptflag(fexcept_t *__flagp, int __excepts)
+{
+ fexcept_t fcsr;
+
+ __excepts &= FE_ALL_EXCEPT;
+ __cfc1(fcsr);
+ *__flagp = fcsr & __excepts;
+
+ return (0);
+}
+
+__fenv_static inline int
+fesetexceptflag(const fexcept_t *__flagp, int __excepts)
+{
+ fexcept_t fcsr;
+
+ __excepts &= FE_ALL_EXCEPT;
+ __cfc1(fcsr);
+ fcsr &= ~__excepts;
+ fcsr |= *__flagp & __excepts;
+ __ctc1(fcsr);
+
+ return (0);
+}
+
+__fenv_static inline int
+feraiseexcept(int __excepts)
+{
+ fexcept_t fcsr;
+
+ __excepts &= FE_ALL_EXCEPT;
+ __cfc1(fcsr);
+ fcsr |= __excepts | (__excepts << _FCSR_CAUSE_SHIFT);
+ __ctc1(fcsr);
+
+ return (0);
+}
+
+__fenv_static inline int
+fetestexcept(int __excepts)
+{
+ fexcept_t fcsr;
+
+ __excepts &= FE_ALL_EXCEPT;
+ __cfc1(fcsr);
+
+ return (fcsr & __excepts);
+}
+
+__fenv_static inline int
+fegetround(void)
+{
+ fexcept_t fcsr;
+
+ __cfc1(fcsr);
+
+ return (fcsr & _ROUND_MASK);
+}
+
+__fenv_static inline int
+fesetround(int __round)
+{
+ fexcept_t fcsr;
+
+ if (__round & ~_ROUND_MASK)
+ return (-1);
+
+ __cfc1(fcsr);
+ fcsr &= ~_ROUND_MASK;
+ fcsr |= __round;
+ __ctc1(fcsr);
+
+ return (0);
+}
+
+__fenv_static inline int
+fegetenv(fenv_t *__envp)
+{
+
+ __cfc1(*__envp);
+
+ return (0);
+}
+
+__fenv_static inline int
+feholdexcept(fenv_t *__envp)
+{
+ fexcept_t fcsr;
+
+ __cfc1(fcsr);
+ *__envp = fcsr;
+ fcsr &= ~(FE_ALL_EXCEPT | _ENABLE_MASK);
+ __ctc1(fcsr);
+
+ return (0);
+}
+
+__fenv_static inline int
+fesetenv(const fenv_t *__envp)
+{
+
+ __ctc1(*__envp);
+
+ return (0);
+}
+
+__fenv_static inline int
+feupdateenv(const fenv_t *__envp)
+{
+ fexcept_t fcsr;
+
+ __cfc1(fcsr);
+ fesetenv(__envp);
+ feraiseexcept(fcsr);
+
+ return (0);
+}
+#endif /* !__mips_soft_float */
+
+#if __BSD_VISIBLE
+
+/* We currently provide no external definitions of the functions below. */
+
+#ifdef __mips_soft_float
+int feenableexcept(int __mask);
+int fedisableexcept(int __mask);
+int fegetexcept(void);
+#else
+static inline int
+feenableexcept(int __mask)
+{
+ fenv_t __old_fcsr, __new_fcsr;
+
+ __cfc1(__old_fcsr);
+ __new_fcsr = __old_fcsr | (__mask & FE_ALL_EXCEPT) << _ENABLE_SHIFT;
+ __ctc1(__new_fcsr);
+
+ return ((__old_fcsr >> _ENABLE_SHIFT) & FE_ALL_EXCEPT);
+}
+
+static inline int
+fedisableexcept(int __mask)
+{
+ fenv_t __old_fcsr, __new_fcsr;
+
+ __cfc1(__old_fcsr);
+ __new_fcsr = __old_fcsr & ~((__mask & FE_ALL_EXCEPT) << _ENABLE_SHIFT);
+ __ctc1(__new_fcsr);
+
+ return ((__old_fcsr >> _ENABLE_SHIFT) & FE_ALL_EXCEPT);
+}
+
+static inline int
+fegetexcept(void)
+{
+ fexcept_t fcsr;
+
+ __cfc1(fcsr);
+
+ return ((fcsr & _ENABLE_MASK) >> _ENABLE_SHIFT);
+}
+
+#endif /* !__mips_soft_float */
+
+#endif /* __BSD_VISIBLE */
+
+__END_DECLS
+
+#endif /* !_FENV_H_ */
--- /dev/null
+/*-
+ * Copyright (c) 2004-2005 David Schultz <das@FreeBSD.ORG>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _FENV_H_
+#define _FENV_H_
+
+#include <sys/types.h>
+
+#ifndef __fenv_static
+#define __fenv_static static
+#endif
+
+typedef __uint32_t fenv_t;
+typedef __uint32_t fexcept_t;
+
+/* Exception flags */
+#define FE_INEXACT 0x02000000
+#define FE_DIVBYZERO 0x04000000
+#define FE_UNDERFLOW 0x08000000
+#define FE_OVERFLOW 0x10000000
+#define FE_INVALID 0x20000000 /* all types of invalid FP ops */
+
+/*
+ * The PowerPC architecture has extra invalid flags that indicate the
+ * specific type of invalid operation occurred. These flags may be
+ * tested, set, and cleared---but not masked---separately. All of
+ * these bits are cleared when FE_INVALID is cleared, but only
+ * FE_VXSOFT is set when FE_INVALID is explicitly set in software.
+ */
+#define FE_VXCVI 0x00000100 /* invalid integer convert */
+#define FE_VXSQRT 0x00000200 /* square root of a negative */
+#define FE_VXSOFT 0x00000400 /* software-requested exception */
+#define FE_VXVC 0x00080000 /* ordered comparison involving NaN */
+#define FE_VXIMZ 0x00100000 /* inf * 0 */
+#define FE_VXZDZ 0x00200000 /* 0 / 0 */
+#define FE_VXIDI 0x00400000 /* inf / inf */
+#define FE_VXISI 0x00800000 /* inf - inf */
+#define FE_VXSNAN 0x01000000 /* operation on a signalling NaN */
+#define FE_ALL_INVALID (FE_VXCVI | FE_VXSQRT | FE_VXSOFT | FE_VXVC | \
+ FE_VXIMZ | FE_VXZDZ | FE_VXIDI | FE_VXISI | \
+ FE_VXSNAN | FE_INVALID)
+#define FE_ALL_EXCEPT (FE_DIVBYZERO | FE_INEXACT | \
+ FE_ALL_INVALID | FE_OVERFLOW | FE_UNDERFLOW)
+
+/* Rounding modes */
+#define FE_TONEAREST 0x0000
+#define FE_TOWARDZERO 0x0001
+#define FE_UPWARD 0x0002
+#define FE_DOWNWARD 0x0003
+#define _ROUND_MASK (FE_TONEAREST | FE_DOWNWARD | \
+ FE_UPWARD | FE_TOWARDZERO)
+
+__BEGIN_DECLS
+
+/* Default floating-point environment */
+extern const fenv_t __fe_dfl_env;
+#define FE_DFL_ENV (&__fe_dfl_env)
+
+/* We need to be able to map status flag positions to mask flag positions */
+#define _FPUSW_SHIFT 22
+#define _ENABLE_MASK ((FE_DIVBYZERO | FE_INEXACT | FE_INVALID | \
+ FE_OVERFLOW | FE_UNDERFLOW) >> _FPUSW_SHIFT)
+
+#ifndef _SOFT_FLOAT
+#define __mffs(__env) __asm __volatile("mffs %0" : "=f" (*(__env)))
+#define __mtfsf(__env) __asm __volatile("mtfsf 255,%0" : : "f" (__env))
+#else
+#define __mffs(__env)
+#define __mtfsf(__env)
+#endif
+
+union __fpscr {
+ double __d;
+ struct {
+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+ fenv_t __reg;
+ __uint32_t __junk;
+#else
+ __uint32_t __junk;
+ fenv_t __reg;
+#endif
+ } __bits;
+};
+
+__fenv_static inline int
+feclearexcept(int __excepts)
+{
+ union __fpscr __r;
+
+ if (__excepts & FE_INVALID)
+ __excepts |= FE_ALL_INVALID;
+ __mffs(&__r.__d);
+ __r.__bits.__reg &= ~__excepts;
+ __mtfsf(__r.__d);
+ return (0);
+}
+
+__fenv_static inline int
+fegetexceptflag(fexcept_t *__flagp, int __excepts)
+{
+ union __fpscr __r;
+
+ __mffs(&__r.__d);
+ *__flagp = __r.__bits.__reg & __excepts;
+ return (0);
+}
+
+__fenv_static inline int
+fesetexceptflag(const fexcept_t *__flagp, int __excepts)
+{
+ union __fpscr __r;
+
+ if (__excepts & FE_INVALID)
+ __excepts |= FE_ALL_EXCEPT;
+ __mffs(&__r.__d);
+ __r.__bits.__reg &= ~__excepts;
+ __r.__bits.__reg |= *__flagp & __excepts;
+ __mtfsf(__r.__d);
+ return (0);
+}
+
+__fenv_static inline int
+feraiseexcept(int __excepts)
+{
+ union __fpscr __r;
+
+ if (__excepts & FE_INVALID)
+ __excepts |= FE_VXSOFT;
+ __mffs(&__r.__d);
+ __r.__bits.__reg |= __excepts;
+ __mtfsf(__r.__d);
+ return (0);
+}
+
+__fenv_static inline int
+fetestexcept(int __excepts)
+{
+ union __fpscr __r;
+
+ __mffs(&__r.__d);
+ return (__r.__bits.__reg & __excepts);
+}
+
+__fenv_static inline int
+fegetround(void)
+{
+ union __fpscr __r;
+
+ __mffs(&__r.__d);
+ return (__r.__bits.__reg & _ROUND_MASK);
+}
+
+__fenv_static inline int
+fesetround(int __round)
+{
+ union __fpscr __r;
+
+ if (__round & ~_ROUND_MASK)
+ return (-1);
+ __mffs(&__r.__d);
+ __r.__bits.__reg &= ~_ROUND_MASK;
+ __r.__bits.__reg |= __round;
+ __mtfsf(__r.__d);
+ return (0);
+}
+
+__fenv_static inline int
+fegetenv(fenv_t *__envp)
+{
+ union __fpscr __r;
+
+ __mffs(&__r.__d);
+ *__envp = __r.__bits.__reg;
+ return (0);
+}
+
+__fenv_static inline int
+feholdexcept(fenv_t *__envp)
+{
+ union __fpscr __r;
+
+ __mffs(&__r.__d);
+ *__envp = __r.__d;
+ __r.__bits.__reg &= ~(FE_ALL_EXCEPT | _ENABLE_MASK);
+ __mtfsf(__r.__d);
+ return (0);
+}
+
+__fenv_static inline int
+fesetenv(const fenv_t *__envp)
+{
+ union __fpscr __r;
+
+ __r.__bits.__reg = *__envp;
+ __mtfsf(__r.__d);
+ return (0);
+}
+
+__fenv_static inline int
+feupdateenv(const fenv_t *__envp)
+{
+ union __fpscr __r;
+
+ __mffs(&__r.__d);
+ __r.__bits.__reg &= FE_ALL_EXCEPT;
+ __r.__bits.__reg |= *__envp;
+ __mtfsf(__r.__d);
+ return (0);
+}
+
+#if __BSD_VISIBLE
+
+/* We currently provide no external definitions of the functions below. */
+
+static inline int
+feenableexcept(int __mask)
+{
+ union __fpscr __r;
+ fenv_t __oldmask;
+
+ __mffs(&__r.__d);
+ __oldmask = __r.__bits.__reg;
+ __r.__bits.__reg |= (__mask & FE_ALL_EXCEPT) >> _FPUSW_SHIFT;
+ __mtfsf(__r.__d);
+ return ((__oldmask & _ENABLE_MASK) << _FPUSW_SHIFT);
+}
+
+static inline int
+fedisableexcept(int __mask)
+{
+ union __fpscr __r;
+ fenv_t __oldmask;
+
+ __mffs(&__r.__d);
+ __oldmask = __r.__bits.__reg;
+ __r.__bits.__reg &= ~((__mask & FE_ALL_EXCEPT) >> _FPUSW_SHIFT);
+ __mtfsf(__r.__d);
+ return ((__oldmask & _ENABLE_MASK) << _FPUSW_SHIFT);
+}
+
+static inline int
+fegetexcept(void)
+{
+ union __fpscr __r;
+
+ __mffs(&__r.__d);
+ return ((__r.__bits.__reg & _ENABLE_MASK) << _FPUSW_SHIFT);
+}
+
+#endif /* __BSD_VISIBLE */
+
+__END_DECLS
+
+#endif /* !_FENV_H_ */
--- /dev/null
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/*
+ * from: @(#)fdlibm.h 5.1 93/09/24
+ * $FreeBSD: src/lib/msun/src/openlibm.h,v 1.82 2011/11/12 19:55:48 theraven Exp $
+ */
+
+#ifdef OPENLIBM_USE_HOST_MATH_H
+#include <math.h>
+#else /* !OPENLIBM_USE_HOST_MATH_H */
+
+#ifndef OPENLIBM_MATH_H
+#define OPENLIBM_MATH_H
+
+#if (defined(_WIN32) || defined (_MSC_VER)) && !defined(__WIN32__)
+ #define __WIN32__
+#endif
+
+#ifndef __arm__
+#define LONG_DOUBLE
+#endif
+
+#ifndef __pure2
+#define __pure2
+#endif
+
+#ifdef _WIN32
+# ifdef IMPORT_EXPORTS
+# define OLM_DLLEXPORT __declspec(dllimport)
+# else
+# define OLM_DLLEXPORT __declspec(dllexport)
+# endif
+#else
+#define OLM_DLLEXPORT __attribute__ ((visibility("default")))
+#endif
+
+/*
+ * ANSI/POSIX
+ */
+extern const union __infinity_un {
+ unsigned char __uc[8];
+ double __ud;
+} __infinity;
+
+extern const union __nan_un {
+ unsigned char __uc[sizeof(float)];
+ float __uf;
+} __nan;
+
+/* VBS
+#if __GNUC_PREREQ__(3, 3) || (defined(__INTEL_COMPILER) && __INTEL_COMPILER >= 800)
+#define __MATH_BUILTIN_CONSTANTS
+#endif
+
+#if __GNUC_PREREQ__(3, 0) && !defined(__INTEL_COMPILER)
+#define __MATH_BUILTIN_RELOPS
+#endif
+*/
+
+//VBS begin
+#define __MATH_BUILTIN_CONSTANTS
+#define __MATH_BUILTIN_RELOPS
+#ifndef __ISO_C_VISIBLE
+#define __ISO_C_VISIBLE 1999
+#endif
+//VBS end
+
+#ifdef __MATH_BUILTIN_CONSTANTS
+#define HUGE_VAL __builtin_huge_val()
+#else
+#define HUGE_VAL (__infinity.__ud)
+#endif
+
+#if __ISO_C_VISIBLE >= 1999
+#define FP_ILOGB0 (-INT_MAX)
+#define FP_ILOGBNAN INT_MAX
+
+#ifdef __MATH_BUILTIN_CONSTANTS
+#define HUGE_VALF __builtin_huge_valf()
+#define HUGE_VALL __builtin_huge_vall()
+#define INFINITY __builtin_inff()
+#define NAN __builtin_nanf("")
+#else
+#define HUGE_VALF (float)HUGE_VAL
+#define HUGE_VALL (long double)HUGE_VAL
+#define INFINITY HUGE_VALF
+#define NAN (__nan.__uf)
+#endif /* __MATH_BUILTIN_CONSTANTS */
+
+#define MATH_ERRNO 1
+#define MATH_ERREXCEPT 2
+#define math_errhandling MATH_ERREXCEPT
+
+#define FP_FAST_FMAF 1
+#ifdef __ia64__
+#define FP_FAST_FMA 1
+#define FP_FAST_FMAL 1
+#endif
+
+/* Symbolic constants to classify floating point numbers. */
+#define FP_INFINITE 0x01
+#define FP_NAN 0x02
+#define FP_NORMAL 0x04
+#define FP_SUBNORMAL 0x08
+#define FP_ZERO 0x10
+#define fpclassify(x) \
+ ((sizeof (x) == sizeof (float)) ? __fpclassifyf(x) \
+ : (sizeof (x) == sizeof (double)) ? __fpclassifyd(x) \
+ : __fpclassifyl(x))
+
+#define isfinite(x) \
+ ((sizeof (x) == sizeof (float)) ? __isfinitef(x) \
+ : (sizeof (x) == sizeof (double)) ? __isfinite(x) \
+ : __isfinitel(x))
+#define isinf(x) \
+ ((sizeof (x) == sizeof (float)) ? __isinff(x) \
+ : (sizeof (x) == sizeof (double)) ? isinf(x) \
+ : __isinfl(x))
+#define isnan(x) \
+ ((sizeof (x) == sizeof (float)) ? __isnanf(x) \
+ : (sizeof (x) == sizeof (double)) ? isnan(x) \
+ : __isnanl(x))
+#define isnormal(x) \
+ ((sizeof (x) == sizeof (float)) ? __isnormalf(x) \
+ : (sizeof (x) == sizeof (double)) ? __isnormal(x) \
+ : __isnormall(x))
+
+#ifdef __MATH_BUILTIN_RELOPS
+#define isgreater(x, y) __builtin_isgreater((x), (y))
+#define isgreaterequal(x, y) __builtin_isgreaterequal((x), (y))
+#define isless(x, y) __builtin_isless((x), (y))
+#define islessequal(x, y) __builtin_islessequal((x), (y))
+#define islessgreater(x, y) __builtin_islessgreater((x), (y))
+#define isunordered(x, y) __builtin_isunordered((x), (y))
+#else
+#define isgreater(x, y) (!isunordered((x), (y)) && (x) > (y))
+#define isgreaterequal(x, y) (!isunordered((x), (y)) && (x) >= (y))
+#define isless(x, y) (!isunordered((x), (y)) && (x) < (y))
+#define islessequal(x, y) (!isunordered((x), (y)) && (x) <= (y))
+#define islessgreater(x, y) (!isunordered((x), (y)) && \
+ ((x) > (y) || (y) > (x)))
+#define isunordered(x, y) (isnan(x) || isnan(y))
+#endif /* __MATH_BUILTIN_RELOPS */
+
+#define signbit(x) \
+ ((sizeof (x) == sizeof (float)) ? __signbitf(x) \
+ : (sizeof (x) == sizeof (double)) ? __signbit(x) \
+ : __signbitl(x))
+
+//VBS
+//typedef __double_t double_t;
+//typedef __float_t float_t;
+#endif /* __ISO_C_VISIBLE >= 1999 */
+
+/*
+ * XOPEN/SVID
+ */
+#if __BSD_VISIBLE || __XSI_VISIBLE
+#define M_E 2.7182818284590452354 /* e */
+#define M_LOG2E 1.4426950408889634074 /* log 2e */
+#define M_LOG10E 0.43429448190325182765 /* log 10e */
+#define M_LN2 0.69314718055994530942 /* log e2 */
+#define M_LN10 2.30258509299404568402 /* log e10 */
+#define M_PI 3.14159265358979323846 /* pi */
+#define M_PI_2 1.57079632679489661923 /* pi/2 */
+#define M_PI_4 0.78539816339744830962 /* pi/4 */
+#define M_1_PI 0.31830988618379067154 /* 1/pi */
+#define M_2_PI 0.63661977236758134308 /* 2/pi */
+#define M_2_SQRTPI 1.12837916709551257390 /* 2/sqrt(pi) */
+#define M_SQRT2 1.41421356237309504880 /* sqrt(2) */
+#define M_SQRT1_2 0.70710678118654752440 /* 1/sqrt(2) */
+
+#define MAXFLOAT ((float)3.40282346638528860e+38)
+
+#ifndef OPENLIBM_ONLY_THREAD_SAFE
+extern int signgam;
+#endif
+#endif /* __BSD_VISIBLE || __XSI_VISIBLE */
+
+#if __BSD_VISIBLE
+#if 0
+/* Old value from 4.4BSD-Lite openlibm.h; this is probably better. */
+#define HUGE HUGE_VAL
+#else
+#define HUGE MAXFLOAT
+#endif
+#endif /* __BSD_VISIBLE */
+
+/*
+ * Most of these functions depend on the rounding mode and have the side
+ * effect of raising floating-point exceptions, so they are not declared
+ * as __pure2. In C99, FENV_ACCESS affects the purity of these functions.
+ */
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+/* Symbol present when OpenLibm is used. */
+int isopenlibm(void);
+
+/*
+ * ANSI/POSIX
+ */
+OLM_DLLEXPORT int __fpclassifyd(double) __pure2;
+OLM_DLLEXPORT int __fpclassifyf(float) __pure2;
+OLM_DLLEXPORT int __fpclassifyl(long double) __pure2;
+OLM_DLLEXPORT int __isfinitef(float) __pure2;
+OLM_DLLEXPORT int __isfinite(double) __pure2;
+OLM_DLLEXPORT int __isfinitel(long double) __pure2;
+OLM_DLLEXPORT int __isinff(float) __pure2;
+OLM_DLLEXPORT int __isinfl(long double) __pure2;
+OLM_DLLEXPORT int __isnanf(float) __pure2;
+OLM_DLLEXPORT int __isnanl(long double) __pure2;
+OLM_DLLEXPORT int __isnormalf(float) __pure2;
+OLM_DLLEXPORT int __isnormal(double) __pure2;
+OLM_DLLEXPORT int __isnormall(long double) __pure2;
+OLM_DLLEXPORT int __signbit(double) __pure2;
+OLM_DLLEXPORT int __signbitf(float) __pure2;
+OLM_DLLEXPORT int __signbitl(long double) __pure2;
+
+OLM_DLLEXPORT double acos(double);
+OLM_DLLEXPORT double asin(double);
+OLM_DLLEXPORT double atan(double);
+OLM_DLLEXPORT double atan2(double, double);
+OLM_DLLEXPORT double cos(double);
+OLM_DLLEXPORT double sin(double);
+OLM_DLLEXPORT double tan(double);
+
+OLM_DLLEXPORT double cosh(double);
+OLM_DLLEXPORT double sinh(double);
+OLM_DLLEXPORT double tanh(double);
+
+OLM_DLLEXPORT double exp(double);
+OLM_DLLEXPORT double frexp(double, int *); /* fundamentally !__pure2 */
+OLM_DLLEXPORT double ldexp(double, int);
+OLM_DLLEXPORT double log(double);
+OLM_DLLEXPORT double log10(double);
+OLM_DLLEXPORT double modf(double, double *); /* fundamentally !__pure2 */
+
+OLM_DLLEXPORT double pow(double, double);
+OLM_DLLEXPORT double sqrt(double);
+
+OLM_DLLEXPORT double ceil(double);
+OLM_DLLEXPORT double fabs(double) __pure2;
+OLM_DLLEXPORT double floor(double);
+OLM_DLLEXPORT double fmod(double, double);
+
+/*
+ * These functions are not in C90.
+ */
+#if __BSD_VISIBLE || __ISO_C_VISIBLE >= 1999 || __XSI_VISIBLE
+OLM_DLLEXPORT double acosh(double);
+OLM_DLLEXPORT double asinh(double);
+OLM_DLLEXPORT double atanh(double);
+OLM_DLLEXPORT double cbrt(double);
+OLM_DLLEXPORT double erf(double);
+OLM_DLLEXPORT double erfc(double);
+OLM_DLLEXPORT double exp2(double);
+OLM_DLLEXPORT double expm1(double);
+OLM_DLLEXPORT double fma(double, double, double);
+OLM_DLLEXPORT double hypot(double, double);
+OLM_DLLEXPORT int ilogb(double) __pure2;
+OLM_DLLEXPORT int (isinf)(double) __pure2;
+OLM_DLLEXPORT int (isnan)(double) __pure2;
+OLM_DLLEXPORT double lgamma(double);
+OLM_DLLEXPORT long long llrint(double);
+OLM_DLLEXPORT long long llround(double);
+OLM_DLLEXPORT double log1p(double);
+OLM_DLLEXPORT double log2(double);
+OLM_DLLEXPORT double logb(double);
+OLM_DLLEXPORT long lrint(double);
+OLM_DLLEXPORT long lround(double);
+OLM_DLLEXPORT double nan(const char *) __pure2;
+OLM_DLLEXPORT double nextafter(double, double);
+OLM_DLLEXPORT double remainder(double, double);
+OLM_DLLEXPORT double remquo(double, double, int *);
+OLM_DLLEXPORT double rint(double);
+#endif /* __BSD_VISIBLE || __ISO_C_VISIBLE >= 1999 || __XSI_VISIBLE */
+
+#if __BSD_VISIBLE || __XSI_VISIBLE
+OLM_DLLEXPORT double j0(double);
+OLM_DLLEXPORT double j1(double);
+OLM_DLLEXPORT double jn(int, double);
+OLM_DLLEXPORT double y0(double);
+OLM_DLLEXPORT double y1(double);
+OLM_DLLEXPORT double yn(int, double);
+#endif /* __BSD_VISIBLE || __XSI_VISIBLE */
+
+#if __BSD_VISIBLE || __ISO_C_VISIBLE >= 1999
+OLM_DLLEXPORT double copysign(double, double) __pure2;
+OLM_DLLEXPORT double fdim(double, double);
+OLM_DLLEXPORT double fmax(double, double) __pure2;
+OLM_DLLEXPORT double fmin(double, double) __pure2;
+OLM_DLLEXPORT double nearbyint(double);
+OLM_DLLEXPORT double round(double);
+OLM_DLLEXPORT double scalbln(double, long);
+OLM_DLLEXPORT double scalbn(double, int);
+OLM_DLLEXPORT double tgamma(double);
+OLM_DLLEXPORT double trunc(double);
+#endif
+
+/*
+ * BSD math library entry points
+ */
+#if __BSD_VISIBLE
+OLM_DLLEXPORT int isnanf(float) __pure2;
+
+/*
+ * Reentrant version of lgamma; passes signgam back by reference as the
+ * second argument; user must allocate space for signgam.
+ */
+OLM_DLLEXPORT double lgamma_r(double, int *);
+
+/*
+ * Single sine/cosine function.
+ */
+OLM_DLLEXPORT void sincos(double, double *, double *);
+#endif /* __BSD_VISIBLE */
+
+/* float versions of ANSI/POSIX functions */
+#if __ISO_C_VISIBLE >= 1999
+OLM_DLLEXPORT float acosf(float);
+OLM_DLLEXPORT float asinf(float);
+OLM_DLLEXPORT float atanf(float);
+OLM_DLLEXPORT float atan2f(float, float);
+OLM_DLLEXPORT float cosf(float);
+OLM_DLLEXPORT float sinf(float);
+OLM_DLLEXPORT float tanf(float);
+
+OLM_DLLEXPORT float coshf(float);
+OLM_DLLEXPORT float sinhf(float);
+OLM_DLLEXPORT float tanhf(float);
+
+OLM_DLLEXPORT float exp2f(float);
+OLM_DLLEXPORT float expf(float);
+OLM_DLLEXPORT float expm1f(float);
+OLM_DLLEXPORT float frexpf(float, int *); /* fundamentally !__pure2 */
+OLM_DLLEXPORT int ilogbf(float) __pure2;
+OLM_DLLEXPORT float ldexpf(float, int);
+OLM_DLLEXPORT float log10f(float);
+OLM_DLLEXPORT float log1pf(float);
+OLM_DLLEXPORT float log2f(float);
+OLM_DLLEXPORT float logf(float);
+OLM_DLLEXPORT float modff(float, float *); /* fundamentally !__pure2 */
+
+OLM_DLLEXPORT float powf(float, float);
+OLM_DLLEXPORT float sqrtf(float);
+
+OLM_DLLEXPORT float ceilf(float);
+OLM_DLLEXPORT float fabsf(float) __pure2;
+OLM_DLLEXPORT float floorf(float);
+OLM_DLLEXPORT float fmodf(float, float);
+OLM_DLLEXPORT float roundf(float);
+
+OLM_DLLEXPORT float erff(float);
+OLM_DLLEXPORT float erfcf(float);
+OLM_DLLEXPORT float hypotf(float, float);
+OLM_DLLEXPORT float lgammaf(float);
+OLM_DLLEXPORT float tgammaf(float);
+
+OLM_DLLEXPORT float acoshf(float);
+OLM_DLLEXPORT float asinhf(float);
+OLM_DLLEXPORT float atanhf(float);
+OLM_DLLEXPORT float cbrtf(float);
+OLM_DLLEXPORT float logbf(float);
+OLM_DLLEXPORT float copysignf(float, float) __pure2;
+OLM_DLLEXPORT long long llrintf(float);
+OLM_DLLEXPORT long long llroundf(float);
+OLM_DLLEXPORT long lrintf(float);
+OLM_DLLEXPORT long lroundf(float);
+OLM_DLLEXPORT float nanf(const char *) __pure2;
+OLM_DLLEXPORT float nearbyintf(float);
+OLM_DLLEXPORT float nextafterf(float, float);
+OLM_DLLEXPORT float remainderf(float, float);
+OLM_DLLEXPORT float remquof(float, float, int *);
+OLM_DLLEXPORT float rintf(float);
+OLM_DLLEXPORT float scalblnf(float, long);
+OLM_DLLEXPORT float scalbnf(float, int);
+OLM_DLLEXPORT float truncf(float);
+
+OLM_DLLEXPORT float fdimf(float, float);
+OLM_DLLEXPORT float fmaf(float, float, float);
+OLM_DLLEXPORT float fmaxf(float, float) __pure2;
+OLM_DLLEXPORT float fminf(float, float) __pure2;
+#endif
+
+/*
+ * float versions of BSD math library entry points
+ */
+#if __BSD_VISIBLE
+OLM_DLLEXPORT float dremf(float, float);
+OLM_DLLEXPORT float j0f(float);
+OLM_DLLEXPORT float j1f(float);
+OLM_DLLEXPORT float jnf(int, float);
+OLM_DLLEXPORT float y0f(float);
+OLM_DLLEXPORT float y1f(float);
+OLM_DLLEXPORT float ynf(int, float);
+
+/*
+ * Float versions of reentrant version of lgamma; passes signgam back by
+ * reference as the second argument; user must allocate space for signgam.
+ */
+OLM_DLLEXPORT float lgammaf_r(float, int *);
+
+/*
+ * Single sine/cosine function.
+ */
+OLM_DLLEXPORT void sincosf(float, float *, float *);
+#endif /* __BSD_VISIBLE */
+
+/*
+ * long double versions of ISO/POSIX math functions
+ */
+#if __ISO_C_VISIBLE >= 1999
+OLM_DLLEXPORT long double acoshl(long double);
+OLM_DLLEXPORT long double acosl(long double);
+OLM_DLLEXPORT long double asinhl(long double);
+OLM_DLLEXPORT long double asinl(long double);
+OLM_DLLEXPORT long double atan2l(long double, long double);
+OLM_DLLEXPORT long double atanhl(long double);
+OLM_DLLEXPORT long double atanl(long double);
+OLM_DLLEXPORT long double cbrtl(long double);
+OLM_DLLEXPORT long double ceill(long double);
+OLM_DLLEXPORT long double copysignl(long double, long double) __pure2;
+OLM_DLLEXPORT long double coshl(long double);
+OLM_DLLEXPORT long double cosl(long double);
+OLM_DLLEXPORT long double erfcl(long double);
+OLM_DLLEXPORT long double erfl(long double);
+OLM_DLLEXPORT long double exp2l(long double);
+OLM_DLLEXPORT long double expl(long double);
+OLM_DLLEXPORT long double expm1l(long double);
+OLM_DLLEXPORT long double fabsl(long double) __pure2;
+OLM_DLLEXPORT long double fdiml(long double, long double);
+OLM_DLLEXPORT long double floorl(long double);
+OLM_DLLEXPORT long double fmal(long double, long double, long double);
+OLM_DLLEXPORT long double fmaxl(long double, long double) __pure2;
+OLM_DLLEXPORT long double fminl(long double, long double) __pure2;
+OLM_DLLEXPORT long double fmodl(long double, long double);
+OLM_DLLEXPORT long double frexpl(long double value, int *); /* fundamentally !__pure2 */
+OLM_DLLEXPORT long double hypotl(long double, long double);
+OLM_DLLEXPORT int ilogbl(long double) __pure2;
+OLM_DLLEXPORT long double ldexpl(long double, int);
+OLM_DLLEXPORT long double lgammal(long double);
+OLM_DLLEXPORT long long llrintl(long double);
+OLM_DLLEXPORT long long llroundl(long double);
+OLM_DLLEXPORT long double log10l(long double);
+OLM_DLLEXPORT long double log1pl(long double);
+OLM_DLLEXPORT long double log2l(long double);
+OLM_DLLEXPORT long double logbl(long double);
+OLM_DLLEXPORT long double logl(long double);
+OLM_DLLEXPORT long lrintl(long double);
+OLM_DLLEXPORT long lroundl(long double);
+OLM_DLLEXPORT long double modfl(long double, long double *); /* fundamentally !__pure2 */
+OLM_DLLEXPORT long double nanl(const char *) __pure2;
+OLM_DLLEXPORT long double nearbyintl(long double);
+OLM_DLLEXPORT long double nextafterl(long double, long double);
+OLM_DLLEXPORT double nexttoward(double, long double);
+OLM_DLLEXPORT float nexttowardf(float, long double);
+OLM_DLLEXPORT long double nexttowardl(long double, long double);
+OLM_DLLEXPORT long double powl(long double, long double);
+OLM_DLLEXPORT long double remainderl(long double, long double);
+OLM_DLLEXPORT long double remquol(long double, long double, int *);
+OLM_DLLEXPORT long double rintl(long double);
+OLM_DLLEXPORT long double roundl(long double);
+OLM_DLLEXPORT long double scalblnl(long double, long);
+OLM_DLLEXPORT long double scalbnl(long double, int);
+OLM_DLLEXPORT long double sinhl(long double);
+OLM_DLLEXPORT long double sinl(long double);
+OLM_DLLEXPORT long double sqrtl(long double);
+OLM_DLLEXPORT long double tanhl(long double);
+OLM_DLLEXPORT long double tanl(long double);
+OLM_DLLEXPORT long double tgammal(long double);
+OLM_DLLEXPORT long double truncl(long double);
+#endif /* __ISO_C_VISIBLE >= 1999 */
+
+/* Reentrant version of lgammal. */
+#if __BSD_VISIBLE
+OLM_DLLEXPORT long double lgammal_r(long double, int *);
+
+/*
+ * Single sine/cosine function.
+ */
+OLM_DLLEXPORT void sincosl(long double, long double *, long double *);
+#endif /* __BSD_VISIBLE */
+
+#if defined(__cplusplus)
+}
+#endif
+#endif /* !OPENLIBM_MATH_H */
+
+#endif /* OPENLIBM_USE_HOST_MATH_H */
--- /dev/null
+$(CUR_SRCS) += invtrig.c \
+ e_acoshl.c e_powl.c k_tanl.c s_exp2l.c \
+ e_atanhl.c e_lgammal_r.c e_sinhl.c s_asinhl.c s_expm1l.c \
+ e_coshl.c e_log10l.c e_tgammal.c \
+ e_expl.c e_log2l.c k_cosl.c s_log1pl.c s_tanhl.c \
+ e_logl.c k_sinl.c s_erfl.c
+
+# s_remquol.c e_fmodl.c s_truncl.c
+# e_hypotl.c s_floorl.c s_nextafterl.c s_ceill.c s_modfl.c
+
+ifneq ($(OS), WINNT)
+$(CUR_SRCS) += s_nanl.c
+endif
--- /dev/null
+/* @(#)e_acosh.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/* acoshl(x)
+ * Method :
+ * Based on
+ * acoshl(x) = logl [ x + sqrtl(x*x-1) ]
+ * we have
+ * acoshl(x) := logl(x)+ln2, if x is large; else
+ * acoshl(x) := logl(2x-1/(sqrtl(x*x-1)+x)) if x>2; else
+ * acoshl(x) := log1pl(t+sqrtl(2.0*t+t*t)); where t=x-1.
+ *
+ * Special cases:
+ * acoshl(x) is NaN with signal if x<1.
+ * acoshl(NaN) is NaN without signal.
+ */
+
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+static const long double
+one = 1.0,
+ln2 = 0.6931471805599453094172321214581766L;
+
+long double
+acoshl(long double x)
+{
+ long double t;
+ u_int64_t lx;
+ int64_t hx;
+ GET_LDOUBLE_WORDS64(hx,lx,x);
+ if(hx<0x3fff000000000000LL) { /* x < 1 */
+ return (x-x)/(x-x);
+ } else if(hx >=0x4035000000000000LL) { /* x > 2**54 */
+ if(hx >=0x7fff000000000000LL) { /* x is inf of NaN */
+ return x+x;
+ } else
+ return logl(x)+ln2; /* acoshl(huge)=logl(2x) */
+ } else if(((hx-0x3fff000000000000LL)|lx)==0) {
+ return 0.0L; /* acosh(1) = 0 */
+ } else if (hx > 0x4000000000000000LL) { /* 2**28 > x > 2 */
+ t=x*x;
+ return logl(2.0L*x-one/(x+sqrtl(t-one)));
+ } else { /* 1<x<2 */
+ t = x-one;
+ return log1pl(t+sqrtl(2.0L*t+t*t));
+ }
+}
--- /dev/null
+/* @(#)e_atanh.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/* atanhl(x)
+ * Method :
+ * 1.Reduced x to positive by atanh(-x) = -atanh(x)
+ * 2.For x>=0.5
+ * 1 2x x
+ * atanhl(x) = --- * log(1 + -------) = 0.5 * log1p(2 * --------)
+ * 2 1 - x 1 - x
+ *
+ * For x<0.5
+ * atanhl(x) = 0.5*log1pl(2x+2x*x/(1-x))
+ *
+ * Special cases:
+ * atanhl(x) is NaN if |x| > 1 with signal;
+ * atanhl(NaN) is that NaN with no signal;
+ * atanhl(+-1) is +-INF with signal.
+ *
+ */
+
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+static const long double one = 1.0L, huge = 1e4900L;
+
+static const long double zero = 0.0L;
+
+long double
+atanhl(long double x)
+{
+ long double t;
+ u_int32_t jx, ix;
+ ieee_quad_shape_type u;
+
+ u.value = x;
+ jx = u.parts32.mswhi;
+ ix = jx & 0x7fffffff;
+ u.parts32.mswhi = ix;
+ if (ix >= 0x3fff0000) /* |x| >= 1.0 or infinity or NaN */
+ {
+ if (u.value == one)
+ return x/zero;
+ else
+ return (x-x)/(x-x);
+ }
+ if(ix<0x3fc60000 && (huge+x)>zero) return x; /* x < 2^-57 */
+
+ if(ix<0x3ffe0000) { /* x < 0.5 */
+ t = u.value+u.value;
+ t = 0.5*log1pl(t+t*u.value/(one-u.value));
+ } else
+ t = 0.5*log1pl((u.value+u.value)/(one-u.value));
+ if(jx & 0x80000000) return -t; else return t;
+}
--- /dev/null
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/*
+ * Copyright (c) 2008 Stephen L. Moshier <steve@moshier.net>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* coshl(x)
+ * Method :
+ * mathematically coshl(x) if defined to be (exp(x)+exp(-x))/2
+ * 1. Replace x by |x| (coshl(x) = coshl(-x)).
+ * 2.
+ * [ exp(x) - 1 ]^2
+ * 0 <= x <= ln2/2 : coshl(x) := 1 + -------------------
+ * 2*exp(x)
+ *
+ * exp(x) + 1/exp(x)
+ * ln2/2 <= x <= 22 : coshl(x) := -------------------
+ * 2
+ * 22 <= x <= lnovft : coshl(x) := expl(x)/2
+ * lnovft <= x <= ln2ovft: coshl(x) := expl(x/2)/2 * expl(x/2)
+ * ln2ovft < x : coshl(x) := huge*huge (overflow)
+ *
+ * Special cases:
+ * coshl(x) is |x| if x is +INF, -INF, or NaN.
+ * only coshl(0)=1 is exact for finite x.
+ */
+
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+static const long double one = 1.0, half = 0.5, huge = 1.0e4900L,
+ovf_thresh = 1.1357216553474703894801348310092223067821E4L;
+
+long double
+coshl(long double x)
+{
+ long double t, w;
+ int32_t ex;
+ ieee_quad_shape_type u;
+
+ u.value = x;
+ ex = u.parts32.mswhi & 0x7fffffff;
+
+ /* Absolute value of x. */
+ u.parts32.mswhi = ex;
+
+ /* x is INF or NaN */
+ if (ex >= 0x7fff0000)
+ return x * x;
+
+ /* |x| in [0,0.5*ln2], return 1+expm1l(|x|)^2/(2*expl(|x|)) */
+ if (ex < 0x3ffd62e4) /* 0.3465728759765625 */
+ {
+ t = expm1l (u.value);
+ w = one + t;
+ if (ex < 0x3fb80000) /* |x| < 2^-116 */
+ return w; /* cosh(tiny) = 1 */
+
+ return one + (t * t) / (w + w);
+ }
+
+ /* |x| in [0.5*ln2,40], return (exp(|x|)+1/exp(|x|)/2; */
+ if (ex < 0x40044000)
+ {
+ t = expl (u.value);
+ return half * t + half / t;
+ }
+
+ /* |x| in [22, ln(maxdouble)] return half*exp(|x|) */
+ if (ex <= 0x400c62e3) /* 11356.375 */
+ return half * expl (u.value);
+
+ /* |x| in [log(maxdouble), overflowthresold] */
+ if (u.value <= ovf_thresh)
+ {
+ w = expl (half * u.value);
+ t = half * w;
+ return t * w;
+ }
+
+ /* |x| > overflowthresold, cosh(x) overflow */
+ return huge * huge;
+}
--- /dev/null
+/* $OpenBSD: e_expl.c,v 1.3 2013/11/12 20:35:18 martynas Exp $ */
+
+/*
+ * Copyright (c) 2008 Stephen L. Moshier <steve@moshier.net>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* expl.c
+ *
+ * Exponential function, 128-bit long double precision
+ *
+ *
+ *
+ * SYNOPSIS:
+ *
+ * long double x, y, expl();
+ *
+ * y = expl( x );
+ *
+ *
+ *
+ * DESCRIPTION:
+ *
+ * Returns e (2.71828...) raised to the x power.
+ *
+ * Range reduction is accomplished by separating the argument
+ * into an integer k and fraction f such that
+ *
+ * x k f
+ * e = 2 e.
+ *
+ * A Pade' form of degree 2/3 is used to approximate exp(f) - 1
+ * in the basic range [-0.5 ln 2, 0.5 ln 2].
+ *
+ *
+ * ACCURACY:
+ *
+ * Relative error:
+ * arithmetic domain # trials peak rms
+ * IEEE +-MAXLOG 100,000 2.6e-34 8.6e-35
+ *
+ *
+ * Error amplification in the exponential function can be
+ * a serious matter. The error propagation involves
+ * exp( X(1+delta) ) = exp(X) ( 1 + X*delta + ... ),
+ * which shows that a 1 lsb error in representing X produces
+ * a relative error of X times 1 lsb in the function.
+ * While the routine gives an accurate result for arguments
+ * that are exactly represented by a long double precision
+ * computer number, the result contains amplified roundoff
+ * error for large arguments not exactly represented.
+ *
+ *
+ * ERROR MESSAGES:
+ *
+ * message condition value returned
+ * exp underflow x < MINLOG 0.0
+ * exp overflow x > MAXLOG MAXNUM
+ *
+ */
+
+/* Exponential function */
+
+#include <float.h>
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+/* Pade' coefficients for exp(x) - 1
+ Theoretical peak relative error = 2.2e-37,
+ relative peak error spread = 9.2e-38
+ */
+static long double P[5] = {
+ 3.279723985560247033712687707263393506266E-10L,
+ 6.141506007208645008909088812338454698548E-7L,
+ 2.708775201978218837374512615596512792224E-4L,
+ 3.508710990737834361215404761139478627390E-2L,
+ 9.999999999999999999999999999999999998502E-1L
+};
+static long double Q[6] = {
+ 2.980756652081995192255342779918052538681E-12L,
+ 1.771372078166251484503904874657985291164E-8L,
+ 1.504792651814944826817779302637284053660E-5L,
+ 3.611828913847589925056132680618007270344E-3L,
+ 2.368408864814233538909747618894558968880E-1L,
+ 2.000000000000000000000000000000000000150E0L
+};
+/* C1 + C2 = ln 2 */
+static const long double C1 = -6.93145751953125E-1L;
+static const long double C2 = -1.428606820309417232121458176568075500134E-6L;
+
+static const long double LOG2EL = 1.442695040888963407359924681001892137426646L;
+static const long double MAXLOGL = 1.1356523406294143949491931077970764891253E4L;
+static const long double MINLOGL = -1.143276959615573793352782661133116431383730e4L;
+static const long double huge = 0x1p10000L;
+#if 0 /* XXX Prevent gcc from erroneously constant folding this. */
+static const long double twom10000 = 0x1p-10000L;
+#else
+static volatile long double twom10000 = 0x1p-10000L;
+#endif
+
+long double
+expl(long double x)
+{
+long double px, xx;
+int n;
+
+if( x > MAXLOGL)
+ return (huge*huge); /* overflow */
+
+if( x < MINLOGL )
+ return (twom10000*twom10000); /* underflow */
+
+/* Express e**x = e**g 2**n
+ * = e**g e**( n loge(2) )
+ * = e**( g + n loge(2) )
+ */
+px = floorl( LOG2EL * x + 0.5L ); /* floor() truncates toward -infinity. */
+n = px;
+x += px * C1;
+x += px * C2;
+/* rational approximation for exponential
+ * of the fractional part:
+ * e**x = 1 + 2x P(x**2)/( Q(x**2) - P(x**2) )
+ */
+xx = x * x;
+px = x * __polevll( xx, P, 4 );
+xx = __polevll( xx, Q, 5 );
+x = px/( xx - px );
+x = 1.0L + x + x;
+
+x = ldexpl( x, n );
+return(x);
+}
--- /dev/null
+/* @(#)e_fmod.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/*
+ * fmodl(x,y)
+ * Return x mod y in exact arithmetic
+ * Method: shift and subtract
+ */
+
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+static const long double one = 1.0, Zero[] = {0.0, -0.0,};
+
+long double
+fmodl(long double x, long double y)
+{
+ int64_t n,hx,hy,hz,ix,iy,sx,i;
+ u_int64_t lx,ly,lz;
+
+ GET_LDOUBLE_WORDS64(hx,lx,x);
+ GET_LDOUBLE_WORDS64(hy,ly,y);
+ sx = hx&0x8000000000000000ULL; /* sign of x */
+ hx ^=sx; /* |x| */
+ hy &= 0x7fffffffffffffffLL; /* |y| */
+
+ /* purge off exception values */
+ if((hy|ly)==0||(hx>=0x7fff000000000000LL)|| /* y=0,or x not finite */
+ ((hy|((ly|-ly)>>63))>0x7fff000000000000LL)) /* or y is NaN */
+ return (x*y)/(x*y);
+ if(hx<=hy) {
+ if((hx<hy)||(lx<ly)) return x; /* |x|<|y| return x */
+ if(lx==ly)
+ return Zero[(u_int64_t)sx>>63]; /* |x|=|y| return x*0*/
+ }
+
+ /* determine ix = ilogb(x) */
+ if(hx<0x0001000000000000LL) { /* subnormal x */
+ if(hx==0) {
+ for (ix = -16431, i=lx; i>0; i<<=1) ix -=1;
+ } else {
+ for (ix = -16382, i=hx<<15; i>0; i<<=1) ix -=1;
+ }
+ } else ix = (hx>>48)-0x3fff;
+
+ /* determine iy = ilogb(y) */
+ if(hy<0x0001000000000000LL) { /* subnormal y */
+ if(hy==0) {
+ for (iy = -16431, i=ly; i>0; i<<=1) iy -=1;
+ } else {
+ for (iy = -16382, i=hy<<15; i>0; i<<=1) iy -=1;
+ }
+ } else iy = (hy>>48)-0x3fff;
+
+ /* set up {hx,lx}, {hy,ly} and align y to x */
+ if(ix >= -16382)
+ hx = 0x0001000000000000LL|(0x0000ffffffffffffLL&hx);
+ else { /* subnormal x, shift x to normal */
+ n = -16382-ix;
+ if(n<=63) {
+ hx = (hx<<n)|(lx>>(64-n));
+ lx <<= n;
+ } else {
+ hx = lx<<(n-64);
+ lx = 0;
+ }
+ }
+ if(iy >= -16382)
+ hy = 0x0001000000000000LL|(0x0000ffffffffffffLL&hy);
+ else { /* subnormal y, shift y to normal */
+ n = -16382-iy;
+ if(n<=63) {
+ hy = (hy<<n)|(ly>>(64-n));
+ ly <<= n;
+ } else {
+ hy = ly<<(n-64);
+ ly = 0;
+ }
+ }
+
+ /* fix point fmod */
+ n = ix - iy;
+ while(n--) {
+ hz=hx-hy;lz=lx-ly; if(lx<ly) hz -= 1;
+ if(hz<0){hx = hx+hx+(lx>>63); lx = lx+lx;}
+ else {
+ if((hz|lz)==0) /* return sign(x)*0 */
+ return Zero[(u_int64_t)sx>>63];
+ hx = hz+hz+(lz>>63); lx = lz+lz;
+ }
+ }
+ hz=hx-hy;lz=lx-ly; if(lx<ly) hz -= 1;
+ if(hz>=0) {hx=hz;lx=lz;}
+
+ /* convert back to floating value and restore the sign */
+ if((hx|lx)==0) /* return sign(x)*0 */
+ return Zero[(u_int64_t)sx>>63];
+ while(hx<0x0001000000000000LL) { /* normalize x */
+ hx = hx+hx+(lx>>63); lx = lx+lx;
+ iy -= 1;
+ }
+ if(iy>= -16382) { /* normalize output */
+ hx = ((hx-0x0001000000000000LL)|((iy+16383)<<48));
+ SET_LDOUBLE_WORDS64(x,hx|sx,lx);
+ } else { /* subnormal output */
+ n = -16382 - iy;
+ if(n<=48) {
+ lx = (lx>>n)|((u_int64_t)hx<<(64-n));
+ hx >>= n;
+ } else if (n<=63) {
+ lx = (hx<<(64-n))|(lx>>n); hx = sx;
+ } else {
+ lx = hx>>(n-64); hx = sx;
+ }
+ SET_LDOUBLE_WORDS64(x,hx|sx,lx);
+ x *= one; /* create necessary signal */
+ }
+ return x; /* exact output */
+}
--- /dev/null
+/* @(#)e_hypot.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/* hypotl(x,y)
+ *
+ * Method :
+ * If (assume round-to-nearest) z=x*x+y*y
+ * has error less than sqrtl(2)/2 ulp, than
+ * sqrtl(z) has error less than 1 ulp (exercise).
+ *
+ * So, compute sqrtl(x*x+y*y) with some care as
+ * follows to get the error below 1 ulp:
+ *
+ * Assume x>y>0;
+ * (if possible, set rounding to round-to-nearest)
+ * 1. if x > 2y use
+ * x1*x1+(y*y+(x2*(x+x1))) for x*x+y*y
+ * where x1 = x with lower 64 bits cleared, x2 = x-x1; else
+ * 2. if x <= 2y use
+ * t1*yy1+((x-y)*(x-y)+(t1*y2+t2*y))
+ * where t1 = 2x with lower 64 bits cleared, t2 = 2x-t1,
+ * yy1= y with lower 64 bits chopped, y2 = y-yy1.
+ *
+ * NOTE: scaling may be necessary if some argument is too
+ * large or too tiny
+ *
+ * Special cases:
+ * hypotl(x,y) is INF if x or y is +INF or -INF; else
+ * hypotl(x,y) is NAN if x or y is NAN.
+ *
+ * Accuracy:
+ * hypotl(x,y) returns sqrtl(x^2+y^2) with error less
+ * than 1 ulps (units in the last place)
+ */
+
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+long double
+hypotl(long double x, long double y)
+{
+ long double a,b,t1,t2,yy1,y2,w;
+ int64_t j,k,ha,hb;
+
+ GET_LDOUBLE_MSW64(ha,x);
+ ha &= 0x7fffffffffffffffLL;
+ GET_LDOUBLE_MSW64(hb,y);
+ hb &= 0x7fffffffffffffffLL;
+ if(hb > ha) {a=y;b=x;j=ha; ha=hb;hb=j;} else {a=x;b=y;}
+ SET_LDOUBLE_MSW64(a,ha); /* a <- |a| */
+ SET_LDOUBLE_MSW64(b,hb); /* b <- |b| */
+ if((ha-hb)>0x78000000000000LL) {return a+b;} /* x/y > 2**120 */
+ k=0;
+ if(ha > 0x5f3f000000000000LL) { /* a>2**8000 */
+ if(ha >= 0x7fff000000000000LL) { /* Inf or NaN */
+ u_int64_t low;
+ w = a+b; /* for sNaN */
+ GET_LDOUBLE_LSW64(low,a);
+ if(((ha&0xffffffffffffLL)|low)==0) w = a;
+ GET_LDOUBLE_LSW64(low,b);
+ if(((hb^0x7fff000000000000LL)|low)==0) w = b;
+ return w;
+ }
+ /* scale a and b by 2**-9600 */
+ ha -= 0x2580000000000000LL;
+ hb -= 0x2580000000000000LL; k += 9600;
+ SET_LDOUBLE_MSW64(a,ha);
+ SET_LDOUBLE_MSW64(b,hb);
+ }
+ if(hb < 0x20bf000000000000LL) { /* b < 2**-8000 */
+ if(hb <= 0x0000ffffffffffffLL) { /* subnormal b or 0 */
+ u_int64_t low;
+ GET_LDOUBLE_LSW64(low,b);
+ if((hb|low)==0) return a;
+ t1=0;
+ SET_LDOUBLE_MSW64(t1,0x7ffd000000000000LL); /* t1=2^16382 */
+ b *= t1;
+ a *= t1;
+ k -= 16382;
+ } else { /* scale a and b by 2^9600 */
+ ha += 0x2580000000000000LL; /* a *= 2^9600 */
+ hb += 0x2580000000000000LL; /* b *= 2^9600 */
+ k -= 9600;
+ SET_LDOUBLE_MSW64(a,ha);
+ SET_LDOUBLE_MSW64(b,hb);
+ }
+ }
+ /* medium size a and b */
+ w = a-b;
+ if (w>b) {
+ t1 = 0;
+ SET_LDOUBLE_MSW64(t1,ha);
+ t2 = a-t1;
+ w = sqrtl(t1*t1-(b*(-b)-t2*(a+t1)));
+ } else {
+ a = a+a;
+ yy1 = 0;
+ SET_LDOUBLE_MSW64(yy1,hb);
+ y2 = b - yy1;
+ t1 = 0;
+ SET_LDOUBLE_MSW64(t1,ha+0x0001000000000000LL);
+ t2 = a - t1;
+ w = sqrtl(t1*yy1-(w*(-w)-(t1*y2+t2*b)));
+ }
+ if(k!=0) {
+ u_int64_t high;
+ t1 = 1.0L;
+ GET_LDOUBLE_MSW64(high,t1);
+ SET_LDOUBLE_MSW64(t1,high+(k<<48));
+ return t1*w;
+ } else return w;
+}
--- /dev/null
+/* $OpenBSD: e_lgammal.c,v 1.3 2011/07/09 05:29:06 martynas Exp $ */
+
+/*
+ * Copyright (c) 2008 Stephen L. Moshier <steve@moshier.net>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* lgammal_r
+ *
+ * Natural logarithm of gamma function
+ *
+ *
+ *
+ * SYNOPSIS:
+ *
+ * long double x, y, lgammal_r();
+ * int signgam;
+ *
+ * y = lgammal_r(x, &signgam);
+ *
+ *
+ *
+ * DESCRIPTION:
+ *
+ * Returns the base e (2.718...) logarithm of the absolute
+ * value of the gamma function of the argument.
+ * The sign (+1 or -1) of the gamma function is returned through signgamp.
+ *
+ * The positive domain is partitioned into numerous segments for approximation.
+ * For x > 10,
+ * log gamma(x) = (x - 0.5) log(x) - x + log sqrt(2 pi) + 1/x R(1/x^2)
+ * Near the minimum at x = x0 = 1.46... the approximation is
+ * log gamma(x0 + z) = log gamma(x0) + z^2 P(z)/Q(z)
+ * for small z.
+ * Elsewhere between 0 and 10,
+ * log gamma(n + z) = log gamma(n) + z P(z)/Q(z)
+ * for various selected n and small z.
+ *
+ * The cosecant reflection formula is employed for negative arguments.
+ *
+ *
+ *
+ * ACCURACY:
+ *
+ *
+ * arithmetic domain # trials peak rms
+ * Relative error:
+ * IEEE 10, 30 100000 3.9e-34 9.8e-35
+ * IEEE 0, 10 100000 3.8e-34 5.3e-35
+ * Absolute error:
+ * IEEE -10, 0 100000 8.0e-34 8.0e-35
+ * IEEE -30, -10 100000 4.4e-34 1.0e-34
+ * IEEE -100, 100 100000 1.0e-34
+ *
+ * The absolute error criterion is the same as relative error
+ * when the function magnitude is greater than one but it is absolute
+ * when the magnitude is less than one.
+ *
+ */
+
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+static const long double PIL = 3.1415926535897932384626433832795028841972E0L;
+static const long double MAXLGM = 1.0485738685148938358098967157129705071571E4928L;
+static const long double one = 1.0L;
+static const long double huge = 1.0e4000L;
+
+/* log gamma(x) = ( x - 0.5 ) * log(x) - x + LS2PI + 1/x P(1/x^2)
+ 1/x <= 0.0741 (x >= 13.495...)
+ Peak relative error 1.5e-36 */
+static const long double ls2pi = 9.1893853320467274178032973640561763986140E-1L;
+#define NRASY 12
+static const long double RASY[NRASY + 1] =
+{
+ 8.333333333333333333333333333310437112111E-2L,
+ -2.777777777777777777777774789556228296902E-3L,
+ 7.936507936507936507795933938448586499183E-4L,
+ -5.952380952380952041799269756378148574045E-4L,
+ 8.417508417507928904209891117498524452523E-4L,
+ -1.917526917481263997778542329739806086290E-3L,
+ 6.410256381217852504446848671499409919280E-3L,
+ -2.955064066900961649768101034477363301626E-2L,
+ 1.796402955865634243663453415388336954675E-1L,
+ -1.391522089007758553455753477688592767741E0L,
+ 1.326130089598399157988112385013829305510E1L,
+ -1.420412699593782497803472576479997819149E2L,
+ 1.218058922427762808938869872528846787020E3L
+};
+
+
+/* log gamma(x+13) = log gamma(13) + x P(x)/Q(x)
+ -0.5 <= x <= 0.5
+ 12.5 <= x+13 <= 13.5
+ Peak relative error 1.1e-36 */
+static const long double lgam13a = 1.9987213134765625E1L;
+static const long double lgam13b = 1.3608962611495173623870550785125024484248E-6L;
+#define NRN13 7
+static const long double RN13[NRN13 + 1] =
+{
+ 8.591478354823578150238226576156275285700E11L,
+ 2.347931159756482741018258864137297157668E11L,
+ 2.555408396679352028680662433943000804616E10L,
+ 1.408581709264464345480765758902967123937E9L,
+ 4.126759849752613822953004114044451046321E7L,
+ 6.133298899622688505854211579222889943778E5L,
+ 3.929248056293651597987893340755876578072E3L,
+ 6.850783280018706668924952057996075215223E0L
+};
+#define NRD13 6
+static const long double RD13[NRD13 + 1] =
+{
+ 3.401225382297342302296607039352935541669E11L,
+ 8.756765276918037910363513243563234551784E10L,
+ 8.873913342866613213078554180987647243903E9L,
+ 4.483797255342763263361893016049310017973E8L,
+ 1.178186288833066430952276702931512870676E7L,
+ 1.519928623743264797939103740132278337476E5L,
+ 7.989298844938119228411117593338850892311E2L
+ /* 1.0E0L */
+};
+
+
+/* log gamma(x+12) = log gamma(12) + x P(x)/Q(x)
+ -0.5 <= x <= 0.5
+ 11.5 <= x+12 <= 12.5
+ Peak relative error 4.1e-36 */
+static const long double lgam12a = 1.75023040771484375E1L;
+static const long double lgam12b = 3.7687254483392876529072161996717039575982E-6L;
+#define NRN12 7
+static const long double RN12[NRN12 + 1] =
+{
+ 4.709859662695606986110997348630997559137E11L,
+ 1.398713878079497115037857470168777995230E11L,
+ 1.654654931821564315970930093932954900867E10L,
+ 9.916279414876676861193649489207282144036E8L,
+ 3.159604070526036074112008954113411389879E7L,
+ 5.109099197547205212294747623977502492861E5L,
+ 3.563054878276102790183396740969279826988E3L,
+ 6.769610657004672719224614163196946862747E0L
+};
+#define NRD12 6
+static const long double RD12[NRD12 + 1] =
+{
+ 1.928167007860968063912467318985802726613E11L,
+ 5.383198282277806237247492369072266389233E10L,
+ 5.915693215338294477444809323037871058363E9L,
+ 3.241438287570196713148310560147925781342E8L,
+ 9.236680081763754597872713592701048455890E6L,
+ 1.292246897881650919242713651166596478850E5L,
+ 7.366532445427159272584194816076600211171E2L
+ /* 1.0E0L */
+};
+
+
+/* log gamma(x+11) = log gamma(11) + x P(x)/Q(x)
+ -0.5 <= x <= 0.5
+ 10.5 <= x+11 <= 11.5
+ Peak relative error 1.8e-35 */
+static const long double lgam11a = 1.5104400634765625E1L;
+static const long double lgam11b = 1.1938309890295225709329251070371882250744E-5L;
+#define NRN11 7
+static const long double RN11[NRN11 + 1] =
+{
+ 2.446960438029415837384622675816736622795E11L,
+ 7.955444974446413315803799763901729640350E10L,
+ 1.030555327949159293591618473447420338444E10L,
+ 6.765022131195302709153994345470493334946E8L,
+ 2.361892792609204855279723576041468347494E7L,
+ 4.186623629779479136428005806072176490125E5L,
+ 3.202506022088912768601325534149383594049E3L,
+ 6.681356101133728289358838690666225691363E0L
+};
+#define NRD11 6
+static const long double RD11[NRD11 + 1] =
+{
+ 1.040483786179428590683912396379079477432E11L,
+ 3.172251138489229497223696648369823779729E10L,
+ 3.806961885984850433709295832245848084614E9L,
+ 2.278070344022934913730015420611609620171E8L,
+ 7.089478198662651683977290023829391596481E6L,
+ 1.083246385105903533237139380509590158658E5L,
+ 6.744420991491385145885727942219463243597E2L
+ /* 1.0E0L */
+};
+
+
+/* log gamma(x+10) = log gamma(10) + x P(x)/Q(x)
+ -0.5 <= x <= 0.5
+ 9.5 <= x+10 <= 10.5
+ Peak relative error 5.4e-37 */
+static const long double lgam10a = 1.280181884765625E1L;
+static const long double lgam10b = 8.6324252196112077178745667061642811492557E-6L;
+#define NRN10 7
+static const long double RN10[NRN10 + 1] =
+{
+ -1.239059737177249934158597996648808363783E14L,
+ -4.725899566371458992365624673357356908719E13L,
+ -7.283906268647083312042059082837754850808E12L,
+ -5.802855515464011422171165179767478794637E11L,
+ -2.532349691157548788382820303182745897298E10L,
+ -5.884260178023777312587193693477072061820E8L,
+ -6.437774864512125749845840472131829114906E6L,
+ -2.350975266781548931856017239843273049384E4L
+};
+#define NRD10 7
+static const long double RD10[NRD10 + 1] =
+{
+ -5.502645997581822567468347817182347679552E13L,
+ -1.970266640239849804162284805400136473801E13L,
+ -2.819677689615038489384974042561531409392E12L,
+ -2.056105863694742752589691183194061265094E11L,
+ -8.053670086493258693186307810815819662078E9L,
+ -1.632090155573373286153427982504851867131E8L,
+ -1.483575879240631280658077826889223634921E6L,
+ -4.002806669713232271615885826373550502510E3L
+ /* 1.0E0L */
+};
+
+
+/* log gamma(x+9) = log gamma(9) + x P(x)/Q(x)
+ -0.5 <= x <= 0.5
+ 8.5 <= x+9 <= 9.5
+ Peak relative error 3.6e-36 */
+static const long double lgam9a = 1.06045989990234375E1L;
+static const long double lgam9b = 3.9037218127284172274007216547549861681400E-6L;
+#define NRN9 7
+static const long double RN9[NRN9 + 1] =
+{
+ -4.936332264202687973364500998984608306189E13L,
+ -2.101372682623700967335206138517766274855E13L,
+ -3.615893404644823888655732817505129444195E12L,
+ -3.217104993800878891194322691860075472926E11L,
+ -1.568465330337375725685439173603032921399E10L,
+ -4.073317518162025744377629219101510217761E8L,
+ -4.983232096406156139324846656819246974500E6L,
+ -2.036280038903695980912289722995505277253E4L
+};
+#define NRD9 7
+static const long double RD9[NRD9 + 1] =
+{
+ -2.306006080437656357167128541231915480393E13L,
+ -9.183606842453274924895648863832233799950E12L,
+ -1.461857965935942962087907301194381010380E12L,
+ -1.185728254682789754150068652663124298303E11L,
+ -5.166285094703468567389566085480783070037E9L,
+ -1.164573656694603024184768200787835094317E8L,
+ -1.177343939483908678474886454113163527909E6L,
+ -3.529391059783109732159524500029157638736E3L
+ /* 1.0E0L */
+};
+
+
+/* log gamma(x+8) = log gamma(8) + x P(x)/Q(x)
+ -0.5 <= x <= 0.5
+ 7.5 <= x+8 <= 8.5
+ Peak relative error 2.4e-37 */
+static const long double lgam8a = 8.525146484375E0L;
+static const long double lgam8b = 1.4876690414300165531036347125050759667737E-5L;
+#define NRN8 8
+static const long double RN8[NRN8 + 1] =
+{
+ 6.600775438203423546565361176829139703289E11L,
+ 3.406361267593790705240802723914281025800E11L,
+ 7.222460928505293914746983300555538432830E10L,
+ 8.102984106025088123058747466840656458342E9L,
+ 5.157620015986282905232150979772409345927E8L,
+ 1.851445288272645829028129389609068641517E7L,
+ 3.489261702223124354745894067468953756656E5L,
+ 2.892095396706665774434217489775617756014E3L,
+ 6.596977510622195827183948478627058738034E0L
+};
+#define NRD8 7
+static const long double RD8[NRD8 + 1] =
+{
+ 3.274776546520735414638114828622673016920E11L,
+ 1.581811207929065544043963828487733970107E11L,
+ 3.108725655667825188135393076860104546416E10L,
+ 3.193055010502912617128480163681842165730E9L,
+ 1.830871482669835106357529710116211541839E8L,
+ 5.790862854275238129848491555068073485086E6L,
+ 9.305213264307921522842678835618803553589E4L,
+ 6.216974105861848386918949336819572333622E2L
+ /* 1.0E0L */
+};
+
+
+/* log gamma(x+7) = log gamma(7) + x P(x)/Q(x)
+ -0.5 <= x <= 0.5
+ 6.5 <= x+7 <= 7.5
+ Peak relative error 3.2e-36 */
+static const long double lgam7a = 6.5792388916015625E0L;
+static const long double lgam7b = 1.2320408538495060178292903945321122583007E-5L;
+#define NRN7 8
+static const long double RN7[NRN7 + 1] =
+{
+ 2.065019306969459407636744543358209942213E11L,
+ 1.226919919023736909889724951708796532847E11L,
+ 2.996157990374348596472241776917953749106E10L,
+ 3.873001919306801037344727168434909521030E9L,
+ 2.841575255593761593270885753992732145094E8L,
+ 1.176342515359431913664715324652399565551E7L,
+ 2.558097039684188723597519300356028511547E5L,
+ 2.448525238332609439023786244782810774702E3L,
+ 6.460280377802030953041566617300902020435E0L
+};
+#define NRD7 7
+static const long double RD7[NRD7 + 1] =
+{
+ 1.102646614598516998880874785339049304483E11L,
+ 6.099297512712715445879759589407189290040E10L,
+ 1.372898136289611312713283201112060238351E10L,
+ 1.615306270420293159907951633566635172343E9L,
+ 1.061114435798489135996614242842561967459E8L,
+ 3.845638971184305248268608902030718674691E6L,
+ 7.081730675423444975703917836972720495507E4L,
+ 5.423122582741398226693137276201344096370E2L
+ /* 1.0E0L */
+};
+
+
+/* log gamma(x+6) = log gamma(6) + x P(x)/Q(x)
+ -0.5 <= x <= 0.5
+ 5.5 <= x+6 <= 6.5
+ Peak relative error 6.2e-37 */
+static const long double lgam6a = 4.7874908447265625E0L;
+static const long double lgam6b = 8.9805548349424770093452324304839959231517E-7L;
+#define NRN6 8
+static const long double RN6[NRN6 + 1] =
+{
+ -3.538412754670746879119162116819571823643E13L,
+ -2.613432593406849155765698121483394257148E13L,
+ -8.020670732770461579558867891923784753062E12L,
+ -1.322227822931250045347591780332435433420E12L,
+ -1.262809382777272476572558806855377129513E11L,
+ -7.015006277027660872284922325741197022467E9L,
+ -2.149320689089020841076532186783055727299E8L,
+ -3.167210585700002703820077565539658995316E6L,
+ -1.576834867378554185210279285358586385266E4L
+};
+#define NRD6 8
+static const long double RD6[NRD6 + 1] =
+{
+ -2.073955870771283609792355579558899389085E13L,
+ -1.421592856111673959642750863283919318175E13L,
+ -4.012134994918353924219048850264207074949E12L,
+ -6.013361045800992316498238470888523722431E11L,
+ -5.145382510136622274784240527039643430628E10L,
+ -2.510575820013409711678540476918249524123E9L,
+ -6.564058379709759600836745035871373240904E7L,
+ -7.861511116647120540275354855221373571536E5L,
+ -2.821943442729620524365661338459579270561E3L
+ /* 1.0E0L */
+};
+
+
+/* log gamma(x+5) = log gamma(5) + x P(x)/Q(x)
+ -0.5 <= x <= 0.5
+ 4.5 <= x+5 <= 5.5
+ Peak relative error 3.4e-37 */
+static const long double lgam5a = 3.17803955078125E0L;
+static const long double lgam5b = 1.4279566695619646941601297055408873990961E-5L;
+#define NRN5 9
+static const long double RN5[NRN5 + 1] =
+{
+ 2.010952885441805899580403215533972172098E11L,
+ 1.916132681242540921354921906708215338584E11L,
+ 7.679102403710581712903937970163206882492E10L,
+ 1.680514903671382470108010973615268125169E10L,
+ 2.181011222911537259440775283277711588410E9L,
+ 1.705361119398837808244780667539728356096E8L,
+ 7.792391565652481864976147945997033946360E6L,
+ 1.910741381027985291688667214472560023819E5L,
+ 2.088138241893612679762260077783794329559E3L,
+ 6.330318119566998299106803922739066556550E0L
+};
+#define NRD5 8
+static const long double RD5[NRD5 + 1] =
+{
+ 1.335189758138651840605141370223112376176E11L,
+ 1.174130445739492885895466097516530211283E11L,
+ 4.308006619274572338118732154886328519910E10L,
+ 8.547402888692578655814445003283720677468E9L,
+ 9.934628078575618309542580800421370730906E8L,
+ 6.847107420092173812998096295422311820672E7L,
+ 2.698552646016599923609773122139463150403E6L,
+ 5.526516251532464176412113632726150253215E4L,
+ 4.772343321713697385780533022595450486932E2L
+ /* 1.0E0L */
+};
+
+
+/* log gamma(x+4) = log gamma(4) + x P(x)/Q(x)
+ -0.5 <= x <= 0.5
+ 3.5 <= x+4 <= 4.5
+ Peak relative error 6.7e-37 */
+static const long double lgam4a = 1.791748046875E0L;
+static const long double lgam4b = 1.1422353055000812477358380702272722990692E-5L;
+#define NRN4 9
+static const long double RN4[NRN4 + 1] =
+{
+ -1.026583408246155508572442242188887829208E13L,
+ -1.306476685384622809290193031208776258809E13L,
+ -7.051088602207062164232806511992978915508E12L,
+ -2.100849457735620004967624442027793656108E12L,
+ -3.767473790774546963588549871673843260569E11L,
+ -4.156387497364909963498394522336575984206E10L,
+ -2.764021460668011732047778992419118757746E9L,
+ -1.036617204107109779944986471142938641399E8L,
+ -1.895730886640349026257780896972598305443E6L,
+ -1.180509051468390914200720003907727988201E4L
+};
+#define NRD4 9
+static const long double RD4[NRD4 + 1] =
+{
+ -8.172669122056002077809119378047536240889E12L,
+ -9.477592426087986751343695251801814226960E12L,
+ -4.629448850139318158743900253637212801682E12L,
+ -1.237965465892012573255370078308035272942E12L,
+ -1.971624313506929845158062177061297598956E11L,
+ -1.905434843346570533229942397763361493610E10L,
+ -1.089409357680461419743730978512856675984E9L,
+ -3.416703082301143192939774401370222822430E7L,
+ -4.981791914177103793218433195857635265295E5L,
+ -2.192507743896742751483055798411231453733E3L
+ /* 1.0E0L */
+};
+
+
+/* log gamma(x+3) = log gamma(3) + x P(x)/Q(x)
+ -0.25 <= x <= 0.5
+ 2.75 <= x+3 <= 3.5
+ Peak relative error 6.0e-37 */
+static const long double lgam3a = 6.93145751953125E-1L;
+static const long double lgam3b = 1.4286068203094172321214581765680755001344E-6L;
+
+#define NRN3 9
+static const long double RN3[NRN3 + 1] =
+{
+ -4.813901815114776281494823863935820876670E11L,
+ -8.425592975288250400493910291066881992620E11L,
+ -6.228685507402467503655405482985516909157E11L,
+ -2.531972054436786351403749276956707260499E11L,
+ -6.170200796658926701311867484296426831687E10L,
+ -9.211477458528156048231908798456365081135E9L,
+ -8.251806236175037114064561038908691305583E8L,
+ -4.147886355917831049939930101151160447495E7L,
+ -1.010851868928346082547075956946476932162E6L,
+ -8.333374463411801009783402800801201603736E3L
+};
+#define NRD3 9
+static const long double RD3[NRD3 + 1] =
+{
+ -5.216713843111675050627304523368029262450E11L,
+ -8.014292925418308759369583419234079164391E11L,
+ -5.180106858220030014546267824392678611990E11L,
+ -1.830406975497439003897734969120997840011E11L,
+ -3.845274631904879621945745960119924118925E10L,
+ -4.891033385370523863288908070309417710903E9L,
+ -3.670172254411328640353855768698287474282E8L,
+ -1.505316381525727713026364396635522516989E7L,
+ -2.856327162923716881454613540575964890347E5L,
+ -1.622140448015769906847567212766206894547E3L
+ /* 1.0E0L */
+};
+
+
+/* log gamma(x+2.5) = log gamma(2.5) + x P(x)/Q(x)
+ -0.125 <= x <= 0.25
+ 2.375 <= x+2.5 <= 2.75 */
+static const long double lgam2r5a = 2.8466796875E-1L;
+static const long double lgam2r5b = 1.4901722919159632494669682701924320137696E-5L;
+#define NRN2r5 8
+static const long double RN2r5[NRN2r5 + 1] =
+{
+ -4.676454313888335499356699817678862233205E9L,
+ -9.361888347911187924389905984624216340639E9L,
+ -7.695353600835685037920815799526540237703E9L,
+ -3.364370100981509060441853085968900734521E9L,
+ -8.449902011848163568670361316804900559863E8L,
+ -1.225249050950801905108001246436783022179E8L,
+ -9.732972931077110161639900388121650470926E6L,
+ -3.695711763932153505623248207576425983573E5L,
+ -4.717341584067827676530426007495274711306E3L
+};
+#define NRD2r5 8
+static const long double RD2r5[NRD2r5 + 1] =
+{
+ -6.650657966618993679456019224416926875619E9L,
+ -1.099511409330635807899718829033488771623E10L,
+ -7.482546968307837168164311101447116903148E9L,
+ -2.702967190056506495988922973755870557217E9L,
+ -5.570008176482922704972943389590409280950E8L,
+ -6.536934032192792470926310043166993233231E7L,
+ -4.101991193844953082400035444146067511725E6L,
+ -1.174082735875715802334430481065526664020E5L,
+ -9.932840389994157592102947657277692978511E2L
+ /* 1.0E0L */
+};
+
+
+/* log gamma(x+2) = x P(x)/Q(x)
+ -0.125 <= x <= +0.375
+ 1.875 <= x+2 <= 2.375
+ Peak relative error 4.6e-36 */
+#define NRN2 9
+static const long double RN2[NRN2 + 1] =
+{
+ -3.716661929737318153526921358113793421524E9L,
+ -1.138816715030710406922819131397532331321E10L,
+ -1.421017419363526524544402598734013569950E10L,
+ -9.510432842542519665483662502132010331451E9L,
+ -3.747528562099410197957514973274474767329E9L,
+ -8.923565763363912474488712255317033616626E8L,
+ -1.261396653700237624185350402781338231697E8L,
+ -9.918402520255661797735331317081425749014E6L,
+ -3.753996255897143855113273724233104768831E5L,
+ -4.778761333044147141559311805999540765612E3L
+};
+#define NRD2 9
+static const long double RD2[NRD2 + 1] =
+{
+ -8.790916836764308497770359421351673950111E9L,
+ -2.023108608053212516399197678553737477486E10L,
+ -1.958067901852022239294231785363504458367E10L,
+ -1.035515043621003101254252481625188704529E10L,
+ -3.253884432621336737640841276619272224476E9L,
+ -6.186383531162456814954947669274235815544E8L,
+ -6.932557847749518463038934953605969951466E7L,
+ -4.240731768287359608773351626528479703758E6L,
+ -1.197343995089189188078944689846348116630E5L,
+ -1.004622911670588064824904487064114090920E3L
+/* 1.0E0 */
+};
+
+
+/* log gamma(x+1.75) = log gamma(1.75) + x P(x)/Q(x)
+ -0.125 <= x <= +0.125
+ 1.625 <= x+1.75 <= 1.875
+ Peak relative error 9.2e-37 */
+static const long double lgam1r75a = -8.441162109375E-2L;
+static const long double lgam1r75b = 1.0500073264444042213965868602268256157604E-5L;
+#define NRN1r75 8
+static const long double RN1r75[NRN1r75 + 1] =
+{
+ -5.221061693929833937710891646275798251513E7L,
+ -2.052466337474314812817883030472496436993E8L,
+ -2.952718275974940270675670705084125640069E8L,
+ -2.132294039648116684922965964126389017840E8L,
+ -8.554103077186505960591321962207519908489E7L,
+ -1.940250901348870867323943119132071960050E7L,
+ -2.379394147112756860769336400290402208435E6L,
+ -1.384060879999526222029386539622255797389E5L,
+ -2.698453601378319296159355612094598695530E3L
+};
+#define NRD1r75 8
+static const long double RD1r75[NRD1r75 + 1] =
+{
+ -2.109754689501705828789976311354395393605E8L,
+ -5.036651829232895725959911504899241062286E8L,
+ -4.954234699418689764943486770327295098084E8L,
+ -2.589558042412676610775157783898195339410E8L,
+ -7.731476117252958268044969614034776883031E7L,
+ -1.316721702252481296030801191240867486965E7L,
+ -1.201296501404876774861190604303728810836E6L,
+ -5.007966406976106636109459072523610273928E4L,
+ -6.155817990560743422008969155276229018209E2L
+ /* 1.0E0L */
+};
+
+
+/* log gamma(x+x0) = y0 + x^2 P(x)/Q(x)
+ -0.0867 <= x <= +0.1634
+ 1.374932... <= x+x0 <= 1.625032...
+ Peak relative error 4.0e-36 */
+static const long double x0a = 1.4616241455078125L;
+static const long double x0b = 7.9994605498412626595423257213002588621246E-6L;
+static const long double y0a = -1.21490478515625E-1L;
+static const long double y0b = 4.1879797753919044854428223084178486438269E-6L;
+#define NRN1r5 8
+static const long double RN1r5[NRN1r5 + 1] =
+{
+ 6.827103657233705798067415468881313128066E5L,
+ 1.910041815932269464714909706705242148108E6L,
+ 2.194344176925978377083808566251427771951E6L,
+ 1.332921400100891472195055269688876427962E6L,
+ 4.589080973377307211815655093824787123508E5L,
+ 8.900334161263456942727083580232613796141E4L,
+ 9.053840838306019753209127312097612455236E3L,
+ 4.053367147553353374151852319743594873771E2L,
+ 5.040631576303952022968949605613514584950E0L
+};
+#define NRD1r5 8
+static const long double RD1r5[NRD1r5 + 1] =
+{
+ 1.411036368843183477558773688484699813355E6L,
+ 4.378121767236251950226362443134306184849E6L,
+ 5.682322855631723455425929877581697918168E6L,
+ 3.999065731556977782435009349967042222375E6L,
+ 1.653651390456781293163585493620758410333E6L,
+ 4.067774359067489605179546964969435858311E5L,
+ 5.741463295366557346748361781768833633256E4L,
+ 4.226404539738182992856094681115746692030E3L,
+ 1.316980975410327975566999780608618774469E2L,
+ /* 1.0E0L */
+};
+
+
+/* log gamma(x+1.25) = log gamma(1.25) + x P(x)/Q(x)
+ -.125 <= x <= +.125
+ 1.125 <= x+1.25 <= 1.375
+ Peak relative error = 4.9e-36 */
+static const long double lgam1r25a = -9.82818603515625E-2L;
+static const long double lgam1r25b = 1.0023929749338536146197303364159774377296E-5L;
+#define NRN1r25 9
+static const long double RN1r25[NRN1r25 + 1] =
+{
+ -9.054787275312026472896002240379580536760E4L,
+ -8.685076892989927640126560802094680794471E4L,
+ 2.797898965448019916967849727279076547109E5L,
+ 6.175520827134342734546868356396008898299E5L,
+ 5.179626599589134831538516906517372619641E5L,
+ 2.253076616239043944538380039205558242161E5L,
+ 5.312653119599957228630544772499197307195E4L,
+ 6.434329437514083776052669599834938898255E3L,
+ 3.385414416983114598582554037612347549220E2L,
+ 4.907821957946273805080625052510832015792E0L
+};
+#define NRD1r25 8
+static const long double RD1r25[NRD1r25 + 1] =
+{
+ 3.980939377333448005389084785896660309000E5L,
+ 1.429634893085231519692365775184490465542E6L,
+ 2.145438946455476062850151428438668234336E6L,
+ 1.743786661358280837020848127465970357893E6L,
+ 8.316364251289743923178092656080441655273E5L,
+ 2.355732939106812496699621491135458324294E5L,
+ 3.822267399625696880571810137601310855419E4L,
+ 3.228463206479133236028576845538387620856E3L,
+ 1.152133170470059555646301189220117965514E2L
+ /* 1.0E0L */
+};
+
+
+/* log gamma(x + 1) = x P(x)/Q(x)
+ 0.0 <= x <= +0.125
+ 1.0 <= x+1 <= 1.125
+ Peak relative error 1.1e-35 */
+#define NRN1 8
+static const long double RN1[NRN1 + 1] =
+{
+ -9.987560186094800756471055681088744738818E3L,
+ -2.506039379419574361949680225279376329742E4L,
+ -1.386770737662176516403363873617457652991E4L,
+ 1.439445846078103202928677244188837130744E4L,
+ 2.159612048879650471489449668295139990693E4L,
+ 1.047439813638144485276023138173676047079E4L,
+ 2.250316398054332592560412486630769139961E3L,
+ 1.958510425467720733041971651126443864041E2L,
+ 4.516830313569454663374271993200291219855E0L
+};
+#define NRD1 7
+static const long double RD1[NRD1 + 1] =
+{
+ 1.730299573175751778863269333703788214547E4L,
+ 6.807080914851328611903744668028014678148E4L,
+ 1.090071629101496938655806063184092302439E5L,
+ 9.124354356415154289343303999616003884080E4L,
+ 4.262071638655772404431164427024003253954E4L,
+ 1.096981664067373953673982635805821283581E4L,
+ 1.431229503796575892151252708527595787588E3L,
+ 7.734110684303689320830401788262295992921E1L
+ /* 1.0E0 */
+};
+
+
+/* log gamma(x + 1) = x P(x)/Q(x)
+ -0.125 <= x <= 0
+ 0.875 <= x+1 <= 1.0
+ Peak relative error 7.0e-37 */
+#define NRNr9 8
+static const long double RNr9[NRNr9 + 1] =
+{
+ 4.441379198241760069548832023257571176884E5L,
+ 1.273072988367176540909122090089580368732E6L,
+ 9.732422305818501557502584486510048387724E5L,
+ -5.040539994443998275271644292272870348684E5L,
+ -1.208719055525609446357448132109723786736E6L,
+ -7.434275365370936547146540554419058907156E5L,
+ -2.075642969983377738209203358199008185741E5L,
+ -2.565534860781128618589288075109372218042E4L,
+ -1.032901669542994124131223797515913955938E3L,
+};
+#define NRDr9 8
+static const long double RDr9[NRDr9 + 1] =
+{
+ -7.694488331323118759486182246005193998007E5L,
+ -3.301918855321234414232308938454112213751E6L,
+ -5.856830900232338906742924836032279404702E6L,
+ -5.540672519616151584486240871424021377540E6L,
+ -3.006530901041386626148342989181721176919E6L,
+ -9.350378280513062139466966374330795935163E5L,
+ -1.566179100031063346901755685375732739511E5L,
+ -1.205016539620260779274902967231510804992E4L,
+ -2.724583156305709733221564484006088794284E2L
+/* 1.0E0 */
+};
+
+
+/* Evaluate P[n] x^n + P[n-1] x^(n-1) + ... + P[0] */
+
+static long double
+neval (long double x, const long double *p, int n)
+{
+ long double y;
+
+ p += n;
+ y = *p--;
+ do
+ {
+ y = y * x + *p--;
+ }
+ while (--n > 0);
+ return y;
+}
+
+
+/* Evaluate x^n+1 + P[n] x^(n) + P[n-1] x^(n-1) + ... + P[0] */
+
+static long double
+deval (long double x, const long double *p, int n)
+{
+ long double y;
+
+ p += n;
+ y = x + *p--;
+ do
+ {
+ y = y * x + *p--;
+ }
+ while (--n > 0);
+ return y;
+}
+
+
+long double
+lgammal_r(long double x, int *signgamp)
+{
+ long double p, q, w, z, nx;
+ int i, nn;
+
+ *signgamp = 1;
+
+ if (!isfinite (x))
+ return x * x;
+
+ if (x == 0.0L)
+ {
+ if (signbit (x))
+ *signgamp = -1;
+ return one / fabsl (x);
+ }
+
+ if (x < 0.0L)
+ {
+ q = -x;
+ p = floorl (q);
+ if (p == q)
+ return (one / (p - p));
+ i = p;
+ if ((i & 1) == 0)
+ *signgamp = -1;
+ else
+ *signgamp = 1;
+ z = q - p;
+ if (z > 0.5L)
+ {
+ p += 1.0L;
+ z = p - q;
+ }
+ z = q * sinl (PIL * z);
+ if (z == 0.0L)
+ return (*signgamp * huge * huge);
+ w = lgammal (q);
+ z = logl (PIL / z) - w;
+ return (z);
+ }
+
+ if (x < 13.5L)
+ {
+ p = 0.0L;
+ nx = floorl (x + 0.5L);
+ nn = nx;
+ switch (nn)
+ {
+ case 0:
+ /* log gamma (x + 1) = log(x) + log gamma(x) */
+ if (x <= 0.125)
+ {
+ p = x * neval (x, RN1, NRN1) / deval (x, RD1, NRD1);
+ }
+ else if (x <= 0.375)
+ {
+ z = x - 0.25L;
+ p = z * neval (z, RN1r25, NRN1r25) / deval (z, RD1r25, NRD1r25);
+ p += lgam1r25b;
+ p += lgam1r25a;
+ }
+ else if (x <= 0.625)
+ {
+ z = x + (1.0L - x0a);
+ z = z - x0b;
+ p = neval (z, RN1r5, NRN1r5) / deval (z, RD1r5, NRD1r5);
+ p = p * z * z;
+ p = p + y0b;
+ p = p + y0a;
+ }
+ else if (x <= 0.875)
+ {
+ z = x - 0.75L;
+ p = z * neval (z, RN1r75, NRN1r75) / deval (z, RD1r75, NRD1r75);
+ p += lgam1r75b;
+ p += lgam1r75a;
+ }
+ else
+ {
+ z = x - 1.0L;
+ p = z * neval (z, RN2, NRN2) / deval (z, RD2, NRD2);
+ }
+ p = p - logl (x);
+ break;
+
+ case 1:
+ if (x < 0.875L)
+ {
+ if (x <= 0.625)
+ {
+ z = x + (1.0L - x0a);
+ z = z - x0b;
+ p = neval (z, RN1r5, NRN1r5) / deval (z, RD1r5, NRD1r5);
+ p = p * z * z;
+ p = p + y0b;
+ p = p + y0a;
+ }
+ else if (x <= 0.875)
+ {
+ z = x - 0.75L;
+ p = z * neval (z, RN1r75, NRN1r75)
+ / deval (z, RD1r75, NRD1r75);
+ p += lgam1r75b;
+ p += lgam1r75a;
+ }
+ else
+ {
+ z = x - 1.0L;
+ p = z * neval (z, RN2, NRN2) / deval (z, RD2, NRD2);
+ }
+ p = p - logl (x);
+ }
+ else if (x < 1.0L)
+ {
+ z = x - 1.0L;
+ p = z * neval (z, RNr9, NRNr9) / deval (z, RDr9, NRDr9);
+ }
+ else if (x == 1.0L)
+ p = 0.0L;
+ else if (x <= 1.125L)
+ {
+ z = x - 1.0L;
+ p = z * neval (z, RN1, NRN1) / deval (z, RD1, NRD1);
+ }
+ else if (x <= 1.375)
+ {
+ z = x - 1.25L;
+ p = z * neval (z, RN1r25, NRN1r25) / deval (z, RD1r25, NRD1r25);
+ p += lgam1r25b;
+ p += lgam1r25a;
+ }
+ else
+ {
+ /* 1.375 <= x+x0 <= 1.625 */
+ z = x - x0a;
+ z = z - x0b;
+ p = neval (z, RN1r5, NRN1r5) / deval (z, RD1r5, NRD1r5);
+ p = p * z * z;
+ p = p + y0b;
+ p = p + y0a;
+ }
+ break;
+
+ case 2:
+ if (x < 1.625L)
+ {
+ z = x - x0a;
+ z = z - x0b;
+ p = neval (z, RN1r5, NRN1r5) / deval (z, RD1r5, NRD1r5);
+ p = p * z * z;
+ p = p + y0b;
+ p = p + y0a;
+ }
+ else if (x < 1.875L)
+ {
+ z = x - 1.75L;
+ p = z * neval (z, RN1r75, NRN1r75) / deval (z, RD1r75, NRD1r75);
+ p += lgam1r75b;
+ p += lgam1r75a;
+ }
+ else if (x == 2.0L)
+ p = 0.0L;
+ else if (x < 2.375L)
+ {
+ z = x - 2.0L;
+ p = z * neval (z, RN2, NRN2) / deval (z, RD2, NRD2);
+ }
+ else
+ {
+ z = x - 2.5L;
+ p = z * neval (z, RN2r5, NRN2r5) / deval (z, RD2r5, NRD2r5);
+ p += lgam2r5b;
+ p += lgam2r5a;
+ }
+ break;
+
+ case 3:
+ if (x < 2.75)
+ {
+ z = x - 2.5L;
+ p = z * neval (z, RN2r5, NRN2r5) / deval (z, RD2r5, NRD2r5);
+ p += lgam2r5b;
+ p += lgam2r5a;
+ }
+ else
+ {
+ z = x - 3.0L;
+ p = z * neval (z, RN3, NRN3) / deval (z, RD3, NRD3);
+ p += lgam3b;
+ p += lgam3a;
+ }
+ break;
+
+ case 4:
+ z = x - 4.0L;
+ p = z * neval (z, RN4, NRN4) / deval (z, RD4, NRD4);
+ p += lgam4b;
+ p += lgam4a;
+ break;
+
+ case 5:
+ z = x - 5.0L;
+ p = z * neval (z, RN5, NRN5) / deval (z, RD5, NRD5);
+ p += lgam5b;
+ p += lgam5a;
+ break;
+
+ case 6:
+ z = x - 6.0L;
+ p = z * neval (z, RN6, NRN6) / deval (z, RD6, NRD6);
+ p += lgam6b;
+ p += lgam6a;
+ break;
+
+ case 7:
+ z = x - 7.0L;
+ p = z * neval (z, RN7, NRN7) / deval (z, RD7, NRD7);
+ p += lgam7b;
+ p += lgam7a;
+ break;
+
+ case 8:
+ z = x - 8.0L;
+ p = z * neval (z, RN8, NRN8) / deval (z, RD8, NRD8);
+ p += lgam8b;
+ p += lgam8a;
+ break;
+
+ case 9:
+ z = x - 9.0L;
+ p = z * neval (z, RN9, NRN9) / deval (z, RD9, NRD9);
+ p += lgam9b;
+ p += lgam9a;
+ break;
+
+ case 10:
+ z = x - 10.0L;
+ p = z * neval (z, RN10, NRN10) / deval (z, RD10, NRD10);
+ p += lgam10b;
+ p += lgam10a;
+ break;
+
+ case 11:
+ z = x - 11.0L;
+ p = z * neval (z, RN11, NRN11) / deval (z, RD11, NRD11);
+ p += lgam11b;
+ p += lgam11a;
+ break;
+
+ case 12:
+ z = x - 12.0L;
+ p = z * neval (z, RN12, NRN12) / deval (z, RD12, NRD12);
+ p += lgam12b;
+ p += lgam12a;
+ break;
+
+ case 13:
+ z = x - 13.0L;
+ p = z * neval (z, RN13, NRN13) / deval (z, RD13, NRD13);
+ p += lgam13b;
+ p += lgam13a;
+ break;
+ }
+ return p;
+ }
+
+ if (x > MAXLGM)
+ return (*signgamp * huge * huge);
+
+ q = ls2pi - x;
+ q = (x - 0.5L) * logl (x) + q;
+ if (x > 1.0e18L)
+ return (q);
+
+ p = 1.0L / (x * x);
+ q += neval (p, RASY, NRASY) / x;
+ return (q);
+}
--- /dev/null
+/* $OpenBSD: e_log10l.c,v 1.1 2011/07/06 00:02:42 martynas Exp $ */
+
+/*
+ * Copyright (c) 2008 Stephen L. Moshier <steve@moshier.net>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* log10l.c
+ *
+ * Common logarithm, 128-bit long double precision
+ *
+ *
+ *
+ * SYNOPSIS:
+ *
+ * long double x, y, log10l();
+ *
+ * y = log10l( x );
+ *
+ *
+ *
+ * DESCRIPTION:
+ *
+ * Returns the base 10 logarithm of x.
+ *
+ * The argument is separated into its exponent and fractional
+ * parts. If the exponent is between -1 and +1, the logarithm
+ * of the fraction is approximated by
+ *
+ * log(1+x) = x - 0.5 x^2 + x^3 P(x)/Q(x).
+ *
+ * Otherwise, setting z = 2(x-1)/x+1),
+ *
+ * log(x) = z + z^3 P(z)/Q(z).
+ *
+ *
+ *
+ * ACCURACY:
+ *
+ * Relative error:
+ * arithmetic domain # trials peak rms
+ * IEEE 0.5, 2.0 30000 2.3e-34 4.9e-35
+ * IEEE exp(+-10000) 30000 1.0e-34 4.1e-35
+ *
+ * In the tests over the interval exp(+-10000), the logarithms
+ * of the random arguments were uniformly distributed over
+ * [-10000, +10000].
+ *
+ */
+
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+/* Coefficients for ln(1+x) = x - x**2/2 + x**3 P(x)/Q(x)
+ * 1/sqrt(2) <= x < sqrt(2)
+ * Theoretical peak relative error = 5.3e-37,
+ * relative peak error spread = 2.3e-14
+ */
+static const long double P[13] =
+{
+ 1.313572404063446165910279910527789794488E4L,
+ 7.771154681358524243729929227226708890930E4L,
+ 2.014652742082537582487669938141683759923E5L,
+ 3.007007295140399532324943111654767187848E5L,
+ 2.854829159639697837788887080758954924001E5L,
+ 1.797628303815655343403735250238293741397E5L,
+ 7.594356839258970405033155585486712125861E4L,
+ 2.128857716871515081352991964243375186031E4L,
+ 3.824952356185897735160588078446136783779E3L,
+ 4.114517881637811823002128927449878962058E2L,
+ 2.321125933898420063925789532045674660756E1L,
+ 4.998469661968096229986658302195402690910E-1L,
+ 1.538612243596254322971797716843006400388E-6L
+};
+static const long double Q[12] =
+{
+ 3.940717212190338497730839731583397586124E4L,
+ 2.626900195321832660448791748036714883242E5L,
+ 7.777690340007566932935753241556479363645E5L,
+ 1.347518538384329112529391120390701166528E6L,
+ 1.514882452993549494932585972882995548426E6L,
+ 1.158019977462989115839826904108208787040E6L,
+ 6.132189329546557743179177159925690841200E5L,
+ 2.248234257620569139969141618556349415120E5L,
+ 5.605842085972455027590989944010492125825E4L,
+ 9.147150349299596453976674231612674085381E3L,
+ 9.104928120962988414618126155557301584078E2L,
+ 4.839208193348159620282142911143429644326E1L
+/* 1.000000000000000000000000000000000000000E0L, */
+};
+
+/* Coefficients for log(x) = z + z^3 P(z^2)/Q(z^2),
+ * where z = 2(x-1)/(x+1)
+ * 1/sqrt(2) <= x < sqrt(2)
+ * Theoretical peak relative error = 1.1e-35,
+ * relative peak error spread 1.1e-9
+ */
+static const long double R[6] =
+{
+ 1.418134209872192732479751274970992665513E5L,
+ -8.977257995689735303686582344659576526998E4L,
+ 2.048819892795278657810231591630928516206E4L,
+ -2.024301798136027039250415126250455056397E3L,
+ 8.057002716646055371965756206836056074715E1L,
+ -8.828896441624934385266096344596648080902E-1L
+};
+static const long double S[6] =
+{
+ 1.701761051846631278975701529965589676574E6L,
+ -1.332535117259762928288745111081235577029E6L,
+ 4.001557694070773974936904547424676279307E5L,
+ -5.748542087379434595104154610899551484314E4L,
+ 3.998526750980007367835804959888064681098E3L,
+ -1.186359407982897997337150403816839480438E2L
+/* 1.000000000000000000000000000000000000000E0L, */
+};
+
+static const long double
+/* log10(2) */
+L102A = 0.3125L,
+L102B = -1.14700043360188047862611052755069732318101185E-2L,
+/* log10(e) */
+L10EA = 0.5L,
+L10EB = -6.570551809674817234887108108339491770560299E-2L,
+/* sqrt(2)/2 */
+SQRTH = 7.071067811865475244008443621048490392848359E-1L;
+
+
+
+/* Evaluate P[n] x^n + P[n-1] x^(n-1) + ... + P[0] */
+
+static long double
+neval (long double x, const long double *p, int n)
+{
+ long double y;
+
+ p += n;
+ y = *p--;
+ do
+ {
+ y = y * x + *p--;
+ }
+ while (--n > 0);
+ return y;
+}
+
+
+/* Evaluate x^n+1 + P[n] x^(n) + P[n-1] x^(n-1) + ... + P[0] */
+
+static long double
+deval (long double x, const long double *p, int n)
+{
+ long double y;
+
+ p += n;
+ y = x + *p--;
+ do
+ {
+ y = y * x + *p--;
+ }
+ while (--n > 0);
+ return y;
+}
+
+
+
+long double
+log10l(long double x)
+{
+ long double z;
+ long double y;
+ int e;
+ int64_t hx, lx;
+
+/* Test for domain */
+ GET_LDOUBLE_WORDS64 (hx, lx, x);
+ if (((hx & 0x7fffffffffffffffLL) | lx) == 0)
+ return (-1.0L / (x - x));
+ if (hx < 0)
+ return (x - x) / (x - x);
+ if (hx >= 0x7fff000000000000LL)
+ return (x + x);
+
+/* separate mantissa from exponent */
+
+/* Note, frexp is used so that denormal numbers
+ * will be handled properly.
+ */
+ x = frexpl (x, &e);
+
+
+/* logarithm using log(x) = z + z**3 P(z)/Q(z),
+ * where z = 2(x-1)/x+1)
+ */
+ if ((e > 2) || (e < -2))
+ {
+ if (x < SQRTH)
+ { /* 2( 2x-1 )/( 2x+1 ) */
+ e -= 1;
+ z = x - 0.5L;
+ y = 0.5L * z + 0.5L;
+ }
+ else
+ { /* 2 (x-1)/(x+1) */
+ z = x - 0.5L;
+ z -= 0.5L;
+ y = 0.5L * x + 0.5L;
+ }
+ x = z / y;
+ z = x * x;
+ y = x * (z * neval (z, R, 5) / deval (z, S, 5));
+ goto done;
+ }
+
+
+/* logarithm using log(1+x) = x - .5x**2 + x**3 P(x)/Q(x) */
+
+ if (x < SQRTH)
+ {
+ e -= 1;
+ x = 2.0 * x - 1.0L; /* 2x - 1 */
+ }
+ else
+ {
+ x = x - 1.0L;
+ }
+ z = x * x;
+ y = x * (z * neval (x, P, 12) / deval (x, Q, 11));
+ y = y - 0.5 * z;
+
+done:
+
+ /* Multiply log of fraction by log10(e)
+ * and base 2 exponent by log10(2).
+ */
+ z = y * L10EB;
+ z += x * L10EB;
+ z += e * L102B;
+ z += y * L10EA;
+ z += x * L10EA;
+ z += e * L102A;
+ return (z);
+}
--- /dev/null
+/* $OpenBSD: e_log2l.c,v 1.1 2011/07/06 00:02:42 martynas Exp $ */
+
+/*
+ * Copyright (c) 2008 Stephen L. Moshier <steve@moshier.net>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* log2l.c
+ * Base 2 logarithm, 128-bit long double precision
+ *
+ *
+ *
+ * SYNOPSIS:
+ *
+ * long double x, y, log2l();
+ *
+ * y = log2l( x );
+ *
+ *
+ *
+ * DESCRIPTION:
+ *
+ * Returns the base 2 logarithm of x.
+ *
+ * The argument is separated into its exponent and fractional
+ * parts. If the exponent is between -1 and +1, the (natural)
+ * logarithm of the fraction is approximated by
+ *
+ * log(1+x) = x - 0.5 x^2 + x^3 P(x)/Q(x).
+ *
+ * Otherwise, setting z = 2(x-1)/x+1),
+ *
+ * log(x) = z + z^3 P(z)/Q(z).
+ *
+ *
+ *
+ * ACCURACY:
+ *
+ * Relative error:
+ * arithmetic domain # trials peak rms
+ * IEEE 0.5, 2.0 100,000 2.6e-34 4.9e-35
+ * IEEE exp(+-10000) 100,000 9.6e-35 4.0e-35
+ *
+ * In the tests over the interval exp(+-10000), the logarithms
+ * of the random arguments were uniformly distributed over
+ * [-10000, +10000].
+ *
+ */
+
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+/* Coefficients for ln(1+x) = x - x**2/2 + x**3 P(x)/Q(x)
+ * 1/sqrt(2) <= x < sqrt(2)
+ * Theoretical peak relative error = 5.3e-37,
+ * relative peak error spread = 2.3e-14
+ */
+static const long double P[13] =
+{
+ 1.313572404063446165910279910527789794488E4L,
+ 7.771154681358524243729929227226708890930E4L,
+ 2.014652742082537582487669938141683759923E5L,
+ 3.007007295140399532324943111654767187848E5L,
+ 2.854829159639697837788887080758954924001E5L,
+ 1.797628303815655343403735250238293741397E5L,
+ 7.594356839258970405033155585486712125861E4L,
+ 2.128857716871515081352991964243375186031E4L,
+ 3.824952356185897735160588078446136783779E3L,
+ 4.114517881637811823002128927449878962058E2L,
+ 2.321125933898420063925789532045674660756E1L,
+ 4.998469661968096229986658302195402690910E-1L,
+ 1.538612243596254322971797716843006400388E-6L
+};
+static const long double Q[12] =
+{
+ 3.940717212190338497730839731583397586124E4L,
+ 2.626900195321832660448791748036714883242E5L,
+ 7.777690340007566932935753241556479363645E5L,
+ 1.347518538384329112529391120390701166528E6L,
+ 1.514882452993549494932585972882995548426E6L,
+ 1.158019977462989115839826904108208787040E6L,
+ 6.132189329546557743179177159925690841200E5L,
+ 2.248234257620569139969141618556349415120E5L,
+ 5.605842085972455027590989944010492125825E4L,
+ 9.147150349299596453976674231612674085381E3L,
+ 9.104928120962988414618126155557301584078E2L,
+ 4.839208193348159620282142911143429644326E1L
+/* 1.000000000000000000000000000000000000000E0L, */
+};
+
+/* Coefficients for log(x) = z + z^3 P(z^2)/Q(z^2),
+ * where z = 2(x-1)/(x+1)
+ * 1/sqrt(2) <= x < sqrt(2)
+ * Theoretical peak relative error = 1.1e-35,
+ * relative peak error spread 1.1e-9
+ */
+static const long double R[6] =
+{
+ 1.418134209872192732479751274970992665513E5L,
+ -8.977257995689735303686582344659576526998E4L,
+ 2.048819892795278657810231591630928516206E4L,
+ -2.024301798136027039250415126250455056397E3L,
+ 8.057002716646055371965756206836056074715E1L,
+ -8.828896441624934385266096344596648080902E-1L
+};
+static const long double S[6] =
+{
+ 1.701761051846631278975701529965589676574E6L,
+ -1.332535117259762928288745111081235577029E6L,
+ 4.001557694070773974936904547424676279307E5L,
+ -5.748542087379434595104154610899551484314E4L,
+ 3.998526750980007367835804959888064681098E3L,
+ -1.186359407982897997337150403816839480438E2L
+/* 1.000000000000000000000000000000000000000E0L, */
+};
+
+static const long double
+/* log2(e) - 1 */
+LOG2EA = 4.4269504088896340735992468100189213742664595E-1L,
+/* sqrt(2)/2 */
+SQRTH = 7.071067811865475244008443621048490392848359E-1L;
+
+
+/* Evaluate P[n] x^n + P[n-1] x^(n-1) + ... + P[0] */
+
+static long double
+neval (long double x, const long double *p, int n)
+{
+ long double y;
+
+ p += n;
+ y = *p--;
+ do
+ {
+ y = y * x + *p--;
+ }
+ while (--n > 0);
+ return y;
+}
+
+
+/* Evaluate x^n+1 + P[n] x^(n) + P[n-1] x^(n-1) + ... + P[0] */
+
+static long double
+deval (long double x, const long double *p, int n)
+{
+ long double y;
+
+ p += n;
+ y = x + *p--;
+ do
+ {
+ y = y * x + *p--;
+ }
+ while (--n > 0);
+ return y;
+}
+
+
+
+long double
+log2l(long double x)
+{
+ long double z;
+ long double y;
+ int e;
+ int64_t hx, lx;
+
+/* Test for domain */
+ GET_LDOUBLE_WORDS64 (hx, lx, x);
+ if (((hx & 0x7fffffffffffffffLL) | lx) == 0)
+ return (-1.0L / (x - x));
+ if (hx < 0)
+ return (x - x) / (x - x);
+ if (hx >= 0x7fff000000000000LL)
+ return (x + x);
+
+/* separate mantissa from exponent */
+
+/* Note, frexp is used so that denormal numbers
+ * will be handled properly.
+ */
+ x = frexpl (x, &e);
+
+
+/* logarithm using log(x) = z + z**3 P(z)/Q(z),
+ * where z = 2(x-1)/x+1)
+ */
+ if ((e > 2) || (e < -2))
+ {
+ if (x < SQRTH)
+ { /* 2( 2x-1 )/( 2x+1 ) */
+ e -= 1;
+ z = x - 0.5L;
+ y = 0.5L * z + 0.5L;
+ }
+ else
+ { /* 2 (x-1)/(x+1) */
+ z = x - 0.5L;
+ z -= 0.5L;
+ y = 0.5L * x + 0.5L;
+ }
+ x = z / y;
+ z = x * x;
+ y = x * (z * neval (z, R, 5) / deval (z, S, 5));
+ goto done;
+ }
+
+
+/* logarithm using log(1+x) = x - .5x**2 + x**3 P(x)/Q(x) */
+
+ if (x < SQRTH)
+ {
+ e -= 1;
+ x = 2.0 * x - 1.0L; /* 2x - 1 */
+ }
+ else
+ {
+ x = x - 1.0L;
+ }
+ z = x * x;
+ y = x * (z * neval (x, P, 12) / deval (x, Q, 11));
+ y = y - 0.5 * z;
+
+done:
+
+/* Multiply log of fraction by log2(e)
+ * and base 2 exponent by 1
+ */
+ z = y * LOG2EA;
+ z += x * LOG2EA;
+ z += y;
+ z += x;
+ z += e;
+ return (z);
+}
--- /dev/null
+/* $OpenBSD: e_logl.c,v 1.1 2011/07/06 00:02:42 martynas Exp $ */
+
+/*
+ * Copyright (c) 2008 Stephen L. Moshier <steve@moshier.net>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* logl.c
+ *
+ * Natural logarithm for 128-bit long double precision.
+ *
+ *
+ *
+ * SYNOPSIS:
+ *
+ * long double x, y, logl();
+ *
+ * y = logl( x );
+ *
+ *
+ *
+ * DESCRIPTION:
+ *
+ * Returns the base e (2.718...) logarithm of x.
+ *
+ * The argument is separated into its exponent and fractional
+ * parts. Use of a lookup table increases the speed of the routine.
+ * The program uses logarithms tabulated at intervals of 1/128 to
+ * cover the domain from approximately 0.7 to 1.4.
+ *
+ * On the interval [-1/128, +1/128] the logarithm of 1+x is approximated by
+ * log(1+x) = x - 0.5 x^2 + x^3 P(x) .
+ *
+ *
+ *
+ * ACCURACY:
+ *
+ * Relative error:
+ * arithmetic domain # trials peak rms
+ * IEEE 0.875, 1.125 100000 1.2e-34 4.1e-35
+ * IEEE 0.125, 8 100000 1.2e-34 4.1e-35
+ *
+ *
+ * WARNING:
+ *
+ * This program uses integer operations on bit fields of floating-point
+ * numbers. It does not work with data structures other than the
+ * structure assumed.
+ *
+ */
+
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+/* log(1+x) = x - .5 x^2 + x^3 l(x)
+ -.0078125 <= x <= +.0078125
+ peak relative error 1.2e-37 */
+static const long double
+l3 = 3.333333333333333333333333333333336096926E-1L,
+l4 = -2.499999999999999999999999999486853077002E-1L,
+l5 = 1.999999999999999999999999998515277861905E-1L,
+l6 = -1.666666666666666666666798448356171665678E-1L,
+l7 = 1.428571428571428571428808945895490721564E-1L,
+l8 = -1.249999999999999987884655626377588149000E-1L,
+l9 = 1.111111111111111093947834982832456459186E-1L,
+l10 = -1.000000000000532974938900317952530453248E-1L,
+l11 = 9.090909090915566247008015301349979892689E-2L,
+l12 = -8.333333211818065121250921925397567745734E-2L,
+l13 = 7.692307559897661630807048686258659316091E-2L,
+l14 = -7.144242754190814657241902218399056829264E-2L,
+l15 = 6.668057591071739754844678883223432347481E-2L;
+
+/* Lookup table of ln(t) - (t-1)
+ t = 0.5 + (k+26)/128)
+ k = 0, ..., 91 */
+static const long double logtbl[92] = {
+-5.5345593589352099112142921677820359632418E-2L,
+-5.2108257402767124761784665198737642086148E-2L,
+-4.8991686870576856279407775480686721935120E-2L,
+-4.5993270766361228596215288742353061431071E-2L,
+-4.3110481649613269682442058976885699556950E-2L,
+-4.0340872319076331310838085093194799765520E-2L,
+-3.7682072451780927439219005993827431503510E-2L,
+-3.5131785416234343803903228503274262719586E-2L,
+-3.2687785249045246292687241862699949178831E-2L,
+-3.0347913785027239068190798397055267411813E-2L,
+-2.8110077931525797884641940838507561326298E-2L,
+-2.5972247078357715036426583294246819637618E-2L,
+-2.3932450635346084858612873953407168217307E-2L,
+-2.1988775689981395152022535153795155900240E-2L,
+-2.0139364778244501615441044267387667496733E-2L,
+-1.8382413762093794819267536615342902718324E-2L,
+-1.6716169807550022358923589720001638093023E-2L,
+-1.5138929457710992616226033183958974965355E-2L,
+-1.3649036795397472900424896523305726435029E-2L,
+-1.2244881690473465543308397998034325468152E-2L,
+-1.0924898127200937840689817557742469105693E-2L,
+-9.6875626072830301572839422532631079809328E-3L,
+-8.5313926245226231463436209313499745894157E-3L,
+-7.4549452072765973384933565912143044991706E-3L,
+-6.4568155251217050991200599386801665681310E-3L,
+-5.5356355563671005131126851708522185605193E-3L,
+-4.6900728132525199028885749289712348829878E-3L,
+-3.9188291218610470766469347968659624282519E-3L,
+-3.2206394539524058873423550293617843896540E-3L,
+-2.5942708080877805657374888909297113032132E-3L,
+-2.0385211375711716729239156839929281289086E-3L,
+-1.5522183228760777967376942769773768850872E-3L,
+-1.1342191863606077520036253234446621373191E-3L,
+-7.8340854719967065861624024730268350459991E-4L,
+-4.9869831458030115699628274852562992756174E-4L,
+-2.7902661731604211834685052867305795169688E-4L,
+-1.2335696813916860754951146082826952093496E-4L,
+-3.0677461025892873184042490943581654591817E-5L,
+#define ZERO logtbl[38]
+ 0.0000000000000000000000000000000000000000E0L,
+-3.0359557945051052537099938863236321874198E-5L,
+-1.2081346403474584914595395755316412213151E-4L,
+-2.7044071846562177120083903771008342059094E-4L,
+-4.7834133324631162897179240322783590830326E-4L,
+-7.4363569786340080624467487620270965403695E-4L,
+-1.0654639687057968333207323853366578860679E-3L,
+-1.4429854811877171341298062134712230604279E-3L,
+-1.8753781835651574193938679595797367137975E-3L,
+-2.3618380914922506054347222273705859653658E-3L,
+-2.9015787624124743013946600163375853631299E-3L,
+-3.4938307889254087318399313316921940859043E-3L,
+-4.1378413103128673800485306215154712148146E-3L,
+-4.8328735414488877044289435125365629849599E-3L,
+-5.5782063183564351739381962360253116934243E-3L,
+-6.3731336597098858051938306767880719015261E-3L,
+-7.2169643436165454612058905294782949315193E-3L,
+-8.1090214990427641365934846191367315083867E-3L,
+-9.0486422112807274112838713105168375482480E-3L,
+-1.0035177140880864314674126398350812606841E-2L,
+-1.1067990155502102718064936259435676477423E-2L,
+-1.2146457974158024928196575103115488672416E-2L,
+-1.3269969823361415906628825374158424754308E-2L,
+-1.4437927104692837124388550722759686270765E-2L,
+-1.5649743073340777659901053944852735064621E-2L,
+-1.6904842527181702880599758489058031645317E-2L,
+-1.8202661505988007336096407340750378994209E-2L,
+-1.9542647000370545390701192438691126552961E-2L,
+-2.0924256670080119637427928803038530924742E-2L,
+-2.2346958571309108496179613803760727786257E-2L,
+-2.3810230892650362330447187267648486279460E-2L,
+-2.5313561699385640380910474255652501521033E-2L,
+-2.6856448685790244233704909690165496625399E-2L,
+-2.8438398935154170008519274953860128449036E-2L,
+-3.0058928687233090922411781058956589863039E-2L,
+-3.1717563112854831855692484086486099896614E-2L,
+-3.3413836095418743219397234253475252001090E-2L,
+-3.5147290019036555862676702093393332533702E-2L,
+-3.6917475563073933027920505457688955423688E-2L,
+-3.8723951502862058660874073462456610731178E-2L,
+-4.0566284516358241168330505467000838017425E-2L,
+-4.2444048996543693813649967076598766917965E-2L,
+-4.4356826869355401653098777649745233339196E-2L,
+-4.6304207416957323121106944474331029996141E-2L,
+-4.8285787106164123613318093945035804818364E-2L,
+-5.0301169421838218987124461766244507342648E-2L,
+-5.2349964705088137924875459464622098310997E-2L,
+-5.4431789996103111613753440311680967840214E-2L,
+-5.6546268881465384189752786409400404404794E-2L,
+-5.8693031345788023909329239565012647817664E-2L,
+-6.0871713627532018185577188079210189048340E-2L,
+-6.3081958078862169742820420185833800925568E-2L,
+-6.5323413029406789694910800219643791556918E-2L,
+-6.7595732653791419081537811574227049288168E-2L
+};
+
+/* ln(2) = ln2a + ln2b with extended precision. */
+static const long double
+ ln2a = 6.93145751953125e-1L,
+ ln2b = 1.4286068203094172321214581765680755001344E-6L;
+
+long double
+logl(long double x)
+{
+ long double z, y, w;
+ ieee_quad_shape_type u, t;
+ unsigned int m;
+ int k, e;
+
+ u.value = x;
+ m = u.parts32.mswhi;
+
+ /* Check for IEEE special cases. */
+ k = m & 0x7fffffff;
+ /* log(0) = -infinity. */
+ if ((k | u.parts32.mswlo | u.parts32.lswhi | u.parts32.lswlo) == 0)
+ {
+ return -0.5L / ZERO;
+ }
+ /* log ( x < 0 ) = NaN */
+ if (m & 0x80000000)
+ {
+ return (x - x) / ZERO;
+ }
+ /* log (infinity or NaN) */
+ if (k >= 0x7fff0000)
+ {
+ return x + x;
+ }
+
+ /* Extract exponent and reduce domain to 0.703125 <= u < 1.40625 */
+ e = (int) (m >> 16) - (int) 0x3ffe;
+ m &= 0xffff;
+ u.parts32.mswhi = m | 0x3ffe0000;
+ m |= 0x10000;
+ /* Find lookup table index k from high order bits of the significand. */
+ if (m < 0x16800)
+ {
+ k = (m - 0xff00) >> 9;
+ /* t is the argument 0.5 + (k+26)/128
+ of the nearest item to u in the lookup table. */
+ t.parts32.mswhi = 0x3fff0000 + (k << 9);
+ t.parts32.mswlo = 0;
+ t.parts32.lswhi = 0;
+ t.parts32.lswlo = 0;
+ u.parts32.mswhi += 0x10000;
+ e -= 1;
+ k += 64;
+ }
+ else
+ {
+ k = (m - 0xfe00) >> 10;
+ t.parts32.mswhi = 0x3ffe0000 + (k << 10);
+ t.parts32.mswlo = 0;
+ t.parts32.lswhi = 0;
+ t.parts32.lswlo = 0;
+ }
+ /* On this interval the table is not used due to cancellation error. */
+ if ((x <= 1.0078125L) && (x >= 0.9921875L))
+ {
+ z = x - 1.0L;
+ k = 64;
+ t.value = 1.0L;
+ e = 0;
+ }
+ else
+ {
+ /* log(u) = log( t u/t ) = log(t) + log(u/t)
+ log(t) is tabulated in the lookup table.
+ Express log(u/t) = log(1+z), where z = u/t - 1 = (u-t)/t.
+ cf. Cody & Waite. */
+ z = (u.value - t.value) / t.value;
+ }
+ /* Series expansion of log(1+z). */
+ w = z * z;
+ y = ((((((((((((l15 * z
+ + l14) * z
+ + l13) * z
+ + l12) * z
+ + l11) * z
+ + l10) * z
+ + l9) * z
+ + l8) * z
+ + l7) * z
+ + l6) * z
+ + l5) * z
+ + l4) * z
+ + l3) * z * w;
+ y -= 0.5 * w;
+ y += e * ln2b; /* Base 2 exponent offset times ln(2). */
+ y += z;
+ y += logtbl[k-26]; /* log(t) - (t-1) */
+ y += (t.value - 1.0L);
+ y += e * ln2a;
+ return y;
+}
--- /dev/null
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/*
+ * Copyright (c) 2008 Stephen L. Moshier <steve@moshier.net>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* powl(x,y) return x**y
+ *
+ * n
+ * Method: Let x = 2 * (1+f)
+ * 1. Compute and return log2(x) in two pieces:
+ * log2(x) = w1 + w2,
+ * where w1 has 113-53 = 60 bit trailing zeros.
+ * 2. Perform y*log2(x) = n+y' by simulating muti-precision
+ * arithmetic, where |y'|<=0.5.
+ * 3. Return x**y = 2**n*exp(y'*log2)
+ *
+ * Special cases:
+ * 1. (anything) ** 0 is 1
+ * 2. (anything) ** 1 is itself
+ * 3. (anything) ** NAN is NAN
+ * 4. NAN ** (anything except 0) is NAN
+ * 5. +-(|x| > 1) ** +INF is +INF
+ * 6. +-(|x| > 1) ** -INF is +0
+ * 7. +-(|x| < 1) ** +INF is +0
+ * 8. +-(|x| < 1) ** -INF is +INF
+ * 9. +-1 ** +-INF is NAN
+ * 10. +0 ** (+anything except 0, NAN) is +0
+ * 11. -0 ** (+anything except 0, NAN, odd integer) is +0
+ * 12. +0 ** (-anything except 0, NAN) is +INF
+ * 13. -0 ** (-anything except 0, NAN, odd integer) is +INF
+ * 14. -0 ** (odd integer) = -( +0 ** (odd integer) )
+ * 15. +INF ** (+anything except 0,NAN) is +INF
+ * 16. +INF ** (-anything except 0,NAN) is +0
+ * 17. -INF ** (anything) = -0 ** (-anything)
+ * 18. (-anything) ** (integer) is (-1)**(integer)*(+anything**integer)
+ * 19. (-anything except 0 and inf) ** (non-integer) is NAN
+ *
+ */
+
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+static const long double bp[] = {
+ 1.0L,
+ 1.5L,
+};
+
+/* log_2(1.5) */
+static const long double dp_h[] = {
+ 0.0,
+ 5.8496250072115607565592654282227158546448E-1L
+};
+
+/* Low part of log_2(1.5) */
+static const long double dp_l[] = {
+ 0.0,
+ 1.0579781240112554492329533686862998106046E-16L
+};
+
+static const long double zero = 0.0L,
+ one = 1.0L,
+ two = 2.0L,
+ two113 = 1.0384593717069655257060992658440192E34L,
+ huge = 1.0e3000L,
+ tiny = 1.0e-3000L;
+
+/* 3/2 log x = 3 z + z^3 + z^3 (z^2 R(z^2))
+ z = (x-1)/(x+1)
+ 1 <= x <= 1.25
+ Peak relative error 2.3e-37 */
+static const long double LN[] =
+{
+ -3.0779177200290054398792536829702930623200E1L,
+ 6.5135778082209159921251824580292116201640E1L,
+ -4.6312921812152436921591152809994014413540E1L,
+ 1.2510208195629420304615674658258363295208E1L,
+ -9.9266909031921425609179910128531667336670E-1L
+};
+static const long double LD[] =
+{
+ -5.129862866715009066465422805058933131960E1L,
+ 1.452015077564081884387441590064272782044E2L,
+ -1.524043275549860505277434040464085593165E2L,
+ 7.236063513651544224319663428634139768808E1L,
+ -1.494198912340228235853027849917095580053E1L
+ /* 1.0E0 */
+};
+
+/* exp(x) = 1 + x - x / (1 - 2 / (x - x^2 R(x^2)))
+ 0 <= x <= 0.5
+ Peak relative error 5.7e-38 */
+static const long double PN[] =
+{
+ 5.081801691915377692446852383385968225675E8L,
+ 9.360895299872484512023336636427675327355E6L,
+ 4.213701282274196030811629773097579432957E4L,
+ 5.201006511142748908655720086041570288182E1L,
+ 9.088368420359444263703202925095675982530E-3L,
+};
+static const long double PD[] =
+{
+ 3.049081015149226615468111430031590411682E9L,
+ 1.069833887183886839966085436512368982758E8L,
+ 8.259257717868875207333991924545445705394E5L,
+ 1.872583833284143212651746812884298360922E3L,
+ /* 1.0E0 */
+};
+
+static const long double
+ /* ln 2 */
+ lg2 = 6.9314718055994530941723212145817656807550E-1L,
+ lg2_h = 6.9314718055994528622676398299518041312695E-1L,
+ lg2_l = 2.3190468138462996154948554638754786504121E-17L,
+ ovt = 8.0085662595372944372e-0017L,
+ /* 2/(3*log(2)) */
+ cp = 9.6179669392597560490661645400126142495110E-1L,
+ cp_h = 9.6179669392597555432899980587535537779331E-1L,
+ cp_l = 5.0577616648125906047157785230014751039424E-17L;
+
+long double
+powl(long double x, long double y)
+{
+ long double z, ax, z_h, z_l, p_h, p_l;
+ long double yy1, t1, t2, r, s, t, u, v, w;
+ long double s2, s_h, s_l, t_h, t_l;
+ int32_t i, j, k, yisint, n;
+ u_int32_t ix, iy;
+ int32_t hx, hy;
+ ieee_quad_shape_type o, p, q;
+
+ p.value = x;
+ hx = p.parts32.mswhi;
+ ix = hx & 0x7fffffff;
+
+ q.value = y;
+ hy = q.parts32.mswhi;
+ iy = hy & 0x7fffffff;
+
+
+ /* y==zero: x**0 = 1 */
+ if ((iy | q.parts32.mswlo | q.parts32.lswhi | q.parts32.lswlo) == 0)
+ return one;
+
+ /* 1.0**y = 1; -1.0**+-Inf = 1 */
+ if (x == one)
+ return one;
+ if (x == -1.0L && iy == 0x7fff0000
+ && (q.parts32.mswlo | q.parts32.lswhi | q.parts32.lswlo) == 0)
+ return one;
+
+ /* +-NaN return x+y */
+ if ((ix > 0x7fff0000)
+ || ((ix == 0x7fff0000)
+ && ((p.parts32.mswlo | p.parts32.lswhi | p.parts32.lswlo) != 0))
+ || (iy > 0x7fff0000)
+ || ((iy == 0x7fff0000)
+ && ((q.parts32.mswlo | q.parts32.lswhi | q.parts32.lswlo) != 0)))
+ return x + y;
+
+ /* determine if y is an odd int when x < 0
+ * yisint = 0 ... y is not an integer
+ * yisint = 1 ... y is an odd int
+ * yisint = 2 ... y is an even int
+ */
+ yisint = 0;
+ if (hx < 0)
+ {
+ if (iy >= 0x40700000) /* 2^113 */
+ yisint = 2; /* even integer y */
+ else if (iy >= 0x3fff0000) /* 1.0 */
+ {
+ if (floorl (y) == y)
+ {
+ z = 0.5 * y;
+ if (floorl (z) == z)
+ yisint = 2;
+ else
+ yisint = 1;
+ }
+ }
+ }
+
+ /* special value of y */
+ if ((q.parts32.mswlo | q.parts32.lswhi | q.parts32.lswlo) == 0)
+ {
+ if (iy == 0x7fff0000) /* y is +-inf */
+ {
+ if (((ix - 0x3fff0000) | p.parts32.mswlo | p.parts32.lswhi |
+ p.parts32.lswlo) == 0)
+ return y - y; /* +-1**inf is NaN */
+ else if (ix >= 0x3fff0000) /* (|x|>1)**+-inf = inf,0 */
+ return (hy >= 0) ? y : zero;
+ else /* (|x|<1)**-,+inf = inf,0 */
+ return (hy < 0) ? -y : zero;
+ }
+ if (iy == 0x3fff0000)
+ { /* y is +-1 */
+ if (hy < 0)
+ return one / x;
+ else
+ return x;
+ }
+ if (hy == 0x40000000)
+ return x * x; /* y is 2 */
+ if (hy == 0x3ffe0000)
+ { /* y is 0.5 */
+ if (hx >= 0) /* x >= +0 */
+ return sqrtl (x);
+ }
+ }
+
+ ax = fabsl (x);
+ /* special value of x */
+ if ((p.parts32.mswlo | p.parts32.lswhi | p.parts32.lswlo) == 0)
+ {
+ if (ix == 0x7fff0000 || ix == 0 || ix == 0x3fff0000)
+ {
+ z = ax; /*x is +-0,+-inf,+-1 */
+ if (hy < 0)
+ z = one / z; /* z = (1/|x|) */
+ if (hx < 0)
+ {
+ if (((ix - 0x3fff0000) | yisint) == 0)
+ {
+ z = (z - z) / (z - z); /* (-1)**non-int is NaN */
+ }
+ else if (yisint == 1)
+ z = -z; /* (x<0)**odd = -(|x|**odd) */
+ }
+ return z;
+ }
+ }
+
+ /* (x<0)**(non-int) is NaN */
+ if (((((u_int32_t) hx >> 31) - 1) | yisint) == 0)
+ return (x - x) / (x - x);
+
+ /* |y| is huge.
+ 2^-16495 = 1/2 of smallest representable value.
+ If (1 - 1/131072)^y underflows, y > 1.4986e9 */
+ if (iy > 0x401d654b)
+ {
+ /* if (1 - 2^-113)^y underflows, y > 1.1873e38 */
+ if (iy > 0x407d654b)
+ {
+ if (ix <= 0x3ffeffff)
+ return (hy < 0) ? huge * huge : tiny * tiny;
+ if (ix >= 0x3fff0000)
+ return (hy > 0) ? huge * huge : tiny * tiny;
+ }
+ /* over/underflow if x is not close to one */
+ if (ix < 0x3ffeffff)
+ return (hy < 0) ? huge * huge : tiny * tiny;
+ if (ix > 0x3fff0000)
+ return (hy > 0) ? huge * huge : tiny * tiny;
+ }
+
+ n = 0;
+ /* take care subnormal number */
+ if (ix < 0x00010000)
+ {
+ ax *= two113;
+ n -= 113;
+ o.value = ax;
+ ix = o.parts32.mswhi;
+ }
+ n += ((ix) >> 16) - 0x3fff;
+ j = ix & 0x0000ffff;
+ /* determine interval */
+ ix = j | 0x3fff0000; /* normalize ix */
+ if (j <= 0x3988)
+ k = 0; /* |x|<sqrt(3/2) */
+ else if (j < 0xbb67)
+ k = 1; /* |x|<sqrt(3) */
+ else
+ {
+ k = 0;
+ n += 1;
+ ix -= 0x00010000;
+ }
+
+ o.value = ax;
+ o.parts32.mswhi = ix;
+ ax = o.value;
+
+ /* compute s = s_h+s_l = (x-1)/(x+1) or (x-1.5)/(x+1.5) */
+ u = ax - bp[k]; /* bp[0]=1.0, bp[1]=1.5 */
+ v = one / (ax + bp[k]);
+ s = u * v;
+ s_h = s;
+
+ o.value = s_h;
+ o.parts32.lswlo = 0;
+ o.parts32.lswhi &= 0xf8000000;
+ s_h = o.value;
+ /* t_h=ax+bp[k] High */
+ t_h = ax + bp[k];
+ o.value = t_h;
+ o.parts32.lswlo = 0;
+ o.parts32.lswhi &= 0xf8000000;
+ t_h = o.value;
+ t_l = ax - (t_h - bp[k]);
+ s_l = v * ((u - s_h * t_h) - s_h * t_l);
+ /* compute log(ax) */
+ s2 = s * s;
+ u = LN[0] + s2 * (LN[1] + s2 * (LN[2] + s2 * (LN[3] + s2 * LN[4])));
+ v = LD[0] + s2 * (LD[1] + s2 * (LD[2] + s2 * (LD[3] + s2 * (LD[4] + s2))));
+ r = s2 * s2 * u / v;
+ r += s_l * (s_h + s);
+ s2 = s_h * s_h;
+ t_h = 3.0 + s2 + r;
+ o.value = t_h;
+ o.parts32.lswlo = 0;
+ o.parts32.lswhi &= 0xf8000000;
+ t_h = o.value;
+ t_l = r - ((t_h - 3.0) - s2);
+ /* u+v = s*(1+...) */
+ u = s_h * t_h;
+ v = s_l * t_h + t_l * s;
+ /* 2/(3log2)*(s+...) */
+ p_h = u + v;
+ o.value = p_h;
+ o.parts32.lswlo = 0;
+ o.parts32.lswhi &= 0xf8000000;
+ p_h = o.value;
+ p_l = v - (p_h - u);
+ z_h = cp_h * p_h; /* cp_h+cp_l = 2/(3*log2) */
+ z_l = cp_l * p_h + p_l * cp + dp_l[k];
+ /* log2(ax) = (s+..)*2/(3*log2) = n + dp_h + z_h + z_l */
+ t = (long double) n;
+ t1 = (((z_h + z_l) + dp_h[k]) + t);
+ o.value = t1;
+ o.parts32.lswlo = 0;
+ o.parts32.lswhi &= 0xf8000000;
+ t1 = o.value;
+ t2 = z_l - (((t1 - t) - dp_h[k]) - z_h);
+
+ /* s (sign of result -ve**odd) = -1 else = 1 */
+ s = one;
+ if (((((u_int32_t) hx >> 31) - 1) | (yisint - 1)) == 0)
+ s = -one; /* (-ve)**(odd int) */
+
+ /* split up y into yy1+y2 and compute (yy1+y2)*(t1+t2) */
+ yy1 = y;
+ o.value = yy1;
+ o.parts32.lswlo = 0;
+ o.parts32.lswhi &= 0xf8000000;
+ yy1 = o.value;
+ p_l = (y - yy1) * t1 + y * t2;
+ p_h = yy1 * t1;
+ z = p_l + p_h;
+ o.value = z;
+ j = o.parts32.mswhi;
+ if (j >= 0x400d0000) /* z >= 16384 */
+ {
+ /* if z > 16384 */
+ if (((j - 0x400d0000) | o.parts32.mswlo | o.parts32.lswhi |
+ o.parts32.lswlo) != 0)
+ return s * huge * huge; /* overflow */
+ else
+ {
+ if (p_l + ovt > z - p_h)
+ return s * huge * huge; /* overflow */
+ }
+ }
+ else if ((j & 0x7fffffff) >= 0x400d01b9) /* z <= -16495 */
+ {
+ /* z < -16495 */
+ if (((j - 0xc00d01bc) | o.parts32.mswlo | o.parts32.lswhi |
+ o.parts32.lswlo)
+ != 0)
+ return s * tiny * tiny; /* underflow */
+ else
+ {
+ if (p_l <= z - p_h)
+ return s * tiny * tiny; /* underflow */
+ }
+ }
+ /* compute 2**(p_h+p_l) */
+ i = j & 0x7fffffff;
+ k = (i >> 16) - 0x3fff;
+ n = 0;
+ if (i > 0x3ffe0000)
+ { /* if |z| > 0.5, set n = [z+0.5] */
+ n = floorl (z + 0.5L);
+ t = n;
+ p_h -= t;
+ }
+ t = p_l + p_h;
+ o.value = t;
+ o.parts32.lswlo = 0;
+ o.parts32.lswhi &= 0xf8000000;
+ t = o.value;
+ u = t * lg2_h;
+ v = (p_l - (t - p_h)) * lg2 + t * lg2_l;
+ z = u + v;
+ w = v - (z - u);
+ /* exp(z) */
+ t = z * z;
+ u = PN[0] + t * (PN[1] + t * (PN[2] + t * (PN[3] + t * PN[4])));
+ v = PD[0] + t * (PD[1] + t * (PD[2] + t * (PD[3] + t)));
+ t1 = z - t * u / v;
+ r = (z * t1) / (t1 - two) - (w + z * w);
+ z = one - (r - z);
+ o.value = z;
+ j = o.parts32.mswhi;
+ j += (n << 16);
+ if ((j >> 16) <= 0)
+ z = scalbnl (z, n); /* subnormal output */
+ else
+ {
+ o.parts32.mswhi = j;
+ z = o.value;
+ }
+ return s * z;
+}
--- /dev/null
+/* From: @(#)e_rem_pio2.c 1.4 95/01/18 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ * Copyright (c) 2008 Steven G. Kargl, David Schultz, Bruce D. Evans.
+ *
+ * Developed at SunSoft, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ *
+ * Optimized by Bruce D. Evans.
+ */
+
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/ld128/e_rem_pio2l.h,v 1.2 2011/05/30 19:41:28 kargl Exp $");
+
+/* ld128 version of __ieee754_rem_pio2l(x,y)
+ *
+ * return the remainder of x rem pi/2 in y[0]+y[1]
+ * use __kernel_rem_pio2()
+ */
+
+#include <float.h>
+#include <openlibm_math.h>
+
+#include "math_private.h"
+#include "fpmath.h"
+
+#define BIAS (LDBL_MAX_EXP - 1)
+
+/*
+ * XXX need to verify that nonzero integer multiples of pi/2 within the
+ * range get no closer to a long double than 2**-140, or that
+ * ilogb(x) + ilogb(min_delta) < 45 - -140.
+ */
+/*
+ * invpio2: 113 bits of 2/pi
+ * pio2_1: first 68 bits of pi/2
+ * pio2_1t: pi/2 - pio2_1
+ * pio2_2: second 68 bits of pi/2
+ * pio2_2t: pi/2 - (pio2_1+pio2_2)
+ * pio2_3: third 68 bits of pi/2
+ * pio2_3t: pi/2 - (pio2_1+pio2_2+pio2_3)
+ */
+
+static const double
+zero = 0.00000000000000000000e+00, /* 0x00000000, 0x00000000 */
+two24 = 1.67772160000000000000e+07; /* 0x41700000, 0x00000000 */
+
+static const long double
+invpio2 = 6.3661977236758134307553505349005747e-01L, /* 0x145f306dc9c882a53f84eafa3ea6a.0p-113 */
+pio2_1 = 1.5707963267948966192292994253909555e+00L, /* 0x1921fb54442d18469800000000000.0p-112 */
+pio2_1t = 2.0222662487959507323996846200947577e-21L, /* 0x13198a2e03707344a4093822299f3.0p-181 */
+pio2_2 = 2.0222662487959507323994779168837751e-21L, /* 0x13198a2e03707344a400000000000.0p-181 */
+pio2_2t = 2.0670321098263988236496903051604844e-43L, /* 0x127044533e63a0105df531d89cd91.0p-254 */
+pio2_3 = 2.0670321098263988236499468110329591e-43L, /* 0x127044533e63a0105e00000000000.0p-254 */
+pio2_3t = -2.5650587247459238361625433492959285e-65L; /* -0x159c4ec64ddaeb5f78671cbfb2210.0p-327 */
+
+//VBS
+//static inline __always_inline int
+//__ieee754_rem_pio2l(long double x, long double *y)
+
+static inline int
+__ieee754_rem_pio2l(long double x, long double *y)
+{
+ union IEEEl2bits u,u1;
+ long double z,w,t,r,fn;
+ double tx[5],ty[3];
+ int64_t n;
+ int e0,ex,i,j,nx;
+ int16_t expsign;
+
+ u.e = x;
+ expsign = u.xbits.expsign;
+ ex = expsign & 0x7fff;
+ if (ex < BIAS + 45 || ex == BIAS + 45 &&
+ u.bits.manh < 0x921fb54442d1LL) {
+ /* |x| ~< 2^45*(pi/2), medium size */
+ /* Use a specialized rint() to get fn. Assume round-to-nearest. */
+ fn = x*invpio2+0x1.8p112;
+ fn = fn-0x1.8p112;
+#ifdef HAVE_EFFICIENT_I64RINT
+ n = i64rint(fn);
+#else
+ n = fn;
+#endif
+ r = x-fn*pio2_1;
+ w = fn*pio2_1t; /* 1st round good to 180 bit */
+ {
+ union IEEEl2bits u2;
+ int ex1;
+ j = ex;
+ y[0] = r-w;
+ u2.e = y[0];
+ ex1 = u2.xbits.expsign & 0x7fff;
+ i = j-ex1;
+ if(i>51) { /* 2nd iteration needed, good to 248 */
+ t = r;
+ w = fn*pio2_2;
+ r = t-w;
+ w = fn*pio2_2t-((t-r)-w);
+ y[0] = r-w;
+ u2.e = y[0];
+ ex1 = u2.xbits.expsign & 0x7fff;
+ i = j-ex1;
+ if(i>119) { /* 3rd iteration need, 316 bits acc */
+ t = r; /* will cover all possible cases */
+ w = fn*pio2_3;
+ r = t-w;
+ w = fn*pio2_3t-((t-r)-w);
+ y[0] = r-w;
+ }
+ }
+ }
+ y[1] = (r-y[0])-w;
+ return n;
+ }
+ /*
+ * all other (large) arguments
+ */
+ if(ex==0x7fff) { /* x is inf or NaN */
+ y[0]=y[1]=x-x; return 0;
+ }
+ /* set z = scalbn(|x|,ilogb(x)-23) */
+ u1.e = x;
+ e0 = ex - BIAS - 23; /* e0 = ilogb(|x|)-23; */
+ u1.xbits.expsign = ex - e0;
+ z = u1.e;
+ for(i=0;i<4;i++) {
+ tx[i] = (double)((int32_t)(z));
+ z = (z-tx[i])*two24;
+ }
+ tx[4] = z;
+ nx = 5;
+ while(tx[nx-1]==zero) nx--; /* skip zero term */
+ n = __kernel_rem_pio2(tx,ty,e0,nx,3);
+ t = (long double)ty[2] + ty[1];
+ r = t + ty[0];
+ w = ty[0] - (r - t);
+ if(expsign<0) {y[0] = -r; y[1] = -w; return -n;}
+ y[0] = r; y[1] = w; return n;
+}
--- /dev/null
+/* @(#)e_sinh.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/*
+ * Copyright (c) 2008 Stephen L. Moshier <steve@moshier.net>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* sinhl(x)
+ * Method :
+ * mathematically sinh(x) if defined to be (exp(x)-exp(-x))/2
+ * 1. Replace x by |x| (sinhl(-x) = -sinhl(x)).
+ * 2.
+ * E + E/(E+1)
+ * 0 <= x <= 25 : sinhl(x) := --------------, E=expm1l(x)
+ * 2
+ *
+ * 25 <= x <= lnovft : sinhl(x) := expl(x)/2
+ * lnovft <= x <= ln2ovft: sinhl(x) := expl(x/2)/2 * expl(x/2)
+ * ln2ovft < x : sinhl(x) := x*shuge (overflow)
+ *
+ * Special cases:
+ * sinhl(x) is |x| if x is +INF, -INF, or NaN.
+ * only sinhl(0)=0 is exact for finite x.
+ */
+
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+static const long double one = 1.0, shuge = 1.0e4931L,
+ovf_thresh = 1.1357216553474703894801348310092223067821E4L;
+
+long double
+sinhl(long double x)
+{
+ long double t, w, h;
+ u_int32_t jx, ix;
+ ieee_quad_shape_type u;
+
+ /* Words of |x|. */
+ u.value = x;
+ jx = u.parts32.mswhi;
+ ix = jx & 0x7fffffff;
+
+ /* x is INF or NaN */
+ if (ix >= 0x7fff0000)
+ return x + x;
+
+ h = 0.5;
+ if (jx & 0x80000000)
+ h = -h;
+
+ /* Absolute value of x. */
+ u.parts32.mswhi = ix;
+
+ /* |x| in [0,40], return sign(x)*0.5*(E+E/(E+1))) */
+ if (ix <= 0x40044000)
+ {
+ if (ix < 0x3fc60000) /* |x| < 2^-57 */
+ if (shuge + x > one)
+ return x; /* sinh(tiny) = tiny with inexact */
+ t = expm1l (u.value);
+ if (ix < 0x3fff0000)
+ return h * (2.0 * t - t * t / (t + one));
+ return h * (t + t / (t + one));
+ }
+
+ /* |x| in [40, log(maxdouble)] return 0.5*exp(|x|) */
+ if (ix <= 0x400c62e3) /* 11356.375 */
+ return h * expl (u.value);
+
+ /* |x| in [log(maxdouble), overflowthreshold]
+ Overflow threshold is log(2 * maxdouble). */
+ if (u.value <= ovf_thresh)
+ {
+ w = expl (0.5 * u.value);
+ t = h * w;
+ return t * w;
+ }
+
+ /* |x| > overflowthreshold, sinhl(x) overflow */
+ return x * shuge;
+}
--- /dev/null
+/* $OpenBSD: e_tgammal.c,v 1.1 2011/07/06 00:02:42 martynas Exp $ */
+
+/*
+ * Copyright (c) 2011 Martynas Venckus <martynas@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+long double
+tgammal(long double x)
+{
+ int64_t i0,i1;
+
+ GET_LDOUBLE_WORDS64(i0,i1,x);
+ if (((i0&0x7fffffffffffffffLL)|i1) == 0)
+ return (1.0/x);
+
+ if (i0<0 && (u_int64_t)i0<0xffff000000000000ULL && rintl(x)==x)
+ return (x-x)/(x-x);
+
+ if (i0==0xffff000000000000ULL && i1==0)
+ return (x-x);
+
+ return expl(lgammal(x));
+}
--- /dev/null
+/*-
+ * Copyright (c) 2008 David Schultz <das@FreeBSD.ORG>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/ld128/invtrig.c,v 1.1 2008/07/31 22:41:26 das Exp $");
+
+#include "ld128/invtrig.h"
+
+/*
+ * asinl() and acosl()
+ */
+const long double
+pS0 = 1.66666666666666666666666666666700314e-01L,
+pS1 = -7.32816946414566252574527475428622708e-01L,
+pS2 = 1.34215708714992334609030036562143589e+00L,
+pS3 = -1.32483151677116409805070261790752040e+00L,
+pS4 = 7.61206183613632558824485341162121989e-01L,
+pS5 = -2.56165783329023486777386833928147375e-01L,
+pS6 = 4.80718586374448793411019434585413855e-02L,
+pS7 = -4.42523267167024279410230886239774718e-03L,
+pS8 = 1.44551535183911458253205638280410064e-04L,
+pS9 = -2.10558957916600254061591040482706179e-07L,
+qS1 = -4.84690167848739751544716485245697428e+00L,
+qS2 = 9.96619113536172610135016921140206980e+00L,
+qS3 = -1.13177895428973036660836798461641458e+01L,
+qS4 = 7.74004374389488266169304117714658761e+00L,
+qS5 = -3.25871986053534084709023539900339905e+00L,
+qS6 = 8.27830318881232209752469022352928864e-01L,
+qS7 = -1.18768052702942805423330715206348004e-01L,
+qS8 = 8.32600764660522313269101537926539470e-03L,
+qS9 = -1.99407384882605586705979504567947007e-04L;
+
+/*
+ * atanl()
+ */
+const long double atanhi[] = {
+ 4.63647609000806116214256231461214397e-01L,
+ 7.85398163397448309615660845819875699e-01L,
+ 9.82793723247329067985710611014666038e-01L,
+ 1.57079632679489661923132169163975140e+00L,
+};
+
+const long double atanlo[] = {
+ 4.89509642257333492668618435220297706e-36L,
+ 2.16795253253094525619926100651083806e-35L,
+ -2.31288434538183565909319952098066272e-35L,
+ 4.33590506506189051239852201302167613e-35L,
+};
+
+const long double aT[] = {
+ 3.33333333333333333333333333333333125e-01L,
+ -1.99999999999999999999999999999180430e-01L,
+ 1.42857142857142857142857142125269827e-01L,
+ -1.11111111111111111111110834490810169e-01L,
+ 9.09090909090909090908522355708623681e-02L,
+ -7.69230769230769230696553844935357021e-02L,
+ 6.66666666666666660390096773046256096e-02L,
+ -5.88235294117646671706582985209643694e-02L,
+ 5.26315789473666478515847092020327506e-02L,
+ -4.76190476189855517021024424991436144e-02L,
+ 4.34782608678695085948531993458097026e-02L,
+ -3.99999999632663469330634215991142368e-02L,
+ 3.70370363987423702891250829918659723e-02L,
+ -3.44827496515048090726669907612335954e-02L,
+ 3.22579620681420149871973710852268528e-02L,
+ -3.03020767654269261041647570626778067e-02L,
+ 2.85641979882534783223403715930946138e-02L,
+ -2.69824879726738568189929461383741323e-02L,
+ 2.54194698498808542954187110873675769e-02L,
+ -2.35083879708189059926183138130183215e-02L,
+ 2.04832358998165364349957325067131428e-02L,
+ -1.54489555488544397858507248612362957e-02L,
+ 8.64492360989278761493037861575248038e-03L,
+ -2.58521121597609872727919154569765469e-03L,
+};
+
+const long double pi_lo = 8.67181013012378102479704402604335225e-35L;
--- /dev/null
+/*-
+ * Copyright (c) 2008 David Schultz <das@FreeBSD.ORG>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: src/lib/msun/ld128/invtrig.h,v 1.1 2008/07/31 22:41:26 das Exp $
+ */
+
+#include <float.h>
+
+#include "fpmath.h"
+
+#define BIAS (LDBL_MAX_EXP - 1)
+#define MANH_SIZE (LDBL_MANH_SIZE + 1)
+
+/* Approximation thresholds. */
+#define ASIN_LINEAR (BIAS - 56) /* 2**-56 */
+#define ACOS_CONST (BIAS - 113) /* 2**-113 */
+#define ATAN_CONST (BIAS + 113) /* 2**113 */
+#define ATAN_LINEAR (BIAS - 56) /* 2**-56 */
+
+/* 0.95 */
+#define THRESH ((0xe666666666666666ULL>>(64-(MANH_SIZE-1)))|LDBL_NBIT)
+
+/* Constants shared by the long double inverse trig functions. */
+#define pS0 _ItL_pS0
+#define pS1 _ItL_pS1
+#define pS2 _ItL_pS2
+#define pS3 _ItL_pS3
+#define pS4 _ItL_pS4
+#define pS5 _ItL_pS5
+#define pS6 _ItL_pS6
+#define pS7 _ItL_pS7
+#define pS8 _ItL_pS8
+#define pS9 _ItL_pS9
+#define qS1 _ItL_qS1
+#define qS2 _ItL_qS2
+#define qS3 _ItL_qS3
+#define qS4 _ItL_qS4
+#define qS5 _ItL_qS5
+#define qS6 _ItL_qS6
+#define qS7 _ItL_qS7
+#define qS8 _ItL_qS8
+#define qS9 _ItL_qS9
+#define atanhi _ItL_atanhi
+#define atanlo _ItL_atanlo
+#define aT _ItL_aT
+#define pi_lo _ItL_pi_lo
+
+#define pio2_hi atanhi[3]
+#define pio2_lo atanlo[3]
+#define pio4_hi atanhi[1]
+
+/* Constants shared by the long double inverse trig functions. */
+extern const long double pS0, pS1, pS2, pS3, pS4, pS5, pS6, pS7, pS8, pS9;
+extern const long double qS1, qS2, qS3, qS4, qS5, qS6, qS7, qS8, qS9;
+extern const long double atanhi[], atanlo[], aT[];
+extern const long double pi_lo;
+
+static inline long double
+P(long double x)
+{
+
+ return (x * (pS0 + x * (pS1 + x * (pS2 + x * (pS3 + x * \
+ (pS4 + x * (pS5 + x * (pS6 + x * (pS7 + x * (pS8 + x * \
+ pS9))))))))));
+}
+
+static inline long double
+Q(long double x)
+{
+
+ return (1.0 + x * (qS1 + x * (qS2 + x * (qS3 + x * (qS4 + x * \
+ (qS5 + x * (qS6 + x * (qS7 + x * (qS8 + x * qS9)))))))));
+}
+
+static inline long double
+T_even(long double x)
+{
+
+ return (aT[0] + x * (aT[2] + x * (aT[4] + x * (aT[6] + x * \
+ (aT[8] + x * (aT[10] + x * (aT[12] + x * (aT[14] + x * \
+ (aT[16] + x * (aT[18] + x * (aT[20] + x * aT[22])))))))))));
+}
+
+static inline long double
+T_odd(long double x)
+{
+
+ return (aT[1] + x * (aT[3] + x * (aT[5] + x * (aT[7] + x * \
+ (aT[9] + x * (aT[11] + x * (aT[13] + x * (aT[15] + x * \
+ (aT[17] + x * (aT[19] + x * (aT[21] + x * aT[23])))))))))));
+}
--- /dev/null
+/* From: @(#)k_cos.c 1.3 95/01/18 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ * Copyright (c) 2008 Steven G. Kargl, David Schultz, Bruce D. Evans.
+ *
+ * Developed at SunSoft, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/ld128/k_cosl.c,v 1.1 2008/02/17 07:32:31 das Exp $");
+
+/*
+ * ld128 version of k_cos.c. See ../src/k_cos.c for most comments.
+ */
+
+#include "math_private.h"
+
+/*
+ * Domain [-0.7854, 0.7854], range ~[-1.80e-37, 1.79e-37]:
+ * |cos(x) - c(x))| < 2**-122.0
+ *
+ * 113-bit precision requires more care than 64-bit precision, since
+ * simple methods give a minimax polynomial with coefficient for x^2
+ * that is 1 ulp below 0.5, but we want it to be precisely 0.5. See
+ * ../ld80/k_cosl.c for more details.
+ */
+static const double
+one = 1.0;
+
+static const long double
+C1 = 0.04166666666666666666666666666666658424671L,
+C2 = -0.001388888888888888888888888888863490893732L,
+C3 = 0.00002480158730158730158730158600795304914210L,
+C4 = -0.2755731922398589065255474947078934284324e-6L,
+C5 = 0.2087675698786809897659225313136400793948e-8L,
+C6 = -0.1147074559772972315817149986812031204775e-10L,
+C7 = 0.4779477332386808976875457937252120293400e-13L;
+
+static const double
+C8 = -0.1561920696721507929516718307820958119868e-15,
+C9 = 0.4110317413744594971475941557607804508039e-18,
+C10 = -0.8896592467191938803288521958313920156409e-21,
+C11 = 0.1601061435794535138244346256065192782581e-23;
+
+long double
+__kernel_cosl(long double x, long double y)
+{
+ long double hz,z,r,w;
+
+ z = x*x;
+ r = z*(C1+z*(C2+z*(C3+z*(C4+z*(C5+z*(C6+z*(C7+
+ z*(C8+z*(C9+z*(C10+z*C11))))))))));
+ hz = 0.5*z;
+ w = one-hz;
+ return w + (((one-w)-hz) + (z*r-x*y));
+}
--- /dev/null
+/* From: @(#)k_sin.c 1.3 95/01/18 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ * Copyright (c) 2008 Steven G. Kargl, David Schultz, Bruce D. Evans.
+ *
+ * Developed at SunSoft, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/ld128/k_sinl.c,v 1.1 2008/02/17 07:32:31 das Exp $");
+
+/*
+ * ld128 version of k_sin.c. See ../src/k_sin.c for most comments.
+ */
+
+#include "math_private.h"
+
+static const double
+half = 0.5;
+
+/*
+ * Domain [-0.7854, 0.7854], range ~[-1.53e-37, 1.659e-37]
+ * |sin(x)/x - s(x)| < 2**-122.1
+ *
+ * See ../ld80/k_cosl.c for more details about the polynomial.
+ */
+static const long double
+S1 = -0.16666666666666666666666666666666666606732416116558L,
+S2 = 0.0083333333333333333333333333333331135404851288270047L,
+S3 = -0.00019841269841269841269841269839935785325638310428717L,
+S4 = 0.27557319223985890652557316053039946268333231205686e-5L,
+S5 = -0.25052108385441718775048214826384312253862930064745e-7L,
+S6 = 0.16059043836821614596571832194524392581082444805729e-9L,
+S7 = -0.76471637318198151807063387954939213287488216303768e-12L,
+S8 = 0.28114572543451292625024967174638477283187397621303e-14L;
+
+static const double
+S9 = -0.82206352458348947812512122163446202498005154296863e-17,
+S10 = 0.19572940011906109418080609928334380560135358385256e-19,
+S11 = -0.38680813379701966970673724299207480965452616911420e-22,
+S12 = 0.64038150078671872796678569586315881020659912139412e-25;
+
+long double
+__kernel_sinl(long double x, long double y, int iy)
+{
+ long double z,r,v;
+
+ z = x*x;
+ v = z*x;
+ r = S2+z*(S3+z*(S4+z*(S5+z*(S6+z*(S7+z*(S8+
+ z*(S9+z*(S10+z*(S11+z*S12)))))))));
+ if(iy==0) return x+v*(S1+z*r);
+ else return x-((z*(half*y-v*r)-y)-v*S1);
+}
--- /dev/null
+/* From: @(#)k_tan.c 1.5 04/04/22 SMI */
+
+/*
+ * ====================================================
+ * Copyright 2004 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright (c) 2008 Steven G. Kargl, David Schultz, Bruce D. Evans.
+ *
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/ld128/k_tanl.c,v 1.1 2008/02/17 07:32:31 das Exp $");
+
+/*
+ * ld128 version of k_tan.c. See ../src/k_tan.c for most comments.
+ */
+
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+/*
+ * Domain [-0.67434, 0.67434], range ~[-3.37e-36, 1.982e-37]
+ * |tan(x)/x - t(x)| < 2**-117.8 (XXX should be ~1e-37)
+ *
+ * See ../ld80/k_cosl.c for more details about the polynomial.
+ */
+static const long double
+T3 = 0x1.5555555555555555555555555553p-2L,
+T5 = 0x1.1111111111111111111111111eb5p-3L,
+T7 = 0x1.ba1ba1ba1ba1ba1ba1ba1b694cd6p-5L,
+T9 = 0x1.664f4882c10f9f32d6bbe09d8bcdp-6L,
+T11 = 0x1.226e355e6c23c8f5b4f5762322eep-7L,
+T13 = 0x1.d6d3d0e157ddfb5fed8e84e27b37p-9L,
+T15 = 0x1.7da36452b75e2b5fce9ee7c2c92ep-10L,
+T17 = 0x1.355824803674477dfcf726649efep-11L,
+T19 = 0x1.f57d7734d1656e0aceb716f614c2p-13L,
+T21 = 0x1.967e18afcb180ed942dfdc518d6cp-14L,
+T23 = 0x1.497d8eea21e95bc7e2aa79b9f2cdp-15L,
+T25 = 0x1.0b132d39f055c81be49eff7afd50p-16L,
+T27 = 0x1.b0f72d33eff7bfa2fbc1059d90b6p-18L,
+T29 = 0x1.5ef2daf21d1113df38d0fbc00267p-19L,
+T31 = 0x1.1c77d6eac0234988cdaa04c96626p-20L,
+T33 = 0x1.cd2a5a292b180e0bdd701057dfe3p-22L,
+T35 = 0x1.75c7357d0298c01a31d0a6f7d518p-23L,
+T37 = 0x1.2f3190f4718a9a520f98f50081fcp-24L,
+pio4 = 0x1.921fb54442d18469898cc51701b8p-1L,
+pio4lo = 0x1.cd129024e088a67cc74020bbea60p-116L;
+
+static const double
+T39 = 0.000000028443389121318352, /* 0x1e8a7592977938.0p-78 */
+T41 = 0.000000011981013102001973, /* 0x19baa1b1223219.0p-79 */
+T43 = 0.0000000038303578044958070, /* 0x107385dfb24529.0p-80 */
+T45 = 0.0000000034664378216909893, /* 0x1dc6c702a05262.0p-81 */
+T47 = -0.0000000015090641701997785, /* -0x19ecef3569ebb6.0p-82 */
+T49 = 0.0000000029449552300483952, /* 0x194c0668da786a.0p-81 */
+T51 = -0.0000000022006995706097711, /* -0x12e763b8845268.0p-81 */
+T53 = 0.0000000015468200913196612, /* 0x1a92fc98c29554.0p-82 */
+T55 = -0.00000000061311613386849674, /* -0x151106cbc779a9.0p-83 */
+T57 = 1.4912469681508012e-10; /* 0x147edbdba6f43a.0p-85 */
+
+long double
+__kernel_tanl(long double x, long double y, int iy) {
+ long double z, r, v, w, s;
+ long double osign;
+ int i;
+
+ iy = (iy == 1 ? -1 : 1); /* XXX recover original interface */
+ osign = (x >= 0 ? 1.0 : -1.0); /* XXX slow, probably wrong for -0 */
+ if (fabsl(x) >= 0.67434) {
+ if (x < 0) {
+ x = -x;
+ y = -y;
+ }
+ z = pio4 - x;
+ w = pio4lo - y;
+ x = z + w;
+ y = 0.0;
+ i = 1;
+ } else
+ i = 0;
+ z = x * x;
+ w = z * z;
+ r = T5 + w * (T9 + w * (T13 + w * (T17 + w * (T21 +
+ w * (T25 + w * (T29 + w * (T33 +
+ w * (T37 + w * (T41 + w * (T45 + w * (T49 + w * (T53 +
+ w * T57))))))))))));
+ v = z * (T7 + w * (T11 + w * (T15 + w * (T19 + w * (T23 +
+ w * (T27 + w * (T31 + w * (T35 +
+ w * (T39 + w * (T43 + w * (T47 + w * (T51 + w * T55))))))))))));
+ s = z * x;
+ r = y + z * (s * (r + v) + y);
+ r += T3 * s;
+ w = x + r;
+ if (i == 1) {
+ v = (long double) iy;
+ return osign *
+ (v - 2.0 * (x - (w * w / (w + v) - r)));
+ }
+ if (iy == 1)
+ return w;
+ else {
+ /*
+ * if allow error up to 2 ulp, simply return
+ * -1.0 / (x+r) here
+ */
+ /* compute -1.0 / (x+r) accurately */
+ long double a, t;
+ z = w;
+ z = z + 0x1p32 - 0x1p32;
+ v = r - (z - x); /* z+v = r+x */
+ t = a = -1.0 / w; /* a = -1.0/w */
+ t = t + 0x1p32 - 0x1p32;
+ s = 1.0 + t * z;
+ return t + a * (s + t * v);
+ }
+}
--- /dev/null
+/* @(#)s_asinh.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/* asinhl(x)
+ * Method :
+ * Based on
+ * asinhl(x) = signl(x) * logl [ |x| + sqrtl(x*x+1) ]
+ * we have
+ * asinhl(x) := x if 1+x*x=1,
+ * := signl(x)*(logl(x)+ln2)) for large |x|, else
+ * := signl(x)*logl(2|x|+1/(|x|+sqrtl(x*x+1))) if|x|>2, else
+ * := signl(x)*log1pl(|x| + x^2/(1 + sqrtl(1+x^2)))
+ */
+
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+static const long double
+ one = 1.0L,
+ ln2 = 6.931471805599453094172321214581765681e-1L,
+ huge = 1.0e+4900L;
+
+long double
+asinhl(long double x)
+{
+ long double t, w;
+ int32_t ix, sign;
+ ieee_quad_shape_type u;
+
+ u.value = x;
+ sign = u.parts32.mswhi;
+ ix = sign & 0x7fffffff;
+ if (ix == 0x7fff0000)
+ return x + x; /* x is inf or NaN */
+ if (ix < 0x3fc70000)
+ { /* |x| < 2^ -56 */
+ if (huge + x > one)
+ return x; /* return x inexact except 0 */
+ }
+ u.parts32.mswhi = ix;
+ if (ix > 0x40350000)
+ { /* |x| > 2 ^ 54 */
+ w = logl (u.value) + ln2;
+ }
+ else if (ix >0x40000000)
+ { /* 2^ 54 > |x| > 2.0 */
+ t = u.value;
+ w = logl (2.0 * t + one / (sqrtl (x * x + one) + t));
+ }
+ else
+ { /* 2.0 > |x| > 2 ^ -56 */
+ t = x * x;
+ w = log1pl (u.value + t / (one + sqrtl (one + t)));
+ }
+ if (sign & 0x80000000)
+ return -w;
+ else
+ return w;
+}
--- /dev/null
+/* @(#)s_ceil.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/*
+ * ceill(x)
+ * Return x rounded toward -inf to integral value
+ * Method:
+ * Bit twiddling.
+ * Exception:
+ * Inexact flag raised if x not equal to ceil(x).
+ */
+
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+static const long double huge = 1.0e4930L;
+
+long double
+ceill(long double x)
+{
+ int64_t i0,i1,jj0;
+ u_int64_t i,j;
+ GET_LDOUBLE_WORDS64(i0,i1,x);
+ jj0 = ((i0>>48)&0x7fff)-0x3fff;
+ if(jj0<48) {
+ if(jj0<0) { /* raise inexact if x != 0 */
+ if(huge+x>0.0) {/* return 0*sign(x) if |x|<1 */
+ if(i0<0) {i0=0x8000000000000000ULL;i1=0;}
+ else if((i0|i1)!=0) { i0=0x3fff000000000000ULL;i1=0;}
+ }
+ } else {
+ i = (0x0000ffffffffffffULL)>>jj0;
+ if(((i0&i)|i1)==0) return x; /* x is integral */
+ if(huge+x>0.0) { /* raise inexact flag */
+ if(i0>0) i0 += (0x0001000000000000LL)>>jj0;
+ i0 &= (~i); i1=0;
+ }
+ }
+ } else if (jj0>111) {
+ if(jj0==0x4000) return x+x; /* inf or NaN */
+ else return x; /* x is integral */
+ } else {
+ i = -1ULL>>(jj0-48);
+ if((i1&i)==0) return x; /* x is integral */
+ if(huge+x>0.0) { /* raise inexact flag */
+ if(i0>0) {
+ if(jj0==48) i0+=1;
+ else {
+ j = i1+(1LL<<(112-jj0));
+ if(j<i1) i0 +=1 ; /* got a carry */
+ i1=j;
+ }
+ }
+ i1 &= (~i);
+ }
+ }
+ SET_LDOUBLE_WORDS64(x,i0,i1);
+ return x;
+}
--- /dev/null
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/*
+ * Copyright (c) 2008 Stephen L. Moshier <steve@moshier.net>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* double erf(double x)
+ * double erfc(double x)
+ * x
+ * 2 |\
+ * erf(x) = --------- | exp(-t*t)dt
+ * sqrt(pi) \|
+ * 0
+ *
+ * erfc(x) = 1-erf(x)
+ * Note that
+ * erf(-x) = -erf(x)
+ * erfc(-x) = 2 - erfc(x)
+ *
+ * Method:
+ * 1. erf(x) = x + x*R(x^2) for |x| in [0, 7/8]
+ * Remark. The formula is derived by noting
+ * erf(x) = (2/sqrt(pi))*(x - x^3/3 + x^5/10 - x^7/42 + ....)
+ * and that
+ * 2/sqrt(pi) = 1.128379167095512573896158903121545171688
+ * is close to one.
+ *
+ * 1a. erf(x) = 1 - erfc(x), for |x| > 1.0
+ * erfc(x) = 1 - erf(x) if |x| < 1/4
+ *
+ * 2. For |x| in [7/8, 1], let s = |x| - 1, and
+ * c = 0.84506291151 rounded to single (24 bits)
+ * erf(s + c) = sign(x) * (c + P1(s)/Q1(s))
+ * Remark: here we use the taylor series expansion at x=1.
+ * erf(1+s) = erf(1) + s*Poly(s)
+ * = 0.845.. + P1(s)/Q1(s)
+ * Note that |P1/Q1|< 0.078 for x in [0.84375,1.25]
+ *
+ * 3. For x in [1/4, 5/4],
+ * erfc(s + const) = erfc(const) + s P1(s)/Q1(s)
+ * for const = 1/4, 3/8, ..., 9/8
+ * and 0 <= s <= 1/8 .
+ *
+ * 4. For x in [5/4, 107],
+ * erfc(x) = (1/x)*exp(-x*x-0.5625 + R(z))
+ * z=1/x^2
+ * The interval is partitioned into several segments
+ * of width 1/8 in 1/x.
+ *
+ * Note1:
+ * To compute exp(-x*x-0.5625+R/S), let s be a single
+ * precision number and s := x; then
+ * -x*x = -s*s + (s-x)*(s+x)
+ * exp(-x*x-0.5626+R/S) =
+ * exp(-s*s-0.5625)*exp((s-x)*(s+x)+R/S);
+ * Note2:
+ * Here 4 and 5 make use of the asymptotic series
+ * exp(-x*x)
+ * erfc(x) ~ ---------- * ( 1 + Poly(1/x^2) )
+ * x*sqrt(pi)
+ *
+ * 5. For inf > x >= 107
+ * erf(x) = sign(x) *(1 - tiny) (raise inexact)
+ * erfc(x) = tiny*tiny (raise underflow) if x > 0
+ * = 2 - tiny if x<0
+ *
+ * 7. Special case:
+ * erf(0) = 0, erf(inf) = 1, erf(-inf) = -1,
+ * erfc(0) = 1, erfc(inf) = 0, erfc(-inf) = 2,
+ * erfc/erf(NaN) is NaN
+ */
+
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+/* Evaluate P[n] x^n + P[n-1] x^(n-1) + ... + P[0] */
+
+static long double
+neval (long double x, const long double *p, int n)
+{
+ long double y;
+
+ p += n;
+ y = *p--;
+ do
+ {
+ y = y * x + *p--;
+ }
+ while (--n > 0);
+ return y;
+}
+
+
+/* Evaluate x^n+1 + P[n] x^(n) + P[n-1] x^(n-1) + ... + P[0] */
+
+static long double
+deval (long double x, const long double *p, int n)
+{
+ long double y;
+
+ p += n;
+ y = x + *p--;
+ do
+ {
+ y = y * x + *p--;
+ }
+ while (--n > 0);
+ return y;
+}
+
+
+
+static const long double
+tiny = 1e-4931L,
+ one = 1.0L,
+ two = 2.0L,
+ /* 2/sqrt(pi) - 1 */
+ efx = 1.2837916709551257389615890312154517168810E-1L,
+ /* 8 * (2/sqrt(pi) - 1) */
+ efx8 = 1.0270333367641005911692712249723613735048E0L;
+
+
+/* erf(x) = x + x R(x^2)
+ 0 <= x <= 7/8
+ Peak relative error 1.8e-35 */
+#define NTN1 8
+static const long double TN1[NTN1 + 1] =
+{
+ -3.858252324254637124543172907442106422373E10L,
+ 9.580319248590464682316366876952214879858E10L,
+ 1.302170519734879977595901236693040544854E10L,
+ 2.922956950426397417800321486727032845006E9L,
+ 1.764317520783319397868923218385468729799E8L,
+ 1.573436014601118630105796794840834145120E7L,
+ 4.028077380105721388745632295157816229289E5L,
+ 1.644056806467289066852135096352853491530E4L,
+ 3.390868480059991640235675479463287886081E1L
+};
+#define NTD1 8
+static const long double TD1[NTD1 + 1] =
+{
+ -3.005357030696532927149885530689529032152E11L,
+ -1.342602283126282827411658673839982164042E11L,
+ -2.777153893355340961288511024443668743399E10L,
+ -3.483826391033531996955620074072768276974E9L,
+ -2.906321047071299585682722511260895227921E8L,
+ -1.653347985722154162439387878512427542691E7L,
+ -6.245520581562848778466500301865173123136E5L,
+ -1.402124304177498828590239373389110545142E4L,
+ -1.209368072473510674493129989468348633579E2L
+/* 1.0E0 */
+};
+
+
+/* erf(z+1) = erf_const + P(z)/Q(z)
+ -.125 <= z <= 0
+ Peak relative error 7.3e-36 */
+static const long double erf_const = 0.845062911510467529296875L;
+#define NTN2 8
+static const long double TN2[NTN2 + 1] =
+{
+ -4.088889697077485301010486931817357000235E1L,
+ 7.157046430681808553842307502826960051036E3L,
+ -2.191561912574409865550015485451373731780E3L,
+ 2.180174916555316874988981177654057337219E3L,
+ 2.848578658049670668231333682379720943455E2L,
+ 1.630362490952512836762810462174798925274E2L,
+ 6.317712353961866974143739396865293596895E0L,
+ 2.450441034183492434655586496522857578066E1L,
+ 5.127662277706787664956025545897050896203E-1L
+};
+#define NTD2 8
+static const long double TD2[NTD2 + 1] =
+{
+ 1.731026445926834008273768924015161048885E4L,
+ 1.209682239007990370796112604286048173750E4L,
+ 1.160950290217993641320602282462976163857E4L,
+ 5.394294645127126577825507169061355698157E3L,
+ 2.791239340533632669442158497532521776093E3L,
+ 8.989365571337319032943005387378993827684E2L,
+ 2.974016493766349409725385710897298069677E2L,
+ 6.148192754590376378740261072533527271947E1L,
+ 1.178502892490738445655468927408440847480E1L
+ /* 1.0E0 */
+};
+
+
+/* erfc(x + 0.25) = erfc(0.25) + x R(x)
+ 0 <= x < 0.125
+ Peak relative error 1.4e-35 */
+#define NRNr13 8
+static const long double RNr13[NRNr13 + 1] =
+{
+ -2.353707097641280550282633036456457014829E3L,
+ 3.871159656228743599994116143079870279866E2L,
+ -3.888105134258266192210485617504098426679E2L,
+ -2.129998539120061668038806696199343094971E1L,
+ -8.125462263594034672468446317145384108734E1L,
+ 8.151549093983505810118308635926270319660E0L,
+ -5.033362032729207310462422357772568553670E0L,
+ -4.253956621135136090295893547735851168471E-2L,
+ -8.098602878463854789780108161581050357814E-2L
+};
+#define NRDr13 7
+static const long double RDr13[NRDr13 + 1] =
+{
+ 2.220448796306693503549505450626652881752E3L,
+ 1.899133258779578688791041599040951431383E2L,
+ 1.061906712284961110196427571557149268454E3L,
+ 7.497086072306967965180978101974566760042E1L,
+ 2.146796115662672795876463568170441327274E2L,
+ 1.120156008362573736664338015952284925592E1L,
+ 2.211014952075052616409845051695042741074E1L,
+ 6.469655675326150785692908453094054988938E-1L
+ /* 1.0E0 */
+};
+/* erfc(0.25) = C13a + C13b to extra precision. */
+static const long double C13a = 0.723663330078125L;
+static const long double C13b = 1.0279753638067014931732235184287934646022E-5L;
+
+
+/* erfc(x + 0.375) = erfc(0.375) + x R(x)
+ 0 <= x < 0.125
+ Peak relative error 1.2e-35 */
+#define NRNr14 8
+static const long double RNr14[NRNr14 + 1] =
+{
+ -2.446164016404426277577283038988918202456E3L,
+ 6.718753324496563913392217011618096698140E2L,
+ -4.581631138049836157425391886957389240794E2L,
+ -2.382844088987092233033215402335026078208E1L,
+ -7.119237852400600507927038680970936336458E1L,
+ 1.313609646108420136332418282286454287146E1L,
+ -6.188608702082264389155862490056401365834E0L,
+ -2.787116601106678287277373011101132659279E-2L,
+ -2.230395570574153963203348263549700967918E-2L
+};
+#define NRDr14 7
+static const long double RDr14[NRDr14 + 1] =
+{
+ 2.495187439241869732696223349840963702875E3L,
+ 2.503549449872925580011284635695738412162E2L,
+ 1.159033560988895481698051531263861842461E3L,
+ 9.493751466542304491261487998684383688622E1L,
+ 2.276214929562354328261422263078480321204E2L,
+ 1.367697521219069280358984081407807931847E1L,
+ 2.276988395995528495055594829206582732682E1L,
+ 7.647745753648996559837591812375456641163E-1L
+ /* 1.0E0 */
+};
+/* erfc(0.375) = C14a + C14b to extra precision. */
+static const long double C14a = 0.5958709716796875L;
+static const long double C14b = 1.2118885490201676174914080878232469565953E-5L;
+
+/* erfc(x + 0.5) = erfc(0.5) + x R(x)
+ 0 <= x < 0.125
+ Peak relative error 4.7e-36 */
+#define NRNr15 8
+static const long double RNr15[NRNr15 + 1] =
+{
+ -2.624212418011181487924855581955853461925E3L,
+ 8.473828904647825181073831556439301342756E2L,
+ -5.286207458628380765099405359607331669027E2L,
+ -3.895781234155315729088407259045269652318E1L,
+ -6.200857908065163618041240848728398496256E1L,
+ 1.469324610346924001393137895116129204737E1L,
+ -6.961356525370658572800674953305625578903E0L,
+ 5.145724386641163809595512876629030548495E-3L,
+ 1.990253655948179713415957791776180406812E-2L
+};
+#define NRDr15 7
+static const long double RDr15[NRDr15 + 1] =
+{
+ 2.986190760847974943034021764693341524962E3L,
+ 5.288262758961073066335410218650047725985E2L,
+ 1.363649178071006978355113026427856008978E3L,
+ 1.921707975649915894241864988942255320833E2L,
+ 2.588651100651029023069013885900085533226E2L,
+ 2.628752920321455606558942309396855629459E1L,
+ 2.455649035885114308978333741080991380610E1L,
+ 1.378826653595128464383127836412100939126E0L
+ /* 1.0E0 */
+};
+/* erfc(0.5) = C15a + C15b to extra precision. */
+static const long double C15a = 0.4794921875L;
+static const long double C15b = 7.9346869534623172533461080354712635484242E-6L;
+
+/* erfc(x + 0.625) = erfc(0.625) + x R(x)
+ 0 <= x < 0.125
+ Peak relative error 5.1e-36 */
+#define NRNr16 8
+static const long double RNr16[NRNr16 + 1] =
+{
+ -2.347887943200680563784690094002722906820E3L,
+ 8.008590660692105004780722726421020136482E2L,
+ -5.257363310384119728760181252132311447963E2L,
+ -4.471737717857801230450290232600243795637E1L,
+ -4.849540386452573306708795324759300320304E1L,
+ 1.140885264677134679275986782978655952843E1L,
+ -6.731591085460269447926746876983786152300E0L,
+ 1.370831653033047440345050025876085121231E-1L,
+ 2.022958279982138755020825717073966576670E-2L,
+};
+#define NRDr16 7
+static const long double RDr16[NRDr16 + 1] =
+{
+ 3.075166170024837215399323264868308087281E3L,
+ 8.730468942160798031608053127270430036627E2L,
+ 1.458472799166340479742581949088453244767E3L,
+ 3.230423687568019709453130785873540386217E2L,
+ 2.804009872719893612081109617983169474655E2L,
+ 4.465334221323222943418085830026979293091E1L,
+ 2.612723259683205928103787842214809134746E1L,
+ 2.341526751185244109722204018543276124997E0L,
+ /* 1.0E0 */
+};
+/* erfc(0.625) = C16a + C16b to extra precision. */
+static const long double C16a = 0.3767547607421875L;
+static const long double C16b = 4.3570693945275513594941232097252997287766E-6L;
+
+/* erfc(x + 0.75) = erfc(0.75) + x R(x)
+ 0 <= x < 0.125
+ Peak relative error 1.7e-35 */
+#define NRNr17 8
+static const long double RNr17[NRNr17 + 1] =
+{
+ -1.767068734220277728233364375724380366826E3L,
+ 6.693746645665242832426891888805363898707E2L,
+ -4.746224241837275958126060307406616817753E2L,
+ -2.274160637728782675145666064841883803196E1L,
+ -3.541232266140939050094370552538987982637E1L,
+ 6.988950514747052676394491563585179503865E0L,
+ -5.807687216836540830881352383529281215100E0L,
+ 3.631915988567346438830283503729569443642E-1L,
+ -1.488945487149634820537348176770282391202E-2L
+};
+#define NRDr17 7
+static const long double RDr17[NRDr17 + 1] =
+{
+ 2.748457523498150741964464942246913394647E3L,
+ 1.020213390713477686776037331757871252652E3L,
+ 1.388857635935432621972601695296561952738E3L,
+ 3.903363681143817750895999579637315491087E2L,
+ 2.784568344378139499217928969529219886578E2L,
+ 5.555800830216764702779238020065345401144E1L,
+ 2.646215470959050279430447295801291168941E1L,
+ 2.984905282103517497081766758550112011265E0L,
+ /* 1.0E0 */
+};
+/* erfc(0.75) = C17a + C17b to extra precision. */
+static const long double C17a = 0.2888336181640625L;
+static const long double C17b = 1.0748182422368401062165408589222625794046E-5L;
+
+
+/* erfc(x + 0.875) = erfc(0.875) + x R(x)
+ 0 <= x < 0.125
+ Peak relative error 2.2e-35 */
+#define NRNr18 8
+static const long double RNr18[NRNr18 + 1] =
+{
+ -1.342044899087593397419622771847219619588E3L,
+ 6.127221294229172997509252330961641850598E2L,
+ -4.519821356522291185621206350470820610727E2L,
+ 1.223275177825128732497510264197915160235E1L,
+ -2.730789571382971355625020710543532867692E1L,
+ 4.045181204921538886880171727755445395862E0L,
+ -4.925146477876592723401384464691452700539E0L,
+ 5.933878036611279244654299924101068088582E-1L,
+ -5.557645435858916025452563379795159124753E-2L
+};
+#define NRDr18 7
+static const long double RDr18[NRDr18 + 1] =
+{
+ 2.557518000661700588758505116291983092951E3L,
+ 1.070171433382888994954602511991940418588E3L,
+ 1.344842834423493081054489613250688918709E3L,
+ 4.161144478449381901208660598266288188426E2L,
+ 2.763670252219855198052378138756906980422E2L,
+ 5.998153487868943708236273854747564557632E1L,
+ 2.657695108438628847733050476209037025318E1L,
+ 3.252140524394421868923289114410336976512E0L,
+ /* 1.0E0 */
+};
+/* erfc(0.875) = C18a + C18b to extra precision. */
+static const long double C18a = 0.215911865234375L;
+static const long double C18b = 1.3073705765341685464282101150637224028267E-5L;
+
+/* erfc(x + 1.0) = erfc(1.0) + x R(x)
+ 0 <= x < 0.125
+ Peak relative error 1.6e-35 */
+#define NRNr19 8
+static const long double RNr19[NRNr19 + 1] =
+{
+ -1.139180936454157193495882956565663294826E3L,
+ 6.134903129086899737514712477207945973616E2L,
+ -4.628909024715329562325555164720732868263E2L,
+ 4.165702387210732352564932347500364010833E1L,
+ -2.286979913515229747204101330405771801610E1L,
+ 1.870695256449872743066783202326943667722E0L,
+ -4.177486601273105752879868187237000032364E0L,
+ 7.533980372789646140112424811291782526263E-1L,
+ -8.629945436917752003058064731308767664446E-2L
+};
+#define NRDr19 7
+static const long double RDr19[NRDr19 + 1] =
+{
+ 2.744303447981132701432716278363418643778E3L,
+ 1.266396359526187065222528050591302171471E3L,
+ 1.466739461422073351497972255511919814273E3L,
+ 4.868710570759693955597496520298058147162E2L,
+ 2.993694301559756046478189634131722579643E2L,
+ 6.868976819510254139741559102693828237440E1L,
+ 2.801505816247677193480190483913753613630E1L,
+ 3.604439909194350263552750347742663954481E0L,
+ /* 1.0E0 */
+};
+/* erfc(1.0) = C19a + C19b to extra precision. */
+static const long double C19a = 0.15728759765625L;
+static const long double C19b = 1.1609394035130658779364917390740703933002E-5L;
+
+/* erfc(x + 1.125) = erfc(1.125) + x R(x)
+ 0 <= x < 0.125
+ Peak relative error 3.6e-36 */
+#define NRNr20 8
+static const long double RNr20[NRNr20 + 1] =
+{
+ -9.652706916457973956366721379612508047640E2L,
+ 5.577066396050932776683469951773643880634E2L,
+ -4.406335508848496713572223098693575485978E2L,
+ 5.202893466490242733570232680736966655434E1L,
+ -1.931311847665757913322495948705563937159E1L,
+ -9.364318268748287664267341457164918090611E-2L,
+ -3.306390351286352764891355375882586201069E0L,
+ 7.573806045289044647727613003096916516475E-1L,
+ -9.611744011489092894027478899545635991213E-2L
+};
+#define NRDr20 7
+static const long double RDr20[NRDr20 + 1] =
+{
+ 3.032829629520142564106649167182428189014E3L,
+ 1.659648470721967719961167083684972196891E3L,
+ 1.703545128657284619402511356932569292535E3L,
+ 6.393465677731598872500200253155257708763E2L,
+ 3.489131397281030947405287112726059221934E2L,
+ 8.848641738570783406484348434387611713070E1L,
+ 3.132269062552392974833215844236160958502E1L,
+ 4.430131663290563523933419966185230513168E0L
+ /* 1.0E0 */
+};
+/* erfc(1.125) = C20a + C20b to extra precision. */
+static const long double C20a = 0.111602783203125L;
+static const long double C20b = 8.9850951672359304215530728365232161564636E-6L;
+
+/* erfc(1/x) = 1/x exp (-1/x^2 - 0.5625 + R(1/x^2))
+ 7/8 <= 1/x < 1
+ Peak relative error 1.4e-35 */
+#define NRNr8 9
+static const long double RNr8[NRNr8 + 1] =
+{
+ 3.587451489255356250759834295199296936784E1L,
+ 5.406249749087340431871378009874875889602E2L,
+ 2.931301290625250886238822286506381194157E3L,
+ 7.359254185241795584113047248898753470923E3L,
+ 9.201031849810636104112101947312492532314E3L,
+ 5.749697096193191467751650366613289284777E3L,
+ 1.710415234419860825710780802678697889231E3L,
+ 2.150753982543378580859546706243022719599E2L,
+ 8.740953582272147335100537849981160931197E0L,
+ 4.876422978828717219629814794707963640913E-2L
+};
+#define NRDr8 8
+static const long double RDr8[NRDr8 + 1] =
+{
+ 6.358593134096908350929496535931630140282E1L,
+ 9.900253816552450073757174323424051765523E2L,
+ 5.642928777856801020545245437089490805186E3L,
+ 1.524195375199570868195152698617273739609E4L,
+ 2.113829644500006749947332935305800887345E4L,
+ 1.526438562626465706267943737310282977138E4L,
+ 5.561370922149241457131421914140039411782E3L,
+ 9.394035530179705051609070428036834496942E2L,
+ 6.147019596150394577984175188032707343615E1L
+ /* 1.0E0 */
+};
+
+/* erfc(1/x) = 1/x exp (-1/x^2 - 0.5625 + R(1/x^2))
+ 0.75 <= 1/x <= 0.875
+ Peak relative error 2.0e-36 */
+#define NRNr7 9
+static const long double RNr7[NRNr7 + 1] =
+{
+ 1.686222193385987690785945787708644476545E1L,
+ 1.178224543567604215602418571310612066594E3L,
+ 1.764550584290149466653899886088166091093E4L,
+ 1.073758321890334822002849369898232811561E5L,
+ 3.132840749205943137619839114451290324371E5L,
+ 4.607864939974100224615527007793867585915E5L,
+ 3.389781820105852303125270837910972384510E5L,
+ 1.174042187110565202875011358512564753399E5L,
+ 1.660013606011167144046604892622504338313E4L,
+ 6.700393957480661937695573729183733234400E2L
+};
+#define NRDr7 9
+static const long double RDr7[NRDr7 + 1] =
+{
+-1.709305024718358874701575813642933561169E3L,
+-3.280033887481333199580464617020514788369E4L,
+-2.345284228022521885093072363418750835214E5L,
+-8.086758123097763971926711729242327554917E5L,
+-1.456900414510108718402423999575992450138E6L,
+-1.391654264881255068392389037292702041855E6L,
+-6.842360801869939983674527468509852583855E5L,
+-1.597430214446573566179675395199807533371E5L,
+-1.488876130609876681421645314851760773480E4L,
+-3.511762950935060301403599443436465645703E2L
+ /* 1.0E0 */
+};
+
+/* erfc(1/x) = 1/x exp(-1/x^2 - 0.5625 + R(1/x^2))
+ 5/8 <= 1/x < 3/4
+ Peak relative error 1.9e-35 */
+#define NRNr6 9
+static const long double RNr6[NRNr6 + 1] =
+{
+ 1.642076876176834390623842732352935761108E0L,
+ 1.207150003611117689000664385596211076662E2L,
+ 2.119260779316389904742873816462800103939E3L,
+ 1.562942227734663441801452930916044224174E4L,
+ 5.656779189549710079988084081145693580479E4L,
+ 1.052166241021481691922831746350942786299E5L,
+ 9.949798524786000595621602790068349165758E4L,
+ 4.491790734080265043407035220188849562856E4L,
+ 8.377074098301530326270432059434791287601E3L,
+ 4.506934806567986810091824791963991057083E2L
+};
+#define NRDr6 9
+static const long double RDr6[NRDr6 + 1] =
+{
+-1.664557643928263091879301304019826629067E2L,
+-3.800035902507656624590531122291160668452E3L,
+-3.277028191591734928360050685359277076056E4L,
+-1.381359471502885446400589109566587443987E5L,
+-3.082204287382581873532528989283748656546E5L,
+-3.691071488256738343008271448234631037095E5L,
+-2.300482443038349815750714219117566715043E5L,
+-6.873955300927636236692803579555752171530E4L,
+-8.262158817978334142081581542749986845399E3L,
+-2.517122254384430859629423488157361983661E2L
+ /* 1.00 */
+};
+
+/* erfc(1/x) = 1/x exp(-1/x^2 - 0.5625 + R(1/x^2))
+ 1/2 <= 1/x < 5/8
+ Peak relative error 4.6e-36 */
+#define NRNr5 10
+static const long double RNr5[NRNr5 + 1] =
+{
+-3.332258927455285458355550878136506961608E-3L,
+-2.697100758900280402659586595884478660721E-1L,
+-6.083328551139621521416618424949137195536E0L,
+-6.119863528983308012970821226810162441263E1L,
+-3.176535282475593173248810678636522589861E2L,
+-8.933395175080560925809992467187963260693E2L,
+-1.360019508488475978060917477620199499560E3L,
+-1.075075579828188621541398761300910213280E3L,
+-4.017346561586014822824459436695197089916E2L,
+-5.857581368145266249509589726077645791341E1L,
+-2.077715925587834606379119585995758954399E0L
+};
+#define NRDr5 9
+static const long double RDr5[NRDr5 + 1] =
+{
+ 3.377879570417399341550710467744693125385E-1L,
+ 1.021963322742390735430008860602594456187E1L,
+ 1.200847646592942095192766255154827011939E2L,
+ 7.118915528142927104078182863387116942836E2L,
+ 2.318159380062066469386544552429625026238E3L,
+ 4.238729853534009221025582008928765281620E3L,
+ 4.279114907284825886266493994833515580782E3L,
+ 2.257277186663261531053293222591851737504E3L,
+ 5.570475501285054293371908382916063822957E2L,
+ 5.142189243856288981145786492585432443560E1L
+ /* 1.0E0 */
+};
+
+/* erfc(1/x) = 1/x exp(-1/x^2 - 0.5625 + R(1/x^2))
+ 3/8 <= 1/x < 1/2
+ Peak relative error 2.0e-36 */
+#define NRNr4 10
+static const long double RNr4[NRNr4 + 1] =
+{
+ 3.258530712024527835089319075288494524465E-3L,
+ 2.987056016877277929720231688689431056567E-1L,
+ 8.738729089340199750734409156830371528862E0L,
+ 1.207211160148647782396337792426311125923E2L,
+ 8.997558632489032902250523945248208224445E2L,
+ 3.798025197699757225978410230530640879762E3L,
+ 9.113203668683080975637043118209210146846E3L,
+ 1.203285891339933238608683715194034900149E4L,
+ 8.100647057919140328536743641735339740855E3L,
+ 2.383888249907144945837976899822927411769E3L,
+ 2.127493573166454249221983582495245662319E2L
+};
+#define NRDr4 10
+static const long double RDr4[NRDr4 + 1] =
+{
+-3.303141981514540274165450687270180479586E-1L,
+-1.353768629363605300707949368917687066724E1L,
+-2.206127630303621521950193783894598987033E2L,
+-1.861800338758066696514480386180875607204E3L,
+-8.889048775872605708249140016201753255599E3L,
+-2.465888106627948210478692168261494857089E4L,
+-3.934642211710774494879042116768390014289E4L,
+-3.455077258242252974937480623730228841003E4L,
+-1.524083977439690284820586063729912653196E4L,
+-2.810541887397984804237552337349093953857E3L,
+-1.343929553541159933824901621702567066156E2L
+ /* 1.0E0 */
+};
+
+/* erfc(1/x) = 1/x exp(-1/x^2 - 0.5625 + R(1/x^2))
+ 1/4 <= 1/x < 3/8
+ Peak relative error 8.4e-37 */
+#define NRNr3 11
+static const long double RNr3[NRNr3 + 1] =
+{
+-1.952401126551202208698629992497306292987E-6L,
+-2.130881743066372952515162564941682716125E-4L,
+-8.376493958090190943737529486107282224387E-3L,
+-1.650592646560987700661598877522831234791E-1L,
+-1.839290818933317338111364667708678163199E0L,
+-1.216278715570882422410442318517814388470E1L,
+-4.818759344462360427612133632533779091386E1L,
+-1.120994661297476876804405329172164436784E2L,
+-1.452850765662319264191141091859300126931E2L,
+-9.485207851128957108648038238656777241333E1L,
+-2.563663855025796641216191848818620020073E1L,
+-1.787995944187565676837847610706317833247E0L
+};
+#define NRDr3 10
+static const long double RDr3[NRDr3 + 1] =
+{
+ 1.979130686770349481460559711878399476903E-4L,
+ 1.156941716128488266238105813374635099057E-2L,
+ 2.752657634309886336431266395637285974292E-1L,
+ 3.482245457248318787349778336603569327521E0L,
+ 2.569347069372696358578399521203959253162E1L,
+ 1.142279000180457419740314694631879921561E2L,
+ 3.056503977190564294341422623108332700840E2L,
+ 4.780844020923794821656358157128719184422E2L,
+ 4.105972727212554277496256802312730410518E2L,
+ 1.724072188063746970865027817017067646246E2L,
+ 2.815939183464818198705278118326590370435E1L
+ /* 1.0E0 */
+};
+
+/* erfc(1/x) = 1/x exp(-1/x^2 - 0.5625 + R(1/x^2))
+ 1/8 <= 1/x < 1/4
+ Peak relative error 1.5e-36 */
+#define NRNr2 11
+static const long double RNr2[NRNr2 + 1] =
+{
+-2.638914383420287212401687401284326363787E-8L,
+-3.479198370260633977258201271399116766619E-6L,
+-1.783985295335697686382487087502222519983E-4L,
+-4.777876933122576014266349277217559356276E-3L,
+-7.450634738987325004070761301045014986520E-2L,
+-7.068318854874733315971973707247467326619E-1L,
+-4.113919921935944795764071670806867038732E0L,
+-1.440447573226906222417767283691888875082E1L,
+-2.883484031530718428417168042141288943905E1L,
+-2.990886974328476387277797361464279931446E1L,
+-1.325283914915104866248279787536128997331E1L,
+-1.572436106228070195510230310658206154374E0L
+};
+#define NRDr2 10
+static const long double RDr2[NRDr2 + 1] =
+{
+ 2.675042728136731923554119302571867799673E-6L,
+ 2.170997868451812708585443282998329996268E-4L,
+ 7.249969752687540289422684951196241427445E-3L,
+ 1.302040375859768674620410563307838448508E-1L,
+ 1.380202483082910888897654537144485285549E0L,
+ 8.926594113174165352623847870299170069350E0L,
+ 3.521089584782616472372909095331572607185E1L,
+ 8.233547427533181375185259050330809105570E1L,
+ 1.072971579885803033079469639073292840135E2L,
+ 6.943803113337964469736022094105143158033E1L,
+ 1.775695341031607738233608307835017282662E1L
+ /* 1.0E0 */
+};
+
+/* erfc(1/x) = 1/x exp(-1/x^2 - 0.5625 + R(1/x^2))
+ 1/128 <= 1/x < 1/8
+ Peak relative error 2.2e-36 */
+#define NRNr1 9
+static const long double RNr1[NRNr1 + 1] =
+{
+-4.250780883202361946697751475473042685782E-8L,
+-5.375777053288612282487696975623206383019E-6L,
+-2.573645949220896816208565944117382460452E-4L,
+-6.199032928113542080263152610799113086319E-3L,
+-8.262721198693404060380104048479916247786E-2L,
+-6.242615227257324746371284637695778043982E-1L,
+-2.609874739199595400225113299437099626386E0L,
+-5.581967563336676737146358534602770006970E0L,
+-5.124398923356022609707490956634280573882E0L,
+-1.290865243944292370661544030414667556649E0L
+};
+#define NRDr1 8
+static const long double RDr1[NRDr1 + 1] =
+{
+ 4.308976661749509034845251315983612976224E-6L,
+ 3.265390126432780184125233455960049294580E-4L,
+ 9.811328839187040701901866531796570418691E-3L,
+ 1.511222515036021033410078631914783519649E-1L,
+ 1.289264341917429958858379585970225092274E0L,
+ 6.147640356182230769548007536914983522270E0L,
+ 1.573966871337739784518246317003956180750E1L,
+ 1.955534123435095067199574045529218238263E1L,
+ 9.472613121363135472247929109615785855865E0L
+ /* 1.0E0 */
+};
+
+
+long double
+erfl(long double x)
+{
+ long double a, y, z;
+ int32_t i, ix, sign;
+ ieee_quad_shape_type u;
+
+ u.value = x;
+ sign = u.parts32.mswhi;
+ ix = sign & 0x7fffffff;
+
+ if (ix >= 0x7fff0000)
+ { /* erf(nan)=nan */
+ i = ((sign & 0xffff0000) >> 31) << 1;
+ return (long double) (1 - i) + one / x; /* erf(+-inf)=+-1 */
+ }
+
+ if (ix >= 0x3fff0000) /* |x| >= 1.0 */
+ {
+ y = erfcl (x);
+ return (one - y);
+ /* return (one - erfcl (x)); */
+ }
+ u.parts32.mswhi = ix;
+ a = u.value;
+ z = x * x;
+ if (ix < 0x3ffec000) /* a < 0.875 */
+ {
+ if (ix < 0x3fc60000) /* |x|<2**-57 */
+ {
+ if (ix < 0x00080000)
+ return 0.125 * (8.0 * x + efx8 * x); /*avoid underflow */
+ return x + efx * x;
+ }
+ y = a + a * neval (z, TN1, NTN1) / deval (z, TD1, NTD1);
+ }
+ else
+ {
+ a = a - one;
+ y = erf_const + neval (a, TN2, NTN2) / deval (a, TD2, NTD2);
+ }
+
+ if (sign & 0x80000000) /* x < 0 */
+ y = -y;
+ return( y );
+}
+
+long double
+erfcl(long double x)
+{
+ long double y, z, p, r;
+ int32_t i, ix, sign;
+ ieee_quad_shape_type u;
+
+ u.value = x;
+ sign = u.parts32.mswhi;
+ ix = sign & 0x7fffffff;
+ u.parts32.mswhi = ix;
+
+ if (ix >= 0x7fff0000)
+ { /* erfc(nan)=nan */
+ /* erfc(+-inf)=0,2 */
+ return (long double) (((u_int32_t) sign >> 31) << 1) + one / x;
+ }
+
+ if (ix < 0x3ffd0000) /* |x| <1/4 */
+ {
+ if (ix < 0x3f8d0000) /* |x|<2**-114 */
+ return one - x;
+ return one - erfl (x);
+ }
+ if (ix < 0x3fff4000) /* 1.25 */
+ {
+ x = u.value;
+ i = 8.0 * x;
+ switch (i)
+ {
+ case 2:
+ z = x - 0.25L;
+ y = C13b + z * neval (z, RNr13, NRNr13) / deval (z, RDr13, NRDr13);
+ y += C13a;
+ break;
+ case 3:
+ z = x - 0.375L;
+ y = C14b + z * neval (z, RNr14, NRNr14) / deval (z, RDr14, NRDr14);
+ y += C14a;
+ break;
+ case 4:
+ z = x - 0.5L;
+ y = C15b + z * neval (z, RNr15, NRNr15) / deval (z, RDr15, NRDr15);
+ y += C15a;
+ break;
+ case 5:
+ z = x - 0.625L;
+ y = C16b + z * neval (z, RNr16, NRNr16) / deval (z, RDr16, NRDr16);
+ y += C16a;
+ break;
+ case 6:
+ z = x - 0.75L;
+ y = C17b + z * neval (z, RNr17, NRNr17) / deval (z, RDr17, NRDr17);
+ y += C17a;
+ break;
+ case 7:
+ z = x - 0.875L;
+ y = C18b + z * neval (z, RNr18, NRNr18) / deval (z, RDr18, NRDr18);
+ y += C18a;
+ break;
+ case 8:
+ z = x - 1.0L;
+ y = C19b + z * neval (z, RNr19, NRNr19) / deval (z, RDr19, NRDr19);
+ y += C19a;
+ break;
+ case 9:
+ z = x - 1.125L;
+ y = C20b + z * neval (z, RNr20, NRNr20) / deval (z, RDr20, NRDr20);
+ y += C20a;
+ break;
+ }
+ if (sign & 0x80000000)
+ y = 2.0L - y;
+ return y;
+ }
+ /* 1.25 < |x| < 107 */
+ if (ix < 0x4005ac00)
+ {
+ /* x < -9 */
+ if ((ix >= 0x40022000) && (sign & 0x80000000))
+ return two - tiny;
+
+ x = fabsl (x);
+ z = one / (x * x);
+ i = 8.0 / x;
+ switch (i)
+ {
+ default:
+ case 0:
+ p = neval (z, RNr1, NRNr1) / deval (z, RDr1, NRDr1);
+ break;
+ case 1:
+ p = neval (z, RNr2, NRNr2) / deval (z, RDr2, NRDr2);
+ break;
+ case 2:
+ p = neval (z, RNr3, NRNr3) / deval (z, RDr3, NRDr3);
+ break;
+ case 3:
+ p = neval (z, RNr4, NRNr4) / deval (z, RDr4, NRDr4);
+ break;
+ case 4:
+ p = neval (z, RNr5, NRNr5) / deval (z, RDr5, NRDr5);
+ break;
+ case 5:
+ p = neval (z, RNr6, NRNr6) / deval (z, RDr6, NRDr6);
+ break;
+ case 6:
+ p = neval (z, RNr7, NRNr7) / deval (z, RDr7, NRDr7);
+ break;
+ case 7:
+ p = neval (z, RNr8, NRNr8) / deval (z, RDr8, NRDr8);
+ break;
+ }
+ u.value = x;
+ u.parts32.lswlo = 0;
+ u.parts32.lswhi &= 0xfe000000;
+ z = u.value;
+ r = expl (-z * z - 0.5625) *
+ expl ((z - x) * (z + x) + p);
+ if ((sign & 0x80000000) == 0)
+ return r / x;
+ else
+ return two - r / x;
+ }
+ else
+ {
+ if ((sign & 0x80000000) == 0)
+ return tiny * tiny;
+ else
+ return two - tiny;
+ }
+}
--- /dev/null
+/*-
+ * Copyright (c) 2005-2008 David Schultz <das@FreeBSD.ORG>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/ld128/s_exp2l.c,v 1.3 2008/02/13 10:44:44 bde Exp $");
+
+#include <float.h>
+#include <openlibm_math.h>
+#include <stdint.h>
+
+#include "fpmath.h"
+#include "math_private.h"
+
+#define TBLBITS 7
+#define TBLSIZE (1 << TBLBITS)
+
+#define BIAS (LDBL_MAX_EXP - 1)
+#define EXPMASK (BIAS + LDBL_MAX_EXP)
+
+#if 0 /* XXX Prevent gcc from erroneously constant folding this. */
+static const long double twom10000 = 0x1p-10000L;
+#else
+static volatile long double twom10000 = 0x1p-10000L;
+#endif
+
+static const long double
+ huge = 0x1p10000L,
+ P1 = 0x1.62e42fefa39ef35793c7673007e6p-1L,
+ P2 = 0x1.ebfbdff82c58ea86f16b06ec9736p-3L,
+ P3 = 0x1.c6b08d704a0bf8b33a762bad3459p-5L,
+ P4 = 0x1.3b2ab6fba4e7729ccbbe0b4f3fc2p-7L,
+ P5 = 0x1.5d87fe78a67311071dee13fd11d9p-10L,
+ P6 = 0x1.430912f86c7876f4b663b23c5fe5p-13L;
+
+static const double
+ P7 = 0x1.ffcbfc588b041p-17,
+ P8 = 0x1.62c0223a5c7c7p-20,
+ P9 = 0x1.b52541ff59713p-24,
+ P10 = 0x1.e4cf56a391e22p-28,
+ redux = 0x1.8p112 / TBLSIZE;
+
+static const long double tbl[TBLSIZE] = {
+ 0x1.6a09e667f3bcc908b2fb1366dfeap-1L,
+ 0x1.6c012750bdabeed76a99800f4edep-1L,
+ 0x1.6dfb23c651a2ef220e2cbe1bc0d4p-1L,
+ 0x1.6ff7df9519483cf87e1b4f3e1e98p-1L,
+ 0x1.71f75e8ec5f73dd2370f2ef0b148p-1L,
+ 0x1.73f9a48a58173bd5c9a4e68ab074p-1L,
+ 0x1.75feb564267c8bf6e9aa33a489a8p-1L,
+ 0x1.780694fde5d3f619ae02808592a4p-1L,
+ 0x1.7a11473eb0186d7d51023f6ccb1ap-1L,
+ 0x1.7c1ed0130c1327c49334459378dep-1L,
+ 0x1.7e2f336cf4e62105d02ba1579756p-1L,
+ 0x1.80427543e1a11b60de67649a3842p-1L,
+ 0x1.82589994cce128acf88afab34928p-1L,
+ 0x1.8471a4623c7acce52f6b97c6444cp-1L,
+ 0x1.868d99b4492ec80e41d90ac2556ap-1L,
+ 0x1.88ac7d98a669966530bcdf2d4cc0p-1L,
+ 0x1.8ace5422aa0db5ba7c55a192c648p-1L,
+ 0x1.8cf3216b5448bef2aa1cd161c57ap-1L,
+ 0x1.8f1ae991577362b982745c72eddap-1L,
+ 0x1.9145b0b91ffc588a61b469f6b6a0p-1L,
+ 0x1.93737b0cdc5e4f4501c3f2540ae8p-1L,
+ 0x1.95a44cbc8520ee9b483695a0e7fep-1L,
+ 0x1.97d829fde4e4f8b9e920f91e8eb6p-1L,
+ 0x1.9a0f170ca07b9ba3109b8c467844p-1L,
+ 0x1.9c49182a3f0901c7c46b071f28dep-1L,
+ 0x1.9e86319e323231824ca78e64c462p-1L,
+ 0x1.a0c667b5de564b29ada8b8cabbacp-1L,
+ 0x1.a309bec4a2d3358c171f770db1f4p-1L,
+ 0x1.a5503b23e255c8b424491caf88ccp-1L,
+ 0x1.a799e1330b3586f2dfb2b158f31ep-1L,
+ 0x1.a9e6b5579fdbf43eb243bdff53a2p-1L,
+ 0x1.ac36bbfd3f379c0db966a3126988p-1L,
+ 0x1.ae89f995ad3ad5e8734d17731c80p-1L,
+ 0x1.b0e07298db66590842acdfc6fb4ep-1L,
+ 0x1.b33a2b84f15faf6bfd0e7bd941b0p-1L,
+ 0x1.b59728de559398e3881111648738p-1L,
+ 0x1.b7f76f2fb5e46eaa7b081ab53ff6p-1L,
+ 0x1.ba5b030a10649840cb3c6af5b74cp-1L,
+ 0x1.bcc1e904bc1d2247ba0f45b3d06cp-1L,
+ 0x1.bf2c25bd71e088408d7025190cd0p-1L,
+ 0x1.c199bdd85529c2220cb12a0916bap-1L,
+ 0x1.c40ab5fffd07a6d14df820f17deap-1L,
+ 0x1.c67f12e57d14b4a2137fd20f2a26p-1L,
+ 0x1.c8f6d9406e7b511acbc48805c3f6p-1L,
+ 0x1.cb720dcef90691503cbd1e949d0ap-1L,
+ 0x1.cdf0b555dc3f9c44f8958fac4f12p-1L,
+ 0x1.d072d4a07897b8d0f22f21a13792p-1L,
+ 0x1.d2f87080d89f18ade123989ea50ep-1L,
+ 0x1.d5818dcfba48725da05aeb66dff8p-1L,
+ 0x1.d80e316c98397bb84f9d048807a0p-1L,
+ 0x1.da9e603db3285708c01a5b6d480cp-1L,
+ 0x1.dd321f301b4604b695de3c0630c0p-1L,
+ 0x1.dfc97337b9b5eb968cac39ed284cp-1L,
+ 0x1.e264614f5a128a12761fa17adc74p-1L,
+ 0x1.e502ee78b3ff6273d130153992d0p-1L,
+ 0x1.e7a51fbc74c834b548b2832378a4p-1L,
+ 0x1.ea4afa2a490d9858f73a18f5dab4p-1L,
+ 0x1.ecf482d8e67f08db0312fb949d50p-1L,
+ 0x1.efa1bee615a27771fd21a92dabb6p-1L,
+ 0x1.f252b376bba974e8696fc3638f24p-1L,
+ 0x1.f50765b6e4540674f84b762861a6p-1L,
+ 0x1.f7bfdad9cbe138913b4bfe72bd78p-1L,
+ 0x1.fa7c1819e90d82e90a7e74b26360p-1L,
+ 0x1.fd3c22b8f71f10975ba4b32bd006p-1L,
+ 0x1.0000000000000000000000000000p+0L,
+ 0x1.0163da9fb33356d84a66ae336e98p+0L,
+ 0x1.02c9a3e778060ee6f7caca4f7a18p+0L,
+ 0x1.04315e86e7f84bd738f9a20da442p+0L,
+ 0x1.059b0d31585743ae7c548eb68c6ap+0L,
+ 0x1.0706b29ddf6ddc6dc403a9d87b1ep+0L,
+ 0x1.0874518759bc808c35f25d942856p+0L,
+ 0x1.09e3ecac6f3834521e060c584d5cp+0L,
+ 0x1.0b5586cf9890f6298b92b7184200p+0L,
+ 0x1.0cc922b7247f7407b705b893dbdep+0L,
+ 0x1.0e3ec32d3d1a2020742e4f8af794p+0L,
+ 0x1.0fb66affed31af232091dd8a169ep+0L,
+ 0x1.11301d0125b50a4ebbf1aed9321cp+0L,
+ 0x1.12abdc06c31cbfb92bad324d6f84p+0L,
+ 0x1.1429aaea92ddfb34101943b2588ep+0L,
+ 0x1.15a98c8a58e512480d573dd562aep+0L,
+ 0x1.172b83c7d517adcdf7c8c50eb162p+0L,
+ 0x1.18af9388c8de9bbbf70b9a3c269cp+0L,
+ 0x1.1a35beb6fcb753cb698f692d2038p+0L,
+ 0x1.1bbe084045cd39ab1e72b442810ep+0L,
+ 0x1.1d4873168b9aa7805b8028990be8p+0L,
+ 0x1.1ed5022fcd91cb8819ff61121fbep+0L,
+ 0x1.2063b88628cd63b8eeb0295093f6p+0L,
+ 0x1.21f49917ddc962552fd29294bc20p+0L,
+ 0x1.2387a6e75623866c1fadb1c159c0p+0L,
+ 0x1.251ce4fb2a63f3582ab7de9e9562p+0L,
+ 0x1.26b4565e27cdd257a673281d3068p+0L,
+ 0x1.284dfe1f5638096cf15cf03c9fa0p+0L,
+ 0x1.29e9df51fdee12c25d15f5a25022p+0L,
+ 0x1.2b87fd0dad98ffddea46538fca24p+0L,
+ 0x1.2d285a6e4030b40091d536d0733ep+0L,
+ 0x1.2ecafa93e2f5611ca0f45d5239a4p+0L,
+ 0x1.306fe0a31b7152de8d5a463063bep+0L,
+ 0x1.32170fc4cd8313539cf1c3009330p+0L,
+ 0x1.33c08b26416ff4c9c8610d96680ep+0L,
+ 0x1.356c55f929ff0c94623476373be4p+0L,
+ 0x1.371a7373aa9caa7145502f45452ap+0L,
+ 0x1.38cae6d05d86585a9cb0d9bed530p+0L,
+ 0x1.3a7db34e59ff6ea1bc9299e0a1fep+0L,
+ 0x1.3c32dc313a8e484001f228b58cf0p+0L,
+ 0x1.3dea64c12342235b41223e13d7eep+0L,
+ 0x1.3fa4504ac801ba0bf701aa417b9cp+0L,
+ 0x1.4160a21f72e29f84325b8f3dbacap+0L,
+ 0x1.431f5d950a896dc704439410b628p+0L,
+ 0x1.44e086061892d03136f409df0724p+0L,
+ 0x1.46a41ed1d005772512f459229f0ap+0L,
+ 0x1.486a2b5c13cd013c1a3b69062f26p+0L,
+ 0x1.4a32af0d7d3de672d8bcf46f99b4p+0L,
+ 0x1.4bfdad5362a271d4397afec42e36p+0L,
+ 0x1.4dcb299fddd0d63b36ef1a9e19dep+0L,
+ 0x1.4f9b2769d2ca6ad33d8b69aa0b8cp+0L,
+ 0x1.516daa2cf6641c112f52c84d6066p+0L,
+ 0x1.5342b569d4f81df0a83c49d86bf4p+0L,
+ 0x1.551a4ca5d920ec52ec620243540cp+0L,
+ 0x1.56f4736b527da66ecb004764e61ep+0L,
+ 0x1.58d12d497c7fd252bc2b7343d554p+0L,
+ 0x1.5ab07dd48542958c93015191e9a8p+0L,
+ 0x1.5c9268a5946b701c4b1b81697ed4p+0L,
+ 0x1.5e76f15ad21486e9be4c20399d12p+0L,
+ 0x1.605e1b976dc08b076f592a487066p+0L,
+ 0x1.6247eb03a5584b1f0fa06fd2d9eap+0L,
+ 0x1.6434634ccc31fc76f8714c4ee122p+0L,
+ 0x1.66238825522249127d9e29b92ea2p+0L,
+ 0x1.68155d44ca973081c57227b9f69ep+0L,
+};
+
+static const float eps[TBLSIZE] = {
+ -0x1.5c50p-101,
+ -0x1.5d00p-106,
+ 0x1.8e90p-102,
+ -0x1.5340p-103,
+ 0x1.1bd0p-102,
+ -0x1.4600p-105,
+ -0x1.7a40p-104,
+ 0x1.d590p-102,
+ -0x1.d590p-101,
+ 0x1.b100p-103,
+ -0x1.0d80p-105,
+ 0x1.6b00p-103,
+ -0x1.9f00p-105,
+ 0x1.c400p-103,
+ 0x1.e120p-103,
+ -0x1.c100p-104,
+ -0x1.9d20p-103,
+ 0x1.a800p-108,
+ 0x1.4c00p-106,
+ -0x1.9500p-106,
+ 0x1.6900p-105,
+ -0x1.29d0p-100,
+ 0x1.4c60p-103,
+ 0x1.13a0p-102,
+ -0x1.5b60p-103,
+ -0x1.1c40p-103,
+ 0x1.db80p-102,
+ 0x1.91a0p-102,
+ 0x1.dc00p-105,
+ 0x1.44c0p-104,
+ 0x1.9710p-102,
+ 0x1.8760p-103,
+ -0x1.a720p-103,
+ 0x1.ed20p-103,
+ -0x1.49c0p-102,
+ -0x1.e000p-111,
+ 0x1.86a0p-103,
+ 0x1.2b40p-103,
+ -0x1.b400p-108,
+ 0x1.1280p-99,
+ -0x1.02d8p-102,
+ -0x1.e3d0p-103,
+ -0x1.b080p-105,
+ -0x1.f100p-107,
+ -0x1.16c0p-105,
+ -0x1.1190p-103,
+ -0x1.a7d2p-100,
+ 0x1.3450p-103,
+ -0x1.67c0p-105,
+ 0x1.4b80p-104,
+ -0x1.c4e0p-103,
+ 0x1.6000p-108,
+ -0x1.3f60p-105,
+ 0x1.93f0p-104,
+ 0x1.5fe0p-105,
+ 0x1.6f80p-107,
+ -0x1.7600p-106,
+ 0x1.21e0p-106,
+ -0x1.3a40p-106,
+ -0x1.40c0p-104,
+ -0x1.9860p-105,
+ -0x1.5d40p-108,
+ -0x1.1d70p-106,
+ 0x1.2760p-105,
+ 0x0.0000p+0,
+ 0x1.21e2p-104,
+ -0x1.9520p-108,
+ -0x1.5720p-106,
+ -0x1.4810p-106,
+ -0x1.be00p-109,
+ 0x1.0080p-105,
+ -0x1.5780p-108,
+ -0x1.d460p-105,
+ -0x1.6140p-105,
+ 0x1.4630p-104,
+ 0x1.ad50p-103,
+ 0x1.82e0p-105,
+ 0x1.1d3cp-101,
+ 0x1.6100p-107,
+ 0x1.ec30p-104,
+ 0x1.f200p-108,
+ 0x1.0b40p-103,
+ 0x1.3660p-102,
+ 0x1.d9d0p-103,
+ -0x1.02d0p-102,
+ 0x1.b070p-103,
+ 0x1.b9c0p-104,
+ -0x1.01c0p-103,
+ -0x1.dfe0p-103,
+ 0x1.1b60p-104,
+ -0x1.ae94p-101,
+ -0x1.3340p-104,
+ 0x1.b3d8p-102,
+ -0x1.6e40p-105,
+ -0x1.3670p-103,
+ 0x1.c140p-104,
+ 0x1.1840p-101,
+ 0x1.1ab0p-102,
+ -0x1.a400p-104,
+ 0x1.1f00p-104,
+ -0x1.7180p-103,
+ 0x1.4ce0p-102,
+ 0x1.9200p-107,
+ -0x1.54c0p-103,
+ 0x1.1b80p-105,
+ -0x1.1828p-101,
+ 0x1.5720p-102,
+ -0x1.a060p-100,
+ 0x1.9160p-102,
+ 0x1.a280p-104,
+ 0x1.3400p-107,
+ 0x1.2b20p-102,
+ 0x1.7800p-108,
+ 0x1.cfd0p-101,
+ 0x1.2ef0p-102,
+ -0x1.2760p-99,
+ 0x1.b380p-104,
+ 0x1.0048p-101,
+ -0x1.60b0p-102,
+ 0x1.a1ccp-100,
+ -0x1.a640p-104,
+ -0x1.08a0p-101,
+ 0x1.7e60p-102,
+ 0x1.22c0p-103,
+ -0x1.7200p-106,
+ 0x1.f0f0p-102,
+ 0x1.eb4ep-99,
+ 0x1.c6e0p-103,
+};
+
+/*
+ * exp2l(x): compute the base 2 exponential of x
+ *
+ * Accuracy: Peak error < 0.502 ulp.
+ *
+ * Method: (accurate tables)
+ *
+ * Reduce x:
+ * x = 2**k + y, for integer k and |y| <= 1/2.
+ * Thus we have exp2(x) = 2**k * exp2(y).
+ *
+ * Reduce y:
+ * y = i/TBLSIZE + z - eps[i] for integer i near y * TBLSIZE.
+ * Thus we have exp2(y) = exp2(i/TBLSIZE) * exp2(z - eps[i]),
+ * with |z - eps[i]| <= 2**-8 + 2**-98 for the table used.
+ *
+ * We compute exp2(i/TBLSIZE) via table lookup and exp2(z - eps[i]) via
+ * a degree-10 minimax polynomial with maximum error under 2**-120.
+ * The values in exp2t[] and eps[] are chosen such that
+ * exp2t[i] = exp2(i/TBLSIZE + eps[i]), and eps[i] is a small offset such
+ * that exp2t[i] is accurate to 2**-122.
+ *
+ * Note that the range of i is +-TBLSIZE/2, so we actually index the tables
+ * by i0 = i + TBLSIZE/2.
+ *
+ * This method is due to Gal, with many details due to Gal and Bachelis:
+ *
+ * Gal, S. and Bachelis, B. An Accurate Elementary Mathematical Library
+ * for the IEEE Floating Point Standard. TOMS 17(1), 26-46 (1991).
+ */
+OLM_DLLEXPORT long double
+exp2l(long double x)
+{
+ union IEEEl2bits u, v;
+ long double r, t, twopk, twopkp10000, z;
+ uint32_t hx, ix, i0;
+ int k;
+
+ u.e = x;
+
+ /* Filter out exceptional cases. */
+ hx = u.xbits.expsign;
+ ix = hx & EXPMASK;
+ if (ix >= BIAS + 14) { /* |x| >= 16384 */
+ if (ix == BIAS + LDBL_MAX_EXP) {
+ if (u.xbits.manh != 0
+ || u.xbits.manl != 0
+ || (hx & 0x8000) == 0)
+ return (x + x); /* x is NaN or +Inf */
+ else
+ return (0.0); /* x is -Inf */
+ }
+ if (x >= 16384)
+ return (huge * huge); /* overflow */
+ if (x <= -16495)
+ return (twom10000 * twom10000); /* underflow */
+ } else if (ix <= BIAS - 115) { /* |x| < 0x1p-115 */
+ return (1.0 + x);
+ }
+
+ /*
+ * Reduce x, computing z, i0, and k. The low bits of x + redux
+ * contain the 16-bit integer part of the exponent (k) followed by
+ * TBLBITS fractional bits (i0). We use bit tricks to extract these
+ * as integers, then set z to the remainder.
+ *
+ * Example: Suppose x is 0xabc.123456p0 and TBLBITS is 8.
+ * Then the low-order word of x + redux is 0x000abc12,
+ * We split this into k = 0xabc and i0 = 0x12 (adjusted to
+ * index into the table), then we compute z = 0x0.003456p0.
+ *
+ * XXX If the exponent is negative, the computation of k depends on
+ * '>>' doing sign extension.
+ */
+ u.e = x + redux;
+ i0 = (u.bits.manl & 0xffffffff) + TBLSIZE / 2;
+ k = (int)i0 >> TBLBITS;
+ i0 = i0 & (TBLSIZE - 1);
+ u.e -= redux;
+ z = x - u.e;
+ v.xbits.manh = 0;
+ v.xbits.manl = 0;
+ if (k >= LDBL_MIN_EXP) {
+ v.xbits.expsign = LDBL_MAX_EXP - 1 + k;
+ twopk = v.e;
+ } else {
+ v.xbits.expsign = LDBL_MAX_EXP - 1 + k + 10000;
+ twopkp10000 = v.e;
+ }
+
+ /* Compute r = exp2(y) = exp2t[i0] * p(z - eps[i]). */
+ t = tbl[i0]; /* exp2t[i0] */
+ z -= eps[i0]; /* eps[i0] */
+ r = t + t * z * (P1 + z * (P2 + z * (P3 + z * (P4 + z * (P5 + z * (P6
+ + z * (P7 + z * (P8 + z * (P9 + z * P10)))))))));
+
+ /* Scale by 2**k. */
+ if(k >= LDBL_MIN_EXP) {
+ if (k == LDBL_MAX_EXP)
+ return (r * 2.0 * 0x1p16383L);
+ return (r * twopk);
+ } else {
+ return (r * twopkp10000 * twom10000);
+ }
+}
--- /dev/null
+/* $OpenBSD: s_expm1l.c,v 1.1 2011/07/06 00:02:42 martynas Exp $ */
+
+/*
+ * Copyright (c) 2008 Stephen L. Moshier <steve@moshier.net>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* expm1l.c
+ *
+ * Exponential function, minus 1
+ * 128-bit long double precision
+ *
+ *
+ *
+ * SYNOPSIS:
+ *
+ * long double x, y, expm1l();
+ *
+ * y = expm1l( x );
+ *
+ *
+ *
+ * DESCRIPTION:
+ *
+ * Returns e (2.71828...) raised to the x power, minus one.
+ *
+ * Range reduction is accomplished by separating the argument
+ * into an integer k and fraction f such that
+ *
+ * x k f
+ * e = 2 e.
+ *
+ * An expansion x + .5 x^2 + x^3 R(x) approximates exp(f) - 1
+ * in the basic range [-0.5 ln 2, 0.5 ln 2].
+ *
+ *
+ * ACCURACY:
+ *
+ * Relative error:
+ * arithmetic domain # trials peak rms
+ * IEEE -79,+MAXLOG 100,000 1.7e-34 4.5e-35
+ *
+ */
+
+#include <errno.h>
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+/* exp(x) - 1 = x + 0.5 x^2 + x^3 P(x)/Q(x)
+ -.5 ln 2 < x < .5 ln 2
+ Theoretical peak relative error = 8.1e-36 */
+
+static const long double
+ P0 = 2.943520915569954073888921213330863757240E8L,
+ P1 = -5.722847283900608941516165725053359168840E7L,
+ P2 = 8.944630806357575461578107295909719817253E6L,
+ P3 = -7.212432713558031519943281748462837065308E5L,
+ P4 = 4.578962475841642634225390068461943438441E4L,
+ P5 = -1.716772506388927649032068540558788106762E3L,
+ P6 = 4.401308817383362136048032038528753151144E1L,
+ P7 = -4.888737542888633647784737721812546636240E-1L,
+ Q0 = 1.766112549341972444333352727998584753865E9L,
+ Q1 = -7.848989743695296475743081255027098295771E8L,
+ Q2 = 1.615869009634292424463780387327037251069E8L,
+ Q3 = -2.019684072836541751428967854947019415698E7L,
+ Q4 = 1.682912729190313538934190635536631941751E6L,
+ Q5 = -9.615511549171441430850103489315371768998E4L,
+ Q6 = 3.697714952261803935521187272204485251835E3L,
+ Q7 = -8.802340681794263968892934703309274564037E1L,
+ /* Q8 = 1.000000000000000000000000000000000000000E0 */
+/* C1 + C2 = ln 2 */
+
+ C1 = 6.93145751953125E-1L,
+ C2 = 1.428606820309417232121458176568075500134E-6L,
+/* ln (2^16384 * (1 - 2^-113)) */
+ maxlog = 1.1356523406294143949491931077970764891253E4L,
+/* ln 2^-114 */
+ minarg = -7.9018778583833765273564461846232128760607E1L, big = 1e4932L;
+
+
+long double
+expm1l(long double x)
+{
+ long double px, qx, xx;
+ int32_t ix, sign;
+ ieee_quad_shape_type u;
+ int k;
+
+ /* Detect infinity and NaN. */
+ u.value = x;
+ ix = u.parts32.mswhi;
+ sign = ix & 0x80000000;
+ ix &= 0x7fffffff;
+ if (ix >= 0x7fff0000)
+ {
+ /* Infinity. */
+ if (((ix & 0xffff) | u.parts32.mswlo | u.parts32.lswhi |
+ u.parts32.lswlo) == 0)
+ {
+ if (sign)
+ return -1.0L;
+ else
+ return x;
+ }
+ /* NaN. No invalid exception. */
+ return x;
+ }
+
+ /* expm1(+- 0) = +- 0. */
+ if ((ix == 0) && (u.parts32.mswlo | u.parts32.lswhi | u.parts32.lswlo) == 0)
+ return x;
+
+ /* Overflow. */
+ if (x > maxlog)
+ return (big * big);
+
+ /* Minimum value. */
+ if (x < minarg)
+ return (4.0/big - 1.0L);
+
+ /* Express x = ln 2 (k + remainder), remainder not exceeding 1/2. */
+ xx = C1 + C2; /* ln 2. */
+ px = floorl (0.5 + x / xx);
+ k = px;
+ /* remainder times ln 2 */
+ x -= px * C1;
+ x -= px * C2;
+
+ /* Approximate exp(remainder ln 2). */
+ px = (((((((P7 * x
+ + P6) * x
+ + P5) * x + P4) * x + P3) * x + P2) * x + P1) * x + P0) * x;
+
+ qx = (((((((x
+ + Q7) * x
+ + Q6) * x + Q5) * x + Q4) * x + Q3) * x + Q2) * x + Q1) * x + Q0;
+
+ xx = x * x;
+ qx = x + (0.5 * xx + xx * px / qx);
+
+ /* exp(x) = exp(k ln 2) exp(remainder ln 2) = 2^k exp(remainder ln 2).
+
+ We have qx = exp(remainder ln 2) - 1, so
+ exp(x) - 1 = 2^k (qx + 1) - 1
+ = 2^k qx + 2^k - 1. */
+
+ px = ldexpl (1.0L, k);
+ x = px * qx + (px - 1.0);
+ return x;
+}
--- /dev/null
+/* @(#)s_floor.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/*
+ * floorl(x)
+ * Return x rounded toward -inf to integral value
+ * Method:
+ * Bit twiddling.
+ * Exception:
+ * Inexact flag raised if x not equal to floor(x).
+ */
+
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+static const long double huge = 1.0e4930L;
+
+long double
+floorl(long double x)
+{
+ int64_t i0,i1,jj0;
+ u_int64_t i,j;
+ GET_LDOUBLE_WORDS64(i0,i1,x);
+ jj0 = ((i0>>48)&0x7fff)-0x3fff;
+ if(jj0<48) {
+ if(jj0<0) { /* raise inexact if x != 0 */
+ if(huge+x>0.0) {
+ if(i0>=0)
+ return 0.0L;
+ else if(((i0&0x7fffffffffffffffLL)|i1)!=0)
+ return -1.0L;
+ }
+ } else {
+ i = (0x0000ffffffffffffULL)>>jj0;
+ if(((i0&i)|i1)==0) return x; /* x is integral */
+ if(huge+x>0.0) { /* raise inexact flag */
+ if(i0<0) i0 += (0x0001000000000000LL)>>jj0;
+ i0 &= (~i); i1=0;
+ }
+ }
+ } else if (jj0>111) {
+ if(jj0==0x4000) return x+x; /* inf or NaN */
+ else return x; /* x is integral */
+ } else {
+ i = -1ULL>>(jj0-48);
+ if((i1&i)==0) return x; /* x is integral */
+ if(huge+x>0.0) { /* raise inexact flag */
+ if(i0<0) {
+ if(jj0==48) i0+=1;
+ else {
+ j = i1+(1LL<<(112-jj0));
+ if(j<i1) i0 +=1 ; /* got a carry */
+ i1=j;
+ }
+ }
+ i1 &= (~i);
+ }
+ }
+ SET_LDOUBLE_WORDS64(x,i0,i1);
+ return x;
+}
--- /dev/null
+/* $OpenBSD: s_log1pl.c,v 1.1 2011/07/06 00:02:42 martynas Exp $ */
+
+/*
+ * Copyright (c) 2008 Stephen L. Moshier <steve@moshier.net>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* log1pl.c
+ *
+ * Relative error logarithm
+ * Natural logarithm of 1+x, 128-bit long double precision
+ *
+ *
+ *
+ * SYNOPSIS:
+ *
+ * long double x, y, log1pl();
+ *
+ * y = log1pl( x );
+ *
+ *
+ *
+ * DESCRIPTION:
+ *
+ * Returns the base e (2.718...) logarithm of 1+x.
+ *
+ * The argument 1+x is separated into its exponent and fractional
+ * parts. If the exponent is between -1 and +1, the logarithm
+ * of the fraction is approximated by
+ *
+ * log(1+x) = x - 0.5 x^2 + x^3 P(x)/Q(x).
+ *
+ * Otherwise, setting z = 2(w-1)/(w+1),
+ *
+ * log(w) = z + z^3 P(z)/Q(z).
+ *
+ *
+ *
+ * ACCURACY:
+ *
+ * Relative error:
+ * arithmetic domain # trials peak rms
+ * IEEE -1, 8 100000 1.9e-34 4.3e-35
+ */
+
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+/* Coefficients for log(1+x) = x - x^2 / 2 + x^3 P(x)/Q(x)
+ * 1/sqrt(2) <= 1+x < sqrt(2)
+ * Theoretical peak relative error = 5.3e-37,
+ * relative peak error spread = 2.3e-14
+ */
+static const long double
+ P12 = 1.538612243596254322971797716843006400388E-6L,
+ P11 = 4.998469661968096229986658302195402690910E-1L,
+ P10 = 2.321125933898420063925789532045674660756E1L,
+ P9 = 4.114517881637811823002128927449878962058E2L,
+ P8 = 3.824952356185897735160588078446136783779E3L,
+ P7 = 2.128857716871515081352991964243375186031E4L,
+ P6 = 7.594356839258970405033155585486712125861E4L,
+ P5 = 1.797628303815655343403735250238293741397E5L,
+ P4 = 2.854829159639697837788887080758954924001E5L,
+ P3 = 3.007007295140399532324943111654767187848E5L,
+ P2 = 2.014652742082537582487669938141683759923E5L,
+ P1 = 7.771154681358524243729929227226708890930E4L,
+ P0 = 1.313572404063446165910279910527789794488E4L,
+ /* Q12 = 1.000000000000000000000000000000000000000E0L, */
+ Q11 = 4.839208193348159620282142911143429644326E1L,
+ Q10 = 9.104928120962988414618126155557301584078E2L,
+ Q9 = 9.147150349299596453976674231612674085381E3L,
+ Q8 = 5.605842085972455027590989944010492125825E4L,
+ Q7 = 2.248234257620569139969141618556349415120E5L,
+ Q6 = 6.132189329546557743179177159925690841200E5L,
+ Q5 = 1.158019977462989115839826904108208787040E6L,
+ Q4 = 1.514882452993549494932585972882995548426E6L,
+ Q3 = 1.347518538384329112529391120390701166528E6L,
+ Q2 = 7.777690340007566932935753241556479363645E5L,
+ Q1 = 2.626900195321832660448791748036714883242E5L,
+ Q0 = 3.940717212190338497730839731583397586124E4L;
+
+/* Coefficients for log(x) = z + z^3 P(z^2)/Q(z^2),
+ * where z = 2(x-1)/(x+1)
+ * 1/sqrt(2) <= x < sqrt(2)
+ * Theoretical peak relative error = 1.1e-35,
+ * relative peak error spread 1.1e-9
+ */
+static const long double
+ R5 = -8.828896441624934385266096344596648080902E-1L,
+ R4 = 8.057002716646055371965756206836056074715E1L,
+ R3 = -2.024301798136027039250415126250455056397E3L,
+ R2 = 2.048819892795278657810231591630928516206E4L,
+ R1 = -8.977257995689735303686582344659576526998E4L,
+ R0 = 1.418134209872192732479751274970992665513E5L,
+ /* S6 = 1.000000000000000000000000000000000000000E0L, */
+ S5 = -1.186359407982897997337150403816839480438E2L,
+ S4 = 3.998526750980007367835804959888064681098E3L,
+ S3 = -5.748542087379434595104154610899551484314E4L,
+ S2 = 4.001557694070773974936904547424676279307E5L,
+ S1 = -1.332535117259762928288745111081235577029E6L,
+ S0 = 1.701761051846631278975701529965589676574E6L;
+
+/* C1 + C2 = ln 2 */
+static const long double C1 = 6.93145751953125E-1L;
+static const long double C2 = 1.428606820309417232121458176568075500134E-6L;
+
+static const long double sqrth = 0.7071067811865475244008443621048490392848L;
+/* ln (2^16384 * (1 - 2^-113)) */
+static const long double zero = 0.0L;
+
+long double
+log1pl(long double xm1)
+{
+ long double x, y, z, r, s;
+ ieee_quad_shape_type u;
+ int32_t hx;
+ int e;
+
+ /* Test for NaN or infinity input. */
+ u.value = xm1;
+ hx = u.parts32.mswhi;
+ if (hx >= 0x7fff0000)
+ return xm1;
+
+ /* log1p(+- 0) = +- 0. */
+ if (((hx & 0x7fffffff) == 0)
+ && (u.parts32.mswlo | u.parts32.lswhi | u.parts32.lswlo) == 0)
+ return xm1;
+
+ x = xm1 + 1.0L;
+
+ /* log1p(-1) = -inf */
+ if (x <= 0.0L)
+ {
+ if (x == 0.0L)
+ return (-1.0L / (x - x));
+ else
+ return (zero / (x - x));
+ }
+
+ /* Separate mantissa from exponent. */
+
+ /* Use frexp used so that denormal numbers will be handled properly. */
+ x = frexpl (x, &e);
+
+ /* Logarithm using log(x) = z + z^3 P(z^2)/Q(z^2),
+ where z = 2(x-1)/x+1). */
+ if ((e > 2) || (e < -2))
+ {
+ if (x < sqrth)
+ { /* 2( 2x-1 )/( 2x+1 ) */
+ e -= 1;
+ z = x - 0.5L;
+ y = 0.5L * z + 0.5L;
+ }
+ else
+ { /* 2 (x-1)/(x+1) */
+ z = x - 0.5L;
+ z -= 0.5L;
+ y = 0.5L * x + 0.5L;
+ }
+ x = z / y;
+ z = x * x;
+ r = ((((R5 * z
+ + R4) * z
+ + R3) * z
+ + R2) * z
+ + R1) * z
+ + R0;
+ s = (((((z
+ + S5) * z
+ + S4) * z
+ + S3) * z
+ + S2) * z
+ + S1) * z
+ + S0;
+ z = x * (z * r / s);
+ z = z + e * C2;
+ z = z + x;
+ z = z + e * C1;
+ return (z);
+ }
+
+
+ /* Logarithm using log(1+x) = x - .5x^2 + x^3 P(x)/Q(x). */
+
+ if (x < sqrth)
+ {
+ e -= 1;
+ if (e != 0)
+ x = 2.0L * x - 1.0L; /* 2x - 1 */
+ else
+ x = xm1;
+ }
+ else
+ {
+ if (e != 0)
+ x = x - 1.0L;
+ else
+ x = xm1;
+ }
+ z = x * x;
+ r = (((((((((((P12 * x
+ + P11) * x
+ + P10) * x
+ + P9) * x
+ + P8) * x
+ + P7) * x
+ + P6) * x
+ + P5) * x
+ + P4) * x
+ + P3) * x
+ + P2) * x
+ + P1) * x
+ + P0;
+ s = (((((((((((x
+ + Q11) * x
+ + Q10) * x
+ + Q9) * x
+ + Q8) * x
+ + Q7) * x
+ + Q6) * x
+ + Q5) * x
+ + Q4) * x
+ + Q3) * x
+ + Q2) * x
+ + Q1) * x
+ + Q0;
+ y = x * (z * r / s);
+ y = y + e * C2;
+ z = y - 0.5L * z;
+ z = z + x;
+ z = z + e * C1;
+ return (z);
+}
--- /dev/null
+/* @(#)s_modf.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/*
+ * modfl(long double x, long double *iptr)
+ * return fraction part of x, and return x's integral part in *iptr.
+ * Method:
+ * Bit twiddling.
+ *
+ * Exception:
+ * No exception.
+ */
+
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+static const long double one = 1.0;
+
+long double
+modfl(long double x, long double *iptr)
+{
+ int64_t i0,i1,jj0;
+ u_int64_t i;
+ GET_LDOUBLE_WORDS64(i0,i1,x);
+ jj0 = ((i0>>48)&0x7fff)-0x3fff; /* exponent of x */
+ if(jj0<48) { /* integer part in high x */
+ if(jj0<0) { /* |x|<1 */
+ /* *iptr = +-0 */
+ SET_LDOUBLE_WORDS64(*iptr,i0&0x8000000000000000ULL,0);
+ return x;
+ } else {
+ i = (0x0000ffffffffffffLL)>>jj0;
+ if(((i0&i)|i1)==0) { /* x is integral */
+ *iptr = x;
+ /* return +-0 */
+ SET_LDOUBLE_WORDS64(x,i0&0x8000000000000000ULL,0);
+ return x;
+ } else {
+ SET_LDOUBLE_WORDS64(*iptr,i0&(~i),0);
+ return x - *iptr;
+ }
+ }
+ } else if (jj0>111) { /* no fraction part */
+ *iptr = x*one;
+ /* We must handle NaNs separately. */
+ if (jj0 == 0x4000 && ((i0 & 0x0000ffffffffffffLL) | i1))
+ return x*one;
+ /* return +-0 */
+ SET_LDOUBLE_WORDS64(x,i0&0x8000000000000000ULL,0);
+ return x;
+ } else { /* fraction part in low x */
+ i = -1ULL>>(jj0-48);
+ if((i1&i)==0) { /* x is integral */
+ *iptr = x;
+ /* return +-0 */
+ SET_LDOUBLE_WORDS64(x,i0&0x8000000000000000ULL,0);
+ return x;
+ } else {
+ SET_LDOUBLE_WORDS64(*iptr,i0,i1&(~i));
+ return x - *iptr;
+ }
+ }
+}
--- /dev/null
+/*-
+ * Copyright (c) 2007 David Schultz
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: src/lib/msun/ld128/s_nanl.c,v 1.3 2008/03/02 20:16:55 das Exp $
+ */
+
+#include <openlibm_math.h>
+
+#include "fpmath.h"
+#include "math_private.h"
+
+OLM_DLLEXPORT long double
+nanl(const char *s)
+{
+ union {
+ union IEEEl2bits ieee;
+ uint32_t bits[4];
+ } u;
+
+ __scan_nan(u.bits, 4, s);
+ u.ieee.bits.exp = 0x7fff;
+ u.ieee.bits.manh |= 1ULL << 47; /* make it a quiet NaN */
+ return (u.ieee.e);
+}
--- /dev/null
+/* @(#)s_nextafter.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/* IEEE functions
+ * nextafterl(x,y)
+ * return the next machine floating-point number of x in the
+ * direction toward y.
+ * Special cases:
+ */
+
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+long double
+nextafterl(long double x, long double y)
+{
+ int64_t hx,hy,ix,iy;
+ u_int64_t lx,ly;
+
+ GET_LDOUBLE_WORDS64(hx,lx,x);
+ GET_LDOUBLE_WORDS64(hy,ly,y);
+ ix = hx&0x7fffffffffffffffLL; /* |x| */
+ iy = hy&0x7fffffffffffffffLL; /* |y| */
+
+ if(((ix>=0x7fff000000000000LL)&&((ix-0x7fff000000000000LL)|lx)!=0) || /* x is nan */
+ ((iy>=0x7fff000000000000LL)&&((iy-0x7fff000000000000LL)|ly)!=0)) /* y is nan */
+ return x+y;
+ if(x==y) return y; /* x=y, return y */
+ if((ix|lx)==0) { /* x == 0 */
+ volatile long double u;
+ SET_LDOUBLE_WORDS64(x,hy&0x8000000000000000ULL,1);/* return +-minsubnormal */
+ u = x;
+ u = u * u; /* raise underflow flag */
+ return x;
+ }
+ if(hx>=0) { /* x > 0 */
+ if(hx>hy||((hx==hy)&&(lx>ly))) { /* x > y, x -= ulp */
+ if(lx==0) hx--;
+ lx--;
+ } else { /* x < y, x += ulp */
+ lx++;
+ if(lx==0) hx++;
+ }
+ } else { /* x < 0 */
+ if(hy>=0||hx>hy||((hx==hy)&&(lx>ly))){/* x < y, x -= ulp */
+ if(lx==0) hx--;
+ lx--;
+ } else { /* x > y, x += ulp */
+ lx++;
+ if(lx==0) hx++;
+ }
+ }
+ hy = hx&0x7fff000000000000LL;
+ if(hy==0x7fff000000000000LL) return x+x;/* overflow */
+ if(hy==0) {
+ volatile long double u = x*x; /* underflow */
+ }
+ SET_LDOUBLE_WORDS64(x,hx,lx);
+ return x;
+}
+
+__strong_alias(nexttowardl, nextafterl);
--- /dev/null
+/* @(#)s_nextafter.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/* IEEE functions
+ * nexttoward(x,y)
+ * return the next machine floating-point number of x in the
+ * direction toward y.
+ * Special cases:
+ */
+
+#include <float.h>
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+double
+nexttoward(double x, long double y)
+{
+ int32_t hx,ix;
+ int64_t hy,iy;
+ u_int32_t lx;
+ u_int64_t ly;
+
+ EXTRACT_WORDS(hx,lx,x);
+ GET_LDOUBLE_WORDS64(hy,ly,y);
+ ix = hx&0x7fffffff; /* |x| */
+ iy = hy&0x7fffffffffffffffLL; /* |y| */
+
+ if(((ix>=0x7ff00000)&&((ix-0x7ff00000)|lx)!=0) || /* x is nan */
+ ((iy>=0x7fff000000000000LL)&&((iy-0x7fff000000000000LL)|ly)!=0))
+ /* y is nan */
+ return x+y;
+ if((long double) x==y) return y; /* x=y, return y */
+ if((ix|lx)==0) { /* x == 0 */
+ volatile double u;
+ INSERT_WORDS(x,(u_int32_t)((hy>>32)&0x80000000),1);/* return +-minsub */
+ u = x;
+ u = u * u; /* raise underflow flag */
+ return x;
+ }
+ if(hx>=0) { /* x > 0 */
+ if (hy<0||(ix>>20)>(iy>>48)-0x3c00
+ || ((ix>>20)==(iy>>48)-0x3c00
+ && (((((int64_t)hx)<<28)|(lx>>4))>(hy&0x0000ffffffffffffLL)
+ || (((((int64_t)hx)<<28)|(lx>>4))==(hy&0x0000ffffffffffffLL)
+ && (lx&0xf)>(ly>>60))))) { /* x > y, x -= ulp */
+ if(lx==0) hx -= 1;
+ lx -= 1;
+ } else { /* x < y, x += ulp */
+ lx += 1;
+ if(lx==0) hx += 1;
+ }
+ } else { /* x < 0 */
+ if (hy>=0||(ix>>20)>(iy>>48)-0x3c00
+ || ((ix>>20)==(iy>>48)-0x3c00
+ && (((((int64_t)hx)<<28)|(lx>>4))>(hy&0x0000ffffffffffffLL)
+ || (((((int64_t)hx)<<28)|(lx>>4))==(hy&0x0000ffffffffffffLL)
+ && (lx&0xf)>(ly>>60))))) { /* x < y, x -= ulp */
+ if(lx==0) hx -= 1;
+ lx -= 1;
+ } else { /* x > y, x += ulp */
+ lx += 1;
+ if(lx==0) hx += 1;
+ }
+ }
+ hy = hx&0x7ff00000;
+ if(hy>=0x7ff00000) {
+ x = x+x; /* overflow */
+ return x;
+ }
+ if(hy<0x00100000) {
+ volatile double u = x*x; /* underflow */
+ }
+ INSERT_WORDS(x,hx,lx);
+ return x;
+}
--- /dev/null
+/* @(#)s_nextafter.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+float
+nexttowardf(float x, long double y)
+{
+ int32_t hx,ix;
+ int64_t hy,iy;
+ u_int64_t ly;
+
+ GET_FLOAT_WORD(hx,x);
+ GET_LDOUBLE_WORDS64(hy,ly,y);
+ ix = hx&0x7fffffff; /* |x| */
+ iy = hy&0x7fffffffffffffffLL; /* |y| */
+
+ if((ix>0x7f800000) || /* x is nan */
+ ((iy>=0x7fff000000000000LL)&&((iy-0x7fff000000000000LL)|ly)!=0))
+ /* y is nan */
+ return x+y;
+ if((long double) x==y) return y; /* x=y, return y */
+ if(ix==0) { /* x == 0 */
+ volatile float u;
+ SET_FLOAT_WORD(x,(u_int32_t)((hy>>32)&0x80000000)|1);/* return +-minsub*/
+ u = x;
+ u = u * u; /* raise underflow flag */
+ return x;
+ }
+ if(hx>=0) { /* x > 0 */
+ if(hy<0||(ix>>23)>(iy>>48)-0x3f80
+ || ((ix>>23)==(iy>>48)-0x3f80
+ && (ix&0x7fffff)>((hy>>25)&0x7fffff))) {/* x > y, x -= ulp */
+ hx -= 1;
+ } else { /* x < y, x += ulp */
+ hx += 1;
+ }
+ } else { /* x < 0 */
+ if(hy>=0||(ix>>23)>(iy>>48)-0x3f80
+ || ((ix>>23)==(iy>>48)-0x3f80
+ && (ix&0x7fffff)>((hy>>25)&0x7fffff))) {/* x < y, x -= ulp */
+ hx -= 1;
+ } else { /* x > y, x += ulp */
+ hx += 1;
+ }
+ }
+ hy = hx&0x7f800000;
+ if(hy>=0x7f800000) return x+x; /* overflow */
+ if(hy<0x00800000) {
+ volatile float u = x*x; /* underflow */
+ }
+ SET_FLOAT_WORD(x,hx);
+ return x;
+}
--- /dev/null
+/* @(#)e_fmod.c 1.3 95/01/18 */
+/*-
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunSoft, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include <sys/types.h>
+#include <machine/ieee.h>
+
+#include <float.h>
+#include <openlibm_math.h>
+#include <stdint.h>
+
+#include "math_private.h"
+
+#define BIAS (LDBL_MAX_EXP - 1)
+
+/*
+ * These macros add and remove an explicit integer bit in front of the
+ * fractional mantissa, if the architecture doesn't have such a bit by
+ * default already.
+ */
+#ifdef LDBL_IMPLICIT_NBIT
+#define LDBL_NBIT 0
+#define SET_NBIT(hx) ((hx) | (1ULL << LDBL_MANH_SIZE))
+#define HFRAC_BITS (EXT_FRACHBITS + EXT_FRACHMBITS)
+#else
+#define LDBL_NBIT 0x80000000
+#define SET_NBIT(hx) (hx)
+#define HFRAC_BITS (EXT_FRACHBITS + EXT_FRACHMBITS - 1)
+#endif
+
+#define MANL_SHIFT (EXT_FRACLMBITS + EXT_FRACLBITS - 1)
+
+static const long double Zero[] = {0.0L, -0.0L};
+
+/*
+ * Return the IEEE remainder and set *quo to the last n bits of the
+ * quotient, rounded to the nearest integer. We choose n=31 because
+ * we wind up computing all the integer bits of the quotient anyway as
+ * a side-effect of computing the remainder by the shift and subtract
+ * method. In practice, this is far more bits than are needed to use
+ * remquo in reduction algorithms.
+ *
+ * Assumptions:
+ * - The low part of the mantissa fits in a manl_t exactly.
+ * - The high part of the mantissa fits in an int64_t with enough room
+ * for an explicit integer bit in front of the fractional bits.
+ */
+long double
+remquol(long double x, long double y, int *quo)
+{
+ int64_t hx,hz,hy,_hx;
+ uint64_t lx,ly,lz;
+ uint64_t sx,sxy;
+ int ix,iy,n,q;
+
+ GET_LDOUBLE_WORDS64(hx,lx,x);
+ GET_LDOUBLE_WORDS64(hy,ly,y);
+ sx = (hx>>48)&0x8000;
+ sxy = sx ^ ((hy>>48)&0x8000);
+ hx &= 0x7fffffffffffffffLL; /* |x| */
+ hy &= 0x7fffffffffffffffLL; /* |y| */
+ SET_LDOUBLE_WORDS64(x,hx,lx);
+ SET_LDOUBLE_WORDS64(y,hy,ly);
+
+ /* purge off exception values */
+ if((hy|ly)==0 || /* y=0 */
+ ((hx>>48) == BIAS + LDBL_MAX_EXP) || /* or x not finite */
+ ((hy>>48) == BIAS + LDBL_MAX_EXP &&
+ (((hy&0x0000ffffffffffffLL)&~LDBL_NBIT)|ly)!=0)) /* or y is NaN */
+ return (x*y)/(x*y);
+ if((hx>>48)<=(hy>>48)) {
+ if(((hx>>48)<(hy>>48)) ||
+ ((hx&0x0000ffffffffffffLL)<=(hy&0x0000ffffffffffffLL) &&
+ ((hx&0x0000ffffffffffffLL)<(hy&0x0000ffffffffffffLL) ||
+ lx<ly))) {
+ q = 0;
+ goto fixup; /* |x|<|y| return x or x-y */
+ }
+ if((hx&0x0000ffffffffffffLL)==(hy&0x0000ffffffffffffLL) &&
+ lx==ly) {
+ *quo = 1;
+ return Zero[sx!=0]; /* |x|=|y| return x*0*/
+ }
+ }
+
+ /* determine ix = ilogb(x) */
+ if((hx>>48) == 0) { /* subnormal x */
+ x *= 0x1.0p512;
+ GET_LDOUBLE_WORDS64(hx,lx,x);
+ ix = (hx>>48) - (BIAS + 512);
+ } else {
+ ix = (hx>>48) - BIAS;
+ }
+
+ /* determine iy = ilogb(y) */
+ if((hy>>48) == 0) { /* subnormal y */
+ y *= 0x1.0p512;
+ GET_LDOUBLE_WORDS64(hy,ly,y);
+ iy = (hy>>48) - (BIAS + 512);
+ } else {
+ iy = (hy>>48) - BIAS;
+ }
+
+ /* set up {hx,lx}, {hy,ly} and align y to x */
+ _hx = SET_NBIT(hx) & 0x0000ffffffffffffLL;
+ hy = SET_NBIT(hy);
+
+ /* fix point fmod */
+ n = ix - iy;
+ q = 0;
+
+ while(n--) {
+ hz=_hx-hy;lz=lx-ly; if(lx<ly) hz -= 1;
+ if(hz<0){_hx = _hx+_hx+(lx>>MANL_SHIFT); lx = lx+lx;}
+ else {_hx = hz+hz+(lz>>MANL_SHIFT); lx = lz+lz; q++;}
+ q <<= 1;
+ }
+ hz=_hx-hy;lz=lx-ly; if(lx<ly) hz -= 1;
+ if(hz>=0) {_hx=hz;lx=lz;q++;}
+
+ /* convert back to floating value and restore the sign */
+ if((_hx|lx)==0) { /* return sign(x)*0 */
+ *quo = (sxy ? -q : q);
+ return Zero[sx!=0];
+ }
+ while(_hx<(1ULL<<HFRAC_BITS)) { /* normalize x */
+ _hx = _hx+_hx+(lx>>MANL_SHIFT); lx = lx+lx;
+ iy -= 1;
+ }
+ hx = (hx&0xffff000000000000LL) | (_hx&0x0000ffffffffffffLL);
+ if (iy < LDBL_MIN_EXP) {
+ hx = (hx&0x0000ffffffffffffLL) | (uint64_t)(iy + BIAS + 512)<<48;
+ SET_LDOUBLE_WORDS64(x,hx,lx);
+ x *= 0x1p-512;
+ GET_LDOUBLE_WORDS64(hx,lx,x);
+ } else {
+ hx = (hx&0x0000ffffffffffffLL) | (uint64_t)(iy + BIAS)<<48;
+ }
+ hx &= 0x7fffffffffffffffLL;
+ SET_LDOUBLE_WORDS64(x,hx,lx);
+fixup:
+ y = fabsl(y);
+ if (y < LDBL_MIN * 2) {
+ if (x+x>y || (x+x==y && (q & 1))) {
+ q++;
+ x-=y;
+ }
+ } else if (x>0.5*y || (x==0.5*y && (q & 1))) {
+ q++;
+ x-=y;
+ }
+
+ GET_LDOUBLE_MSW64(hx,x);
+ hx ^= sx;
+ SET_LDOUBLE_MSW64(x,hx);
+
+ q &= 0x7fffffff;
+ *quo = (sxy ? -q : q);
+ return x;
+}
--- /dev/null
+/* @(#)s_tanh.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/*
+ * Copyright (c) 2008 Stephen L. Moshier <steve@moshier.net>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* tanhl(x)
+ * Return the Hyperbolic Tangent of x
+ *
+ * Method :
+ * x -x
+ * e - e
+ * 0. tanhl(x) is defined to be -----------
+ * x -x
+ * e + e
+ * 1. reduce x to non-negative by tanhl(-x) = -tanhl(x).
+ * 2. 0 <= x <= 2**-57 : tanhl(x) := x*(one+x)
+ * -t
+ * 2**-57 < x <= 1 : tanhl(x) := -----; t = expm1l(-2x)
+ * t + 2
+ * 2
+ * 1 <= x <= 40.0 : tanhl(x) := 1- ----- ; t=expm1l(2x)
+ * t + 2
+ * 40.0 < x <= INF : tanhl(x) := 1.
+ *
+ * Special cases:
+ * tanhl(NaN) is NaN;
+ * only tanhl(0)=0 is exact for finite argument.
+ */
+
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+static const long double one = 1.0, two = 2.0, tiny = 1.0e-4900L;
+
+long double
+tanhl(long double x)
+{
+ long double t, z;
+ u_int32_t jx, ix;
+ ieee_quad_shape_type u;
+
+ /* Words of |x|. */
+ u.value = x;
+ jx = u.parts32.mswhi;
+ ix = jx & 0x7fffffff;
+ /* x is INF or NaN */
+ if (ix >= 0x7fff0000)
+ {
+ /* for NaN it's not important which branch: tanhl(NaN) = NaN */
+ if (jx & 0x80000000)
+ return one / x - one; /* tanhl(-inf)= -1; */
+ else
+ return one / x + one; /* tanhl(+inf)=+1 */
+ }
+
+ /* |x| < 40 */
+ if (ix < 0x40044000)
+ {
+ if (u.value == 0)
+ return x; /* x == +- 0 */
+ if (ix < 0x3fc60000) /* |x| < 2^-57 */
+ return x * (one + tiny); /* tanh(small) = small */
+ u.parts32.mswhi = ix; /* Absolute value of x. */
+ if (ix >= 0x3fff0000)
+ { /* |x| >= 1 */
+ t = expm1l (two * u.value);
+ z = one - two / (t + two);
+ }
+ else
+ {
+ t = expm1l (-two * u.value);
+ z = -t / (t + two);
+ }
+ /* |x| > 40, return +-1 */
+ }
+ else
+ {
+ z = one - tiny; /* raised inexact flag */
+ }
+ return (jx & 0x80000000) ? -z : z;
+}
--- /dev/null
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ *
+ * From: @(#)s_floor.c 5.1 93/09/24
+ */
+
+/*
+ * truncl(x)
+ * Return x rounded toward 0 to integral value
+ * Method:
+ * Bit twiddling.
+ * Exception:
+ * Inexact flag raised if x not equal to truncl(x).
+ */
+
+#include <sys/types.h>
+#include <machine/ieee.h>
+
+#include <float.h>
+#include <openlibm_math.h>
+#include <stdint.h>
+
+#include "math_private.h"
+
+#ifdef LDBL_IMPLICIT_NBIT
+#define MANH_SIZE (EXT_FRACHBITS + EXT_FRACHMBITS + 1)
+#else
+#define MANH_SIZE (EXT_FRACHBITS + EXT_FRACHMBITS)
+#endif
+
+static const long double huge = 1.0e300;
+static const float zero[] = { 0.0, -0.0 };
+
+long double
+truncl(long double x)
+{
+ int e;
+ int64_t ix0, ix1;
+
+ GET_LDOUBLE_WORDS64(ix0,ix1,x);
+ e = ((ix0>>48)&0x7fff) - LDBL_MAX_EXP + 1;
+
+ if (e < MANH_SIZE - 1) {
+ if (e < 0) { /* raise inexact if x != 0 */
+ if (huge + x > 0.0)
+ return (zero[((ix0>>48)&0x8000)!=0]);
+ } else {
+ uint64_t m = ((1llu << MANH_SIZE) - 1) >> (e + 1);
+ if (((ix0 & m) | ix1) == 0)
+ return (x); /* x is integral */
+ if (huge + x > 0.0) { /* raise inexact flag */
+ ix0 &= ~m;
+ ix1 = 0;
+ }
+ }
+ } else if (e < LDBL_MANT_DIG - 1) {
+ uint64_t m = (uint64_t)-1 >> (64 - LDBL_MANT_DIG + e + 1);
+ if ((ix1 & m) == 0)
+ return (x); /* x is integral */
+ if (huge + x > 0.0) /* raise inexact flag */
+ ix1 &= ~m;
+ }
+ SET_LDOUBLE_WORDS64(x,ix0,ix1);
+ return (x);
+}
--- /dev/null
+$(CUR_SRCS) += invtrig.c \
+ e_acoshl.c e_powl.c k_tanl.c s_exp2l.c \
+ e_atanhl.c e_lgammal_r.c e_sinhl.c s_asinhl.c s_expm1l.c \
+ e_coshl.c e_log10l.c e_tgammal.c \
+ e_expl.c e_log2l.c k_cosl.c s_log1pl.c s_tanhl.c \
+ e_logl.c k_sinl.c s_erfl.c
+
+# s_remquol.c e_fmodl.c s_truncl.c
+# e_hypotl.c s_floorl.c s_nextafterl.c s_ceill.c s_modfl.c
+
+ifneq ($(OS), WINNT)
+$(CUR_SRCS) += s_nanl.c
+endif
--- /dev/null
+/* @(#)e_acosh.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/* acoshl(x)
+ * Method :
+ * Based on
+ * acoshl(x) = logl [ x + sqrtl(x*x-1) ]
+ * we have
+ * acoshl(x) := logl(x)+ln2, if x is large; else
+ * acoshl(x) := logl(2x-1/(sqrtl(x*x-1)+x)) if x>2; else
+ * acoshl(x) := log1pl(t+sqrtl(2.0*t+t*t)); where t=x-1.
+ *
+ * Special cases:
+ * acoshl(x) is NaN with signal if x<1.
+ * acoshl(NaN) is NaN without signal.
+ */
+
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+static const long double
+one = 1.0,
+ln2 = 6.931471805599453094287e-01L; /* 0x3FFE, 0xB17217F7, 0xD1CF79AC */
+
+long double
+acoshl(long double x)
+{
+ long double t;
+ u_int32_t se,i0,i1;
+ GET_LDOUBLE_WORDS(se,i0,i1,x);
+ if(se<0x3fff || se & 0x8000) { /* x < 1 */
+ return (x-x)/(x-x);
+ } else if(se >=0x401d) { /* x > 2**30 */
+ if(se >=0x7fff) { /* x is inf of NaN */
+ return x+x;
+ } else
+ return logl(x)+ln2; /* acoshl(huge)=logl(2x) */
+ } else if(((se-0x3fff)|i0|i1)==0) {
+ return 0.0; /* acosh(1) = 0 */
+ } else if (se > 0x4000) { /* 2**28 > x > 2 */
+ t=x*x;
+ return logl(2.0*x-one/(x+sqrtl(t-one)));
+ } else { /* 1<x<2 */
+ t = x-one;
+ return log1pl(t+sqrtl(2.0*t+t*t));
+ }
+}
--- /dev/null
+/* @(#)e_atanh.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/* atanhl(x)
+ * Method :
+ * 1.Reduced x to positive by atanh(-x) = -atanh(x)
+ * 2.For x>=0.5
+ * 1 2x x
+ * atanhl(x) = --- * log(1 + -------) = 0.5 * log1p(2 * --------)
+ * 2 1 - x 1 - x
+ *
+ * For x<0.5
+ * atanhl(x) = 0.5*log1pl(2x+2x*x/(1-x))
+ *
+ * Special cases:
+ * atanhl(x) is NaN if |x| > 1 with signal;
+ * atanhl(NaN) is that NaN with no signal;
+ * atanhl(+-1) is +-INF with signal.
+ *
+ */
+
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+static const long double one = 1.0, huge = 1e4900L;
+
+static const long double zero = 0.0;
+
+long double
+atanhl(long double x)
+{
+ long double t;
+ int32_t ix;
+ u_int32_t se,i0,i1;
+ GET_LDOUBLE_WORDS(se,i0,i1,x);
+ ix = se&0x7fff;
+ if ((ix+((((i0&0x7fffffff)|i1)|(-((i0&0x7fffffff)|i1)))>>31))>0x3fff)
+ /* |x|>1 */
+ return (x-x)/(x-x);
+ if(ix==0x3fff)
+ return x/zero;
+ if(ix<0x3fe3&&(huge+x)>zero) return x; /* x<2**-28 */
+ SET_LDOUBLE_EXP(x,ix);
+ if(ix<0x3ffe) { /* x < 0.5 */
+ t = x+x;
+ t = 0.5*log1pl(t+t*x/(one-x));
+ } else
+ t = 0.5*log1pl((x+x)/(one-x));
+ if(se<=0x7fff) return t; else return -t;
+}
--- /dev/null
+/* @(#)e_cosh.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/* coshl(x)
+ * Method :
+ * mathematically coshl(x) if defined to be (exp(x)+exp(-x))/2
+ * 1. Replace x by |x| (coshl(x) = coshl(-x)).
+ * 2.
+ * [ exp(x) - 1 ]^2
+ * 0 <= x <= ln2/2 : coshl(x) := 1 + -------------------
+ * 2*exp(x)
+ *
+ * exp(x) + 1/exp(x)
+ * ln2/2 <= x <= 22 : coshl(x) := -------------------
+ * 2
+ * 22 <= x <= lnovft : coshl(x) := expl(x)/2
+ * lnovft <= x <= ln2ovft: coshl(x) := expl(x/2)/2 * expl(x/2)
+ * ln2ovft < x : coshl(x) := huge*huge (overflow)
+ *
+ * Special cases:
+ * coshl(x) is |x| if x is +INF, -INF, or NaN.
+ * only coshl(0)=1 is exact for finite x.
+ */
+
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+static const long double one = 1.0, half=0.5, huge = 1.0e4900L;
+
+long double
+coshl(long double x)
+{
+ long double t,w;
+ int32_t ex;
+ u_int32_t mx,lx;
+
+ /* High word of |x|. */
+ GET_LDOUBLE_WORDS(ex,mx,lx,x);
+ ex &= 0x7fff;
+
+ /* x is INF or NaN */
+ if(ex==0x7fff) return x*x;
+
+ /* |x| in [0,0.5*ln2], return 1+expm1l(|x|)^2/(2*expl(|x|)) */
+ if(ex < 0x3ffd || (ex == 0x3ffd && mx < 0xb17217f7u)) {
+ t = expm1l(fabsl(x));
+ w = one+t;
+ if (ex<0x3fbc) return w; /* cosh(tiny) = 1 */
+ return one+(t*t)/(w+w);
+ }
+
+ /* |x| in [0.5*ln2,22], return (exp(|x|)+1/exp(|x|)/2; */
+ if (ex < 0x4003 || (ex == 0x4003 && mx < 0xb0000000u)) {
+ t = expl(fabsl(x));
+ return half*t+half/t;
+ }
+
+ /* |x| in [22, ln(maxdouble)] return half*exp(|x|) */
+ if (ex < 0x400c || (ex == 0x400c && mx < 0xb1700000u))
+ return half*expl(fabsl(x));
+
+ /* |x| in [log(maxdouble), log(2*maxdouble)) */
+ if (ex == 0x400c && (mx < 0xb174ddc0u
+ || (mx == 0xb174ddc0u && lx < 0x31aec0ebu)))
+ {
+ w = expl(half*fabsl(x));
+ t = half*w;
+ return t*w;
+ }
+
+ /* |x| >= log(2*maxdouble), cosh(x) overflow */
+ return huge*huge;
+}
--- /dev/null
+/* $OpenBSD: e_expl.c,v 1.3 2013/11/12 20:35:19 martynas Exp $ */
+
+/*
+ * Copyright (c) 2008 Stephen L. Moshier <steve@moshier.net>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* expl.c
+ *
+ * Exponential function, long double precision
+ *
+ *
+ *
+ * SYNOPSIS:
+ *
+ * long double x, y, expl();
+ *
+ * y = expl( x );
+ *
+ *
+ *
+ * DESCRIPTION:
+ *
+ * Returns e (2.71828...) raised to the x power.
+ *
+ * Range reduction is accomplished by separating the argument
+ * into an integer k and fraction f such that
+ *
+ * x k f
+ * e = 2 e.
+ *
+ * A Pade' form of degree 2/3 is used to approximate exp(f) - 1
+ * in the basic range [-0.5 ln 2, 0.5 ln 2].
+ *
+ *
+ * ACCURACY:
+ *
+ * Relative error:
+ * arithmetic domain # trials peak rms
+ * IEEE +-10000 50000 1.12e-19 2.81e-20
+ *
+ *
+ * Error amplification in the exponential function can be
+ * a serious matter. The error propagation involves
+ * exp( X(1+delta) ) = exp(X) ( 1 + X*delta + ... ),
+ * which shows that a 1 lsb error in representing X produces
+ * a relative error of X times 1 lsb in the function.
+ * While the routine gives an accurate result for arguments
+ * that are exactly represented by a long double precision
+ * computer number, the result contains amplified roundoff
+ * error for large arguments not exactly represented.
+ *
+ *
+ * ERROR MESSAGES:
+ *
+ * message condition value returned
+ * exp underflow x < MINLOG 0.0
+ * exp overflow x > MAXLOG MAXNUM
+ *
+ */
+
+/* Exponential function */
+
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+static long double P[3] = {
+ 1.2617719307481059087798E-4L,
+ 3.0299440770744196129956E-2L,
+ 9.9999999999999999991025E-1L,
+};
+static long double Q[4] = {
+ 3.0019850513866445504159E-6L,
+ 2.5244834034968410419224E-3L,
+ 2.2726554820815502876593E-1L,
+ 2.0000000000000000000897E0L,
+};
+static const long double C1 = 6.9314575195312500000000E-1L;
+static const long double C2 = 1.4286068203094172321215E-6L;
+static const long double MAXLOGL = 1.1356523406294143949492E4L;
+static const long double MINLOGL = -1.13994985314888605586758E4L;
+static const long double LOG2EL = 1.4426950408889634073599E0L;
+
+long double
+expl(long double x)
+{
+long double px, xx;
+int n;
+
+if( isnan(x) )
+ return(x);
+if( x > MAXLOGL)
+ return( INFINITY );
+
+if( x < MINLOGL )
+ return(0.0L);
+
+/* Express e**x = e**g 2**n
+ * = e**g e**( n loge(2) )
+ * = e**( g + n loge(2) )
+ */
+px = floorl( LOG2EL * x + 0.5L ); /* floor() truncates toward -infinity. */
+n = px;
+x -= px * C1;
+x -= px * C2;
+
+
+/* rational approximation for exponential
+ * of the fractional part:
+ * e**x = 1 + 2x P(x**2)/( Q(x**2) - P(x**2) )
+ */
+xx = x * x;
+px = x * __polevll( xx, P, 2 );
+x = px/( __polevll( xx, Q, 3 ) - px );
+x = 1.0L + ldexpl( x, 1 );
+
+x = ldexpl( x, n );
+return(x);
+}
--- /dev/null
+/* @(#)e_fmod.c 1.3 95/01/18 */
+/*-
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunSoft, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include <sys/types.h>
+//#include <machine/ieee.h>
+
+#include <float.h>
+#include <openlibm_math.h>
+#include <stdint.h>
+
+#include "math_private.h"
+
+#define BIAS (LDBL_MAX_EXP - 1)
+
+/*
+ * These macros add and remove an explicit integer bit in front of the
+ * fractional mantissa, if the architecture doesn't have such a bit by
+ * default already.
+ */
+#ifdef LDBL_IMPLICIT_NBIT
+#define LDBL_NBIT 0
+#define SET_NBIT(hx) ((hx) | (1ULL << LDBL_MANH_SIZE))
+#define HFRAC_BITS EXT_FRACHBITS
+#else
+#define LDBL_NBIT 0x80000000
+#define SET_NBIT(hx) (hx)
+#define HFRAC_BITS (EXT_FRACHBITS - 1)
+#endif
+
+#define MANL_SHIFT (EXT_FRACLBITS - 1)
+
+static const long double one = 1.0, Zero[] = {0.0, -0.0,};
+
+/*
+ * fmodl(x,y)
+ * Return x mod y in exact arithmetic
+ * Method: shift and subtract
+ *
+ * Assumptions:
+ * - The low part of the mantissa fits in a manl_t exactly.
+ * - The high part of the mantissa fits in an int64_t with enough room
+ * for an explicit integer bit in front of the fractional bits.
+ */
+long double
+fmodl(long double x, long double y)
+{
+ union {
+ long double e;
+ struct ieee_ext bits;
+ } ux, uy;
+ int64_t hx,hz; /* We need a carry bit even if LDBL_MANH_SIZE is 32. */
+ uint32_t hy;
+ uint32_t lx,ly,lz;
+ int ix,iy,n,sx;
+
+ ux.e = x;
+ uy.e = y;
+ sx = ux.bits.ext_sign;
+
+ /* purge off exception values */
+ if((uy.bits.ext_exp|uy.bits.ext_frach|uy.bits.ext_fracl)==0 || /* y=0 */
+ (ux.bits.ext_exp == BIAS + LDBL_MAX_EXP) || /* or x not finite */
+ (uy.bits.ext_exp == BIAS + LDBL_MAX_EXP &&
+ ((uy.bits.ext_frach&~LDBL_NBIT)|uy.bits.ext_fracl)!=0)) /* or y is NaN */
+ return (x*y)/(x*y);
+ if(ux.bits.ext_exp<=uy.bits.ext_exp) {
+ if((ux.bits.ext_exp<uy.bits.ext_exp) ||
+ (ux.bits.ext_frach<=uy.bits.ext_frach &&
+ (ux.bits.ext_frach<uy.bits.ext_frach ||
+ ux.bits.ext_fracl<uy.bits.ext_fracl))) {
+ return x; /* |x|<|y| return x or x-y */
+ }
+ if(ux.bits.ext_frach==uy.bits.ext_frach &&
+ ux.bits.ext_fracl==uy.bits.ext_fracl) {
+ return Zero[sx]; /* |x|=|y| return x*0*/
+ }
+ }
+
+ /* determine ix = ilogb(x) */
+ if(ux.bits.ext_exp == 0) { /* subnormal x */
+ ux.e *= 0x1.0p512;
+ ix = ux.bits.ext_exp - (BIAS + 512);
+ } else {
+ ix = ux.bits.ext_exp - BIAS;
+ }
+
+ /* determine iy = ilogb(y) */
+ if(uy.bits.ext_exp == 0) { /* subnormal y */
+ uy.e *= 0x1.0p512;
+ iy = uy.bits.ext_exp - (BIAS + 512);
+ } else {
+ iy = uy.bits.ext_exp - BIAS;
+ }
+
+ /* set up {hx,lx}, {hy,ly} and align y to x */
+ hx = SET_NBIT(ux.bits.ext_frach);
+ hy = SET_NBIT(uy.bits.ext_frach);
+ lx = ux.bits.ext_fracl;
+ ly = uy.bits.ext_fracl;
+
+ /* fix point fmod */
+ n = ix - iy;
+
+ while(n--) {
+ hz=hx-hy;lz=lx-ly; if(lx<ly) hz -= 1;
+ if(hz<0){hx = hx+hx+(lx>>MANL_SHIFT); lx = lx+lx;}
+ else {
+ if ((hz|lz)==0) /* return sign(x)*0 */
+ return Zero[sx];
+ hx = hz+hz+(lz>>MANL_SHIFT); lx = lz+lz;
+ }
+ }
+ hz=hx-hy;lz=lx-ly; if(lx<ly) hz -= 1;
+ if(hz>=0) {hx=hz;lx=lz;}
+
+ /* convert back to floating value and restore the sign */
+ if((hx|lx)==0) /* return sign(x)*0 */
+ return Zero[sx];
+ while(hx<(1ULL<<HFRAC_BITS)) { /* normalize x */
+ hx = hx+hx+(lx>>MANL_SHIFT); lx = lx+lx;
+ iy -= 1;
+ }
+ ux.bits.ext_frach = hx; /* The mantissa is truncated here if needed. */
+ ux.bits.ext_fracl = lx;
+ if (iy < LDBL_MIN_EXP) {
+ ux.bits.ext_exp = iy + (BIAS + 512);
+ ux.e *= 0x1p-512;
+ } else {
+ ux.bits.ext_exp = iy + BIAS;
+ }
+ x = ux.e * one; /* create necessary signal */
+ return x; /* exact output */
+}
--- /dev/null
+/* @(#)e_hypot.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/* hypotl(x,y)
+ *
+ * Method :
+ * If (assume round-to-nearest) z=x*x+y*y
+ * has error less than sqrt(2)/2 ulp, than
+ * sqrt(z) has error less than 1 ulp (exercise).
+ *
+ * So, compute sqrt(x*x+y*y) with some care as
+ * follows to get the error below 1 ulp:
+ *
+ * Assume x>y>0;
+ * (if possible, set rounding to round-to-nearest)
+ * 1. if x > 2y use
+ * x1*x1+(y*y+(x2*(x+x1))) for x*x+y*y
+ * where x1 = x with lower 32 bits cleared, x2 = x-x1; else
+ * 2. if x <= 2y use
+ * t1*yy1+((x-y)*(x-y)+(t1*y2+t2*y))
+ * where t1 = 2x with lower 32 bits cleared, t2 = 2x-t1,
+ * yy1= y with lower 32 bits chopped, y2 = y-yy1.
+ *
+ * NOTE: scaling may be necessary if some argument is too
+ * large or too tiny
+ *
+ * Special cases:
+ * hypot(x,y) is INF if x or y is +INF or -INF; else
+ * hypot(x,y) is NAN if x or y is NAN.
+ *
+ * Accuracy:
+ * hypot(x,y) returns sqrt(x^2+y^2) with error less
+ * than 1 ulps (units in the last place)
+ */
+
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+long double
+hypotl(long double x, long double y)
+{
+ long double a,b,t1,t2,yy1,y2,w;
+ u_int32_t j,k,ea,eb;
+
+ GET_LDOUBLE_EXP(ea,x);
+ ea &= 0x7fff;
+ GET_LDOUBLE_EXP(eb,y);
+ eb &= 0x7fff;
+ if(eb > ea) {a=y;b=x;j=ea; ea=eb;eb=j;} else {a=x;b=y;}
+ SET_LDOUBLE_EXP(a,ea); /* a <- |a| */
+ SET_LDOUBLE_EXP(b,eb); /* b <- |b| */
+ if((ea-eb)>0x46) {return a+b;} /* x/y > 2**70 */
+ k=0;
+ if(ea > 0x5f3f) { /* a>2**8000 */
+ if(ea == 0x7fff) { /* Inf or NaN */
+ u_int32_t es,high,low;
+ w = a+b; /* for sNaN */
+ GET_LDOUBLE_WORDS(es,high,low,a);
+ if(((high&0x7fffffff)|low)==0) w = a;
+ GET_LDOUBLE_WORDS(es,high,low,b);
+ if(((eb^0x7fff)|(high&0x7fffffff)|low)==0) w = b;
+ return w;
+ }
+ /* scale a and b by 2**-9600 */
+ ea -= 0x2580; eb -= 0x2580; k += 9600;
+ SET_LDOUBLE_EXP(a,ea);
+ SET_LDOUBLE_EXP(b,eb);
+ }
+ if(eb < 0x20bf) { /* b < 2**-8000 */
+ if(eb == 0) { /* subnormal b or 0 */
+ u_int32_t es,high,low;
+ GET_LDOUBLE_WORDS(es,high,low,b);
+ if((high|low)==0) return a;
+ SET_LDOUBLE_WORDS(t1, 0x7ffd, 0, 0); /* t1=2^16382 */
+ b *= t1;
+ a *= t1;
+ k -= 16382;
+ } else { /* scale a and b by 2^9600 */
+ ea += 0x2580; /* a *= 2^9600 */
+ eb += 0x2580; /* b *= 2^9600 */
+ k -= 9600;
+ SET_LDOUBLE_EXP(a,ea);
+ SET_LDOUBLE_EXP(b,eb);
+ }
+ }
+ /* medium size a and b */
+ w = a-b;
+ if (w>b) {
+ u_int32_t high;
+ GET_LDOUBLE_MSW(high,a);
+ SET_LDOUBLE_WORDS(t1,ea,high,0);
+ t2 = a-t1;
+ w = sqrtl(t1*t1-(b*(-b)-t2*(a+t1)));
+ } else {
+ u_int32_t high;
+ GET_LDOUBLE_MSW(high,b);
+ a = a+a;
+ SET_LDOUBLE_WORDS(yy1,eb,high,0);
+ y2 = b - yy1;
+ GET_LDOUBLE_MSW(high,a);
+ SET_LDOUBLE_WORDS(t1,ea+1,high,0);
+ t2 = a - t1;
+ w = sqrtl(t1*yy1-(w*(-w)-(t1*y2+t2*b)));
+ }
+ if(k!=0) {
+ u_int32_t es;
+ t1 = 1.0;
+ GET_LDOUBLE_EXP(es,t1);
+ SET_LDOUBLE_EXP(t1,es+k);
+ return t1*w;
+ } else return w;
+}
--- /dev/null
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/*
+ * Copyright (c) 2008 Stephen L. Moshier <steve@moshier.net>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* lgammal_r(x, signgamp)
+ * Reentrant version of the logarithm of the Gamma function
+ * with user provide pointer for the sign of Gamma(x).
+ *
+ * Method:
+ * 1. Argument Reduction for 0 < x <= 8
+ * Since gamma(1+s)=s*gamma(s), for x in [0,8], we may
+ * reduce x to a number in [1.5,2.5] by
+ * lgamma(1+s) = log(s) + lgamma(s)
+ * for example,
+ * lgamma(7.3) = log(6.3) + lgamma(6.3)
+ * = log(6.3*5.3) + lgamma(5.3)
+ * = log(6.3*5.3*4.3*3.3*2.3) + lgamma(2.3)
+ * 2. Polynomial approximation of lgamma around its
+ * minimun ymin=1.461632144968362245 to maintain monotonicity.
+ * On [ymin-0.23, ymin+0.27] (i.e., [1.23164,1.73163]), use
+ * Let z = x-ymin;
+ * lgamma(x) = -1.214862905358496078218 + z^2*poly(z)
+ * 2. Rational approximation in the primary interval [2,3]
+ * We use the following approximation:
+ * s = x-2.0;
+ * lgamma(x) = 0.5*s + s*P(s)/Q(s)
+ * Our algorithms are based on the following observation
+ *
+ * zeta(2)-1 2 zeta(3)-1 3
+ * lgamma(2+s) = s*(1-Euler) + --------- * s - --------- * s + ...
+ * 2 3
+ *
+ * where Euler = 0.5771... is the Euler constant, which is very
+ * close to 0.5.
+ *
+ * 3. For x>=8, we have
+ * lgamma(x)~(x-0.5)log(x)-x+0.5*log(2pi)+1/(12x)-1/(360x**3)+....
+ * (better formula:
+ * lgamma(x)~(x-0.5)*(log(x)-1)-.5*(log(2pi)-1) + ...)
+ * Let z = 1/x, then we approximation
+ * f(z) = lgamma(x) - (x-0.5)(log(x)-1)
+ * by
+ * 3 5 11
+ * w = w0 + w1*z + w2*z + w3*z + ... + w6*z
+ *
+ * 4. For negative x, since (G is gamma function)
+ * -x*G(-x)*G(x) = pi/sin(pi*x),
+ * we have
+ * G(x) = pi/(sin(pi*x)*(-x)*G(-x))
+ * since G(-x) is positive, sign(G(x)) = sign(sin(pi*x)) for x<0
+ * Hence, for x<0, signgam = sign(sin(pi*x)) and
+ * lgamma(x) = log(|Gamma(x)|)
+ * = log(pi/(|x*sin(pi*x)|)) - lgamma(-x);
+ * Note: one should avoid compute pi*(-x) directly in the
+ * computation of sin(pi*(-x)).
+ *
+ * 5. Special Cases
+ * lgamma(2+s) ~ s*(1-Euler) for tiny s
+ * lgamma(1)=lgamma(2)=0
+ * lgamma(x) ~ -log(x) for tiny x
+ * lgamma(0) = lgamma(inf) = inf
+ * lgamma(-integer) = +-inf
+ *
+ */
+
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+static const long double
+ half = 0.5L,
+ one = 1.0L,
+ pi = 3.14159265358979323846264L,
+ two63 = 9.223372036854775808e18L,
+
+ /* lgam(1+x) = 0.5 x + x a(x)/b(x)
+ -0.268402099609375 <= x <= 0
+ peak relative error 6.6e-22 */
+ a0 = -6.343246574721079391729402781192128239938E2L,
+ a1 = 1.856560238672465796768677717168371401378E3L,
+ a2 = 2.404733102163746263689288466865843408429E3L,
+ a3 = 8.804188795790383497379532868917517596322E2L,
+ a4 = 1.135361354097447729740103745999661157426E2L,
+ a5 = 3.766956539107615557608581581190400021285E0L,
+
+ b0 = 8.214973713960928795704317259806842490498E3L,
+ b1 = 1.026343508841367384879065363925870888012E4L,
+ b2 = 4.553337477045763320522762343132210919277E3L,
+ b3 = 8.506975785032585797446253359230031874803E2L,
+ b4 = 6.042447899703295436820744186992189445813E1L,
+ /* b5 = 1.000000000000000000000000000000000000000E0 */
+
+
+ tc = 1.4616321449683623412626595423257213284682E0L,
+ tf = -1.2148629053584961146050602565082954242826E-1,/* double precision */
+/* tt = (tail of tf), i.e. tf + tt has extended precision. */
+ tt = 3.3649914684731379602768989080467587736363E-18L,
+ /* lgam ( 1.4616321449683623412626595423257213284682E0 ) =
+-1.2148629053584960809551455717769158215135617312999903886372437313313530E-1 */
+
+ /* lgam (x + tc) = tf + tt + x g(x)/h(x)
+ - 0.230003726999612341262659542325721328468 <= x
+ <= 0.2699962730003876587373404576742786715318
+ peak relative error 2.1e-21 */
+ g0 = 3.645529916721223331888305293534095553827E-18L,
+ g1 = 5.126654642791082497002594216163574795690E3L,
+ g2 = 8.828603575854624811911631336122070070327E3L,
+ g3 = 5.464186426932117031234820886525701595203E3L,
+ g4 = 1.455427403530884193180776558102868592293E3L,
+ g5 = 1.541735456969245924860307497029155838446E2L,
+ g6 = 4.335498275274822298341872707453445815118E0L,
+
+ h0 = 1.059584930106085509696730443974495979641E4L,
+ h1 = 2.147921653490043010629481226937850618860E4L,
+ h2 = 1.643014770044524804175197151958100656728E4L,
+ h3 = 5.869021995186925517228323497501767586078E3L,
+ h4 = 9.764244777714344488787381271643502742293E2L,
+ h5 = 6.442485441570592541741092969581997002349E1L,
+ /* h6 = 1.000000000000000000000000000000000000000E0 */
+
+
+ /* lgam (x+1) = -0.5 x + x u(x)/v(x)
+ -0.100006103515625 <= x <= 0.231639862060546875
+ peak relative error 1.3e-21 */
+ u0 = -8.886217500092090678492242071879342025627E1L,
+ u1 = 6.840109978129177639438792958320783599310E2L,
+ u2 = 2.042626104514127267855588786511809932433E3L,
+ u3 = 1.911723903442667422201651063009856064275E3L,
+ u4 = 7.447065275665887457628865263491667767695E2L,
+ u5 = 1.132256494121790736268471016493103952637E2L,
+ u6 = 4.484398885516614191003094714505960972894E0L,
+
+ v0 = 1.150830924194461522996462401210374632929E3L,
+ v1 = 3.399692260848747447377972081399737098610E3L,
+ v2 = 3.786631705644460255229513563657226008015E3L,
+ v3 = 1.966450123004478374557778781564114347876E3L,
+ v4 = 4.741359068914069299837355438370682773122E2L,
+ v5 = 4.508989649747184050907206782117647852364E1L,
+ /* v6 = 1.000000000000000000000000000000000000000E0 */
+
+
+ /* lgam (x+2) = .5 x + x s(x)/r(x)
+ 0 <= x <= 1
+ peak relative error 7.2e-22 */
+ s0 = 1.454726263410661942989109455292824853344E6L,
+ s1 = -3.901428390086348447890408306153378922752E6L,
+ s2 = -6.573568698209374121847873064292963089438E6L,
+ s3 = -3.319055881485044417245964508099095984643E6L,
+ s4 = -7.094891568758439227560184618114707107977E5L,
+ s5 = -6.263426646464505837422314539808112478303E4L,
+ s6 = -1.684926520999477529949915657519454051529E3L,
+
+ r0 = -1.883978160734303518163008696712983134698E7L,
+ r1 = -2.815206082812062064902202753264922306830E7L,
+ r2 = -1.600245495251915899081846093343626358398E7L,
+ r3 = -4.310526301881305003489257052083370058799E6L,
+ r4 = -5.563807682263923279438235987186184968542E5L,
+ r5 = -3.027734654434169996032905158145259713083E4L,
+ r6 = -4.501995652861105629217250715790764371267E2L,
+ /* r6 = 1.000000000000000000000000000000000000000E0 */
+
+
+/* lgam(x) = ( x - 0.5 ) * log(x) - x + LS2PI + 1/x w(1/x^2)
+ x >= 8
+ Peak relative error 1.51e-21
+ w0 = LS2PI - 0.5 */
+ w0 = 4.189385332046727417803e-1L,
+ w1 = 8.333333333333331447505E-2L,
+ w2 = -2.777777777750349603440E-3L,
+ w3 = 7.936507795855070755671E-4L,
+ w4 = -5.952345851765688514613E-4L,
+ w5 = 8.412723297322498080632E-4L,
+ w6 = -1.880801938119376907179E-3L,
+ w7 = 4.885026142432270781165E-3L;
+
+static const long double zero = 0.0L;
+
+static long double
+sin_pi(long double x)
+{
+ long double y, z;
+ int n, ix;
+ u_int32_t se, i0, i1;
+
+ GET_LDOUBLE_WORDS (se, i0, i1, x);
+ ix = se & 0x7fff;
+ ix = (ix << 16) | (i0 >> 16);
+ if (ix < 0x3ffd8000) /* 0.25 */
+ return sinl (pi * x);
+ y = -x; /* x is assume negative */
+
+ /*
+ * argument reduction, make sure inexact flag not raised if input
+ * is an integer
+ */
+ z = floorl (y);
+ if (z != y)
+ { /* inexact anyway */
+ y *= 0.5;
+ y = 2.0*(y - floorl(y)); /* y = |x| mod 2.0 */
+ n = (int) (y*4.0);
+ }
+ else
+ {
+ if (ix >= 0x403f8000) /* 2^64 */
+ {
+ y = zero; n = 0; /* y must be even */
+ }
+ else
+ {
+ if (ix < 0x403e8000) /* 2^63 */
+ z = y + two63; /* exact */
+ GET_LDOUBLE_WORDS (se, i0, i1, z);
+ n = i1 & 1;
+ y = n;
+ n <<= 2;
+ }
+ }
+
+ switch (n)
+ {
+ case 0:
+ y = sinl (pi * y);
+ break;
+ case 1:
+ case 2:
+ y = cosl (pi * (half - y));
+ break;
+ case 3:
+ case 4:
+ y = sinl (pi * (one - y));
+ break;
+ case 5:
+ case 6:
+ y = -cosl (pi * (y - 1.5));
+ break;
+ default:
+ y = sinl (pi * (y - 2.0));
+ break;
+ }
+ return -y;
+}
+
+
+long double
+lgammal_r(long double x, int *signgamp)
+{
+ long double t, y, z, nadj, p, p1, p2, q, r, w;
+ int i, ix;
+ u_int32_t se, i0, i1;
+
+ *signgamp = 1;
+ GET_LDOUBLE_WORDS (se, i0, i1, x);
+ ix = se & 0x7fff;
+
+ if ((ix | i0 | i1) == 0)
+ {
+ if (se & 0x8000)
+ *signgamp = -1;
+ return one / fabsl (x);
+ }
+
+ ix = (ix << 16) | (i0 >> 16);
+
+ /* purge off +-inf, NaN, +-0, and negative arguments */
+ if (ix >= 0x7fff0000)
+ return x * x;
+
+ if (ix < 0x3fc08000) /* 2^-63 */
+ { /* |x|<2**-63, return -log(|x|) */
+ if (se & 0x8000)
+ {
+ *signgamp = -1;
+ return -logl (-x);
+ }
+ else
+ return -logl (x);
+ }
+ if (se & 0x8000)
+ {
+ t = sin_pi (x);
+ if (t == zero)
+ return one / fabsl (t); /* -integer */
+ nadj = logl (pi / fabsl (t * x));
+ if (t < zero)
+ *signgamp = -1;
+ x = -x;
+ }
+
+ /* purge off 1 and 2 */
+ if ((((ix - 0x3fff8000) | i0 | i1) == 0)
+ || (((ix - 0x40008000) | i0 | i1) == 0))
+ r = 0;
+ else if (ix < 0x40008000) /* 2.0 */
+ {
+ /* x < 2.0 */
+ if (ix <= 0x3ffee666) /* 8.99993896484375e-1 */
+ {
+ /* lgamma(x) = lgamma(x+1) - log(x) */
+ r = -logl (x);
+ if (ix >= 0x3ffebb4a) /* 7.31597900390625e-1 */
+ {
+ y = x - one;
+ i = 0;
+ }
+ else if (ix >= 0x3ffced33)/* 2.31639862060546875e-1 */
+ {
+ y = x - (tc - one);
+ i = 1;
+ }
+ else
+ {
+ /* x < 0.23 */
+ y = x;
+ i = 2;
+ }
+ }
+ else
+ {
+ r = zero;
+ if (ix >= 0x3fffdda6) /* 1.73162841796875 */
+ {
+ /* [1.7316,2] */
+ y = x - 2.0;
+ i = 0;
+ }
+ else if (ix >= 0x3fff9da6)/* 1.23162841796875 */
+ {
+ /* [1.23,1.73] */
+ y = x - tc;
+ i = 1;
+ }
+ else
+ {
+ /* [0.9, 1.23] */
+ y = x - one;
+ i = 2;
+ }
+ }
+ switch (i)
+ {
+ case 0:
+ p1 = a0 + y * (a1 + y * (a2 + y * (a3 + y * (a4 + y * a5))));
+ p2 = b0 + y * (b1 + y * (b2 + y * (b3 + y * (b4 + y))));
+ r += half * y + y * p1/p2;
+ break;
+ case 1:
+ p1 = g0 + y * (g1 + y * (g2 + y * (g3 + y * (g4 + y * (g5 + y * g6)))));
+ p2 = h0 + y * (h1 + y * (h2 + y * (h3 + y * (h4 + y * (h5 + y)))));
+ p = tt + y * p1/p2;
+ r += (tf + p);
+ break;
+ case 2:
+ p1 = y * (u0 + y * (u1 + y * (u2 + y * (u3 + y * (u4 + y * (u5 + y * u6))))));
+ p2 = v0 + y * (v1 + y * (v2 + y * (v3 + y * (v4 + y * (v5 + y)))));
+ r += (-half * y + p1 / p2);
+ }
+ }
+ else if (ix < 0x40028000) /* 8.0 */
+ {
+ /* x < 8.0 */
+ i = (int) x;
+ t = zero;
+ y = x - (double) i;
+ p = y *
+ (s0 + y * (s1 + y * (s2 + y * (s3 + y * (s4 + y * (s5 + y * s6))))));
+ q = r0 + y * (r1 + y * (r2 + y * (r3 + y * (r4 + y * (r5 + y * (r6 + y))))));
+ r = half * y + p / q;
+ z = one; /* lgamma(1+s) = log(s) + lgamma(s) */
+ switch (i)
+ {
+ case 7:
+ z *= (y + 6.0); /* FALLTHRU */
+ case 6:
+ z *= (y + 5.0); /* FALLTHRU */
+ case 5:
+ z *= (y + 4.0); /* FALLTHRU */
+ case 4:
+ z *= (y + 3.0); /* FALLTHRU */
+ case 3:
+ z *= (y + 2.0); /* FALLTHRU */
+ r += logl (z);
+ break;
+ }
+ }
+ else if (ix < 0x40418000) /* 2^66 */
+ {
+ /* 8.0 <= x < 2**66 */
+ t = logl (x);
+ z = one / x;
+ y = z * z;
+ w = w0 + z * (w1
+ + y * (w2 + y * (w3 + y * (w4 + y * (w5 + y * (w6 + y * w7))))));
+ r = (x - half) * (t - one) + w;
+ }
+ else
+ /* 2**66 <= x <= inf */
+ r = x * (logl (x) - one);
+ if (se & 0x8000)
+ r = nadj - r;
+ return r;
+}
--- /dev/null
+/* $OpenBSD: e_log10l.c,v 1.2 2013/11/12 20:35:19 martynas Exp $ */
+
+/*
+ * Copyright (c) 2008 Stephen L. Moshier <steve@moshier.net>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* log10l.c
+ *
+ * Common logarithm, long double precision
+ *
+ *
+ *
+ * SYNOPSIS:
+ *
+ * long double x, y, log10l();
+ *
+ * y = log10l( x );
+ *
+ *
+ *
+ * DESCRIPTION:
+ *
+ * Returns the base 10 logarithm of x.
+ *
+ * The argument is separated into its exponent and fractional
+ * parts. If the exponent is between -1 and +1, the logarithm
+ * of the fraction is approximated by
+ *
+ * log(1+x) = x - 0.5 x**2 + x**3 P(x)/Q(x).
+ *
+ * Otherwise, setting z = 2(x-1)/x+1),
+ *
+ * log(x) = z + z**3 P(z)/Q(z).
+ *
+ *
+ *
+ * ACCURACY:
+ *
+ * Relative error:
+ * arithmetic domain # trials peak rms
+ * IEEE 0.5, 2.0 30000 9.0e-20 2.6e-20
+ * IEEE exp(+-10000) 30000 6.0e-20 2.3e-20
+ *
+ * In the tests over the interval exp(+-10000), the logarithms
+ * of the random arguments were uniformly distributed over
+ * [-10000, +10000].
+ *
+ * ERROR MESSAGES:
+ *
+ * log singularity: x = 0; returns MINLOG
+ * log domain: x < 0; returns MINLOG
+ */
+
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+/* Coefficients for log(1+x) = x - x**2/2 + x**3 P(x)/Q(x)
+ * 1/sqrt(2) <= x < sqrt(2)
+ * Theoretical peak relative error = 6.2e-22
+ */
+static long double P[] = {
+ 4.9962495940332550844739E-1L,
+ 1.0767376367209449010438E1L,
+ 7.7671073698359539859595E1L,
+ 2.5620629828144409632571E2L,
+ 4.2401812743503691187826E2L,
+ 3.4258224542413922935104E2L,
+ 1.0747524399916215149070E2L,
+};
+static long double Q[] = {
+/* 1.0000000000000000000000E0,*/
+ 2.3479774160285863271658E1L,
+ 1.9444210022760132894510E2L,
+ 7.7952888181207260646090E2L,
+ 1.6911722418503949084863E3L,
+ 2.0307734695595183428202E3L,
+ 1.2695660352705325274404E3L,
+ 3.2242573199748645407652E2L,
+};
+
+/* Coefficients for log(x) = z + z^3 P(z^2)/Q(z^2),
+ * where z = 2(x-1)/(x+1)
+ * 1/sqrt(2) <= x < sqrt(2)
+ * Theoretical peak relative error = 6.16e-22
+ */
+
+static long double R[4] = {
+ 1.9757429581415468984296E-3L,
+-7.1990767473014147232598E-1L,
+ 1.0777257190312272158094E1L,
+-3.5717684488096787370998E1L,
+};
+static long double S[4] = {
+/* 1.00000000000000000000E0L,*/
+-2.6201045551331104417768E1L,
+ 1.9361891836232102174846E2L,
+-4.2861221385716144629696E2L,
+};
+/* log10(2) */
+#define L102A 0.3125L
+#define L102B -1.1470004336018804786261e-2L
+/* log10(e) */
+#define L10EA 0.5L
+#define L10EB -6.5705518096748172348871e-2L
+
+#define SQRTH 0.70710678118654752440L
+
+long double
+log10l(long double x)
+{
+long double y;
+volatile long double z;
+int e;
+
+if( isnan(x) )
+ return(x);
+/* Test for domain */
+if( x <= 0.0L )
+ {
+ if( x == 0.0L )
+ return (-1.0L / (x - x));
+ else
+ return (x - x) / (x - x);
+ }
+if( x == INFINITY )
+ return(INFINITY);
+/* separate mantissa from exponent */
+
+/* Note, frexp is used so that denormal numbers
+ * will be handled properly.
+ */
+x = frexpl( x, &e );
+
+
+/* logarithm using log(x) = z + z**3 P(z)/Q(z),
+ * where z = 2(x-1)/x+1)
+ */
+if( (e > 2) || (e < -2) )
+{
+if( x < SQRTH )
+ { /* 2( 2x-1 )/( 2x+1 ) */
+ e -= 1;
+ z = x - 0.5L;
+ y = 0.5L * z + 0.5L;
+ }
+else
+ { /* 2 (x-1)/(x+1) */
+ z = x - 0.5L;
+ z -= 0.5L;
+ y = 0.5L * x + 0.5L;
+ }
+x = z / y;
+z = x*x;
+y = x * ( z * __polevll( z, R, 3 ) / __p1evll( z, S, 3 ) );
+goto done;
+}
+
+
+/* logarithm using log(1+x) = x - .5x**2 + x**3 P(x)/Q(x) */
+
+if( x < SQRTH )
+ {
+ e -= 1;
+ x = ldexpl( x, 1 ) - 1.0L; /* 2x - 1 */
+ }
+else
+ {
+ x = x - 1.0L;
+ }
+z = x*x;
+y = x * ( z * __polevll( x, P, 6 ) / __p1evll( x, Q, 7 ) );
+y = y - ldexpl( z, -1 ); /* -0.5x^2 + ... */
+
+done:
+
+/* Multiply log of fraction by log10(e)
+ * and base 2 exponent by log10(2).
+ *
+ * ***CAUTION***
+ *
+ * This sequence of operations is critical and it may
+ * be horribly defeated by some compiler optimizers.
+ */
+z = y * (L10EB);
+z += x * (L10EB);
+z += e * (L102B);
+z += y * (L10EA);
+z += x * (L10EA);
+z += e * (L102A);
+
+return( z );
+}
--- /dev/null
+/* $OpenBSD: e_log2l.c,v 1.2 2013/11/12 20:35:19 martynas Exp $ */
+
+/*
+ * Copyright (c) 2008 Stephen L. Moshier <steve@moshier.net>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* log2l.c
+ *
+ * Base 2 logarithm, long double precision
+ *
+ *
+ *
+ * SYNOPSIS:
+ *
+ * long double x, y, log2l();
+ *
+ * y = log2l( x );
+ *
+ *
+ *
+ * DESCRIPTION:
+ *
+ * Returns the base 2 logarithm of x.
+ *
+ * The argument is separated into its exponent and fractional
+ * parts. If the exponent is between -1 and +1, the (natural)
+ * logarithm of the fraction is approximated by
+ *
+ * log(1+x) = x - 0.5 x**2 + x**3 P(x)/Q(x).
+ *
+ * Otherwise, setting z = 2(x-1)/x+1),
+ *
+ * log(x) = z + z**3 P(z)/Q(z).
+ *
+ *
+ *
+ * ACCURACY:
+ *
+ * Relative error:
+ * arithmetic domain # trials peak rms
+ * IEEE 0.5, 2.0 30000 9.8e-20 2.7e-20
+ * IEEE exp(+-10000) 70000 5.4e-20 2.3e-20
+ *
+ * In the tests over the interval exp(+-10000), the logarithms
+ * of the random arguments were uniformly distributed over
+ * [-10000, +10000].
+ *
+ * ERROR MESSAGES:
+ *
+ * log singularity: x = 0; returns -INFINITY
+ * log domain: x < 0; returns NAN
+ */
+
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+/* Coefficients for ln(1+x) = x - x**2/2 + x**3 P(x)/Q(x)
+ * 1/sqrt(2) <= x < sqrt(2)
+ * Theoretical peak relative error = 6.2e-22
+ */
+static long double P[] = {
+ 4.9962495940332550844739E-1L,
+ 1.0767376367209449010438E1L,
+ 7.7671073698359539859595E1L,
+ 2.5620629828144409632571E2L,
+ 4.2401812743503691187826E2L,
+ 3.4258224542413922935104E2L,
+ 1.0747524399916215149070E2L,
+};
+static long double Q[] = {
+/* 1.0000000000000000000000E0,*/
+ 2.3479774160285863271658E1L,
+ 1.9444210022760132894510E2L,
+ 7.7952888181207260646090E2L,
+ 1.6911722418503949084863E3L,
+ 2.0307734695595183428202E3L,
+ 1.2695660352705325274404E3L,
+ 3.2242573199748645407652E2L,
+};
+
+/* Coefficients for log(x) = z + z^3 P(z^2)/Q(z^2),
+ * where z = 2(x-1)/(x+1)
+ * 1/sqrt(2) <= x < sqrt(2)
+ * Theoretical peak relative error = 6.16e-22
+ */
+static long double R[4] = {
+ 1.9757429581415468984296E-3L,
+-7.1990767473014147232598E-1L,
+ 1.0777257190312272158094E1L,
+-3.5717684488096787370998E1L,
+};
+static long double S[4] = {
+/* 1.00000000000000000000E0L,*/
+-2.6201045551331104417768E1L,
+ 1.9361891836232102174846E2L,
+-4.2861221385716144629696E2L,
+};
+/* log2(e) - 1 */
+#define LOG2EA 4.4269504088896340735992e-1L
+
+#define SQRTH 0.70710678118654752440L
+
+long double
+log2l(long double x)
+{
+volatile long double z;
+long double y;
+int e;
+
+if( isnan(x) )
+ return(x);
+if( x == INFINITY )
+ return(x);
+/* Test for domain */
+if( x <= 0.0L )
+ {
+ if( x == 0.0L )
+ return( -INFINITY );
+ else
+ return( NAN );
+ }
+
+/* separate mantissa from exponent */
+
+/* Note, frexp is used so that denormal numbers
+ * will be handled properly.
+ */
+x = frexpl( x, &e );
+
+
+/* logarithm using log(x) = z + z**3 P(z)/Q(z),
+ * where z = 2(x-1)/x+1)
+ */
+if( (e > 2) || (e < -2) )
+{
+if( x < SQRTH )
+ { /* 2( 2x-1 )/( 2x+1 ) */
+ e -= 1;
+ z = x - 0.5L;
+ y = 0.5L * z + 0.5L;
+ }
+else
+ { /* 2 (x-1)/(x+1) */
+ z = x - 0.5L;
+ z -= 0.5L;
+ y = 0.5L * x + 0.5L;
+ }
+x = z / y;
+z = x*x;
+y = x * ( z * __polevll( z, R, 3 ) / __p1evll( z, S, 3 ) );
+goto done;
+}
+
+
+/* logarithm using log(1+x) = x - .5x**2 + x**3 P(x)/Q(x) */
+
+if( x < SQRTH )
+ {
+ e -= 1;
+ x = ldexpl( x, 1 ) - 1.0L; /* 2x - 1 */
+ }
+else
+ {
+ x = x - 1.0L;
+ }
+z = x*x;
+y = x * ( z * __polevll( x, P, 6 ) / __p1evll( x, Q, 7 ) );
+y = y - ldexpl( z, -1 ); /* -0.5x^2 + ... */
+
+done:
+
+/* Multiply log of fraction by log2(e)
+ * and base 2 exponent by 1
+ *
+ * ***CAUTION***
+ *
+ * This sequence of operations is critical and it may
+ * be horribly defeated by some compiler optimizers.
+ */
+z = y * LOG2EA;
+z += x * LOG2EA;
+z += y;
+z += x;
+z += e;
+return( z );
+}
--- /dev/null
+/* $OpenBSD: e_logl.c,v 1.3 2013/11/12 20:35:19 martynas Exp $ */
+
+/*
+ * Copyright (c) 2008 Stephen L. Moshier <steve@moshier.net>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* logl.c
+ *
+ * Natural logarithm, long double precision
+ *
+ *
+ *
+ * SYNOPSIS:
+ *
+ * long double x, y, logl();
+ *
+ * y = logl( x );
+ *
+ *
+ *
+ * DESCRIPTION:
+ *
+ * Returns the base e (2.718...) logarithm of x.
+ *
+ * The argument is separated into its exponent and fractional
+ * parts. If the exponent is between -1 and +1, the logarithm
+ * of the fraction is approximated by
+ *
+ * log(1+x) = x - 0.5 x**2 + x**3 P(x)/Q(x).
+ *
+ * Otherwise, setting z = 2(x-1)/x+1),
+ *
+ * log(x) = z + z**3 P(z)/Q(z).
+ *
+ *
+ *
+ * ACCURACY:
+ *
+ * Relative error:
+ * arithmetic domain # trials peak rms
+ * IEEE 0.5, 2.0 150000 8.71e-20 2.75e-20
+ * IEEE exp(+-10000) 100000 5.39e-20 2.34e-20
+ *
+ * In the tests over the interval exp(+-10000), the logarithms
+ * of the random arguments were uniformly distributed over
+ * [-10000, +10000].
+ *
+ * ERROR MESSAGES:
+ *
+ * log singularity: x = 0; returns -INFINITY
+ * log domain: x < 0; returns NAN
+ */
+
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+/* Coefficients for log(1+x) = x - x**2/2 + x**3 P(x)/Q(x)
+ * 1/sqrt(2) <= x < sqrt(2)
+ * Theoretical peak relative error = 2.32e-20
+ */
+static long double P[] = {
+ 4.5270000862445199635215E-5L,
+ 4.9854102823193375972212E-1L,
+ 6.5787325942061044846969E0L,
+ 2.9911919328553073277375E1L,
+ 6.0949667980987787057556E1L,
+ 5.7112963590585538103336E1L,
+ 2.0039553499201281259648E1L,
+};
+static long double Q[] = {
+/* 1.0000000000000000000000E0,*/
+ 1.5062909083469192043167E1L,
+ 8.3047565967967209469434E1L,
+ 2.2176239823732856465394E2L,
+ 3.0909872225312059774938E2L,
+ 2.1642788614495947685003E2L,
+ 6.0118660497603843919306E1L,
+};
+
+/* Coefficients for log(x) = z + z^3 P(z^2)/Q(z^2),
+ * where z = 2(x-1)/(x+1)
+ * 1/sqrt(2) <= x < sqrt(2)
+ * Theoretical peak relative error = 6.16e-22
+ */
+
+static long double R[4] = {
+ 1.9757429581415468984296E-3L,
+-7.1990767473014147232598E-1L,
+ 1.0777257190312272158094E1L,
+-3.5717684488096787370998E1L,
+};
+static long double S[4] = {
+/* 1.00000000000000000000E0L,*/
+-2.6201045551331104417768E1L,
+ 1.9361891836232102174846E2L,
+-4.2861221385716144629696E2L,
+};
+static const long double C1 = 6.9314575195312500000000E-1L;
+static const long double C2 = 1.4286068203094172321215E-6L;
+
+#define SQRTH 0.70710678118654752440L
+
+long double
+logl(long double x)
+{
+long double y, z;
+int e;
+
+if( isnan(x) )
+ return(x);
+if( x == INFINITY )
+ return(x);
+/* Test for domain */
+if( x <= 0.0L )
+ {
+ if( x == 0.0L )
+ return( -INFINITY );
+ else
+ return( NAN );
+ }
+
+/* separate mantissa from exponent */
+
+/* Note, frexp is used so that denormal numbers
+ * will be handled properly.
+ */
+x = frexpl( x, &e );
+
+/* logarithm using log(x) = z + z**3 P(z)/Q(z),
+ * where z = 2(x-1)/x+1)
+ */
+if( (e > 2) || (e < -2) )
+{
+if( x < SQRTH )
+ { /* 2( 2x-1 )/( 2x+1 ) */
+ e -= 1;
+ z = x - 0.5L;
+ y = 0.5L * z + 0.5L;
+ }
+else
+ { /* 2 (x-1)/(x+1) */
+ z = x - 0.5L;
+ z -= 0.5L;
+ y = 0.5L * x + 0.5L;
+ }
+x = z / y;
+z = x*x;
+z = x * ( z * __polevll( z, R, 3 ) / __p1evll( z, S, 3 ) );
+z = z + e * C2;
+z = z + x;
+z = z + e * C1;
+return( z );
+}
+
+
+/* logarithm using log(1+x) = x - .5x**2 + x**3 P(x)/Q(x) */
+
+if( x < SQRTH )
+ {
+ e -= 1;
+ x = ldexpl( x, 1 ) - 1.0L; /* 2x - 1 */
+ }
+else
+ {
+ x = x - 1.0L;
+ }
+z = x*x;
+y = x * ( z * __polevll( x, P, 6 ) / __p1evll( x, Q, 6 ) );
+y = y + e * C2;
+z = y - ldexpl( z, -1 ); /* y - 0.5 * z */
+/* Note, the sum of above terms does not exceed x/4,
+ * so it contributes at most about 1/4 lsb to the error.
+ */
+z = z + x;
+z = z + e * C1; /* This sum has an error of 1/2 lsb. */
+return( z );
+}
--- /dev/null
+/* $OpenBSD: e_powl.c,v 1.5 2013/11/12 20:35:19 martynas Exp $ */
+
+/*
+ * Copyright (c) 2008 Stephen L. Moshier <steve@moshier.net>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* powl.c
+ *
+ * Power function, long double precision
+ *
+ *
+ *
+ * SYNOPSIS:
+ *
+ * long double x, y, z, powl();
+ *
+ * z = powl( x, y );
+ *
+ *
+ *
+ * DESCRIPTION:
+ *
+ * Computes x raised to the yth power. Analytically,
+ *
+ * x**y = exp( y log(x) ).
+ *
+ * Following Cody and Waite, this program uses a lookup table
+ * of 2**-i/32 and pseudo extended precision arithmetic to
+ * obtain several extra bits of accuracy in both the logarithm
+ * and the exponential.
+ *
+ *
+ *
+ * ACCURACY:
+ *
+ * The relative error of pow(x,y) can be estimated
+ * by y dl ln(2), where dl is the absolute error of
+ * the internally computed base 2 logarithm. At the ends
+ * of the approximation interval the logarithm equal 1/32
+ * and its relative error is about 1 lsb = 1.1e-19. Hence
+ * the predicted relative error in the result is 2.3e-21 y .
+ *
+ * Relative error:
+ * arithmetic domain # trials peak rms
+ *
+ * IEEE +-1000 40000 2.8e-18 3.7e-19
+ * .001 < x < 1000, with log(x) uniformly distributed.
+ * -1000 < y < 1000, y uniformly distributed.
+ *
+ * IEEE 0,8700 60000 6.5e-18 1.0e-18
+ * 0.99 < x < 1.01, 0 < y < 8700, uniformly distributed.
+ *
+ *
+ * ERROR MESSAGES:
+ *
+ * message condition value returned
+ * pow overflow x**y > MAXNUM INFINITY
+ * pow underflow x**y < 1/MAXNUM 0.0
+ * pow domain x<0 and y noninteger 0.0
+ *
+ */
+
+#include <float.h>
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+/* Table size */
+#define NXT 32
+/* log2(Table size) */
+#define LNXT 5
+
+/* log(1+x) = x - .5x^2 + x^3 * P(z)/Q(z)
+ * on the domain 2^(-1/32) - 1 <= x <= 2^(1/32) - 1
+ */
+static long double P[] = {
+ 8.3319510773868690346226E-4L,
+ 4.9000050881978028599627E-1L,
+ 1.7500123722550302671919E0L,
+ 1.4000100839971580279335E0L,
+};
+static long double Q[] = {
+/* 1.0000000000000000000000E0L,*/
+ 5.2500282295834889175431E0L,
+ 8.4000598057587009834666E0L,
+ 4.2000302519914740834728E0L,
+};
+/* A[i] = 2^(-i/32), rounded to IEEE long double precision.
+ * If i is even, A[i] + B[i/2] gives additional accuracy.
+ */
+static long double A[33] = {
+ 1.0000000000000000000000E0L,
+ 9.7857206208770013448287E-1L,
+ 9.5760328069857364691013E-1L,
+ 9.3708381705514995065011E-1L,
+ 9.1700404320467123175367E-1L,
+ 8.9735453750155359320742E-1L,
+ 8.7812608018664974155474E-1L,
+ 8.5930964906123895780165E-1L,
+ 8.4089641525371454301892E-1L,
+ 8.2287773907698242225554E-1L,
+ 8.0524516597462715409607E-1L,
+ 7.8799042255394324325455E-1L,
+ 7.7110541270397041179298E-1L,
+ 7.5458221379671136985669E-1L,
+ 7.3841307296974965571198E-1L,
+ 7.2259040348852331001267E-1L,
+ 7.0710678118654752438189E-1L,
+ 6.9195494098191597746178E-1L,
+ 6.7712777346844636413344E-1L,
+ 6.6261832157987064729696E-1L,
+ 6.4841977732550483296079E-1L,
+ 6.3452547859586661129850E-1L,
+ 6.2092890603674202431705E-1L,
+ 6.0762367999023443907803E-1L,
+ 5.9460355750136053334378E-1L,
+ 5.8186242938878875689693E-1L,
+ 5.6939431737834582684856E-1L,
+ 5.5719337129794626814472E-1L,
+ 5.4525386633262882960438E-1L,
+ 5.3357020033841180906486E-1L,
+ 5.2213689121370692017331E-1L,
+ 5.1094857432705833910408E-1L,
+ 5.0000000000000000000000E-1L,
+};
+static long double B[17] = {
+ 0.0000000000000000000000E0L,
+ 2.6176170809902549338711E-20L,
+-1.0126791927256478897086E-20L,
+ 1.3438228172316276937655E-21L,
+ 1.2207982955417546912101E-20L,
+-6.3084814358060867200133E-21L,
+ 1.3164426894366316434230E-20L,
+-1.8527916071632873716786E-20L,
+ 1.8950325588932570796551E-20L,
+ 1.5564775779538780478155E-20L,
+ 6.0859793637556860974380E-21L,
+-2.0208749253662532228949E-20L,
+ 1.4966292219224761844552E-20L,
+ 3.3540909728056476875639E-21L,
+-8.6987564101742849540743E-22L,
+-1.2327176863327626135542E-20L,
+ 0.0000000000000000000000E0L,
+};
+
+/* 2^x = 1 + x P(x),
+ * on the interval -1/32 <= x <= 0
+ */
+static long double R[] = {
+ 1.5089970579127659901157E-5L,
+ 1.5402715328927013076125E-4L,
+ 1.3333556028915671091390E-3L,
+ 9.6181291046036762031786E-3L,
+ 5.5504108664798463044015E-2L,
+ 2.4022650695910062854352E-1L,
+ 6.9314718055994530931447E-1L,
+};
+
+#define douba(k) A[k]
+#define doubb(k) B[k]
+#define MEXP (NXT*16384.0L)
+/* The following if denormal numbers are supported, else -MEXP: */
+#define MNEXP (-NXT*(16384.0L+64.0L))
+/* log2(e) - 1 */
+#define LOG2EA 0.44269504088896340735992L
+
+#define F W
+#define Fa Wa
+#define Fb Wb
+#define G W
+#define Ga Wa
+#define Gb u
+#define H W
+#define Ha Wb
+#define Hb Wb
+
+static const long double MAXLOGL = 1.1356523406294143949492E4L;
+static const long double MINLOGL = -1.13994985314888605586758E4L;
+static const long double LOGE2L = 6.9314718055994530941723E-1L;
+static volatile long double z;
+static long double w, W, Wa, Wb, ya, yb, u;
+static const long double huge = 0x1p10000L;
+#if 0 /* XXX Prevent gcc from erroneously constant folding this. */
+static const long double twom10000 = 0x1p-10000L;
+#else
+static volatile long double twom10000 = 0x1p-10000L;
+#endif
+
+static long double reducl( long double );
+static long double powil ( long double, int );
+
+long double
+powl(long double x, long double y)
+{
+/* double F, Fa, Fb, G, Ga, Gb, H, Ha, Hb */
+int i, nflg, iyflg, yoddint;
+long e;
+
+if( y == 0.0L )
+ return( 1.0L );
+
+if( x == 1.0L )
+ return( 1.0L );
+
+if( isnan(x) )
+ return( x );
+if( isnan(y) )
+ return( y );
+
+if( y == 1.0L )
+ return( x );
+
+if( !isfinite(y) && x == -1.0L )
+ return( 1.0L );
+
+if( y >= LDBL_MAX )
+ {
+ if( x > 1.0L )
+ return( INFINITY );
+ if( x > 0.0L && x < 1.0L )
+ return( 0.0L );
+ if( x < -1.0L )
+ return( INFINITY );
+ if( x > -1.0L && x < 0.0L )
+ return( 0.0L );
+ }
+if( y <= -LDBL_MAX )
+ {
+ if( x > 1.0L )
+ return( 0.0L );
+ if( x > 0.0L && x < 1.0L )
+ return( INFINITY );
+ if( x < -1.0L )
+ return( 0.0L );
+ if( x > -1.0L && x < 0.0L )
+ return( INFINITY );
+ }
+if( x >= LDBL_MAX )
+ {
+ if( y > 0.0L )
+ return( INFINITY );
+ return( 0.0L );
+ }
+
+w = floorl(y);
+/* Set iyflg to 1 if y is an integer. */
+iyflg = 0;
+if( w == y )
+ iyflg = 1;
+
+/* Test for odd integer y. */
+yoddint = 0;
+if( iyflg )
+ {
+ ya = fabsl(y);
+ ya = floorl(0.5L * ya);
+ yb = 0.5L * fabsl(w);
+ if( ya != yb )
+ yoddint = 1;
+ }
+
+if( x <= -LDBL_MAX )
+ {
+ if( y > 0.0L )
+ {
+ if( yoddint )
+ return( -INFINITY );
+ return( INFINITY );
+ }
+ if( y < 0.0L )
+ {
+ if( yoddint )
+ return( -0.0L );
+ return( 0.0 );
+ }
+ }
+
+
+nflg = 0; /* flag = 1 if x<0 raised to integer power */
+if( x <= 0.0L )
+ {
+ if( x == 0.0L )
+ {
+ if( y < 0.0 )
+ {
+ if( signbit(x) && yoddint )
+ return( -INFINITY );
+ return( INFINITY );
+ }
+ if( y > 0.0 )
+ {
+ if( signbit(x) && yoddint )
+ return( -0.0L );
+ return( 0.0 );
+ }
+ if( y == 0.0L )
+ return( 1.0L ); /* 0**0 */
+ else
+ return( 0.0L ); /* 0**y */
+ }
+ else
+ {
+ if( iyflg == 0 )
+ return (x - x) / (x - x); /* (x<0)**(non-int) is NaN */
+ nflg = 1;
+ }
+ }
+
+/* Integer power of an integer. */
+
+if( iyflg )
+ {
+ i = w;
+ w = floorl(x);
+ if( (w == x) && (fabsl(y) < 32768.0) )
+ {
+ w = powil( x, (int) y );
+ return( w );
+ }
+ }
+
+
+if( nflg )
+ x = fabsl(x);
+
+/* separate significand from exponent */
+x = frexpl( x, &i );
+e = i;
+
+/* find significand in antilog table A[] */
+i = 1;
+if( x <= douba(17) )
+ i = 17;
+if( x <= douba(i+8) )
+ i += 8;
+if( x <= douba(i+4) )
+ i += 4;
+if( x <= douba(i+2) )
+ i += 2;
+if( x >= douba(1) )
+ i = -1;
+i += 1;
+
+
+/* Find (x - A[i])/A[i]
+ * in order to compute log(x/A[i]):
+ *
+ * log(x) = log( a x/a ) = log(a) + log(x/a)
+ *
+ * log(x/a) = log(1+v), v = x/a - 1 = (x-a)/a
+ */
+x -= douba(i);
+x -= doubb(i/2);
+x /= douba(i);
+
+
+/* rational approximation for log(1+v):
+ *
+ * log(1+v) = v - v**2/2 + v**3 P(v) / Q(v)
+ */
+z = x*x;
+w = x * ( z * __polevll( x, P, 3 ) / __p1evll( x, Q, 3 ) );
+w = w - ldexpl( z, -1 ); /* w - 0.5 * z */
+
+/* Convert to base 2 logarithm:
+ * multiply by log2(e) = 1 + LOG2EA
+ */
+z = LOG2EA * w;
+z += w;
+z += LOG2EA * x;
+z += x;
+
+/* Compute exponent term of the base 2 logarithm. */
+w = -i;
+w = ldexpl( w, -LNXT ); /* divide by NXT */
+w += e;
+/* Now base 2 log of x is w + z. */
+
+/* Multiply base 2 log by y, in extended precision. */
+
+/* separate y into large part ya
+ * and small part yb less than 1/NXT
+ */
+ya = reducl(y);
+yb = y - ya;
+
+/* (w+z)(ya+yb)
+ * = w*ya + w*yb + z*y
+ */
+F = z * y + w * yb;
+Fa = reducl(F);
+Fb = F - Fa;
+
+G = Fa + w * ya;
+Ga = reducl(G);
+Gb = G - Ga;
+
+H = Fb + Gb;
+Ha = reducl(H);
+w = ldexpl( Ga+Ha, LNXT );
+
+/* Test the power of 2 for overflow */
+if( w > MEXP )
+ return (huge * huge); /* overflow */
+
+if( w < MNEXP )
+ return (twom10000 * twom10000); /* underflow */
+
+e = w;
+Hb = H - Ha;
+
+if( Hb > 0.0L )
+ {
+ e += 1;
+ Hb -= (1.0L/NXT); /*0.0625L;*/
+ }
+
+/* Now the product y * log2(x) = Hb + e/NXT.
+ *
+ * Compute base 2 exponential of Hb,
+ * where -0.0625 <= Hb <= 0.
+ */
+z = Hb * __polevll( Hb, R, 6 ); /* z = 2**Hb - 1 */
+
+/* Express e/NXT as an integer plus a negative number of (1/NXT)ths.
+ * Find lookup table entry for the fractional power of 2.
+ */
+if( e < 0 )
+ i = 0;
+else
+ i = 1;
+i = e/NXT + i;
+e = NXT*i - e;
+w = douba( e );
+z = w * z; /* 2**-e * ( 1 + (2**Hb-1) ) */
+z = z + w;
+z = ldexpl( z, i ); /* multiply by integer power of 2 */
+
+if( nflg )
+ {
+/* For negative x,
+ * find out if the integer exponent
+ * is odd or even.
+ */
+ w = ldexpl( y, -1 );
+ w = floorl(w);
+ w = ldexpl( w, 1 );
+ if( w != y )
+ z = -z; /* odd exponent */
+ }
+
+return( z );
+}
+
+
+/* Find a multiple of 1/NXT that is within 1/NXT of x. */
+static long double
+reducl(long double x)
+{
+long double t;
+
+t = ldexpl( x, LNXT );
+t = floorl( t );
+t = ldexpl( t, -LNXT );
+return(t);
+}
+
+/* powil.c
+ *
+ * Real raised to integer power, long double precision
+ *
+ *
+ *
+ * SYNOPSIS:
+ *
+ * long double x, y, powil();
+ * int n;
+ *
+ * y = powil( x, n );
+ *
+ *
+ *
+ * DESCRIPTION:
+ *
+ * Returns argument x raised to the nth power.
+ * The routine efficiently decomposes n as a sum of powers of
+ * two. The desired power is a product of two-to-the-kth
+ * powers of x. Thus to compute the 32767 power of x requires
+ * 28 multiplications instead of 32767 multiplications.
+ *
+ *
+ *
+ * ACCURACY:
+ *
+ *
+ * Relative error:
+ * arithmetic x domain n domain # trials peak rms
+ * IEEE .001,1000 -1022,1023 50000 4.3e-17 7.8e-18
+ * IEEE 1,2 -1022,1023 20000 3.9e-17 7.6e-18
+ * IEEE .99,1.01 0,8700 10000 3.6e-16 7.2e-17
+ *
+ * Returns MAXNUM on overflow, zero on underflow.
+ *
+ */
+
+static long double
+powil(long double x, int nn)
+{
+long double ww, y;
+long double s;
+int n, e, sign, asign, lx;
+
+if( x == 0.0L )
+ {
+ if( nn == 0 )
+ return( 1.0L );
+ else if( nn < 0 )
+ return( LDBL_MAX );
+ else
+ return( 0.0L );
+ }
+
+if( nn == 0 )
+ return( 1.0L );
+
+
+if( x < 0.0L )
+ {
+ asign = -1;
+ x = -x;
+ }
+else
+ asign = 0;
+
+
+if( nn < 0 )
+ {
+ sign = -1;
+ n = -nn;
+ }
+else
+ {
+ sign = 1;
+ n = nn;
+ }
+
+/* Overflow detection */
+
+/* Calculate approximate logarithm of answer */
+s = x;
+s = frexpl( s, &lx );
+e = (lx - 1)*n;
+if( (e == 0) || (e > 64) || (e < -64) )
+ {
+ s = (s - 7.0710678118654752e-1L) / (s + 7.0710678118654752e-1L);
+ s = (2.9142135623730950L * s - 0.5L + lx) * nn * LOGE2L;
+ }
+else
+ {
+ s = LOGE2L * e;
+ }
+
+if( s > MAXLOGL )
+ return (huge * huge); /* overflow */
+
+if( s < MINLOGL )
+ return (twom10000 * twom10000); /* underflow */
+/* Handle tiny denormal answer, but with less accuracy
+ * since roundoff error in 1.0/x will be amplified.
+ * The precise demarcation should be the gradual underflow threshold.
+ */
+if( s < (-MAXLOGL+2.0L) )
+ {
+ x = 1.0L/x;
+ sign = -sign;
+ }
+
+/* First bit of the power */
+if( n & 1 )
+ y = x;
+
+else
+ {
+ y = 1.0L;
+ asign = 0;
+ }
+
+ww = x;
+n >>= 1;
+while( n )
+ {
+ ww = ww * ww; /* arg to the 2-to-the-kth power */
+ if( n & 1 ) /* if that bit is set, then include in product */
+ y *= ww;
+ n >>= 1;
+ }
+
+if( asign )
+ y = -y; /* odd power of negative number */
+if( sign < 0 )
+ y = 1.0L/y;
+return(y);
+}
--- /dev/null
+/* From: @(#)e_rem_pio2.c 1.4 95/01/18 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ * Copyright (c) 2008 Steven G. Kargl, David Schultz, Bruce D. Evans.
+ *
+ * Developed at SunSoft, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ *
+ * Optimized by Bruce D. Evans.
+ */
+
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/ld80/e_rem_pio2l.h,v 1.3 2011/06/18 13:56:33 benl Exp $");
+
+/* ld80 version of __ieee754_rem_pio2l(x,y)
+ *
+ * return the remainder of x rem pi/2 in y[0]+y[1]
+ * use __kernel_rem_pio2()
+ */
+
+#include <float.h>
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+#define BIAS (LDBL_MAX_EXP - 1)
+
+/*
+ * invpio2: 64 bits of 2/pi
+ * pio2_1: first 39 bits of pi/2
+ * pio2_1t: pi/2 - pio2_1
+ * pio2_2: second 39 bits of pi/2
+ * pio2_2t: pi/2 - (pio2_1+pio2_2)
+ * pio2_3: third 39 bits of pi/2
+ * pio2_3t: pi/2 - (pio2_1+pio2_2+pio2_3)
+ */
+
+static const double
+zero = 0.00000000000000000000e+00, /* 0x00000000, 0x00000000 */
+two24 = 1.67772160000000000000e+07, /* 0x41700000, 0x00000000 */
+pio2_1 = 1.57079632679597125389e+00, /* 0x3FF921FB, 0x54444000 */
+pio2_2 = -1.07463465549783099519e-12, /* -0x12e7b967674000.0p-92 */
+pio2_3 = 6.36831716351370313614e-25; /* 0x18a2e037074000.0p-133 */
+
+#if defined(__amd64__) || defined(__i386__)
+/* Long double constants are slow on these arches, and broken on i386. */
+static const volatile double
+invpio2hi = 6.3661977236758138e-01, /* 0x145f306dc9c883.0p-53 */
+invpio2lo = -3.9356538861223811e-17, /* -0x16b00000000000.0p-107 */
+pio2_1thi = -1.0746346554971943e-12, /* -0x12e7b9676733af.0p-92 */
+pio2_1tlo = 8.8451028997905949e-29, /* 0x1c080000000000.0p-146 */
+pio2_2thi = 6.3683171635109499e-25, /* 0x18a2e03707344a.0p-133 */
+pio2_2tlo = 2.3183081793789774e-41, /* 0x10280000000000.0p-187 */
+pio2_3thi = -2.7529965190440717e-37, /* -0x176b7ed8fbbacc.0p-174 */
+pio2_3tlo = -4.2006647512740502e-54; /* -0x19c00000000000.0p-230 */
+#define invpio2 ((long double)invpio2hi + invpio2lo)
+#define pio2_1t ((long double)pio2_1thi + pio2_1tlo)
+#define pio2_2t ((long double)pio2_2thi + pio2_2tlo)
+#define pio2_3t ((long double)pio2_3thi + pio2_3tlo)
+#else
+static const long double
+invpio2 = 6.36619772367581343076e-01L, /* 0xa2f9836e4e44152a.0p-64 */
+pio2_1t = -1.07463465549719416346e-12L, /* -0x973dcb3b399d747f.0p-103 */
+pio2_2t = 6.36831716351095013979e-25L, /* 0xc51701b839a25205.0p-144 */
+pio2_3t = -2.75299651904407171810e-37L; /* -0xbb5bf6c7ddd660ce.0p-185 */
+#endif
+
+//VBS
+//static inline __always_inline int
+//__ieee754_rem_pio2l(long double x, long double *y)
+
+static inline int
+__ieee754_rem_pio2l(long double x, long double *y)
+{
+ union IEEEl2bits u,u1;
+ long double z,w,t,r,fn;
+ double tx[3],ty[2];
+ int e0,ex,i,j,nx,n;
+ int16_t expsign;
+
+ u.e = x;
+ expsign = u.xbits.expsign;
+ ex = expsign & 0x7fff;
+ if (ex < BIAS + 25 || (ex == BIAS + 25 && u.bits.manh < 0xc90fdaa2)) {
+ /* |x| ~< 2^25*(pi/2), medium size */
+ /* Use a specialized rint() to get fn. Assume round-to-nearest. */
+ fn = x*invpio2+0x1.8p63;
+ fn = fn-0x1.8p63;
+#ifdef HAVE_EFFICIENT_IRINT
+ n = irint(fn);
+#else
+ n = fn;
+#endif
+ r = x-fn*pio2_1;
+ w = fn*pio2_1t; /* 1st round good to 102 bit */
+ {
+ union IEEEl2bits u2;
+ int ex1;
+ j = ex;
+ y[0] = r-w;
+ u2.e = y[0];
+ ex1 = u2.xbits.expsign & 0x7fff;
+ i = j-ex1;
+ if(i>22) { /* 2nd iteration needed, good to 141 */
+ t = r;
+ w = fn*pio2_2;
+ r = t-w;
+ w = fn*pio2_2t-((t-r)-w);
+ y[0] = r-w;
+ u2.e = y[0];
+ ex1 = u2.xbits.expsign & 0x7fff;
+ i = j-ex1;
+ if(i>61) { /* 3rd iteration need, 180 bits acc */
+ t = r; /* will cover all possible cases */
+ w = fn*pio2_3;
+ r = t-w;
+ w = fn*pio2_3t-((t-r)-w);
+ y[0] = r-w;
+ }
+ }
+ }
+ y[1] = (r-y[0])-w;
+ return n;
+ }
+ /*
+ * all other (large) arguments
+ */
+ if(ex==0x7fff) { /* x is inf or NaN */
+ y[0]=y[1]=x-x; return 0;
+ }
+ /* set z = scalbn(|x|,ilogb(x)-23) */
+ u1.e = x;
+ e0 = ex - BIAS - 23; /* e0 = ilogb(|x|)-23; */
+ u1.xbits.expsign = ex - e0;
+ z = u1.e;
+ for(i=0;i<2;i++) {
+ tx[i] = (double)((int32_t)(z));
+ z = (z-tx[i])*two24;
+ }
+ tx[2] = z;
+ nx = 3;
+ while(tx[nx-1]==zero) nx--; /* skip zero term */
+ n = __kernel_rem_pio2(tx,ty,e0,nx,2);
+ r = (long double)ty[0] + ty[1];
+ w = ty[1] - (r - ty[0]);
+ if(expsign<0) {y[0] = -r; y[1] = -w; return -n;}
+ y[0] = r; y[1] = w; return n;
+}
--- /dev/null
+/* @(#)e_sinh.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/* sinhl(x)
+ * Method :
+ * mathematically sinh(x) if defined to be (exp(x)-exp(-x))/2
+ * 1. Replace x by |x| (sinhl(-x) = -sinhl(x)).
+ * 2.
+ * E + E/(E+1)
+ * 0 <= x <= 25 : sinhl(x) := --------------, E=expm1l(x)
+ * 2
+ *
+ * 25 <= x <= lnovft : sinhl(x) := expl(x)/2
+ * lnovft <= x <= ln2ovft: sinhl(x) := expl(x/2)/2 * expl(x/2)
+ * ln2ovft < x : sinhl(x) := x*shuge (overflow)
+ *
+ * Special cases:
+ * sinhl(x) is |x| if x is +INF, -INF, or NaN.
+ * only sinhl(0)=0 is exact for finite x.
+ */
+
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+static const long double one = 1.0, shuge = 1.0e4931L;
+
+long double
+sinhl(long double x)
+{
+ long double t,w,h;
+ u_int32_t jx,ix,i0,i1;
+
+ /* Words of |x|. */
+ GET_LDOUBLE_WORDS(jx,i0,i1,x);
+ ix = jx&0x7fff;
+
+ /* x is INF or NaN */
+ if(ix==0x7fff) return x+x;
+
+ h = 0.5;
+ if (jx & 0x8000) h = -h;
+ /* |x| in [0,25], return sign(x)*0.5*(E+E/(E+1))) */
+ if (ix < 0x4003 || (ix == 0x4003 && i0 <= 0xc8000000)) { /* |x|<25 */
+ if (ix<0x3fdf) /* |x|<2**-32 */
+ if(shuge+x>one) return x;/* sinh(tiny) = tiny with inexact */
+ t = expm1l(fabsl(x));
+ if(ix<0x3fff) return h*(2.0*t-t*t/(t+one));
+ return h*(t+t/(t+one));
+ }
+
+ /* |x| in [25, log(maxdouble)] return 0.5*exp(|x|) */
+ if (ix < 0x400c || (ix == 0x400c && i0 < 0xb17217f7))
+ return h*expl(fabsl(x));
+
+ /* |x| in [log(maxdouble), overflowthreshold] */
+ if (ix<0x400c || (ix == 0x400c && (i0 < 0xb174ddc0
+ || (i0 == 0xb174ddc0
+ && i1 <= 0x31aec0ea)))) {
+ w = expl(0.5*fabsl(x));
+ t = h*w;
+ return t*w;
+ }
+
+ /* |x| > overflowthreshold, sinhl(x) overflow */
+ return x*shuge;
+}
--- /dev/null
+/* $OpenBSD: e_tgammal.c,v 1.4 2013/11/12 20:35:19 martynas Exp $ */
+
+/*
+ * Copyright (c) 2008 Stephen L. Moshier <steve@moshier.net>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* tgammal.c
+ *
+ * Gamma function
+ *
+ *
+ *
+ * SYNOPSIS:
+ *
+ * long double x, y, tgammal();
+ *
+ * y = tgammal( x );
+ *
+ *
+ *
+ * DESCRIPTION:
+ *
+ * Returns gamma function of the argument. The result is correctly
+ * signed. This variable is also filled in by the logarithmic gamma
+ * function lgamma().
+ *
+ * Arguments |x| <= 13 are reduced by recurrence and the function
+ * approximated by a rational function of degree 7/8 in the
+ * interval (2,3). Large arguments are handled by Stirling's
+ * formula. Large negative arguments are made positive using
+ * a reflection formula.
+ *
+ *
+ * ACCURACY:
+ *
+ * Relative error:
+ * arithmetic domain # trials peak rms
+ * IEEE -40,+40 10000 3.6e-19 7.9e-20
+ * IEEE -1755,+1755 10000 4.8e-18 6.5e-19
+ *
+ * Accuracy for large arguments is dominated by error in powl().
+ *
+ */
+
+#include <float.h>
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+/*
+tgamma(x+2) = tgamma(x+2) P(x)/Q(x)
+0 <= x <= 1
+Relative error
+n=7, d=8
+Peak error = 1.83e-20
+Relative error spread = 8.4e-23
+*/
+
+static long double P[8] = {
+ 4.212760487471622013093E-5L,
+ 4.542931960608009155600E-4L,
+ 4.092666828394035500949E-3L,
+ 2.385363243461108252554E-2L,
+ 1.113062816019361559013E-1L,
+ 3.629515436640239168939E-1L,
+ 8.378004301573126728826E-1L,
+ 1.000000000000000000009E0L,
+};
+static long double Q[9] = {
+-1.397148517476170440917E-5L,
+ 2.346584059160635244282E-4L,
+-1.237799246653152231188E-3L,
+-7.955933682494738320586E-4L,
+ 2.773706565840072979165E-2L,
+-4.633887671244534213831E-2L,
+-2.243510905670329164562E-1L,
+ 4.150160950588455434583E-1L,
+ 9.999999999999999999908E-1L,
+};
+
+/*
+static long double P[] = {
+-3.01525602666895735709e0L,
+-3.25157411956062339893e1L,
+-2.92929976820724030353e2L,
+-1.70730828800510297666e3L,
+-7.96667499622741999770e3L,
+-2.59780216007146401957e4L,
+-5.99650230220855581642e4L,
+-7.15743521530849602425e4L
+};
+static long double Q[] = {
+ 1.00000000000000000000e0L,
+-1.67955233807178858919e1L,
+ 8.85946791747759881659e1L,
+ 5.69440799097468430177e1L,
+-1.98526250512761318471e3L,
+ 3.31667508019495079814e3L,
+ 1.60577839621734713377e4L,
+-2.97045081369399940529e4L,
+-7.15743521530849602412e4L
+};
+*/
+#define MAXGAML 1755.455L
+/*static const long double LOGPI = 1.14472988584940017414L;*/
+
+/* Stirling's formula for the gamma function
+tgamma(x) = sqrt(2 pi) x^(x-.5) exp(-x) (1 + 1/x P(1/x))
+z(x) = x
+13 <= x <= 1024
+Relative error
+n=8, d=0
+Peak error = 9.44e-21
+Relative error spread = 8.8e-4
+*/
+
+static long double STIR[9] = {
+ 7.147391378143610789273E-4L,
+-2.363848809501759061727E-5L,
+-5.950237554056330156018E-4L,
+ 6.989332260623193171870E-5L,
+ 7.840334842744753003862E-4L,
+-2.294719747873185405699E-4L,
+-2.681327161876304418288E-3L,
+ 3.472222222230075327854E-3L,
+ 8.333333333333331800504E-2L,
+};
+
+#define MAXSTIR 1024.0L
+static const long double SQTPI = 2.50662827463100050242E0L;
+
+/* 1/tgamma(x) = z P(z)
+ * z(x) = 1/x
+ * 0 < x < 0.03125
+ * Peak relative error 4.2e-23
+ */
+
+static long double S[9] = {
+-1.193945051381510095614E-3L,
+ 7.220599478036909672331E-3L,
+-9.622023360406271645744E-3L,
+-4.219773360705915470089E-2L,
+ 1.665386113720805206758E-1L,
+-4.200263503403344054473E-2L,
+-6.558780715202540684668E-1L,
+ 5.772156649015328608253E-1L,
+ 1.000000000000000000000E0L,
+};
+
+/* 1/tgamma(-x) = z P(z)
+ * z(x) = 1/x
+ * 0 < x < 0.03125
+ * Peak relative error 5.16e-23
+ * Relative error spread = 2.5e-24
+ */
+
+static long double SN[9] = {
+ 1.133374167243894382010E-3L,
+ 7.220837261893170325704E-3L,
+ 9.621911155035976733706E-3L,
+-4.219773343731191721664E-2L,
+-1.665386113944413519335E-1L,
+-4.200263503402112910504E-2L,
+ 6.558780715202536547116E-1L,
+ 5.772156649015328608727E-1L,
+-1.000000000000000000000E0L,
+};
+
+static const long double PIL = 3.1415926535897932384626L;
+
+static long double stirf ( long double );
+
+/* Gamma function computed by Stirling's formula.
+ */
+static long double stirf(long double x)
+{
+long double y, w, v;
+
+w = 1.0L/x;
+/* For large x, use rational coefficients from the analytical expansion. */
+if( x > 1024.0L )
+ w = (((((6.97281375836585777429E-5L * w
+ + 7.84039221720066627474E-4L) * w
+ - 2.29472093621399176955E-4L) * w
+ - 2.68132716049382716049E-3L) * w
+ + 3.47222222222222222222E-3L) * w
+ + 8.33333333333333333333E-2L) * w
+ + 1.0L;
+else
+ w = 1.0L + w * __polevll( w, STIR, 8 );
+y = expl(x);
+if( x > MAXSTIR )
+ { /* Avoid overflow in pow() */
+ v = powl( x, 0.5L * x - 0.25L );
+ y = v * (v / y);
+ }
+else
+ {
+ y = powl( x, x - 0.5L ) / y;
+ }
+y = SQTPI * y * w;
+return( y );
+}
+
+long double
+tgammal(long double x)
+{
+long double p, q, z;
+int i;
+
+if( isnan(x) )
+ return(NAN);
+if(x == INFINITY)
+ return(INFINITY);
+if(x == -INFINITY)
+ return(x - x);
+if( x == 0.0L )
+ return( 1.0L / x );
+q = fabsl(x);
+
+if( q > 13.0L )
+ {
+ int sign = 1;
+ if( q > MAXGAML )
+ goto goverf;
+ if( x < 0.0L )
+ {
+ p = floorl(q);
+ if( p == q )
+ return (x - x) / (x - x);
+ i = p;
+ if( (i & 1) == 0 )
+ sign = -1;
+ z = q - p;
+ if( z > 0.5L )
+ {
+ p += 1.0L;
+ z = q - p;
+ }
+ z = q * sinl( PIL * z );
+ z = fabsl(z) * stirf(q);
+ if( z <= PIL/LDBL_MAX )
+ {
+goverf:
+ return( sign * INFINITY);
+ }
+ z = PIL/z;
+ }
+ else
+ {
+ z = stirf(x);
+ }
+ return( sign * z );
+ }
+
+z = 1.0L;
+while( x >= 3.0L )
+ {
+ x -= 1.0L;
+ z *= x;
+ }
+
+while( x < -0.03125L )
+ {
+ z /= x;
+ x += 1.0L;
+ }
+
+if( x <= 0.03125L )
+ goto small;
+
+while( x < 2.0L )
+ {
+ z /= x;
+ x += 1.0L;
+ }
+
+if( x == 2.0L )
+ return(z);
+
+x -= 2.0L;
+p = __polevll( x, P, 7 );
+q = __polevll( x, Q, 8 );
+z = z * p / q;
+return z;
+
+small:
+if( x == 0.0L )
+ return (x - x) / (x - x);
+else
+ {
+ if( x < 0.0L )
+ {
+ x = -x;
+ q = z / (x * __polevll( x, SN, 8 ));
+ }
+ else
+ q = z / (x * __polevll( x, S, 8 ));
+ }
+return q;
+}
--- /dev/null
+/*-
+ * Copyright (c) 2008 David Schultz <das@FreeBSD.ORG>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/ld80/invtrig.c,v 1.1 2008/07/31 22:41:26 das Exp $");
+
+#include "ld80/invtrig.h"
+
+/*
+ * asinl() and acosl()
+ */
+const long double
+pS0 = 1.66666666666666666631e-01L,
+pS1 = -4.16313987993683104320e-01L,
+pS2 = 3.69068046323246813704e-01L,
+pS3 = -1.36213932016738603108e-01L,
+pS4 = 1.78324189708471965733e-02L,
+pS5 = -2.19216428382605211588e-04L,
+pS6 = -7.10526623669075243183e-06L,
+qS1 = -2.94788392796209867269e+00L,
+qS2 = 3.27309890266528636716e+00L,
+qS3 = -1.68285799854822427013e+00L,
+qS4 = 3.90699412641738801874e-01L,
+qS5 = -3.14365703596053263322e-02L;
+
+/*
+ * atanl()
+ */
+const long double atanhi[] = {
+ 4.63647609000806116202e-01L,
+ 7.85398163397448309628e-01L,
+ 9.82793723247329067960e-01L,
+ 1.57079632679489661926e+00L,
+};
+
+const long double atanlo[] = {
+ 1.18469937025062860669e-20L,
+ -1.25413940316708300586e-20L,
+ 2.55232234165405176172e-20L,
+ -2.50827880633416601173e-20L,
+};
+
+const long double aT[] = {
+ 3.33333333333333333017e-01L,
+ -1.99999999999999632011e-01L,
+ 1.42857142857046531280e-01L,
+ -1.11111111100562372733e-01L,
+ 9.09090902935647302252e-02L,
+ -7.69230552476207730353e-02L,
+ 6.66661718042406260546e-02L,
+ -5.88158892835030888692e-02L,
+ 5.25499891539726639379e-02L,
+ -4.70119845393155721494e-02L,
+ 4.03539201366454414072e-02L,
+ -2.91303858419364158725e-02L,
+ 1.24822046299269234080e-02L,
+};
+
+const long double pi_lo = -5.01655761266833202345e-20L;
--- /dev/null
+/*-
+ * Copyright (c) 2008 David Schultz <das@FreeBSD.ORG>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: src/lib/msun/ld80/invtrig.h,v 1.2 2008/08/02 03:56:22 das Exp $
+ */
+
+#include <float.h>
+
+#include <openlibm_math.h>
+
+#define BIAS (LDBL_MAX_EXP - 1)
+#define MANH_SIZE LDBL_MANH_SIZE
+
+/* Approximation thresholds. */
+#define ASIN_LINEAR (BIAS - 32) /* 2**-32 */
+#define ACOS_CONST (BIAS - 65) /* 2**-65 */
+#define ATAN_CONST (BIAS + 65) /* 2**65 */
+#define ATAN_LINEAR (BIAS - 32) /* 2**-32 */
+
+/* 0.95 */
+#define THRESH ((0xe666666666666666ULL>>(64-(MANH_SIZE-1)))|LDBL_NBIT)
+
+/* Constants shared by the long double inverse trig functions. */
+#define pS0 _ItL_pS0
+#define pS1 _ItL_pS1
+#define pS2 _ItL_pS2
+#define pS3 _ItL_pS3
+#define pS4 _ItL_pS4
+#define pS5 _ItL_pS5
+#define pS6 _ItL_pS6
+#define qS1 _ItL_qS1
+#define qS2 _ItL_qS2
+#define qS3 _ItL_qS3
+#define qS4 _ItL_qS4
+#define qS5 _ItL_qS5
+#define atanhi _ItL_atanhi
+#define atanlo _ItL_atanlo
+#define aT _ItL_aT
+#define pi_lo _ItL_pi_lo
+
+#define pio2_hi atanhi[3]
+#define pio2_lo atanlo[3]
+#define pio4_hi atanhi[1]
+
+#ifdef STRUCT_DECLS
+typedef struct longdouble {
+ uint64_t mant;
+ uint16_t expsign;
+} LONGDOUBLE;
+#else
+typedef long double LONGDOUBLE;
+#endif
+
+extern const LONGDOUBLE pS0, pS1, pS2, pS3, pS4, pS5, pS6;
+extern const LONGDOUBLE qS1, qS2, qS3, qS4, qS5;
+extern const LONGDOUBLE atanhi[], atanlo[], aT[];
+extern const LONGDOUBLE pi_lo;
+
+#ifndef STRUCT_DECLS
+
+static inline long double
+P(long double x)
+{
+
+ return (x * (pS0 + x * (pS1 + x * (pS2 + x * (pS3 + x * \
+ (pS4 + x * (pS5 + x * pS6)))))));
+}
+
+static inline long double
+Q(long double x)
+{
+
+ return (1.0 + x * (qS1 + x * (qS2 + x * (qS3 + x * (qS4 + x * qS5)))));
+}
+
+static inline long double
+T_even(long double x)
+{
+
+ return (aT[0] + x * (aT[2] + x * (aT[4] + x * (aT[6] + x * \
+ (aT[8] + x * (aT[10] + x * aT[12]))))));
+}
+
+static inline long double
+T_odd(long double x)
+{
+
+ return (aT[1] + x * (aT[3] + x * (aT[5] + x * (aT[7] + x * \
+ (aT[9] + x * aT[11])))));
+}
+
+#endif
--- /dev/null
+/* From: @(#)k_cos.c 1.3 95/01/18 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ * Copyright (c) 2008 Steven G. Kargl, David Schultz, Bruce D. Evans.
+ *
+ * Developed at SunSoft, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/ld80/k_cosl.c,v 1.1 2008/02/17 07:32:14 das Exp $");
+
+/*
+ * ld80 version of k_cos.c. See ../src/k_cos.c for most comments.
+ */
+
+#include "math_private.h"
+
+/*
+ * Domain [-0.7854, 0.7854], range ~[-2.43e-23, 2.425e-23]:
+ * |cos(x) - c(x)| < 2**-75.1
+ *
+ * The coefficients of c(x) were generated by a pari-gp script using
+ * a Remez algorithm that searches for the best higher coefficients
+ * after rounding leading coefficients to a specified precision.
+ *
+ * Simpler methods like Chebyshev or basic Remez barely suffice for
+ * cos() in 64-bit precision, because we want the coefficient of x^2
+ * to be precisely -0.5 so that multiplying by it is exact, and plain
+ * rounding of the coefficients of a good polynomial approximation only
+ * gives this up to about 64-bit precision. Plain rounding also gives
+ * a mediocre approximation for the coefficient of x^4, but a rounding
+ * error of 0.5 ulps for this coefficient would only contribute ~0.01
+ * ulps to the final error, so this is unimportant. Rounding errors in
+ * higher coefficients are even less important.
+ *
+ * In fact, coefficients above the x^4 one only need to have 53-bit
+ * precision, and this is more efficient. We get this optimization
+ * almost for free from the complications needed to search for the best
+ * higher coefficients.
+ */
+static const double
+one = 1.0;
+
+#if defined(__amd64__) || defined(__i386__)
+/* Long double constants are slow on these arches, and broken on i386. */
+static const volatile double
+C1hi = 0.041666666666666664, /* 0x15555555555555.0p-57 */
+C1lo = 2.2598839032744733e-18; /* 0x14d80000000000.0p-111 */
+#define C1 ((long double)C1hi + C1lo)
+#else
+static const long double
+C1 = 0.0416666666666666666136L; /* 0xaaaaaaaaaaaaaa9b.0p-68 */
+#endif
+
+static const double
+C2 = -0.0013888888888888874, /* -0x16c16c16c16c10.0p-62 */
+C3 = 0.000024801587301571716, /* 0x1a01a01a018e22.0p-68 */
+C4 = -0.00000027557319215507120, /* -0x127e4fb7602f22.0p-74 */
+C5 = 0.0000000020876754400407278, /* 0x11eed8caaeccf1.0p-81 */
+C6 = -1.1470297442401303e-11, /* -0x19393412bd1529.0p-89 */
+C7 = 4.7383039476436467e-14; /* 0x1aac9d9af5c43e.0p-97 */
+
+long double
+__kernel_cosl(long double x, long double y)
+{
+ long double hz,z,r,w;
+
+ z = x*x;
+ r = z*(C1+z*(C2+z*(C3+z*(C4+z*(C5+z*(C6+z*C7))))));
+ hz = 0.5*z;
+ w = one-hz;
+ return w + (((one-w)-hz) + (z*r-x*y));
+}
--- /dev/null
+/* From: @(#)k_sin.c 1.3 95/01/18 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ * Copyright (c) 2008 Steven G. Kargl, David Schultz, Bruce D. Evans.
+ *
+ * Developed at SunSoft, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/ld80/k_sinl.c,v 1.1 2008/02/17 07:32:14 das Exp $");
+
+/*
+ * ld80 version of k_sin.c. See ../src/k_sin.c for most comments.
+ */
+
+#include "math_private.h"
+
+static const double
+half = 0.5;
+
+/*
+ * Domain [-0.7854, 0.7854], range ~[-1.89e-22, 1.915e-22]
+ * |sin(x)/x - s(x)| < 2**-72.1
+ *
+ * See ../ld80/k_cosl.c for more details about the polynomial.
+ */
+#if defined(__amd64__) || defined(__i386__)
+/* Long double constants are slow on these arches, and broken on i386. */
+static const volatile double
+S1hi = -0.16666666666666666, /* -0x15555555555555.0p-55 */
+S1lo = -9.2563760475949941e-18; /* -0x15580000000000.0p-109 */
+#define S1 ((long double)S1hi + S1lo)
+#else
+static const long double
+S1 = -0.166666666666666666671L; /* -0xaaaaaaaaaaaaaaab.0p-66 */
+#endif
+
+static const double
+S2 = 0.0083333333333333332, /* 0x11111111111111.0p-59 */
+S3 = -0.00019841269841269427, /* -0x1a01a01a019f81.0p-65 */
+S4 = 0.0000027557319223597490, /* 0x171de3a55560f7.0p-71 */
+S5 = -0.000000025052108218074604, /* -0x1ae64564f16cad.0p-78 */
+S6 = 1.6059006598854211e-10, /* 0x161242b90243b5.0p-85 */
+S7 = -7.6429779983024564e-13, /* -0x1ae42ebd1b2e00.0p-93 */
+S8 = 2.6174587166648325e-15; /* 0x179372ea0b3f64.0p-101 */
+
+long double
+__kernel_sinl(long double x, long double y, int iy)
+{
+ long double z,r,v;
+
+ z = x*x;
+ v = z*x;
+ r = S2+z*(S3+z*(S4+z*(S5+z*(S6+z*(S7+z*S8)))));
+ if(iy==0) return x+v*(S1+z*r);
+ else return x-((z*(half*y-v*r)-y)-v*S1);
+}
--- /dev/null
+/* From: @(#)k_tan.c 1.5 04/04/22 SMI */
+
+/*
+ * ====================================================
+ * Copyright 2004 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright (c) 2008 Steven G. Kargl, David Schultz, Bruce D. Evans.
+ *
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/ld80/k_tanl.c,v 1.3 2008/02/18 15:39:52 bde Exp $");
+
+/*
+ * ld80 version of k_tan.c. See ../src/k_tan.c for most comments.
+ */
+
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+/*
+ * Domain [-0.67434, 0.67434], range ~[-2.25e-22, 1.921e-22]
+ * |tan(x)/x - t(x)| < 2**-71.9
+ *
+ * See k_cosl.c for more details about the polynomial.
+ */
+#if defined(__amd64__) || defined(__i386__)
+/* Long double constants are slow on these arches, and broken on i386. */
+static const volatile double
+T3hi = 0.33333333333333331, /* 0x15555555555555.0p-54 */
+T3lo = 1.8350121769317163e-17, /* 0x15280000000000.0p-108 */
+T5hi = 0.13333333333333336, /* 0x11111111111112.0p-55 */
+T5lo = 1.3051083651294260e-17, /* 0x1e180000000000.0p-109 */
+T7hi = 0.053968253968250494, /* 0x1ba1ba1ba1b827.0p-57 */
+T7lo = 3.1509625637859973e-18, /* 0x1d100000000000.0p-111 */
+pio4_hi = 0.78539816339744828, /* 0x1921fb54442d18.0p-53 */
+pio4_lo = 3.0628711372715500e-17, /* 0x11a80000000000.0p-107 */
+pio4lo_hi = -1.2541394031670831e-20, /* -0x1d9cceba3f91f2.0p-119 */
+pio4lo_lo = 6.1493048227390915e-37; /* 0x1a280000000000.0p-173 */
+#define T3 ((long double)T3hi + T3lo)
+#define T5 ((long double)T5hi + T5lo)
+#define T7 ((long double)T7hi + T7lo)
+#define pio4 ((long double)pio4_hi + pio4_lo)
+#define pio4lo ((long double)pio4lo_hi + pio4lo_lo)
+#else
+static const long double
+T3 = 0.333333333333333333180L, /* 0xaaaaaaaaaaaaaaa5.0p-65 */
+T5 = 0.133333333333333372290L, /* 0x88888888888893c3.0p-66 */
+T7 = 0.0539682539682504975744L, /* 0xdd0dd0dd0dc13ba2.0p-68 */
+pio4 = 0.785398163397448309628L, /* 0xc90fdaa22168c235.0p-64 */
+pio4lo = -1.25413940316708300586e-20L; /* -0xece675d1fc8f8cbb.0p-130 */
+#endif
+
+static const double
+T9 = 0.021869488536312216, /* 0x1664f4882cc1c2.0p-58 */
+T11 = 0.0088632355256619590, /* 0x1226e355c17612.0p-59 */
+T13 = 0.0035921281113786528, /* 0x1d6d3d185d7ff8.0p-61 */
+T15 = 0.0014558334756312418, /* 0x17da354aa3f96b.0p-62 */
+T17 = 0.00059003538700862256, /* 0x13559358685b83.0p-63 */
+T19 = 0.00023907843576635544, /* 0x1f56242026b5be.0p-65 */
+T21 = 0.000097154625656538905, /* 0x1977efc26806f4.0p-66 */
+T23 = 0.000038440165747303162, /* 0x14275a09b3ceac.0p-67 */
+T25 = 0.000018082171885432524, /* 0x12f5e563e5487e.0p-68 */
+T27 = 0.0000024196006108814377, /* 0x144c0d80cc6896.0p-71 */
+T29 = 0.0000078293456938132840, /* 0x106b59141a6cb3.0p-69 */
+T31 = -0.0000032609076735050182, /* -0x1b5abef3ba4b59.0p-71 */
+T33 = 0.0000023261313142559411; /* 0x13835436c0c87f.0p-71 */
+
+long double
+__kernel_tanl(long double x, long double y, int iy) {
+ long double z, r, v, w, s;
+ long double osign;
+ int i;
+
+ iy = (iy == 1 ? -1 : 1); /* XXX recover original interface */
+ osign = (x >= 0 ? 1.0 : -1.0); /* XXX slow, probably wrong for -0 */
+ if (fabsl(x) >= 0.67434) {
+ if (x < 0) {
+ x = -x;
+ y = -y;
+ }
+ z = pio4 - x;
+ w = pio4lo - y;
+ x = z + w;
+ y = 0.0;
+ i = 1;
+ } else
+ i = 0;
+ z = x * x;
+ w = z * z;
+ r = T5 + w * (T9 + w * (T13 + w * (T17 + w * (T21 +
+ w * (T25 + w * (T29 + w * T33))))));
+ v = z * (T7 + w * (T11 + w * (T15 + w * (T19 + w * (T23 +
+ w * (T27 + w * T31))))));
+ s = z * x;
+ r = y + z * (s * (r + v) + y);
+ r += T3 * s;
+ w = x + r;
+ if (i == 1) {
+ v = (long double) iy;
+ return osign *
+ (v - 2.0 * (x - (w * w / (w + v) - r)));
+ }
+ if (iy == 1)
+ return w;
+ else {
+ /*
+ * if allow error up to 2 ulp, simply return
+ * -1.0 / (x+r) here
+ */
+ /* compute -1.0 / (x+r) accurately */
+ long double a, t;
+ z = w;
+ z = z + 0x1p32 - 0x1p32;
+ v = r - (z - x); /* z+v = r+x */
+ t = a = -1.0 / w; /* a = -1.0/w */
+ t = t + 0x1p32 - 0x1p32;
+ s = 1.0 + t * z;
+ return t + a * (s + t * v);
+ }
+}
--- /dev/null
+/* @(#)s_asinh.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/* asinhl(x)
+ * Method :
+ * Based on
+ * asinhl(x) = signl(x) * logl [ |x| + sqrtl(x*x+1) ]
+ * we have
+ * asinhl(x) := x if 1+x*x=1,
+ * := signl(x)*(logl(x)+ln2)) for large |x|, else
+ * := signl(x)*logl(2|x|+1/(|x|+sqrtl(x*x+1))) if|x|>2, else
+ * := signl(x)*log1pl(|x| + x^2/(1 + sqrtl(1+x^2)))
+ */
+
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+static const long double
+one = 1.000000000000000000000e+00L, /* 0x3FFF, 0x00000000, 0x00000000 */
+ln2 = 6.931471805599453094287e-01L, /* 0x3FFE, 0xB17217F7, 0xD1CF79AC */
+huge= 1.000000000000000000e+4900L;
+
+long double
+asinhl(long double x)
+{
+ long double t,w;
+ int32_t hx,ix;
+ GET_LDOUBLE_EXP(hx,x);
+ ix = hx&0x7fff;
+ if(ix==0x7fff) return x+x; /* x is inf or NaN */
+ if(ix< 0x3fde) { /* |x|<2**-34 */
+ if(huge+x>one) return x; /* return x inexact except 0 */
+ }
+ if(ix>0x4020) { /* |x| > 2**34 */
+ w = logl(fabsl(x))+ln2;
+ } else if (ix>0x4000) { /* 2**34 > |x| > 2.0 */
+ t = fabsl(x);
+ w = logl(2.0*t+one/(sqrtl(x*x+one)+t));
+ } else { /* 2.0 > |x| > 2**-28 */
+ t = x*x;
+ w =log1pl(fabsl(x)+t/(one+sqrtl(one+t)));
+ }
+ if(hx&0x8000) return -w; else return w;
+}
--- /dev/null
+/* @(#)s_ceil.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/*
+ * ceill(x)
+ * Return x rounded toward -inf to integral value
+ * Method:
+ * Bit twiddling.
+ * Exception:
+ * Inexact flag raised if x not equal to ceil(x).
+ */
+
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+static const long double huge = 1.0e4930L;
+
+long double
+ceill(long double x)
+{
+ int32_t i1,jj0;
+ u_int32_t i,j,se,i0,sx;
+ GET_LDOUBLE_WORDS(se,i0,i1,x);
+ sx = (se>>15)&1;
+ jj0 = (se&0x7fff)-0x3fff;
+ if(jj0<31) {
+ if(jj0<0) { /* raise inexact if x != 0 */
+ if(huge+x>0.0) {/* return 0*sign(x) if |x|<1 */
+ if(sx) {se=0x8000;i0=0;i1=0;}
+ else if((i0|i1)!=0) { se=0x3fff;i0=0;i1=0;}
+ }
+ } else {
+ i = (0x7fffffff)>>jj0;
+ if(((i0&i)|i1)==0) return x; /* x is integral */
+ if(huge+x>0.0) { /* raise inexact flag */
+ if(sx==0) {
+ if (jj0>0 && (i0+(0x80000000>>jj0))>i0)
+ i0+=0x80000000>>jj0;
+ else
+ {
+ i = 0x7fffffff;
+ ++se;
+ }
+ }
+ i0 &= (~i); i1=0;
+ }
+ }
+ } else if (jj0>62) {
+ if(jj0==0x4000) return x+x; /* inf or NaN */
+ else return x; /* x is integral */
+ } else {
+ i = ((u_int32_t)(0xffffffff))>>(jj0-31);
+ if((i1&i)==0) return x; /* x is integral */
+ if(huge+x>0.0) { /* raise inexact flag */
+ if(sx==0) {
+ if(jj0==31) i0+=1;
+ else {
+ j = i1 + (1<<(63-jj0));
+ if(j<i1) i0+=1; /* got a carry */
+ i1 = j;
+ }
+ }
+ i1 &= (~i);
+ }
+ }
+ SET_LDOUBLE_WORDS(x,se,i0,i1);
+ return x;
+}
--- /dev/null
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/*
+ * Copyright (c) 2008 Stephen L. Moshier <steve@moshier.net>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* double erf(double x)
+ * double erfc(double x)
+ * x
+ * 2 |\
+ * erf(x) = --------- | exp(-t*t)dt
+ * sqrt(pi) \|
+ * 0
+ *
+ * erfc(x) = 1-erf(x)
+ * Note that
+ * erf(-x) = -erf(x)
+ * erfc(-x) = 2 - erfc(x)
+ *
+ * Method:
+ * 1. For |x| in [0, 0.84375]
+ * erf(x) = x + x*R(x^2)
+ * erfc(x) = 1 - erf(x) if x in [-.84375,0.25]
+ * = 0.5 + ((0.5-x)-x*R) if x in [0.25,0.84375]
+ * Remark. The formula is derived by noting
+ * erf(x) = (2/sqrt(pi))*(x - x^3/3 + x^5/10 - x^7/42 + ....)
+ * and that
+ * 2/sqrt(pi) = 1.128379167095512573896158903121545171688
+ * is close to one. The interval is chosen because the fix
+ * point of erf(x) is near 0.6174 (i.e., erf(x)=x when x is
+ * near 0.6174), and by some experiment, 0.84375 is chosen to
+ * guarantee the error is less than one ulp for erf.
+ *
+ * 2. For |x| in [0.84375,1.25], let s = |x| - 1, and
+ * c = 0.84506291151 rounded to single (24 bits)
+ * erf(x) = sign(x) * (c + P1(s)/Q1(s))
+ * erfc(x) = (1-c) - P1(s)/Q1(s) if x > 0
+ * 1+(c+P1(s)/Q1(s)) if x < 0
+ * Remark: here we use the taylor series expansion at x=1.
+ * erf(1+s) = erf(1) + s*Poly(s)
+ * = 0.845.. + P1(s)/Q1(s)
+ * Note that |P1/Q1|< 0.078 for x in [0.84375,1.25]
+ *
+ * 3. For x in [1.25,1/0.35(~2.857143)],
+ * erfc(x) = (1/x)*exp(-x*x-0.5625+R1(z)/S1(z))
+ * z=1/x^2
+ * erf(x) = 1 - erfc(x)
+ *
+ * 4. For x in [1/0.35,107]
+ * erfc(x) = (1/x)*exp(-x*x-0.5625+R2/S2) if x > 0
+ * = 2.0 - (1/x)*exp(-x*x-0.5625+R2(z)/S2(z))
+ * if -6.666<x<0
+ * = 2.0 - tiny (if x <= -6.666)
+ * z=1/x^2
+ * erf(x) = sign(x)*(1.0 - erfc(x)) if x < 6.666, else
+ * erf(x) = sign(x)*(1.0 - tiny)
+ * Note1:
+ * To compute exp(-x*x-0.5625+R/S), let s be a single
+ * precision number and s := x; then
+ * -x*x = -s*s + (s-x)*(s+x)
+ * exp(-x*x-0.5626+R/S) =
+ * exp(-s*s-0.5625)*exp((s-x)*(s+x)+R/S);
+ * Note2:
+ * Here 4 and 5 make use of the asymptotic series
+ * exp(-x*x)
+ * erfc(x) ~ ---------- * ( 1 + Poly(1/x^2) )
+ * x*sqrt(pi)
+ *
+ * 5. For inf > x >= 107
+ * erf(x) = sign(x) *(1 - tiny) (raise inexact)
+ * erfc(x) = tiny*tiny (raise underflow) if x > 0
+ * = 2 - tiny if x<0
+ *
+ * 7. Special case:
+ * erf(0) = 0, erf(inf) = 1, erf(-inf) = -1,
+ * erfc(0) = 1, erfc(inf) = 0, erfc(-inf) = 2,
+ * erfc/erf(NaN) is NaN
+ */
+
+
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+static const long double
+tiny = 1e-4931L,
+ half = 0.5L,
+ one = 1.0L,
+ two = 2.0L,
+ /* c = (float)0.84506291151 */
+ erx = 0.845062911510467529296875L,
+/*
+ * Coefficients for approximation to erf on [0,0.84375]
+ */
+ /* 2/sqrt(pi) - 1 */
+ efx = 1.2837916709551257389615890312154517168810E-1L,
+ /* 8 * (2/sqrt(pi) - 1) */
+ efx8 = 1.0270333367641005911692712249723613735048E0L,
+
+ pp[6] = {
+ 1.122751350964552113068262337278335028553E6L,
+ -2.808533301997696164408397079650699163276E6L,
+ -3.314325479115357458197119660818768924100E5L,
+ -6.848684465326256109712135497895525446398E4L,
+ -2.657817695110739185591505062971929859314E3L,
+ -1.655310302737837556654146291646499062882E2L,
+ },
+
+ qq[6] = {
+ 8.745588372054466262548908189000448124232E6L,
+ 3.746038264792471129367533128637019611485E6L,
+ 7.066358783162407559861156173539693900031E5L,
+ 7.448928604824620999413120955705448117056E4L,
+ 4.511583986730994111992253980546131408924E3L,
+ 1.368902937933296323345610240009071254014E2L,
+ /* 1.000000000000000000000000000000000000000E0 */
+ },
+
+/*
+ * Coefficients for approximation to erf in [0.84375,1.25]
+ */
+/* erf(x+1) = 0.845062911510467529296875 + pa(x)/qa(x)
+ -0.15625 <= x <= +.25
+ Peak relative error 8.5e-22 */
+
+ pa[8] = {
+ -1.076952146179812072156734957705102256059E0L,
+ 1.884814957770385593365179835059971587220E2L,
+ -5.339153975012804282890066622962070115606E1L,
+ 4.435910679869176625928504532109635632618E1L,
+ 1.683219516032328828278557309642929135179E1L,
+ -2.360236618396952560064259585299045804293E0L,
+ 1.852230047861891953244413872297940938041E0L,
+ 9.394994446747752308256773044667843200719E-2L,
+ },
+
+ qa[7] = {
+ 4.559263722294508998149925774781887811255E2L,
+ 3.289248982200800575749795055149780689738E2L,
+ 2.846070965875643009598627918383314457912E2L,
+ 1.398715859064535039433275722017479994465E2L,
+ 6.060190733759793706299079050985358190726E1L,
+ 2.078695677795422351040502569964299664233E1L,
+ 4.641271134150895940966798357442234498546E0L,
+ /* 1.000000000000000000000000000000000000000E0 */
+ },
+
+/*
+ * Coefficients for approximation to erfc in [1.25,1/0.35]
+ */
+/* erfc(1/x) = x exp (-1/x^2 - 0.5625 + ra(x^2)/sa(x^2))
+ 1/2.85711669921875 < 1/x < 1/1.25
+ Peak relative error 3.1e-21 */
+
+ ra[] = {
+ 1.363566591833846324191000679620738857234E-1L,
+ 1.018203167219873573808450274314658434507E1L,
+ 1.862359362334248675526472871224778045594E2L,
+ 1.411622588180721285284945138667933330348E3L,
+ 5.088538459741511988784440103218342840478E3L,
+ 8.928251553922176506858267311750789273656E3L,
+ 7.264436000148052545243018622742770549982E3L,
+ 2.387492459664548651671894725748959751119E3L,
+ 2.220916652813908085449221282808458466556E2L,
+ },
+
+ sa[] = {
+ -1.382234625202480685182526402169222331847E1L,
+ -3.315638835627950255832519203687435946482E2L,
+ -2.949124863912936259747237164260785326692E3L,
+ -1.246622099070875940506391433635999693661E4L,
+ -2.673079795851665428695842853070996219632E4L,
+ -2.880269786660559337358397106518918220991E4L,
+ -1.450600228493968044773354186390390823713E4L,
+ -2.874539731125893533960680525192064277816E3L,
+ -1.402241261419067750237395034116942296027E2L,
+ /* 1.000000000000000000000000000000000000000E0 */
+ },
+/*
+ * Coefficients for approximation to erfc in [1/.35,107]
+ */
+/* erfc(1/x) = x exp (-1/x^2 - 0.5625 + rb(x^2)/sb(x^2))
+ 1/6.6666259765625 < 1/x < 1/2.85711669921875
+ Peak relative error 4.2e-22 */
+ rb[] = {
+ -4.869587348270494309550558460786501252369E-5L,
+ -4.030199390527997378549161722412466959403E-3L,
+ -9.434425866377037610206443566288917589122E-2L,
+ -9.319032754357658601200655161585539404155E-1L,
+ -4.273788174307459947350256581445442062291E0L,
+ -8.842289940696150508373541814064198259278E0L,
+ -7.069215249419887403187988144752613025255E0L,
+ -1.401228723639514787920274427443330704764E0L,
+ },
+
+ sb[] = {
+ 4.936254964107175160157544545879293019085E-3L,
+ 1.583457624037795744377163924895349412015E-1L,
+ 1.850647991850328356622940552450636420484E0L,
+ 9.927611557279019463768050710008450625415E0L,
+ 2.531667257649436709617165336779212114570E1L,
+ 2.869752886406743386458304052862814690045E1L,
+ 1.182059497870819562441683560749192539345E1L,
+ /* 1.000000000000000000000000000000000000000E0 */
+ },
+/* erfc(1/x) = x exp (-1/x^2 - 0.5625 + rc(x^2)/sc(x^2))
+ 1/107 <= 1/x <= 1/6.6666259765625
+ Peak relative error 1.1e-21 */
+ rc[] = {
+ -8.299617545269701963973537248996670806850E-5L,
+ -6.243845685115818513578933902532056244108E-3L,
+ -1.141667210620380223113693474478394397230E-1L,
+ -7.521343797212024245375240432734425789409E-1L,
+ -1.765321928311155824664963633786967602934E0L,
+ -1.029403473103215800456761180695263439188E0L,
+ },
+
+ sc[] = {
+ 8.413244363014929493035952542677768808601E-3L,
+ 2.065114333816877479753334599639158060979E-1L,
+ 1.639064941530797583766364412782135680148E0L,
+ 4.936788463787115555582319302981666347450E0L,
+ 5.005177727208955487404729933261347679090E0L,
+ /* 1.000000000000000000000000000000000000000E0 */
+ };
+
+long double
+erfl(long double x)
+{
+ long double R, S, P, Q, s, y, z, r;
+ int32_t ix, i;
+ u_int32_t se, i0, i1;
+
+ GET_LDOUBLE_WORDS (se, i0, i1, x);
+ ix = se & 0x7fff;
+
+ if (ix >= 0x7fff)
+ { /* erf(nan)=nan */
+ i = ((se & 0xffff) >> 15) << 1;
+ return (long double) (1 - i) + one / x; /* erf(+-inf)=+-1 */
+ }
+
+ ix = (ix << 16) | (i0 >> 16);
+ if (ix < 0x3ffed800) /* |x|<0.84375 */
+ {
+ if (ix < 0x3fde8000) /* |x|<2**-33 */
+ {
+ if (ix < 0x00080000)
+ return 0.125 * (8.0 * x + efx8 * x); /*avoid underflow */
+ return x + efx * x;
+ }
+ z = x * x;
+ r = pp[0] + z * (pp[1]
+ + z * (pp[2] + z * (pp[3] + z * (pp[4] + z * pp[5]))));
+ s = qq[0] + z * (qq[1]
+ + z * (qq[2] + z * (qq[3] + z * (qq[4] + z * (qq[5] + z)))));
+ y = r / s;
+ return x + x * y;
+ }
+ if (ix < 0x3fffa000) /* 1.25 */
+ { /* 0.84375 <= |x| < 1.25 */
+ s = fabsl (x) - one;
+ P = pa[0] + s * (pa[1] + s * (pa[2]
+ + s * (pa[3] + s * (pa[4] + s * (pa[5] + s * (pa[6] + s * pa[7]))))));
+ Q = qa[0] + s * (qa[1] + s * (qa[2]
+ + s * (qa[3] + s * (qa[4] + s * (qa[5] + s * (qa[6] + s))))));
+ if ((se & 0x8000) == 0)
+ return erx + P / Q;
+ else
+ return -erx - P / Q;
+ }
+ if (ix >= 0x4001d555) /* 6.6666259765625 */
+ { /* inf>|x|>=6.666 */
+ if ((se & 0x8000) == 0)
+ return one - tiny;
+ else
+ return tiny - one;
+ }
+ x = fabsl (x);
+ s = one / (x * x);
+ if (ix < 0x4000b6db) /* 2.85711669921875 */
+ {
+ R = ra[0] + s * (ra[1] + s * (ra[2] + s * (ra[3] + s * (ra[4] +
+ s * (ra[5] + s * (ra[6] + s * (ra[7] + s * ra[8])))))));
+ S = sa[0] + s * (sa[1] + s * (sa[2] + s * (sa[3] + s * (sa[4] +
+ s * (sa[5] + s * (sa[6] + s * (sa[7] + s * (sa[8] + s))))))));
+ }
+ else
+ { /* |x| >= 1/0.35 */
+ R = rb[0] + s * (rb[1] + s * (rb[2] + s * (rb[3] + s * (rb[4] +
+ s * (rb[5] + s * (rb[6] + s * rb[7]))))));
+ S = sb[0] + s * (sb[1] + s * (sb[2] + s * (sb[3] + s * (sb[4] +
+ s * (sb[5] + s * (sb[6] + s))))));
+ }
+ z = x;
+ GET_LDOUBLE_WORDS (i, i0, i1, z);
+ i1 = 0;
+ SET_LDOUBLE_WORDS (z, i, i0, i1);
+ r =
+ expl (-z * z - 0.5625) * expl ((z - x) * (z + x) + R / S);
+ if ((se & 0x8000) == 0)
+ return one - r / x;
+ else
+ return r / x - one;
+}
+
+long double
+erfcl(long double x)
+{
+ int32_t hx, ix;
+ long double R, S, P, Q, s, y, z, r;
+ u_int32_t se, i0, i1;
+
+ GET_LDOUBLE_WORDS (se, i0, i1, x);
+ ix = se & 0x7fff;
+ if (ix >= 0x7fff)
+ { /* erfc(nan)=nan */
+ /* erfc(+-inf)=0,2 */
+ return (long double) (((se & 0xffff) >> 15) << 1) + one / x;
+ }
+
+ ix = (ix << 16) | (i0 >> 16);
+ if (ix < 0x3ffed800) /* |x|<0.84375 */
+ {
+ if (ix < 0x3fbe0000) /* |x|<2**-65 */
+ return one - x;
+ z = x * x;
+ r = pp[0] + z * (pp[1]
+ + z * (pp[2] + z * (pp[3] + z * (pp[4] + z * pp[5]))));
+ s = qq[0] + z * (qq[1]
+ + z * (qq[2] + z * (qq[3] + z * (qq[4] + z * (qq[5] + z)))));
+ y = r / s;
+ if (ix < 0x3ffd8000) /* x<1/4 */
+ {
+ return one - (x + x * y);
+ }
+ else
+ {
+ r = x * y;
+ r += (x - half);
+ return half - r;
+ }
+ }
+ if (ix < 0x3fffa000) /* 1.25 */
+ { /* 0.84375 <= |x| < 1.25 */
+ s = fabsl (x) - one;
+ P = pa[0] + s * (pa[1] + s * (pa[2]
+ + s * (pa[3] + s * (pa[4] + s * (pa[5] + s * (pa[6] + s * pa[7]))))));
+ Q = qa[0] + s * (qa[1] + s * (qa[2]
+ + s * (qa[3] + s * (qa[4] + s * (qa[5] + s * (qa[6] + s))))));
+ if ((se & 0x8000) == 0)
+ {
+ z = one - erx;
+ return z - P / Q;
+ }
+ else
+ {
+ z = erx + P / Q;
+ return one + z;
+ }
+ }
+ if (ix < 0x4005d600) /* 107 */
+ { /* |x|<107 */
+ x = fabsl (x);
+ s = one / (x * x);
+ if (ix < 0x4000b6db) /* 2.85711669921875 */
+ { /* |x| < 1/.35 ~ 2.857143 */
+ R = ra[0] + s * (ra[1] + s * (ra[2] + s * (ra[3] + s * (ra[4] +
+ s * (ra[5] + s * (ra[6] + s * (ra[7] + s * ra[8])))))));
+ S = sa[0] + s * (sa[1] + s * (sa[2] + s * (sa[3] + s * (sa[4] +
+ s * (sa[5] + s * (sa[6] + s * (sa[7] + s * (sa[8] + s))))))));
+ }
+ else if (ix < 0x4001d555) /* 6.6666259765625 */
+ { /* 6.666 > |x| >= 1/.35 ~ 2.857143 */
+ R = rb[0] + s * (rb[1] + s * (rb[2] + s * (rb[3] + s * (rb[4] +
+ s * (rb[5] + s * (rb[6] + s * rb[7]))))));
+ S = sb[0] + s * (sb[1] + s * (sb[2] + s * (sb[3] + s * (sb[4] +
+ s * (sb[5] + s * (sb[6] + s))))));
+ }
+ else
+ { /* |x| >= 6.666 */
+ if (se & 0x8000)
+ return two - tiny; /* x < -6.666 */
+
+ R = rc[0] + s * (rc[1] + s * (rc[2] + s * (rc[3] +
+ s * (rc[4] + s * rc[5]))));
+ S = sc[0] + s * (sc[1] + s * (sc[2] + s * (sc[3] +
+ s * (sc[4] + s))));
+ }
+ z = x;
+ GET_LDOUBLE_WORDS (hx, i0, i1, z);
+ i1 = 0;
+ i0 &= 0xffffff00;
+ SET_LDOUBLE_WORDS (z, hx, i0, i1);
+ r = expl (-z * z - 0.5625) *
+ expl ((z - x) * (z + x) + R / S);
+ if ((se & 0x8000) == 0)
+ return r / x;
+ else
+ return two - r / x;
+ }
+ else
+ {
+ if ((se & 0x8000) == 0)
+ return tiny * tiny;
+ else
+ return two - tiny;
+ }
+}
--- /dev/null
+/*-
+ * Copyright (c) 2005-2008 David Schultz <das@FreeBSD.ORG>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/ld80/s_exp2l.c,v 1.3 2008/02/13 10:44:44 bde Exp $");
+
+#include <float.h>
+#include <stdint.h>
+
+#include "bsd_cdefs.h"
+#include "amd64/bsd_ieeefp.h"
+
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+#define TBLBITS 7
+#define TBLSIZE (1 << TBLBITS)
+
+#define BIAS (LDBL_MAX_EXP - 1)
+#define EXPMASK (BIAS + LDBL_MAX_EXP)
+
+static const long double huge = 0x1p10000L;
+#if 0 /* XXX Prevent gcc from erroneously constant folding this. */
+static const long double twom10000 = 0x1p-10000L;
+#else
+static volatile long double twom10000 = 0x1p-10000L;
+#endif
+
+static const double
+ redux = 0x1.8p63 / TBLSIZE,
+ P1 = 0x1.62e42fefa39efp-1,
+ P2 = 0x1.ebfbdff82c58fp-3,
+ P3 = 0x1.c6b08d7049fap-5,
+ P4 = 0x1.3b2ab6fba4da5p-7,
+ P5 = 0x1.5d8804780a736p-10,
+ P6 = 0x1.430918835e33dp-13;
+
+static const double tbl[TBLSIZE * 2] = {
+ 0x1.6a09e667f3bcdp-1, -0x1.bdd3413b2648p-55,
+ 0x1.6c012750bdabfp-1, -0x1.2895667ff0cp-57,
+ 0x1.6dfb23c651a2fp-1, -0x1.bbe3a683c88p-58,
+ 0x1.6ff7df9519484p-1, -0x1.83c0f25860fp-56,
+ 0x1.71f75e8ec5f74p-1, -0x1.16e4786887bp-56,
+ 0x1.73f9a48a58174p-1, -0x1.0a8d96c65d5p-55,
+ 0x1.75feb564267c9p-1, -0x1.0245957316ep-55,
+ 0x1.780694fde5d3fp-1, 0x1.866b80a0216p-55,
+ 0x1.7a11473eb0187p-1, -0x1.41577ee0499p-56,
+ 0x1.7c1ed0130c132p-1, 0x1.f124cd1164ep-55,
+ 0x1.7e2f336cf4e62p-1, 0x1.05d02ba157ap-57,
+ 0x1.80427543e1a12p-1, -0x1.27c86626d97p-55,
+ 0x1.82589994cce13p-1, -0x1.d4c1dd41533p-55,
+ 0x1.8471a4623c7adp-1, -0x1.8d684a341cep-56,
+ 0x1.868d99b4492edp-1, -0x1.fc6f89bd4f68p-55,
+ 0x1.88ac7d98a6699p-1, 0x1.994c2f37cb5p-55,
+ 0x1.8ace5422aa0dbp-1, 0x1.6e9f156864bp-55,
+ 0x1.8cf3216b5448cp-1, -0x1.0d55e32e9e4p-57,
+ 0x1.8f1ae99157736p-1, 0x1.5cc13a2e397p-56,
+ 0x1.9145b0b91ffc6p-1, -0x1.dd6792e5825p-55,
+ 0x1.93737b0cdc5e5p-1, -0x1.75fc781b58p-58,
+ 0x1.95a44cbc8520fp-1, -0x1.64b7c96a5fp-57,
+ 0x1.97d829fde4e5p-1, -0x1.d185b7c1b86p-55,
+ 0x1.9a0f170ca07bap-1, -0x1.173bd91cee6p-55,
+ 0x1.9c49182a3f09p-1, 0x1.c7c46b071f2p-57,
+ 0x1.9e86319e32323p-1, 0x1.824ca78e64cp-57,
+ 0x1.a0c667b5de565p-1, -0x1.359495d1cd5p-55,
+ 0x1.a309bec4a2d33p-1, 0x1.6305c7ddc368p-55,
+ 0x1.a5503b23e255dp-1, -0x1.d2f6edb8d42p-55,
+ 0x1.a799e1330b358p-1, 0x1.bcb7ecac564p-55,
+ 0x1.a9e6b5579fdbfp-1, 0x1.0fac90ef7fdp-55,
+ 0x1.ac36bbfd3f37ap-1, -0x1.f9234cae76dp-56,
+ 0x1.ae89f995ad3adp-1, 0x1.7a1cd345dcc8p-55,
+ 0x1.b0e07298db666p-1, -0x1.bdef54c80e4p-55,
+ 0x1.b33a2b84f15fbp-1, -0x1.2805e3084d8p-58,
+ 0x1.b59728de5593ap-1, -0x1.c71dfbbba6ep-55,
+ 0x1.b7f76f2fb5e47p-1, -0x1.5584f7e54acp-57,
+ 0x1.ba5b030a1064ap-1, -0x1.efcd30e5429p-55,
+ 0x1.bcc1e904bc1d2p-1, 0x1.23dd07a2d9fp-56,
+ 0x1.bf2c25bd71e09p-1, -0x1.efdca3f6b9c8p-55,
+ 0x1.c199bdd85529cp-1, 0x1.11065895049p-56,
+ 0x1.c40ab5fffd07ap-1, 0x1.b4537e083c6p-55,
+ 0x1.c67f12e57d14bp-1, 0x1.2884dff483c8p-55,
+ 0x1.c8f6d9406e7b5p-1, 0x1.1acbc48805cp-57,
+ 0x1.cb720dcef9069p-1, 0x1.503cbd1e94ap-57,
+ 0x1.cdf0b555dc3fap-1, -0x1.dd83b53829dp-56,
+ 0x1.d072d4a07897cp-1, -0x1.cbc3743797a8p-55,
+ 0x1.d2f87080d89f2p-1, -0x1.d487b719d858p-55,
+ 0x1.d5818dcfba487p-1, 0x1.2ed02d75b37p-56,
+ 0x1.d80e316c98398p-1, -0x1.11ec18bedep-55,
+ 0x1.da9e603db3285p-1, 0x1.c2300696db5p-55,
+ 0x1.dd321f301b46p-1, 0x1.2da5778f019p-55,
+ 0x1.dfc97337b9b5fp-1, -0x1.1a5cd4f184b8p-55,
+ 0x1.e264614f5a129p-1, -0x1.7b627817a148p-55,
+ 0x1.e502ee78b3ff6p-1, 0x1.39e8980a9cdp-56,
+ 0x1.e7a51fbc74c83p-1, 0x1.2d522ca0c8ep-55,
+ 0x1.ea4afa2a490dap-1, -0x1.e9c23179c288p-55,
+ 0x1.ecf482d8e67f1p-1, -0x1.c93f3b411ad8p-55,
+ 0x1.efa1bee615a27p-1, 0x1.dc7f486a4b68p-55,
+ 0x1.f252b376bba97p-1, 0x1.3a1a5bf0d8e8p-55,
+ 0x1.f50765b6e454p-1, 0x1.9d3e12dd8a18p-55,
+ 0x1.f7bfdad9cbe14p-1, -0x1.dbb12d00635p-55,
+ 0x1.fa7c1819e90d8p-1, 0x1.74853f3a593p-56,
+ 0x1.fd3c22b8f71f1p-1, 0x1.2eb74966578p-58,
+ 0x1p+0, 0x0p+0,
+ 0x1.0163da9fb3335p+0, 0x1.b61299ab8cd8p-54,
+ 0x1.02c9a3e778061p+0, -0x1.19083535b08p-56,
+ 0x1.04315e86e7f85p+0, -0x1.0a31c1977c98p-54,
+ 0x1.059b0d3158574p+0, 0x1.d73e2a475b4p-55,
+ 0x1.0706b29ddf6dep+0, -0x1.c91dfe2b13cp-55,
+ 0x1.0874518759bc8p+0, 0x1.186be4bb284p-57,
+ 0x1.09e3ecac6f383p+0, 0x1.14878183161p-54,
+ 0x1.0b5586cf9890fp+0, 0x1.8a62e4adc61p-54,
+ 0x1.0cc922b7247f7p+0, 0x1.01edc16e24f8p-54,
+ 0x1.0e3ec32d3d1a2p+0, 0x1.03a1727c58p-59,
+ 0x1.0fb66affed31bp+0, -0x1.b9bedc44ebcp-57,
+ 0x1.11301d0125b51p+0, -0x1.6c51039449bp-54,
+ 0x1.12abdc06c31ccp+0, -0x1.1b514b36ca8p-58,
+ 0x1.1429aaea92dep+0, -0x1.32fbf9af1368p-54,
+ 0x1.15a98c8a58e51p+0, 0x1.2406ab9eeabp-55,
+ 0x1.172b83c7d517bp+0, -0x1.19041b9d78ap-55,
+ 0x1.18af9388c8deap+0, -0x1.11023d1970f8p-54,
+ 0x1.1a35beb6fcb75p+0, 0x1.e5b4c7b4969p-55,
+ 0x1.1bbe084045cd4p+0, -0x1.95386352ef6p-54,
+ 0x1.1d4873168b9aap+0, 0x1.e016e00a264p-54,
+ 0x1.1ed5022fcd91dp+0, -0x1.1df98027bb78p-54,
+ 0x1.2063b88628cd6p+0, 0x1.dc775814a85p-55,
+ 0x1.21f49917ddc96p+0, 0x1.2a97e9494a6p-55,
+ 0x1.2387a6e756238p+0, 0x1.9b07eb6c7058p-54,
+ 0x1.251ce4fb2a63fp+0, 0x1.ac155bef4f5p-55,
+ 0x1.26b4565e27cddp+0, 0x1.2bd339940eap-55,
+ 0x1.284dfe1f56381p+0, -0x1.a4c3a8c3f0d8p-54,
+ 0x1.29e9df51fdee1p+0, 0x1.612e8afad12p-55,
+ 0x1.2b87fd0dad99p+0, -0x1.10adcd6382p-59,
+ 0x1.2d285a6e4030bp+0, 0x1.0024754db42p-54,
+ 0x1.2ecafa93e2f56p+0, 0x1.1ca0f45d524p-56,
+ 0x1.306fe0a31b715p+0, 0x1.6f46ad23183p-55,
+ 0x1.32170fc4cd831p+0, 0x1.a9ce78e1804p-55,
+ 0x1.33c08b26416ffp+0, 0x1.327218436598p-54,
+ 0x1.356c55f929ff1p+0, -0x1.b5cee5c4e46p-55,
+ 0x1.371a7373aa9cbp+0, -0x1.63aeabf42ebp-54,
+ 0x1.38cae6d05d866p+0, -0x1.e958d3c99048p-54,
+ 0x1.3a7db34e59ff7p+0, -0x1.5e436d661f6p-56,
+ 0x1.3c32dc313a8e5p+0, -0x1.efff8375d2ap-54,
+ 0x1.3dea64c123422p+0, 0x1.ada0911f09fp-55,
+ 0x1.3fa4504ac801cp+0, -0x1.7d023f956fap-54,
+ 0x1.4160a21f72e2ap+0, -0x1.ef3691c309p-58,
+ 0x1.431f5d950a897p+0, -0x1.1c7dde35f7ap-55,
+ 0x1.44e086061892dp+0, 0x1.89b7a04ef8p-59,
+ 0x1.46a41ed1d0057p+0, 0x1.c944bd1648a8p-54,
+ 0x1.486a2b5c13cdp+0, 0x1.3c1a3b69062p-56,
+ 0x1.4a32af0d7d3dep+0, 0x1.9cb62f3d1be8p-54,
+ 0x1.4bfdad5362a27p+0, 0x1.d4397afec42p-56,
+ 0x1.4dcb299fddd0dp+0, 0x1.8ecdbbc6a78p-54,
+ 0x1.4f9b2769d2ca7p+0, -0x1.4b309d25958p-54,
+ 0x1.516daa2cf6642p+0, -0x1.f768569bd94p-55,
+ 0x1.5342b569d4f82p+0, -0x1.07abe1db13dp-55,
+ 0x1.551a4ca5d920fp+0, -0x1.d689cefede6p-55,
+ 0x1.56f4736b527dap+0, 0x1.9bb2c011d938p-54,
+ 0x1.58d12d497c7fdp+0, 0x1.295e15b9a1ep-55,
+ 0x1.5ab07dd485429p+0, 0x1.6324c0546478p-54,
+ 0x1.5c9268a5946b7p+0, 0x1.c4b1b81698p-60,
+ 0x1.5e76f15ad2148p+0, 0x1.ba6f93080e68p-54,
+ 0x1.605e1b976dc09p+0, -0x1.3e2429b56de8p-54,
+ 0x1.6247eb03a5585p+0, -0x1.383c17e40b48p-54,
+ 0x1.6434634ccc32p+0, -0x1.c483c759d89p-55,
+ 0x1.6623882552225p+0, -0x1.bb60987591cp-54,
+ 0x1.68155d44ca973p+0, 0x1.038ae44f74p-57,
+};
+
+/*
+ * exp2l(x): compute the base 2 exponential of x
+ *
+ * Accuracy: Peak error < 0.511 ulp.
+ *
+ * Method: (equally-spaced tables)
+ *
+ * Reduce x:
+ * x = 2**k + y, for integer k and |y| <= 1/2.
+ * Thus we have exp2l(x) = 2**k * exp2(y).
+ *
+ * Reduce y:
+ * y = i/TBLSIZE + z for integer i near y * TBLSIZE.
+ * Thus we have exp2(y) = exp2(i/TBLSIZE) * exp2(z),
+ * with |z| <= 2**-(TBLBITS+1).
+ *
+ * We compute exp2(i/TBLSIZE) via table lookup and exp2(z) via a
+ * degree-6 minimax polynomial with maximum error under 2**-69.
+ * The table entries each have 104 bits of accuracy, encoded as
+ * a pair of double precision values.
+ */
+OLM_DLLEXPORT long double
+exp2l(long double x)
+{
+ union IEEEl2bits u, v;
+ long double r, twopk, twopkp10000, z;
+ uint32_t hx, ix, i0;
+ int k;
+
+ /* Filter out exceptional cases. */
+ u.e = x;
+ hx = u.xbits.expsign;
+ ix = hx & EXPMASK;
+ if (ix >= BIAS + 14) { /* |x| >= 16384 or x is NaN */
+ if (ix == BIAS + LDBL_MAX_EXP) {
+ if (u.xbits.man != 1ULL << 63 || (hx & 0x8000) == 0)
+ return (x + x); /* x is +Inf or NaN */
+ else
+ return (0.0); /* x is -Inf */
+ }
+ if (x >= 16384)
+ return (huge * huge); /* overflow */
+ if (x <= -16446)
+ return (twom10000 * twom10000); /* underflow */
+ } else if (ix <= BIAS - 66) { /* |x| < 0x1p-66 */
+ return (1.0 + x);
+ }
+
+#ifdef __i386__
+ /*
+ * The default precision on i386 is 53 bits, so long doubles are
+ * broken. Call exp2() to get an accurate (double precision) result.
+ */
+ if (__fpgetprec() != FP_PE)
+ return (exp2(x));
+#endif
+
+
+ /*
+ * Reduce x, computing z, i0, and k. The low bits of x + redux
+ * contain the 16-bit integer part of the exponent (k) followed by
+ * TBLBITS fractional bits (i0). We use bit tricks to extract these
+ * as integers, then set z to the remainder.
+ *
+ * Example: Suppose x is 0xabc.123456p0 and TBLBITS is 8.
+ * Then the low-order word of x + redux is 0x000abc12,
+ * We split this into k = 0xabc and i0 = 0x12 (adjusted to
+ * index into the table), then we compute z = 0x0.003456p0.
+ *
+ * XXX If the exponent is negative, the computation of k depends on
+ * '>>' doing sign extension.
+ */
+ u.e = x + redux;
+ i0 = u.bits.manl + TBLSIZE / 2;
+ k = (int)i0 >> TBLBITS;
+ i0 = (i0 & (TBLSIZE - 1)) << 1;
+ u.e -= redux;
+ z = x - u.e;
+ v.xbits.man = 1ULL << 63;
+ if (k >= LDBL_MIN_EXP) {
+ v.xbits.expsign = LDBL_MAX_EXP - 1 + k;
+ twopk = v.e;
+ } else {
+ v.xbits.expsign = LDBL_MAX_EXP - 1 + k + 10000;
+ twopkp10000 = v.e;
+ }
+
+ /* Compute r = exp2l(y) = exp2lt[i0] * p(z). */
+ long double t_hi = tbl[i0];
+ long double t_lo = tbl[i0 + 1];
+ /* XXX This gives > 1 ulp errors outside of FE_TONEAREST mode */
+ r = t_lo + (t_hi + t_lo) * z * (P1 + z * (P2 + z * (P3 + z * (P4
+ + z * (P5 + z * P6))))) + t_hi;
+
+ /* Scale by 2**k. */
+ if (k >= LDBL_MIN_EXP) {
+ if (k == LDBL_MAX_EXP)
+ return (r * 2.0 * 0x1p16383L);
+ return (r * twopk);
+ } else {
+ return (r * twopkp10000 * twom10000);
+ }
+}
--- /dev/null
+/* $OpenBSD: s_expm1l.c,v 1.2 2011/07/20 21:02:51 martynas Exp $ */
+
+/*
+ * Copyright (c) 2008 Stephen L. Moshier <steve@moshier.net>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* expm1l.c
+ *
+ * Exponential function, minus 1
+ * Long double precision
+ *
+ *
+ * SYNOPSIS:
+ *
+ * long double x, y, expm1l();
+ *
+ * y = expm1l( x );
+ *
+ *
+ *
+ * DESCRIPTION:
+ *
+ * Returns e (2.71828...) raised to the x power, minus 1.
+ *
+ * Range reduction is accomplished by separating the argument
+ * into an integer k and fraction f such that
+ *
+ * x k f
+ * e = 2 e.
+ *
+ * An expansion x + .5 x^2 + x^3 R(x) approximates exp(f) - 1
+ * in the basic range [-0.5 ln 2, 0.5 ln 2].
+ *
+ *
+ * ACCURACY:
+ *
+ * Relative error:
+ * arithmetic domain # trials peak rms
+ * IEEE -45,+MAXLOG 200,000 1.2e-19 2.5e-20
+ *
+ * ERROR MESSAGES:
+ *
+ * message condition value returned
+ * expm1l overflow x > MAXLOG MAXNUM
+ *
+ */
+
+#include <openlibm_math.h>
+
+static const long double MAXLOGL = 1.1356523406294143949492E4L;
+
+/* exp(x) - 1 = x + 0.5 x^2 + x^3 P(x)/Q(x)
+ -.5 ln 2 < x < .5 ln 2
+ Theoretical peak relative error = 3.4e-22 */
+
+static const long double
+ P0 = -1.586135578666346600772998894928250240826E4L,
+ P1 = 2.642771505685952966904660652518429479531E3L,
+ P2 = -3.423199068835684263987132888286791620673E2L,
+ P3 = 1.800826371455042224581246202420972737840E1L,
+ P4 = -5.238523121205561042771939008061958820811E-1L,
+
+ Q0 = -9.516813471998079611319047060563358064497E4L,
+ Q1 = 3.964866271411091674556850458227710004570E4L,
+ Q2 = -7.207678383830091850230366618190187434796E3L,
+ Q3 = 7.206038318724600171970199625081491823079E2L,
+ Q4 = -4.002027679107076077238836622982900945173E1L,
+ /* Q5 = 1.000000000000000000000000000000000000000E0 */
+
+/* C1 + C2 = ln 2 */
+C1 = 6.93145751953125E-1L,
+C2 = 1.428606820309417232121458176568075500134E-6L,
+/* ln 2^-65 */
+minarg = -4.5054566736396445112120088E1L;
+static const long double huge = 0x1p10000L;
+
+long double
+expm1l(long double x)
+{
+long double px, qx, xx;
+int k;
+
+/* Overflow. */
+if (x > MAXLOGL)
+ return (huge*huge); /* overflow */
+
+if (x == 0.0)
+ return x;
+
+/* Minimum value. */
+if (x < minarg)
+ return -1.0L;
+
+xx = C1 + C2;
+
+/* Express x = ln 2 (k + remainder), remainder not exceeding 1/2. */
+px = floorl (0.5 + x / xx);
+k = px;
+/* remainder times ln 2 */
+x -= px * C1;
+x -= px * C2;
+
+/* Approximate exp(remainder ln 2). */
+px = (((( P4 * x
+ + P3) * x
+ + P2) * x
+ + P1) * x
+ + P0) * x;
+
+qx = (((( x
+ + Q4) * x
+ + Q3) * x
+ + Q2) * x
+ + Q1) * x
+ + Q0;
+
+xx = x * x;
+qx = x + (0.5 * xx + xx * px / qx);
+
+/* exp(x) = exp(k ln 2) exp(remainder ln 2) = 2^k exp(remainder ln 2).
+ We have qx = exp(remainder ln 2) - 1, so
+ exp(x) - 1 = 2^k (qx + 1) - 1 = 2^k qx + 2^k - 1. */
+px = ldexpl(1.0L, k);
+x = px * qx + (px - 1.0);
+return x;
+}
--- /dev/null
+/* @(#)s_floor.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/*
+ * floorl(x)
+ * Return x rounded toward -inf to integral value
+ * Method:
+ * Bit twiddling.
+ * Exception:
+ * Inexact flag raised if x not equal to floor(x).
+ */
+
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+static const long double huge = 1.0e4930L;
+
+long double
+floorl(long double x)
+{
+ int32_t i1,jj0;
+ u_int32_t i,j,se,i0,sx;
+ GET_LDOUBLE_WORDS(se,i0,i1,x);
+ sx = (se>>15)&1;
+ jj0 = (se&0x7fff)-0x3fff;
+ if(jj0<31) {
+ if(jj0<0) { /* raise inexact if x != 0 */
+ if(huge+x>0.0) {
+ if(sx==0)
+ return 0.0L;
+ else if(((se&0x7fff)|i0|i1)!=0)
+ return -1.0L;
+ }
+ } else {
+ i = (0x7fffffff)>>jj0;
+ if(((i0&i)|i1)==0) return x; /* x is integral */
+ if(huge+x>0.0) { /* raise inexact flag */
+ if(sx) {
+ if (jj0>0 && (i0+(0x80000000>>jj0))>i0)
+ i0 += (0x80000000)>>jj0;
+ else
+ {
+ i = 0x7fffffff;
+ ++se;
+ }
+ }
+ i0 &= (~i); i1=0;
+ }
+ }
+ } else if (jj0>62) {
+ if(jj0==0x4000) return x+x; /* inf or NaN */
+ else return x; /* x is integral */
+ } else {
+ i = ((u_int32_t)(0xffffffff))>>(jj0-31);
+ if((i1&i)==0) return x; /* x is integral */
+ if(huge+x>0.0) { /* raise inexact flag */
+ if(sx) {
+ if(jj0==31) i0+=1;
+ else {
+ j = i1+(1<<(63-jj0));
+ if(j<i1) i0 +=1 ; /* got a carry */
+ i1=j;
+ }
+ }
+ i1 &= (~i);
+ }
+ }
+ SET_LDOUBLE_WORDS(x,se,i0,i1);
+ return x;
+}
--- /dev/null
+/* $OpenBSD: s_log1pl.c,v 1.3 2013/11/12 20:35:19 martynas Exp $ */
+
+/*
+ * Copyright (c) 2008 Stephen L. Moshier <steve@moshier.net>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* log1pl.c
+ *
+ * Relative error logarithm
+ * Natural logarithm of 1+x, long double precision
+ *
+ *
+ *
+ * SYNOPSIS:
+ *
+ * long double x, y, log1pl();
+ *
+ * y = log1pl( x );
+ *
+ *
+ *
+ * DESCRIPTION:
+ *
+ * Returns the base e (2.718...) logarithm of 1+x.
+ *
+ * The argument 1+x is separated into its exponent and fractional
+ * parts. If the exponent is between -1 and +1, the logarithm
+ * of the fraction is approximated by
+ *
+ * log(1+x) = x - 0.5 x^2 + x^3 P(x)/Q(x).
+ *
+ * Otherwise, setting z = 2(x-1)/x+1),
+ *
+ * log(x) = z + z^3 P(z)/Q(z).
+ *
+ *
+ *
+ * ACCURACY:
+ *
+ * Relative error:
+ * arithmetic domain # trials peak rms
+ * IEEE -1.0, 9.0 100000 8.2e-20 2.5e-20
+ *
+ * ERROR MESSAGES:
+ *
+ * log singularity: x-1 = 0; returns -INFINITY
+ * log domain: x-1 < 0; returns NAN
+ */
+
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+/* Coefficients for log(1+x) = x - x^2 / 2 + x^3 P(x)/Q(x)
+ * 1/sqrt(2) <= x < sqrt(2)
+ * Theoretical peak relative error = 2.32e-20
+ */
+
+static long double P[] = {
+ 4.5270000862445199635215E-5L,
+ 4.9854102823193375972212E-1L,
+ 6.5787325942061044846969E0L,
+ 2.9911919328553073277375E1L,
+ 6.0949667980987787057556E1L,
+ 5.7112963590585538103336E1L,
+ 2.0039553499201281259648E1L,
+};
+static long double Q[] = {
+/* 1.0000000000000000000000E0,*/
+ 1.5062909083469192043167E1L,
+ 8.3047565967967209469434E1L,
+ 2.2176239823732856465394E2L,
+ 3.0909872225312059774938E2L,
+ 2.1642788614495947685003E2L,
+ 6.0118660497603843919306E1L,
+};
+
+/* Coefficients for log(x) = z + z^3 P(z^2)/Q(z^2),
+ * where z = 2(x-1)/(x+1)
+ * 1/sqrt(2) <= x < sqrt(2)
+ * Theoretical peak relative error = 6.16e-22
+ */
+
+static long double R[4] = {
+ 1.9757429581415468984296E-3L,
+-7.1990767473014147232598E-1L,
+ 1.0777257190312272158094E1L,
+-3.5717684488096787370998E1L,
+};
+static long double S[4] = {
+/* 1.00000000000000000000E0L,*/
+-2.6201045551331104417768E1L,
+ 1.9361891836232102174846E2L,
+-4.2861221385716144629696E2L,
+};
+static const long double C1 = 6.9314575195312500000000E-1L;
+static const long double C2 = 1.4286068203094172321215E-6L;
+
+#define SQRTH 0.70710678118654752440L
+
+long double
+log1pl(long double xm1)
+{
+long double x, y, z;
+int e;
+
+if( isnan(xm1) )
+ return(xm1);
+if( xm1 == INFINITY )
+ return(xm1);
+if(xm1 == 0.0)
+ return(xm1);
+
+x = xm1 + 1.0L;
+
+/* Test for domain errors. */
+if( x <= 0.0L )
+ {
+ if( x == 0.0L )
+ return( -INFINITY );
+ else
+ return( NAN );
+ }
+
+/* Separate mantissa from exponent.
+ Use frexp so that denormal numbers will be handled properly. */
+x = frexpl( x, &e );
+
+/* logarithm using log(x) = z + z^3 P(z)/Q(z),
+ where z = 2(x-1)/x+1) */
+if( (e > 2) || (e < -2) )
+{
+if( x < SQRTH )
+ { /* 2( 2x-1 )/( 2x+1 ) */
+ e -= 1;
+ z = x - 0.5L;
+ y = 0.5L * z + 0.5L;
+ }
+else
+ { /* 2 (x-1)/(x+1) */
+ z = x - 0.5L;
+ z -= 0.5L;
+ y = 0.5L * x + 0.5L;
+ }
+x = z / y;
+z = x*x;
+z = x * ( z * __polevll( z, R, 3 ) / __p1evll( z, S, 3 ) );
+z = z + e * C2;
+z = z + x;
+z = z + e * C1;
+return( z );
+}
+
+
+/* logarithm using log(1+x) = x - .5x**2 + x**3 P(x)/Q(x) */
+
+if( x < SQRTH )
+ {
+ e -= 1;
+ if (e != 0)
+ x = 2.0 * x - 1.0L;
+ else
+ x = xm1;
+ }
+else
+ {
+ if (e != 0)
+ x = x - 1.0L;
+ else
+ x = xm1;
+ }
+z = x*x;
+y = x * ( z * __polevll( x, P, 6 ) / __p1evll( x, Q, 6 ) );
+y = y + e * C2;
+z = y - 0.5 * z;
+z = z + x;
+z = z + e * C1;
+return( z );
+}
--- /dev/null
+/* @(#)s_modf.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/*
+ * modfl(long double x, long double *iptr)
+ * return fraction part of x, and return x's integral part in *iptr.
+ * Method:
+ * Bit twiddling.
+ *
+ * Exception:
+ * No exception.
+ */
+
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+static const long double one = 1.0;
+
+long double
+modfl(long double x, long double *iptr)
+{
+ int32_t i0,i1,jj0;
+ u_int32_t i,se;
+ GET_LDOUBLE_WORDS(se,i0,i1,x);
+ jj0 = (se&0x7fff)-0x3fff; /* exponent of x */
+ if(jj0<32) { /* integer part in high x */
+ if(jj0<0) { /* |x|<1 */
+ SET_LDOUBLE_WORDS(*iptr,se&0x8000,0,0); /* *iptr = +-0 */
+ return x;
+ } else {
+ i = (0x7fffffff)>>jj0;
+ if(((i0&i)|i1)==0) { /* x is integral */
+ *iptr = x;
+ SET_LDOUBLE_WORDS(x,se&0x8000,0,0); /* return +-0 */
+ return x;
+ } else {
+ SET_LDOUBLE_WORDS(*iptr,se,i0&(~i),0);
+ return x - *iptr;
+ }
+ }
+ } else if (jj0>63) { /* no fraction part */
+ *iptr = x*one;
+ /* We must handle NaNs separately. */
+ if (jj0 == 0x4000 && ((i0 & 0x7fffffff) | i1))
+ return x*one;
+ SET_LDOUBLE_WORDS(x,se&0x8000,0,0); /* return +-0 */
+ return x;
+ } else { /* fraction part in low x */
+ i = ((u_int32_t)(0x7fffffff))>>(jj0-32);
+ if((i1&i)==0) { /* x is integral */
+ *iptr = x;
+ SET_LDOUBLE_WORDS(x,se&0x8000,0,0); /* return +-0 */
+ return x;
+ } else {
+ SET_LDOUBLE_WORDS(*iptr,se,i0,i1&(~i));
+ return x - *iptr;
+ }
+ }
+}
--- /dev/null
+/*-
+ * Copyright (c) 2007 David Schultz
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: src/lib/msun/ld80/s_nanl.c,v 1.2 2007/12/18 23:46:31 das Exp $
+ */
+
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+OLM_DLLEXPORT long double
+nanl(const char *s)
+{
+ union {
+ union IEEEl2bits ieee;
+ uint32_t bits[3];
+ } u;
+
+ __scan_nan(u.bits, 3, s);
+ u.ieee.bits.exp = 0x7fff;
+ u.ieee.bits.manh |= 0xc0000000; /* make it a quiet NaN */
+ return (u.ieee.e);
+}
--- /dev/null
+/* @(#)s_nextafter.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/* IEEE functions
+ * nextafterl(x,y)
+ * return the next machine floating-point number of x in the
+ * direction toward y.
+ * Special cases:
+ */
+
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+long double
+nextafterl(long double x, long double y)
+{
+ int32_t hx,hy,ix,iy;
+ u_int32_t lx,ly,esx,esy;
+
+ GET_LDOUBLE_WORDS(esx,hx,lx,x);
+ GET_LDOUBLE_WORDS(esy,hy,ly,y);
+ ix = esx&0x7fff; /* |x| */
+ iy = esy&0x7fff; /* |y| */
+
+ if (((ix==0x7fff)&&((hx&0x7fffffff|lx)!=0)) || /* x is nan */
+ ((iy==0x7fff)&&((hy&0x7fffffff|ly)!=0))) /* y is nan */
+ return x+y;
+ if(x==y) return y; /* x=y, return y */
+ if((ix|hx|lx)==0) { /* x == 0 */
+ volatile long double u;
+ SET_LDOUBLE_WORDS(x,esy&0x8000,0,1);/* return +-minsubnormal */
+ u = x;
+ u = u * u; /* raise underflow flag */
+ return x;
+ }
+ if(esx<0x8000) { /* x > 0 */
+ if(ix>iy||((ix==iy) && (hx>hy||((hx==hy)&&(lx>ly))))) {
+ /* x > y, x -= ulp */
+ if(lx==0) {
+ if ((hx&0x7fffffff)==0) esx -= 1;
+ hx = (hx - 1) | (hx & 0x80000000);
+ }
+ lx -= 1;
+ } else { /* x < y, x += ulp */
+ lx += 1;
+ if(lx==0) {
+ hx = (hx + 1) | (hx & 0x80000000);
+ if ((hx&0x7fffffff)==0) esx += 1;
+ }
+ }
+ } else { /* x < 0 */
+ if(esy>=0||(ix>iy||((ix==iy)&&(hx>hy||((hx==hy)&&(lx>ly)))))){
+ /* x < y, x -= ulp */
+ if(lx==0) {
+ if ((hx&0x7fffffff)==0) esx -= 1;
+ hx = (hx - 1) | (hx & 0x80000000);
+ }
+ lx -= 1;
+ } else { /* x > y, x += ulp */
+ lx += 1;
+ if(lx==0) {
+ hx = (hx + 1) | (hx & 0x80000000);
+ if ((hx&0x7fffffff)==0) esx += 1;
+ }
+ }
+ }
+ esy = esx&0x7fff;
+ if(esy==0x7fff) return x+x; /* overflow */
+ if(esy==0) {
+ volatile long double u = x*x; /* underflow */
+ if(u==x) {
+ SET_LDOUBLE_WORDS(x,esx,hx,lx);
+ return x;
+ }
+ }
+ SET_LDOUBLE_WORDS(x,esx,hx,lx);
+ return x;
+}
+
+//__strong_alias(nexttowardl, nextafterl);
--- /dev/null
+/* @(#)s_nextafter.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/* IEEE functions
+ * nexttoward(x,y)
+ * return the next machine floating-point number of x in the
+ * direction toward y.
+ * Special cases:
+ */
+
+#include <float.h>
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+double
+nexttoward(double x, long double y)
+{
+ int32_t hx,ix,iy;
+ u_int32_t lx,hy,ly,esy;
+
+ EXTRACT_WORDS(hx,lx,x);
+ GET_LDOUBLE_WORDS(esy,hy,ly,y);
+ ix = hx&0x7fffffff; /* |x| */
+ iy = esy&0x7fff; /* |y| */
+
+ if(((ix>=0x7ff00000)&&((ix-0x7ff00000)|lx)!=0) || /* x is nan */
+ ((iy>=0x7fff)&&(hy|ly)!=0)) /* y is nan */
+ return x+y;
+ if((long double) x==y) return y; /* x=y, return y */
+ if((ix|lx)==0) { /* x == 0 */
+ volatile double u;
+ INSERT_WORDS(x,(esy&0x8000)<<16,1); /* return +-minsub */
+ u = x;
+ u = u * u; /* raise underflow flag */
+ return x;
+ }
+ if(hx>=0) { /* x > 0 */
+ if (esy>=0x8000||((ix>>20)&0x7ff)>iy-0x3c00
+ || (((ix>>20)&0x7ff)==iy-0x3c00
+ && (((hx<<11)|(lx>>21))>(hy&0x7fffffff)
+ || (((hx<<11)|(lx>>21))==(hy&0x7fffffff)
+ && (lx<<11)>ly)))) { /* x > y, x -= ulp */
+ if(lx==0) hx -= 1;
+ lx -= 1;
+ } else { /* x < y, x += ulp */
+ lx += 1;
+ if(lx==0) hx += 1;
+ }
+ } else { /* x < 0 */
+ if (esy<0x8000||((ix>>20)&0x7ff)>iy-0x3c00
+ || (((ix>>20)&0x7ff)==iy-0x3c00
+ && (((hx<<11)|(lx>>21))>(hy&0x7fffffff)
+ || (((hx<<11)|(lx>>21))==(hy&0x7fffffff)
+ && (lx<<11)>ly)))) {/* x < y, x -= ulp */
+ if(lx==0) hx -= 1;
+ lx -= 1;
+ } else { /* x > y, x += ulp */
+ lx += 1;
+ if(lx==0) hx += 1;
+ }
+ }
+ hy = hx&0x7ff00000;
+ if(hy>=0x7ff00000) {
+ x = x+x; /* overflow */
+ return x;
+ }
+ if(hy<0x00100000) {
+ volatile double u = x*x; /* underflow */
+ if(u==x) {
+ INSERT_WORDS(x,hx,lx);
+ return x;
+ }
+ }
+ INSERT_WORDS(x,hx,lx);
+ return x;
+}
--- /dev/null
+/* @(#)s_nextafter.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include <float.h>
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+float
+nexttowardf(float x, long double y)
+{
+ int32_t hx,ix,iy;
+ u_int32_t hy,ly,esy;
+
+ GET_FLOAT_WORD(hx,x);
+ GET_LDOUBLE_WORDS(esy,hy,ly,y);
+ ix = hx&0x7fffffff; /* |x| */
+ iy = esy&0x7fff; /* |y| */
+
+ if((ix>0x7f800000) || /* x is nan */
+ (iy>=0x7fff&&((hy|ly)!=0))) /* y is nan */
+ return x+y;
+ if((long double) x==y) return y; /* x=y, return y */
+ if(ix==0) { /* x == 0 */
+ volatile float u;
+ SET_FLOAT_WORD(x,((esy&0x8000)<<16)|1);/* return +-minsub*/
+ u = x;
+ u = u * u; /* raise underflow flag */
+ return x;
+ }
+ if(hx>=0) { /* x > 0 */
+ if(esy>=0x8000||((ix>>23)&0xff)>iy-0x3f80
+ || (((ix>>23)&0xff)==iy-0x3f80
+ && ((ix&0x7fffff)<<8)>(hy&0x7fffffff))) {/* x > y, x -= ulp */
+ hx -= 1;
+ } else { /* x < y, x += ulp */
+ hx += 1;
+ }
+ } else { /* x < 0 */
+ if(esy<0x8000||((ix>>23)&0xff)>iy-0x3f80
+ || (((ix>>23)&0xff)==iy-0x3f80
+ && ((ix&0x7fffff)<<8)>(hy&0x7fffffff))) {/* x < y, x -= ulp */
+ hx -= 1;
+ } else { /* x > y, x += ulp */
+ hx += 1;
+ }
+ }
+ hy = hx&0x7f800000;
+ if(hy>=0x7f800000) {
+ x = x+x; /* overflow */
+ return x;
+ }
+ if(hy<0x00800000) {
+ volatile float u = x*x; /* underflow */
+ }
+ SET_FLOAT_WORD(x,hx);
+ return x;
+}
--- /dev/null
+/* @(#)e_fmod.c 1.3 95/01/18 */
+/*-
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunSoft, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include <sys/types.h>
+#include <machine/ieee.h>
+
+#include <float.h>
+#include <openlibm_math.h>
+#include <stdint.h>
+
+#include "math_private.h"
+
+#define BIAS (LDBL_MAX_EXP - 1)
+
+/*
+ * These macros add and remove an explicit integer bit in front of the
+ * fractional mantissa, if the architecture doesn't have such a bit by
+ * default already.
+ */
+#ifdef LDBL_IMPLICIT_NBIT
+#define LDBL_NBIT 0
+#define SET_NBIT(hx) ((hx) | (1ULL << LDBL_MANH_SIZE))
+#define HFRAC_BITS EXT_FRACHBITS
+#else
+#define LDBL_NBIT 0x80000000
+#define SET_NBIT(hx) (hx)
+#define HFRAC_BITS (EXT_FRACHBITS - 1)
+#endif
+
+#define MANL_SHIFT (EXT_FRACLBITS - 1)
+
+static const long double Zero[] = {0.0L, -0.0L};
+
+/*
+ * Return the IEEE remainder and set *quo to the last n bits of the
+ * quotient, rounded to the nearest integer. We choose n=31 because
+ * we wind up computing all the integer bits of the quotient anyway as
+ * a side-effect of computing the remainder by the shift and subtract
+ * method. In practice, this is far more bits than are needed to use
+ * remquo in reduction algorithms.
+ *
+ * Assumptions:
+ * - The low part of the mantissa fits in a manl_t exactly.
+ * - The high part of the mantissa fits in an int64_t with enough room
+ * for an explicit integer bit in front of the fractional bits.
+ */
+long double
+remquol(long double x, long double y, int *quo)
+{
+ int64_t hx,hz; /* We need a carry bit even if LDBL_MANH_SIZE is 32. */
+ uint32_t hy;
+ uint32_t lx,ly,lz;
+ uint32_t esx, esy;
+ int ix,iy,n,q,sx,sxy;
+
+ GET_LDOUBLE_WORDS(esx,hx,lx,x);
+ GET_LDOUBLE_WORDS(esy,hy,ly,y);
+ sx = esx & 0x8000;
+ sxy = sx ^ (esy & 0x8000);
+ esx &= 0x7fff; /* |x| */
+ esy &= 0x7fff; /* |y| */
+ SET_LDOUBLE_EXP(x,esx);
+ SET_LDOUBLE_EXP(y,esy);
+
+ /* purge off exception values */
+ if((esy|hy|ly)==0 || /* y=0 */
+ (esx == BIAS + LDBL_MAX_EXP) || /* or x not finite */
+ (esy == BIAS + LDBL_MAX_EXP &&
+ ((hy&~LDBL_NBIT)|ly)!=0)) /* or y is NaN */
+ return (x*y)/(x*y);
+ if(esx<=esy) {
+ if((esx<esy) ||
+ (hx<=hy &&
+ (hx<hy ||
+ lx<ly))) {
+ q = 0;
+ goto fixup; /* |x|<|y| return x or x-y */
+ }
+ if(hx==hy && lx==ly) {
+ *quo = 1;
+ return Zero[sx!=0]; /* |x|=|y| return x*0*/
+ }
+ }
+
+ /* determine ix = ilogb(x) */
+ if(esx == 0) { /* subnormal x */
+ x *= 0x1.0p512;
+ GET_LDOUBLE_WORDS(esx,hx,lx,x);
+ ix = esx - (BIAS + 512);
+ } else {
+ ix = esx - BIAS;
+ }
+
+ /* determine iy = ilogb(y) */
+ if(esy == 0) { /* subnormal y */
+ y *= 0x1.0p512;
+ GET_LDOUBLE_WORDS(esy,hy,ly,y);
+ iy = esy - (BIAS + 512);
+ } else {
+ iy = esy - BIAS;
+ }
+
+ /* set up {hx,lx}, {hy,ly} and align y to x */
+ hx = SET_NBIT(hx);
+ lx = SET_NBIT(lx);
+
+ /* fix point fmod */
+ n = ix - iy;
+ q = 0;
+
+ while(n--) {
+ hz=hx-hy;lz=lx-ly; if(lx<ly) hz -= 1;
+ if(hz<0){hx = hx+hx+(lx>>MANL_SHIFT); lx = lx+lx;}
+ else {hx = hz+hz+(lz>>MANL_SHIFT); lx = lz+lz; q++;}
+ q <<= 1;
+ }
+ hz=hx-hy;lz=lx-ly; if(lx<ly) hz -= 1;
+ if(hz>=0) {hx=hz;lx=lz;q++;}
+
+ /* convert back to floating value and restore the sign */
+ if((hx|lx)==0) { /* return sign(x)*0 */
+ *quo = (sxy ? -q : q);
+ return Zero[sx!=0];
+ }
+ while(hx<(1ULL<<HFRAC_BITS)) { /* normalize x */
+ hx = hx+hx+(lx>>MANL_SHIFT); lx = lx+lx;
+ iy -= 1;
+ }
+ if (iy < LDBL_MIN_EXP) {
+ esx = (iy + BIAS + 512) & 0x7fff;
+ SET_LDOUBLE_WORDS(x,esx,hx,lx);
+ x *= 0x1p-512;
+ GET_LDOUBLE_WORDS(esx,hx,lx,x);
+ } else {
+ esx = (iy + BIAS) & 0x7fff;
+ }
+ SET_LDOUBLE_WORDS(x,esx,hx,lx);
+fixup:
+ y = fabsl(y);
+ if (y < LDBL_MIN * 2) {
+ if (x+x>y || (x+x==y && (q & 1))) {
+ q++;
+ x-=y;
+ }
+ } else if (x>0.5*y || (x==0.5*y && (q & 1))) {
+ q++;
+ x-=y;
+ }
+
+ GET_LDOUBLE_EXP(esx,x);
+ esx ^= sx;
+ SET_LDOUBLE_EXP(x,esx);
+
+ q &= 0x7fffffff;
+ *quo = (sxy ? -q : q);
+ return x;
+}
--- /dev/null
+/* @(#)s_tanh.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/* tanhl(x)
+ * Return the Hyperbolic Tangent of x
+ *
+ * Method :
+ * x -x
+ * e - e
+ * 0. tanhl(x) is defined to be -----------
+ * x -x
+ * e + e
+ * 1. reduce x to non-negative by tanhl(-x) = -tanhl(x).
+ * 2. 0 <= x <= 2**-55 : tanhl(x) := x*(one+x)
+ * -t
+ * 2**-55 < x <= 1 : tanhl(x) := -----; t = expm1l(-2x)
+ * t + 2
+ * 2
+ * 1 <= x <= 23.0 : tanhl(x) := 1- ----- ; t=expm1l(2x)
+ * t + 2
+ * 23.0 < x <= INF : tanhl(x) := 1.
+ *
+ * Special cases:
+ * tanhl(NaN) is NaN;
+ * only tanhl(0)=0 is exact for finite argument.
+ */
+
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+static const long double one=1.0, two=2.0, tiny = 1.0e-4900L;
+
+long double
+tanhl(long double x)
+{
+ long double t,z;
+ int32_t se;
+ u_int32_t jj0,jj1,ix;
+
+ /* High word of |x|. */
+ GET_LDOUBLE_WORDS(se,jj0,jj1,x);
+ ix = se&0x7fff;
+
+ /* x is INF or NaN */
+ if(ix==0x7fff) {
+ /* for NaN it's not important which branch: tanhl(NaN) = NaN */
+ if (se&0x8000) return one/x-one; /* tanhl(-inf)= -1; */
+ else return one/x+one; /* tanhl(+inf)=+1 */
+ }
+
+ /* |x| < 23 */
+ if (ix < 0x4003 || (ix == 0x4003 && jj0 < 0xb8000000u)) {/* |x|<23 */
+ if ((ix|jj0|jj1) == 0)
+ return x; /* x == +- 0 */
+ if (ix<0x3fc8) /* |x|<2**-55 */
+ return x*(one+tiny); /* tanh(small) = small */
+ if (ix>=0x3fff) { /* |x|>=1 */
+ t = expm1l(two*fabsl(x));
+ z = one - two/(t+two);
+ } else {
+ t = expm1l(-two*fabsl(x));
+ z= -t/(t+two);
+ }
+ /* |x| > 23, return +-1 */
+ } else {
+ z = one - tiny; /* raised inexact flag */
+ }
+ return (se&0x8000)? -z: z;
+}
--- /dev/null
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ *
+ * From: @(#)s_floor.c 5.1 93/09/24
+ */
+
+/*
+ * truncl(x)
+ * Return x rounded toward 0 to integral value
+ * Method:
+ * Bit twiddling.
+ * Exception:
+ * Inexact flag raised if x not equal to truncl(x).
+ */
+
+#include <sys/types.h>
+//#include <machine/ieee.h>
+
+#include <float.h>
+#include <openlibm_math.h>
+#include <stdint.h>
+
+#include "math_private.h"
+
+#ifdef LDBL_IMPLICIT_NBIT
+#define MANH_SIZE (EXT_FRACHBITS + 1)
+#else
+#define MANH_SIZE EXT_FRACHBITS
+#endif
+
+static const long double huge = 1.0e300;
+static const float zero[] = { 0.0, -0.0 };
+
+long double
+truncl(long double x)
+{
+ int e, es;
+ uint32_t ix0, ix1;
+
+ GET_LDOUBLE_WORDS(es,ix0,ix1,x);
+ e = (es&0x7fff) - LDBL_MAX_EXP + 1;
+
+ if (e < MANH_SIZE - 1) {
+ if (e < 0) { /* raise inexact if x != 0 */
+ if (huge + x > 0.0)
+ return (zero[(es&0x8000)!=0]);
+ } else {
+ uint64_t m = ((1llu << MANH_SIZE) - 1) >> (e + 1);
+ if (((ix0 & m) | ix1) == 0)
+ return (x); /* x is integral */
+ if (huge + x > 0.0) { /* raise inexact flag */
+ ix0 &= ~m;
+ ix1 = 0;
+ }
+ }
+ } else if (e < LDBL_MANT_DIG - 1) {
+ uint64_t m = (uint64_t)-1 >> (64 - LDBL_MANT_DIG + e + 1);
+ if ((ix1 & m) == 0)
+ return (x); /* x is integral */
+ if (huge + x > 0.0) /* raise inexact flag */
+ ix1 &= ~m;
+ }
+ SET_LDOUBLE_WORDS(x,es,ix0,ix1);
+ return (x);
+}
--- /dev/null
+$(CUR_SRCS) = fenv.c
--- /dev/null
+/*-
+ * Copyright (c) 2004-2011 David Schultz <das@FreeBSD.ORG>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _FENV_H_
+#error "This file is meant to be included only by <fenv.h>."
+#endif
+
+/*
+ * This file implements the functionality of <fenv.h> on platforms that
+ * lack an FPU and use softfloat in libc for floating point. To use it,
+ * you must write an <fenv.h> that provides the following:
+ *
+ * - a typedef for fenv_t, which may be an integer or struct type
+ * - a typedef for fexcept_t (XXX This file assumes fexcept_t is a
+ * simple integer type containing the exception mask.)
+ * - definitions of FE_* constants for the five exceptions and four
+ * rounding modes in IEEE 754, as described in fenv(3)
+ * - a definition, and the corresponding external symbol, for FE_DFL_ENV
+ * - a macro __set_env(env, flags, mask, rnd), which sets the given fenv_t
+ * from the exception flags, mask, and rounding mode
+ * - macros __env_flags(env), __env_mask(env), and __env_round(env), which
+ * extract fields from an fenv_t
+ * - a definition of __fenv_static
+ *
+ * If the architecture supports an optional FPU, it's recommended that you
+ * define fenv_t and fexcept_t to match the hardware ABI. Otherwise, it
+ * doesn't matter how you define them.
+ */
+
+extern int __softfloat_float_exception_flags;
+extern int __softfloat_float_exception_mask;
+extern int __softfloat_float_rounding_mode;
+void __softfloat_float_raise(int);
+
+__fenv_static inline int
+feclearexcept(int __excepts)
+{
+
+ __softfloat_float_exception_flags &= ~__excepts;
+ return (0);
+}
+
+__fenv_static inline int
+fegetexceptflag(fexcept_t *__flagp, int __excepts)
+{
+
+ *__flagp = __softfloat_float_exception_flags & __excepts;
+ return (0);
+}
+
+__fenv_static inline int
+fesetexceptflag(const fexcept_t *__flagp, int __excepts)
+{
+
+ __softfloat_float_exception_flags &= ~__excepts;
+ __softfloat_float_exception_flags |= *__flagp & __excepts;
+ return (0);
+}
+
+__fenv_static inline int
+feraiseexcept(int __excepts)
+{
+
+ __softfloat_float_raise(__excepts);
+ return (0);
+}
+
+__fenv_static inline int
+fetestexcept(int __excepts)
+{
+
+ return (__softfloat_float_exception_flags & __excepts);
+}
+
+__fenv_static inline int
+fegetround(void)
+{
+
+ return (__softfloat_float_rounding_mode);
+}
+
+__fenv_static inline int
+fesetround(int __round)
+{
+
+ __softfloat_float_rounding_mode = __round;
+ return (0);
+}
+
+__fenv_static inline int
+fegetenv(fenv_t *__envp)
+{
+
+ __set_env(*__envp, __softfloat_float_exception_flags,
+ __softfloat_float_exception_mask, __softfloat_float_rounding_mode);
+ return (0);
+}
+
+__fenv_static inline int
+feholdexcept(fenv_t *__envp)
+{
+ fenv_t __env;
+
+ fegetenv(__envp);
+ __softfloat_float_exception_flags = 0;
+ __softfloat_float_exception_mask = 0;
+ return (0);
+}
+
+__fenv_static inline int
+fesetenv(const fenv_t *__envp)
+{
+
+ __softfloat_float_exception_flags = __env_flags(*__envp);
+ __softfloat_float_exception_mask = __env_mask(*__envp);
+ __softfloat_float_rounding_mode = __env_round(*__envp);
+ return (0);
+}
+
+__fenv_static inline int
+feupdateenv(const fenv_t *__envp)
+{
+ int __oflags = __softfloat_float_exception_flags;
+
+ fesetenv(__envp);
+ feraiseexcept(__oflags);
+ return (0);
+}
+
+#if __BSD_VISIBLE
+
+/* We currently provide no external definitions of the functions below. */
+
+__fenv_static inline int
+feenableexcept(int __mask)
+{
+ int __omask = __softfloat_float_exception_mask;
+
+ __softfloat_float_exception_mask |= __mask;
+ return (__omask);
+}
+
+__fenv_static inline int
+fedisableexcept(int __mask)
+{
+ int __omask = __softfloat_float_exception_mask;
+
+ __softfloat_float_exception_mask &= ~__mask;
+ return (__omask);
+}
+
+__fenv_static inline int
+fegetexcept(void)
+{
+
+ return (__softfloat_float_exception_mask);
+}
+
+#endif /* __BSD_VISIBLE */
\ No newline at end of file
--- /dev/null
+/*-
+ * Copyright (c) 2004 David Schultz <das@FreeBSD.ORG>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#define __fenv_static
+#include "openlibm_fenv.h"
+
+#ifdef __GNUC_GNU_INLINE__
+#error "This file must be compiled with C99 'inline' semantics"
+#endif
+
+/*
+ * Hopefully the system ID byte is immutable, so it's valid to use
+ * this as a default environment.
+ */
+const fenv_t __fe_dfl_env = 0;
+
+#ifdef __mips_soft_float
+#define __set_env(env, flags, mask, rnd) env = ((flags) \
+ | (mask)<<_FPUSW_SHIFT \
+ | (rnd) << 24)
+#define __env_flags(env) ((env) & FE_ALL_EXCEPT)
+#define __env_mask(env) (((env) >> _FPUSW_SHIFT) \
+ & FE_ALL_EXCEPT)
+#define __env_round(env) (((env) >> 24) & _ROUND_MASK)
+#include "fenv-softfloat.h"
+#endif
+
+extern inline int feclearexcept(int __excepts);
+extern inline int fegetexceptflag(fexcept_t *__flagp, int __excepts);
+extern inline int fesetexceptflag(const fexcept_t *__flagp, int __excepts);
+extern inline int feraiseexcept(int __excepts);
+extern inline int fetestexcept(int __excepts);
+extern inline int fegetround(void);
+extern inline int fesetround(int __round);
+extern inline int fegetenv(fenv_t *__envp);
+extern inline int feholdexcept(fenv_t *__envp);
+extern inline int fesetenv(const fenv_t *__envp);
+extern inline int feupdateenv(const fenv_t *__envp);
+extern inline int feenableexcept(int __mask);
+extern inline int fedisableexcept(int __mask);
+extern inline int fegetexcept(void);
+
--- /dev/null
+exec_prefix=${prefix}
+includedir=${prefix}/include
+libdir=${exec_prefix}/lib
+
+Name: openlibm
+Version: ${version}
+URL: https://github.com/JuliaLang/openlibm
+Description: High quality system independent, open source libm.
+Cflags: -I${includedir}
+Libs: -L${libdir} -lopenlibm
--- /dev/null
+$(CUR_SRCS) = fenv.c
--- /dev/null
+/*-
+ * Copyright (c) 2004 David Schultz <das@FreeBSD.ORG>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#define __fenv_static
+#include <openlibm_fenv.h>
+
+#ifdef __GNUC_GNU_INLINE__
+#error "This file must be compiled with C99 'inline' semantics"
+#endif
+
+const fenv_t __fe_dfl_env = 0x00000000;
+
+extern inline int feclearexcept(int __excepts);
+extern inline int fegetexceptflag(fexcept_t *__flagp, int __excepts);
+extern inline int fesetexceptflag(const fexcept_t *__flagp, int __excepts);
+extern inline int feraiseexcept(int __excepts);
+extern inline int fetestexcept(int __excepts);
+extern inline int fegetround(void);
+extern inline int fesetround(int __round);
+extern inline int fegetenv(fenv_t *__envp);
+extern inline int feholdexcept(fenv_t *__envp);
+extern inline int fesetenv(const fenv_t *__envp);
+extern inline int feupdateenv(const fenv_t *__envp);
--- /dev/null
+$(CUR_SRCS) = common.c \
+ e_acos.c e_acosf.c e_acosh.c e_acoshf.c e_asin.c e_asinf.c \
+ e_atan2.c e_atan2f.c e_atanh.c e_atanhf.c e_cosh.c e_coshf.c e_exp.c \
+ e_expf.c e_fmod.c e_fmodf.c \
+ e_hypot.c e_hypotf.c e_j0.c e_j0f.c e_j1.c e_j1f.c \
+ e_jn.c e_jnf.c e_lgamma.c e_lgamma_r.c e_lgammaf.c e_lgammaf_r.c \
+ e_log.c e_log10.c e_log10f.c e_log2.c e_log2f.c e_logf.c \
+ e_pow.c e_powf.c e_remainder.c e_remainderf.c \
+ e_rem_pio2.c e_rem_pio2f.c \
+ e_sinh.c e_sinhf.c e_sqrt.c e_sqrtf.c \
+ k_cos.c k_exp.c k_expf.c k_rem_pio2.c k_sin.c k_tan.c \
+ k_cosf.c k_sinf.c k_tanf.c \
+ s_asinh.c s_asinhf.c s_atan.c s_atanf.c s_carg.c s_cargf.c \
+ s_cbrt.c s_cbrtf.c s_ceil.c s_ceilf.c \
+ s_copysign.c s_copysignf.c s_cos.c s_cosf.c \
+ s_csqrt.c s_csqrtf.c s_erf.c s_erff.c \
+ s_exp2.c s_exp2f.c s_expm1.c s_expm1f.c s_fabs.c s_fabsf.c s_fdim.c \
+ s_floor.c s_floorf.c s_fma.c s_fmaf.c \
+ s_fmax.c s_fmaxf.c s_fmin.c \
+ s_fminf.c s_fpclassify.c \
+ s_frexp.c s_frexpf.c s_ilogb.c s_ilogbf.c \
+ s_isinf.c s_isfinite.c s_isnormal.c s_isnan.c \
+ s_llrint.c s_llrintf.c s_llround.c s_llroundf.c \
+ s_log1p.c s_log1pf.c s_logb.c s_logbf.c s_lrint.c s_lrintf.c \
+ s_lround.c s_lroundf.c s_modf.c s_modff.c \
+ s_nearbyint.c s_nextafter.c s_nextafterf.c \
+ s_nexttowardf.c s_remquo.c s_remquof.c \
+ s_rint.c s_rintf.c s_round.c s_roundf.c \
+ s_scalbln.c s_scalbn.c s_scalbnf.c s_signbit.c \
+ s_signgam.c s_sin.c s_sincos.c \
+ s_sinf.c s_sincosf.c s_tan.c s_tanf.c s_tanh.c s_tanhf.c s_tgammaf.c \
+ s_trunc.c s_truncf.c s_cpow.c s_cpowf.c \
+ w_cabs.c w_cabsf.c
+
+ifneq ($(OS), WINNT)
+$(CUR_SRCS) += s_nan.c
+endif
+
+# Add in long double functions for x86, x64 and aarch64
+ifneq ($(filter $(ARCH),i387 amd64 aarch64),)
+# C99 long double functions
+$(CUR_SRCS) += s_copysignl.c s_fabsl.c s_llrintl.c s_lrintl.c s_modfl.c
+
+# If long double != double use these; otherwise, we alias the double versions.
+$(CUR_SRCS) += e_acosl.c e_asinl.c e_atan2l.c e_fmodl.c \
+ s_fmaxl.c s_fminl.c s_ilogbl.c \
+ e_hypotl.c e_lgammal.c e_remainderl.c e_sqrtl.c \
+ s_atanl.c s_ceill.c s_cosl.c s_cprojl.c \
+ s_csqrtl.c s_floorl.c s_fmal.c \
+ s_frexpl.c s_logbl.c s_nexttoward.c \
+ s_remquol.c s_roundl.c s_lroundl.c s_llroundl.c \
+ s_cpowl.c s_cargl.c \
+ s_sinl.c s_sincosl.c s_tanl.c s_truncl.c w_cabsl.c \
+ s_nextafterl.c s_rintl.c s_scalbnl.c polevll.c \
+ s_casinl.c s_ctanl.c \
+ s_cimagl.c s_conjl.c s_creall.c s_cacoshl.c s_catanhl.c s_casinhl.c \
+ s_catanl.c s_csinl.c s_cacosl.c s_cexpl.c s_csinhl.c s_ccoshl.c \
+ s_clogl.c s_ctanhl.c s_ccosl.c s_cbrtl.c
+endif
+
+# C99 complex functions
+$(CUR_SRCS) += s_ccosh.c s_ccoshf.c s_cexp.c s_cexpf.c \
+ s_cimag.c s_cimagf.c \
+ s_conj.c s_conjf.c \
+ s_cproj.c s_cprojf.c s_creal.c s_crealf.c \
+ s_csinh.c s_csinhf.c s_ctanh.c s_ctanhf.c \
+ s_cacos.c s_cacosf.c \
+ s_cacosh.c s_cacoshf.c \
+ s_casin.c s_casinf.c s_casinh.c s_casinhf.c \
+ s_catan.c s_catanf.c s_catanh.c s_catanhf.c \
+ s_clog.c s_clogf.c
--- /dev/null
+/*-
+ * Copyright (c) 2002, 2003 David Schultz <das@FreeBSD.ORG>
+ * Copyright (2) 2014 The FreeBSD Foundation
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: head/lib/libc/aarch64/_fpmath.h 281197 2015-04-07 09:52:14Z andrew $
+ */
+
+union IEEEl2bits {
+ long double e;
+ struct {
+ unsigned long manl :64;
+ unsigned long manh :48;
+ unsigned int exp :15;
+ unsigned int sign :1;
+ } bits;
+ /* TODO andrew: Check the packing here */
+ struct {
+ unsigned long manl :64;
+ unsigned long manh :48;
+ unsigned int expsign :16;
+ } xbits;
+};
+
+#define LDBL_NBIT 0
+#define LDBL_IMPLICIT_NBIT
+#define mask_nbit_l(u) ((void)0)
+
+#define LDBL_MANH_SIZE 48
+#define LDBL_MANL_SIZE 64
+
+#define LDBL_TO_ARRAY32(u, a) do { \
+ (a)[0] = (uint32_t)(u).bits.manl; \
+ (a)[1] = (uint32_t)((u).bits.manl >> 32); \
+ (a)[2] = (uint32_t)(u).bits.manh; \
+ (a)[3] = (uint32_t)((u).bits.manh >> 32); \
+} while(0)
--- /dev/null
+/*-
+ * Copyright (c) 2002, 2003 David Schultz <das@FreeBSD.ORG>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: src/lib/libc/amd64/_fpmath.h,v 1.7 2008/01/17 16:39:06 bde Exp $
+ */
+
+union IEEEl2bits {
+ long double e;
+ struct {
+ unsigned int manl :32;
+ unsigned int manh :32;
+ unsigned int exp :15;
+ unsigned int sign :1;
+ unsigned int junkl :16;
+ unsigned int junkh :32;
+ } bits;
+ struct {
+ unsigned long man :64;
+ unsigned int expsign :16;
+ unsigned long junk :48;
+ } xbits;
+};
+
+#define LDBL_NBIT 0x80000000
+#define mask_nbit_l(u) ((u).bits.manh &= ~LDBL_NBIT)
+
+#define LDBL_MANH_SIZE 32
+#define LDBL_MANL_SIZE 32
+
+#define LDBL_TO_ARRAY32(u, a) do { \
+ (a)[0] = (uint32_t)(u).bits.manl; \
+ (a)[1] = (uint32_t)(u).bits.manh; \
+} while (0)
--- /dev/null
+/*-
+ * Copyright (c) 1991, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Berkeley Software Design, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)cdefs.h 8.8 (Berkeley) 1/9/95
+ * $FreeBSD: src/sys/sys/cdefs.h,v 1.114 2011/02/18 21:44:53 nwhitehorn Exp $
+ */
+
+/* Do not redefine macros if the system provides them in sys/cdefs.h.
+ * The two macros correspond to different platforms. */
+#ifndef _BSD_CDEFS_H_
+#define _BSD_CDEFS_H_
+
+/*
+ * This code has been put in place to help reduce the addition of
+ * compiler specific defines in FreeBSD code. It helps to aid in
+ * having a compiler-agnostic source tree.
+ */
+
+#if defined(__GNUC__) || defined(__INTEL_COMPILER)
+
+#if __GNUC__ >= 3 || defined(__INTEL_COMPILER)
+#define __GNUCLIKE_ASM 3
+#else
+#define __GNUCLIKE_ASM 2
+#endif
+
+#define __CC_SUPPORTS___INLINE__ 1
+
+#endif /* __GNUC__ || __INTEL_COMPILER */
+
+#if defined(__STDC__) || defined(__cplusplus)
+
+#define __volatile volatile
+#if defined(__cplusplus)
+#define __inline inline /* convert to C++ keyword */
+#else
+#if !defined(__CC_SUPPORTS___INLINE)
+#define __inline /* delete GCC keyword */
+#endif /* ! __CC_SUPPORTS___INLINE */
+#endif /* !__cplusplus */
+
+#else /* !(__STDC__ || __cplusplus) */
+
+#if !defined(__CC_SUPPORTS___INLINE)
+#define __inline
+#define __volatile
+#endif /* !__CC_SUPPORTS___INLINE */
+#endif /* !(__STDC__ || __cplusplus) */
+
+/*
+ * Macro to test if we're using a specific version of gcc or later.
+ */
+#ifndef __GNUC_PREREQ__
+#if defined(__GNUC__) && !defined(__INTEL_COMPILER)
+#define __GNUC_PREREQ__(ma, mi) \
+ (__GNUC__ > (ma) || __GNUC__ == (ma) && __GNUC_MINOR__ >= (mi))
+#else
+#define __GNUC_PREREQ__(ma, mi) 0
+#endif
+#endif /* __GNUC_PREREQ__ */
+
+/*
+ * Compiler-dependent macro to help declare pure (no side effects) functions.
+ * It is null except for versions of gcc that are known to support the features
+ * properly (old versions of gcc-2 supported the dead and pure features
+ * in a different (wrong) way), and for icc. If we do not provide an implementation
+ * for a given compiler, let the compile fail if it is told to use
+ * a feature that we cannot live without.
+ */
+#if !defined(__pure2) && (__GNUC_PREREQ__(2, 7) || defined(__INTEL_COMPILER))
+#define __pure2 __attribute__((__const__))
+#endif
+
+#endif /* !_BSD_CDEFS_H_ */
--- /dev/null
+#ifndef _CDEFS_COMPAT_H_
+#define _CDEFS_COMPAT_H_
+
+#if !defined(__BEGIN_DECLS)
+#if defined(__cplusplus)
+#define __BEGIN_DECLS extern "C" {
+#define __END_DECLS }
+#else
+#define __BEGIN_DECLS
+#define __END_DECLS
+#endif
+#endif /* !defined(__BEGIN_DECLS) */
+
+#ifdef __GNUC__
+#ifndef __strong_reference
+#ifdef __APPLE__
+#define __strong_reference(sym,aliassym) __weak_reference(sym,aliassym)
+#else
+#define __strong_reference(sym,aliassym) \
+ OLM_DLLEXPORT extern __typeof (sym) aliassym __attribute__ ((__alias__ (#sym)));
+#endif /* __APPLE__ */
+#endif /* __strong_reference */
+
+#ifndef __weak_reference
+#ifdef __ELF__
+#ifdef __STDC__
+#define __weak_reference(sym,alias) \
+ __asm__(".weak " #alias); \
+ __asm__(".equ " #alias ", " #sym)
+#ifndef __warn_references
+#define __warn_references(sym,msg) \
+ __asm__(".section .gnu.warning." #sym); \
+ __asm__(".asciz \"" msg "\""); \
+ __asm__(".previous")
+#endif /* __warn_references */
+#else
+#define __weak_reference(sym,alias) \
+ __asm__(".weak alias"); \
+ __asm__(".equ alias, sym")
+#ifndef __warn_references
+#define __warn_references(sym,msg) \
+ __asm__(".section .gnu.warning.sym"); \
+ __asm__(".asciz \"msg\""); \
+ __asm__(".previous")
+#endif /* __warn_references */
+#endif /* __STDC__ */
+#elif defined(__clang__) /* CLANG */
+#ifdef __STDC__
+#define __weak_reference(sym,alias) \
+ __asm__(".weak_reference " #alias); \
+ __asm__(".set " #alias ", " #sym)
+#else
+#define __weak_reference(sym,alias) \
+ __asm__(".weak_reference alias");\
+ __asm__(".set alias, sym")
+#endif
+#else /* !__ELF__ */
+#ifdef __STDC__
+#define __weak_reference(sym,alias) \
+ __asm__(".stabs \"_" #alias "\",11,0,0,0"); \
+ __asm__(".stabs \"_" #sym "\",1,0,0,0")
+#ifndef __warn_references
+#define __warn_references(sym,msg) \
+ __asm__(".stabs \"" msg "\",30,0,0,0"); \
+ __asm__(".stabs \"_" #sym "\",1,0,0,0")
+#endif /* __warn_references */
+#else
+#define __weak_reference(sym,alias) \
+ __asm__(".stabs \"_/**/alias\",11,0,0,0"); \
+ __asm__(".stabs \"_/**/sym\",1,0,0,0")
+#ifndef __warn_references
+#define __warn_references(sym,msg) \
+ __asm__(".stabs msg,30,0,0,0"); \
+ __asm__(".stabs \"_/**/sym\",1,0,0,0")
+#endif /* __warn_references */
+#endif /* __STDC__ */
+#endif /* __ELF__ */
+#endif /* __weak_reference */
+#endif /* __GNUC__ */
+
+
+#endif /* _CDEFS_COMPAT_H_ */
--- /dev/null
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+OLM_DLLEXPORT int isopenlibm(void) {
+ return 1;
+}
--- /dev/null
+
+/* @(#)e_acos.c 1.3 95/01/18 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunSoft, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/src/e_acos.c,v 1.13 2008/07/31 22:41:26 das Exp $");
+
+/* __ieee754_acos(x)
+ * Method :
+ * acos(x) = pi/2 - asin(x)
+ * acos(-x) = pi/2 + asin(x)
+ * For |x|<=0.5
+ * acos(x) = pi/2 - (x + x*x^2*R(x^2)) (see asin.c)
+ * For x>0.5
+ * acos(x) = pi/2 - (pi/2 - 2asin(sqrt((1-x)/2)))
+ * = 2asin(sqrt((1-x)/2))
+ * = 2s + 2s*z*R(z) ...z=(1-x)/2, s=sqrt(z)
+ * = 2f + (2c + 2s*z*R(z))
+ * where f=hi part of s, and c = (z-f*f)/(s+f) is the correction term
+ * for f so that f+c ~ sqrt(z).
+ * For x<-0.5
+ * acos(x) = pi - 2asin(sqrt((1-|x|)/2))
+ * = pi - 0.5*(s+s*z*R(z)), where z=(1-|x|)/2,s=sqrt(z)
+ *
+ * Special cases:
+ * if x is NaN, return x itself;
+ * if |x|>1, return NaN with invalid signal.
+ *
+ * Function needed: sqrt
+ */
+
+#include <float.h>
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+static const double
+one= 1.00000000000000000000e+00, /* 0x3FF00000, 0x00000000 */
+pi = 3.14159265358979311600e+00, /* 0x400921FB, 0x54442D18 */
+pio2_hi = 1.57079632679489655800e+00; /* 0x3FF921FB, 0x54442D18 */
+static volatile double
+pio2_lo = 6.12323399573676603587e-17; /* 0x3C91A626, 0x33145C07 */
+static const double
+pS0 = 1.66666666666666657415e-01, /* 0x3FC55555, 0x55555555 */
+pS1 = -3.25565818622400915405e-01, /* 0xBFD4D612, 0x03EB6F7D */
+pS2 = 2.01212532134862925881e-01, /* 0x3FC9C155, 0x0E884455 */
+pS3 = -4.00555345006794114027e-02, /* 0xBFA48228, 0xB5688F3B */
+pS4 = 7.91534994289814532176e-04, /* 0x3F49EFE0, 0x7501B288 */
+pS5 = 3.47933107596021167570e-05, /* 0x3F023DE1, 0x0DFDF709 */
+qS1 = -2.40339491173441421878e+00, /* 0xC0033A27, 0x1C8A2D4B */
+qS2 = 2.02094576023350569471e+00, /* 0x40002AE5, 0x9C598AC8 */
+qS3 = -6.88283971605453293030e-01, /* 0xBFE6066C, 0x1B8D0159 */
+qS4 = 7.70381505559019352791e-02; /* 0x3FB3B8C5, 0xB12E9282 */
+
+OLM_DLLEXPORT double
+__ieee754_acos(double x)
+{
+ double z,p,q,r,w,s,c,df;
+ int32_t hx,ix;
+ GET_HIGH_WORD(hx,x);
+ ix = hx&0x7fffffff;
+ if(ix>=0x3ff00000) { /* |x| >= 1 */
+ u_int32_t lx;
+ GET_LOW_WORD(lx,x);
+ if(((ix-0x3ff00000)|lx)==0) { /* |x|==1 */
+ if(hx>0) return 0.0; /* acos(1) = 0 */
+ else return pi+2.0*pio2_lo; /* acos(-1)= pi */
+ }
+ return (x-x)/(x-x); /* acos(|x|>1) is NaN */
+ }
+ if(ix<0x3fe00000) { /* |x| < 0.5 */
+ if(ix<=0x3c600000) return pio2_hi+pio2_lo;/*if|x|<2**-57*/
+ z = x*x;
+ p = z*(pS0+z*(pS1+z*(pS2+z*(pS3+z*(pS4+z*pS5)))));
+ q = one+z*(qS1+z*(qS2+z*(qS3+z*qS4)));
+ r = p/q;
+ return pio2_hi - (x - (pio2_lo-x*r));
+ } else if (hx<0) { /* x < -0.5 */
+ z = (one+x)*0.5;
+ p = z*(pS0+z*(pS1+z*(pS2+z*(pS3+z*(pS4+z*pS5)))));
+ q = one+z*(qS1+z*(qS2+z*(qS3+z*qS4)));
+ s = sqrt(z);
+ r = p/q;
+ w = r*s-pio2_lo;
+ return pi - 2.0*(s+w);
+ } else { /* x > 0.5 */
+ z = (one-x)*0.5;
+ s = sqrt(z);
+ df = s;
+ SET_LOW_WORD(df,0);
+ c = (z-df*df)/(s+df);
+ p = z*(pS0+z*(pS1+z*(pS2+z*(pS3+z*(pS4+z*pS5)))));
+ q = one+z*(qS1+z*(qS2+z*(qS3+z*qS4)));
+ r = p/q;
+ w = r*s+c;
+ return 2.0*(df+w);
+ }
+}
+
+#if LDBL_MANT_DIG == 53
+__weak_reference(acos, acosl);
+#endif
--- /dev/null
+/* e_acosf.c -- float version of e_acos.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/src/e_acosf.c,v 1.11 2008/08/03 17:39:54 das Exp $");
+
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+static const float
+one = 1.0000000000e+00, /* 0x3F800000 */
+pi = 3.1415925026e+00, /* 0x40490fda */
+pio2_hi = 1.5707962513e+00; /* 0x3fc90fda */
+static volatile float
+pio2_lo = 7.5497894159e-08; /* 0x33a22168 */
+static const float
+pS0 = 1.6666586697e-01,
+pS1 = -4.2743422091e-02,
+pS2 = -8.6563630030e-03,
+qS1 = -7.0662963390e-01;
+
+OLM_DLLEXPORT float
+__ieee754_acosf(float x)
+{
+ float z,p,q,r,w,s,c,df;
+ int32_t hx,ix;
+ GET_FLOAT_WORD(hx,x);
+ ix = hx&0x7fffffff;
+ if(ix>=0x3f800000) { /* |x| >= 1 */
+ if(ix==0x3f800000) { /* |x| == 1 */
+ if(hx>0) return 0.0; /* acos(1) = 0 */
+ else return pi+(float)2.0*pio2_lo; /* acos(-1)= pi */
+ }
+ return (x-x)/(x-x); /* acos(|x|>1) is NaN */
+ }
+ if(ix<0x3f000000) { /* |x| < 0.5 */
+ if(ix<=0x32800000) return pio2_hi+pio2_lo;/*if|x|<2**-26*/
+ z = x*x;
+ p = z*(pS0+z*(pS1+z*pS2));
+ q = one+z*qS1;
+ r = p/q;
+ return pio2_hi - (x - (pio2_lo-x*r));
+ } else if (hx<0) { /* x < -0.5 */
+ z = (one+x)*(float)0.5;
+ p = z*(pS0+z*(pS1+z*pS2));
+ q = one+z*qS1;
+ s = sqrtf(z);
+ r = p/q;
+ w = r*s-pio2_lo;
+ return pi - (float)2.0*(s+w);
+ } else { /* x > 0.5 */
+ int32_t idf;
+ z = (one-x)*(float)0.5;
+ s = sqrtf(z);
+ df = s;
+ GET_FLOAT_WORD(idf,df);
+ SET_FLOAT_WORD(df,idf&0xfffff000);
+ c = (z-df*df)/(s+df);
+ p = z*(pS0+z*(pS1+z*pS2));
+ q = one+z*qS1;
+ r = p/q;
+ w = r*s+c;
+ return (float)2.0*(df+w);
+ }
+}
--- /dev/null
+
+/* @(#)e_acosh.c 1.3 95/01/18 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunSoft, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ *
+ */
+
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/src/e_acosh.c,v 1.9 2008/02/22 02:30:34 das Exp $");
+
+/* __ieee754_acosh(x)
+ * Method :
+ * Based on
+ * acosh(x) = log [ x + sqrt(x*x-1) ]
+ * we have
+ * acosh(x) := log(x)+ln2, if x is large; else
+ * acosh(x) := log(2x-1/(sqrt(x*x-1)+x)) if x>2; else
+ * acosh(x) := log1p(t+sqrt(2.0*t+t*t)); where t=x-1.
+ *
+ * Special cases:
+ * acosh(x) is NaN with signal if x<1.
+ * acosh(NaN) is NaN without signal.
+ */
+
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+static const double
+one = 1.0,
+ln2 = 6.93147180559945286227e-01; /* 0x3FE62E42, 0xFEFA39EF */
+
+OLM_DLLEXPORT double
+__ieee754_acosh(double x)
+{
+ double t;
+ int32_t hx;
+ u_int32_t lx;
+ EXTRACT_WORDS(hx,lx,x);
+ if(hx<0x3ff00000) { /* x < 1 */
+ return (x-x)/(x-x);
+ } else if(hx >=0x41b00000) { /* x > 2**28 */
+ if(hx >=0x7ff00000) { /* x is inf of NaN */
+ return x+x;
+ } else
+ return __ieee754_log(x)+ln2; /* acosh(huge)=log(2x) */
+ } else if(((hx-0x3ff00000)|lx)==0) {
+ return 0.0; /* acosh(1) = 0 */
+ } else if (hx > 0x40000000) { /* 2**28 > x > 2 */
+ t=x*x;
+ return __ieee754_log(2.0*x-one/(x+sqrt(t-one)));
+ } else { /* 1<x<2 */
+ t = x-one;
+ return log1p(t+sqrt(2.0*t+t*t));
+ }
+}
--- /dev/null
+/* e_acoshf.c -- float version of e_acosh.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/src/e_acoshf.c,v 1.8 2008/02/22 02:30:34 das Exp $");
+
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+static const float
+one = 1.0,
+ln2 = 6.9314718246e-01; /* 0x3f317218 */
+
+OLM_DLLEXPORT float
+__ieee754_acoshf(float x)
+{
+ float t;
+ int32_t hx;
+ GET_FLOAT_WORD(hx,x);
+ if(hx<0x3f800000) { /* x < 1 */
+ return (x-x)/(x-x);
+ } else if(hx >=0x4d800000) { /* x > 2**28 */
+ if(hx >=0x7f800000) { /* x is inf of NaN */
+ return x+x;
+ } else
+ return __ieee754_logf(x)+ln2; /* acosh(huge)=log(2x) */
+ } else if (hx==0x3f800000) {
+ return 0.0; /* acosh(1) = 0 */
+ } else if (hx > 0x40000000) { /* 2**28 > x > 2 */
+ t=x*x;
+ return __ieee754_logf((float)2.0*x-one/(x+__ieee754_sqrtf(t-one)));
+ } else { /* 1<x<2 */
+ t = x-one;
+ return log1pf(t+__ieee754_sqrtf((float)2.0*t+t*t));
+ }
+}
--- /dev/null
+
+/* @(#)e_acos.c 1.3 95/01/18 */
+/* FreeBSD: head/lib/msun/src/e_acos.c 176451 2008-02-22 02:30:36Z das */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunSoft, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/src/e_acosl.c,v 1.2 2008/08/02 03:56:22 das Exp $");
+
+/*
+ * See comments in e_acos.c.
+ * Converted to long double by David Schultz <das@FreeBSD.ORG>.
+ */
+
+#include <float.h>
+#include <openlibm_math.h>
+
+#include "invtrig.h"
+#include "math_private.h"
+
+static const long double
+one= 1.00000000000000000000e+00;
+
+#ifdef __i386__
+/* XXX Work around the fact that gcc truncates long double constants on i386 */
+static volatile double
+pi1 = 3.14159265358979311600e+00, /* 0x1.921fb54442d18p+1 */
+pi2 = 1.22514845490862001043e-16; /* 0x1.1a80000000000p-53 */
+#define pi ((long double)pi1 + pi2)
+#else
+static const long double
+pi = 3.14159265358979323846264338327950280e+00L;
+#endif
+
+OLM_DLLEXPORT long double
+acosl(long double x)
+{
+ union IEEEl2bits u;
+ long double z,p,q,r,w,s,c,df;
+ int16_t expsign, expt;
+ u.e = x;
+ expsign = u.xbits.expsign;
+ expt = expsign & 0x7fff;
+ if(expt >= BIAS) { /* |x| >= 1 */
+ if(expt==BIAS && ((u.bits.manh&~LDBL_NBIT)|u.bits.manl)==0) {
+ if (expsign>0) return 0.0; /* acos(1) = 0 */
+ else return pi+2.0*pio2_lo; /* acos(-1)= pi */
+ }
+ return (x-x)/(x-x); /* acos(|x|>1) is NaN */
+ }
+ if(expt<BIAS-1) { /* |x| < 0.5 */
+ if(expt<ACOS_CONST) return pio2_hi+pio2_lo;/*x tiny: acosl=pi/2*/
+ z = x*x;
+ p = P(z);
+ q = Q(z);
+ r = p/q;
+ return pio2_hi - (x - (pio2_lo-x*r));
+ } else if (expsign<0) { /* x < -0.5 */
+ z = (one+x)*0.5;
+ p = P(z);
+ q = Q(z);
+ s = sqrtl(z);
+ r = p/q;
+ w = r*s-pio2_lo;
+ return pi - 2.0*(s+w);
+ } else { /* x > 0.5 */
+ z = (one-x)*0.5;
+ s = sqrtl(z);
+ u.e = s;
+ u.bits.manl = 0;
+ df = u.e;
+ c = (z-df*df)/(s+df);
+ p = P(z);
+ q = Q(z);
+ r = p/q;
+ w = r*s+c;
+ return 2.0*(df+w);
+ }
+}
--- /dev/null
+
+/* @(#)e_asin.c 1.3 95/01/18 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunSoft, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/src/e_asin.c,v 1.15 2011/02/10 07:37:50 das Exp $");
+
+/* __ieee754_asin(x)
+ * Method :
+ * Since asin(x) = x + x^3/6 + x^5*3/40 + x^7*15/336 + ...
+ * we approximate asin(x) on [0,0.5] by
+ * asin(x) = x + x*x^2*R(x^2)
+ * where
+ * R(x^2) is a rational approximation of (asin(x)-x)/x^3
+ * and its remez error is bounded by
+ * |(asin(x)-x)/x^3 - R(x^2)| < 2^(-58.75)
+ *
+ * For x in [0.5,1]
+ * asin(x) = pi/2-2*asin(sqrt((1-x)/2))
+ * Let y = (1-x), z = y/2, s := sqrt(z), and pio2_hi+pio2_lo=pi/2;
+ * then for x>0.98
+ * asin(x) = pi/2 - 2*(s+s*z*R(z))
+ * = pio2_hi - (2*(s+s*z*R(z)) - pio2_lo)
+ * For x<=0.98, let pio4_hi = pio2_hi/2, then
+ * f = hi part of s;
+ * c = sqrt(z) - f = (z-f*f)/(s+f) ...f+c=sqrt(z)
+ * and
+ * asin(x) = pi/2 - 2*(s+s*z*R(z))
+ * = pio4_hi+(pio4-2s)-(2s*z*R(z)-pio2_lo)
+ * = pio4_hi+(pio4-2f)-(2s*z*R(z)-(pio2_lo+2c))
+ *
+ * Special cases:
+ * if x is NaN, return x itself;
+ * if |x|>1, return NaN with invalid signal.
+ *
+ */
+
+#include <float.h>
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+static const double
+one = 1.00000000000000000000e+00, /* 0x3FF00000, 0x00000000 */
+huge = 1.000e+300,
+pio2_hi = 1.57079632679489655800e+00, /* 0x3FF921FB, 0x54442D18 */
+pio2_lo = 6.12323399573676603587e-17, /* 0x3C91A626, 0x33145C07 */
+pio4_hi = 7.85398163397448278999e-01, /* 0x3FE921FB, 0x54442D18 */
+ /* coefficient for R(x^2) */
+pS0 = 1.66666666666666657415e-01, /* 0x3FC55555, 0x55555555 */
+pS1 = -3.25565818622400915405e-01, /* 0xBFD4D612, 0x03EB6F7D */
+pS2 = 2.01212532134862925881e-01, /* 0x3FC9C155, 0x0E884455 */
+pS3 = -4.00555345006794114027e-02, /* 0xBFA48228, 0xB5688F3B */
+pS4 = 7.91534994289814532176e-04, /* 0x3F49EFE0, 0x7501B288 */
+pS5 = 3.47933107596021167570e-05, /* 0x3F023DE1, 0x0DFDF709 */
+qS1 = -2.40339491173441421878e+00, /* 0xC0033A27, 0x1C8A2D4B */
+qS2 = 2.02094576023350569471e+00, /* 0x40002AE5, 0x9C598AC8 */
+qS3 = -6.88283971605453293030e-01, /* 0xBFE6066C, 0x1B8D0159 */
+qS4 = 7.70381505559019352791e-02; /* 0x3FB3B8C5, 0xB12E9282 */
+
+OLM_DLLEXPORT double
+__ieee754_asin(double x)
+{
+ double t=0.0,w,p,q,c,r,s;
+ int32_t hx,ix;
+ GET_HIGH_WORD(hx,x);
+ ix = hx&0x7fffffff;
+ if(ix>= 0x3ff00000) { /* |x|>= 1 */
+ u_int32_t lx;
+ GET_LOW_WORD(lx,x);
+ if(((ix-0x3ff00000)|lx)==0)
+ /* asin(1)=+-pi/2 with inexact */
+ return x*pio2_hi+x*pio2_lo;
+ return (x-x)/(x-x); /* asin(|x|>1) is NaN */
+ } else if (ix<0x3fe00000) { /* |x|<0.5 */
+ if(ix<0x3e500000) { /* if |x| < 2**-26 */
+ if(huge+x>one) return x;/* return x with inexact if x!=0*/
+ }
+ t = x*x;
+ p = t*(pS0+t*(pS1+t*(pS2+t*(pS3+t*(pS4+t*pS5)))));
+ q = one+t*(qS1+t*(qS2+t*(qS3+t*qS4)));
+ w = p/q;
+ return x+x*w;
+ }
+ /* 1> |x|>= 0.5 */
+ w = one-fabs(x);
+ t = w*0.5;
+ p = t*(pS0+t*(pS1+t*(pS2+t*(pS3+t*(pS4+t*pS5)))));
+ q = one+t*(qS1+t*(qS2+t*(qS3+t*qS4)));
+ s = sqrt(t);
+ if(ix>=0x3FEF3333) { /* if |x| > 0.975 */
+ w = p/q;
+ t = pio2_hi-(2.0*(s+s*w)-pio2_lo);
+ } else {
+ w = s;
+ SET_LOW_WORD(w,0);
+ c = (t-w*w)/(s+w);
+ r = p/q;
+ p = 2.0*s*r-(pio2_lo-2.0*c);
+ q = pio4_hi-2.0*w;
+ t = pio4_hi-(p-q);
+ }
+ if(hx>0) return t; else return -t;
+}
+
+#if LDBL_MANT_DIG == 53
+__weak_reference(asin, asinl);
+#endif
--- /dev/null
+/* e_asinf.c -- float version of e_asin.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/src/e_asinf.c,v 1.13 2008/08/08 00:21:27 das Exp $");
+
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+static const float
+one = 1.0000000000e+00, /* 0x3F800000 */
+huge = 1.000e+30,
+ /* coefficient for R(x^2) */
+pS0 = 1.6666586697e-01,
+pS1 = -4.2743422091e-02,
+pS2 = -8.6563630030e-03,
+qS1 = -7.0662963390e-01;
+
+static const double
+pio2 = 1.570796326794896558e+00;
+
+OLM_DLLEXPORT float
+__ieee754_asinf(float x)
+{
+ double s;
+ float t,w,p,q;
+ int32_t hx,ix;
+ GET_FLOAT_WORD(hx,x);
+ ix = hx&0x7fffffff;
+ if(ix>=0x3f800000) { /* |x| >= 1 */
+ if(ix==0x3f800000) /* |x| == 1 */
+ return x*pio2; /* asin(+-1) = +-pi/2 with inexact */
+ return (x-x)/(x-x); /* asin(|x|>1) is NaN */
+ } else if (ix<0x3f000000) { /* |x|<0.5 */
+ if(ix<0x39800000) { /* |x| < 2**-12 */
+ if(huge+x>one) return x;/* return x with inexact if x!=0*/
+ }
+ t = x*x;
+ p = t*(pS0+t*(pS1+t*pS2));
+ q = one+t*qS1;
+ w = p/q;
+ return x+x*w;
+ }
+ /* 1> |x|>= 0.5 */
+ w = one-fabsf(x);
+ t = w*(float)0.5;
+ p = t*(pS0+t*(pS1+t*pS2));
+ q = one+t*qS1;
+ s = sqrt(t);
+ w = p/q;
+ t = pio2-2.0*(s+s*w);
+ if(hx>0) return t; else return -t;
+}
--- /dev/null
+
+/* @(#)e_asin.c 1.3 95/01/18 */
+/* FreeBSD: head/lib/msun/src/e_asin.c 176451 2008-02-22 02:30:36Z das */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunSoft, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/src/e_asinl.c,v 1.2 2008/08/03 17:49:05 das Exp $");
+
+/*
+ * See comments in e_asin.c.
+ * Converted to long double by David Schultz <das@FreeBSD.ORG>.
+ */
+
+#include <float.h>
+#include <openlibm_math.h>
+
+#include "invtrig.h"
+#include "math_private.h"
+
+static const long double
+one = 1.00000000000000000000e+00,
+huge = 1.000e+300;
+
+OLM_DLLEXPORT long double
+asinl(long double x)
+{
+ union IEEEl2bits u;
+ long double t=0.0,w,p,q,c,r,s;
+ int16_t expsign, expt;
+ u.e = x;
+ expsign = u.xbits.expsign;
+ expt = expsign & 0x7fff;
+ if(expt >= BIAS) { /* |x|>= 1 */
+ if(expt==BIAS && ((u.bits.manh&~LDBL_NBIT)|u.bits.manl)==0)
+ /* asin(1)=+-pi/2 with inexact */
+ return x*pio2_hi+x*pio2_lo;
+ return (x-x)/(x-x); /* asin(|x|>1) is NaN */
+ } else if (expt<BIAS-1) { /* |x|<0.5 */
+ if(expt<ASIN_LINEAR) { /* if |x| is small, asinl(x)=x */
+ if(huge+x>one) return x;/* return x with inexact if x!=0*/
+ }
+ t = x*x;
+ p = P(t);
+ q = Q(t);
+ w = p/q;
+ return x+x*w;
+ }
+ /* 1> |x|>= 0.5 */
+ w = one-fabsl(x);
+ t = w*0.5;
+ p = P(t);
+ q = Q(t);
+ s = sqrtl(t);
+ if(u.bits.manh>=THRESH) { /* if |x| is close to 1 */
+ w = p/q;
+ t = pio2_hi-(2.0*(s+s*w)-pio2_lo);
+ } else {
+ u.e = s;
+ u.bits.manl = 0;
+ w = u.e;
+ c = (t-w*w)/(s+w);
+ r = p/q;
+ p = 2.0*s*r-(pio2_lo-2.0*c);
+ q = pio4_hi-2.0*w;
+ t = pio4_hi-(p-q);
+ }
+ if(expsign>0) return t; else return -t;
+}
--- /dev/null
+
+/* @(#)e_atan2.c 1.3 95/01/18 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunSoft, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ *
+ */
+
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/src/e_atan2.c,v 1.14 2008/08/02 19:17:00 das Exp $");
+
+/* __ieee754_atan2(y,x)
+ * Method :
+ * 1. Reduce y to positive by atan2(y,x)=-atan2(-y,x).
+ * 2. Reduce x to positive by (if x and y are unexceptional):
+ * ARG (x+iy) = arctan(y/x) ... if x > 0,
+ * ARG (x+iy) = pi - arctan[y/(-x)] ... if x < 0,
+ *
+ * Special cases:
+ *
+ * ATAN2((anything), NaN ) is NaN;
+ * ATAN2(NAN , (anything) ) is NaN;
+ * ATAN2(+-0, +(anything but NaN)) is +-0 ;
+ * ATAN2(+-0, -(anything but NaN)) is +-pi ;
+ * ATAN2(+-(anything but 0 and NaN), 0) is +-pi/2;
+ * ATAN2(+-(anything but INF and NaN), +INF) is +-0 ;
+ * ATAN2(+-(anything but INF and NaN), -INF) is +-pi;
+ * ATAN2(+-INF,+INF ) is +-pi/4 ;
+ * ATAN2(+-INF,-INF ) is +-3pi/4;
+ * ATAN2(+-INF, (anything but,0,NaN, and INF)) is +-pi/2;
+ *
+ * Constants:
+ * The hexadecimal values are the intended ones for the following
+ * constants. The decimal values may be used, provided that the
+ * compiler will convert from decimal to binary accurately enough
+ * to produce the hexadecimal values shown.
+ */
+
+#include <float.h>
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+static volatile double
+tiny = 1.0e-300;
+static const double
+zero = 0.0,
+pi_o_4 = 7.8539816339744827900E-01, /* 0x3FE921FB, 0x54442D18 */
+pi_o_2 = 1.5707963267948965580E+00, /* 0x3FF921FB, 0x54442D18 */
+pi = 3.1415926535897931160E+00; /* 0x400921FB, 0x54442D18 */
+static volatile double
+pi_lo = 1.2246467991473531772E-16; /* 0x3CA1A626, 0x33145C07 */
+
+OLM_DLLEXPORT double
+__ieee754_atan2(double y, double x)
+{
+ double z;
+ int32_t k,m,hx,hy,ix,iy;
+ u_int32_t lx,ly;
+
+ EXTRACT_WORDS(hx,lx,x);
+ ix = hx&0x7fffffff;
+ EXTRACT_WORDS(hy,ly,y);
+ iy = hy&0x7fffffff;
+ if(((ix|((lx|-lx)>>31))>0x7ff00000)||
+ ((iy|((ly|-ly)>>31))>0x7ff00000)) /* x or y is NaN */
+ return x+y;
+ if(hx==0x3ff00000&&lx==0) return atan(y); /* x=1.0 */
+ m = ((hy>>31)&1)|((hx>>30)&2); /* 2*sign(x)+sign(y) */
+
+ /* when y = 0 */
+ if((iy|ly)==0) {
+ switch(m) {
+ case 0:
+ case 1: return y; /* atan(+-0,+anything)=+-0 */
+ case 2: return pi+tiny;/* atan(+0,-anything) = pi */
+ case 3: return -pi-tiny;/* atan(-0,-anything) =-pi */
+ }
+ }
+ /* when x = 0 */
+ if((ix|lx)==0) return (hy<0)? -pi_o_2-tiny: pi_o_2+tiny;
+
+ /* when x is INF */
+ if(ix==0x7ff00000) {
+ if(iy==0x7ff00000) {
+ switch(m) {
+ case 0: return pi_o_4+tiny;/* atan(+INF,+INF) */
+ case 1: return -pi_o_4-tiny;/* atan(-INF,+INF) */
+ case 2: return 3.0*pi_o_4+tiny;/*atan(+INF,-INF)*/
+ case 3: return -3.0*pi_o_4-tiny;/*atan(-INF,-INF)*/
+ }
+ } else {
+ switch(m) {
+ case 0: return zero ; /* atan(+...,+INF) */
+ case 1: return -zero ; /* atan(-...,+INF) */
+ case 2: return pi+tiny ; /* atan(+...,-INF) */
+ case 3: return -pi-tiny ; /* atan(-...,-INF) */
+ }
+ }
+ }
+ /* when y is INF */
+ if(iy==0x7ff00000) return (hy<0)? -pi_o_2-tiny: pi_o_2+tiny;
+
+ /* compute y/x */
+ k = (iy-ix)>>20;
+ if(k > 60) { /* |y/x| > 2**60 */
+ z=pi_o_2+0.5*pi_lo;
+ m&=1;
+ }
+ else if(hx<0&&k<-60) z=0.0; /* 0 > |y|/x > -2**-60 */
+ else z=atan(fabs(y/x)); /* safe to do y/x */
+ switch (m) {
+ case 0: return z ; /* atan(+,+) */
+ case 1: return -z ; /* atan(-,+) */
+ case 2: return pi-(z-pi_lo);/* atan(+,-) */
+ default: /* case 3 */
+ return (z-pi_lo)-pi;/* atan(-,-) */
+ }
+}
+
+#if LDBL_MANT_DIG == 53
+__weak_reference(atan2, atan2l);
+#endif
--- /dev/null
+/* e_atan2f.c -- float version of e_atan2.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/src/e_atan2f.c,v 1.12 2008/08/03 17:39:54 das Exp $");
+
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+static volatile float
+tiny = 1.0e-30;
+static const float
+zero = 0.0,
+pi_o_4 = 7.8539818525e-01, /* 0x3f490fdb */
+pi_o_2 = 1.5707963705e+00, /* 0x3fc90fdb */
+pi = 3.1415927410e+00; /* 0x40490fdb */
+static volatile float
+pi_lo = -8.7422776573e-08; /* 0xb3bbbd2e */
+
+OLM_DLLEXPORT float
+__ieee754_atan2f(float y, float x)
+{
+ float z;
+ int32_t k,m,hx,hy,ix,iy;
+
+ GET_FLOAT_WORD(hx,x);
+ ix = hx&0x7fffffff;
+ GET_FLOAT_WORD(hy,y);
+ iy = hy&0x7fffffff;
+ if((ix>0x7f800000)||
+ (iy>0x7f800000)) /* x or y is NaN */
+ return x+y;
+ if(hx==0x3f800000) return atanf(y); /* x=1.0 */
+ m = ((hy>>31)&1)|((hx>>30)&2); /* 2*sign(x)+sign(y) */
+
+ /* when y = 0 */
+ if(iy==0) {
+ switch(m) {
+ case 0:
+ case 1: return y; /* atan(+-0,+anything)=+-0 */
+ case 2: return pi+tiny;/* atan(+0,-anything) = pi */
+ case 3: return -pi-tiny;/* atan(-0,-anything) =-pi */
+ }
+ }
+ /* when x = 0 */
+ if(ix==0) return (hy<0)? -pi_o_2-tiny: pi_o_2+tiny;
+
+ /* when x is INF */
+ if(ix==0x7f800000) {
+ if(iy==0x7f800000) {
+ switch(m) {
+ case 0: return pi_o_4+tiny;/* atan(+INF,+INF) */
+ case 1: return -pi_o_4-tiny;/* atan(-INF,+INF) */
+ case 2: return (float)3.0*pi_o_4+tiny;/*atan(+INF,-INF)*/
+ case 3: return (float)-3.0*pi_o_4-tiny;/*atan(-INF,-INF)*/
+ }
+ } else {
+ switch(m) {
+ case 0: return zero ; /* atan(+...,+INF) */
+ case 1: return -zero ; /* atan(-...,+INF) */
+ case 2: return pi+tiny ; /* atan(+...,-INF) */
+ case 3: return -pi-tiny ; /* atan(-...,-INF) */
+ }
+ }
+ }
+ /* when y is INF */
+ if(iy==0x7f800000) return (hy<0)? -pi_o_2-tiny: pi_o_2+tiny;
+
+ /* compute y/x */
+ k = (iy-ix)>>23;
+ if(k > 26) { /* |y/x| > 2**26 */
+ z=pi_o_2+(float)0.5*pi_lo;
+ m&=1;
+ }
+ else if(k<-26&&hx<0) z=0.0; /* 0 > |y|/x > -2**-26 */
+ else z=atanf(fabsf(y/x)); /* safe to do y/x */
+ switch (m) {
+ case 0: return z ; /* atan(+,+) */
+ case 1: return -z ; /* atan(-,+) */
+ case 2: return pi-(z-pi_lo);/* atan(+,-) */
+ default: /* case 3 */
+ return (z-pi_lo)-pi;/* atan(-,-) */
+ }
+}
--- /dev/null
+
+/* @(#)e_atan2.c 1.3 95/01/18 */
+/* FreeBSD: head/lib/msun/src/e_atan2.c 176451 2008-02-22 02:30:36Z das */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunSoft, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ *
+ */
+
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/src/e_atan2l.c,v 1.3 2008/08/02 19:17:00 das Exp $");
+
+/*
+ * See comments in e_atan2.c.
+ * Converted to long double by David Schultz <das@FreeBSD.ORG>.
+ */
+
+#include <float.h>
+#include <openlibm_math.h>
+
+#include "invtrig.h"
+#include "math_private.h"
+
+static volatile long double
+tiny = 1.0e-300;
+static const long double
+zero = 0.0;
+
+#ifdef __i386__
+/* XXX Work around the fact that gcc truncates long double constants on i386 */
+static volatile double
+pi1 = 3.14159265358979311600e+00, /* 0x1.921fb54442d18p+1 */
+pi2 = 1.22514845490862001043e-16; /* 0x1.1a80000000000p-53 */
+#define pi ((long double)pi1 + pi2)
+#else
+static const long double
+pi = 3.14159265358979323846264338327950280e+00L;
+#endif
+
+OLM_DLLEXPORT long double
+atan2l(long double y, long double x)
+{
+ union IEEEl2bits ux, uy;
+ long double z;
+ int32_t k,m;
+ int16_t exptx, expsignx, expty, expsigny;
+
+ uy.e = y;
+ expsigny = uy.xbits.expsign;
+ expty = expsigny & 0x7fff;
+ ux.e = x;
+ expsignx = ux.xbits.expsign;
+ exptx = expsignx & 0x7fff;
+
+ if ((exptx==BIAS+LDBL_MAX_EXP &&
+ ((ux.bits.manh&~LDBL_NBIT)|ux.bits.manl)!=0) || /* x is NaN */
+ (expty==BIAS+LDBL_MAX_EXP &&
+ ((uy.bits.manh&~LDBL_NBIT)|uy.bits.manl)!=0)) /* y is NaN */
+ return x+y;
+ if (expsignx==BIAS && ((ux.bits.manh&~LDBL_NBIT)|ux.bits.manl)==0)
+ return atanl(y); /* x=1.0 */
+ m = ((expsigny>>15)&1)|((expsignx>>14)&2); /* 2*sign(x)+sign(y) */
+
+ /* when y = 0 */
+ if(expty==0 && ((uy.bits.manh&~LDBL_NBIT)|uy.bits.manl)==0) {
+ switch(m) {
+ case 0:
+ case 1: return y; /* atan(+-0,+anything)=+-0 */
+ case 2: return pi+tiny;/* atan(+0,-anything) = pi */
+ case 3: return -pi-tiny;/* atan(-0,-anything) =-pi */
+ }
+ }
+ /* when x = 0 */
+ if(exptx==0 && ((ux.bits.manh&~LDBL_NBIT)|ux.bits.manl)==0)
+ return (expsigny<0)? -pio2_hi-tiny: pio2_hi+tiny;
+
+ /* when x is INF */
+ if(exptx==BIAS+LDBL_MAX_EXP) {
+ if(expty==BIAS+LDBL_MAX_EXP) {
+ switch(m) {
+ case 0: return pio2_hi*0.5+tiny;/* atan(+INF,+INF) */
+ case 1: return -pio2_hi*0.5-tiny;/* atan(-INF,+INF) */
+ case 2: return 1.5*pio2_hi+tiny;/*atan(+INF,-INF)*/
+ case 3: return -1.5*pio2_hi-tiny;/*atan(-INF,-INF)*/
+ }
+ } else {
+ switch(m) {
+ case 0: return zero ; /* atan(+...,+INF) */
+ case 1: return -zero ; /* atan(-...,+INF) */
+ case 2: return pi+tiny ; /* atan(+...,-INF) */
+ case 3: return -pi-tiny ; /* atan(-...,-INF) */
+ }
+ }
+ }
+ /* when y is INF */
+ if(expty==BIAS+LDBL_MAX_EXP)
+ return (expsigny<0)? -pio2_hi-tiny: pio2_hi+tiny;
+
+ /* compute y/x */
+ k = expty-exptx;
+ if(k > LDBL_MANT_DIG+2) { /* |y/x| huge */
+ z=pio2_hi+pio2_lo;
+ m&=1;
+ }
+ else if(expsignx<0&&k<-LDBL_MANT_DIG-2) z=0.0; /* |y/x| tiny, x<0 */
+ else z=atanl(fabsl(y/x)); /* safe to do y/x */
+ switch (m) {
+ case 0: return z ; /* atan(+,+) */
+ case 1: return -z ; /* atan(-,+) */
+ case 2: return pi-(z-pi_lo);/* atan(+,-) */
+ default: /* case 3 */
+ return (z-pi_lo)-pi;/* atan(-,-) */
+ }
+}
--- /dev/null
+
+/* @(#)e_atanh.c 1.3 95/01/18 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunSoft, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ *
+ */
+
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/src/e_atanh.c,v 1.8 2008/02/22 02:30:34 das Exp $");
+
+/* __ieee754_atanh(x)
+ * Method :
+ * 1.Reduced x to positive by atanh(-x) = -atanh(x)
+ * 2.For x>=0.5
+ * 1 2x x
+ * atanh(x) = --- * log(1 + -------) = 0.5 * log1p(2 * --------)
+ * 2 1 - x 1 - x
+ *
+ * For x<0.5
+ * atanh(x) = 0.5*log1p(2x+2x*x/(1-x))
+ *
+ * Special cases:
+ * atanh(x) is NaN if |x| > 1 with signal;
+ * atanh(NaN) is that NaN with no signal;
+ * atanh(+-1) is +-INF with signal.
+ *
+ */
+
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+static const double one = 1.0, huge = 1e300;
+static const double zero = 0.0;
+
+OLM_DLLEXPORT double
+__ieee754_atanh(double x)
+{
+ double t;
+ int32_t hx,ix;
+ u_int32_t lx;
+ EXTRACT_WORDS(hx,lx,x);
+ ix = hx&0x7fffffff;
+ if ((ix|((lx|(-lx))>>31))>0x3ff00000) /* |x|>1 */
+ return (x-x)/(x-x);
+ if(ix==0x3ff00000)
+ return x/zero;
+ if(ix<0x3e300000&&(huge+x)>zero) return x; /* x<2**-28 */
+ SET_HIGH_WORD(x,ix);
+ if(ix<0x3fe00000) { /* x < 0.5 */
+ t = x+x;
+ t = 0.5*log1p(t+t*x/(one-x));
+ } else
+ t = 0.5*log1p((x+x)/(one-x));
+ if(hx>=0) return t; else return -t;
+}
--- /dev/null
+/* e_atanhf.c -- float version of e_atanh.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/src/e_atanhf.c,v 1.7 2008/02/22 02:30:34 das Exp $");
+
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+static const float one = 1.0, huge = 1e30;
+
+static const float zero = 0.0;
+
+OLM_DLLEXPORT float
+__ieee754_atanhf(float x)
+{
+ float t;
+ int32_t hx,ix;
+ GET_FLOAT_WORD(hx,x);
+ ix = hx&0x7fffffff;
+ if (ix>0x3f800000) /* |x|>1 */
+ return (x-x)/(x-x);
+ if(ix==0x3f800000)
+ return x/zero;
+ if(ix<0x31800000&&(huge+x)>zero) return x; /* x<2**-28 */
+ SET_FLOAT_WORD(x,ix);
+ if(ix<0x3f000000) { /* x < 0.5 */
+ t = x+x;
+ t = (float)0.5*log1pf(t+t*x/(one-x));
+ } else
+ t = (float)0.5*log1pf((x+x)/(one-x));
+ if(hx>=0) return t; else return -t;
+}
--- /dev/null
+
+/* @(#)e_cosh.c 1.3 95/01/18 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunSoft, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/src/e_cosh.c,v 1.10 2011/10/21 06:28:47 das Exp $");
+
+/* __ieee754_cosh(x)
+ * Method :
+ * mathematically cosh(x) if defined to be (exp(x)+exp(-x))/2
+ * 1. Replace x by |x| (cosh(x) = cosh(-x)).
+ * 2.
+ * [ exp(x) - 1 ]^2
+ * 0 <= x <= ln2/2 : cosh(x) := 1 + -------------------
+ * 2*exp(x)
+ *
+ * exp(x) + 1/exp(x)
+ * ln2/2 <= x <= 22 : cosh(x) := -------------------
+ * 2
+ * 22 <= x <= lnovft : cosh(x) := exp(x)/2
+ * lnovft <= x <= ln2ovft: cosh(x) := exp(x/2)/2 * exp(x/2)
+ * ln2ovft < x : cosh(x) := huge*huge (overflow)
+ *
+ * Special cases:
+ * cosh(x) is |x| if x is +INF, -INF, or NaN.
+ * only cosh(0)=1 is exact for finite x.
+ */
+
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+static const double one = 1.0, half=0.5, huge = 1.0e300;
+
+OLM_DLLEXPORT double
+__ieee754_cosh(double x)
+{
+ double t,w;
+ int32_t ix;
+
+ /* High word of |x|. */
+ GET_HIGH_WORD(ix,x);
+ ix &= 0x7fffffff;
+
+ /* x is INF or NaN */
+ if(ix>=0x7ff00000) return x*x;
+
+ /* |x| in [0,0.5*ln2], return 1+expm1(|x|)^2/(2*exp(|x|)) */
+ if(ix<0x3fd62e43) {
+ t = expm1(fabs(x));
+ w = one+t;
+ if (ix<0x3c800000) return w; /* cosh(tiny) = 1 */
+ return one+(t*t)/(w+w);
+ }
+
+ /* |x| in [0.5*ln2,22], return (exp(|x|)+1/exp(|x|)/2; */
+ if (ix < 0x40360000) {
+ t = __ieee754_exp(fabs(x));
+ return half*t+half/t;
+ }
+
+ /* |x| in [22, log(maxdouble)] return half*exp(|x|) */
+ if (ix < 0x40862E42) return half*__ieee754_exp(fabs(x));
+
+ /* |x| in [log(maxdouble), overflowthresold] */
+ if (ix<=0x408633CE)
+ return __ldexp_exp(fabs(x), -1);
+
+ /* |x| > overflowthresold, cosh(x) overflow */
+ return huge*huge;
+}
--- /dev/null
+/* e_coshf.c -- float version of e_cosh.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/src/e_coshf.c,v 1.9 2011/10/21 06:28:47 das Exp $");
+
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+static const float one = 1.0, half=0.5, huge = 1.0e30;
+
+OLM_DLLEXPORT float
+__ieee754_coshf(float x)
+{
+ float t,w;
+ int32_t ix;
+
+ GET_FLOAT_WORD(ix,x);
+ ix &= 0x7fffffff;
+
+ /* x is INF or NaN */
+ if(ix>=0x7f800000) return x*x;
+
+ /* |x| in [0,0.5*ln2], return 1+expm1(|x|)^2/(2*exp(|x|)) */
+ if(ix<0x3eb17218) {
+ t = expm1f(fabsf(x));
+ w = one+t;
+ if (ix<0x39800000) return one; /* cosh(tiny) = 1 */
+ return one+(t*t)/(w+w);
+ }
+
+ /* |x| in [0.5*ln2,9], return (exp(|x|)+1/exp(|x|))/2; */
+ if (ix < 0x41100000) {
+ t = __ieee754_expf(fabsf(x));
+ return half*t+half/t;
+ }
+
+ /* |x| in [9, log(maxfloat)] return half*exp(|x|) */
+ if (ix < 0x42b17217) return half*__ieee754_expf(fabsf(x));
+
+ /* |x| in [log(maxfloat), overflowthresold] */
+ if (ix<=0x42b2d4fc)
+ return __ldexp_expf(fabsf(x), -1);
+
+ /* |x| > overflowthresold, cosh(x) overflow */
+ return huge*huge;
+}
--- /dev/null
+
+/* @(#)e_exp.c 1.6 04/04/22 */
+/*
+ * ====================================================
+ * Copyright (C) 2004 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/src/e_exp.c,v 1.14 2011/10/21 06:26:38 das Exp $");
+
+/* __ieee754_exp(x)
+ * Returns the exponential of x.
+ *
+ * Method
+ * 1. Argument reduction:
+ * Reduce x to an r so that |r| <= 0.5*ln2 ~ 0.34658.
+ * Given x, find r and integer k such that
+ *
+ * x = k*ln2 + r, |r| <= 0.5*ln2.
+ *
+ * Here r will be represented as r = hi-lo for better
+ * accuracy.
+ *
+ * 2. Approximation of exp(r) by a special rational function on
+ * the interval [0,0.34658]:
+ * Write
+ * R(r**2) = r*(exp(r)+1)/(exp(r)-1) = 2 + r*r/6 - r**4/360 + ...
+ * We use a special Remes algorithm on [0,0.34658] to generate
+ * a polynomial of degree 5 to approximate R. The maximum error
+ * of this polynomial approximation is bounded by 2**-59. In
+ * other words,
+ * R(z) ~ 2.0 + P1*z + P2*z**2 + P3*z**3 + P4*z**4 + P5*z**5
+ * (where z=r*r, and the values of P1 to P5 are listed below)
+ * and
+ * | 5 | -59
+ * | 2.0+P1*z+...+P5*z - R(z) | <= 2
+ * | |
+ * The computation of exp(r) thus becomes
+ * 2*r
+ * exp(r) = 1 + -------
+ * R - r
+ * r*R1(r)
+ * = 1 + r + ----------- (for better accuracy)
+ * 2 - R1(r)
+ * where
+ * 2 4 10
+ * R1(r) = r - (P1*r + P2*r + ... + P5*r ).
+ *
+ * 3. Scale back to obtain exp(x):
+ * From step 1, we have
+ * exp(x) = 2^k * exp(r)
+ *
+ * Special cases:
+ * exp(INF) is INF, exp(NaN) is NaN;
+ * exp(-INF) is 0, and
+ * for finite argument, only exp(0)=1 is exact.
+ *
+ * Accuracy:
+ * according to an error analysis, the error is always less than
+ * 1 ulp (unit in the last place).
+ *
+ * Misc. info.
+ * For IEEE double
+ * if x > 7.09782712893383973096e+02 then exp(x) overflow
+ * if x < -7.45133219101941108420e+02 then exp(x) underflow
+ *
+ * Constants:
+ * The hexadecimal values are the intended ones for the following
+ * constants. The decimal values may be used, provided that the
+ * compiler will convert from decimal to binary accurately enough
+ * to produce the hexadecimal values shown.
+ */
+
+#include <float.h>
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+static const double
+one = 1.0,
+halF[2] = {0.5,-0.5,},
+huge = 1.0e+300,
+o_threshold= 7.09782712893383973096e+02, /* 0x40862E42, 0xFEFA39EF */
+u_threshold= -7.45133219101941108420e+02, /* 0xc0874910, 0xD52D3051 */
+ln2HI[2] ={ 6.93147180369123816490e-01, /* 0x3fe62e42, 0xfee00000 */
+ -6.93147180369123816490e-01,},/* 0xbfe62e42, 0xfee00000 */
+ln2LO[2] ={ 1.90821492927058770002e-10, /* 0x3dea39ef, 0x35793c76 */
+ -1.90821492927058770002e-10,},/* 0xbdea39ef, 0x35793c76 */
+invln2 = 1.44269504088896338700e+00, /* 0x3ff71547, 0x652b82fe */
+P1 = 1.66666666666666019037e-01, /* 0x3FC55555, 0x5555553E */
+P2 = -2.77777777770155933842e-03, /* 0xBF66C16C, 0x16BEBD93 */
+P3 = 6.61375632143793436117e-05, /* 0x3F11566A, 0xAF25DE2C */
+P4 = -1.65339022054652515390e-06, /* 0xBEBBBD41, 0xC5D26BF1 */
+P5 = 4.13813679705723846039e-08; /* 0x3E663769, 0x72BEA4D0 */
+
+static volatile double
+twom1000= 9.33263618503218878990e-302; /* 2**-1000=0x01700000,0*/
+
+OLM_DLLEXPORT double
+__ieee754_exp(double x) /* default IEEE double exp */
+{
+ double y,hi=0.0,lo=0.0,c,t,twopk;
+ int32_t k=0,xsb;
+ u_int32_t hx;
+
+ GET_HIGH_WORD(hx,x);
+ xsb = (hx>>31)&1; /* sign bit of x */
+ hx &= 0x7fffffff; /* high word of |x| */
+
+ /* filter out non-finite argument */
+ if(hx >= 0x40862E42) { /* if |x|>=709.78... */
+ if(hx>=0x7ff00000) {
+ u_int32_t lx;
+ GET_LOW_WORD(lx,x);
+ if(((hx&0xfffff)|lx)!=0)
+ return x+x; /* NaN */
+ else return (xsb==0)? x:0.0; /* exp(+-inf)={inf,0} */
+ }
+ if(x > o_threshold) return huge*huge; /* overflow */
+ if(x < u_threshold) return twom1000*twom1000; /* underflow */
+ }
+
+ /* this implementation gives 2.7182818284590455 for exp(1.0),
+ which is well within the allowable error. however,
+ 2.718281828459045 is closer to the true value so we prefer that
+ answer, given that 1.0 is such an important argument value. */
+ if (x == 1.0)
+ return 2.718281828459045235360;
+
+ /* argument reduction */
+ if(hx > 0x3fd62e42) { /* if |x| > 0.5 ln2 */
+ if(hx < 0x3FF0A2B2) { /* and |x| < 1.5 ln2 */
+ hi = x-ln2HI[xsb]; lo=ln2LO[xsb]; k = 1-xsb-xsb;
+ } else {
+ k = (int)(invln2*x+halF[xsb]);
+ t = k;
+ hi = x - t*ln2HI[0]; /* t*ln2HI is exact here */
+ lo = t*ln2LO[0];
+ }
+ STRICT_ASSIGN(double, x, hi - lo);
+ }
+ else if(hx < 0x3e300000) { /* when |x|<2**-28 */
+ if(huge+x>one) return one+x;/* trigger inexact */
+ }
+ else k = 0;
+
+ /* x is now in primary range */
+ t = x*x;
+ if(k >= -1021)
+ INSERT_WORDS(twopk,0x3ff00000+(k<<20), 0);
+ else
+ INSERT_WORDS(twopk,0x3ff00000+((k+1000)<<20), 0);
+ c = x - t*(P1+t*(P2+t*(P3+t*(P4+t*P5))));
+ if(k==0) return one-((x*c)/(c-2.0)-x);
+ else y = one-((lo-(x*c)/(2.0-c))-hi);
+ if(k >= -1021) {
+ if (k==1024) return y*2.0*0x1p1023;
+ return y*twopk;
+ } else {
+ return y*twopk*twom1000;
+ }
+}
--- /dev/null
+/* e_expf.c -- float version of e_exp.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/src/e_expf.c,v 1.16 2011/10/21 06:26:38 das Exp $");
+
+#include <float.h>
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+static const float
+one = 1.0,
+halF[2] = {0.5,-0.5,},
+huge = 1.0e+30,
+o_threshold= 8.8721679688e+01, /* 0x42b17180 */
+u_threshold= -1.0397208405e+02, /* 0xc2cff1b5 */
+ln2HI[2] ={ 6.9314575195e-01, /* 0x3f317200 */
+ -6.9314575195e-01,}, /* 0xbf317200 */
+ln2LO[2] ={ 1.4286067653e-06, /* 0x35bfbe8e */
+ -1.4286067653e-06,}, /* 0xb5bfbe8e */
+invln2 = 1.4426950216e+00, /* 0x3fb8aa3b */
+/*
+ * Domain [-0.34568, 0.34568], range ~[-4.278e-9, 4.447e-9]:
+ * |x*(exp(x)+1)/(exp(x)-1) - p(x)| < 2**-27.74
+ */
+P1 = 1.6666625440e-1, /* 0xaaaa8f.0p-26 */
+P2 = -2.7667332906e-3; /* -0xb55215.0p-32 */
+
+static volatile float twom100 = 7.8886090522e-31; /* 2**-100=0x0d800000 */
+
+OLM_DLLEXPORT float
+__ieee754_expf(float x)
+{
+ float y,hi=0.0,lo=0.0,c,t,twopk;
+ int32_t k=0,xsb;
+ u_int32_t hx;
+
+ GET_FLOAT_WORD(hx,x);
+ xsb = (hx>>31)&1; /* sign bit of x */
+ hx &= 0x7fffffff; /* high word of |x| */
+
+ /* filter out non-finite argument */
+ if(hx >= 0x42b17218) { /* if |x|>=88.721... */
+ if(hx>0x7f800000)
+ return x+x; /* NaN */
+ if(hx==0x7f800000)
+ return (xsb==0)? x:0.0; /* exp(+-inf)={inf,0} */
+ if(x > o_threshold) return huge*huge; /* overflow */
+ if(x < u_threshold) return twom100*twom100; /* underflow */
+ }
+
+ /* argument reduction */
+ if(hx > 0x3eb17218) { /* if |x| > 0.5 ln2 */
+ if(hx < 0x3F851592) { /* and |x| < 1.5 ln2 */
+ hi = x-ln2HI[xsb]; lo=ln2LO[xsb]; k = 1-xsb-xsb;
+ } else {
+ k = invln2*x+halF[xsb];
+ t = k;
+ hi = x - t*ln2HI[0]; /* t*ln2HI is exact here */
+ lo = t*ln2LO[0];
+ }
+ STRICT_ASSIGN(float, x, hi - lo);
+ }
+ else if(hx < 0x39000000) { /* when |x|<2**-14 */
+ if(huge+x>one) return one+x;/* trigger inexact */
+ }
+ else k = 0;
+
+ /* x is now in primary range */
+ t = x*x;
+ if(k >= -125)
+ SET_FLOAT_WORD(twopk,0x3f800000+(k<<23));
+ else
+ SET_FLOAT_WORD(twopk,0x3f800000+((k+100)<<23));
+ c = x - t*(P1+t*P2);
+ if(k==0) return one-((x*c)/(c-(float)2.0)-x);
+ else y = one-((lo-(x*c)/((float)2.0-c))-hi);
+ if(k >= -125) {
+ if(k==128) return y*2.0F*0x1p127F;
+ return y*twopk;
+ } else {
+ return y*twopk*twom100;
+ }
+}
--- /dev/null
+
+/* @(#)e_fmod.c 1.3 95/01/18 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunSoft, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/src/e_fmod.c,v 1.10 2008/02/22 02:30:34 das Exp $");
+
+/*
+ * __ieee754_fmod(x,y)
+ * Return x mod y in exact arithmetic
+ * Method: shift and subtract
+ */
+
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+static const double one = 1.0, Zero[] = {0.0, -0.0,};
+
+OLM_DLLEXPORT double
+__ieee754_fmod(double x, double y)
+{
+ int32_t n,hx,hy,hz,ix,iy,sx,i;
+ u_int32_t lx,ly,lz;
+
+ EXTRACT_WORDS(hx,lx,x);
+ EXTRACT_WORDS(hy,ly,y);
+ sx = hx&0x80000000; /* sign of x */
+ hx ^=sx; /* |x| */
+ hy &= 0x7fffffff; /* |y| */
+
+ /* purge off exception values */
+ if((hy|ly)==0||(hx>=0x7ff00000)|| /* y=0,or x not finite */
+ ((hy|((ly|-ly)>>31))>0x7ff00000)) /* or y is NaN */
+ return (x*y)/(x*y);
+ if(hx<=hy) {
+ if((hx<hy)||(lx<ly)) return x; /* |x|<|y| return x */
+ if(lx==ly)
+ return Zero[(u_int32_t)sx>>31]; /* |x|=|y| return x*0*/
+ }
+
+ /* determine ix = ilogb(x) */
+ if(hx<0x00100000) { /* subnormal x */
+ if(hx==0) {
+ for (ix = -1043, i=lx; i>0; i<<=1) ix -=1;
+ } else {
+ for (ix = -1022,i=(hx<<11); i>0; i<<=1) ix -=1;
+ }
+ } else ix = (hx>>20)-1023;
+
+ /* determine iy = ilogb(y) */
+ if(hy<0x00100000) { /* subnormal y */
+ if(hy==0) {
+ for (iy = -1043, i=ly; i>0; i<<=1) iy -=1;
+ } else {
+ for (iy = -1022,i=(hy<<11); i>0; i<<=1) iy -=1;
+ }
+ } else iy = (hy>>20)-1023;
+
+ /* set up {hx,lx}, {hy,ly} and align y to x */
+ if(ix >= -1022)
+ hx = 0x00100000|(0x000fffff&hx);
+ else { /* subnormal x, shift x to normal */
+ n = -1022-ix;
+ if(n<=31) {
+ hx = (hx<<n)|(lx>>(32-n));
+ lx <<= n;
+ } else {
+ hx = lx<<(n-32);
+ lx = 0;
+ }
+ }
+ if(iy >= -1022)
+ hy = 0x00100000|(0x000fffff&hy);
+ else { /* subnormal y, shift y to normal */
+ n = -1022-iy;
+ if(n<=31) {
+ hy = (hy<<n)|(ly>>(32-n));
+ ly <<= n;
+ } else {
+ hy = ly<<(n-32);
+ ly = 0;
+ }
+ }
+
+ /* fix point fmod */
+ n = ix - iy;
+ while(n--) {
+ hz=hx-hy;lz=lx-ly; if(lx<ly) hz -= 1;
+ if(hz<0){hx = hx+hx+(lx>>31); lx = lx+lx;}
+ else {
+ if((hz|lz)==0) /* return sign(x)*0 */
+ return Zero[(u_int32_t)sx>>31];
+ hx = hz+hz+(lz>>31); lx = lz+lz;
+ }
+ }
+ hz=hx-hy;lz=lx-ly; if(lx<ly) hz -= 1;
+ if(hz>=0) {hx=hz;lx=lz;}
+
+ /* convert back to floating value and restore the sign */
+ if((hx|lx)==0) /* return sign(x)*0 */
+ return Zero[(u_int32_t)sx>>31];
+ while(hx<0x00100000) { /* normalize x */
+ hx = hx+hx+(lx>>31); lx = lx+lx;
+ iy -= 1;
+ }
+ if(iy>= -1022) { /* normalize output */
+ hx = ((hx-0x00100000)|((iy+1023)<<20));
+ INSERT_WORDS(x,hx|sx,lx);
+ } else { /* subnormal output */
+ n = -1022 - iy;
+ if(n<=20) {
+ lx = (lx>>n)|((u_int32_t)hx<<(32-n));
+ hx >>= n;
+ } else if (n<=31) {
+ lx = (hx<<(32-n))|(lx>>n); hx = sx;
+ } else {
+ lx = hx>>(n-32); hx = sx;
+ }
+ INSERT_WORDS(x,hx|sx,lx);
+ x *= one; /* create necessary signal */
+ }
+ return x; /* exact output */
+}
--- /dev/null
+/* e_fmodf.c -- float version of e_fmod.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/src/e_fmodf.c,v 1.7 2008/02/22 02:30:34 das Exp $");
+
+/*
+ * __ieee754_fmodf(x,y)
+ * Return x mod y in exact arithmetic
+ * Method: shift and subtract
+ */
+
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+static const float one = 1.0, Zero[] = {0.0, -0.0,};
+
+OLM_DLLEXPORT float
+__ieee754_fmodf(float x, float y)
+{
+ int32_t n,hx,hy,hz,ix,iy,sx,i;
+
+ GET_FLOAT_WORD(hx,x);
+ GET_FLOAT_WORD(hy,y);
+ sx = hx&0x80000000; /* sign of x */
+ hx ^=sx; /* |x| */
+ hy &= 0x7fffffff; /* |y| */
+
+ /* purge off exception values */
+ if(hy==0||(hx>=0x7f800000)|| /* y=0,or x not finite */
+ (hy>0x7f800000)) /* or y is NaN */
+ return (x*y)/(x*y);
+ if(hx<hy) return x; /* |x|<|y| return x */
+ if(hx==hy)
+ return Zero[(u_int32_t)sx>>31]; /* |x|=|y| return x*0*/
+
+ /* determine ix = ilogb(x) */
+ if(hx<0x00800000) { /* subnormal x */
+ for (ix = -126,i=(hx<<8); i>0; i<<=1) ix -=1;
+ } else ix = (hx>>23)-127;
+
+ /* determine iy = ilogb(y) */
+ if(hy<0x00800000) { /* subnormal y */
+ for (iy = -126,i=(hy<<8); i>=0; i<<=1) iy -=1;
+ } else iy = (hy>>23)-127;
+
+ /* set up {hx,lx}, {hy,ly} and align y to x */
+ if(ix >= -126)
+ hx = 0x00800000|(0x007fffff&hx);
+ else { /* subnormal x, shift x to normal */
+ n = -126-ix;
+ hx = hx<<n;
+ }
+ if(iy >= -126)
+ hy = 0x00800000|(0x007fffff&hy);
+ else { /* subnormal y, shift y to normal */
+ n = -126-iy;
+ hy = hy<<n;
+ }
+
+ /* fix point fmod */
+ n = ix - iy;
+ while(n--) {
+ hz=hx-hy;
+ if(hz<0){hx = hx+hx;}
+ else {
+ if(hz==0) /* return sign(x)*0 */
+ return Zero[(u_int32_t)sx>>31];
+ hx = hz+hz;
+ }
+ }
+ hz=hx-hy;
+ if(hz>=0) {hx=hz;}
+
+ /* convert back to floating value and restore the sign */
+ if(hx==0) /* return sign(x)*0 */
+ return Zero[(u_int32_t)sx>>31];
+ while(hx<0x00800000) { /* normalize x */
+ hx = hx+hx;
+ iy -= 1;
+ }
+ if(iy>= -126) { /* normalize output */
+ hx = ((hx-0x00800000)|((iy+127)<<23));
+ SET_FLOAT_WORD(x,hx|sx);
+ } else { /* subnormal output */
+ n = -126 - iy;
+ hx >>= n;
+ SET_FLOAT_WORD(x,hx|sx);
+ x *= one; /* create necessary signal */
+ }
+ return x; /* exact output */
+}
--- /dev/null
+/* @(#)e_fmod.c 1.3 95/01/18 */
+/*-
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunSoft, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/src/e_fmodl.c,v 1.2 2008/07/31 20:09:47 das Exp $");
+
+#include <float.h>
+#include <openlibm_math.h>
+#include <stdint.h>
+
+#include "fpmath.h"
+
+#include "math_private.h"
+
+#define BIAS (LDBL_MAX_EXP - 1)
+
+#if LDBL_MANL_SIZE > 32
+typedef u_int64_t manl_t;
+#else
+typedef u_int32_t manl_t;
+#endif
+
+#if LDBL_MANH_SIZE > 32
+typedef u_int64_t manh_t;
+#else
+typedef u_int32_t manh_t;
+#endif
+
+/*
+ * These macros add and remove an explicit integer bit in front of the
+ * fractional mantissa, if the architecture doesn't have such a bit by
+ * default already.
+ */
+#ifdef LDBL_IMPLICIT_NBIT
+#define SET_NBIT(hx) ((hx) | (1ULL << LDBL_MANH_SIZE))
+#define HFRAC_BITS LDBL_MANH_SIZE
+#else
+#define SET_NBIT(hx) (hx)
+#define HFRAC_BITS (LDBL_MANH_SIZE - 1)
+#endif
+
+#define MANL_SHIFT (LDBL_MANL_SIZE - 1)
+
+static const long double one = 1.0, Zero[] = {0.0, -0.0,};
+
+/*
+ * fmodl(x,y)
+ * Return x mod y in exact arithmetic
+ * Method: shift and subtract
+ *
+ * Assumptions:
+ * - The low part of the mantissa fits in a manl_t exactly.
+ * - The high part of the mantissa fits in an int64_t with enough room
+ * for an explicit integer bit in front of the fractional bits.
+ */
+OLM_DLLEXPORT long double
+fmodl(long double x, long double y)
+{
+ union IEEEl2bits ux, uy;
+ int64_t hx,hz; /* We need a carry bit even if LDBL_MANH_SIZE is 32. */
+ manh_t hy;
+ manl_t lx,ly,lz;
+ int ix,iy,n,sx;
+
+ ux.e = x;
+ uy.e = y;
+ sx = ux.bits.sign;
+
+ /* purge off exception values */
+ if((uy.bits.exp|uy.bits.manh|uy.bits.manl)==0 || /* y=0 */
+ (ux.bits.exp == BIAS + LDBL_MAX_EXP) || /* or x not finite */
+ (uy.bits.exp == BIAS + LDBL_MAX_EXP &&
+ ((uy.bits.manh&~LDBL_NBIT)|uy.bits.manl)!=0)) /* or y is NaN */
+ return (x*y)/(x*y);
+ if(ux.bits.exp<=uy.bits.exp) {
+ if((ux.bits.exp<uy.bits.exp) ||
+ (ux.bits.manh<=uy.bits.manh &&
+ (ux.bits.manh<uy.bits.manh ||
+ ux.bits.manl<uy.bits.manl))) {
+ return x; /* |x|<|y| return x or x-y */
+ }
+ if(ux.bits.manh==uy.bits.manh && ux.bits.manl==uy.bits.manl) {
+ return Zero[sx]; /* |x|=|y| return x*0*/
+ }
+ }
+
+ /* determine ix = ilogb(x) */
+ if(ux.bits.exp == 0) { /* subnormal x */
+ ux.e *= 0x1.0p512;
+ ix = ux.bits.exp - (BIAS + 512);
+ } else {
+ ix = ux.bits.exp - BIAS;
+ }
+
+ /* determine iy = ilogb(y) */
+ if(uy.bits.exp == 0) { /* subnormal y */
+ uy.e *= 0x1.0p512;
+ iy = uy.bits.exp - (BIAS + 512);
+ } else {
+ iy = uy.bits.exp - BIAS;
+ }
+
+ /* set up {hx,lx}, {hy,ly} and align y to x */
+ hx = SET_NBIT(ux.bits.manh);
+ hy = SET_NBIT(uy.bits.manh);
+ lx = ux.bits.manl;
+ ly = uy.bits.manl;
+
+ /* fix point fmod */
+ n = ix - iy;
+
+ while(n--) {
+ hz=hx-hy;lz=lx-ly; if(lx<ly) hz -= 1;
+ if(hz<0){hx = hx+hx+(lx>>MANL_SHIFT); lx = lx+lx;}
+ else {
+ if ((hz|lz)==0) /* return sign(x)*0 */
+ return Zero[sx];
+ hx = hz+hz+(lz>>MANL_SHIFT); lx = lz+lz;
+ }
+ }
+ hz=hx-hy;lz=lx-ly; if(lx<ly) hz -= 1;
+ if(hz>=0) {hx=hz;lx=lz;}
+
+ /* convert back to floating value and restore the sign */
+ if((hx|lx)==0) /* return sign(x)*0 */
+ return Zero[sx];
+ while(hx<(1ULL<<HFRAC_BITS)) { /* normalize x */
+ hx = hx+hx+(lx>>MANL_SHIFT); lx = lx+lx;
+ iy -= 1;
+ }
+ ux.bits.manh = hx; /* The mantissa is truncated here if needed. */
+ ux.bits.manl = lx;
+ if (iy < LDBL_MIN_EXP) {
+ ux.bits.exp = iy + (BIAS + 512);
+ ux.e *= 0x1p-512;
+ } else {
+ ux.bits.exp = iy + BIAS;
+ }
+ x = ux.e * one; /* create necessary signal */
+ return x; /* exact output */
+}
--- /dev/null
+
+/* @(#)e_hypot.c 1.3 95/01/18 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunSoft, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/src/e_hypot.c,v 1.14 2011/10/15 07:00:28 das Exp $");
+
+/* __ieee754_hypot(x,y)
+ *
+ * Method :
+ * If (assume round-to-nearest) z=x*x+y*y
+ * has error less than sqrt(2)/2 ulp, than
+ * sqrt(z) has error less than 1 ulp (exercise).
+ *
+ * So, compute sqrt(x*x+y*y) with some care as
+ * follows to get the error below 1 ulp:
+ *
+ * Assume x>y>0;
+ * (if possible, set rounding to round-to-nearest)
+ * 1. if x > 2y use
+ * x1*x1+(y*y+(x2*(x+x1))) for x*x+y*y
+ * where x1 = x with lower 32 bits cleared, x2 = x-x1; else
+ * 2. if x <= 2y use
+ * t1*y1+((x-y)*(x-y)+(t1*y2+t2*y))
+ * where t1 = 2x with lower 32 bits cleared, t2 = 2x-t1,
+ * y1= y with lower 32 bits chopped, y2 = y-y1.
+ *
+ * NOTE: scaling may be necessary if some argument is too
+ * large or too tiny
+ *
+ * Special cases:
+ * hypot(x,y) is INF if x or y is +INF or -INF; else
+ * hypot(x,y) is NAN if x or y is NAN.
+ *
+ * Accuracy:
+ * hypot(x,y) returns sqrt(x^2+y^2) with error less
+ * than 1 ulps (units in the last place)
+ */
+
+#include <float.h>
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+OLM_DLLEXPORT double
+__ieee754_hypot(double x, double y)
+{
+ double a,b,t1,t2,y1,y2,w;
+ int32_t j,k,ha,hb;
+
+ GET_HIGH_WORD(ha,x);
+ ha &= 0x7fffffff;
+ GET_HIGH_WORD(hb,y);
+ hb &= 0x7fffffff;
+ if(hb > ha) {a=y;b=x;j=ha; ha=hb;hb=j;} else {a=x;b=y;}
+ a = fabs(a);
+ b = fabs(b);
+ if((ha-hb)>0x3c00000) {return a+b;} /* x/y > 2**60 */
+ k=0;
+ if(ha > 0x5f300000) { /* a>2**500 */
+ if(ha >= 0x7ff00000) { /* Inf or NaN */
+ u_int32_t low;
+ /* Use original arg order iff result is NaN; quieten sNaNs. */
+ w = fabs(x+0.0)-fabs(y+0.0);
+ GET_LOW_WORD(low,a);
+ if(((ha&0xfffff)|low)==0) w = a;
+ GET_LOW_WORD(low,b);
+ if(((hb^0x7ff00000)|low)==0) w = b;
+ return w;
+ }
+ /* scale a and b by 2**-600 */
+ ha -= 0x25800000; hb -= 0x25800000; k += 600;
+ SET_HIGH_WORD(a,ha);
+ SET_HIGH_WORD(b,hb);
+ }
+ if(hb < 0x20b00000) { /* b < 2**-500 */
+ if(hb <= 0x000fffff) { /* subnormal b or 0 */
+ u_int32_t low;
+ GET_LOW_WORD(low,b);
+ if((hb|low)==0) return a;
+ t1=0;
+ SET_HIGH_WORD(t1,0x7fd00000); /* t1=2^1022 */
+ b *= t1;
+ a *= t1;
+ k -= 1022;
+ } else { /* scale a and b by 2^600 */
+ ha += 0x25800000; /* a *= 2^600 */
+ hb += 0x25800000; /* b *= 2^600 */
+ k -= 600;
+ SET_HIGH_WORD(a,ha);
+ SET_HIGH_WORD(b,hb);
+ }
+ }
+ /* medium size a and b */
+ w = a-b;
+ if (w>b) {
+ t1 = 0;
+ SET_HIGH_WORD(t1,ha);
+ t2 = a-t1;
+ w = sqrt(t1*t1-(b*(-b)-t2*(a+t1)));
+ } else {
+ a = a+a;
+ y1 = 0;
+ SET_HIGH_WORD(y1,hb);
+ y2 = b - y1;
+ t1 = 0;
+ SET_HIGH_WORD(t1,ha+0x00100000);
+ t2 = a - t1;
+ w = sqrt(t1*y1-(w*(-w)-(t1*y2+t2*b)));
+ }
+ if(k!=0) {
+ u_int32_t high;
+ t1 = 1.0;
+ GET_HIGH_WORD(high,t1);
+ SET_HIGH_WORD(t1,high+(k<<20));
+ return t1*w;
+ } else return w;
+}
+
+#if LDBL_MANT_DIG == 53
+__weak_reference(hypot, hypotl);
+#endif
--- /dev/null
+/* e_hypotf.c -- float version of e_hypot.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/src/e_hypotf.c,v 1.14 2011/10/15 07:00:28 das Exp $");
+
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+OLM_DLLEXPORT float
+__ieee754_hypotf(float x, float y)
+{
+ float a,b,t1,t2,y1,y2,w;
+ int32_t j,k,ha,hb;
+
+ GET_FLOAT_WORD(ha,x);
+ ha &= 0x7fffffff;
+ GET_FLOAT_WORD(hb,y);
+ hb &= 0x7fffffff;
+ if(hb > ha) {a=y;b=x;j=ha; ha=hb;hb=j;} else {a=x;b=y;}
+ a = fabsf(a);
+ b = fabsf(b);
+ if((ha-hb)>0xf000000) {return a+b;} /* x/y > 2**30 */
+ k=0;
+ if(ha > 0x58800000) { /* a>2**50 */
+ if(ha >= 0x7f800000) { /* Inf or NaN */
+ /* Use original arg order iff result is NaN; quieten sNaNs. */
+ w = fabsf(x+0.0F)-fabsf(y+0.0F);
+ if(ha == 0x7f800000) w = a;
+ if(hb == 0x7f800000) w = b;
+ return w;
+ }
+ /* scale a and b by 2**-68 */
+ ha -= 0x22000000; hb -= 0x22000000; k += 68;
+ SET_FLOAT_WORD(a,ha);
+ SET_FLOAT_WORD(b,hb);
+ }
+ if(hb < 0x26800000) { /* b < 2**-50 */
+ if(hb <= 0x007fffff) { /* subnormal b or 0 */
+ if(hb==0) return a;
+ SET_FLOAT_WORD(t1,0x7e800000); /* t1=2^126 */
+ b *= t1;
+ a *= t1;
+ k -= 126;
+ } else { /* scale a and b by 2^68 */
+ ha += 0x22000000; /* a *= 2^68 */
+ hb += 0x22000000; /* b *= 2^68 */
+ k -= 68;
+ SET_FLOAT_WORD(a,ha);
+ SET_FLOAT_WORD(b,hb);
+ }
+ }
+ /* medium size a and b */
+ w = a-b;
+ if (w>b) {
+ SET_FLOAT_WORD(t1,ha&0xfffff000);
+ t2 = a-t1;
+ w = __ieee754_sqrtf(t1*t1-(b*(-b)-t2*(a+t1)));
+ } else {
+ a = a+a;
+ SET_FLOAT_WORD(y1,hb&0xfffff000);
+ y2 = b - y1;
+ SET_FLOAT_WORD(t1,(ha+0x00800000)&0xfffff000);
+ t2 = a - t1;
+ w = __ieee754_sqrtf(t1*y1-(w*(-w)-(t1*y2+t2*b)));
+ }
+ if(k!=0) {
+ SET_FLOAT_WORD(t1,0x3f800000+(k<<23));
+ return t1*w;
+ } else return w;
+}
--- /dev/null
+/* From: @(#)e_hypot.c 1.3 95/01/18 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunSoft, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/src/e_hypotl.c,v 1.3 2011/10/16 05:36:39 das Exp $");
+
+/* long double version of hypot(). See e_hypot.c for most comments. */
+
+#include <float.h>
+#include <openlibm_math.h>
+
+#include "fpmath.h"
+#include "math_private.h"
+
+#define GET_LDBL_MAN(h, l, v) do { \
+ union IEEEl2bits uv; \
+ \
+ uv.e = v; \
+ h = uv.bits.manh; \
+ l = uv.bits.manl; \
+} while (0)
+
+#undef GET_HIGH_WORD
+#define GET_HIGH_WORD(i, v) GET_LDBL_EXPSIGN(i, v)
+#undef SET_HIGH_WORD
+#define SET_HIGH_WORD(v, i) SET_LDBL_EXPSIGN(v, i)
+
+#define DESW(exp) (exp) /* delta expsign word */
+#define ESW(exp) (MAX_EXP - 1 + (exp)) /* expsign word */
+#define MANT_DIG LDBL_MANT_DIG
+#define MAX_EXP LDBL_MAX_EXP
+
+#if LDBL_MANL_SIZE > 32
+typedef u_int64_t man_t;
+#else
+typedef u_int32_t man_t;
+#endif
+
+OLM_DLLEXPORT long double
+hypotl(long double x, long double y)
+{
+ long double a=x,b=y,t1,t2,y1,y2,w;
+ int32_t j,k,ha,hb;
+
+ GET_HIGH_WORD(ha,x);
+ ha &= 0x7fff;
+ GET_HIGH_WORD(hb,y);
+ hb &= 0x7fff;
+ if(hb > ha) {a=y;b=x;j=ha; ha=hb;hb=j;} else {a=x;b=y;}
+ a = fabsl(a);
+ b = fabsl(b);
+ if((ha-hb)>DESW(MANT_DIG+7)) {return a+b;} /* x/y > 2**(MANT_DIG+7) */
+ k=0;
+ if(ha > ESW(MAX_EXP/2-12)) { /* a>2**(MAX_EXP/2-12) */
+ if(ha >= ESW(MAX_EXP)) { /* Inf or NaN */
+ man_t manh, manl;
+ /* Use original arg order iff result is NaN; quieten sNaNs. */
+ w = fabsl(x+0.0)-fabsl(y+0.0);
+ GET_LDBL_MAN(manh,manl,a);
+ if (manh == LDBL_NBIT && manl == 0) w = a;
+ GET_LDBL_MAN(manh,manl,b);
+ if (hb >= ESW(MAX_EXP) && manh == LDBL_NBIT && manl == 0) w = b;
+ return w;
+ }
+ /* scale a and b by 2**-(MAX_EXP/2+88) */
+ ha -= DESW(MAX_EXP/2+88); hb -= DESW(MAX_EXP/2+88);
+ k += MAX_EXP/2+88;
+ SET_HIGH_WORD(a,ha);
+ SET_HIGH_WORD(b,hb);
+ }
+ if(hb < ESW(-(MAX_EXP/2-12))) { /* b < 2**-(MAX_EXP/2-12) */
+ if(hb <= 0) { /* subnormal b or 0 */
+ man_t manh, manl;
+ GET_LDBL_MAN(manh,manl,b);
+ if((manh|manl)==0) return a;
+ t1=0;
+ SET_HIGH_WORD(t1,ESW(MAX_EXP-2)); /* t1=2^(MAX_EXP-2) */
+ b *= t1;
+ a *= t1;
+ k -= MAX_EXP-2;
+ } else { /* scale a and b by 2^(MAX_EXP/2+88) */
+ ha += DESW(MAX_EXP/2+88);
+ hb += DESW(MAX_EXP/2+88);
+ k -= MAX_EXP/2+88;
+ SET_HIGH_WORD(a,ha);
+ SET_HIGH_WORD(b,hb);
+ }
+ }
+ /* medium size a and b */
+ w = a-b;
+ if (w>b) {
+ t1 = a;
+ union IEEEl2bits uv;
+ uv.e = t1; uv.bits.manl = 0; t1 = uv.e;
+ t2 = a-t1;
+ w = sqrtl(t1*t1-(b*(-b)-t2*(a+t1)));
+ } else {
+ a = a+a;
+ y1 = b;
+ union IEEEl2bits uv;
+ uv.e = y1; uv.bits.manl = 0; y1 = uv.e;
+ y2 = b - y1;
+ t1 = a;
+ uv.e = t1; uv.bits.manl = 0; t1 = uv.e;
+ t2 = a - t1;
+ w = sqrtl(t1*y1-(w*(-w)-(t1*y2+t2*b)));
+ }
+ if(k!=0) {
+ u_int32_t high;
+ t1 = 1.0;
+ GET_HIGH_WORD(high,t1);
+ SET_HIGH_WORD(t1,high+DESW(k));
+ return t1*w;
+ } else return w;
+}
--- /dev/null
+
+/* @(#)e_j0.c 1.3 95/01/18 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunSoft, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include <assert.h>
+
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/src/e_j0.c,v 1.9 2008/02/22 02:30:35 das Exp $");
+
+/* __ieee754_j0(x), __ieee754_y0(x)
+ * Bessel function of the first and second kinds of order zero.
+ * Method -- j0(x):
+ * 1. For tiny x, we use j0(x) = 1 - x^2/4 + x^4/64 - ...
+ * 2. Reduce x to |x| since j0(x)=j0(-x), and
+ * for x in (0,2)
+ * j0(x) = 1-z/4+ z^2*R0/S0, where z = x*x;
+ * (precision: |j0-1+z/4-z^2R0/S0 |<2**-63.67 )
+ * for x in (2,inf)
+ * j0(x) = sqrt(2/(pi*x))*(p0(x)*cos(x0)-q0(x)*sin(x0))
+ * where x0 = x-pi/4. It is better to compute sin(x0),cos(x0)
+ * as follow:
+ * cos(x0) = cos(x)cos(pi/4)+sin(x)sin(pi/4)
+ * = 1/sqrt(2) * (cos(x) + sin(x))
+ * sin(x0) = sin(x)cos(pi/4)-cos(x)sin(pi/4)
+ * = 1/sqrt(2) * (sin(x) - cos(x))
+ * (To avoid cancellation, use
+ * sin(x) +- cos(x) = -cos(2x)/(sin(x) -+ cos(x))
+ * to compute the worse one.)
+ *
+ * 3 Special cases
+ * j0(nan)= nan
+ * j0(0) = 1
+ * j0(inf) = 0
+ *
+ * Method -- y0(x):
+ * 1. For x<2.
+ * Since
+ * y0(x) = 2/pi*(j0(x)*(ln(x/2)+Euler) + x^2/4 - ...)
+ * therefore y0(x)-2/pi*j0(x)*ln(x) is an even function.
+ * We use the following function to approximate y0,
+ * y0(x) = U(z)/V(z) + (2/pi)*(j0(x)*ln(x)), z= x^2
+ * where
+ * U(z) = u00 + u01*z + ... + u06*z^6
+ * V(z) = 1 + v01*z + ... + v04*z^4
+ * with absolute approximation error bounded by 2**-72.
+ * Note: For tiny x, U/V = u0 and j0(x)~1, hence
+ * y0(tiny) = u0 + (2/pi)*ln(tiny), (choose tiny<2**-27)
+ * 2. For x>=2.
+ * y0(x) = sqrt(2/(pi*x))*(p0(x)*cos(x0)+q0(x)*sin(x0))
+ * where x0 = x-pi/4. It is better to compute sin(x0),cos(x0)
+ * by the method mentioned above.
+ * 3. Special cases: y0(0)=-inf, y0(x<0)=NaN, y0(inf)=0.
+ */
+
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+static double pzero(double), qzero(double);
+
+static const double
+huge = 1e300,
+one = 1.0,
+invsqrtpi= 5.64189583547756279280e-01, /* 0x3FE20DD7, 0x50429B6D */
+tpi = 6.36619772367581382433e-01, /* 0x3FE45F30, 0x6DC9C883 */
+ /* R0/S0 on [0, 2.00] */
+R02 = 1.56249999999999947958e-02, /* 0x3F8FFFFF, 0xFFFFFFFD */
+R03 = -1.89979294238854721751e-04, /* 0xBF28E6A5, 0xB61AC6E9 */
+R04 = 1.82954049532700665670e-06, /* 0x3EBEB1D1, 0x0C503919 */
+R05 = -4.61832688532103189199e-09, /* 0xBE33D5E7, 0x73D63FCE */
+S01 = 1.56191029464890010492e-02, /* 0x3F8FFCE8, 0x82C8C2A4 */
+S02 = 1.16926784663337450260e-04, /* 0x3F1EA6D2, 0xDD57DBF4 */
+S03 = 5.13546550207318111446e-07, /* 0x3EA13B54, 0xCE84D5A9 */
+S04 = 1.16614003333790000205e-09; /* 0x3E1408BC, 0xF4745D8F */
+
+static const double zero = 0.0;
+
+OLM_DLLEXPORT double
+__ieee754_j0(double x)
+{
+ double z, s,c,ss,cc,r,u,v;
+ int32_t hx,ix;
+
+ GET_HIGH_WORD(hx,x);
+ ix = hx&0x7fffffff;
+ if(ix>=0x7ff00000) return one/(x*x);
+ x = fabs(x);
+ if(ix >= 0x40000000) { /* |x| >= 2.0 */
+ s = sin(x);
+ c = cos(x);
+ ss = s-c;
+ cc = s+c;
+ if(ix<0x7fe00000) { /* make sure x+x not overflow */
+ z = -cos(x+x);
+ if ((s*c)<zero) cc = z/ss;
+ else ss = z/cc;
+ }
+ /*
+ * j0(x) = 1/sqrt(pi) * (P(0,x)*cc - Q(0,x)*ss) / sqrt(x)
+ * y0(x) = 1/sqrt(pi) * (P(0,x)*ss + Q(0,x)*cc) / sqrt(x)
+ */
+ if(ix>0x48000000) z = (invsqrtpi*cc)/sqrt(x);
+ else {
+ u = pzero(x); v = qzero(x);
+ z = invsqrtpi*(u*cc-v*ss)/sqrt(x);
+ }
+ return z;
+ }
+ if(ix<0x3f200000) { /* |x| < 2**-13 */
+ if(huge+x>one) { /* raise inexact if x != 0 */
+ if(ix<0x3e400000) return one; /* |x|<2**-27 */
+ else return one - 0.25*x*x;
+ }
+ }
+ z = x*x;
+ r = z*(R02+z*(R03+z*(R04+z*R05)));
+ s = one+z*(S01+z*(S02+z*(S03+z*S04)));
+ if(ix < 0x3FF00000) { /* |x| < 1.00 */
+ return one + z*(-0.25+(r/s));
+ } else {
+ u = 0.5*x;
+ return((one+u)*(one-u)+z*(r/s));
+ }
+}
+
+static const double
+u00 = -7.38042951086872317523e-02, /* 0xBFB2E4D6, 0x99CBD01F */
+u01 = 1.76666452509181115538e-01, /* 0x3FC69D01, 0x9DE9E3FC */
+u02 = -1.38185671945596898896e-02, /* 0xBF8C4CE8, 0xB16CFA97 */
+u03 = 3.47453432093683650238e-04, /* 0x3F36C54D, 0x20B29B6B */
+u04 = -3.81407053724364161125e-06, /* 0xBECFFEA7, 0x73D25CAD */
+u05 = 1.95590137035022920206e-08, /* 0x3E550057, 0x3B4EABD4 */
+u06 = -3.98205194132103398453e-11, /* 0xBDC5E43D, 0x693FB3C8 */
+v01 = 1.27304834834123699328e-02, /* 0x3F8A1270, 0x91C9C71A */
+v02 = 7.60068627350353253702e-05, /* 0x3F13ECBB, 0xF578C6C1 */
+v03 = 2.59150851840457805467e-07, /* 0x3E91642D, 0x7FF202FD */
+v04 = 4.41110311332675467403e-10; /* 0x3DFE5018, 0x3BD6D9EF */
+
+OLM_DLLEXPORT double
+__ieee754_y0(double x)
+{
+ double z, s,c,ss,cc,u,v;
+ int32_t hx,ix,lx;
+
+ EXTRACT_WORDS(hx,lx,x);
+ ix = 0x7fffffff&hx;
+ /* Y0(NaN) is NaN, y0(-inf) is Nan, y0(inf) is 0 */
+ if(ix>=0x7ff00000) return one/(x+x*x);
+ if((ix|lx)==0) return -one/zero;
+ if(hx<0) return zero/zero;
+ if(ix >= 0x40000000) { /* |x| >= 2.0 */
+ /* y0(x) = sqrt(2/(pi*x))*(p0(x)*sin(x0)+q0(x)*cos(x0))
+ * where x0 = x-pi/4
+ * Better formula:
+ * cos(x0) = cos(x)cos(pi/4)+sin(x)sin(pi/4)
+ * = 1/sqrt(2) * (sin(x) + cos(x))
+ * sin(x0) = sin(x)cos(3pi/4)-cos(x)sin(3pi/4)
+ * = 1/sqrt(2) * (sin(x) - cos(x))
+ * To avoid cancellation, use
+ * sin(x) +- cos(x) = -cos(2x)/(sin(x) -+ cos(x))
+ * to compute the worse one.
+ */
+ s = sin(x);
+ c = cos(x);
+ ss = s-c;
+ cc = s+c;
+ /*
+ * j0(x) = 1/sqrt(pi) * (P(0,x)*cc - Q(0,x)*ss) / sqrt(x)
+ * y0(x) = 1/sqrt(pi) * (P(0,x)*ss + Q(0,x)*cc) / sqrt(x)
+ */
+ if(ix<0x7fe00000) { /* make sure x+x not overflow */
+ z = -cos(x+x);
+ if ((s*c)<zero) cc = z/ss;
+ else ss = z/cc;
+ }
+ if(ix>0x48000000) z = (invsqrtpi*ss)/sqrt(x);
+ else {
+ u = pzero(x); v = qzero(x);
+ z = invsqrtpi*(u*ss+v*cc)/sqrt(x);
+ }
+ return z;
+ }
+ if(ix<=0x3e400000) { /* x < 2**-27 */
+ return(u00 + tpi*__ieee754_log(x));
+ }
+ z = x*x;
+ u = u00+z*(u01+z*(u02+z*(u03+z*(u04+z*(u05+z*u06)))));
+ v = one+z*(v01+z*(v02+z*(v03+z*v04)));
+ return(u/v + tpi*(__ieee754_j0(x)*__ieee754_log(x)));
+}
+
+/* The asymptotic expansions of pzero is
+ * 1 - 9/128 s^2 + 11025/98304 s^4 - ..., where s = 1/x.
+ * For x >= 2, We approximate pzero by
+ * pzero(x) = 1 + (R/S)
+ * where R = pR0 + pR1*s^2 + pR2*s^4 + ... + pR5*s^10
+ * S = 1 + pS0*s^2 + ... + pS4*s^10
+ * and
+ * | pzero(x)-1-R/S | <= 2 ** ( -60.26)
+ */
+static const double pR8[6] = { /* for x in [inf, 8]=1/[0,0.125] */
+ 0.00000000000000000000e+00, /* 0x00000000, 0x00000000 */
+ -7.03124999999900357484e-02, /* 0xBFB1FFFF, 0xFFFFFD32 */
+ -8.08167041275349795626e+00, /* 0xC02029D0, 0xB44FA779 */
+ -2.57063105679704847262e+02, /* 0xC0701102, 0x7B19E863 */
+ -2.48521641009428822144e+03, /* 0xC0A36A6E, 0xCD4DCAFC */
+ -5.25304380490729545272e+03, /* 0xC0B4850B, 0x36CC643D */
+};
+static const double pS8[5] = {
+ 1.16534364619668181717e+02, /* 0x405D2233, 0x07A96751 */
+ 3.83374475364121826715e+03, /* 0x40ADF37D, 0x50596938 */
+ 4.05978572648472545552e+04, /* 0x40E3D2BB, 0x6EB6B05F */
+ 1.16752972564375915681e+05, /* 0x40FC810F, 0x8F9FA9BD */
+ 4.76277284146730962675e+04, /* 0x40E74177, 0x4F2C49DC */
+};
+
+static const double pR5[6] = { /* for x in [8,4.5454]=1/[0.125,0.22001] */
+ -1.14125464691894502584e-11, /* 0xBDA918B1, 0x47E495CC */
+ -7.03124940873599280078e-02, /* 0xBFB1FFFF, 0xE69AFBC6 */
+ -4.15961064470587782438e+00, /* 0xC010A370, 0xF90C6BBF */
+ -6.76747652265167261021e+01, /* 0xC050EB2F, 0x5A7D1783 */
+ -3.31231299649172967747e+02, /* 0xC074B3B3, 0x6742CC63 */
+ -3.46433388365604912451e+02, /* 0xC075A6EF, 0x28A38BD7 */
+};
+static const double pS5[5] = {
+ 6.07539382692300335975e+01, /* 0x404E6081, 0x0C98C5DE */
+ 1.05125230595704579173e+03, /* 0x40906D02, 0x5C7E2864 */
+ 5.97897094333855784498e+03, /* 0x40B75AF8, 0x8FBE1D60 */
+ 9.62544514357774460223e+03, /* 0x40C2CCB8, 0xFA76FA38 */
+ 2.40605815922939109441e+03, /* 0x40A2CC1D, 0xC70BE864 */
+};
+
+static const double pR3[6] = {/* for x in [4.547,2.8571]=1/[0.2199,0.35001] */
+ -2.54704601771951915620e-09, /* 0xBE25E103, 0x6FE1AA86 */
+ -7.03119616381481654654e-02, /* 0xBFB1FFF6, 0xF7C0E24B */
+ -2.40903221549529611423e+00, /* 0xC00345B2, 0xAEA48074 */
+ -2.19659774734883086467e+01, /* 0xC035F74A, 0x4CB94E14 */
+ -5.80791704701737572236e+01, /* 0xC04D0A22, 0x420A1A45 */
+ -3.14479470594888503854e+01, /* 0xC03F72AC, 0xA892D80F */
+};
+static const double pS3[5] = {
+ 3.58560338055209726349e+01, /* 0x4041ED92, 0x84077DD3 */
+ 3.61513983050303863820e+02, /* 0x40769839, 0x464A7C0E */
+ 1.19360783792111533330e+03, /* 0x4092A66E, 0x6D1061D6 */
+ 1.12799679856907414432e+03, /* 0x40919FFC, 0xB8C39B7E */
+ 1.73580930813335754692e+02, /* 0x4065B296, 0xFC379081 */
+};
+
+static const double pR2[6] = {/* for x in [2.8570,2]=1/[0.3499,0.5] */
+ -8.87534333032526411254e-08, /* 0xBE77D316, 0xE927026D */
+ -7.03030995483624743247e-02, /* 0xBFB1FF62, 0x495E1E42 */
+ -1.45073846780952986357e+00, /* 0xBFF73639, 0x8A24A843 */
+ -7.63569613823527770791e+00, /* 0xC01E8AF3, 0xEDAFA7F3 */
+ -1.11931668860356747786e+01, /* 0xC02662E6, 0xC5246303 */
+ -3.23364579351335335033e+00, /* 0xC009DE81, 0xAF8FE70F */
+};
+static const double pS2[5] = {
+ 2.22202997532088808441e+01, /* 0x40363865, 0x908B5959 */
+ 1.36206794218215208048e+02, /* 0x4061069E, 0x0EE8878F */
+ 2.70470278658083486789e+02, /* 0x4070E786, 0x42EA079B */
+ 1.53875394208320329881e+02, /* 0x40633C03, 0x3AB6FAFF */
+ 1.46576176948256193810e+01, /* 0x402D50B3, 0x44391809 */
+};
+
+ /* Note: This function is only called for ix>=0x40000000 (see above) */
+ static double pzero(double x)
+{
+ const double *p,*q;
+ double z,r,s;
+ int32_t ix;
+ GET_HIGH_WORD(ix,x);
+ ix &= 0x7fffffff;
+ assert(ix>=0x40000000 && ix<=0x48000000);
+ if(ix>=0x40200000) {p = pR8; q= pS8;}
+ else if(ix>=0x40122E8B){p = pR5; q= pS5;}
+ else if(ix>=0x4006DB6D){p = pR3; q= pS3;}
+ else {p = pR2; q= pS2;}
+ z = one/(x*x);
+ r = p[0]+z*(p[1]+z*(p[2]+z*(p[3]+z*(p[4]+z*p[5]))));
+ s = one+z*(q[0]+z*(q[1]+z*(q[2]+z*(q[3]+z*q[4]))));
+ return one+ r/s;
+}
+
+
+/* For x >= 8, the asymptotic expansions of qzero is
+ * -1/8 s + 75/1024 s^3 - ..., where s = 1/x.
+ * We approximate pzero by
+ * qzero(x) = s*(-1.25 + (R/S))
+ * where R = qR0 + qR1*s^2 + qR2*s^4 + ... + qR5*s^10
+ * S = 1 + qS0*s^2 + ... + qS5*s^12
+ * and
+ * | qzero(x)/s +1.25-R/S | <= 2 ** ( -61.22)
+ */
+static const double qR8[6] = { /* for x in [inf, 8]=1/[0,0.125] */
+ 0.00000000000000000000e+00, /* 0x00000000, 0x00000000 */
+ 7.32421874999935051953e-02, /* 0x3FB2BFFF, 0xFFFFFE2C */
+ 1.17682064682252693899e+01, /* 0x40278952, 0x5BB334D6 */
+ 5.57673380256401856059e+02, /* 0x40816D63, 0x15301825 */
+ 8.85919720756468632317e+03, /* 0x40C14D99, 0x3E18F46D */
+ 3.70146267776887834771e+04, /* 0x40E212D4, 0x0E901566 */
+};
+static const double qS8[6] = {
+ 1.63776026895689824414e+02, /* 0x406478D5, 0x365B39BC */
+ 8.09834494656449805916e+03, /* 0x40BFA258, 0x4E6B0563 */
+ 1.42538291419120476348e+05, /* 0x41016652, 0x54D38C3F */
+ 8.03309257119514397345e+05, /* 0x412883DA, 0x83A52B43 */
+ 8.40501579819060512818e+05, /* 0x4129A66B, 0x28DE0B3D */
+ -3.43899293537866615225e+05, /* 0xC114FD6D, 0x2C9530C5 */
+};
+
+static const double qR5[6] = { /* for x in [8,4.5454]=1/[0.125,0.22001] */
+ 1.84085963594515531381e-11, /* 0x3DB43D8F, 0x29CC8CD9 */
+ 7.32421766612684765896e-02, /* 0x3FB2BFFF, 0xD172B04C */
+ 5.83563508962056953777e+00, /* 0x401757B0, 0xB9953DD3 */
+ 1.35111577286449829671e+02, /* 0x4060E392, 0x0A8788E9 */
+ 1.02724376596164097464e+03, /* 0x40900CF9, 0x9DC8C481 */
+ 1.98997785864605384631e+03, /* 0x409F17E9, 0x53C6E3A6 */
+};
+static const double qS5[6] = {
+ 8.27766102236537761883e+01, /* 0x4054B1B3, 0xFB5E1543 */
+ 2.07781416421392987104e+03, /* 0x40A03BA0, 0xDA21C0CE */
+ 1.88472887785718085070e+04, /* 0x40D267D2, 0x7B591E6D */
+ 5.67511122894947329769e+04, /* 0x40EBB5E3, 0x97E02372 */
+ 3.59767538425114471465e+04, /* 0x40E19118, 0x1F7A54A0 */
+ -5.35434275601944773371e+03, /* 0xC0B4EA57, 0xBEDBC609 */
+};
+
+static const double qR3[6] = {/* for x in [4.547,2.8571]=1/[0.2199,0.35001] */
+ 4.37741014089738620906e-09, /* 0x3E32CD03, 0x6ADECB82 */
+ 7.32411180042911447163e-02, /* 0x3FB2BFEE, 0x0E8D0842 */
+ 3.34423137516170720929e+00, /* 0x400AC0FC, 0x61149CF5 */
+ 4.26218440745412650017e+01, /* 0x40454F98, 0x962DAEDD */
+ 1.70808091340565596283e+02, /* 0x406559DB, 0xE25EFD1F */
+ 1.66733948696651168575e+02, /* 0x4064D77C, 0x81FA21E0 */
+};
+static const double qS3[6] = {
+ 4.87588729724587182091e+01, /* 0x40486122, 0xBFE343A6 */
+ 7.09689221056606015736e+02, /* 0x40862D83, 0x86544EB3 */
+ 3.70414822620111362994e+03, /* 0x40ACF04B, 0xE44DFC63 */
+ 6.46042516752568917582e+03, /* 0x40B93C6C, 0xD7C76A28 */
+ 2.51633368920368957333e+03, /* 0x40A3A8AA, 0xD94FB1C0 */
+ -1.49247451836156386662e+02, /* 0xC062A7EB, 0x201CF40F */
+};
+
+static const double qR2[6] = {/* for x in [2.8570,2]=1/[0.3499,0.5] */
+ 1.50444444886983272379e-07, /* 0x3E84313B, 0x54F76BDB */
+ 7.32234265963079278272e-02, /* 0x3FB2BEC5, 0x3E883E34 */
+ 1.99819174093815998816e+00, /* 0x3FFFF897, 0xE727779C */
+ 1.44956029347885735348e+01, /* 0x402CFDBF, 0xAAF96FE5 */
+ 3.16662317504781540833e+01, /* 0x403FAA8E, 0x29FBDC4A */
+ 1.62527075710929267416e+01, /* 0x403040B1, 0x71814BB4 */
+};
+static const double qS2[6] = {
+ 3.03655848355219184498e+01, /* 0x403E5D96, 0xF7C07AED */
+ 2.69348118608049844624e+02, /* 0x4070D591, 0xE4D14B40 */
+ 8.44783757595320139444e+02, /* 0x408A6645, 0x22B3BF22 */
+ 8.82935845112488550512e+02, /* 0x408B977C, 0x9C5CC214 */
+ 2.12666388511798828631e+02, /* 0x406A9553, 0x0E001365 */
+ -5.31095493882666946917e+00, /* 0xC0153E6A, 0xF8B32931 */
+};
+
+ /* Note: This function is only called for ix>=0x40000000 (see above) */
+ static double qzero(double x)
+{
+ const double *p,*q;
+ double s,r,z;
+ int32_t ix;
+ GET_HIGH_WORD(ix,x);
+ ix &= 0x7fffffff;
+ assert(ix>=0x40000000 && ix<=0x48000000);
+ if(ix>=0x40200000) {p = qR8; q= qS8;}
+ else if(ix>=0x40122E8B){p = qR5; q= qS5;}
+ else if(ix>=0x4006DB6D){p = qR3; q= qS3;}
+ else {p = qR2; q= qS2;}
+ z = one/(x*x);
+ r = p[0]+z*(p[1]+z*(p[2]+z*(p[3]+z*(p[4]+z*p[5]))));
+ s = one+z*(q[0]+z*(q[1]+z*(q[2]+z*(q[3]+z*(q[4]+z*q[5])))));
+ return (-.125 + r/s)/x;
+}
--- /dev/null
+/* e_j0f.c -- float version of e_j0.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include <assert.h>
+#include "cdefs-compat.h"
+
+#include <openlibm_math.h>
+#include "math_private.h"
+
+static float pzerof(float), qzerof(float);
+
+static const float
+huge = 1e30,
+one = 1.0,
+invsqrtpi= 5.6418961287e-01, /* 0x3f106ebb */
+tpi = 6.3661974669e-01, /* 0x3f22f983 */
+ /* R0/S0 on [0, 2.00] */
+R02 = 1.5625000000e-02, /* 0x3c800000 */
+R03 = -1.8997929874e-04, /* 0xb947352e */
+R04 = 1.8295404516e-06, /* 0x35f58e88 */
+R05 = -4.6183270541e-09, /* 0xb19eaf3c */
+S01 = 1.5619102865e-02, /* 0x3c7fe744 */
+S02 = 1.1692678527e-04, /* 0x38f53697 */
+S03 = 5.1354652442e-07, /* 0x3509daa6 */
+S04 = 1.1661400734e-09; /* 0x30a045e8 */
+
+static const float zero = 0.0;
+
+OLM_DLLEXPORT float
+__ieee754_j0f(float x)
+{
+ float z, s,c,ss,cc,r,u,v;
+ int32_t hx,ix;
+
+ GET_FLOAT_WORD(hx,x);
+ ix = hx&0x7fffffff;
+ if(ix>=0x7f800000) return one/(x*x);
+ x = fabsf(x);
+ if(ix >= 0x40000000) { /* |x| >= 2.0 */
+ s = sinf(x);
+ c = cosf(x);
+ ss = s-c;
+ cc = s+c;
+ if(ix<0x7f000000) { /* make sure x+x not overflow */
+ z = -cosf(x+x);
+ if ((s*c)<zero) cc = z/ss;
+ else ss = z/cc;
+ }
+ /*
+ * j0(x) = 1/sqrt(pi) * (P(0,x)*cc - Q(0,x)*ss) / sqrt(x)
+ * y0(x) = 1/sqrt(pi) * (P(0,x)*ss + Q(0,x)*cc) / sqrt(x)
+ */
+ if(ix>0x58000000) z = (invsqrtpi*cc)/sqrtf(x); /* |x|>2**49 */
+ else {
+ u = pzerof(x); v = qzerof(x);
+ z = invsqrtpi*(u*cc-v*ss)/sqrtf(x);
+ }
+ return z;
+ }
+ if(ix<0x3b000000) { /* |x| < 2**-9 */
+ if(huge+x>one) { /* raise inexact if x != 0 */
+ if(ix<0x39800000) return one; /* |x|<2**-12 */
+ else return one - x*x/4;
+ }
+ }
+ z = x*x;
+ r = z*(R02+z*(R03+z*(R04+z*R05)));
+ s = one+z*(S01+z*(S02+z*(S03+z*S04)));
+ if(ix < 0x3F800000) { /* |x| < 1.00 */
+ return one + z*((float)-0.25+(r/s));
+ } else {
+ u = (float)0.5*x;
+ return((one+u)*(one-u)+z*(r/s));
+ }
+}
+
+static const float
+u00 = -7.3804296553e-02, /* 0xbd9726b5 */
+u01 = 1.7666645348e-01, /* 0x3e34e80d */
+u02 = -1.3818567619e-02, /* 0xbc626746 */
+u03 = 3.4745343146e-04, /* 0x39b62a69 */
+u04 = -3.8140706238e-06, /* 0xb67ff53c */
+u05 = 1.9559013964e-08, /* 0x32a802ba */
+u06 = -3.9820518410e-11, /* 0xae2f21eb */
+v01 = 1.2730483897e-02, /* 0x3c509385 */
+v02 = 7.6006865129e-05, /* 0x389f65e0 */
+v03 = 2.5915085189e-07, /* 0x348b216c */
+v04 = 4.4111031494e-10; /* 0x2ff280c2 */
+
+OLM_DLLEXPORT float
+__ieee754_y0f(float x)
+{
+ float z, s,c,ss,cc,u,v;
+ int32_t hx,ix;
+
+ GET_FLOAT_WORD(hx,x);
+ ix = 0x7fffffff&hx;
+ /* Y0(NaN) is NaN, y0(-inf) is Nan, y0(inf) is 0 */
+ if(ix>=0x7f800000) return one/(x+x*x);
+ if(ix==0) return -one/zero;
+ if(hx<0) return zero/zero;
+ if(ix >= 0x40000000) { /* |x| >= 2.0 */
+ /* y0(x) = sqrt(2/(pi*x))*(p0(x)*sin(x0)+q0(x)*cos(x0))
+ * where x0 = x-pi/4
+ * Better formula:
+ * cos(x0) = cos(x)cos(pi/4)+sin(x)sin(pi/4)
+ * = 1/sqrt(2) * (sin(x) + cos(x))
+ * sin(x0) = sin(x)cos(3pi/4)-cos(x)sin(3pi/4)
+ * = 1/sqrt(2) * (sin(x) - cos(x))
+ * To avoid cancellation, use
+ * sin(x) +- cos(x) = -cos(2x)/(sin(x) -+ cos(x))
+ * to compute the worse one.
+ */
+ s = sinf(x);
+ c = cosf(x);
+ ss = s-c;
+ cc = s+c;
+ /*
+ * j0(x) = 1/sqrt(pi) * (P(0,x)*cc - Q(0,x)*ss) / sqrt(x)
+ * y0(x) = 1/sqrt(pi) * (P(0,x)*ss + Q(0,x)*cc) / sqrt(x)
+ */
+ if(ix<0x7f000000) { /* make sure x+x not overflow */
+ z = -cosf(x+x);
+ if ((s*c)<zero) cc = z/ss;
+ else ss = z/cc;
+ }
+ if(ix>0x58000000) z = (invsqrtpi*ss)/sqrtf(x); /* |x|>2**49 */
+ else {
+ u = pzerof(x); v = qzerof(x);
+ z = invsqrtpi*(u*ss+v*cc)/sqrtf(x);
+ }
+ return z;
+ }
+ if(ix<=0x39000000) { /* x < 2**-13 */
+ return(u00 + tpi*__ieee754_logf(x));
+ }
+ z = x*x;
+ u = u00+z*(u01+z*(u02+z*(u03+z*(u04+z*(u05+z*u06)))));
+ v = one+z*(v01+z*(v02+z*(v03+z*v04)));
+ return(u/v + tpi*(__ieee754_j0f(x)*__ieee754_logf(x)));
+}
+
+/* The asymptotic expansions of pzero is
+ * 1 - 9/128 s^2 + 11025/98304 s^4 - ..., where s = 1/x.
+ * For x >= 2, We approximate pzero by
+ * pzero(x) = 1 + (R/S)
+ * where R = pR0 + pR1*s^2 + pR2*s^4 + ... + pR5*s^10
+ * S = 1 + pS0*s^2 + ... + pS4*s^10
+ * and
+ * | pzero(x)-1-R/S | <= 2 ** ( -60.26)
+ */
+static const float pR8[6] = { /* for x in [inf, 8]=1/[0,0.125] */
+ 0.0000000000e+00, /* 0x00000000 */
+ -7.0312500000e-02, /* 0xbd900000 */
+ -8.0816707611e+00, /* 0xc1014e86 */
+ -2.5706311035e+02, /* 0xc3808814 */
+ -2.4852163086e+03, /* 0xc51b5376 */
+ -5.2530439453e+03, /* 0xc5a4285a */
+};
+static const float pS8[5] = {
+ 1.1653436279e+02, /* 0x42e91198 */
+ 3.8337448730e+03, /* 0x456f9beb */
+ 4.0597855469e+04, /* 0x471e95db */
+ 1.1675296875e+05, /* 0x47e4087c */
+ 4.7627726562e+04, /* 0x473a0bba */
+};
+static const float pR5[6] = { /* for x in [8,4.5454]=1/[0.125,0.22001] */
+ -1.1412546255e-11, /* 0xad48c58a */
+ -7.0312492549e-02, /* 0xbd8fffff */
+ -4.1596107483e+00, /* 0xc0851b88 */
+ -6.7674766541e+01, /* 0xc287597b */
+ -3.3123129272e+02, /* 0xc3a59d9b */
+ -3.4643338013e+02, /* 0xc3ad3779 */
+};
+static const float pS5[5] = {
+ 6.0753936768e+01, /* 0x42730408 */
+ 1.0512523193e+03, /* 0x44836813 */
+ 5.9789707031e+03, /* 0x45bad7c4 */
+ 9.6254453125e+03, /* 0x461665c8 */
+ 2.4060581055e+03, /* 0x451660ee */
+};
+
+static const float pR3[6] = {/* for x in [4.547,2.8571]=1/[0.2199,0.35001] */
+ -2.5470459075e-09, /* 0xb12f081b */
+ -7.0311963558e-02, /* 0xbd8fffb8 */
+ -2.4090321064e+00, /* 0xc01a2d95 */
+ -2.1965976715e+01, /* 0xc1afba52 */
+ -5.8079170227e+01, /* 0xc2685112 */
+ -3.1447946548e+01, /* 0xc1fb9565 */
+};
+static const float pS3[5] = {
+ 3.5856033325e+01, /* 0x420f6c94 */
+ 3.6151397705e+02, /* 0x43b4c1ca */
+ 1.1936077881e+03, /* 0x44953373 */
+ 1.1279968262e+03, /* 0x448cffe6 */
+ 1.7358093262e+02, /* 0x432d94b8 */
+};
+
+static const float pR2[6] = {/* for x in [2.8570,2]=1/[0.3499,0.5] */
+ -8.8753431271e-08, /* 0xb3be98b7 */
+ -7.0303097367e-02, /* 0xbd8ffb12 */
+ -1.4507384300e+00, /* 0xbfb9b1cc */
+ -7.6356959343e+00, /* 0xc0f4579f */
+ -1.1193166733e+01, /* 0xc1331736 */
+ -3.2336456776e+00, /* 0xc04ef40d */
+};
+static const float pS2[5] = {
+ 2.2220300674e+01, /* 0x41b1c32d */
+ 1.3620678711e+02, /* 0x430834f0 */
+ 2.7047027588e+02, /* 0x43873c32 */
+ 1.5387539673e+02, /* 0x4319e01a */
+ 1.4657617569e+01, /* 0x416a859a */
+};
+
+ static float pzerof(float x)
+{
+ const float *p,*q;
+ float z,r,s;
+ int32_t ix;
+ GET_FLOAT_WORD(ix,x);
+ ix &= 0x7fffffff;
+ if(ix>=0x41000000) {p = pR8; q= pS8;}
+ else if(ix>=0x409173eb){p = pR5; q= pS5;}
+ else if(ix>=0x4036d917){p = pR3; q= pS3;}
+ else {p = pR2; q= pS2;} /* ix>=0x40000000 */
+ z = one/(x*x);
+ r = p[0]+z*(p[1]+z*(p[2]+z*(p[3]+z*(p[4]+z*p[5]))));
+ s = one+z*(q[0]+z*(q[1]+z*(q[2]+z*(q[3]+z*q[4]))));
+ return one+ r/s;
+}
+
+
+/* For x >= 8, the asymptotic expansions of qzero is
+ * -1/8 s + 75/1024 s^3 - ..., where s = 1/x.
+ * We approximate pzero by
+ * qzero(x) = s*(-1.25 + (R/S))
+ * where R = qR0 + qR1*s^2 + qR2*s^4 + ... + qR5*s^10
+ * S = 1 + qS0*s^2 + ... + qS5*s^12
+ * and
+ * | qzero(x)/s +1.25-R/S | <= 2 ** ( -61.22)
+ */
+static const float qR8[6] = { /* for x in [inf, 8]=1/[0,0.125] */
+ 0.0000000000e+00, /* 0x00000000 */
+ 7.3242187500e-02, /* 0x3d960000 */
+ 1.1768206596e+01, /* 0x413c4a93 */
+ 5.5767340088e+02, /* 0x440b6b19 */
+ 8.8591972656e+03, /* 0x460a6cca */
+ 3.7014625000e+04, /* 0x471096a0 */
+};
+static const float qS8[6] = {
+ 1.6377603149e+02, /* 0x4323c6aa */
+ 8.0983447266e+03, /* 0x45fd12c2 */
+ 1.4253829688e+05, /* 0x480b3293 */
+ 8.0330925000e+05, /* 0x49441ed4 */
+ 8.4050156250e+05, /* 0x494d3359 */
+ -3.4389928125e+05, /* 0xc8a7eb69 */
+};
+
+static const float qR5[6] = { /* for x in [8,4.5454]=1/[0.125,0.22001] */
+ 1.8408595828e-11, /* 0x2da1ec79 */
+ 7.3242180049e-02, /* 0x3d95ffff */
+ 5.8356351852e+00, /* 0x40babd86 */
+ 1.3511157227e+02, /* 0x43071c90 */
+ 1.0272437744e+03, /* 0x448067cd */
+ 1.9899779053e+03, /* 0x44f8bf4b */
+};
+static const float qS5[6] = {
+ 8.2776611328e+01, /* 0x42a58da0 */
+ 2.0778142090e+03, /* 0x4501dd07 */
+ 1.8847289062e+04, /* 0x46933e94 */
+ 5.6751113281e+04, /* 0x475daf1d */
+ 3.5976753906e+04, /* 0x470c88c1 */
+ -5.3543427734e+03, /* 0xc5a752be */
+};
+
+static const float qR3[6] = {/* for x in [4.547,2.8571]=1/[0.2199,0.35001] */
+ 4.3774099900e-09, /* 0x3196681b */
+ 7.3241114616e-02, /* 0x3d95ff70 */
+ 3.3442313671e+00, /* 0x405607e3 */
+ 4.2621845245e+01, /* 0x422a7cc5 */
+ 1.7080809021e+02, /* 0x432acedf */
+ 1.6673394775e+02, /* 0x4326bbe4 */
+};
+static const float qS3[6] = {
+ 4.8758872986e+01, /* 0x42430916 */
+ 7.0968920898e+02, /* 0x44316c1c */
+ 3.7041481934e+03, /* 0x4567825f */
+ 6.4604252930e+03, /* 0x45c9e367 */
+ 2.5163337402e+03, /* 0x451d4557 */
+ -1.4924745178e+02, /* 0xc3153f59 */
+};
+
+static const float qR2[6] = {/* for x in [2.8570,2]=1/[0.3499,0.5] */
+ 1.5044444979e-07, /* 0x342189db */
+ 7.3223426938e-02, /* 0x3d95f62a */
+ 1.9981917143e+00, /* 0x3fffc4bf */
+ 1.4495602608e+01, /* 0x4167edfd */
+ 3.1666231155e+01, /* 0x41fd5471 */
+ 1.6252708435e+01, /* 0x4182058c */
+};
+static const float qS2[6] = {
+ 3.0365585327e+01, /* 0x41f2ecb8 */
+ 2.6934811401e+02, /* 0x4386ac8f */
+ 8.4478375244e+02, /* 0x44533229 */
+ 8.8293585205e+02, /* 0x445cbbe5 */
+ 2.1266638184e+02, /* 0x4354aa98 */
+ -5.3109550476e+00, /* 0xc0a9f358 */
+};
+
+ static float qzerof(float x)
+{
+ const float *p,*q;
+ float s,r,z;
+ int32_t ix;
+ GET_FLOAT_WORD(ix,x);
+ ix &= 0x7fffffff;
+ if(ix>=0x41000000) {p = qR8; q= qS8;}
+ else if(ix>=0x409173eb){p = qR5; q= qS5;}
+ else if(ix>=0x4036d917){p = qR3; q= qS3;}
+ else {p = qR2; q= qS2;} /* ix>=0x40000000 */
+ z = one/(x*x);
+ r = p[0]+z*(p[1]+z*(p[2]+z*(p[3]+z*(p[4]+z*p[5]))));
+ s = one+z*(q[0]+z*(q[1]+z*(q[2]+z*(q[3]+z*(q[4]+z*q[5])))));
+ return (-(float).125 + r/s)/x;
+}
--- /dev/null
+
+/* @(#)e_j1.c 1.3 95/01/18 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunSoft, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include <assert.h>
+
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/src/e_j1.c,v 1.9 2008/02/22 02:30:35 das Exp $");
+
+/* __ieee754_j1(x), __ieee754_y1(x)
+ * Bessel function of the first and second kinds of order zero.
+ * Method -- j1(x):
+ * 1. For tiny x, we use j1(x) = x/2 - x^3/16 + x^5/384 - ...
+ * 2. Reduce x to |x| since j1(x)=-j1(-x), and
+ * for x in (0,2)
+ * j1(x) = x/2 + x*z*R0/S0, where z = x*x;
+ * (precision: |j1/x - 1/2 - R0/S0 |<2**-61.51 )
+ * for x in (2,inf)
+ * j1(x) = sqrt(2/(pi*x))*(p1(x)*cos(x1)-q1(x)*sin(x1))
+ * y1(x) = sqrt(2/(pi*x))*(p1(x)*sin(x1)+q1(x)*cos(x1))
+ * where x1 = x-3*pi/4. It is better to compute sin(x1),cos(x1)
+ * as follow:
+ * cos(x1) = cos(x)cos(3pi/4)+sin(x)sin(3pi/4)
+ * = 1/sqrt(2) * (sin(x) - cos(x))
+ * sin(x1) = sin(x)cos(3pi/4)-cos(x)sin(3pi/4)
+ * = -1/sqrt(2) * (sin(x) + cos(x))
+ * (To avoid cancellation, use
+ * sin(x) +- cos(x) = -cos(2x)/(sin(x) -+ cos(x))
+ * to compute the worse one.)
+ *
+ * 3 Special cases
+ * j1(nan)= nan
+ * j1(0) = 0
+ * j1(inf) = 0
+ *
+ * Method -- y1(x):
+ * 1. screen out x<=0 cases: y1(0)=-inf, y1(x<0)=NaN
+ * 2. For x<2.
+ * Since
+ * y1(x) = 2/pi*(j1(x)*(ln(x/2)+Euler)-1/x-x/2+5/64*x^3-...)
+ * therefore y1(x)-2/pi*j1(x)*ln(x)-1/x is an odd function.
+ * We use the following function to approximate y1,
+ * y1(x) = x*U(z)/V(z) + (2/pi)*(j1(x)*ln(x)-1/x), z= x^2
+ * where for x in [0,2] (abs err less than 2**-65.89)
+ * U(z) = U0[0] + U0[1]*z + ... + U0[4]*z^4
+ * V(z) = 1 + v0[0]*z + ... + v0[4]*z^5
+ * Note: For tiny x, 1/x dominate y1 and hence
+ * y1(tiny) = -2/pi/tiny, (choose tiny<2**-54)
+ * 3. For x>=2.
+ * y1(x) = sqrt(2/(pi*x))*(p1(x)*sin(x1)+q1(x)*cos(x1))
+ * where x1 = x-3*pi/4. It is better to compute sin(x1),cos(x1)
+ * by method mentioned above.
+ */
+
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+static double pone(double), qone(double);
+
+static const double
+huge = 1e300,
+one = 1.0,
+invsqrtpi= 5.64189583547756279280e-01, /* 0x3FE20DD7, 0x50429B6D */
+tpi = 6.36619772367581382433e-01, /* 0x3FE45F30, 0x6DC9C883 */
+ /* R0/S0 on [0,2] */
+r00 = -6.25000000000000000000e-02, /* 0xBFB00000, 0x00000000 */
+r01 = 1.40705666955189706048e-03, /* 0x3F570D9F, 0x98472C61 */
+r02 = -1.59955631084035597520e-05, /* 0xBEF0C5C6, 0xBA169668 */
+r03 = 4.96727999609584448412e-08, /* 0x3E6AAAFA, 0x46CA0BD9 */
+s01 = 1.91537599538363460805e-02, /* 0x3F939D0B, 0x12637E53 */
+s02 = 1.85946785588630915560e-04, /* 0x3F285F56, 0xB9CDF664 */
+s03 = 1.17718464042623683263e-06, /* 0x3EB3BFF8, 0x333F8498 */
+s04 = 5.04636257076217042715e-09, /* 0x3E35AC88, 0xC97DFF2C */
+s05 = 1.23542274426137913908e-11; /* 0x3DAB2ACF, 0xCFB97ED8 */
+
+static const double zero = 0.0;
+
+OLM_DLLEXPORT double
+__ieee754_j1(double x)
+{
+ double z, s,c,ss,cc,r,u,v,y;
+ int32_t hx,ix;
+
+ GET_HIGH_WORD(hx,x);
+ ix = hx&0x7fffffff;
+ if(ix>=0x7ff00000) return one/x;
+ y = fabs(x);
+ if(ix >= 0x40000000) { /* |x| >= 2.0 */
+ s = sin(y);
+ c = cos(y);
+ ss = -s-c;
+ cc = s-c;
+ if(ix<0x7fe00000) { /* make sure y+y not overflow */
+ z = cos(y+y);
+ if ((s*c)>zero) cc = z/ss;
+ else ss = z/cc;
+ }
+ /*
+ * j1(x) = 1/sqrt(pi) * (P(1,x)*cc - Q(1,x)*ss) / sqrt(x)
+ * y1(x) = 1/sqrt(pi) * (P(1,x)*ss + Q(1,x)*cc) / sqrt(x)
+ */
+ if(ix>0x48000000) z = (invsqrtpi*cc)/sqrt(y);
+ else {
+ u = pone(y); v = qone(y);
+ z = invsqrtpi*(u*cc-v*ss)/sqrt(y);
+ }
+ if(hx<0) return -z;
+ else return z;
+ }
+ if(ix<0x3e400000) { /* |x|<2**-27 */
+ if(huge+x>one) return 0.5*x;/* inexact if x!=0 necessary */
+ }
+ z = x*x;
+ r = z*(r00+z*(r01+z*(r02+z*r03)));
+ s = one+z*(s01+z*(s02+z*(s03+z*(s04+z*s05))));
+ r *= x;
+ return(x*0.5+r/s);
+}
+
+static const double U0[5] = {
+ -1.96057090646238940668e-01, /* 0xBFC91866, 0x143CBC8A */
+ 5.04438716639811282616e-02, /* 0x3FA9D3C7, 0x76292CD1 */
+ -1.91256895875763547298e-03, /* 0xBF5F55E5, 0x4844F50F */
+ 2.35252600561610495928e-05, /* 0x3EF8AB03, 0x8FA6B88E */
+ -9.19099158039878874504e-08, /* 0xBE78AC00, 0x569105B8 */
+};
+static const double V0[5] = {
+ 1.99167318236649903973e-02, /* 0x3F94650D, 0x3F4DA9F0 */
+ 2.02552581025135171496e-04, /* 0x3F2A8C89, 0x6C257764 */
+ 1.35608801097516229404e-06, /* 0x3EB6C05A, 0x894E8CA6 */
+ 6.22741452364621501295e-09, /* 0x3E3ABF1D, 0x5BA69A86 */
+ 1.66559246207992079114e-11, /* 0x3DB25039, 0xDACA772A */
+};
+
+OLM_DLLEXPORT double
+__ieee754_y1(double x)
+{
+ double z, s,c,ss,cc,u,v;
+ int32_t hx,ix,lx;
+
+ EXTRACT_WORDS(hx,lx,x);
+ ix = 0x7fffffff&hx;
+ /* if Y1(NaN) is NaN, Y1(-inf) is NaN, Y1(inf) is 0 */
+ if(ix>=0x7ff00000) return one/(x+x*x);
+ if((ix|lx)==0) return -one/zero;
+ if(hx<0) return zero/zero;
+ if(ix >= 0x40000000) { /* |x| >= 2.0 */
+ s = sin(x);
+ c = cos(x);
+ ss = -s-c;
+ cc = s-c;
+ if(ix<0x7fe00000) { /* make sure x+x not overflow */
+ z = cos(x+x);
+ if ((s*c)>zero) cc = z/ss;
+ else ss = z/cc;
+ }
+ /* y1(x) = sqrt(2/(pi*x))*(p1(x)*sin(x0)+q1(x)*cos(x0))
+ * where x0 = x-3pi/4
+ * Better formula:
+ * cos(x0) = cos(x)cos(3pi/4)+sin(x)sin(3pi/4)
+ * = 1/sqrt(2) * (sin(x) - cos(x))
+ * sin(x0) = sin(x)cos(3pi/4)-cos(x)sin(3pi/4)
+ * = -1/sqrt(2) * (cos(x) + sin(x))
+ * To avoid cancellation, use
+ * sin(x) +- cos(x) = -cos(2x)/(sin(x) -+ cos(x))
+ * to compute the worse one.
+ */
+ if(ix>0x48000000) z = (invsqrtpi*ss)/sqrt(x);
+ else {
+ u = pone(x); v = qone(x);
+ z = invsqrtpi*(u*ss+v*cc)/sqrt(x);
+ }
+ return z;
+ }
+ if(ix<=0x3c900000) { /* x < 2**-54 */
+ return(-tpi/x);
+ }
+ z = x*x;
+ u = U0[0]+z*(U0[1]+z*(U0[2]+z*(U0[3]+z*U0[4])));
+ v = one+z*(V0[0]+z*(V0[1]+z*(V0[2]+z*(V0[3]+z*V0[4]))));
+ return(x*(u/v) + tpi*(__ieee754_j1(x)*__ieee754_log(x)-one/x));
+}
+
+/* For x >= 8, the asymptotic expansions of pone is
+ * 1 + 15/128 s^2 - 4725/2^15 s^4 - ..., where s = 1/x.
+ * We approximate pone by
+ * pone(x) = 1 + (R/S)
+ * where R = pr0 + pr1*s^2 + pr2*s^4 + ... + pr5*s^10
+ * S = 1 + ps0*s^2 + ... + ps4*s^10
+ * and
+ * | pone(x)-1-R/S | <= 2 ** ( -60.06)
+ */
+
+static const double pr8[6] = { /* for x in [inf, 8]=1/[0,0.125] */
+ 0.00000000000000000000e+00, /* 0x00000000, 0x00000000 */
+ 1.17187499999988647970e-01, /* 0x3FBDFFFF, 0xFFFFFCCE */
+ 1.32394806593073575129e+01, /* 0x402A7A9D, 0x357F7FCE */
+ 4.12051854307378562225e+02, /* 0x4079C0D4, 0x652EA590 */
+ 3.87474538913960532227e+03, /* 0x40AE457D, 0xA3A532CC */
+ 7.91447954031891731574e+03, /* 0x40BEEA7A, 0xC32782DD */
+};
+static const double ps8[5] = {
+ 1.14207370375678408436e+02, /* 0x405C8D45, 0x8E656CAC */
+ 3.65093083420853463394e+03, /* 0x40AC85DC, 0x964D274F */
+ 3.69562060269033463555e+04, /* 0x40E20B86, 0x97C5BB7F */
+ 9.76027935934950801311e+04, /* 0x40F7D42C, 0xB28F17BB */
+ 3.08042720627888811578e+04, /* 0x40DE1511, 0x697A0B2D */
+};
+
+static const double pr5[6] = { /* for x in [8,4.5454]=1/[0.125,0.22001] */
+ 1.31990519556243522749e-11, /* 0x3DAD0667, 0xDAE1CA7D */
+ 1.17187493190614097638e-01, /* 0x3FBDFFFF, 0xE2C10043 */
+ 6.80275127868432871736e+00, /* 0x401B3604, 0x6E6315E3 */
+ 1.08308182990189109773e+02, /* 0x405B13B9, 0x452602ED */
+ 5.17636139533199752805e+02, /* 0x40802D16, 0xD052D649 */
+ 5.28715201363337541807e+02, /* 0x408085B8, 0xBB7E0CB7 */
+};
+static const double ps5[5] = {
+ 5.92805987221131331921e+01, /* 0x404DA3EA, 0xA8AF633D */
+ 9.91401418733614377743e+02, /* 0x408EFB36, 0x1B066701 */
+ 5.35326695291487976647e+03, /* 0x40B4E944, 0x5706B6FB */
+ 7.84469031749551231769e+03, /* 0x40BEA4B0, 0xB8A5BB15 */
+ 1.50404688810361062679e+03, /* 0x40978030, 0x036F5E51 */
+};
+
+static const double pr3[6] = {
+ 3.02503916137373618024e-09, /* 0x3E29FC21, 0xA7AD9EDD */
+ 1.17186865567253592491e-01, /* 0x3FBDFFF5, 0x5B21D17B */
+ 3.93297750033315640650e+00, /* 0x400F76BC, 0xE85EAD8A */
+ 3.51194035591636932736e+01, /* 0x40418F48, 0x9DA6D129 */
+ 9.10550110750781271918e+01, /* 0x4056C385, 0x4D2C1837 */
+ 4.85590685197364919645e+01, /* 0x4048478F, 0x8EA83EE5 */
+};
+static const double ps3[5] = {
+ 3.47913095001251519989e+01, /* 0x40416549, 0xA134069C */
+ 3.36762458747825746741e+02, /* 0x40750C33, 0x07F1A75F */
+ 1.04687139975775130551e+03, /* 0x40905B7C, 0x5037D523 */
+ 8.90811346398256432622e+02, /* 0x408BD67D, 0xA32E31E9 */
+ 1.03787932439639277504e+02, /* 0x4059F26D, 0x7C2EED53 */
+};
+
+static const double pr2[6] = {/* for x in [2.8570,2]=1/[0.3499,0.5] */
+ 1.07710830106873743082e-07, /* 0x3E7CE9D4, 0xF65544F4 */
+ 1.17176219462683348094e-01, /* 0x3FBDFF42, 0xBE760D83 */
+ 2.36851496667608785174e+00, /* 0x4002F2B7, 0xF98FAEC0 */
+ 1.22426109148261232917e+01, /* 0x40287C37, 0x7F71A964 */
+ 1.76939711271687727390e+01, /* 0x4031B1A8, 0x177F8EE2 */
+ 5.07352312588818499250e+00, /* 0x40144B49, 0xA574C1FE */
+};
+static const double ps2[5] = {
+ 2.14364859363821409488e+01, /* 0x40356FBD, 0x8AD5ECDC */
+ 1.25290227168402751090e+02, /* 0x405F5293, 0x14F92CD5 */
+ 2.32276469057162813669e+02, /* 0x406D08D8, 0xD5A2DBD9 */
+ 1.17679373287147100768e+02, /* 0x405D6B7A, 0xDA1884A9 */
+ 8.36463893371618283368e+00, /* 0x4020BAB1, 0xF44E5192 */
+};
+
+ /* Note: This function is only called for ix>=0x40000000 (see above) */
+ static double pone(double x)
+{
+ const double *p,*q;
+ double z,r,s;
+ int32_t ix;
+ GET_HIGH_WORD(ix,x);
+ ix &= 0x7fffffff;
+ assert(ix>=0x40000000 && ix<=0x48000000);
+ if(ix>=0x40200000) {p = pr8; q= ps8;}
+ else if(ix>=0x40122E8B){p = pr5; q= ps5;}
+ else if(ix>=0x4006DB6D){p = pr3; q= ps3;}
+ else {p = pr2; q= ps2;}
+ z = one/(x*x);
+ r = p[0]+z*(p[1]+z*(p[2]+z*(p[3]+z*(p[4]+z*p[5]))));
+ s = one+z*(q[0]+z*(q[1]+z*(q[2]+z*(q[3]+z*q[4]))));
+ return one+ r/s;
+}
+
+
+/* For x >= 8, the asymptotic expansions of qone is
+ * 3/8 s - 105/1024 s^3 - ..., where s = 1/x.
+ * We approximate pone by
+ * qone(x) = s*(0.375 + (R/S))
+ * where R = qr1*s^2 + qr2*s^4 + ... + qr5*s^10
+ * S = 1 + qs1*s^2 + ... + qs6*s^12
+ * and
+ * | qone(x)/s -0.375-R/S | <= 2 ** ( -61.13)
+ */
+
+static const double qr8[6] = { /* for x in [inf, 8]=1/[0,0.125] */
+ 0.00000000000000000000e+00, /* 0x00000000, 0x00000000 */
+ -1.02539062499992714161e-01, /* 0xBFBA3FFF, 0xFFFFFDF3 */
+ -1.62717534544589987888e+01, /* 0xC0304591, 0xA26779F7 */
+ -7.59601722513950107896e+02, /* 0xC087BCD0, 0x53E4B576 */
+ -1.18498066702429587167e+04, /* 0xC0C724E7, 0x40F87415 */
+ -4.84385124285750353010e+04, /* 0xC0E7A6D0, 0x65D09C6A */
+};
+static const double qs8[6] = {
+ 1.61395369700722909556e+02, /* 0x40642CA6, 0xDE5BCDE5 */
+ 7.82538599923348465381e+03, /* 0x40BE9162, 0xD0D88419 */
+ 1.33875336287249578163e+05, /* 0x4100579A, 0xB0B75E98 */
+ 7.19657723683240939863e+05, /* 0x4125F653, 0x72869C19 */
+ 6.66601232617776375264e+05, /* 0x412457D2, 0x7719AD5C */
+ -2.94490264303834643215e+05, /* 0xC111F969, 0x0EA5AA18 */
+};
+
+static const double qr5[6] = { /* for x in [8,4.5454]=1/[0.125,0.22001] */
+ -2.08979931141764104297e-11, /* 0xBDB6FA43, 0x1AA1A098 */
+ -1.02539050241375426231e-01, /* 0xBFBA3FFF, 0xCB597FEF */
+ -8.05644828123936029840e+00, /* 0xC0201CE6, 0xCA03AD4B */
+ -1.83669607474888380239e+02, /* 0xC066F56D, 0x6CA7B9B0 */
+ -1.37319376065508163265e+03, /* 0xC09574C6, 0x6931734F */
+ -2.61244440453215656817e+03, /* 0xC0A468E3, 0x88FDA79D */
+};
+static const double qs5[6] = {
+ 8.12765501384335777857e+01, /* 0x405451B2, 0xFF5A11B2 */
+ 1.99179873460485964642e+03, /* 0x409F1F31, 0xE77BF839 */
+ 1.74684851924908907677e+04, /* 0x40D10F1F, 0x0D64CE29 */
+ 4.98514270910352279316e+04, /* 0x40E8576D, 0xAABAD197 */
+ 2.79480751638918118260e+04, /* 0x40DB4B04, 0xCF7C364B */
+ -4.71918354795128470869e+03, /* 0xC0B26F2E, 0xFCFFA004 */
+};
+
+static const double qr3[6] = {
+ -5.07831226461766561369e-09, /* 0xBE35CFA9, 0xD38FC84F */
+ -1.02537829820837089745e-01, /* 0xBFBA3FEB, 0x51AEED54 */
+ -4.61011581139473403113e+00, /* 0xC01270C2, 0x3302D9FF */
+ -5.78472216562783643212e+01, /* 0xC04CEC71, 0xC25D16DA */
+ -2.28244540737631695038e+02, /* 0xC06C87D3, 0x4718D55F */
+ -2.19210128478909325622e+02, /* 0xC06B66B9, 0x5F5C1BF6 */
+};
+static const double qs3[6] = {
+ 4.76651550323729509273e+01, /* 0x4047D523, 0xCCD367E4 */
+ 6.73865112676699709482e+02, /* 0x40850EEB, 0xC031EE3E */
+ 3.38015286679526343505e+03, /* 0x40AA684E, 0x448E7C9A */
+ 5.54772909720722782367e+03, /* 0x40B5ABBA, 0xA61D54A6 */
+ 1.90311919338810798763e+03, /* 0x409DBC7A, 0x0DD4DF4B */
+ -1.35201191444307340817e+02, /* 0xC060E670, 0x290A311F */
+};
+
+static const double qr2[6] = {/* for x in [2.8570,2]=1/[0.3499,0.5] */
+ -1.78381727510958865572e-07, /* 0xBE87F126, 0x44C626D2 */
+ -1.02517042607985553460e-01, /* 0xBFBA3E8E, 0x9148B010 */
+ -2.75220568278187460720e+00, /* 0xC0060484, 0x69BB4EDA */
+ -1.96636162643703720221e+01, /* 0xC033A9E2, 0xC168907F */
+ -4.23253133372830490089e+01, /* 0xC04529A3, 0xDE104AAA */
+ -2.13719211703704061733e+01, /* 0xC0355F36, 0x39CF6E52 */
+};
+static const double qs2[6] = {
+ 2.95333629060523854548e+01, /* 0x403D888A, 0x78AE64FF */
+ 2.52981549982190529136e+02, /* 0x406F9F68, 0xDB821CBA */
+ 7.57502834868645436472e+02, /* 0x4087AC05, 0xCE49A0F7 */
+ 7.39393205320467245656e+02, /* 0x40871B25, 0x48D4C029 */
+ 1.55949003336666123687e+02, /* 0x40637E5E, 0x3C3ED8D4 */
+ -4.95949898822628210127e+00, /* 0xC013D686, 0xE71BE86B */
+};
+
+ /* Note: This function is only called for ix>=0x40000000 (see above) */
+ static double qone(double x)
+{
+ const double *p,*q;
+ double s,r,z;
+ int32_t ix;
+ GET_HIGH_WORD(ix,x);
+ ix &= 0x7fffffff;
+ assert(ix>=0x40000000 && ix<=0x48000000);
+ if(ix>=0x40200000) {p = qr8; q= qs8;}
+ else if(ix>=0x40122E8B){p = qr5; q= qs5;}
+ else if(ix>=0x4006DB6D){p = qr3; q= qs3;}
+ else {p = qr2; q= qs2;}
+ z = one/(x*x);
+ r = p[0]+z*(p[1]+z*(p[2]+z*(p[3]+z*(p[4]+z*p[5]))));
+ s = one+z*(q[0]+z*(q[1]+z*(q[2]+z*(q[3]+z*(q[4]+z*q[5])))));
+ return (.375 + r/s)/x;
+}
--- /dev/null
+/* e_j1f.c -- float version of e_j1.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include <assert.h>
+#include "cdefs-compat.h"
+#include <openlibm_math.h>
+#include "math_private.h"
+
+static float ponef(float), qonef(float);
+
+static const float
+huge = 1e30,
+one = 1.0,
+invsqrtpi= 5.6418961287e-01, /* 0x3f106ebb */
+tpi = 6.3661974669e-01, /* 0x3f22f983 */
+ /* R0/S0 on [0,2] */
+r00 = -6.2500000000e-02, /* 0xbd800000 */
+r01 = 1.4070566976e-03, /* 0x3ab86cfd */
+r02 = -1.5995563444e-05, /* 0xb7862e36 */
+r03 = 4.9672799207e-08, /* 0x335557d2 */
+s01 = 1.9153760746e-02, /* 0x3c9ce859 */
+s02 = 1.8594678841e-04, /* 0x3942fab6 */
+s03 = 1.1771846857e-06, /* 0x359dffc2 */
+s04 = 5.0463624390e-09, /* 0x31ad6446 */
+s05 = 1.2354227016e-11; /* 0x2d59567e */
+
+static const float zero = 0.0;
+
+OLM_DLLEXPORT float
+__ieee754_j1f(float x)
+{
+ float z, s,c,ss,cc,r,u,v,y;
+ int32_t hx,ix;
+
+ GET_FLOAT_WORD(hx,x);
+ ix = hx&0x7fffffff;
+ if(ix>=0x7f800000) return one/x;
+ y = fabsf(x);
+ if(ix >= 0x40000000) { /* |x| >= 2.0 */
+ s = sinf(y);
+ c = cosf(y);
+ ss = -s-c;
+ cc = s-c;
+ if(ix<0x7f000000) { /* make sure y+y not overflow */
+ z = cosf(y+y);
+ if ((s*c)>zero) cc = z/ss;
+ else ss = z/cc;
+ }
+ /*
+ * j1(x) = 1/sqrt(pi) * (P(1,x)*cc - Q(1,x)*ss) / sqrt(x)
+ * y1(x) = 1/sqrt(pi) * (P(1,x)*ss + Q(1,x)*cc) / sqrt(x)
+ */
+ if(ix>0x58000000) z = (invsqrtpi*cc)/sqrtf(y); /* |x|>2**49 */
+ else {
+ u = ponef(y); v = qonef(y);
+ z = invsqrtpi*(u*cc-v*ss)/sqrtf(y);
+ }
+ if(hx<0) return -z;
+ else return z;
+ }
+ if(ix<0x39000000) { /* |x|<2**-13 */
+ if(huge+x>one) return (float)0.5*x;/* inexact if x!=0 necessary */
+ }
+ z = x*x;
+ r = z*(r00+z*(r01+z*(r02+z*r03)));
+ s = one+z*(s01+z*(s02+z*(s03+z*(s04+z*s05))));
+ r *= x;
+ return(x*(float)0.5+r/s);
+}
+
+static const float U0[5] = {
+ -1.9605709612e-01, /* 0xbe48c331 */
+ 5.0443872809e-02, /* 0x3d4e9e3c */
+ -1.9125689287e-03, /* 0xbafaaf2a */
+ 2.3525259166e-05, /* 0x37c5581c */
+ -9.1909917899e-08, /* 0xb3c56003 */
+};
+static const float V0[5] = {
+ 1.9916731864e-02, /* 0x3ca3286a */
+ 2.0255257550e-04, /* 0x3954644b */
+ 1.3560879779e-06, /* 0x35b602d4 */
+ 6.2274145840e-09, /* 0x31d5f8eb */
+ 1.6655924903e-11, /* 0x2d9281cf */
+};
+
+OLM_DLLEXPORT float
+__ieee754_y1f(float x)
+{
+ float z, s,c,ss,cc,u,v;
+ int32_t hx,ix;
+
+ GET_FLOAT_WORD(hx,x);
+ ix = 0x7fffffff&hx;
+ /* if Y1(NaN) is NaN, Y1(-inf) is NaN, Y1(inf) is 0 */
+ if(ix>=0x7f800000) return one/(x+x*x);
+ if(ix==0) return -one/zero;
+ if(hx<0) return zero/zero;
+ if(ix >= 0x40000000) { /* |x| >= 2.0 */
+ s = sinf(x);
+ c = cosf(x);
+ ss = -s-c;
+ cc = s-c;
+ if(ix<0x7f000000) { /* make sure x+x not overflow */
+ z = cosf(x+x);
+ if ((s*c)>zero) cc = z/ss;
+ else ss = z/cc;
+ }
+ /* y1(x) = sqrt(2/(pi*x))*(p1(x)*sin(x0)+q1(x)*cos(x0))
+ * where x0 = x-3pi/4
+ * Better formula:
+ * cos(x0) = cos(x)cos(3pi/4)+sin(x)sin(3pi/4)
+ * = 1/sqrt(2) * (sin(x) - cos(x))
+ * sin(x0) = sin(x)cos(3pi/4)-cos(x)sin(3pi/4)
+ * = -1/sqrt(2) * (cos(x) + sin(x))
+ * To avoid cancellation, use
+ * sin(x) +- cos(x) = -cos(2x)/(sin(x) -+ cos(x))
+ * to compute the worse one.
+ */
+ if(ix>0x58000000) z = (invsqrtpi*ss)/sqrtf(x); /* |x|>2**49 */
+ else {
+ u = ponef(x); v = qonef(x);
+ z = invsqrtpi*(u*ss+v*cc)/sqrtf(x);
+ }
+ return z;
+ }
+ if(ix<=0x33000000) { /* x < 2**-25 */
+ return(-tpi/x);
+ }
+ z = x*x;
+ u = U0[0]+z*(U0[1]+z*(U0[2]+z*(U0[3]+z*U0[4])));
+ v = one+z*(V0[0]+z*(V0[1]+z*(V0[2]+z*(V0[3]+z*V0[4]))));
+ return(x*(u/v) + tpi*(__ieee754_j1f(x)*__ieee754_logf(x)-one/x));
+}
+
+/* For x >= 8, the asymptotic expansions of pone is
+ * 1 + 15/128 s^2 - 4725/2^15 s^4 - ..., where s = 1/x.
+ * We approximate pone by
+ * pone(x) = 1 + (R/S)
+ * where R = pr0 + pr1*s^2 + pr2*s^4 + ... + pr5*s^10
+ * S = 1 + ps0*s^2 + ... + ps4*s^10
+ * and
+ * | pone(x)-1-R/S | <= 2 ** ( -60.06)
+ */
+
+static const float pr8[6] = { /* for x in [inf, 8]=1/[0,0.125] */
+ 0.0000000000e+00, /* 0x00000000 */
+ 1.1718750000e-01, /* 0x3df00000 */
+ 1.3239480972e+01, /* 0x4153d4ea */
+ 4.1205184937e+02, /* 0x43ce06a3 */
+ 3.8747453613e+03, /* 0x45722bed */
+ 7.9144794922e+03, /* 0x45f753d6 */
+};
+static const float ps8[5] = {
+ 1.1420736694e+02, /* 0x42e46a2c */
+ 3.6509309082e+03, /* 0x45642ee5 */
+ 3.6956207031e+04, /* 0x47105c35 */
+ 9.7602796875e+04, /* 0x47bea166 */
+ 3.0804271484e+04, /* 0x46f0a88b */
+};
+
+static const float pr5[6] = { /* for x in [8,4.5454]=1/[0.125,0.22001] */
+ 1.3199052094e-11, /* 0x2d68333f */
+ 1.1718749255e-01, /* 0x3defffff */
+ 6.8027510643e+00, /* 0x40d9b023 */
+ 1.0830818176e+02, /* 0x42d89dca */
+ 5.1763616943e+02, /* 0x440168b7 */
+ 5.2871520996e+02, /* 0x44042dc6 */
+};
+static const float ps5[5] = {
+ 5.9280597687e+01, /* 0x426d1f55 */
+ 9.9140142822e+02, /* 0x4477d9b1 */
+ 5.3532670898e+03, /* 0x45a74a23 */
+ 7.8446904297e+03, /* 0x45f52586 */
+ 1.5040468750e+03, /* 0x44bc0180 */
+};
+
+static const float pr3[6] = {
+ 3.0250391081e-09, /* 0x314fe10d */
+ 1.1718686670e-01, /* 0x3defffab */
+ 3.9329774380e+00, /* 0x407bb5e7 */
+ 3.5119403839e+01, /* 0x420c7a45 */
+ 9.1055007935e+01, /* 0x42b61c2a */
+ 4.8559066772e+01, /* 0x42423c7c */
+};
+static const float ps3[5] = {
+ 3.4791309357e+01, /* 0x420b2a4d */
+ 3.3676245117e+02, /* 0x43a86198 */
+ 1.0468714600e+03, /* 0x4482dbe3 */
+ 8.9081134033e+02, /* 0x445eb3ed */
+ 1.0378793335e+02, /* 0x42cf936c */
+};
+
+static const float pr2[6] = {/* for x in [2.8570,2]=1/[0.3499,0.5] */
+ 1.0771083225e-07, /* 0x33e74ea8 */
+ 1.1717621982e-01, /* 0x3deffa16 */
+ 2.3685150146e+00, /* 0x401795c0 */
+ 1.2242610931e+01, /* 0x4143e1bc */
+ 1.7693971634e+01, /* 0x418d8d41 */
+ 5.0735230446e+00, /* 0x40a25a4d */
+};
+static const float ps2[5] = {
+ 2.1436485291e+01, /* 0x41ab7dec */
+ 1.2529022980e+02, /* 0x42fa9499 */
+ 2.3227647400e+02, /* 0x436846c7 */
+ 1.1767937469e+02, /* 0x42eb5bd7 */
+ 8.3646392822e+00, /* 0x4105d590 */
+};
+
+ static float ponef(float x)
+{
+ const float *p,*q;
+ float z,r,s;
+ int32_t ix;
+ GET_FLOAT_WORD(ix,x);
+ ix &= 0x7fffffff;
+ if(ix>=0x41000000) {p = pr8; q= ps8;}
+ else if(ix>=0x409173eb){p = pr5; q= ps5;}
+ else if(ix>=0x4036d917){p = pr3; q= ps3;}
+ else {p = pr2; q= ps2;} /* ix>=0x40000000 */
+ z = one/(x*x);
+ r = p[0]+z*(p[1]+z*(p[2]+z*(p[3]+z*(p[4]+z*p[5]))));
+ s = one+z*(q[0]+z*(q[1]+z*(q[2]+z*(q[3]+z*q[4]))));
+ return one+ r/s;
+}
+
+
+/* For x >= 8, the asymptotic expansions of qone is
+ * 3/8 s - 105/1024 s^3 - ..., where s = 1/x.
+ * We approximate pone by
+ * qone(x) = s*(0.375 + (R/S))
+ * where R = qr1*s^2 + qr2*s^4 + ... + qr5*s^10
+ * S = 1 + qs1*s^2 + ... + qs6*s^12
+ * and
+ * | qone(x)/s -0.375-R/S | <= 2 ** ( -61.13)
+ */
+
+static const float qr8[6] = { /* for x in [inf, 8]=1/[0,0.125] */
+ 0.0000000000e+00, /* 0x00000000 */
+ -1.0253906250e-01, /* 0xbdd20000 */
+ -1.6271753311e+01, /* 0xc1822c8d */
+ -7.5960174561e+02, /* 0xc43de683 */
+ -1.1849806641e+04, /* 0xc639273a */
+ -4.8438511719e+04, /* 0xc73d3683 */
+};
+static const float qs8[6] = {
+ 1.6139537048e+02, /* 0x43216537 */
+ 7.8253862305e+03, /* 0x45f48b17 */
+ 1.3387534375e+05, /* 0x4802bcd6 */
+ 7.1965775000e+05, /* 0x492fb29c */
+ 6.6660125000e+05, /* 0x4922be94 */
+ -2.9449025000e+05, /* 0xc88fcb48 */
+};
+
+static const float qr5[6] = { /* for x in [8,4.5454]=1/[0.125,0.22001] */
+ -2.0897993405e-11, /* 0xadb7d219 */
+ -1.0253904760e-01, /* 0xbdd1fffe */
+ -8.0564479828e+00, /* 0xc100e736 */
+ -1.8366960144e+02, /* 0xc337ab6b */
+ -1.3731937256e+03, /* 0xc4aba633 */
+ -2.6124443359e+03, /* 0xc523471c */
+};
+static const float qs5[6] = {
+ 8.1276550293e+01, /* 0x42a28d98 */
+ 1.9917987061e+03, /* 0x44f8f98f */
+ 1.7468484375e+04, /* 0x468878f8 */
+ 4.9851425781e+04, /* 0x4742bb6d */
+ 2.7948074219e+04, /* 0x46da5826 */
+ -4.7191835938e+03, /* 0xc5937978 */
+};
+
+static const float qr3[6] = {
+ -5.0783124372e-09, /* 0xb1ae7d4f */
+ -1.0253783315e-01, /* 0xbdd1ff5b */
+ -4.6101160049e+00, /* 0xc0938612 */
+ -5.7847221375e+01, /* 0xc267638e */
+ -2.2824453735e+02, /* 0xc3643e9a */
+ -2.1921012878e+02, /* 0xc35b35cb */
+};
+static const float qs3[6] = {
+ 4.7665153503e+01, /* 0x423ea91e */
+ 6.7386511230e+02, /* 0x4428775e */
+ 3.3801528320e+03, /* 0x45534272 */
+ 5.5477290039e+03, /* 0x45ad5dd5 */
+ 1.9031191406e+03, /* 0x44ede3d0 */
+ -1.3520118713e+02, /* 0xc3073381 */
+};
+
+static const float qr2[6] = {/* for x in [2.8570,2]=1/[0.3499,0.5] */
+ -1.7838172539e-07, /* 0xb43f8932 */
+ -1.0251704603e-01, /* 0xbdd1f475 */
+ -2.7522056103e+00, /* 0xc0302423 */
+ -1.9663616180e+01, /* 0xc19d4f16 */
+ -4.2325313568e+01, /* 0xc2294d1f */
+ -2.1371921539e+01, /* 0xc1aaf9b2 */
+};
+static const float qs2[6] = {
+ 2.9533363342e+01, /* 0x41ec4454 */
+ 2.5298155212e+02, /* 0x437cfb47 */
+ 7.5750280762e+02, /* 0x443d602e */
+ 7.3939318848e+02, /* 0x4438d92a */
+ 1.5594900513e+02, /* 0x431bf2f2 */
+ -4.9594988823e+00, /* 0xc09eb437 */
+};
+
+ static float qonef(float x)
+{
+ const float *p,*q;
+ float s,r,z;
+ int32_t ix;
+ GET_FLOAT_WORD(ix,x);
+ ix &= 0x7fffffff;
+ if(ix>=0x41000000) {p = qr8; q= qs8;}
+ else if(ix>=0x409173eb){p = qr5; q= qs5;}
+ else if(ix>=0x4036d917){p = qr3; q= qs3;}
+ else {p = qr2; q= qs2;} /* ix>=0x40000000 */
+ z = one/(x*x);
+ r = p[0]+z*(p[1]+z*(p[2]+z*(p[3]+z*(p[4]+z*p[5]))));
+ s = one+z*(q[0]+z*(q[1]+z*(q[2]+z*(q[3]+z*(q[4]+z*q[5])))));
+ return ((float).375 + r/s)/x;
+}
--- /dev/null
+
+/* @(#)e_jn.c 1.4 95/01/18 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunSoft, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/src/e_jn.c,v 1.11 2010/11/13 10:54:10 uqs Exp $");
+
+/*
+ * __ieee754_jn(n, x), __ieee754_yn(n, x)
+ * floating point Bessel's function of the 1st and 2nd kind
+ * of order n
+ *
+ * Special cases:
+ * y0(0)=y1(0)=yn(n,0) = -inf with division by zero signal;
+ * y0(-ve)=y1(-ve)=yn(n,-ve) are NaN with invalid signal.
+ * Note 2. About jn(n,x), yn(n,x)
+ * For n=0, j0(x) is called,
+ * for n=1, j1(x) is called,
+ * for n<x, forward recursion us used starting
+ * from values of j0(x) and j1(x).
+ * for n>x, a continued fraction approximation to
+ * j(n,x)/j(n-1,x) is evaluated and then backward
+ * recursion is used starting from a supposed value
+ * for j(n,x). The resulting value of j(0,x) is
+ * compared with the actual value to correct the
+ * supposed value of j(n,x).
+ *
+ * yn(n,x) is similar in all respects, except
+ * that forward recursion is used for all
+ * values of n>1.
+ *
+ */
+
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+static const double
+invsqrtpi= 5.64189583547756279280e-01, /* 0x3FE20DD7, 0x50429B6D */
+two = 2.00000000000000000000e+00, /* 0x40000000, 0x00000000 */
+one = 1.00000000000000000000e+00; /* 0x3FF00000, 0x00000000 */
+
+static const double zero = 0.00000000000000000000e+00;
+
+OLM_DLLEXPORT double
+__ieee754_jn(int n, double x)
+{
+ int32_t i,hx,ix,lx, sgn;
+ double a, b, temp, di;
+ double z, w;
+
+ /* J(-n,x) = (-1)^n * J(n, x), J(n, -x) = (-1)^n * J(n, x)
+ * Thus, J(-n,x) = J(n,-x)
+ */
+ EXTRACT_WORDS(hx,lx,x);
+ ix = 0x7fffffff&hx;
+ /* if J(n,NaN) is NaN */
+ if((ix|((u_int32_t)(lx|-lx))>>31)>0x7ff00000) return x+x;
+ if(n<0){
+ n = -n;
+ x = -x;
+ hx ^= 0x80000000;
+ }
+ if(n==0) return(__ieee754_j0(x));
+ if(n==1) return(__ieee754_j1(x));
+ sgn = (n&1)&(hx>>31); /* even n -- 0, odd n -- sign(x) */
+ x = fabs(x);
+ if((ix|lx)==0||ix>=0x7ff00000) /* if x is 0 or inf */
+ b = zero;
+ else if((double)n<=x) {
+ /* Safe to use J(n+1,x)=2n/x *J(n,x)-J(n-1,x) */
+ if(ix>=0x52D00000) { /* x > 2**302 */
+ /* (x >> n**2)
+ * Jn(x) = cos(x-(2n+1)*pi/4)*sqrt(2/x*pi)
+ * Yn(x) = sin(x-(2n+1)*pi/4)*sqrt(2/x*pi)
+ * Let s=sin(x), c=cos(x),
+ * xn=x-(2n+1)*pi/4, sqt2 = sqrt(2),then
+ *
+ * n sin(xn)*sqt2 cos(xn)*sqt2
+ * ----------------------------------
+ * 0 s-c c+s
+ * 1 -s-c -c+s
+ * 2 -s+c -c-s
+ * 3 s+c c-s
+ */
+ switch(n&3) {
+ case 0: temp = cos(x)+sin(x); break;
+ case 1: temp = -cos(x)+sin(x); break;
+ case 2: temp = -cos(x)-sin(x); break;
+ case 3: temp = cos(x)-sin(x); break;
+ }
+ b = invsqrtpi*temp/sqrt(x);
+ } else {
+ a = __ieee754_j0(x);
+ b = __ieee754_j1(x);
+ for(i=1;i<n;i++){
+ temp = b;
+ b = b*((double)(i+i)/x) - a; /* avoid underflow */
+ a = temp;
+ }
+ }
+ } else {
+ if(ix<0x3e100000) { /* x < 2**-29 */
+ /* x is tiny, return the first Taylor expansion of J(n,x)
+ * J(n,x) = 1/n!*(x/2)^n - ...
+ */
+ if(n>33) /* underflow */
+ b = zero;
+ else {
+ temp = x*0.5; b = temp;
+ for (a=one,i=2;i<=n;i++) {
+ a *= (double)i; /* a = n! */
+ b *= temp; /* b = (x/2)^n */
+ }
+ b = b/a;
+ }
+ } else {
+ /* use backward recurrence */
+ /* x x^2 x^2
+ * J(n,x)/J(n-1,x) = ---- ------ ------ .....
+ * 2n - 2(n+1) - 2(n+2)
+ *
+ * 1 1 1
+ * (for large x) = ---- ------ ------ .....
+ * 2n 2(n+1) 2(n+2)
+ * -- - ------ - ------ -
+ * x x x
+ *
+ * Let w = 2n/x and h=2/x, then the above quotient
+ * is equal to the continued fraction:
+ * 1
+ * = -----------------------
+ * 1
+ * w - -----------------
+ * 1
+ * w+h - ---------
+ * w+2h - ...
+ *
+ * To determine how many terms needed, let
+ * Q(0) = w, Q(1) = w(w+h) - 1,
+ * Q(k) = (w+k*h)*Q(k-1) - Q(k-2),
+ * When Q(k) > 1e4 good for single
+ * When Q(k) > 1e9 good for double
+ * When Q(k) > 1e17 good for quadruple
+ */
+ /* determine k */
+ double t,v;
+ double q0,q1,h,tmp; int32_t k,m;
+ w = (n+n)/(double)x; h = 2.0/(double)x;
+ q0 = w; z = w+h; q1 = w*z - 1.0; k=1;
+ while(q1<1.0e9) {
+ k += 1; z += h;
+ tmp = z*q1 - q0;
+ q0 = q1;
+ q1 = tmp;
+ }
+ m = n+n;
+ for(t=zero, i = 2*(n+k); i>=m; i -= 2) t = one/(i/x-t);
+ a = t;
+ b = one;
+ /* estimate log((2/x)^n*n!) = n*log(2/x)+n*ln(n)
+ * Hence, if n*(log(2n/x)) > ...
+ * single 8.8722839355e+01
+ * double 7.09782712893383973096e+02
+ * long double 1.1356523406294143949491931077970765006170e+04
+ * then recurrent value may overflow and the result is
+ * likely underflow to zero
+ */
+ tmp = n;
+ v = two/x;
+ tmp = tmp*__ieee754_log(fabs(v*tmp));
+ if(tmp<7.09782712893383973096e+02) {
+ for(i=n-1,di=(double)(i+i);i>0;i--){
+ temp = b;
+ b *= di;
+ b = b/x - a;
+ a = temp;
+ di -= two;
+ }
+ } else {
+ for(i=n-1,di=(double)(i+i);i>0;i--){
+ temp = b;
+ b *= di;
+ b = b/x - a;
+ a = temp;
+ di -= two;
+ /* scale b to avoid spurious overflow */
+ if(b>1e100) {
+ a /= b;
+ t /= b;
+ b = one;
+ }
+ }
+ }
+ z = __ieee754_j0(x);
+ w = __ieee754_j1(x);
+ if (fabs(z) >= fabs(w))
+ b = (t*z/b);
+ else
+ b = (t*w/a);
+ }
+ }
+ if(sgn==1) return -b; else return b;
+}
+
+OLM_DLLEXPORT double
+__ieee754_yn(int n, double x)
+{
+ int32_t i,hx,ix,lx;
+ int32_t sign;
+ double a, b, temp;
+
+ EXTRACT_WORDS(hx,lx,x);
+ ix = 0x7fffffff&hx;
+ /* if Y(n,NaN) is NaN */
+ if((ix|((u_int32_t)(lx|-lx))>>31)>0x7ff00000) return x+x;
+ if((ix|lx)==0) return -one/zero;
+ if(hx<0) return zero/zero;
+ sign = 1;
+ if(n<0){
+ n = -n;
+ sign = 1 - ((n&1)<<1);
+ }
+ if(n==0) return(__ieee754_y0(x));
+ if(n==1) return(sign*__ieee754_y1(x));
+ if(ix==0x7ff00000) return zero;
+ if(ix>=0x52D00000) { /* x > 2**302 */
+ /* (x >> n**2)
+ * Jn(x) = cos(x-(2n+1)*pi/4)*sqrt(2/x*pi)
+ * Yn(x) = sin(x-(2n+1)*pi/4)*sqrt(2/x*pi)
+ * Let s=sin(x), c=cos(x),
+ * xn=x-(2n+1)*pi/4, sqt2 = sqrt(2),then
+ *
+ * n sin(xn)*sqt2 cos(xn)*sqt2
+ * ----------------------------------
+ * 0 s-c c+s
+ * 1 -s-c -c+s
+ * 2 -s+c -c-s
+ * 3 s+c c-s
+ */
+ switch(n&3) {
+ case 0: temp = sin(x)-cos(x); break;
+ case 1: temp = -sin(x)-cos(x); break;
+ case 2: temp = -sin(x)+cos(x); break;
+ case 3: temp = sin(x)+cos(x); break;
+ }
+ b = invsqrtpi*temp/sqrt(x);
+ } else {
+ u_int32_t high;
+ a = __ieee754_y0(x);
+ b = __ieee754_y1(x);
+ /* quit if b is -inf */
+ GET_HIGH_WORD(high,b);
+ for(i=1;i<n&&high!=0xfff00000;i++){
+ temp = b;
+ b = ((double)(i+i)/x)*b - a;
+ GET_HIGH_WORD(high,b);
+ a = temp;
+ }
+ }
+ if(sign>0) return b; else return -b;
+}
--- /dev/null
+/* e_jnf.c -- float version of e_jn.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/src/e_jnf.c,v 1.11 2010/11/13 10:54:10 uqs Exp $");
+
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+static const float
+two = 2.0000000000e+00, /* 0x40000000 */
+one = 1.0000000000e+00; /* 0x3F800000 */
+
+static const float zero = 0.0000000000e+00;
+
+OLM_DLLEXPORT float
+__ieee754_jnf(int n, float x)
+{
+ int32_t i,hx,ix, sgn;
+ float a, b, temp, di;
+ float z, w;
+
+ /* J(-n,x) = (-1)^n * J(n, x), J(n, -x) = (-1)^n * J(n, x)
+ * Thus, J(-n,x) = J(n,-x)
+ */
+ GET_FLOAT_WORD(hx,x);
+ ix = 0x7fffffff&hx;
+ /* if J(n,NaN) is NaN */
+ if(ix>0x7f800000) return x+x;
+ if(n<0){
+ n = -n;
+ x = -x;
+ hx ^= 0x80000000;
+ }
+ if(n==0) return(__ieee754_j0f(x));
+ if(n==1) return(__ieee754_j1f(x));
+ sgn = (n&1)&(hx>>31); /* even n -- 0, odd n -- sign(x) */
+ x = fabsf(x);
+ if(ix==0||ix>=0x7f800000) /* if x is 0 or inf */
+ b = zero;
+ else if((float)n<=x) {
+ /* Safe to use J(n+1,x)=2n/x *J(n,x)-J(n-1,x) */
+ a = __ieee754_j0f(x);
+ b = __ieee754_j1f(x);
+ for(i=1;i<n;i++){
+ temp = b;
+ b = b*((float)(i+i)/x) - a; /* avoid underflow */
+ a = temp;
+ }
+ } else {
+ if(ix<0x30800000) { /* x < 2**-29 */
+ /* x is tiny, return the first Taylor expansion of J(n,x)
+ * J(n,x) = 1/n!*(x/2)^n - ...
+ */
+ if(n>33) /* underflow */
+ b = zero;
+ else {
+ temp = x*(float)0.5; b = temp;
+ for (a=one,i=2;i<=n;i++) {
+ a *= (float)i; /* a = n! */
+ b *= temp; /* b = (x/2)^n */
+ }
+ b = b/a;
+ }
+ } else {
+ /* use backward recurrence */
+ /* x x^2 x^2
+ * J(n,x)/J(n-1,x) = ---- ------ ------ .....
+ * 2n - 2(n+1) - 2(n+2)
+ *
+ * 1 1 1
+ * (for large x) = ---- ------ ------ .....
+ * 2n 2(n+1) 2(n+2)
+ * -- - ------ - ------ -
+ * x x x
+ *
+ * Let w = 2n/x and h=2/x, then the above quotient
+ * is equal to the continued fraction:
+ * 1
+ * = -----------------------
+ * 1
+ * w - -----------------
+ * 1
+ * w+h - ---------
+ * w+2h - ...
+ *
+ * To determine how many terms needed, let
+ * Q(0) = w, Q(1) = w(w+h) - 1,
+ * Q(k) = (w+k*h)*Q(k-1) - Q(k-2),
+ * When Q(k) > 1e4 good for single
+ * When Q(k) > 1e9 good for double
+ * When Q(k) > 1e17 good for quadruple
+ */
+ /* determine k */
+ float t,v;
+ float q0,q1,h,tmp; int32_t k,m;
+ w = (n+n)/(float)x; h = (float)2.0/(float)x;
+ q0 = w; z = w+h; q1 = w*z - (float)1.0; k=1;
+ while(q1<(float)1.0e9) {
+ k += 1; z += h;
+ tmp = z*q1 - q0;
+ q0 = q1;
+ q1 = tmp;
+ }
+ m = n+n;
+ for(t=zero, i = 2*(n+k); i>=m; i -= 2) t = one/(i/x-t);
+ a = t;
+ b = one;
+ /* estimate log((2/x)^n*n!) = n*log(2/x)+n*ln(n)
+ * Hence, if n*(log(2n/x)) > ...
+ * single 8.8722839355e+01
+ * double 7.09782712893383973096e+02
+ * long double 1.1356523406294143949491931077970765006170e+04
+ * then recurrent value may overflow and the result is
+ * likely underflow to zero
+ */
+ tmp = n;
+ v = two/x;
+ tmp = tmp*__ieee754_logf(fabsf(v*tmp));
+ if(tmp<(float)8.8721679688e+01) {
+ for(i=n-1,di=(float)(i+i);i>0;i--){
+ temp = b;
+ b *= di;
+ b = b/x - a;
+ a = temp;
+ di -= two;
+ }
+ } else {
+ for(i=n-1,di=(float)(i+i);i>0;i--){
+ temp = b;
+ b *= di;
+ b = b/x - a;
+ a = temp;
+ di -= two;
+ /* scale b to avoid spurious overflow */
+ if(b>(float)1e10) {
+ a /= b;
+ t /= b;
+ b = one;
+ }
+ }
+ }
+ z = __ieee754_j0f(x);
+ w = __ieee754_j1f(x);
+ if (fabsf(z) >= fabsf(w))
+ b = (t*z/b);
+ else
+ b = (t*w/a);
+ }
+ }
+ if(sgn==1) return -b; else return b;
+}
+
+OLM_DLLEXPORT float
+__ieee754_ynf(int n, float x)
+{
+ int32_t i,hx,ix,ib;
+ int32_t sign;
+ float a, b, temp;
+
+ GET_FLOAT_WORD(hx,x);
+ ix = 0x7fffffff&hx;
+ /* if Y(n,NaN) is NaN */
+ if(ix>0x7f800000) return x+x;
+ if(ix==0) return -one/zero;
+ if(hx<0) return zero/zero;
+ sign = 1;
+ if(n<0){
+ n = -n;
+ sign = 1 - ((n&1)<<1);
+ }
+ if(n==0) return(__ieee754_y0f(x));
+ if(n==1) return(sign*__ieee754_y1f(x));
+ if(ix==0x7f800000) return zero;
+
+ a = __ieee754_y0f(x);
+ b = __ieee754_y1f(x);
+ /* quit if b is -inf */
+ GET_FLOAT_WORD(ib,b);
+ for(i=1;i<n&&ib!=0xff800000;i++){
+ temp = b;
+ b = ((float)(i+i)/x)*b - a;
+ GET_FLOAT_WORD(ib,b);
+ a = temp;
+ }
+ if(sign>0) return b; else return -b;
+}
--- /dev/null
+
+/* @(#)e_lgamma.c 1.3 95/01/18 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunSoft, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ *
+ */
+
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/src/e_lgamma.c,v 1.9 2008/02/22 02:30:35 das Exp $");
+
+/* __ieee754_lgamma(x)
+ * Return the logarithm of the Gamma function of x.
+ *
+ * Method: call __ieee754_lgamma_r
+ */
+
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+OLM_DLLEXPORT double
+__ieee754_lgamma(double x)
+{
+#ifdef OPENLIBM_ONLY_THREAD_SAFE
+ int signgam;
+#endif
+
+ return __ieee754_lgamma_r(x,&signgam);
+}
--- /dev/null
+
+/* @(#)e_lgamma_r.c 1.3 95/01/18 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunSoft, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ *
+ */
+
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/src/e_lgamma_r.c,v 1.11 2011/10/15 07:00:28 das Exp $");
+
+/* __ieee754_lgamma_r(x, signgamp)
+ * Reentrant version of the logarithm of the Gamma function
+ * with user provide pointer for the sign of Gamma(x).
+ *
+ * Method:
+ * 1. Argument Reduction for 0 < x <= 8
+ * Since gamma(1+s)=s*gamma(s), for x in [0,8], we may
+ * reduce x to a number in [1.5,2.5] by
+ * lgamma(1+s) = log(s) + lgamma(s)
+ * for example,
+ * lgamma(7.3) = log(6.3) + lgamma(6.3)
+ * = log(6.3*5.3) + lgamma(5.3)
+ * = log(6.3*5.3*4.3*3.3*2.3) + lgamma(2.3)
+ * 2. Polynomial approximation of lgamma around its
+ * minimun ymin=1.461632144968362245 to maintain monotonicity.
+ * On [ymin-0.23, ymin+0.27] (i.e., [1.23164,1.73163]), use
+ * Let z = x-ymin;
+ * lgamma(x) = -1.214862905358496078218 + z^2*poly(z)
+ * where
+ * poly(z) is a 14 degree polynomial.
+ * 2. Rational approximation in the primary interval [2,3]
+ * We use the following approximation:
+ * s = x-2.0;
+ * lgamma(x) = 0.5*s + s*P(s)/Q(s)
+ * with accuracy
+ * |P/Q - (lgamma(x)-0.5s)| < 2**-61.71
+ * Our algorithms are based on the following observation
+ *
+ * zeta(2)-1 2 zeta(3)-1 3
+ * lgamma(2+s) = s*(1-Euler) + --------- * s - --------- * s + ...
+ * 2 3
+ *
+ * where Euler = 0.5771... is the Euler constant, which is very
+ * close to 0.5.
+ *
+ * 3. For x>=8, we have
+ * lgamma(x)~(x-0.5)log(x)-x+0.5*log(2pi)+1/(12x)-1/(360x**3)+....
+ * (better formula:
+ * lgamma(x)~(x-0.5)*(log(x)-1)-.5*(log(2pi)-1) + ...)
+ * Let z = 1/x, then we approximation
+ * f(z) = lgamma(x) - (x-0.5)(log(x)-1)
+ * by
+ * 3 5 11
+ * w = w0 + w1*z + w2*z + w3*z + ... + w6*z
+ * where
+ * |w - f(z)| < 2**-58.74
+ *
+ * 4. For negative x, since (G is gamma function)
+ * -x*G(-x)*G(x) = pi/sin(pi*x),
+ * we have
+ * G(x) = pi/(sin(pi*x)*(-x)*G(-x))
+ * since G(-x) is positive, sign(G(x)) = sign(sin(pi*x)) for x<0
+ * Hence, for x<0, signgam = sign(sin(pi*x)) and
+ * lgamma(x) = log(|Gamma(x)|)
+ * = log(pi/(|x*sin(pi*x)|)) - lgamma(-x);
+ * Note: one should avoid compute pi*(-x) directly in the
+ * computation of sin(pi*(-x)).
+ *
+ * 5. Special Cases
+ * lgamma(2+s) ~ s*(1-Euler) for tiny s
+ * lgamma(1) = lgamma(2) = 0
+ * lgamma(x) ~ -log(|x|) for tiny x
+ * lgamma(0) = lgamma(neg.integer) = inf and raise divide-by-zero
+ * lgamma(inf) = inf
+ * lgamma(-inf) = inf (bug for bug compatible with C99!?)
+ *
+ */
+
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+static const double
+two52= 4.50359962737049600000e+15, /* 0x43300000, 0x00000000 */
+half= 5.00000000000000000000e-01, /* 0x3FE00000, 0x00000000 */
+one = 1.00000000000000000000e+00, /* 0x3FF00000, 0x00000000 */
+pi = 3.14159265358979311600e+00, /* 0x400921FB, 0x54442D18 */
+a0 = 7.72156649015328655494e-02, /* 0x3FB3C467, 0xE37DB0C8 */
+a1 = 3.22467033424113591611e-01, /* 0x3FD4A34C, 0xC4A60FAD */
+a2 = 6.73523010531292681824e-02, /* 0x3FB13E00, 0x1A5562A7 */
+a3 = 2.05808084325167332806e-02, /* 0x3F951322, 0xAC92547B */
+a4 = 7.38555086081402883957e-03, /* 0x3F7E404F, 0xB68FEFE8 */
+a5 = 2.89051383673415629091e-03, /* 0x3F67ADD8, 0xCCB7926B */
+a6 = 1.19270763183362067845e-03, /* 0x3F538A94, 0x116F3F5D */
+a7 = 5.10069792153511336608e-04, /* 0x3F40B6C6, 0x89B99C00 */
+a8 = 2.20862790713908385557e-04, /* 0x3F2CF2EC, 0xED10E54D */
+a9 = 1.08011567247583939954e-04, /* 0x3F1C5088, 0x987DFB07 */
+a10 = 2.52144565451257326939e-05, /* 0x3EFA7074, 0x428CFA52 */
+a11 = 4.48640949618915160150e-05, /* 0x3F07858E, 0x90A45837 */
+tc = 1.46163214496836224576e+00, /* 0x3FF762D8, 0x6356BE3F */
+tf = -1.21486290535849611461e-01, /* 0xBFBF19B9, 0xBCC38A42 */
+/* tt = -(tail of tf) */
+tt = -3.63867699703950536541e-18, /* 0xBC50C7CA, 0xA48A971F */
+t0 = 4.83836122723810047042e-01, /* 0x3FDEF72B, 0xC8EE38A2 */
+t1 = -1.47587722994593911752e-01, /* 0xBFC2E427, 0x8DC6C509 */
+t2 = 6.46249402391333854778e-02, /* 0x3FB08B42, 0x94D5419B */
+t3 = -3.27885410759859649565e-02, /* 0xBFA0C9A8, 0xDF35B713 */
+t4 = 1.79706750811820387126e-02, /* 0x3F9266E7, 0x970AF9EC */
+t5 = -1.03142241298341437450e-02, /* 0xBF851F9F, 0xBA91EC6A */
+t6 = 6.10053870246291332635e-03, /* 0x3F78FCE0, 0xE370E344 */
+t7 = -3.68452016781138256760e-03, /* 0xBF6E2EFF, 0xB3E914D7 */
+t8 = 2.25964780900612472250e-03, /* 0x3F6282D3, 0x2E15C915 */
+t9 = -1.40346469989232843813e-03, /* 0xBF56FE8E, 0xBF2D1AF1 */
+t10 = 8.81081882437654011382e-04, /* 0x3F4CDF0C, 0xEF61A8E9 */
+t11 = -5.38595305356740546715e-04, /* 0xBF41A610, 0x9C73E0EC */
+t12 = 3.15632070903625950361e-04, /* 0x3F34AF6D, 0x6C0EBBF7 */
+t13 = -3.12754168375120860518e-04, /* 0xBF347F24, 0xECC38C38 */
+t14 = 3.35529192635519073543e-04, /* 0x3F35FD3E, 0xE8C2D3F4 */
+u0 = -7.72156649015328655494e-02, /* 0xBFB3C467, 0xE37DB0C8 */
+u1 = 6.32827064025093366517e-01, /* 0x3FE4401E, 0x8B005DFF */
+u2 = 1.45492250137234768737e+00, /* 0x3FF7475C, 0xD119BD6F */
+u3 = 9.77717527963372745603e-01, /* 0x3FEF4976, 0x44EA8450 */
+u4 = 2.28963728064692451092e-01, /* 0x3FCD4EAE, 0xF6010924 */
+u5 = 1.33810918536787660377e-02, /* 0x3F8B678B, 0xBF2BAB09 */
+v1 = 2.45597793713041134822e+00, /* 0x4003A5D7, 0xC2BD619C */
+v2 = 2.12848976379893395361e+00, /* 0x40010725, 0xA42B18F5 */
+v3 = 7.69285150456672783825e-01, /* 0x3FE89DFB, 0xE45050AF */
+v4 = 1.04222645593369134254e-01, /* 0x3FBAAE55, 0xD6537C88 */
+v5 = 3.21709242282423911810e-03, /* 0x3F6A5ABB, 0x57D0CF61 */
+s0 = -7.72156649015328655494e-02, /* 0xBFB3C467, 0xE37DB0C8 */
+s1 = 2.14982415960608852501e-01, /* 0x3FCB848B, 0x36E20878 */
+s2 = 3.25778796408930981787e-01, /* 0x3FD4D98F, 0x4F139F59 */
+s3 = 1.46350472652464452805e-01, /* 0x3FC2BB9C, 0xBEE5F2F7 */
+s4 = 2.66422703033638609560e-02, /* 0x3F9B481C, 0x7E939961 */
+s5 = 1.84028451407337715652e-03, /* 0x3F5E26B6, 0x7368F239 */
+s6 = 3.19475326584100867617e-05, /* 0x3F00BFEC, 0xDD17E945 */
+r1 = 1.39200533467621045958e+00, /* 0x3FF645A7, 0x62C4AB74 */
+r2 = 7.21935547567138069525e-01, /* 0x3FE71A18, 0x93D3DCDC */
+r3 = 1.71933865632803078993e-01, /* 0x3FC601ED, 0xCCFBDF27 */
+r4 = 1.86459191715652901344e-02, /* 0x3F9317EA, 0x742ED475 */
+r5 = 7.77942496381893596434e-04, /* 0x3F497DDA, 0xCA41A95B */
+r6 = 7.32668430744625636189e-06, /* 0x3EDEBAF7, 0xA5B38140 */
+w0 = 4.18938533204672725052e-01, /* 0x3FDACFE3, 0x90C97D69 */
+w1 = 8.33333333333329678849e-02, /* 0x3FB55555, 0x5555553B */
+w2 = -2.77777777728775536470e-03, /* 0xBF66C16C, 0x16B02E5C */
+w3 = 7.93650558643019558500e-04, /* 0x3F4A019F, 0x98CF38B6 */
+w4 = -5.95187557450339963135e-04, /* 0xBF4380CB, 0x8C0FE741 */
+w5 = 8.36339918996282139126e-04, /* 0x3F4B67BA, 0x4CDAD5D1 */
+w6 = -1.63092934096575273989e-03; /* 0xBF5AB89D, 0x0B9E43E4 */
+
+static const double zero= 0.00000000000000000000e+00;
+
+ static double sin_pi(double x)
+{
+ double y,z;
+ int n,ix;
+
+ GET_HIGH_WORD(ix,x);
+ ix &= 0x7fffffff;
+
+ if(ix<0x3fd00000) return __kernel_sin(pi*x,zero,0);
+ y = -x; /* x is assume negative */
+
+ /*
+ * argument reduction, make sure inexact flag not raised if input
+ * is an integer
+ */
+ z = floor(y);
+ if(z!=y) { /* inexact anyway */
+ y *= 0.5;
+ y = 2.0*(y - floor(y)); /* y = |x| mod 2.0 */
+ n = (int) (y*4.0);
+ } else {
+ if(ix>=0x43400000) {
+ y = zero; n = 0; /* y must be even */
+ } else {
+ if(ix<0x43300000) z = y+two52; /* exact */
+ GET_LOW_WORD(n,z);
+ n &= 1;
+ y = n;
+ n<<= 2;
+ }
+ }
+ switch (n) {
+ case 0: y = __kernel_sin(pi*y,zero,0); break;
+ case 1:
+ case 2: y = __kernel_cos(pi*(0.5-y),zero); break;
+ case 3:
+ case 4: y = __kernel_sin(pi*(one-y),zero,0); break;
+ case 5:
+ case 6: y = -__kernel_cos(pi*(y-1.5),zero); break;
+ default: y = __kernel_sin(pi*(y-2.0),zero,0); break;
+ }
+ return -y;
+}
+
+
+OLM_DLLEXPORT double
+__ieee754_lgamma_r(double x, int *signgamp)
+{
+ double t,y,z,nadj,p,p1,p2,p3,q,r,w;
+ int32_t hx;
+ int i,lx,ix;
+
+ EXTRACT_WORDS(hx,lx,x);
+
+ /* purge off +-inf, NaN, +-0, tiny and negative arguments */
+ *signgamp = 1;
+ ix = hx&0x7fffffff;
+ if(ix>=0x7ff00000) return x*x;
+ if((ix|lx)==0) return one/zero;
+ if(ix<0x3b900000) { /* |x|<2**-70, return -log(|x|) */
+ if(hx<0) {
+ *signgamp = -1;
+ return -__ieee754_log(-x);
+ } else return -__ieee754_log(x);
+ }
+ if(hx<0) {
+ if(ix>=0x43300000) /* |x|>=2**52, must be -integer */
+ return one/zero;
+ t = sin_pi(x);
+ if(t==zero) return one/zero; /* -integer */
+ nadj = __ieee754_log(pi/fabs(t*x));
+ if(t<zero) *signgamp = -1;
+ x = -x;
+ }
+
+ /* purge off 1 and 2 */
+ if((((ix-0x3ff00000)|lx)==0)||(((ix-0x40000000)|lx)==0)) r = 0;
+ /* for x < 2.0 */
+ else if(ix<0x40000000) {
+ if(ix<=0x3feccccc) { /* lgamma(x) = lgamma(x+1)-log(x) */
+ r = -__ieee754_log(x);
+ if(ix>=0x3FE76944) {y = one-x; i= 0;}
+ else if(ix>=0x3FCDA661) {y= x-(tc-one); i=1;}
+ else {y = x; i=2;}
+ } else {
+ r = zero;
+ if(ix>=0x3FFBB4C3) {y=2.0-x;i=0;} /* [1.7316,2] */
+ else if(ix>=0x3FF3B4C4) {y=x-tc;i=1;} /* [1.23,1.73] */
+ else {y=x-one;i=2;}
+ }
+ switch(i) {
+ case 0:
+ z = y*y;
+ p1 = a0+z*(a2+z*(a4+z*(a6+z*(a8+z*a10))));
+ p2 = z*(a1+z*(a3+z*(a5+z*(a7+z*(a9+z*a11)))));
+ p = y*p1+p2;
+ r += (p-0.5*y); break;
+ case 1:
+ z = y*y;
+ w = z*y;
+ p1 = t0+w*(t3+w*(t6+w*(t9 +w*t12))); /* parallel comp */
+ p2 = t1+w*(t4+w*(t7+w*(t10+w*t13)));
+ p3 = t2+w*(t5+w*(t8+w*(t11+w*t14)));
+ p = z*p1-(tt-w*(p2+y*p3));
+ r += (tf + p); break;
+ case 2:
+ p1 = y*(u0+y*(u1+y*(u2+y*(u3+y*(u4+y*u5)))));
+ p2 = one+y*(v1+y*(v2+y*(v3+y*(v4+y*v5))));
+ r += (-0.5*y + p1/p2);
+ }
+ }
+ else if(ix<0x40200000) { /* x < 8.0 */
+ i = (int)x;
+ y = x-(double)i;
+ p = y*(s0+y*(s1+y*(s2+y*(s3+y*(s4+y*(s5+y*s6))))));
+ q = one+y*(r1+y*(r2+y*(r3+y*(r4+y*(r5+y*r6)))));
+ r = half*y+p/q;
+ z = one; /* lgamma(1+s) = log(s) + lgamma(s) */
+ switch(i) {
+ case 7: z *= (y+6.0); /* FALLTHRU */
+ case 6: z *= (y+5.0); /* FALLTHRU */
+ case 5: z *= (y+4.0); /* FALLTHRU */
+ case 4: z *= (y+3.0); /* FALLTHRU */
+ case 3: z *= (y+2.0); /* FALLTHRU */
+ r += __ieee754_log(z); break;
+ }
+ /* 8.0 <= x < 2**58 */
+ } else if (ix < 0x43900000) {
+ t = __ieee754_log(x);
+ z = one/x;
+ y = z*z;
+ w = w0+z*(w1+y*(w2+y*(w3+y*(w4+y*(w5+y*w6)))));
+ r = (x-half)*(t-one)+w;
+ } else
+ /* 2**58 <= x <= inf */
+ r = x*(__ieee754_log(x)-one);
+ if(hx<0) r = nadj - r;
+ return r;
+}
--- /dev/null
+/* e_lgammaf.c -- float version of e_lgamma.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/src/e_lgammaf.c,v 1.8 2008/02/22 02:30:35 das Exp $");
+
+/* __ieee754_lgammaf(x)
+ * Return the logarithm of the Gamma function of x.
+ *
+ * Method: call __ieee754_lgammaf_r
+ */
+
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+OLM_DLLEXPORT float
+__ieee754_lgammaf(float x)
+{
+#ifdef OPENLIBM_ONLY_THREAD_SAFE
+ int signgam;
+#endif
+
+ return __ieee754_lgammaf_r(x,&signgam);
+}
--- /dev/null
+/* e_lgammaf_r.c -- float version of e_lgamma_r.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/src/e_lgammaf_r.c,v 1.12 2011/10/15 07:00:28 das Exp $");
+
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+static const float
+two23= 8.3886080000e+06, /* 0x4b000000 */
+half= 5.0000000000e-01, /* 0x3f000000 */
+one = 1.0000000000e+00, /* 0x3f800000 */
+pi = 3.1415927410e+00, /* 0x40490fdb */
+a0 = 7.7215664089e-02, /* 0x3d9e233f */
+a1 = 3.2246702909e-01, /* 0x3ea51a66 */
+a2 = 6.7352302372e-02, /* 0x3d89f001 */
+a3 = 2.0580807701e-02, /* 0x3ca89915 */
+a4 = 7.3855509982e-03, /* 0x3bf2027e */
+a5 = 2.8905137442e-03, /* 0x3b3d6ec6 */
+a6 = 1.1927076848e-03, /* 0x3a9c54a1 */
+a7 = 5.1006977446e-04, /* 0x3a05b634 */
+a8 = 2.2086278477e-04, /* 0x39679767 */
+a9 = 1.0801156895e-04, /* 0x38e28445 */
+a10 = 2.5214456400e-05, /* 0x37d383a2 */
+a11 = 4.4864096708e-05, /* 0x383c2c75 */
+tc = 1.4616321325e+00, /* 0x3fbb16c3 */
+tf = -1.2148628384e-01, /* 0xbdf8cdcd */
+/* tt = -(tail of tf) */
+tt = 6.6971006518e-09, /* 0x31e61c52 */
+t0 = 4.8383611441e-01, /* 0x3ef7b95e */
+t1 = -1.4758771658e-01, /* 0xbe17213c */
+t2 = 6.4624942839e-02, /* 0x3d845a15 */
+t3 = -3.2788541168e-02, /* 0xbd064d47 */
+t4 = 1.7970675603e-02, /* 0x3c93373d */
+t5 = -1.0314224288e-02, /* 0xbc28fcfe */
+t6 = 6.1005386524e-03, /* 0x3bc7e707 */
+t7 = -3.6845202558e-03, /* 0xbb7177fe */
+t8 = 2.2596477065e-03, /* 0x3b141699 */
+t9 = -1.4034647029e-03, /* 0xbab7f476 */
+t10 = 8.8108185446e-04, /* 0x3a66f867 */
+t11 = -5.3859531181e-04, /* 0xba0d3085 */
+t12 = 3.1563205994e-04, /* 0x39a57b6b */
+t13 = -3.1275415677e-04, /* 0xb9a3f927 */
+t14 = 3.3552918467e-04, /* 0x39afe9f7 */
+u0 = -7.7215664089e-02, /* 0xbd9e233f */
+u1 = 6.3282704353e-01, /* 0x3f2200f4 */
+u2 = 1.4549225569e+00, /* 0x3fba3ae7 */
+u3 = 9.7771751881e-01, /* 0x3f7a4bb2 */
+u4 = 2.2896373272e-01, /* 0x3e6a7578 */
+u5 = 1.3381091878e-02, /* 0x3c5b3c5e */
+v1 = 2.4559779167e+00, /* 0x401d2ebe */
+v2 = 2.1284897327e+00, /* 0x4008392d */
+v3 = 7.6928514242e-01, /* 0x3f44efdf */
+v4 = 1.0422264785e-01, /* 0x3dd572af */
+v5 = 3.2170924824e-03, /* 0x3b52d5db */
+s0 = -7.7215664089e-02, /* 0xbd9e233f */
+s1 = 2.1498242021e-01, /* 0x3e5c245a */
+s2 = 3.2577878237e-01, /* 0x3ea6cc7a */
+s3 = 1.4635047317e-01, /* 0x3e15dce6 */
+s4 = 2.6642270386e-02, /* 0x3cda40e4 */
+s5 = 1.8402845599e-03, /* 0x3af135b4 */
+s6 = 3.1947532989e-05, /* 0x3805ff67 */
+r1 = 1.3920053244e+00, /* 0x3fb22d3b */
+r2 = 7.2193557024e-01, /* 0x3f38d0c5 */
+r3 = 1.7193385959e-01, /* 0x3e300f6e */
+r4 = 1.8645919859e-02, /* 0x3c98bf54 */
+r5 = 7.7794247773e-04, /* 0x3a4beed6 */
+r6 = 7.3266842264e-06, /* 0x36f5d7bd */
+w0 = 4.1893854737e-01, /* 0x3ed67f1d */
+w1 = 8.3333335817e-02, /* 0x3daaaaab */
+w2 = -2.7777778450e-03, /* 0xbb360b61 */
+w3 = 7.9365057172e-04, /* 0x3a500cfd */
+w4 = -5.9518753551e-04, /* 0xba1c065c */
+w5 = 8.3633989561e-04, /* 0x3a5b3dd2 */
+w6 = -1.6309292987e-03; /* 0xbad5c4e8 */
+
+static const float zero= 0.0000000000e+00;
+
+ static float sin_pif(float x)
+{
+ float y,z;
+ int n,ix;
+
+ GET_FLOAT_WORD(ix,x);
+ ix &= 0x7fffffff;
+
+ if(ix<0x3e800000) return __kernel_sindf(pi*x);
+ y = -x; /* x is assume negative */
+
+ /*
+ * argument reduction, make sure inexact flag not raised if input
+ * is an integer
+ */
+ z = floorf(y);
+ if(z!=y) { /* inexact anyway */
+ y *= (float)0.5;
+ y = (float)2.0*(y - floorf(y)); /* y = |x| mod 2.0 */
+ n = (int) (y*(float)4.0);
+ } else {
+ if(ix>=0x4b800000) {
+ y = zero; n = 0; /* y must be even */
+ } else {
+ if(ix<0x4b000000) z = y+two23; /* exact */
+ GET_FLOAT_WORD(n,z);
+ n &= 1;
+ y = n;
+ n<<= 2;
+ }
+ }
+ switch (n) {
+ case 0: y = __kernel_sindf(pi*y); break;
+ case 1:
+ case 2: y = __kernel_cosdf(pi*((float)0.5-y)); break;
+ case 3:
+ case 4: y = __kernel_sindf(pi*(one-y)); break;
+ case 5:
+ case 6: y = -__kernel_cosdf(pi*(y-(float)1.5)); break;
+ default: y = __kernel_sindf(pi*(y-(float)2.0)); break;
+ }
+ return -y;
+}
+
+
+OLM_DLLEXPORT float
+__ieee754_lgammaf_r(float x, int *signgamp)
+{
+ float t,y,z,nadj,p,p1,p2,p3,q,r,w;
+ int32_t hx;
+ int i,ix;
+
+ GET_FLOAT_WORD(hx,x);
+
+ /* purge off +-inf, NaN, +-0, tiny and negative arguments */
+ *signgamp = 1;
+ ix = hx&0x7fffffff;
+ if(ix>=0x7f800000) return x*x;
+ if(ix==0) return one/zero;
+ if(ix<0x35000000) { /* |x|<2**-21, return -log(|x|) */
+ if(hx<0) {
+ *signgamp = -1;
+ return -__ieee754_logf(-x);
+ } else return -__ieee754_logf(x);
+ }
+ if(hx<0) {
+ if(ix>=0x4b000000) /* |x|>=2**23, must be -integer */
+ return one/zero;
+ t = sin_pif(x);
+ if(t==zero) return one/zero; /* -integer */
+ nadj = __ieee754_logf(pi/fabsf(t*x));
+ if(t<zero) *signgamp = -1;
+ x = -x;
+ }
+
+ /* purge off 1 and 2 */
+ if (ix==0x3f800000||ix==0x40000000) r = 0;
+ /* for x < 2.0 */
+ else if(ix<0x40000000) {
+ if(ix<=0x3f666666) { /* lgamma(x) = lgamma(x+1)-log(x) */
+ r = -__ieee754_logf(x);
+ if(ix>=0x3f3b4a20) {y = one-x; i= 0;}
+ else if(ix>=0x3e6d3308) {y= x-(tc-one); i=1;}
+ else {y = x; i=2;}
+ } else {
+ r = zero;
+ if(ix>=0x3fdda618) {y=(float)2.0-x;i=0;} /* [1.7316,2] */
+ else if(ix>=0x3F9da620) {y=x-tc;i=1;} /* [1.23,1.73] */
+ else {y=x-one;i=2;}
+ }
+ switch(i) {
+ case 0:
+ z = y*y;
+ p1 = a0+z*(a2+z*(a4+z*(a6+z*(a8+z*a10))));
+ p2 = z*(a1+z*(a3+z*(a5+z*(a7+z*(a9+z*a11)))));
+ p = y*p1+p2;
+ r += (p-(float)0.5*y); break;
+ case 1:
+ z = y*y;
+ w = z*y;
+ p1 = t0+w*(t3+w*(t6+w*(t9 +w*t12))); /* parallel comp */
+ p2 = t1+w*(t4+w*(t7+w*(t10+w*t13)));
+ p3 = t2+w*(t5+w*(t8+w*(t11+w*t14)));
+ p = z*p1-(tt-w*(p2+y*p3));
+ r += (tf + p); break;
+ case 2:
+ p1 = y*(u0+y*(u1+y*(u2+y*(u3+y*(u4+y*u5)))));
+ p2 = one+y*(v1+y*(v2+y*(v3+y*(v4+y*v5))));
+ r += (-(float)0.5*y + p1/p2);
+ }
+ }
+ else if(ix<0x41000000) { /* x < 8.0 */
+ i = (int)x;
+ y = x-(float)i;
+ p = y*(s0+y*(s1+y*(s2+y*(s3+y*(s4+y*(s5+y*s6))))));
+ q = one+y*(r1+y*(r2+y*(r3+y*(r4+y*(r5+y*r6)))));
+ r = half*y+p/q;
+ z = one; /* lgamma(1+s) = log(s) + lgamma(s) */
+ switch(i) {
+ case 7: z *= (y+(float)6.0); /* FALLTHRU */
+ case 6: z *= (y+(float)5.0); /* FALLTHRU */
+ case 5: z *= (y+(float)4.0); /* FALLTHRU */
+ case 4: z *= (y+(float)3.0); /* FALLTHRU */
+ case 3: z *= (y+(float)2.0); /* FALLTHRU */
+ r += __ieee754_logf(z); break;
+ }
+ /* 8.0 <= x < 2**58 */
+ } else if (ix < 0x5c800000) {
+ t = __ieee754_logf(x);
+ z = one/x;
+ y = z*z;
+ w = w0+z*(w1+y*(w2+y*(w3+y*(w4+y*(w5+y*w6)))));
+ r = (x-half)*(t-one)+w;
+ } else
+ /* 2**58 <= x <= inf */
+ r = x*(__ieee754_logf(x)-one);
+ if(hx<0) r = nadj - r;
+ return r;
+}
--- /dev/null
+#include "cdefs-compat.h"
+
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+OLM_DLLEXPORT long double
+lgammal(long double x)
+{
+#ifdef OPENLIBM_ONLY_THREAD_SAFE
+ int signgam;
+#endif
+
+ return (lgammal_r(x, &signgam));
+}
--- /dev/null
+
+/* @(#)e_log.c 1.3 95/01/18 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunSoft, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/src/e_log.c,v 1.15 2008/03/29 16:37:59 das Exp $");
+
+/* __ieee754_log(x)
+ * Return the logrithm of x
+ *
+ * Method :
+ * 1. Argument Reduction: find k and f such that
+ * x = 2^k * (1+f),
+ * where sqrt(2)/2 < 1+f < sqrt(2) .
+ *
+ * 2. Approximation of log(1+f).
+ * Let s = f/(2+f) ; based on log(1+f) = log(1+s) - log(1-s)
+ * = 2s + 2/3 s**3 + 2/5 s**5 + .....,
+ * = 2s + s*R
+ * We use a special Reme algorithm on [0,0.1716] to generate
+ * a polynomial of degree 14 to approximate R The maximum error
+ * of this polynomial approximation is bounded by 2**-58.45. In
+ * other words,
+ * 2 4 6 8 10 12 14
+ * R(z) ~ Lg1*s +Lg2*s +Lg3*s +Lg4*s +Lg5*s +Lg6*s +Lg7*s
+ * (the values of Lg1 to Lg7 are listed in the program)
+ * and
+ * | 2 14 | -58.45
+ * | Lg1*s +...+Lg7*s - R(z) | <= 2
+ * | |
+ * Note that 2s = f - s*f = f - hfsq + s*hfsq, where hfsq = f*f/2.
+ * In order to guarantee error in log below 1ulp, we compute log
+ * by
+ * log(1+f) = f - s*(f - R) (if f is not too large)
+ * log(1+f) = f - (hfsq - s*(hfsq+R)). (better accuracy)
+ *
+ * 3. Finally, log(x) = k*ln2 + log(1+f).
+ * = k*ln2_hi+(f-(hfsq-(s*(hfsq+R)+k*ln2_lo)))
+ * Here ln2 is split into two floating point number:
+ * ln2_hi + ln2_lo,
+ * where n*ln2_hi is always exact for |n| < 2000.
+ *
+ * Special cases:
+ * log(x) is NaN with signal if x < 0 (including -INF) ;
+ * log(+INF) is +INF; log(0) is -INF with signal;
+ * log(NaN) is that NaN with no signal.
+ *
+ * Accuracy:
+ * according to an error analysis, the error is always less than
+ * 1 ulp (unit in the last place).
+ *
+ * Constants:
+ * The hexadecimal values are the intended ones for the following
+ * constants. The decimal values may be used, provided that the
+ * compiler will convert from decimal to binary accurately enough
+ * to produce the hexadecimal values shown.
+ */
+
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+static const double
+ln2_hi = 6.93147180369123816490e-01, /* 3fe62e42 fee00000 */
+ln2_lo = 1.90821492927058770002e-10, /* 3dea39ef 35793c76 */
+two54 = 1.80143985094819840000e+16, /* 43500000 00000000 */
+Lg1 = 6.666666666666735130e-01, /* 3FE55555 55555593 */
+Lg2 = 3.999999999940941908e-01, /* 3FD99999 9997FA04 */
+Lg3 = 2.857142874366239149e-01, /* 3FD24924 94229359 */
+Lg4 = 2.222219843214978396e-01, /* 3FCC71C5 1D8E78AF */
+Lg5 = 1.818357216161805012e-01, /* 3FC74664 96CB03DE */
+Lg6 = 1.531383769920937332e-01, /* 3FC39A09 D078C69F */
+Lg7 = 1.479819860511658591e-01; /* 3FC2F112 DF3E5244 */
+
+static const double zero = 0.0;
+
+OLM_DLLEXPORT double
+__ieee754_log(double x)
+{
+ double hfsq,f,s,z,R,w,t1,t2,dk;
+ int32_t k,hx,i,j;
+ u_int32_t lx;
+
+ EXTRACT_WORDS(hx,lx,x);
+
+ k=0;
+ if (hx < 0x00100000) { /* x < 2**-1022 */
+ if (((hx&0x7fffffff)|lx)==0)
+ return -two54/zero; /* log(+-0)=-inf */
+ if (hx<0) return (x-x)/zero; /* log(-#) = NaN */
+ k -= 54; x *= two54; /* subnormal number, scale up x */
+ GET_HIGH_WORD(hx,x);
+ }
+ if (hx >= 0x7ff00000) return x+x;
+ k += (hx>>20)-1023;
+ hx &= 0x000fffff;
+ i = (hx+0x95f64)&0x100000;
+ SET_HIGH_WORD(x,hx|(i^0x3ff00000)); /* normalize x or x/2 */
+ k += (i>>20);
+ f = x-1.0;
+ if((0x000fffff&(2+hx))<3) { /* -2**-20 <= f < 2**-20 */
+ if(f==zero) {
+ if(k==0) {
+ return zero;
+ } else {
+ dk=(double)k;
+ return dk*ln2_hi+dk*ln2_lo;
+ }
+ }
+ R = f*f*(0.5-0.33333333333333333*f);
+ if(k==0) return f-R; else {dk=(double)k;
+ return dk*ln2_hi-((R-dk*ln2_lo)-f);}
+ }
+ s = f/(2.0+f);
+ dk = (double)k;
+ z = s*s;
+ i = hx-0x6147a;
+ w = z*z;
+ j = 0x6b851-hx;
+ t1= w*(Lg2+w*(Lg4+w*Lg6));
+ t2= z*(Lg1+w*(Lg3+w*(Lg5+w*Lg7)));
+ i |= j;
+ R = t2+t1;
+ if(i>0) {
+ hfsq=0.5*f*f;
+ if(k==0) return f-(hfsq-s*(hfsq+R)); else
+ return dk*ln2_hi-((hfsq-(s*(hfsq+R)+dk*ln2_lo))-f);
+ } else {
+ if(k==0) return f-s*(f-R); else
+ return dk*ln2_hi-((s*(f-R)-dk*ln2_lo)-f);
+ }
+}
--- /dev/null
+
+/* @(#)e_log10.c 1.3 95/01/18 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunSoft, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/src/e_log10.c,v 1.15 2011/10/15 05:23:28 das Exp $");
+
+/*
+ * Return the base 10 logarithm of x. See e_log.c and k_log.h for most
+ * comments.
+ *
+ * log10(x) = (f - 0.5*f*f + k_log1p(f)) / ln10 + k * log10(2)
+ * in not-quite-routine extra precision.
+ */
+
+#include <openlibm_math.h>
+
+#include "math_private.h"
+#include "k_log.h"
+
+static const double
+two54 = 1.80143985094819840000e+16, /* 0x43500000, 0x00000000 */
+ivln10hi = 4.34294481878168880939e-01, /* 0x3fdbcb7b, 0x15200000 */
+ivln10lo = 2.50829467116452752298e-11, /* 0x3dbb9438, 0xca9aadd5 */
+log10_2hi = 3.01029995663611771306e-01, /* 0x3FD34413, 0x509F6000 */
+log10_2lo = 3.69423907715893078616e-13; /* 0x3D59FEF3, 0x11F12B36 */
+
+static const double zero = 0.0;
+
+OLM_DLLEXPORT double
+__ieee754_log10(double x)
+{
+ double f,hfsq,hi,lo,r,val_hi,val_lo,w,y,y2;
+ int32_t i,k,hx;
+ u_int32_t lx;
+
+ EXTRACT_WORDS(hx,lx,x);
+
+ k=0;
+ if (hx < 0x00100000) { /* x < 2**-1022 */
+ if (((hx&0x7fffffff)|lx)==0)
+ return -two54/zero; /* log(+-0)=-inf */
+ if (hx<0) return (x-x)/zero; /* log(-#) = NaN */
+ k -= 54; x *= two54; /* subnormal number, scale up x */
+ GET_HIGH_WORD(hx,x);
+ }
+ if (hx >= 0x7ff00000) return x+x;
+ if (hx == 0x3ff00000 && lx == 0)
+ return zero; /* log(1) = +0 */
+ k += (hx>>20)-1023;
+ hx &= 0x000fffff;
+ i = (hx+0x95f64)&0x100000;
+ SET_HIGH_WORD(x,hx|(i^0x3ff00000)); /* normalize x or x/2 */
+ k += (i>>20);
+ y = (double)k;
+ f = x - 1.0;
+ hfsq = 0.5*f*f;
+ r = k_log1p(f);
+
+ /* See e_log2.c for most details. */
+ hi = f - hfsq;
+ SET_LOW_WORD(hi,0);
+ lo = (f - hi) - hfsq + r;
+ val_hi = hi*ivln10hi;
+ y2 = y*log10_2hi;
+ val_lo = y*log10_2lo + (lo+hi)*ivln10lo + lo*ivln10hi;
+
+ /*
+ * Extra precision in for adding y*log10_2hi is not strictly needed
+ * since there is no very large cancellation near x = sqrt(2) or
+ * x = 1/sqrt(2), but we do it anyway since it costs little on CPUs
+ * with some parallelism and it reduces the error for many args.
+ */
+ w = y2 + val_hi;
+ val_lo += (y2 - w) + val_hi;
+ val_hi = w;
+
+ return val_lo + val_hi;
+}
--- /dev/null
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/src/e_log10f.c,v 1.13 2011/10/16 05:36:23 das Exp $");
+
+/*
+ * Float version of e_log10.c. See the latter for most comments.
+ */
+
+#include <openlibm_math.h>
+
+#include "math_private.h"
+#include "k_logf.h"
+
+// VBS
+#define float_t float
+
+static const float
+two25 = 3.3554432000e+07, /* 0x4c000000 */
+ivln10hi = 4.3432617188e-01, /* 0x3ede6000 */
+ivln10lo = -3.1689971365e-05, /* 0xb804ead9 */
+log10_2hi = 3.0102920532e-01, /* 0x3e9a2080 */
+log10_2lo = 7.9034151668e-07; /* 0x355427db */
+
+static const float zero = 0.0;
+
+OLM_DLLEXPORT float
+__ieee754_log10f(float x)
+{
+ float f,hfsq,hi,lo,r,y;
+ int32_t i,k,hx;
+
+ GET_FLOAT_WORD(hx,x);
+
+ k=0;
+ if (hx < 0x00800000) { /* x < 2**-126 */
+ if ((hx&0x7fffffff)==0)
+ return -two25/zero; /* log(+-0)=-inf */
+ if (hx<0) return (x-x)/zero; /* log(-#) = NaN */
+ k -= 25; x *= two25; /* subnormal number, scale up x */
+ GET_FLOAT_WORD(hx,x);
+ }
+ if (hx >= 0x7f800000) return x+x;
+ if (hx == 0x3f800000)
+ return zero; /* log(1) = +0 */
+ k += (hx>>23)-127;
+ hx &= 0x007fffff;
+ i = (hx+(0x4afb0d))&0x800000;
+ SET_FLOAT_WORD(x,hx|(i^0x3f800000)); /* normalize x or x/2 */
+ k += (i>>23);
+ y = (float)k;
+ f = x - (float)1.0;
+ hfsq = (float)0.5*f*f;
+ r = k_log1pf(f);
+
+ /* See e_log2f.c and e_log2.c for details. */
+ if (sizeof(float_t) > sizeof(float))
+ return (r - hfsq + f) * ((float_t)ivln10lo + ivln10hi) +
+ y * ((float_t)log10_2lo + log10_2hi);
+ hi = f - hfsq;
+ GET_FLOAT_WORD(hx,hi);
+ SET_FLOAT_WORD(hi,hx&0xfffff000);
+ lo = (f - hi) - hfsq + r;
+ return y*log10_2lo + (lo+hi)*ivln10lo + lo*ivln10hi + hi*ivln10hi +
+ y*log10_2hi;
+}
--- /dev/null
+
+/* @(#)e_log10.c 1.3 95/01/18 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunSoft, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/src/e_log2.c,v 1.4 2011/10/15 05:23:28 das Exp $");
+
+/*
+ * Return the base 2 logarithm of x. See e_log.c and k_log.h for most
+ * comments.
+ *
+ * This reduces x to {k, 1+f} exactly as in e_log.c, then calls the kernel,
+ * then does the combining and scaling steps
+ * log2(x) = (f - 0.5*f*f + k_log1p(f)) / ln2 + k
+ * in not-quite-routine extra precision.
+ */
+
+#include <openlibm_math.h>
+
+#include "math_private.h"
+#include "k_log.h"
+
+static const double
+two54 = 1.80143985094819840000e+16, /* 0x43500000, 0x00000000 */
+ivln2hi = 1.44269504072144627571e+00, /* 0x3ff71547, 0x65200000 */
+ivln2lo = 1.67517131648865118353e-10; /* 0x3de705fc, 0x2eefa200 */
+
+static const double zero = 0.0;
+
+OLM_DLLEXPORT double
+__ieee754_log2(double x)
+{
+ double f,hfsq,hi,lo,r,val_hi,val_lo,w,y;
+ int32_t i,k,hx;
+ u_int32_t lx;
+
+ EXTRACT_WORDS(hx,lx,x);
+
+ k=0;
+ if (hx < 0x00100000) { /* x < 2**-1022 */
+ if (((hx&0x7fffffff)|lx)==0)
+ return -two54/zero; /* log(+-0)=-inf */
+ if (hx<0) return (x-x)/zero; /* log(-#) = NaN */
+ k -= 54; x *= two54; /* subnormal number, scale up x */
+ GET_HIGH_WORD(hx,x);
+ }
+ if (hx >= 0x7ff00000) return x+x;
+ if (hx == 0x3ff00000 && lx == 0)
+ return zero; /* log(1) = +0 */
+ k += (hx>>20)-1023;
+ hx &= 0x000fffff;
+ i = (hx+0x95f64)&0x100000;
+ SET_HIGH_WORD(x,hx|(i^0x3ff00000)); /* normalize x or x/2 */
+ k += (i>>20);
+ y = (double)k;
+ f = x - 1.0;
+ hfsq = 0.5*f*f;
+ r = k_log1p(f);
+
+ /*
+ * f-hfsq must (for args near 1) be evaluated in extra precision
+ * to avoid a large cancellation when x is near sqrt(2) or 1/sqrt(2).
+ * This is fairly efficient since f-hfsq only depends on f, so can
+ * be evaluated in parallel with R. Not combining hfsq with R also
+ * keeps R small (though not as small as a true `lo' term would be),
+ * so that extra precision is not needed for terms involving R.
+ *
+ * Compiler bugs involving extra precision used to break Dekker's
+ * theorem for spitting f-hfsq as hi+lo, unless double_t was used
+ * or the multi-precision calculations were avoided when double_t
+ * has extra precision. These problems are now automatically
+ * avoided as a side effect of the optimization of combining the
+ * Dekker splitting step with the clear-low-bits step.
+ *
+ * y must (for args near sqrt(2) and 1/sqrt(2)) be added in extra
+ * precision to avoid a very large cancellation when x is very near
+ * these values. Unlike the above cancellations, this problem is
+ * specific to base 2. It is strange that adding +-1 is so much
+ * harder than adding +-ln2 or +-log10_2.
+ *
+ * This uses Dekker's theorem to normalize y+val_hi, so the
+ * compiler bugs are back in some configurations, sigh. And I
+ * don't want to used double_t to avoid them, since that gives a
+ * pessimization and the support for avoiding the pessimization
+ * is not yet available.
+ *
+ * The multi-precision calculations for the multiplications are
+ * routine.
+ */
+ hi = f - hfsq;
+ SET_LOW_WORD(hi,0);
+ lo = (f - hi) - hfsq + r;
+ val_hi = hi*ivln2hi;
+ val_lo = (lo+hi)*ivln2lo + lo*ivln2hi;
+
+ /* spadd(val_hi, val_lo, y), except for not using double_t: */
+ w = y + val_hi;
+ val_lo += (y - w) + val_hi;
+ val_hi = w;
+
+ return val_lo + val_hi;
+}
--- /dev/null
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/src/e_log2f.c,v 1.5 2011/10/15 05:23:28 das Exp $");
+
+/*
+ * Float version of e_log2.c. See the latter for most comments.
+ */
+
+#include <openlibm_math.h>
+
+#include "math_private.h"
+#include "k_logf.h"
+
+// VBS
+#define float_t float
+
+static const float
+two25 = 3.3554432000e+07, /* 0x4c000000 */
+ivln2hi = 1.4428710938e+00, /* 0x3fb8b000 */
+ivln2lo = -1.7605285393e-04; /* 0xb9389ad4 */
+
+static const float zero = 0.0;
+
+OLM_DLLEXPORT float
+__ieee754_log2f(float x)
+{
+ float f,hfsq,hi,lo,r,y;
+ int32_t i,k,hx;
+
+ GET_FLOAT_WORD(hx,x);
+
+ k=0;
+ if (hx < 0x00800000) { /* x < 2**-126 */
+ if ((hx&0x7fffffff)==0)
+ return -two25/zero; /* log(+-0)=-inf */
+ if (hx<0) return (x-x)/zero; /* log(-#) = NaN */
+ k -= 25; x *= two25; /* subnormal number, scale up x */
+ GET_FLOAT_WORD(hx,x);
+ }
+ if (hx >= 0x7f800000) return x+x;
+ if (hx == 0x3f800000)
+ return zero; /* log(1) = +0 */
+ k += (hx>>23)-127;
+ hx &= 0x007fffff;
+ i = (hx+(0x4afb0d))&0x800000;
+ SET_FLOAT_WORD(x,hx|(i^0x3f800000)); /* normalize x or x/2 */
+ k += (i>>23);
+ y = (float)k;
+ f = x - (float)1.0;
+ hfsq = (float)0.5*f*f;
+ r = k_log1pf(f);
+
+ /*
+ * We no longer need to avoid falling into the multi-precision
+ * calculations due to compiler bugs breaking Dekker's theorem.
+ * Keep avoiding this as an optimization. See e_log2.c for more
+ * details (some details are here only because the optimization
+ * is not yet available in double precision).
+ *
+ * Another compiler bug turned up. With gcc on i386,
+ * (ivln2lo + ivln2hi) would be evaluated in float precision
+ * despite runtime evaluations using double precision. So we
+ * must cast one of its terms to float_t. This makes the whole
+ * expression have type float_t, so return is forced to waste
+ * time clobbering its extra precision.
+ */
+ if (sizeof(float_t) > sizeof(float))
+ return (r - hfsq + f) * ((float_t)ivln2lo + ivln2hi) + y;
+
+ hi = f - hfsq;
+ GET_FLOAT_WORD(hx,hi);
+ SET_FLOAT_WORD(hi,hx&0xfffff000);
+ lo = (f - hi) - hfsq + r;
+ return (lo+hi)*ivln2lo + lo*ivln2hi + hi*ivln2hi + y;
+}
--- /dev/null
+/* e_logf.c -- float version of e_log.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/src/e_logf.c,v 1.11 2008/03/29 16:37:59 das Exp $");
+
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+static const float
+ln2_hi = 6.9313812256e-01, /* 0x3f317180 */
+ln2_lo = 9.0580006145e-06, /* 0x3717f7d1 */
+two25 = 3.355443200e+07, /* 0x4c000000 */
+/* |(log(1+s)-log(1-s))/s - Lg(s)| < 2**-34.24 (~[-4.95e-11, 4.97e-11]). */
+Lg1 = 0xaaaaaa.0p-24, /* 0.66666662693 */
+Lg2 = 0xccce13.0p-25, /* 0.40000972152 */
+Lg3 = 0x91e9ee.0p-25, /* 0.28498786688 */
+Lg4 = 0xf89e26.0p-26; /* 0.24279078841 */
+
+static const float zero = 0.0;
+
+OLM_DLLEXPORT float
+__ieee754_logf(float x)
+{
+ float hfsq,f,s,z,R,w,t1,t2,dk;
+ int32_t k,ix,i,j;
+
+ GET_FLOAT_WORD(ix,x);
+
+ k=0;
+ if (ix < 0x00800000) { /* x < 2**-126 */
+ if ((ix&0x7fffffff)==0)
+ return -two25/zero; /* log(+-0)=-inf */
+ if (ix<0) return (x-x)/zero; /* log(-#) = NaN */
+ k -= 25; x *= two25; /* subnormal number, scale up x */
+ GET_FLOAT_WORD(ix,x);
+ }
+ if (ix >= 0x7f800000) return x+x;
+ k += (ix>>23)-127;
+ ix &= 0x007fffff;
+ i = (ix+(0x95f64<<3))&0x800000;
+ SET_FLOAT_WORD(x,ix|(i^0x3f800000)); /* normalize x or x/2 */
+ k += (i>>23);
+ f = x-(float)1.0;
+ if((0x007fffff&(0x8000+ix))<0xc000) { /* -2**-9 <= f < 2**-9 */
+ if(f==zero) {
+ if(k==0) {
+ return zero;
+ } else {
+ dk=(float)k;
+ return dk*ln2_hi+dk*ln2_lo;
+ }
+ }
+ R = f*f*((float)0.5-(float)0.33333333333333333*f);
+ if(k==0) return f-R; else {dk=(float)k;
+ return dk*ln2_hi-((R-dk*ln2_lo)-f);}
+ }
+ s = f/((float)2.0+f);
+ dk = (float)k;
+ z = s*s;
+ i = ix-(0x6147a<<3);
+ w = z*z;
+ j = (0x6b851<<3)-ix;
+ t1= w*(Lg2+w*Lg4);
+ t2= z*(Lg1+w*Lg3);
+ i |= j;
+ R = t2+t1;
+ if(i>0) {
+ hfsq=(float)0.5*f*f;
+ if(k==0) return f-(hfsq-s*(hfsq+R)); else
+ return dk*ln2_hi-((hfsq-(s*(hfsq+R)+dk*ln2_lo))-f);
+ } else {
+ if(k==0) return f-s*(f-R); else
+ return dk*ln2_hi-((s*(f-R)-dk*ln2_lo)-f);
+ }
+}
--- /dev/null
+/* @(#)e_pow.c 1.5 04/04/22 SMI */
+/*
+ * ====================================================
+ * Copyright (C) 2004 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/src/e_pow.c,v 1.14 2011/10/21 06:26:07 das Exp $");
+
+/* __ieee754_pow(x,y) return x**y
+ *
+ * n
+ * Method: Let x = 2 * (1+f)
+ * 1. Compute and return log2(x) in two pieces:
+ * log2(x) = w1 + w2,
+ * where w1 has 53-24 = 29 bit trailing zeros.
+ * 2. Perform y*log2(x) = n+y' by simulating muti-precision
+ * arithmetic, where |y'|<=0.5.
+ * 3. Return x**y = 2**n*exp(y'*log2)
+ *
+ * Special cases:
+ * 1. (anything) ** 0 is 1
+ * 2. (anything) ** 1 is itself
+ * 3. (anything) ** NAN is NAN
+ * 4. NAN ** (anything except 0) is NAN
+ * 5. +-(|x| > 1) ** +INF is +INF
+ * 6. +-(|x| > 1) ** -INF is +0
+ * 7. +-(|x| < 1) ** +INF is +0
+ * 8. +-(|x| < 1) ** -INF is +INF
+ * 9. +-1 ** +-INF is NAN
+ * 10. +0 ** (+anything except 0, NAN) is +0
+ * 11. -0 ** (+anything except 0, NAN, odd integer) is +0
+ * 12. +0 ** (-anything except 0, NAN) is +INF
+ * 13. -0 ** (-anything except 0, NAN, odd integer) is +INF
+ * 14. -0 ** (odd integer) = -( +0 ** (odd integer) )
+ * 15. +INF ** (+anything except 0,NAN) is +INF
+ * 16. +INF ** (-anything except 0,NAN) is +0
+ * 17. -INF ** (anything) = -0 ** (-anything)
+ * 18. (-anything) ** (integer) is (-1)**(integer)*(+anything**integer)
+ * 19. (-anything except 0 and inf) ** (non-integer) is NAN
+ *
+ * Accuracy:
+ * pow(x,y) returns x**y nearly rounded. In particular
+ * pow(integer,integer)
+ * always returns the correct integer provided it is
+ * representable.
+ *
+ * Constants :
+ * The hexadecimal values are the intended ones for the following
+ * constants. The decimal values may be used, provided that the
+ * compiler will convert from decimal to binary accurately enough
+ * to produce the hexadecimal values shown.
+ */
+
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+static const double
+bp[] = {1.0, 1.5,},
+dp_h[] = { 0.0, 5.84962487220764160156e-01,}, /* 0x3FE2B803, 0x40000000 */
+dp_l[] = { 0.0, 1.35003920212974897128e-08,}, /* 0x3E4CFDEB, 0x43CFD006 */
+zero = 0.0,
+one = 1.0,
+two = 2.0,
+two53 = 9007199254740992.0, /* 0x43400000, 0x00000000 */
+huge = 1.0e300,
+tiny = 1.0e-300,
+ /* poly coefs for (3/2)*(log(x)-2s-2/3*s**3 */
+L1 = 5.99999999999994648725e-01, /* 0x3FE33333, 0x33333303 */
+L2 = 4.28571428578550184252e-01, /* 0x3FDB6DB6, 0xDB6FABFF */
+L3 = 3.33333329818377432918e-01, /* 0x3FD55555, 0x518F264D */
+L4 = 2.72728123808534006489e-01, /* 0x3FD17460, 0xA91D4101 */
+L5 = 2.30660745775561754067e-01, /* 0x3FCD864A, 0x93C9DB65 */
+L6 = 2.06975017800338417784e-01, /* 0x3FCA7E28, 0x4A454EEF */
+P1 = 1.66666666666666019037e-01, /* 0x3FC55555, 0x5555553E */
+P2 = -2.77777777770155933842e-03, /* 0xBF66C16C, 0x16BEBD93 */
+P3 = 6.61375632143793436117e-05, /* 0x3F11566A, 0xAF25DE2C */
+P4 = -1.65339022054652515390e-06, /* 0xBEBBBD41, 0xC5D26BF1 */
+P5 = 4.13813679705723846039e-08, /* 0x3E663769, 0x72BEA4D0 */
+lg2 = 6.93147180559945286227e-01, /* 0x3FE62E42, 0xFEFA39EF */
+lg2_h = 6.93147182464599609375e-01, /* 0x3FE62E43, 0x00000000 */
+lg2_l = -1.90465429995776804525e-09, /* 0xBE205C61, 0x0CA86C39 */
+ovt = 8.0085662595372944372e-0017, /* -(1024-log2(ovfl+.5ulp)) */
+cp = 9.61796693925975554329e-01, /* 0x3FEEC709, 0xDC3A03FD =2/(3ln2) */
+cp_h = 9.61796700954437255859e-01, /* 0x3FEEC709, 0xE0000000 =(float)cp */
+cp_l = -7.02846165095275826516e-09, /* 0xBE3E2FE0, 0x145B01F5 =tail of cp_h*/
+ivln2 = 1.44269504088896338700e+00, /* 0x3FF71547, 0x652B82FE =1/ln2 */
+ivln2_h = 1.44269502162933349609e+00, /* 0x3FF71547, 0x60000000 =24b 1/ln2*/
+ivln2_l = 1.92596299112661746887e-08; /* 0x3E54AE0B, 0xF85DDF44 =1/ln2 tail*/
+
+OLM_DLLEXPORT double
+__ieee754_pow(double x, double y)
+{
+ double z,ax,z_h,z_l,p_h,p_l;
+ double y1,t1,t2,r,s,t,u,v,w;
+ int32_t i,j,k,yisint,n;
+ int32_t hx,hy,ix,iy;
+ u_int32_t lx,ly;
+
+ EXTRACT_WORDS(hx,lx,x);
+ EXTRACT_WORDS(hy,ly,y);
+ ix = hx&0x7fffffff; iy = hy&0x7fffffff;
+
+ /* y==zero: x**0 = 1 */
+ if((iy|ly)==0) return one;
+
+ /* x==1: 1**y = 1, even if y is NaN */
+ if (hx==0x3ff00000 && lx == 0) return one;
+
+ /* y!=zero: result is NaN if either arg is NaN */
+ if(ix > 0x7ff00000 || ((ix==0x7ff00000)&&(lx!=0)) ||
+ iy > 0x7ff00000 || ((iy==0x7ff00000)&&(ly!=0)))
+ return (x+0.0)+(y+0.0);
+
+ /* determine if y is an odd int when x < 0
+ * yisint = 0 ... y is not an integer
+ * yisint = 1 ... y is an odd int
+ * yisint = 2 ... y is an even int
+ */
+ yisint = 0;
+ if(hx<0) {
+ if(iy>=0x43400000) yisint = 2; /* even integer y */
+ else if(iy>=0x3ff00000) {
+ k = (iy>>20)-0x3ff; /* exponent */
+ if(k>20) {
+ j = ly>>(52-k);
+ if((j<<(52-k))==ly) yisint = 2-(j&1);
+ } else if(ly==0) {
+ j = iy>>(20-k);
+ if((j<<(20-k))==iy) yisint = 2-(j&1);
+ }
+ }
+ }
+
+ /* special value of y */
+ if(ly==0) {
+ if (iy==0x7ff00000) { /* y is +-inf */
+ if(((ix-0x3ff00000)|lx)==0)
+ return one; /* (-1)**+-inf is NaN */
+ else if (ix >= 0x3ff00000)/* (|x|>1)**+-inf = inf,0 */
+ return (hy>=0)? y: zero;
+ else /* (|x|<1)**-,+inf = inf,0 */
+ return (hy<0)?-y: zero;
+ }
+ if(iy==0x3ff00000) { /* y is +-1 */
+ if(hy<0) return one/x; else return x;
+ }
+ if(hy==0x40000000) return x*x; /* y is 2 */
+ if(hy==0x40080000) return x*x*x; /* y is 3 */
+ if(hy==0x40100000) { /* y is 4 */
+ u = x*x;
+ return u*u;
+ }
+ if(hy==0x3fe00000) { /* y is 0.5 */
+ if(hx>=0) /* x >= +0 */
+ return sqrt(x);
+ }
+ }
+
+ ax = fabs(x);
+ /* special value of x */
+ if(lx==0) {
+ if(ix==0x7ff00000||ix==0||ix==0x3ff00000){
+ z = ax; /*x is +-0,+-inf,+-1*/
+ if(hy<0) z = one/z; /* z = (1/|x|) */
+ if(hx<0) {
+ if(((ix-0x3ff00000)|yisint)==0) {
+ z = (z-z)/(z-z); /* (-1)**non-int is NaN */
+ } else if(yisint==1)
+ z = -z; /* (x<0)**odd = -(|x|**odd) */
+ }
+ return z;
+ }
+ }
+
+ /* CYGNUS LOCAL + fdlibm-5.3 fix: This used to be
+ n = (hx>>31)+1;
+ but ANSI C says a right shift of a signed negative quantity is
+ implementation defined. */
+ n = ((u_int32_t)hx>>31)-1;
+
+ /* (x<0)**(non-int) is NaN */
+ if((n|yisint)==0) return (x-x)/(x-x);
+
+ s = one; /* s (sign of result -ve**odd) = -1 else = 1 */
+ if((n|(yisint-1))==0) s = -one;/* (-ve)**(odd int) */
+
+ /* |y| is huge */
+ if(iy>0x41e00000) { /* if |y| > 2**31 */
+ if(iy>0x43f00000){ /* if |y| > 2**64, must o/uflow */
+ if(ix<=0x3fefffff) return (hy<0)? huge*huge:tiny*tiny;
+ if(ix>=0x3ff00000) return (hy>0)? huge*huge:tiny*tiny;
+ }
+ /* over/underflow if x is not close to one */
+ if(ix<0x3fefffff) return (hy<0)? s*huge*huge:s*tiny*tiny;
+ if(ix>0x3ff00000) return (hy>0)? s*huge*huge:s*tiny*tiny;
+ /* now |1-x| is tiny <= 2**-20, suffice to compute
+ log(x) by x-x^2/2+x^3/3-x^4/4 */
+ t = ax-one; /* t has 20 trailing zeros */
+ w = (t*t)*(0.5-t*(0.3333333333333333333333-t*0.25));
+ u = ivln2_h*t; /* ivln2_h has 21 sig. bits */
+ v = t*ivln2_l-w*ivln2;
+ t1 = u+v;
+ SET_LOW_WORD(t1,0);
+ t2 = v-(t1-u);
+ } else {
+ double ss,s2,s_h,s_l,t_h,t_l;
+ n = 0;
+ /* take care subnormal number */
+ if(ix<0x00100000)
+ {ax *= two53; n -= 53; GET_HIGH_WORD(ix,ax); }
+ n += ((ix)>>20)-0x3ff;
+ j = ix&0x000fffff;
+ /* determine interval */
+ ix = j|0x3ff00000; /* normalize ix */
+ if(j<=0x3988E) k=0; /* |x|<sqrt(3/2) */
+ else if(j<0xBB67A) k=1; /* |x|<sqrt(3) */
+ else {k=0;n+=1;ix -= 0x00100000;}
+ SET_HIGH_WORD(ax,ix);
+
+ /* compute ss = s_h+s_l = (x-1)/(x+1) or (x-1.5)/(x+1.5) */
+ u = ax-bp[k]; /* bp[0]=1.0, bp[1]=1.5 */
+ v = one/(ax+bp[k]);
+ ss = u*v;
+ s_h = ss;
+ SET_LOW_WORD(s_h,0);
+ /* t_h=ax+bp[k] High */
+ t_h = zero;
+ SET_HIGH_WORD(t_h,((ix>>1)|0x20000000)+0x00080000+(k<<18));
+ t_l = ax - (t_h-bp[k]);
+ s_l = v*((u-s_h*t_h)-s_h*t_l);
+ /* compute log(ax) */
+ s2 = ss*ss;
+ r = s2*s2*(L1+s2*(L2+s2*(L3+s2*(L4+s2*(L5+s2*L6)))));
+ r += s_l*(s_h+ss);
+ s2 = s_h*s_h;
+ t_h = 3.0+s2+r;
+ SET_LOW_WORD(t_h,0);
+ t_l = r-((t_h-3.0)-s2);
+ /* u+v = ss*(1+...) */
+ u = s_h*t_h;
+ v = s_l*t_h+t_l*ss;
+ /* 2/(3log2)*(ss+...) */
+ p_h = u+v;
+ SET_LOW_WORD(p_h,0);
+ p_l = v-(p_h-u);
+ z_h = cp_h*p_h; /* cp_h+cp_l = 2/(3*log2) */
+ z_l = cp_l*p_h+p_l*cp+dp_l[k];
+ /* log2(ax) = (ss+..)*2/(3*log2) = n + dp_h + z_h + z_l */
+ t = (double)n;
+ t1 = (((z_h+z_l)+dp_h[k])+t);
+ SET_LOW_WORD(t1,0);
+ t2 = z_l-(((t1-t)-dp_h[k])-z_h);
+ }
+
+ /* split up y into y1+y2 and compute (y1+y2)*(t1+t2) */
+ y1 = y;
+ SET_LOW_WORD(y1,0);
+ p_l = (y-y1)*t1+y*t2;
+ p_h = y1*t1;
+ z = p_l+p_h;
+ EXTRACT_WORDS(j,i,z);
+ if (j>=0x40900000) { /* z >= 1024 */
+ if(((j-0x40900000)|i)!=0) /* if z > 1024 */
+ return s*huge*huge; /* overflow */
+ else {
+ if(p_l+ovt>z-p_h) return s*huge*huge; /* overflow */
+ }
+ } else if((j&0x7fffffff)>=0x4090cc00 ) { /* z <= -1075 */
+ if(((j-0xc090cc00)|i)!=0) /* z < -1075 */
+ return s*tiny*tiny; /* underflow */
+ else {
+ if(p_l<=z-p_h) return s*tiny*tiny; /* underflow */
+ }
+ }
+ /*
+ * compute 2**(p_h+p_l)
+ */
+ i = j&0x7fffffff;
+ k = (i>>20)-0x3ff;
+ n = 0;
+ if(i>0x3fe00000) { /* if |z| > 0.5, set n = [z+0.5] */
+ n = j+(0x00100000>>(k+1));
+ k = ((n&0x7fffffff)>>20)-0x3ff; /* new k for n */
+ t = zero;
+ SET_HIGH_WORD(t,n&~(0x000fffff>>k));
+ n = ((n&0x000fffff)|0x00100000)>>(20-k);
+ if(j<0) n = -n;
+ p_h -= t;
+ }
+ t = p_l+p_h;
+ SET_LOW_WORD(t,0);
+ u = t*lg2_h;
+ v = (p_l-(t-p_h))*lg2+t*lg2_l;
+ z = u+v;
+ w = v-(z-u);
+ t = z*z;
+ t1 = z - t*(P1+t*(P2+t*(P3+t*(P4+t*P5))));
+ r = (z*t1)/(t1-two)-(w+z*w);
+ z = one-(r-z);
+ GET_HIGH_WORD(j,z);
+ j += (n<<20);
+ if((j>>20)<=0) z = scalbn(z,n); /* subnormal output */
+ else SET_HIGH_WORD(z,j);
+ return s*z;
+}
--- /dev/null
+/* e_powf.c -- float version of e_pow.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/src/e_powf.c,v 1.16 2011/10/21 06:26:07 das Exp $");
+
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+static const float
+bp[] = {1.0, 1.5,},
+dp_h[] = { 0.0, 5.84960938e-01,}, /* 0x3f15c000 */
+dp_l[] = { 0.0, 1.56322085e-06,}, /* 0x35d1cfdc */
+zero = 0.0,
+one = 1.0,
+two = 2.0,
+two24 = 16777216.0, /* 0x4b800000 */
+huge = 1.0e30,
+tiny = 1.0e-30,
+ /* poly coefs for (3/2)*(log(x)-2s-2/3*s**3 */
+L1 = 6.0000002384e-01, /* 0x3f19999a */
+L2 = 4.2857143283e-01, /* 0x3edb6db7 */
+L3 = 3.3333334327e-01, /* 0x3eaaaaab */
+L4 = 2.7272811532e-01, /* 0x3e8ba305 */
+L5 = 2.3066075146e-01, /* 0x3e6c3255 */
+L6 = 2.0697501302e-01, /* 0x3e53f142 */
+P1 = 1.6666667163e-01, /* 0x3e2aaaab */
+P2 = -2.7777778450e-03, /* 0xbb360b61 */
+P3 = 6.6137559770e-05, /* 0x388ab355 */
+P4 = -1.6533901999e-06, /* 0xb5ddea0e */
+P5 = 4.1381369442e-08, /* 0x3331bb4c */
+lg2 = 6.9314718246e-01, /* 0x3f317218 */
+lg2_h = 6.93145752e-01, /* 0x3f317200 */
+lg2_l = 1.42860654e-06, /* 0x35bfbe8c */
+ovt = 4.2995665694e-08, /* -(128-log2(ovfl+.5ulp)) */
+cp = 9.6179670095e-01, /* 0x3f76384f =2/(3ln2) */
+cp_h = 9.6191406250e-01, /* 0x3f764000 =12b cp */
+cp_l = -1.1736857402e-04, /* 0xb8f623c6 =tail of cp_h */
+ivln2 = 1.4426950216e+00, /* 0x3fb8aa3b =1/ln2 */
+ivln2_h = 1.4426879883e+00, /* 0x3fb8aa00 =16b 1/ln2*/
+ivln2_l = 7.0526075433e-06; /* 0x36eca570 =1/ln2 tail*/
+
+OLM_DLLEXPORT float
+__ieee754_powf(float x, float y)
+{
+ float z,ax,z_h,z_l,p_h,p_l;
+ float y1,t1,t2,r,s,sn,t,u,v,w;
+ int32_t i,j,k,yisint,n;
+ int32_t hx,hy,ix,iy,is;
+
+ GET_FLOAT_WORD(hx,x);
+ GET_FLOAT_WORD(hy,y);
+ ix = hx&0x7fffffff; iy = hy&0x7fffffff;
+
+ /* y==zero: x**0 = 1 */
+ if(iy==0) return one;
+
+ /* x==1: 1**y = 1, even if y is NaN */
+ if (hx==0x3f800000) return one;
+
+ /* y!=zero: result is NaN if either arg is NaN */
+ if(ix > 0x7f800000 ||
+ iy > 0x7f800000)
+ return (x+0.0F)+(y+0.0F);
+
+ /* determine if y is an odd int when x < 0
+ * yisint = 0 ... y is not an integer
+ * yisint = 1 ... y is an odd int
+ * yisint = 2 ... y is an even int
+ */
+ yisint = 0;
+ if(hx<0) {
+ if(iy>=0x4b800000) yisint = 2; /* even integer y */
+ else if(iy>=0x3f800000) {
+ k = (iy>>23)-0x7f; /* exponent */
+ j = iy>>(23-k);
+ if((j<<(23-k))==iy) yisint = 2-(j&1);
+ }
+ }
+
+ /* special value of y */
+ if (iy==0x7f800000) { /* y is +-inf */
+ if (ix==0x3f800000)
+ return one; /* (-1)**+-inf is NaN */
+ else if (ix > 0x3f800000)/* (|x|>1)**+-inf = inf,0 */
+ return (hy>=0)? y: zero;
+ else /* (|x|<1)**-,+inf = inf,0 */
+ return (hy<0)?-y: zero;
+ }
+ if(iy==0x3f800000) { /* y is +-1 */
+ if(hy<0) return one/x; else return x;
+ }
+ if(hy==0x40000000) return x*x; /* y is 2 */
+ if(hy==0x40400000) return x*x*x; /* y is 3 */
+ if(hy==0x40800000) { /* y is 4 */
+ u = x*x;
+ return u*u;
+ }
+ if(hy==0x3f000000) { /* y is 0.5 */
+ if(hx>=0) /* x >= +0 */
+ return __ieee754_sqrtf(x);
+ }
+
+ ax = fabsf(x);
+ /* special value of x */
+ if(ix==0x7f800000||ix==0||ix==0x3f800000){
+ z = ax; /*x is +-0,+-inf,+-1*/
+ if(hy<0) z = one/z; /* z = (1/|x|) */
+ if(hx<0) {
+ if(((ix-0x3f800000)|yisint)==0) {
+ z = (z-z)/(z-z); /* (-1)**non-int is NaN */
+ } else if(yisint==1)
+ z = -z; /* (x<0)**odd = -(|x|**odd) */
+ }
+ return z;
+ }
+
+ n = ((u_int32_t)hx>>31)-1;
+
+ /* (x<0)**(non-int) is NaN */
+ if((n|yisint)==0) return (x-x)/(x-x);
+
+ sn = one; /* s (sign of result -ve**odd) = -1 else = 1 */
+ if((n|(yisint-1))==0) sn = -one;/* (-ve)**(odd int) */
+
+ /* |y| is huge */
+ if(iy>0x4d000000) { /* if |y| > 2**27 */
+ /* over/underflow if x is not close to one */
+ if(ix<0x3f7ffff8) return (hy<0)? sn*huge*huge:sn*tiny*tiny;
+ if(ix>0x3f800007) return (hy>0)? sn*huge*huge:sn*tiny*tiny;
+ /* now |1-x| is tiny <= 2**-20, suffice to compute
+ log(x) by x-x^2/2+x^3/3-x^4/4 */
+ t = ax-1; /* t has 20 trailing zeros */
+ w = (t*t)*((float)0.5-t*((float)0.333333333333-t*(float)0.25));
+ u = ivln2_h*t; /* ivln2_h has 16 sig. bits */
+ v = t*ivln2_l-w*ivln2;
+ t1 = u+v;
+ GET_FLOAT_WORD(is,t1);
+ SET_FLOAT_WORD(t1,is&0xfffff000);
+ t2 = v-(t1-u);
+ } else {
+ float s2,s_h,s_l,t_h,t_l;
+ n = 0;
+ /* take care subnormal number */
+ if(ix<0x00800000)
+ {ax *= two24; n -= 24; GET_FLOAT_WORD(ix,ax); }
+ n += ((ix)>>23)-0x7f;
+ j = ix&0x007fffff;
+ /* determine interval */
+ ix = j|0x3f800000; /* normalize ix */
+ if(j<=0x1cc471) k=0; /* |x|<sqrt(3/2) */
+ else if(j<0x5db3d7) k=1; /* |x|<sqrt(3) */
+ else {k=0;n+=1;ix -= 0x00800000;}
+ SET_FLOAT_WORD(ax,ix);
+
+ /* compute s = s_h+s_l = (x-1)/(x+1) or (x-1.5)/(x+1.5) */
+ u = ax-bp[k]; /* bp[0]=1.0, bp[1]=1.5 */
+ v = one/(ax+bp[k]);
+ s = u*v;
+ s_h = s;
+ GET_FLOAT_WORD(is,s_h);
+ SET_FLOAT_WORD(s_h,is&0xfffff000);
+ /* t_h=ax+bp[k] High */
+ is = ((ix>>1)&0xfffff000)|0x20000000;
+ SET_FLOAT_WORD(t_h,is+0x00400000+(k<<21));
+ t_l = ax - (t_h-bp[k]);
+ s_l = v*((u-s_h*t_h)-s_h*t_l);
+ /* compute log(ax) */
+ s2 = s*s;
+ r = s2*s2*(L1+s2*(L2+s2*(L3+s2*(L4+s2*(L5+s2*L6)))));
+ r += s_l*(s_h+s);
+ s2 = s_h*s_h;
+ t_h = (float)3.0+s2+r;
+ GET_FLOAT_WORD(is,t_h);
+ SET_FLOAT_WORD(t_h,is&0xfffff000);
+ t_l = r-((t_h-(float)3.0)-s2);
+ /* u+v = s*(1+...) */
+ u = s_h*t_h;
+ v = s_l*t_h+t_l*s;
+ /* 2/(3log2)*(s+...) */
+ p_h = u+v;
+ GET_FLOAT_WORD(is,p_h);
+ SET_FLOAT_WORD(p_h,is&0xfffff000);
+ p_l = v-(p_h-u);
+ z_h = cp_h*p_h; /* cp_h+cp_l = 2/(3*log2) */
+ z_l = cp_l*p_h+p_l*cp+dp_l[k];
+ /* log2(ax) = (s+..)*2/(3*log2) = n + dp_h + z_h + z_l */
+ t = (float)n;
+ t1 = (((z_h+z_l)+dp_h[k])+t);
+ GET_FLOAT_WORD(is,t1);
+ SET_FLOAT_WORD(t1,is&0xfffff000);
+ t2 = z_l-(((t1-t)-dp_h[k])-z_h);
+ }
+
+ /* split up y into y1+y2 and compute (y1+y2)*(t1+t2) */
+ GET_FLOAT_WORD(is,y);
+ SET_FLOAT_WORD(y1,is&0xfffff000);
+ p_l = (y-y1)*t1+y*t2;
+ p_h = y1*t1;
+ z = p_l+p_h;
+ GET_FLOAT_WORD(j,z);
+ if (j>0x43000000) /* if z > 128 */
+ return sn*huge*huge; /* overflow */
+ else if (j==0x43000000) { /* if z == 128 */
+ if(p_l+ovt>z-p_h) return sn*huge*huge; /* overflow */
+ }
+ else if ((j&0x7fffffff)>0x43160000) /* z <= -150 */
+ return sn*tiny*tiny; /* underflow */
+ else if (j==0xc3160000){ /* z == -150 */
+ if(p_l<=z-p_h) return sn*tiny*tiny; /* underflow */
+ }
+ /*
+ * compute 2**(p_h+p_l)
+ */
+ i = j&0x7fffffff;
+ k = (i>>23)-0x7f;
+ n = 0;
+ if(i>0x3f000000) { /* if |z| > 0.5, set n = [z+0.5] */
+ n = j+(0x00800000>>(k+1));
+ k = ((n&0x7fffffff)>>23)-0x7f; /* new k for n */
+ SET_FLOAT_WORD(t,n&~(0x007fffff>>k));
+ n = ((n&0x007fffff)|0x00800000)>>(23-k);
+ if(j<0) n = -n;
+ p_h -= t;
+ }
+ t = p_l+p_h;
+ GET_FLOAT_WORD(is,t);
+ SET_FLOAT_WORD(t,is&0xffff8000);
+ u = t*lg2_h;
+ v = (p_l-(t-p_h))*lg2+t*lg2_l;
+ z = u+v;
+ w = v-(z-u);
+ t = z*z;
+ t1 = z - t*(P1+t*(P2+t*(P3+t*(P4+t*P5))));
+ r = (z*t1)/(t1-two)-(w+z*w);
+ z = one-(r-z);
+ GET_FLOAT_WORD(j,z);
+ j += (n<<23);
+ if((j>>23)<=0) z = scalbnf(z,n); /* subnormal output */
+ else SET_FLOAT_WORD(z,j);
+ return sn*z;
+}
--- /dev/null
+
+/* @(#)e_rem_pio2.c 1.4 95/01/18 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunSoft, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ *
+ * Optimized by Bruce D. Evans.
+ */
+
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/src/e_rem_pio2.c,v 1.22 2011/06/19 17:07:58 kargl Exp $");
+
+/* __ieee754_rem_pio2(x,y)
+ *
+ * return the remainder of x rem pi/2 in y[0]+y[1]
+ * use __kernel_rem_pio2()
+ */
+
+#include <float.h>
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+/*
+ * invpio2: 53 bits of 2/pi
+ * pio2_1: first 33 bit of pi/2
+ * pio2_1t: pi/2 - pio2_1
+ * pio2_2: second 33 bit of pi/2
+ * pio2_2t: pi/2 - (pio2_1+pio2_2)
+ * pio2_3: third 33 bit of pi/2
+ * pio2_3t: pi/2 - (pio2_1+pio2_2+pio2_3)
+ */
+
+static const double
+zero = 0.00000000000000000000e+00, /* 0x00000000, 0x00000000 */
+two24 = 1.67772160000000000000e+07, /* 0x41700000, 0x00000000 */
+invpio2 = 6.36619772367581382433e-01, /* 0x3FE45F30, 0x6DC9C883 */
+pio2_1 = 1.57079632673412561417e+00, /* 0x3FF921FB, 0x54400000 */
+pio2_1t = 6.07710050650619224932e-11, /* 0x3DD0B461, 0x1A626331 */
+pio2_2 = 6.07710050630396597660e-11, /* 0x3DD0B461, 0x1A600000 */
+pio2_2t = 2.02226624879595063154e-21, /* 0x3BA3198A, 0x2E037073 */
+pio2_3 = 2.02226624871116645580e-21, /* 0x3BA3198A, 0x2E000000 */
+pio2_3t = 8.47842766036889956997e-32; /* 0x397B839A, 0x252049C1 */
+
+__inline int
+__ieee754_rem_pio2(double x, double *y)
+{
+ double z,w,t,r,fn;
+ double tx[3],ty[2];
+ int32_t e0,i,j,nx,n,ix,hx;
+ u_int32_t low;
+
+ GET_HIGH_WORD(hx,x); /* high word of x */
+ ix = hx&0x7fffffff;
+#if 0 /* Must be handled in caller. */
+ if(ix<=0x3fe921fb) /* |x| ~<= pi/4 , no need for reduction */
+ {y[0] = x; y[1] = 0; return 0;}
+#endif
+ if (ix <= 0x400f6a7a) { /* |x| ~<= 5pi/4 */
+ if ((ix & 0xfffff) == 0x921fb) /* |x| ~= pi/2 or 2pi/2 */
+ goto medium; /* cancellation -- use medium case */
+ if (ix <= 0x4002d97c) { /* |x| ~<= 3pi/4 */
+ if (hx > 0) {
+ z = x - pio2_1; /* one round good to 85 bits */
+ y[0] = z - pio2_1t;
+ y[1] = (z-y[0])-pio2_1t;
+ return 1;
+ } else {
+ z = x + pio2_1;
+ y[0] = z + pio2_1t;
+ y[1] = (z-y[0])+pio2_1t;
+ return -1;
+ }
+ } else {
+ if (hx > 0) {
+ z = x - 2*pio2_1;
+ y[0] = z - 2*pio2_1t;
+ y[1] = (z-y[0])-2*pio2_1t;
+ return 2;
+ } else {
+ z = x + 2*pio2_1;
+ y[0] = z + 2*pio2_1t;
+ y[1] = (z-y[0])+2*pio2_1t;
+ return -2;
+ }
+ }
+ }
+ if (ix <= 0x401c463b) { /* |x| ~<= 9pi/4 */
+ if (ix <= 0x4015fdbc) { /* |x| ~<= 7pi/4 */
+ if (ix == 0x4012d97c) /* |x| ~= 3pi/2 */
+ goto medium;
+ if (hx > 0) {
+ z = x - 3*pio2_1;
+ y[0] = z - 3*pio2_1t;
+ y[1] = (z-y[0])-3*pio2_1t;
+ return 3;
+ } else {
+ z = x + 3*pio2_1;
+ y[0] = z + 3*pio2_1t;
+ y[1] = (z-y[0])+3*pio2_1t;
+ return -3;
+ }
+ } else {
+ if (ix == 0x401921fb) /* |x| ~= 4pi/2 */
+ goto medium;
+ if (hx > 0) {
+ z = x - 4*pio2_1;
+ y[0] = z - 4*pio2_1t;
+ y[1] = (z-y[0])-4*pio2_1t;
+ return 4;
+ } else {
+ z = x + 4*pio2_1;
+ y[0] = z + 4*pio2_1t;
+ y[1] = (z-y[0])+4*pio2_1t;
+ return -4;
+ }
+ }
+ }
+ if(ix<0x413921fb) { /* |x| ~< 2^20*(pi/2), medium size */
+medium:
+ /* Use a specialized rint() to get fn. Assume round-to-nearest. */
+ STRICT_ASSIGN(double,fn,x*invpio2+0x1.8p52);
+ fn = fn-0x1.8p52;
+#ifdef HAVE_EFFICIENT_IRINT
+ n = irint(fn);
+#else
+ n = (int32_t)fn;
+#endif
+ r = x-fn*pio2_1;
+ w = fn*pio2_1t; /* 1st round good to 85 bit */
+ {
+ u_int32_t high;
+ j = ix>>20;
+ y[0] = r-w;
+ GET_HIGH_WORD(high,y[0]);
+ i = j-((high>>20)&0x7ff);
+ if(i>16) { /* 2nd iteration needed, good to 118 */
+ t = r;
+ w = fn*pio2_2;
+ r = t-w;
+ w = fn*pio2_2t-((t-r)-w);
+ y[0] = r-w;
+ GET_HIGH_WORD(high,y[0]);
+ i = j-((high>>20)&0x7ff);
+ if(i>49) { /* 3rd iteration need, 151 bits acc */
+ t = r; /* will cover all possible cases */
+ w = fn*pio2_3;
+ r = t-w;
+ w = fn*pio2_3t-((t-r)-w);
+ y[0] = r-w;
+ }
+ }
+ }
+ y[1] = (r-y[0])-w;
+ return n;
+ }
+ /*
+ * all other (large) arguments
+ */
+ if(ix>=0x7ff00000) { /* x is inf or NaN */
+ y[0]=y[1]=x-x; return 0;
+ }
+ /* set z = scalbn(|x|,ilogb(x)-23) */
+ GET_LOW_WORD(low,x);
+ e0 = (ix>>20)-1046; /* e0 = ilogb(z)-23; */
+ INSERT_WORDS(z, ix - ((int32_t)(e0<<20)), low);
+ for(i=0;i<2;i++) {
+ tx[i] = (double)((int32_t)(z));
+ z = (z-tx[i])*two24;
+ }
+ tx[2] = z;
+ nx = 3;
+ while(tx[nx-1]==zero) nx--; /* skip zero term */
+ n = __kernel_rem_pio2(tx,ty,e0,nx,1);
+ if(hx<0) {y[0] = -ty[0]; y[1] = -ty[1]; return -n;}
+ y[0] = ty[0]; y[1] = ty[1]; return n;
+}
--- /dev/null
+/* e_rem_pio2f.c -- float version of e_rem_pio2.c
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ * Debugged and optimized by Bruce D. Evans.
+ */
+
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/src/e_rem_pio2f.c,v 1.32 2009/06/03 08:16:34 ed Exp $");
+
+/* __ieee754_rem_pio2f(x,y)
+ *
+ * return the remainder of x rem pi/2 in *y
+ * use double precision for everything except passing x
+ * use __kernel_rem_pio2() for large x
+ */
+
+#include <float.h>
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+/*
+ * invpio2: 53 bits of 2/pi
+ * pio2_1: first 33 bit of pi/2
+ * pio2_1t: pi/2 - pio2_1
+ */
+
+static const double
+invpio2 = 6.36619772367581382433e-01, /* 0x3FE45F30, 0x6DC9C883 */
+pio2_1 = 1.57079631090164184570e+00, /* 0x3FF921FB, 0x50000000 */
+pio2_1t = 1.58932547735281966916e-08; /* 0x3E5110b4, 0x611A6263 */
+
+__inline int
+__ieee754_rem_pio2f(float x, double *y)
+{
+ double w,r,fn;
+ double tx[1],ty[1];
+ float z;
+ int32_t e0,n,ix,hx;
+
+ GET_FLOAT_WORD(hx,x);
+ ix = hx&0x7fffffff;
+ /* 33+53 bit pi is good enough for medium size */
+ if(ix<0x4dc90fdb) { /* |x| ~< 2^28*(pi/2), medium size */
+ /* Use a specialized rint() to get fn. Assume round-to-nearest. */
+ STRICT_ASSIGN(double,fn,x*invpio2+0x1.8p52);
+ fn = fn-0x1.8p52;
+#ifdef HAVE_EFFICIENT_IRINT
+ n = irint(fn);
+#else
+ n = (int32_t)fn;
+#endif
+ r = x-fn*pio2_1;
+ w = fn*pio2_1t;
+ *y = r-w;
+ return n;
+ }
+ /*
+ * all other (large) arguments
+ */
+ if(ix>=0x7f800000) { /* x is inf or NaN */
+ *y=x-x; return 0;
+ }
+ /* set z = scalbn(|x|,ilogb(|x|)-23) */
+ e0 = (ix>>23)-150; /* e0 = ilogb(|x|)-23; */
+ SET_FLOAT_WORD(z, ix - ((int32_t)(e0<<23)));
+ tx[0] = z;
+ n = __kernel_rem_pio2(tx,ty,e0,1,0);
+ if(hx<0) {*y = -ty[0]; return -n;}
+ *y = ty[0]; return n;
+}
--- /dev/null
+
+/* @(#)e_remainder.c 1.3 95/01/18 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunSoft, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/src/e_remainder.c,v 1.12 2008/03/30 20:47:42 das Exp $");
+
+/* __ieee754_remainder(x,p)
+ * Return :
+ * returns x REM p = x - [x/p]*p as if in infinite
+ * precise arithmetic, where [x/p] is the (infinite bit)
+ * integer nearest x/p (in half way case choose the even one).
+ * Method :
+ * Based on fmod() return x-[x/p]chopped*p exactlp.
+ */
+
+#include <float.h>
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+static const double zero = 0.0;
+
+
+OLM_DLLEXPORT double
+__ieee754_remainder(double x, double p)
+{
+ int32_t hx,hp;
+ u_int32_t sx,lx,lp;
+ double p_half;
+
+ EXTRACT_WORDS(hx,lx,x);
+ EXTRACT_WORDS(hp,lp,p);
+ sx = hx&0x80000000;
+ hp &= 0x7fffffff;
+ hx &= 0x7fffffff;
+
+ /* purge off exception values */
+ if((hp|lp)==0) return (x*p)/(x*p); /* p = 0 */
+ if((hx>=0x7ff00000)|| /* x not finite */
+ ((hp>=0x7ff00000)&& /* p is NaN */
+ (((hp-0x7ff00000)|lp)!=0)))
+ return ((long double)x*p)/((long double)x*p);
+
+
+ if (hp<=0x7fdfffff) x = __ieee754_fmod(x,p+p); /* now x < 2p */
+ if (((hx-hp)|(lx-lp))==0) return zero*x;
+ x = fabs(x);
+ p = fabs(p);
+ if (hp<0x00200000) {
+ if(x+x>p) {
+ x-=p;
+ if(x+x>=p) x -= p;
+ }
+ } else {
+ p_half = 0.5*p;
+ if(x>p_half) {
+ x-=p;
+ if(x>=p_half) x -= p;
+ }
+ }
+ GET_HIGH_WORD(hx,x);
+ if ((hx&0x7fffffff)==0) hx = 0;
+ SET_HIGH_WORD(x,hx^sx);
+ return x;
+}
+
+#if LDBL_MANT_DIG == 53
+__weak_reference(remainder, remainderl);
+#endif
--- /dev/null
+/* e_remainderf.c -- float version of e_remainder.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/src/e_remainderf.c,v 1.8 2008/02/12 17:11:36 bde Exp $");
+
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+static const float zero = 0.0;
+
+
+OLM_DLLEXPORT float
+__ieee754_remainderf(float x, float p)
+{
+ int32_t hx,hp;
+ u_int32_t sx;
+ float p_half;
+
+ GET_FLOAT_WORD(hx,x);
+ GET_FLOAT_WORD(hp,p);
+ sx = hx&0x80000000;
+ hp &= 0x7fffffff;
+ hx &= 0x7fffffff;
+
+ /* purge off exception values */
+ if(hp==0) return (x*p)/(x*p); /* p = 0 */
+ if((hx>=0x7f800000)|| /* x not finite */
+ ((hp>0x7f800000))) /* p is NaN */
+ return ((long double)x*p)/((long double)x*p);
+
+
+ if (hp<=0x7effffff) x = __ieee754_fmodf(x,p+p); /* now x < 2p */
+ if ((hx-hp)==0) return zero*x;
+ x = fabsf(x);
+ p = fabsf(p);
+ if (hp<0x01000000) {
+ if(x+x>p) {
+ x-=p;
+ if(x+x>=p) x -= p;
+ }
+ } else {
+ p_half = (float)0.5*p;
+ if(x>p_half) {
+ x-=p;
+ if(x>=p_half) x -= p;
+ }
+ }
+ GET_FLOAT_WORD(hx,x);
+ if ((hx&0x7fffffff)==0) hx = 0;
+ SET_FLOAT_WORD(x,hx^sx);
+ return x;
+}
--- /dev/null
+/*-
+ * Copyright (c) 2008 David Schultz <das@FreeBSD.ORG>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/src/e_remainderl.c,v 1.1 2008/03/30 20:47:42 das Exp $");
+
+#include <openlibm_math.h>
+#include "math_private.h"
+
+OLM_DLLEXPORT long double
+remainderl(long double x, long double y)
+{
+ int quo;
+
+ return (remquol(x, y, &quo));
+}
--- /dev/null
+
+/* @(#)e_sinh.c 1.3 95/01/18 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunSoft, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/src/e_sinh.c,v 1.11 2011/10/21 06:28:47 das Exp $");
+
+/* __ieee754_sinh(x)
+ * Method :
+ * mathematically sinh(x) if defined to be (exp(x)-exp(-x))/2
+ * 1. Replace x by |x| (sinh(-x) = -sinh(x)).
+ * 2.
+ * E + E/(E+1)
+ * 0 <= x <= 22 : sinh(x) := --------------, E=expm1(x)
+ * 2
+ *
+ * 22 <= x <= lnovft : sinh(x) := exp(x)/2
+ * lnovft <= x <= ln2ovft: sinh(x) := exp(x/2)/2 * exp(x/2)
+ * ln2ovft < x : sinh(x) := x*shuge (overflow)
+ *
+ * Special cases:
+ * sinh(x) is |x| if x is +INF, -INF, or NaN.
+ * only sinh(0)=0 is exact for finite x.
+ */
+
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+static const double one = 1.0, shuge = 1.0e307;
+
+OLM_DLLEXPORT double
+__ieee754_sinh(double x)
+{
+ double t,h;
+ int32_t ix,jx;
+
+ /* High word of |x|. */
+ GET_HIGH_WORD(jx,x);
+ ix = jx&0x7fffffff;
+
+ /* x is INF or NaN */
+ if(ix>=0x7ff00000) return x+x;
+
+ h = 0.5;
+ if (jx<0) h = -h;
+ /* |x| in [0,22], return sign(x)*0.5*(E+E/(E+1))) */
+ if (ix < 0x40360000) { /* |x|<22 */
+ if (ix<0x3e300000) /* |x|<2**-28 */
+ if(shuge+x>one) return x;/* sinh(tiny) = tiny with inexact */
+ t = expm1(fabs(x));
+ if(ix<0x3ff00000) return h*(2.0*t-t*t/(t+one));
+ return h*(t+t/(t+one));
+ }
+
+ /* |x| in [22, log(maxdouble)] return 0.5*exp(|x|) */
+ if (ix < 0x40862E42) return h*__ieee754_exp(fabs(x));
+
+ /* |x| in [log(maxdouble), overflowthresold] */
+ if (ix<=0x408633CE)
+ return h*2.0*__ldexp_exp(fabs(x), -1);
+
+ /* |x| > overflowthresold, sinh(x) overflow */
+ return x*shuge;
+}
--- /dev/null
+/* e_sinhf.c -- float version of e_sinh.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/src/e_sinhf.c,v 1.10 2011/10/21 06:28:47 das Exp $");
+
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+static const float one = 1.0, shuge = 1.0e37;
+
+OLM_DLLEXPORT float
+__ieee754_sinhf(float x)
+{
+ float t,h;
+ int32_t ix,jx;
+
+ GET_FLOAT_WORD(jx,x);
+ ix = jx&0x7fffffff;
+
+ /* x is INF or NaN */
+ if(ix>=0x7f800000) return x+x;
+
+ h = 0.5;
+ if (jx<0) h = -h;
+ /* |x| in [0,9], return sign(x)*0.5*(E+E/(E+1))) */
+ if (ix < 0x41100000) { /* |x|<9 */
+ if (ix<0x39800000) /* |x|<2**-12 */
+ if(shuge+x>one) return x;/* sinh(tiny) = tiny with inexact */
+ t = expm1f(fabsf(x));
+ if(ix<0x3f800000) return h*((float)2.0*t-t*t/(t+one));
+ return h*(t+t/(t+one));
+ }
+
+ /* |x| in [9, logf(maxfloat)] return 0.5*exp(|x|) */
+ if (ix < 0x42b17217) return h*__ieee754_expf(fabsf(x));
+
+ /* |x| in [logf(maxfloat), overflowthresold] */
+ if (ix<=0x42b2d4fc)
+ return h*2.0F*__ldexp_expf(fabsf(x), -1);
+
+ /* |x| > overflowthresold, sinh(x) overflow */
+ return x*shuge;
+}
--- /dev/null
+
+/* @(#)e_sqrt.c 1.3 95/01/18 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunSoft, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/src/e_sqrt.c,v 1.11 2008/03/02 01:47:58 das Exp $");
+
+/* __ieee754_sqrt(x)
+ * Return correctly rounded sqrt.
+ * ------------------------------------------
+ * | Use the hardware sqrt if you have one |
+ * ------------------------------------------
+ * Method:
+ * Bit by bit method using integer arithmetic. (Slow, but portable)
+ * 1. Normalization
+ * Scale x to y in [1,4) with even powers of 2:
+ * find an integer k such that 1 <= (y=x*2^(2k)) < 4, then
+ * sqrt(x) = 2^k * sqrt(y)
+ * 2. Bit by bit computation
+ * Let q = sqrt(y) truncated to i bit after binary point (q = 1),
+ * i 0
+ * i+1 2
+ * s = 2*q , and y = 2 * ( y - q ). (1)
+ * i i i i
+ *
+ * To compute q from q , one checks whether
+ * i+1 i
+ *
+ * -(i+1) 2
+ * (q + 2 ) <= y. (2)
+ * i
+ * -(i+1)
+ * If (2) is false, then q = q ; otherwise q = q + 2 .
+ * i+1 i i+1 i
+ *
+ * With some algebric manipulation, it is not difficult to see
+ * that (2) is equivalent to
+ * -(i+1)
+ * s + 2 <= y (3)
+ * i i
+ *
+ * The advantage of (3) is that s and y can be computed by
+ * i i
+ * the following recurrence formula:
+ * if (3) is false
+ *
+ * s = s , y = y ; (4)
+ * i+1 i i+1 i
+ *
+ * otherwise,
+ * -i -(i+1)
+ * s = s + 2 , y = y - s - 2 (5)
+ * i+1 i i+1 i i
+ *
+ * One may easily use induction to prove (4) and (5).
+ * Note. Since the left hand side of (3) contain only i+2 bits,
+ * it does not necessary to do a full (53-bit) comparison
+ * in (3).
+ * 3. Final rounding
+ * After generating the 53 bits result, we compute one more bit.
+ * Together with the remainder, we can decide whether the
+ * result is exact, bigger than 1/2ulp, or less than 1/2ulp
+ * (it will never equal to 1/2ulp).
+ * The rounding mode can be detected by checking whether
+ * huge + tiny is equal to huge, and whether huge - tiny is
+ * equal to huge for some floating point number "huge" and "tiny".
+ *
+ * Special cases:
+ * sqrt(+-0) = +-0 ... exact
+ * sqrt(inf) = inf
+ * sqrt(-ve) = NaN ... with invalid signal
+ * sqrt(NaN) = NaN ... with invalid signal for signaling NaN
+ *
+ * Other methods : see the appended file at the end of the program below.
+ *---------------
+ */
+
+#include <float.h>
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+static const double one = 1.0, tiny=1.0e-300;
+
+OLM_DLLEXPORT double
+__ieee754_sqrt(double x)
+{
+ double z;
+ int32_t sign = (int)0x80000000;
+ int32_t ix0,s0,q,m,t,i;
+ u_int32_t r,t1,s1,ix1,q1;
+
+ EXTRACT_WORDS(ix0,ix1,x);
+
+ /* take care of Inf and NaN */
+ if((ix0&0x7ff00000)==0x7ff00000) {
+ return x*x+x; /* sqrt(NaN)=NaN, sqrt(+inf)=+inf
+ sqrt(-inf)=sNaN */
+ }
+ /* take care of zero */
+ if(ix0<=0) {
+ if(((ix0&(~sign))|ix1)==0) return x;/* sqrt(+-0) = +-0 */
+ else if(ix0<0)
+ return (x-x)/(x-x); /* sqrt(-ve) = sNaN */
+ }
+ /* normalize x */
+ m = (ix0>>20);
+ if(m==0) { /* subnormal x */
+ while(ix0==0) {
+ m -= 21;
+ ix0 |= (ix1>>11); ix1 <<= 21;
+ }
+ for(i=0;(ix0&0x00100000)==0;i++) ix0<<=1;
+ m -= i-1;
+ ix0 |= (ix1>>(32-i));
+ ix1 <<= i;
+ }
+ m -= 1023; /* unbias exponent */
+ ix0 = (ix0&0x000fffff)|0x00100000;
+ if(m&1){ /* odd m, double x to make it even */
+ ix0 += ix0 + ((ix1&sign)>>31);
+ ix1 += ix1;
+ }
+ m >>= 1; /* m = [m/2] */
+
+ /* generate sqrt(x) bit by bit */
+ ix0 += ix0 + ((ix1&sign)>>31);
+ ix1 += ix1;
+ q = q1 = s0 = s1 = 0; /* [q,q1] = sqrt(x) */
+ r = 0x00200000; /* r = moving bit from right to left */
+
+ while(r!=0) {
+ t = s0+r;
+ if(t<=ix0) {
+ s0 = t+r;
+ ix0 -= t;
+ q += r;
+ }
+ ix0 += ix0 + ((ix1&sign)>>31);
+ ix1 += ix1;
+ r>>=1;
+ }
+
+ r = sign;
+ while(r!=0) {
+ t1 = s1+r;
+ t = s0;
+ if((t<ix0)||((t==ix0)&&(t1<=ix1))) {
+ s1 = t1+r;
+ if(((t1&sign)==sign)&&(s1&sign)==0) s0 += 1;
+ ix0 -= t;
+ if (ix1 < t1) ix0 -= 1;
+ ix1 -= t1;
+ q1 += r;
+ }
+ ix0 += ix0 + ((ix1&sign)>>31);
+ ix1 += ix1;
+ r>>=1;
+ }
+
+ /* use floating add to find out rounding direction */
+ if((ix0|ix1)!=0) {
+ z = one-tiny; /* trigger inexact flag */
+ if (z>=one) {
+ z = one+tiny;
+ if (q1==(u_int32_t)0xffffffff) { q1=0; q += 1;}
+ else if (z>one) {
+ if (q1==(u_int32_t)0xfffffffe) q+=1;
+ q1+=2;
+ } else
+ q1 += (q1&1);
+ }
+ }
+ ix0 = (q>>1)+0x3fe00000;
+ ix1 = q1>>1;
+ if ((q&1)==1) ix1 |= sign;
+ ix0 += (m <<20);
+ INSERT_WORDS(z,ix0,ix1);
+ return z;
+}
+
+#if (LDBL_MANT_DIG == 53)
+__weak_reference(sqrt, sqrtl);
+#endif
+
+/*
+Other methods (use floating-point arithmetic)
+-------------
+(This is a copy of a drafted paper by Prof W. Kahan
+and K.C. Ng, written in May, 1986)
+
+ Two algorithms are given here to implement sqrt(x)
+ (IEEE double precision arithmetic) in software.
+ Both supply sqrt(x) correctly rounded. The first algorithm (in
+ Section A) uses newton iterations and involves four divisions.
+ The second one uses reciproot iterations to avoid division, but
+ requires more multiplications. Both algorithms need the ability
+ to chop results of arithmetic operations instead of round them,
+ and the INEXACT flag to indicate when an arithmetic operation
+ is executed exactly with no roundoff error, all part of the
+ standard (IEEE 754-1985). The ability to perform shift, add,
+ subtract and logical AND operations upon 32-bit words is needed
+ too, though not part of the standard.
+
+A. sqrt(x) by Newton Iteration
+
+ (1) Initial approximation
+
+ Let x0 and x1 be the leading and the trailing 32-bit words of
+ a floating point number x (in IEEE double format) respectively
+
+ 1 11 52 ...widths
+ ------------------------------------------------------
+ x: |s| e | f |
+ ------------------------------------------------------
+ msb lsb msb lsb ...order
+
+
+ ------------------------ ------------------------
+ x0: |s| e | f1 | x1: | f2 |
+ ------------------------ ------------------------
+
+ By performing shifts and subtracts on x0 and x1 (both regarded
+ as integers), we obtain an 8-bit approximation of sqrt(x) as
+ follows.
+
+ k := (x0>>1) + 0x1ff80000;
+ y0 := k - T1[31&(k>>15)]. ... y ~ sqrt(x) to 8 bits
+ Here k is a 32-bit integer and T1[] is an integer array containing
+ correction terms. Now magically the floating value of y (y's
+ leading 32-bit word is y0, the value of its trailing word is 0)
+ approximates sqrt(x) to almost 8-bit.
+
+ Value of T1:
+ static int T1[32]= {
+ 0, 1024, 3062, 5746, 9193, 13348, 18162, 23592,
+ 29598, 36145, 43202, 50740, 58733, 67158, 75992, 85215,
+ 83599, 71378, 60428, 50647, 41945, 34246, 27478, 21581,
+ 16499, 12183, 8588, 5674, 3403, 1742, 661, 130,};
+
+ (2) Iterative refinement
+
+ Apply Heron's rule three times to y, we have y approximates
+ sqrt(x) to within 1 ulp (Unit in the Last Place):
+
+ y := (y+x/y)/2 ... almost 17 sig. bits
+ y := (y+x/y)/2 ... almost 35 sig. bits
+ y := y-(y-x/y)/2 ... within 1 ulp
+
+
+ Remark 1.
+ Another way to improve y to within 1 ulp is:
+
+ y := (y+x/y) ... almost 17 sig. bits to 2*sqrt(x)
+ y := y - 0x00100006 ... almost 18 sig. bits to sqrt(x)
+
+ 2
+ (x-y )*y
+ y := y + 2* ---------- ...within 1 ulp
+ 2
+ 3y + x
+
+
+ This formula has one division fewer than the one above; however,
+ it requires more multiplications and additions. Also x must be
+ scaled in advance to avoid spurious overflow in evaluating the
+ expression 3y*y+x. Hence it is not recommended uless division
+ is slow. If division is very slow, then one should use the
+ reciproot algorithm given in section B.
+
+ (3) Final adjustment
+
+ By twiddling y's last bit it is possible to force y to be
+ correctly rounded according to the prevailing rounding mode
+ as follows. Let r and i be copies of the rounding mode and
+ inexact flag before entering the square root program. Also we
+ use the expression y+-ulp for the next representable floating
+ numbers (up and down) of y. Note that y+-ulp = either fixed
+ point y+-1, or multiply y by nextafter(1,+-inf) in chopped
+ mode.
+
+ I := FALSE; ... reset INEXACT flag I
+ R := RZ; ... set rounding mode to round-toward-zero
+ z := x/y; ... chopped quotient, possibly inexact
+ If(not I) then { ... if the quotient is exact
+ if(z=y) {
+ I := i; ... restore inexact flag
+ R := r; ... restore rounded mode
+ return sqrt(x):=y.
+ } else {
+ z := z - ulp; ... special rounding
+ }
+ }
+ i := TRUE; ... sqrt(x) is inexact
+ If (r=RN) then z=z+ulp ... rounded-to-nearest
+ If (r=RP) then { ... round-toward-+inf
+ y = y+ulp; z=z+ulp;
+ }
+ y := y+z; ... chopped sum
+ y0:=y0-0x00100000; ... y := y/2 is correctly rounded.
+ I := i; ... restore inexact flag
+ R := r; ... restore rounded mode
+ return sqrt(x):=y.
+
+ (4) Special cases
+
+ Square root of +inf, +-0, or NaN is itself;
+ Square root of a negative number is NaN with invalid signal.
+
+
+B. sqrt(x) by Reciproot Iteration
+
+ (1) Initial approximation
+
+ Let x0 and x1 be the leading and the trailing 32-bit words of
+ a floating point number x (in IEEE double format) respectively
+ (see section A). By performing shifs and subtracts on x0 and y0,
+ we obtain a 7.8-bit approximation of 1/sqrt(x) as follows.
+
+ k := 0x5fe80000 - (x0>>1);
+ y0:= k - T2[63&(k>>14)]. ... y ~ 1/sqrt(x) to 7.8 bits
+
+ Here k is a 32-bit integer and T2[] is an integer array
+ containing correction terms. Now magically the floating
+ value of y (y's leading 32-bit word is y0, the value of
+ its trailing word y1 is set to zero) approximates 1/sqrt(x)
+ to almost 7.8-bit.
+
+ Value of T2:
+ static int T2[64]= {
+ 0x1500, 0x2ef8, 0x4d67, 0x6b02, 0x87be, 0xa395, 0xbe7a, 0xd866,
+ 0xf14a, 0x1091b,0x11fcd,0x13552,0x14999,0x15c98,0x16e34,0x17e5f,
+ 0x18d03,0x19a01,0x1a545,0x1ae8a,0x1b5c4,0x1bb01,0x1bfde,0x1c28d,
+ 0x1c2de,0x1c0db,0x1ba73,0x1b11c,0x1a4b5,0x1953d,0x18266,0x16be0,
+ 0x1683e,0x179d8,0x18a4d,0x19992,0x1a789,0x1b445,0x1bf61,0x1c989,
+ 0x1d16d,0x1d77b,0x1dddf,0x1e2ad,0x1e5bf,0x1e6e8,0x1e654,0x1e3cd,
+ 0x1df2a,0x1d635,0x1cb16,0x1be2c,0x1ae4e,0x19bde,0x1868e,0x16e2e,
+ 0x1527f,0x1334a,0x11051,0xe951, 0xbe01, 0x8e0d, 0x5924, 0x1edd,};
+
+ (2) Iterative refinement
+
+ Apply Reciproot iteration three times to y and multiply the
+ result by x to get an approximation z that matches sqrt(x)
+ to about 1 ulp. To be exact, we will have
+ -1ulp < sqrt(x)-z<1.0625ulp.
+
+ ... set rounding mode to Round-to-nearest
+ y := y*(1.5-0.5*x*y*y) ... almost 15 sig. bits to 1/sqrt(x)
+ y := y*((1.5-2^-30)+0.5*x*y*y)... about 29 sig. bits to 1/sqrt(x)
+ ... special arrangement for better accuracy
+ z := x*y ... 29 bits to sqrt(x), with z*y<1
+ z := z + 0.5*z*(1-z*y) ... about 1 ulp to sqrt(x)
+
+ Remark 2. The constant 1.5-2^-30 is chosen to bias the error so that
+ (a) the term z*y in the final iteration is always less than 1;
+ (b) the error in the final result is biased upward so that
+ -1 ulp < sqrt(x) - z < 1.0625 ulp
+ instead of |sqrt(x)-z|<1.03125ulp.
+
+ (3) Final adjustment
+
+ By twiddling y's last bit it is possible to force y to be
+ correctly rounded according to the prevailing rounding mode
+ as follows. Let r and i be copies of the rounding mode and
+ inexact flag before entering the square root program. Also we
+ use the expression y+-ulp for the next representable floating
+ numbers (up and down) of y. Note that y+-ulp = either fixed
+ point y+-1, or multiply y by nextafter(1,+-inf) in chopped
+ mode.
+
+ R := RZ; ... set rounding mode to round-toward-zero
+ switch(r) {
+ case RN: ... round-to-nearest
+ if(x<= z*(z-ulp)...chopped) z = z - ulp; else
+ if(x<= z*(z+ulp)...chopped) z = z; else z = z+ulp;
+ break;
+ case RZ:case RM: ... round-to-zero or round-to--inf
+ R:=RP; ... reset rounding mod to round-to-+inf
+ if(x<z*z ... rounded up) z = z - ulp; else
+ if(x>=(z+ulp)*(z+ulp) ...rounded up) z = z+ulp;
+ break;
+ case RP: ... round-to-+inf
+ if(x>(z+ulp)*(z+ulp)...chopped) z = z+2*ulp; else
+ if(x>z*z ...chopped) z = z+ulp;
+ break;
+ }
+
+ Remark 3. The above comparisons can be done in fixed point. For
+ example, to compare x and w=z*z chopped, it suffices to compare
+ x1 and w1 (the trailing parts of x and w), regarding them as
+ two's complement integers.
+
+ ...Is z an exact square root?
+ To determine whether z is an exact square root of x, let z1 be the
+ trailing part of z, and also let x0 and x1 be the leading and
+ trailing parts of x.
+
+ If ((z1&0x03ffffff)!=0) ... not exact if trailing 26 bits of z!=0
+ I := 1; ... Raise Inexact flag: z is not exact
+ else {
+ j := 1 - [(x0>>20)&1] ... j = logb(x) mod 2
+ k := z1 >> 26; ... get z's 25-th and 26-th
+ fraction bits
+ I := i or (k&j) or ((k&(j+j+1))!=(x1&3));
+ }
+ R:= r ... restore rounded mode
+ return sqrt(x):=z.
+
+ If multiplication is cheaper then the foregoing red tape, the
+ Inexact flag can be evaluated by
+
+ I := i;
+ I := (z*z!=x) or I.
+
+ Note that z*z can overwrite I; this value must be sensed if it is
+ True.
+
+ Remark 4. If z*z = x exactly, then bit 25 to bit 0 of z1 must be
+ zero.
+
+ --------------------
+ z1: | f2 |
+ --------------------
+ bit 31 bit 0
+
+ Further more, bit 27 and 26 of z1, bit 0 and 1 of x1, and the odd
+ or even of logb(x) have the following relations:
+
+ -------------------------------------------------
+ bit 27,26 of z1 bit 1,0 of x1 logb(x)
+ -------------------------------------------------
+ 00 00 odd and even
+ 01 01 even
+ 10 10 odd
+ 10 00 even
+ 11 01 even
+ -------------------------------------------------
+
+ (4) Special cases (see (4) of Section A).
+
+ */
+
--- /dev/null
+/* e_sqrtf.c -- float version of e_sqrt.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+static const float one = 1.0, tiny=1.0e-30;
+
+OLM_DLLEXPORT float
+__ieee754_sqrtf(float x)
+{
+ float z;
+ int32_t sign = (int)0x80000000;
+ int32_t ix,s,q,m,t,i;
+ u_int32_t r;
+
+ GET_FLOAT_WORD(ix,x);
+
+ /* take care of Inf and NaN */
+ if((ix&0x7f800000)==0x7f800000) {
+ return x*x+x; /* sqrt(NaN)=NaN, sqrt(+inf)=+inf
+ sqrt(-inf)=sNaN */
+ }
+ /* take care of zero */
+ if(ix<=0) {
+ if((ix&(~sign))==0) return x;/* sqrt(+-0) = +-0 */
+ else if(ix<0)
+ return (x-x)/(x-x); /* sqrt(-ve) = sNaN */
+ }
+ /* normalize x */
+ m = (ix>>23);
+ if(m==0) { /* subnormal x */
+ for(i=0;(ix&0x00800000)==0;i++) ix<<=1;
+ m -= i-1;
+ }
+ m -= 127; /* unbias exponent */
+ ix = (ix&0x007fffff)|0x00800000;
+ if(m&1) /* odd m, double x to make it even */
+ ix += ix;
+ m >>= 1; /* m = [m/2] */
+
+ /* generate sqrt(x) bit by bit */
+ ix += ix;
+ q = s = 0; /* q = sqrt(x) */
+ r = 0x01000000; /* r = moving bit from right to left */
+
+ while(r!=0) {
+ t = s+r;
+ if(t<=ix) {
+ s = t+r;
+ ix -= t;
+ q += r;
+ }
+ ix += ix;
+ r>>=1;
+ }
+
+ /* use floating add to find out rounding direction */
+ if(ix!=0) {
+ z = one-tiny; /* trigger inexact flag */
+ if (z>=one) {
+ z = one+tiny;
+ if (z>one)
+ q += 2;
+ else
+ q += (q&1);
+ }
+ }
+ ix = (q>>1)+0x3f000000;
+ ix += (m <<23);
+ SET_FLOAT_WORD(z,ix);
+ return z;
+}
--- /dev/null
+/*-
+ * Copyright (c) 2007 Steven G. Kargl
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice unmodified, this list of conditions, and the following
+ * disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/src/e_sqrtl.c,v 1.1 2008/03/02 01:47:58 das Exp $");
+
+#include <float.h>
+#include <openlibm_fenv.h>
+#include <openlibm_math.h>
+
+#include "fpmath.h"
+#include "math_private.h"
+
+/* Return (x + ulp) for normal positive x. Assumes no overflow. */
+static inline long double
+inc(long double x)
+{
+ union IEEEl2bits u;
+
+ u.e = x;
+ if (++u.bits.manl == 0) {
+ if (++u.bits.manh == 0) {
+ u.bits.exp++;
+ u.bits.manh |= LDBL_NBIT;
+ }
+ }
+ return (u.e);
+}
+
+/* Return (x - ulp) for normal positive x. Assumes no underflow. */
+static inline long double
+dec(long double x)
+{
+ union IEEEl2bits u;
+
+ u.e = x;
+ if (u.bits.manl-- == 0) {
+ if (u.bits.manh-- == LDBL_NBIT) {
+ u.bits.exp--;
+ u.bits.manh |= LDBL_NBIT;
+ }
+ }
+ return (u.e);
+}
+
+#ifndef __GNUC__
+#pragma STDC FENV_ACCESS ON
+#endif
+
+/*
+ * This is slow, but simple and portable. You should use hardware sqrt
+ * if possible.
+ */
+
+OLM_DLLEXPORT long double
+sqrtl(long double x)
+{
+ union IEEEl2bits u;
+ int k, r;
+ long double lo, xn;
+ fenv_t env;
+
+ u.e = x;
+
+ /* If x = NaN, then sqrt(x) = NaN. */
+ /* If x = Inf, then sqrt(x) = Inf. */
+ /* If x = -Inf, then sqrt(x) = NaN. */
+ if (u.bits.exp == LDBL_MAX_EXP * 2 - 1)
+ return (x * x + x);
+
+ /* If x = +-0, then sqrt(x) = +-0. */
+ if ((u.bits.manh | u.bits.manl | u.bits.exp) == 0)
+ return (x);
+
+ /* If x < 0, then raise invalid and return NaN */
+ if (u.bits.sign)
+ return ((x - x) / (x - x));
+
+ feholdexcept(&env);
+
+ if (u.bits.exp == 0) {
+ /* Adjust subnormal numbers. */
+ u.e *= 0x1.0p514;
+ k = -514;
+ } else {
+ k = 0;
+ }
+ /*
+ * u.e is a normal number, so break it into u.e = e*2^n where
+ * u.e = (2*e)*2^2k for odd n and u.e = (4*e)*2^2k for even n.
+ */
+ if ((u.bits.exp - 0x3ffe) & 1) { /* n is odd. */
+ k += u.bits.exp - 0x3fff; /* 2k = n - 1. */
+ u.bits.exp = 0x3fff; /* u.e in [1,2). */
+ } else {
+ k += u.bits.exp - 0x4000; /* 2k = n - 2. */
+ u.bits.exp = 0x4000; /* u.e in [2,4). */
+ }
+
+ /*
+ * Newton's iteration.
+ * Split u.e into a high and low part to achieve additional precision.
+ */
+ xn = sqrt(u.e); /* 53-bit estimate of sqrtl(x). */
+#if LDBL_MANT_DIG > 100
+ xn = (xn + (u.e / xn)) * 0.5; /* 106-bit estimate. */
+#endif
+ lo = u.e;
+ u.bits.manl = 0; /* Zero out lower bits. */
+ lo = (lo - u.e) / xn; /* Low bits divided by xn. */
+ xn = xn + (u.e / xn); /* High portion of estimate. */
+ u.e = xn + lo; /* Combine everything. */
+ u.bits.exp += (k >> 1) - 1;
+
+ feclearexcept(FE_INEXACT);
+ r = fegetround();
+ fesetround(FE_TOWARDZERO); /* Set to round-toward-zero. */
+ xn = x / u.e; /* Chopped quotient (inexact?). */
+
+ if (!fetestexcept(FE_INEXACT)) { /* Quotient is exact. */
+ if (xn == u.e) {
+ fesetenv(&env);
+ return (u.e);
+ }
+ /* Round correctly for inputs like x = y**2 - ulp. */
+ xn = dec(xn); /* xn = xn - ulp. */
+ }
+
+ if (r == FE_TONEAREST) {
+ xn = inc(xn); /* xn = xn + ulp. */
+ } else if (r == FE_UPWARD) {
+ u.e = inc(u.e); /* u.e = u.e + ulp. */
+ xn = inc(xn); /* xn = xn + ulp. */
+ }
+ u.e = u.e + xn; /* Chopped sum. */
+ feupdateenv(&env); /* Restore env and raise inexact */
+ u.bits.exp--;
+ return (u.e);
+}
--- /dev/null
+/*-
+ * Copyright (c) 2003 Mike Barcroft <mike@FreeBSD.org>
+ * Copyright (c) 2002 David Schultz <das@FreeBSD.ORG>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: src/lib/libc/include/fpmath.h,v 1.4 2008/12/23 22:20:59 marcel Exp $
+ */
+#ifndef _FPMATH_H_
+#define _FPMATH_H_
+
+#if defined(__aarch64__)
+#include "aarch64_fpmath.h"
+#elif defined(__i386__) || defined(__x86_64__)
+#ifdef __LP64__
+#include "amd64_fpmath.h"
+#else
+#include "i386_fpmath.h"
+#endif
+#elif defined(__powerpc__)
+#include "powerpc_fpmath.h"
+#elif defined(__mips__)
+#include "mips_fpmath.h"
+#endif
+
+/* Definitions provided directly by GCC and Clang. */
+#if !(defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) && defined(__ORDER_BIG_ENDIAN__))
+
+#if defined(__GLIBC__)
+
+#include <features.h>
+#include <endian.h>
+#define __ORDER_LITTLE_ENDIAN__ __LITTLE_ENDIAN
+#define __ORDER_BIG_ENDIAN__ __BIG_ENDIAN
+#define __BYTE_ORDER__ __BYTE_ORDER
+
+#elif defined(__APPLE__)
+
+#include <machine/endian.h>
+#define __ORDER_LITTLE_ENDIAN__ LITTLE_ENDIAN
+#define __ORDER_BIG_ENDIAN__ BIG_ENDIAN
+#define __BYTE_ORDER__ BYTE_ORDER
+
+#elif defined(_WIN32)
+
+#define __ORDER_LITTLE_ENDIAN__ 1234
+#define __ORDER_BIG_ENDIAN__ 4321
+#define __BYTE_ORDER__ __ORDER_LITTLE_ENDIAN__
+
+#endif
+
+#endif /* __BYTE_ORDER__, __ORDER_LITTLE_ENDIAN__ and __ORDER_BIG_ENDIAN__ */
+
+#ifndef __FLOAT_WORD_ORDER__
+#define __FLOAT_WORD_ORDER__ __BYTE_ORDER__
+#endif
+
+union IEEEf2bits {
+ float f;
+ struct {
+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+ unsigned int man :23;
+ unsigned int exp :8;
+ unsigned int sign :1;
+#else /* _BIG_ENDIAN */
+ unsigned int sign :1;
+ unsigned int exp :8;
+ unsigned int man :23;
+#endif
+ } bits;
+};
+
+#define DBL_MANH_SIZE 20
+#define DBL_MANL_SIZE 32
+
+union IEEEd2bits {
+ double d;
+ struct {
+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+#if __FLOAT_WORD_ORDER__ == __ORDER_LITTLE_ENDIAN__
+ unsigned int manl :32;
+#endif
+ unsigned int manh :20;
+ unsigned int exp :11;
+ unsigned int sign :1;
+#if __FLOAT_WORD_ORDER__ == __ORDER_BIG_ENDIAN__
+ unsigned int manl :32;
+#endif
+#else /* _BIG_ENDIAN */
+ unsigned int sign :1;
+ unsigned int exp :11;
+ unsigned int manh :20;
+ unsigned int manl :32;
+#endif
+ } bits;
+};
+
+#endif
--- /dev/null
+/*-
+ * Copyright (c) 2002, 2003 David Schultz <das@FreeBSD.ORG>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: src/lib/libc/i386/_fpmath.h,v 1.6 2008/01/17 16:39:06 bde Exp $
+ */
+
+union IEEEl2bits {
+ long double e;
+ struct {
+ unsigned int manl :32;
+ unsigned int manh :32;
+ unsigned int exp :15;
+ unsigned int sign :1;
+ unsigned int junk :16;
+ } bits;
+ struct {
+ unsigned long long man :64;
+ unsigned int expsign :16;
+ unsigned int junk :16;
+ } xbits;
+};
+
+#define LDBL_NBIT 0x80000000
+#define mask_nbit_l(u) ((u).bits.manh &= ~LDBL_NBIT)
+
+#define LDBL_MANH_SIZE 32
+#define LDBL_MANL_SIZE 32
+
+#define LDBL_TO_ARRAY32(u, a) do { \
+ (a)[0] = (uint32_t)(u).bits.manl; \
+ (a)[1] = (uint32_t)(u).bits.manh; \
+} while (0)
--- /dev/null
+
+/* @(#)k_cos.c 1.3 95/01/18 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunSoft, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/src/k_cos.c,v 1.12 2008/02/19 12:54:14 bde Exp $");
+
+/*
+ * __kernel_cos( x, y )
+ * kernel cos function on [-pi/4, pi/4], pi/4 ~ 0.785398164
+ * Input x is assumed to be bounded by ~pi/4 in magnitude.
+ * Input y is the tail of x.
+ *
+ * Algorithm
+ * 1. Since cos(-x) = cos(x), we need only to consider positive x.
+ * 2. if x < 2^-27 (hx<0x3e400000 0), return 1 with inexact if x!=0.
+ * 3. cos(x) is approximated by a polynomial of degree 14 on
+ * [0,pi/4]
+ * 4 14
+ * cos(x) ~ 1 - x*x/2 + C1*x + ... + C6*x
+ * where the remez error is
+ *
+ * | 2 4 6 8 10 12 14 | -58
+ * |cos(x)-(1-.5*x +C1*x +C2*x +C3*x +C4*x +C5*x +C6*x )| <= 2
+ * | |
+ *
+ * 4 6 8 10 12 14
+ * 4. let r = C1*x +C2*x +C3*x +C4*x +C5*x +C6*x , then
+ * cos(x) ~ 1 - x*x/2 + r
+ * since cos(x+y) ~ cos(x) - sin(x)*y
+ * ~ cos(x) - x*y,
+ * a correction term is necessary in cos(x) and hence
+ * cos(x+y) = 1 - (x*x/2 - (r - x*y))
+ * For better accuracy, rearrange to
+ * cos(x+y) ~ w + (tmp + (r-x*y))
+ * where w = 1 - x*x/2 and tmp is a tiny correction term
+ * (1 - x*x/2 == w + tmp exactly in infinite precision).
+ * The exactness of w + tmp in infinite precision depends on w
+ * and tmp having the same precision as x. If they have extra
+ * precision due to compiler bugs, then the extra precision is
+ * only good provided it is retained in all terms of the final
+ * expression for cos(). Retention happens in all cases tested
+ * under FreeBSD, so don't pessimize things by forcibly clipping
+ * any extra precision in w.
+ */
+
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+static const double
+one = 1.00000000000000000000e+00, /* 0x3FF00000, 0x00000000 */
+C1 = 4.16666666666666019037e-02, /* 0x3FA55555, 0x5555554C */
+C2 = -1.38888888888741095749e-03, /* 0xBF56C16C, 0x16C15177 */
+C3 = 2.48015872894767294178e-05, /* 0x3EFA01A0, 0x19CB1590 */
+C4 = -2.75573143513906633035e-07, /* 0xBE927E4F, 0x809C52AD */
+C5 = 2.08757232129817482790e-09, /* 0x3E21EE9E, 0xBDB4B1C4 */
+C6 = -1.13596475577881948265e-11; /* 0xBDA8FAE9, 0xBE8838D4 */
+
+OLM_DLLEXPORT double
+__kernel_cos(double x, double y)
+{
+ double hz,z,r,w;
+
+ z = x*x;
+ w = z*z;
+ r = z*(C1+z*(C2+z*C3)) + w*w*(C4+z*(C5+z*C6));
+ hz = 0.5*z;
+ w = one-hz;
+ return w + (((one-w)-hz) + (z*r-x*y));
+}
--- /dev/null
+/* k_cosf.c -- float version of k_cos.c
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ * Debugged and optimized by Bruce D. Evans.
+ */
+
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#ifndef INLINE_KERNEL_COSDF
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/src/k_cosf.c,v 1.18 2009/06/03 08:16:34 ed Exp $");
+#endif
+
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+/* |cos(x) - c(x)| < 2**-34.1 (~[-5.37e-11, 5.295e-11]). */
+static const double
+one = 1.0,
+C0 = -0x1ffffffd0c5e81.0p-54, /* -0.499999997251031003120 */
+C1 = 0x155553e1053a42.0p-57, /* 0.0416666233237390631894 */
+C2 = -0x16c087e80f1e27.0p-62, /* -0.00138867637746099294692 */
+C3 = 0x199342e0ee5069.0p-68; /* 0.0000243904487962774090654 */
+
+#ifndef INLINE_KERNEL_COSDF
+extern
+#endif
+//__inline float
+OLM_DLLEXPORT float
+__kernel_cosdf(double x)
+{
+ double r, w, z;
+
+ /* Try to optimize for parallel evaluation as in k_tanf.c. */
+ z = x*x;
+ w = z*z;
+ r = C2+z*C3;
+ return ((one+z*C0) + w*C1) + (w*z)*r;
+}
--- /dev/null
+/*-
+ * Copyright (c) 2011 David Schultz <das@FreeBSD.ORG>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/src/k_exp.c,v 1.1 2011/10/21 06:27:56 das Exp $");
+
+#include <openlibm_complex.h>
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+static const u_int32_t k = 1799; /* constant for reduction */
+static const double kln2 = 1246.97177782734161156; /* k * ln2 */
+
+/*
+ * Compute exp(x), scaled to avoid spurious overflow. An exponent is
+ * returned separately in 'expt'.
+ *
+ * Input: ln(DBL_MAX) <= x < ln(2 * DBL_MAX / DBL_MIN_DENORM) ~= 1454.91
+ * Output: 2**1023 <= y < 2**1024
+ */
+static double
+__frexp_exp(double x, int *expt)
+{
+ double exp_x;
+ u_int32_t hx;
+
+ /*
+ * We use exp(x) = exp(x - kln2) * 2**k, carefully chosen to
+ * minimize |exp(kln2) - 2**k|. We also scale the exponent of
+ * exp_x to MAX_EXP so that the result can be multiplied by
+ * a tiny number without losing accuracy due to denormalization.
+ */
+ exp_x = exp(x - kln2);
+ GET_HIGH_WORD(hx, exp_x);
+ *expt = (hx >> 20) - (0x3ff + 1023) + k;
+ SET_HIGH_WORD(exp_x, (hx & 0xfffff) | ((0x3ff + 1023) << 20));
+ return (exp_x);
+}
+
+/*
+ * __ldexp_exp(x, expt) and __ldexp_cexp(x, expt) compute exp(x) * 2**expt.
+ * They are intended for large arguments (real part >= ln(DBL_MAX))
+ * where care is needed to avoid overflow.
+ *
+ * The present implementation is narrowly tailored for our hyperbolic and
+ * exponential functions. We assume expt is small (0 or -1), and the caller
+ * has filtered out very large x, for which overflow would be inevitable.
+ */
+
+OLM_DLLEXPORT double
+__ldexp_exp(double x, int expt)
+{
+ double exp_x, scale;
+ int ex_expt;
+
+ exp_x = __frexp_exp(x, &ex_expt);
+ expt += ex_expt;
+ INSERT_WORDS(scale, (0x3ff + expt) << 20, 0);
+ return (exp_x * scale);
+}
+
+OLM_DLLEXPORT double complex
+__ldexp_cexp(double complex z, int expt)
+{
+ double x, y, exp_x, scale1, scale2;
+ int ex_expt, half_expt;
+
+ x = creal(z);
+ y = cimag(z);
+ exp_x = __frexp_exp(x, &ex_expt);
+ expt += ex_expt;
+
+ /*
+ * Arrange so that scale1 * scale2 == 2**expt. We use this to
+ * compensate for scalbn being horrendously slow.
+ */
+ half_expt = expt / 2;
+ INSERT_WORDS(scale1, (0x3ff + half_expt) << 20, 0);
+ half_expt = expt - half_expt;
+ INSERT_WORDS(scale2, (0x3ff + half_expt) << 20, 0);
+
+ return (CMPLX(cos(y) * exp_x * scale1 * scale2,
+ sin(y) * exp_x * scale1 * scale2));
+}
--- /dev/null
+/*-
+ * Copyright (c) 2011 David Schultz <das@FreeBSD.ORG>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/src/k_expf.c,v 1.1 2011/10/21 06:27:56 das Exp $");
+
+#include <openlibm_complex.h>
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+static const u_int32_t k = 235; /* constant for reduction */
+static const float kln2 = 162.88958740F; /* k * ln2 */
+
+/*
+ * See k_exp.c for details.
+ *
+ * Input: ln(FLT_MAX) <= x < ln(2 * FLT_MAX / FLT_MIN_DENORM) ~= 192.7
+ * Output: 2**127 <= y < 2**128
+ */
+static float
+__frexp_expf(float x, int *expt)
+{
+ double exp_x;
+ u_int32_t hx;
+
+ exp_x = expf(x - kln2);
+ GET_FLOAT_WORD(hx, exp_x);
+ *expt = (hx >> 23) - (0x7f + 127) + k;
+ SET_FLOAT_WORD(exp_x, (hx & 0x7fffff) | ((0x7f + 127) << 23));
+ return (exp_x);
+}
+
+OLM_DLLEXPORT float
+__ldexp_expf(float x, int expt)
+{
+ float exp_x, scale;
+ int ex_expt;
+
+ exp_x = __frexp_expf(x, &ex_expt);
+ expt += ex_expt;
+ SET_FLOAT_WORD(scale, (0x7f + expt) << 23);
+ return (exp_x * scale);
+}
+
+OLM_DLLEXPORT float complex
+__ldexp_cexpf(float complex z, int expt)
+{
+ float x, y, exp_x, scale1, scale2;
+ int ex_expt, half_expt;
+
+ x = crealf(z);
+ y = cimagf(z);
+ exp_x = __frexp_expf(x, &ex_expt);
+ expt += ex_expt;
+
+ half_expt = expt / 2;
+ SET_FLOAT_WORD(scale1, (0x7f + half_expt) << 23);
+ half_expt = expt - half_expt;
+ SET_FLOAT_WORD(scale2, (0x7f + half_expt) << 23);
+
+ return (CMPLXF(cosf(y) * exp_x * scale1 * scale2,
+ sinf(y) * exp_x * scale1 * scale2));
+}
--- /dev/null
+
+/* @(#)e_log.c 1.3 95/01/18 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunSoft, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/src/k_log.h,v 1.2 2011/10/15 05:23:28 das Exp $");
+
+/*
+ * k_log1p(f):
+ * Return log(1+f) - f for 1+f in ~[sqrt(2)/2, sqrt(2)].
+ *
+ * The following describes the overall strategy for computing
+ * logarithms in base e. The argument reduction and adding the final
+ * term of the polynomial are done by the caller for increased accuracy
+ * when different bases are used.
+ *
+ * Method :
+ * 1. Argument Reduction: find k and f such that
+ * x = 2^k * (1+f),
+ * where sqrt(2)/2 < 1+f < sqrt(2) .
+ *
+ * 2. Approximation of log(1+f).
+ * Let s = f/(2+f) ; based on log(1+f) = log(1+s) - log(1-s)
+ * = 2s + 2/3 s**3 + 2/5 s**5 + .....,
+ * = 2s + s*R
+ * We use a special Reme algorithm on [0,0.1716] to generate
+ * a polynomial of degree 14 to approximate R The maximum error
+ * of this polynomial approximation is bounded by 2**-58.45. In
+ * other words,
+ * 2 4 6 8 10 12 14
+ * R(z) ~ Lg1*s +Lg2*s +Lg3*s +Lg4*s +Lg5*s +Lg6*s +Lg7*s
+ * (the values of Lg1 to Lg7 are listed in the program)
+ * and
+ * | 2 14 | -58.45
+ * | Lg1*s +...+Lg7*s - R(z) | <= 2
+ * | |
+ * Note that 2s = f - s*f = f - hfsq + s*hfsq, where hfsq = f*f/2.
+ * In order to guarantee error in log below 1ulp, we compute log
+ * by
+ * log(1+f) = f - s*(f - R) (if f is not too large)
+ * log(1+f) = f - (hfsq - s*(hfsq+R)). (better accuracy)
+ *
+ * 3. Finally, log(x) = k*ln2 + log(1+f).
+ * = k*ln2_hi+(f-(hfsq-(s*(hfsq+R)+k*ln2_lo)))
+ * Here ln2 is split into two floating point number:
+ * ln2_hi + ln2_lo,
+ * where n*ln2_hi is always exact for |n| < 2000.
+ *
+ * Special cases:
+ * log(x) is NaN with signal if x < 0 (including -INF) ;
+ * log(+INF) is +INF; log(0) is -INF with signal;
+ * log(NaN) is that NaN with no signal.
+ *
+ * Accuracy:
+ * according to an error analysis, the error is always less than
+ * 1 ulp (unit in the last place).
+ *
+ * Constants:
+ * The hexadecimal values are the intended ones for the following
+ * constants. The decimal values may be used, provided that the
+ * compiler will convert from decimal to binary accurately enough
+ * to produce the hexadecimal values shown.
+ */
+
+static const double
+Lg1 = 6.666666666666735130e-01, /* 3FE55555 55555593 */
+Lg2 = 3.999999999940941908e-01, /* 3FD99999 9997FA04 */
+Lg3 = 2.857142874366239149e-01, /* 3FD24924 94229359 */
+Lg4 = 2.222219843214978396e-01, /* 3FCC71C5 1D8E78AF */
+Lg5 = 1.818357216161805012e-01, /* 3FC74664 96CB03DE */
+Lg6 = 1.531383769920937332e-01, /* 3FC39A09 D078C69F */
+Lg7 = 1.479819860511658591e-01; /* 3FC2F112 DF3E5244 */
+
+/*
+ * We always inline k_log1p(), since doing so produces a
+ * substantial performance improvement (~40% on amd64).
+ */
+static inline double
+k_log1p(double f)
+{
+ double hfsq,s,z,R,w,t1,t2;
+
+ s = f/(2.0+f);
+ z = s*s;
+ w = z*z;
+ t1= w*(Lg2+w*(Lg4+w*Lg6));
+ t2= z*(Lg1+w*(Lg3+w*(Lg5+w*Lg7)));
+ R = t2+t1;
+ hfsq=0.5*f*f;
+ return s*(hfsq+R);
+}
--- /dev/null
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/src/k_logf.h,v 1.3 2011/10/15 05:23:28 das Exp $");
+
+/*
+ * Float version of k_log.h. See the latter for most comments.
+ */
+
+static const float
+/* |(log(1+s)-log(1-s))/s - Lg(s)| < 2**-34.24 (~[-4.95e-11, 4.97e-11]). */
+Lg1 = 0xaaaaaa.0p-24, /* 0.66666662693 */
+Lg2 = 0xccce13.0p-25, /* 0.40000972152 */
+Lg3 = 0x91e9ee.0p-25, /* 0.28498786688 */
+Lg4 = 0xf89e26.0p-26; /* 0.24279078841 */
+
+static inline float
+k_log1pf(float f)
+{
+ float hfsq,s,z,R,w,t1,t2;
+
+ s = f/((float)2.0+f);
+ z = s*s;
+ w = z*z;
+ t1= w*(Lg2+w*Lg4);
+ t2= z*(Lg1+w*Lg3);
+ R = t2+t1;
+ hfsq=(float)0.5*f*f;
+ return s*(hfsq+R);
+}
--- /dev/null
+
+/* @(#)k_rem_pio2.c 1.3 95/01/18 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunSoft, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/src/k_rem_pio2.c,v 1.11 2008/02/25 11:43:20 bde Exp $");
+
+/*
+ * __kernel_rem_pio2(x,y,e0,nx,prec)
+ * double x[],y[]; int e0,nx,prec;
+ *
+ * __kernel_rem_pio2 return the last three digits of N with
+ * y = x - N*pi/2
+ * so that |y| < pi/2.
+ *
+ * The method is to compute the integer (mod 8) and fraction parts of
+ * (2/pi)*x without doing the full multiplication. In general we
+ * skip the part of the product that are known to be a huge integer (
+ * more accurately, = 0 mod 8 ). Thus the number of operations are
+ * independent of the exponent of the input.
+ *
+ * (2/pi) is represented by an array of 24-bit integers in ipio2[].
+ *
+ * Input parameters:
+ * x[] The input value (must be positive) is broken into nx
+ * pieces of 24-bit integers in double precision format.
+ * x[i] will be the i-th 24 bit of x. The scaled exponent
+ * of x[0] is given in input parameter e0 (i.e., x[0]*2^e0
+ * match x's up to 24 bits.
+ *
+ * Example of breaking a double positive z into x[0]+x[1]+x[2]:
+ * e0 = ilogb(z)-23
+ * z = scalbn(z,-e0)
+ * for i = 0,1,2
+ * x[i] = floor(z)
+ * z = (z-x[i])*2**24
+ *
+ *
+ * y[] ouput result in an array of double precision numbers.
+ * The dimension of y[] is:
+ * 24-bit precision 1
+ * 53-bit precision 2
+ * 64-bit precision 2
+ * 113-bit precision 3
+ * The actual value is the sum of them. Thus for 113-bit
+ * precison, one may have to do something like:
+ *
+ * long double t,w,r_head, r_tail;
+ * t = (long double)y[2] + (long double)y[1];
+ * w = (long double)y[0];
+ * r_head = t+w;
+ * r_tail = w - (r_head - t);
+ *
+ * e0 The exponent of x[0]. Must be <= 16360 or you need to
+ * expand the ipio2 table.
+ *
+ * nx dimension of x[]
+ *
+ * prec an integer indicating the precision:
+ * 0 24 bits (single)
+ * 1 53 bits (double)
+ * 2 64 bits (extended)
+ * 3 113 bits (quad)
+ *
+ * External function:
+ * double scalbn(), floor();
+ *
+ *
+ * Here is the description of some local variables:
+ *
+ * jk jk+1 is the initial number of terms of ipio2[] needed
+ * in the computation. The minimum and recommended value
+ * for jk is 3,4,4,6 for single, double, extended, and quad.
+ * jk+1 must be 2 larger than you might expect so that our
+ * recomputation test works. (Up to 24 bits in the integer
+ * part (the 24 bits of it that we compute) and 23 bits in
+ * the fraction part may be lost to cancelation before we
+ * recompute.)
+ *
+ * jz local integer variable indicating the number of
+ * terms of ipio2[] used.
+ *
+ * jx nx - 1
+ *
+ * jv index for pointing to the suitable ipio2[] for the
+ * computation. In general, we want
+ * ( 2^e0*x[0] * ipio2[jv-1]*2^(-24jv) )/8
+ * is an integer. Thus
+ * e0-3-24*jv >= 0 or (e0-3)/24 >= jv
+ * Hence jv = max(0,(e0-3)/24).
+ *
+ * jp jp+1 is the number of terms in PIo2[] needed, jp = jk.
+ *
+ * q[] double array with integral value, representing the
+ * 24-bits chunk of the product of x and 2/pi.
+ *
+ * q0 the corresponding exponent of q[0]. Note that the
+ * exponent for q[i] would be q0-24*i.
+ *
+ * PIo2[] double precision array, obtained by cutting pi/2
+ * into 24 bits chunks.
+ *
+ * f[] ipio2[] in floating point
+ *
+ * iq[] integer array by breaking up q[] in 24-bits chunk.
+ *
+ * fq[] final product of x*(2/pi) in fq[0],..,fq[jk]
+ *
+ * ih integer. If >0 it indicates q[] is >= 0.5, hence
+ * it also indicates the *sign* of the result.
+ *
+ */
+
+
+/*
+ * Constants:
+ * The hexadecimal values are the intended ones for the following
+ * constants. The decimal values may be used, provided that the
+ * compiler will convert from decimal to binary accurately enough
+ * to produce the hexadecimal values shown.
+ */
+
+#include <float.h>
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+static const int init_jk[] = {3,4,4,6}; /* initial value for jk */
+
+/*
+ * Table of constants for 2/pi, 396 Hex digits (476 decimal) of 2/pi
+ *
+ * integer array, contains the (24*i)-th to (24*i+23)-th
+ * bit of 2/pi after binary point. The corresponding
+ * floating value is
+ *
+ * ipio2[i] * 2^(-24(i+1)).
+ *
+ * NB: This table must have at least (e0-3)/24 + jk terms.
+ * For quad precision (e0 <= 16360, jk = 6), this is 686.
+ */
+static const int32_t ipio2[] = {
+0xA2F983, 0x6E4E44, 0x1529FC, 0x2757D1, 0xF534DD, 0xC0DB62,
+0x95993C, 0x439041, 0xFE5163, 0xABDEBB, 0xC561B7, 0x246E3A,
+0x424DD2, 0xE00649, 0x2EEA09, 0xD1921C, 0xFE1DEB, 0x1CB129,
+0xA73EE8, 0x8235F5, 0x2EBB44, 0x84E99C, 0x7026B4, 0x5F7E41,
+0x3991D6, 0x398353, 0x39F49C, 0x845F8B, 0xBDF928, 0x3B1FF8,
+0x97FFDE, 0x05980F, 0xEF2F11, 0x8B5A0A, 0x6D1F6D, 0x367ECF,
+0x27CB09, 0xB74F46, 0x3F669E, 0x5FEA2D, 0x7527BA, 0xC7EBE5,
+0xF17B3D, 0x0739F7, 0x8A5292, 0xEA6BFB, 0x5FB11F, 0x8D5D08,
+0x560330, 0x46FC7B, 0x6BABF0, 0xCFBC20, 0x9AF436, 0x1DA9E3,
+0x91615E, 0xE61B08, 0x659985, 0x5F14A0, 0x68408D, 0xFFD880,
+0x4D7327, 0x310606, 0x1556CA, 0x73A8C9, 0x60E27B, 0xC08C6B,
+
+#if LDBL_MAX_EXP > 1024
+#if LDBL_MAX_EXP > 16384
+#error "ipio2 table needs to be expanded"
+#endif
+0x47C419, 0xC367CD, 0xDCE809, 0x2A8359, 0xC4768B, 0x961CA6,
+0xDDAF44, 0xD15719, 0x053EA5, 0xFF0705, 0x3F7E33, 0xE832C2,
+0xDE4F98, 0x327DBB, 0xC33D26, 0xEF6B1E, 0x5EF89F, 0x3A1F35,
+0xCAF27F, 0x1D87F1, 0x21907C, 0x7C246A, 0xFA6ED5, 0x772D30,
+0x433B15, 0xC614B5, 0x9D19C3, 0xC2C4AD, 0x414D2C, 0x5D000C,
+0x467D86, 0x2D71E3, 0x9AC69B, 0x006233, 0x7CD2B4, 0x97A7B4,
+0xD55537, 0xF63ED7, 0x1810A3, 0xFC764D, 0x2A9D64, 0xABD770,
+0xF87C63, 0x57B07A, 0xE71517, 0x5649C0, 0xD9D63B, 0x3884A7,
+0xCB2324, 0x778AD6, 0x23545A, 0xB91F00, 0x1B0AF1, 0xDFCE19,
+0xFF319F, 0x6A1E66, 0x615799, 0x47FBAC, 0xD87F7E, 0xB76522,
+0x89E832, 0x60BFE6, 0xCDC4EF, 0x09366C, 0xD43F5D, 0xD7DE16,
+0xDE3B58, 0x929BDE, 0x2822D2, 0xE88628, 0x4D58E2, 0x32CAC6,
+0x16E308, 0xCB7DE0, 0x50C017, 0xA71DF3, 0x5BE018, 0x34132E,
+0x621283, 0x014883, 0x5B8EF5, 0x7FB0AD, 0xF2E91E, 0x434A48,
+0xD36710, 0xD8DDAA, 0x425FAE, 0xCE616A, 0xA4280A, 0xB499D3,
+0xF2A606, 0x7F775C, 0x83C2A3, 0x883C61, 0x78738A, 0x5A8CAF,
+0xBDD76F, 0x63A62D, 0xCBBFF4, 0xEF818D, 0x67C126, 0x45CA55,
+0x36D9CA, 0xD2A828, 0x8D61C2, 0x77C912, 0x142604, 0x9B4612,
+0xC459C4, 0x44C5C8, 0x91B24D, 0xF31700, 0xAD43D4, 0xE54929,
+0x10D5FD, 0xFCBE00, 0xCC941E, 0xEECE70, 0xF53E13, 0x80F1EC,
+0xC3E7B3, 0x28F8C7, 0x940593, 0x3E71C1, 0xB3092E, 0xF3450B,
+0x9C1288, 0x7B20AB, 0x9FB52E, 0xC29247, 0x2F327B, 0x6D550C,
+0x90A772, 0x1FE76B, 0x96CB31, 0x4A1679, 0xE27941, 0x89DFF4,
+0x9794E8, 0x84E6E2, 0x973199, 0x6BED88, 0x365F5F, 0x0EFDBB,
+0xB49A48, 0x6CA467, 0x427271, 0x325D8D, 0xB8159F, 0x09E5BC,
+0x25318D, 0x3974F7, 0x1C0530, 0x010C0D, 0x68084B, 0x58EE2C,
+0x90AA47, 0x02E774, 0x24D6BD, 0xA67DF7, 0x72486E, 0xEF169F,
+0xA6948E, 0xF691B4, 0x5153D1, 0xF20ACF, 0x339820, 0x7E4BF5,
+0x6863B2, 0x5F3EDD, 0x035D40, 0x7F8985, 0x295255, 0xC06437,
+0x10D86D, 0x324832, 0x754C5B, 0xD4714E, 0x6E5445, 0xC1090B,
+0x69F52A, 0xD56614, 0x9D0727, 0x50045D, 0xDB3BB4, 0xC576EA,
+0x17F987, 0x7D6B49, 0xBA271D, 0x296996, 0xACCCC6, 0x5414AD,
+0x6AE290, 0x89D988, 0x50722C, 0xBEA404, 0x940777, 0x7030F3,
+0x27FC00, 0xA871EA, 0x49C266, 0x3DE064, 0x83DD97, 0x973FA3,
+0xFD9443, 0x8C860D, 0xDE4131, 0x9D3992, 0x8C70DD, 0xE7B717,
+0x3BDF08, 0x2B3715, 0xA0805C, 0x93805A, 0x921110, 0xD8E80F,
+0xAF806C, 0x4BFFDB, 0x0F9038, 0x761859, 0x15A562, 0xBBCB61,
+0xB989C7, 0xBD4010, 0x04F2D2, 0x277549, 0xF6B6EB, 0xBB22DB,
+0xAA140A, 0x2F2689, 0x768364, 0x333B09, 0x1A940E, 0xAA3A51,
+0xC2A31D, 0xAEEDAF, 0x12265C, 0x4DC26D, 0x9C7A2D, 0x9756C0,
+0x833F03, 0xF6F009, 0x8C402B, 0x99316D, 0x07B439, 0x15200C,
+0x5BC3D8, 0xC492F5, 0x4BADC6, 0xA5CA4E, 0xCD37A7, 0x36A9E6,
+0x9492AB, 0x6842DD, 0xDE6319, 0xEF8C76, 0x528B68, 0x37DBFC,
+0xABA1AE, 0x3115DF, 0xA1AE00, 0xDAFB0C, 0x664D64, 0xB705ED,
+0x306529, 0xBF5657, 0x3AFF47, 0xB9F96A, 0xF3BE75, 0xDF9328,
+0x3080AB, 0xF68C66, 0x15CB04, 0x0622FA, 0x1DE4D9, 0xA4B33D,
+0x8F1B57, 0x09CD36, 0xE9424E, 0xA4BE13, 0xB52333, 0x1AAAF0,
+0xA8654F, 0xA5C1D2, 0x0F3F0B, 0xCD785B, 0x76F923, 0x048B7B,
+0x721789, 0x53A6C6, 0xE26E6F, 0x00EBEF, 0x584A9B, 0xB7DAC4,
+0xBA66AA, 0xCFCF76, 0x1D02D1, 0x2DF1B1, 0xC1998C, 0x77ADC3,
+0xDA4886, 0xA05DF7, 0xF480C6, 0x2FF0AC, 0x9AECDD, 0xBC5C3F,
+0x6DDED0, 0x1FC790, 0xB6DB2A, 0x3A25A3, 0x9AAF00, 0x9353AD,
+0x0457B6, 0xB42D29, 0x7E804B, 0xA707DA, 0x0EAA76, 0xA1597B,
+0x2A1216, 0x2DB7DC, 0xFDE5FA, 0xFEDB89, 0xFDBE89, 0x6C76E4,
+0xFCA906, 0x70803E, 0x156E85, 0xFF87FD, 0x073E28, 0x336761,
+0x86182A, 0xEABD4D, 0xAFE7B3, 0x6E6D8F, 0x396795, 0x5BBF31,
+0x48D784, 0x16DF30, 0x432DC7, 0x356125, 0xCE70C9, 0xB8CB30,
+0xFD6CBF, 0xA200A4, 0xE46C05, 0xA0DD5A, 0x476F21, 0xD21262,
+0x845CB9, 0x496170, 0xE0566B, 0x015299, 0x375550, 0xB7D51E,
+0xC4F133, 0x5F6E13, 0xE4305D, 0xA92E85, 0xC3B21D, 0x3632A1,
+0xA4B708, 0xD4B1EA, 0x21F716, 0xE4698F, 0x77FF27, 0x80030C,
+0x2D408D, 0xA0CD4F, 0x99A520, 0xD3A2B3, 0x0A5D2F, 0x42F9B4,
+0xCBDA11, 0xD0BE7D, 0xC1DB9B, 0xBD17AB, 0x81A2CA, 0x5C6A08,
+0x17552E, 0x550027, 0xF0147F, 0x8607E1, 0x640B14, 0x8D4196,
+0xDEBE87, 0x2AFDDA, 0xB6256B, 0x34897B, 0xFEF305, 0x9EBFB9,
+0x4F6A68, 0xA82A4A, 0x5AC44F, 0xBCF82D, 0x985AD7, 0x95C7F4,
+0x8D4D0D, 0xA63A20, 0x5F57A4, 0xB13F14, 0x953880, 0x0120CC,
+0x86DD71, 0xB6DEC9, 0xF560BF, 0x11654D, 0x6B0701, 0xACB08C,
+0xD0C0B2, 0x485551, 0x0EFB1E, 0xC37295, 0x3B06A3, 0x3540C0,
+0x7BDC06, 0xCC45E0, 0xFA294E, 0xC8CAD6, 0x41F3E8, 0xDE647C,
+0xD8649B, 0x31BED9, 0xC397A4, 0xD45877, 0xC5E369, 0x13DAF0,
+0x3C3ABA, 0x461846, 0x5F7555, 0xF5BDD2, 0xC6926E, 0x5D2EAC,
+0xED440E, 0x423E1C, 0x87C461, 0xE9FD29, 0xF3D6E7, 0xCA7C22,
+0x35916F, 0xC5E008, 0x8DD7FF, 0xE26A6E, 0xC6FDB0, 0xC10893,
+0x745D7C, 0xB2AD6B, 0x9D6ECD, 0x7B723E, 0x6A11C6, 0xA9CFF7,
+0xDF7329, 0xBAC9B5, 0x5100B7, 0x0DB2E2, 0x24BA74, 0x607DE5,
+0x8AD874, 0x2C150D, 0x0C1881, 0x94667E, 0x162901, 0x767A9F,
+0xBEFDFD, 0xEF4556, 0x367ED9, 0x13D9EC, 0xB9BA8B, 0xFC97C4,
+0x27A831, 0xC36EF1, 0x36C594, 0x56A8D8, 0xB5A8B4, 0x0ECCCF,
+0x2D8912, 0x34576F, 0x89562C, 0xE3CE99, 0xB920D6, 0xAA5E6B,
+0x9C2A3E, 0xCC5F11, 0x4A0BFD, 0xFBF4E1, 0x6D3B8E, 0x2C86E2,
+0x84D4E9, 0xA9B4FC, 0xD1EEEF, 0xC9352E, 0x61392F, 0x442138,
+0xC8D91B, 0x0AFC81, 0x6A4AFB, 0xD81C2F, 0x84B453, 0x8C994E,
+0xCC2254, 0xDC552A, 0xD6C6C0, 0x96190B, 0xB8701A, 0x649569,
+0x605A26, 0xEE523F, 0x0F117F, 0x11B5F4, 0xF5CBFC, 0x2DBC34,
+0xEEBC34, 0xCC5DE8, 0x605EDD, 0x9B8E67, 0xEF3392, 0xB817C9,
+0x9B5861, 0xBC57E1, 0xC68351, 0x103ED8, 0x4871DD, 0xDD1C2D,
+0xA118AF, 0x462C21, 0xD7F359, 0x987AD9, 0xC0549E, 0xFA864F,
+0xFC0656, 0xAE79E5, 0x362289, 0x22AD38, 0xDC9367, 0xAAE855,
+0x382682, 0x9BE7CA, 0xA40D51, 0xB13399, 0x0ED7A9, 0x480569,
+0xF0B265, 0xA7887F, 0x974C88, 0x36D1F9, 0xB39221, 0x4A827B,
+0x21CF98, 0xDC9F40, 0x5547DC, 0x3A74E1, 0x42EB67, 0xDF9DFE,
+0x5FD45E, 0xA4677B, 0x7AACBA, 0xA2F655, 0x23882B, 0x55BA41,
+0x086E59, 0x862A21, 0x834739, 0xE6E389, 0xD49EE5, 0x40FB49,
+0xE956FF, 0xCA0F1C, 0x8A59C5, 0x2BFA94, 0xC5C1D3, 0xCFC50F,
+0xAE5ADB, 0x86C547, 0x624385, 0x3B8621, 0x94792C, 0x876110,
+0x7B4C2A, 0x1A2C80, 0x12BF43, 0x902688, 0x893C78, 0xE4C4A8,
+0x7BDBE5, 0xC23AC4, 0xEAF426, 0x8A67F7, 0xBF920D, 0x2BA365,
+0xB1933D, 0x0B7CBD, 0xDC51A4, 0x63DD27, 0xDDE169, 0x19949A,
+0x9529A8, 0x28CE68, 0xB4ED09, 0x209F44, 0xCA984E, 0x638270,
+0x237C7E, 0x32B90F, 0x8EF5A7, 0xE75614, 0x08F121, 0x2A9DB5,
+0x4D7E6F, 0x5119A5, 0xABF9B5, 0xD6DF82, 0x61DD96, 0x023616,
+0x9F3AC4, 0xA1A283, 0x6DED72, 0x7A8D39, 0xA9B882, 0x5C326B,
+0x5B2746, 0xED3400, 0x7700D2, 0x55F4FC, 0x4D5901, 0x8071E0,
+#endif
+
+};
+
+static const double PIo2[] = {
+ 1.57079625129699707031e+00, /* 0x3FF921FB, 0x40000000 */
+ 7.54978941586159635335e-08, /* 0x3E74442D, 0x00000000 */
+ 5.39030252995776476554e-15, /* 0x3CF84698, 0x80000000 */
+ 3.28200341580791294123e-22, /* 0x3B78CC51, 0x60000000 */
+ 1.27065575308067607349e-29, /* 0x39F01B83, 0x80000000 */
+ 1.22933308981111328932e-36, /* 0x387A2520, 0x40000000 */
+ 2.73370053816464559624e-44, /* 0x36E38222, 0x80000000 */
+ 2.16741683877804819444e-51, /* 0x3569F31D, 0x00000000 */
+};
+
+static const double
+zero = 0.0,
+one = 1.0,
+two24 = 1.67772160000000000000e+07, /* 0x41700000, 0x00000000 */
+twon24 = 5.96046447753906250000e-08; /* 0x3E700000, 0x00000000 */
+
+OLM_DLLEXPORT int
+__kernel_rem_pio2(double *x, double *y, int e0, int nx, int prec)
+{
+ int32_t jz,jx,jv,jp,jk,carry,n,iq[20],i,j,k,m,q0,ih;
+ double z,fw,f[20],fq[20],q[20];
+
+ /* initialize jk*/
+ jk = init_jk[prec];
+ jp = jk;
+
+ /* determine jx,jv,q0, note that 3>q0 */
+ jx = nx-1;
+ jv = (e0-3)/24; if(jv<0) jv=0;
+ q0 = e0-24*(jv+1);
+
+ /* set up f[0] to f[jx+jk] where f[jx+jk] = ipio2[jv+jk] */
+ j = jv-jx; m = jx+jk;
+ for(i=0;i<=m;i++,j++) f[i] = (j<0)? zero : (double) ipio2[j];
+
+ /* compute q[0],q[1],...q[jk] */
+ for (i=0;i<=jk;i++) {
+ for(j=0,fw=0.0;j<=jx;j++) fw += x[j]*f[jx+i-j];
+ q[i] = fw;
+ }
+
+ jz = jk;
+recompute:
+ /* distill q[] into iq[] reversingly */
+ for(i=0,j=jz,z=q[jz];j>0;i++,j--) {
+ fw = (double)((int32_t)(twon24* z));
+ iq[i] = (int32_t)(z-two24*fw);
+ z = q[j-1]+fw;
+ }
+
+ /* compute n */
+ z = scalbn(z,q0); /* actual value of z */
+ z -= 8.0*floor(z*0.125); /* trim off integer >= 8 */
+ n = (int32_t) z;
+ z -= (double)n;
+ ih = 0;
+ if(q0>0) { /* need iq[jz-1] to determine n */
+ i = (iq[jz-1]>>(24-q0)); n += i;
+ iq[jz-1] -= i<<(24-q0);
+ ih = iq[jz-1]>>(23-q0);
+ }
+ else if(q0==0) ih = iq[jz-1]>>23;
+ else if(z>=0.5) ih=2;
+
+ if(ih>0) { /* q > 0.5 */
+ n += 1; carry = 0;
+ for(i=0;i<jz ;i++) { /* compute 1-q */
+ j = iq[i];
+ if(carry==0) {
+ if(j!=0) {
+ carry = 1; iq[i] = 0x1000000- j;
+ }
+ } else iq[i] = 0xffffff - j;
+ }
+ if(q0>0) { /* rare case: chance is 1 in 12 */
+ switch(q0) {
+ case 1:
+ iq[jz-1] &= 0x7fffff; break;
+ case 2:
+ iq[jz-1] &= 0x3fffff; break;
+ }
+ }
+ if(ih==2) {
+ z = one - z;
+ if(carry!=0) z -= scalbn(one,q0);
+ }
+ }
+
+ /* check if recomputation is needed */
+ if(z==zero) {
+ j = 0;
+ for (i=jz-1;i>=jk;i--) j |= iq[i];
+ if(j==0) { /* need recomputation */
+ for(k=1;iq[jk-k]==0;k++); /* k = no. of terms needed */
+
+ for(i=jz+1;i<=jz+k;i++) { /* add q[jz+1] to q[jz+k] */
+ f[jx+i] = (double) ipio2[jv+i];
+ for(j=0,fw=0.0;j<=jx;j++) fw += x[j]*f[jx+i-j];
+ q[i] = fw;
+ }
+ jz += k;
+ goto recompute;
+ }
+ }
+
+ /* chop off zero terms */
+ if(z==0.0) {
+ jz -= 1; q0 -= 24;
+ while(iq[jz]==0) { jz--; q0-=24;}
+ } else { /* break z into 24-bit if necessary */
+ z = scalbn(z,-q0);
+ if(z>=two24) {
+ fw = (double)((int32_t)(twon24*z));
+ iq[jz] = (int32_t)(z-two24*fw);
+ jz += 1; q0 += 24;
+ iq[jz] = (int32_t) fw;
+ } else iq[jz] = (int32_t) z ;
+ }
+
+ /* convert integer "bit" chunk to floating-point value */
+ fw = scalbn(one,q0);
+ for(i=jz;i>=0;i--) {
+ q[i] = fw*(double)iq[i]; fw*=twon24;
+ }
+
+ /* compute PIo2[0,...,jp]*q[jz,...,0] */
+ for(i=jz;i>=0;i--) {
+ for(fw=0.0,k=0;k<=jp&&k<=jz-i;k++) fw += PIo2[k]*q[i+k];
+ fq[jz-i] = fw;
+ }
+
+ /* compress fq[] into y[] */
+ switch(prec) {
+ case 0:
+ fw = 0.0;
+ for (i=jz;i>=0;i--) fw += fq[i];
+ y[0] = (ih==0)? fw: -fw;
+ break;
+ case 1:
+ case 2:
+ fw = 0.0;
+ for (i=jz;i>=0;i--) fw += fq[i];
+ STRICT_ASSIGN(double,fw,fw);
+ y[0] = (ih==0)? fw: -fw;
+ fw = fq[0]-fw;
+ for (i=1;i<=jz;i++) fw += fq[i];
+ y[1] = (ih==0)? fw: -fw;
+ break;
+ case 3: /* painful */
+ for (i=jz;i>0;i--) {
+ fw = fq[i-1]+fq[i];
+ fq[i] += fq[i-1]-fw;
+ fq[i-1] = fw;
+ }
+ for (i=jz;i>1;i--) {
+ fw = fq[i-1]+fq[i];
+ fq[i] += fq[i-1]-fw;
+ fq[i-1] = fw;
+ }
+ for (fw=0.0,i=jz;i>=2;i--) fw += fq[i];
+ if(ih==0) {
+ y[0] = fq[0]; y[1] = fq[1]; y[2] = fw;
+ } else {
+ y[0] = -fq[0]; y[1] = -fq[1]; y[2] = -fw;
+ }
+ }
+ return n&7;
+}
--- /dev/null
+
+/* @(#)k_sin.c 1.3 95/01/18 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunSoft, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/src/k_sin.c,v 1.11 2008/02/19 12:54:14 bde Exp $");
+
+/* __kernel_sin( x, y, iy)
+ * kernel sin function on ~[-pi/4, pi/4] (except on -0), pi/4 ~ 0.7854
+ * Input x is assumed to be bounded by ~pi/4 in magnitude.
+ * Input y is the tail of x.
+ * Input iy indicates whether y is 0. (if iy=0, y assume to be 0).
+ *
+ * Algorithm
+ * 1. Since sin(-x) = -sin(x), we need only to consider positive x.
+ * 2. Callers must return sin(-0) = -0 without calling here since our
+ * odd polynomial is not evaluated in a way that preserves -0.
+ * Callers may do the optimization sin(x) ~ x for tiny x.
+ * 3. sin(x) is approximated by a polynomial of degree 13 on
+ * [0,pi/4]
+ * 3 13
+ * sin(x) ~ x + S1*x + ... + S6*x
+ * where
+ *
+ * |sin(x) 2 4 6 8 10 12 | -58
+ * |----- - (1+S1*x +S2*x +S3*x +S4*x +S5*x +S6*x )| <= 2
+ * | x |
+ *
+ * 4. sin(x+y) = sin(x) + sin'(x')*y
+ * ~ sin(x) + (1-x*x/2)*y
+ * For better accuracy, let
+ * 3 2 2 2 2
+ * r = x *(S2+x *(S3+x *(S4+x *(S5+x *S6))))
+ * then 3 2
+ * sin(x) = x + (S1*x + (x *(r-y/2)+y))
+ */
+
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+static const double
+half = 5.00000000000000000000e-01, /* 0x3FE00000, 0x00000000 */
+S1 = -1.66666666666666324348e-01, /* 0xBFC55555, 0x55555549 */
+S2 = 8.33333333332248946124e-03, /* 0x3F811111, 0x1110F8A6 */
+S3 = -1.98412698298579493134e-04, /* 0xBF2A01A0, 0x19C161D5 */
+S4 = 2.75573137070700676789e-06, /* 0x3EC71DE3, 0x57B1FE7D */
+S5 = -2.50507602534068634195e-08, /* 0xBE5AE5E6, 0x8A2B9CEB */
+S6 = 1.58969099521155010221e-10; /* 0x3DE5D93A, 0x5ACFD57C */
+
+OLM_DLLEXPORT double
+__kernel_sin(double x, double y, int iy)
+{
+ double z,r,v,w;
+
+ z = x*x;
+ w = z*z;
+ r = S2+z*(S3+z*S4) + z*w*(S5+z*S6);
+ v = z*x;
+ if(iy==0) return x+v*(S1+z*r);
+ else return x-((z*(half*y-v*r)-y)-v*S1);
+}
--- /dev/null
+/* k_sinf.c -- float version of k_sin.c
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ * Optimized by Bruce D. Evans.
+ */
+
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#ifndef INLINE_KERNEL_SINDF
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/src/k_sinf.c,v 1.16 2009/06/03 08:16:34 ed Exp $");
+#endif
+
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+/* |sin(x)/x - s(x)| < 2**-37.5 (~[-4.89e-12, 4.824e-12]). */
+static const double
+S1 = -0x15555554cbac77.0p-55, /* -0.166666666416265235595 */
+S2 = 0x111110896efbb2.0p-59, /* 0.0083333293858894631756 */
+S3 = -0x1a00f9e2cae774.0p-65, /* -0.000198393348360966317347 */
+S4 = 0x16cd878c3b46a7.0p-71; /* 0.0000027183114939898219064 */
+
+#ifndef INLINE_KERNEL_SINDF
+extern
+#endif
+//__inline float
+OLM_DLLEXPORT float
+__kernel_sindf(double x)
+{
+ double r, s, w, z;
+
+ /* Try to optimize for parallel evaluation as in k_tanf.c. */
+ z = x*x;
+ w = z*z;
+ r = S3+z*S4;
+ s = z*x;
+ return (x + s*(S1+z*S2)) + s*w*r;
+}
--- /dev/null
+/* @(#)k_tan.c 1.5 04/04/22 SMI */
+
+/*
+ * ====================================================
+ * Copyright 2004 Sun Microsystems, Inc. All Rights Reserved.
+ *
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/* INDENT OFF */
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/src/k_tan.c,v 1.13 2008/02/22 02:30:35 das Exp $");
+
+/* __kernel_tan( x, y, k )
+ * kernel tan function on ~[-pi/4, pi/4] (except on -0), pi/4 ~ 0.7854
+ * Input x is assumed to be bounded by ~pi/4 in magnitude.
+ * Input y is the tail of x.
+ * Input k indicates whether tan (if k = 1) or -1/tan (if k = -1) is returned.
+ *
+ * Algorithm
+ * 1. Since tan(-x) = -tan(x), we need only to consider positive x.
+ * 2. Callers must return tan(-0) = -0 without calling here since our
+ * odd polynomial is not evaluated in a way that preserves -0.
+ * Callers may do the optimization tan(x) ~ x for tiny x.
+ * 3. tan(x) is approximated by a odd polynomial of degree 27 on
+ * [0,0.67434]
+ * 3 27
+ * tan(x) ~ x + T1*x + ... + T13*x
+ * where
+ *
+ * |tan(x) 2 4 26 | -59.2
+ * |----- - (1+T1*x +T2*x +.... +T13*x )| <= 2
+ * | x |
+ *
+ * Note: tan(x+y) = tan(x) + tan'(x)*y
+ * ~ tan(x) + (1+x*x)*y
+ * Therefore, for better accuracy in computing tan(x+y), let
+ * 3 2 2 2 2
+ * r = x *(T2+x *(T3+x *(...+x *(T12+x *T13))))
+ * then
+ * 3 2
+ * tan(x+y) = x + (T1*x + (x *(r+y)+y))
+ *
+ * 4. For x in [0.67434,pi/4], let y = pi/4 - x, then
+ * tan(x) = tan(pi/4-y) = (1-tan(y))/(1+tan(y))
+ * = 1 - 2*(tan(y) - (tan(y)^2)/(1+tan(y)))
+ */
+
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+static const double xxx[] = {
+ 3.33333333333334091986e-01, /* 3FD55555, 55555563 */
+ 1.33333333333201242699e-01, /* 3FC11111, 1110FE7A */
+ 5.39682539762260521377e-02, /* 3FABA1BA, 1BB341FE */
+ 2.18694882948595424599e-02, /* 3F9664F4, 8406D637 */
+ 8.86323982359930005737e-03, /* 3F8226E3, E96E8493 */
+ 3.59207910759131235356e-03, /* 3F6D6D22, C9560328 */
+ 1.45620945432529025516e-03, /* 3F57DBC8, FEE08315 */
+ 5.88041240820264096874e-04, /* 3F4344D8, F2F26501 */
+ 2.46463134818469906812e-04, /* 3F3026F7, 1A8D1068 */
+ 7.81794442939557092300e-05, /* 3F147E88, A03792A6 */
+ 7.14072491382608190305e-05, /* 3F12B80F, 32F0A7E9 */
+ -1.85586374855275456654e-05, /* BEF375CB, DB605373 */
+ 2.59073051863633712884e-05, /* 3EFB2A70, 74BF7AD4 */
+/* one */ 1.00000000000000000000e+00, /* 3FF00000, 00000000 */
+/* pio4 */ 7.85398163397448278999e-01, /* 3FE921FB, 54442D18 */
+/* pio4lo */ 3.06161699786838301793e-17 /* 3C81A626, 33145C07 */
+};
+#define one xxx[13]
+#define pio4 xxx[14]
+#define pio4lo xxx[15]
+#define T xxx
+/* INDENT ON */
+
+double
+__kernel_tan(double x, double y, int iy) {
+ double z, r, v, w, s;
+ int32_t ix, hx;
+
+ GET_HIGH_WORD(hx,x);
+ ix = hx & 0x7fffffff; /* high word of |x| */
+ if (ix >= 0x3FE59428) { /* |x| >= 0.6744 */
+ if (hx < 0) {
+ x = -x;
+ y = -y;
+ }
+ z = pio4 - x;
+ w = pio4lo - y;
+ x = z + w;
+ y = 0.0;
+ }
+ z = x * x;
+ w = z * z;
+ /*
+ * Break x^5*(T[1]+x^2*T[2]+...) into
+ * x^5(T[1]+x^4*T[3]+...+x^20*T[11]) +
+ * x^5(x^2*(T[2]+x^4*T[4]+...+x^22*[T12]))
+ */
+ r = T[1] + w * (T[3] + w * (T[5] + w * (T[7] + w * (T[9] +
+ w * T[11]))));
+ v = z * (T[2] + w * (T[4] + w * (T[6] + w * (T[8] + w * (T[10] +
+ w * T[12])))));
+ s = z * x;
+ r = y + z * (s * (r + v) + y);
+ r += T[0] * s;
+ w = x + r;
+ if (ix >= 0x3FE59428) {
+ v = (double) iy;
+ return (double) (1 - ((hx >> 30) & 2)) *
+ (v - 2.0 * (x - (w * w / (w + v) - r)));
+ }
+ if (iy == 1)
+ return w;
+ else {
+ /*
+ * if allow error up to 2 ulp, simply return
+ * -1.0 / (x+r) here
+ */
+ /* compute -1.0 / (x+r) accurately */
+ double a, t;
+ z = w;
+ SET_LOW_WORD(z,0);
+ v = r - (z - x); /* z+v = r+x */
+ t = a = -1.0 / w; /* a = -1.0/w */
+ SET_LOW_WORD(t,0);
+ s = 1.0 + t * z;
+ return t + a * (s + t * v);
+ }
+}
--- /dev/null
+/* k_tanf.c -- float version of k_tan.c
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ * Optimized by Bruce D. Evans.
+ */
+
+/*
+ * ====================================================
+ * Copyright 2004 Sun Microsystems, Inc. All Rights Reserved.
+ *
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#ifndef INLINE_KERNEL_TANDF
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/src/k_tanf.c,v 1.23 2009/06/03 08:16:34 ed Exp $");
+#endif
+
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+/* |tan(x)/x - t(x)| < 2**-25.5 (~[-2e-08, 2e-08]). */
+static const double
+T[] = {
+ 0x15554d3418c99f.0p-54, /* 0.333331395030791399758 */
+ 0x1112fd38999f72.0p-55, /* 0.133392002712976742718 */
+ 0x1b54c91d865afe.0p-57, /* 0.0533812378445670393523 */
+ 0x191df3908c33ce.0p-58, /* 0.0245283181166547278873 */
+ 0x185dadfcecf44e.0p-61, /* 0.00297435743359967304927 */
+ 0x1362b9bf971bcd.0p-59, /* 0.00946564784943673166728 */
+};
+
+#ifndef INLINE_KERNEL_TANDF
+extern
+#endif
+//__inline float
+OLM_DLLEXPORT float
+__kernel_tandf(double x, int iy)
+{
+ double z,r,w,s,t,u;
+
+ z = x*x;
+ /*
+ * Split up the polynomial into small independent terms to give
+ * opportunities for parallel evaluation. The chosen splitting is
+ * micro-optimized for Athlons (XP, X64). It costs 2 multiplications
+ * relative to Horner's method on sequential machines.
+ *
+ * We add the small terms from lowest degree up for efficiency on
+ * non-sequential machines (the lowest degree terms tend to be ready
+ * earlier). Apart from this, we don't care about order of
+ * operations, and don't need to to care since we have precision to
+ * spare. However, the chosen splitting is good for accuracy too,
+ * and would give results as accurate as Horner's method if the
+ * small terms were added from highest degree down.
+ */
+ r = T[4]+z*T[5];
+ t = T[2]+z*T[3];
+ w = z*z;
+ s = z*x;
+ u = T[0]+z*T[1];
+ r = (x+s*u)+(s*w)*(t+w*r);
+ if(iy==1) return r;
+ else return -1.0/r;
+}
--- /dev/null
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/*
+ * from: @(#)fdlibm.h 5.1 93/09/24
+ * $FreeBSD: src/lib/msun/src/math_private.h,v 1.34 2011/10/21 06:27:56 das Exp $
+ */
+
+#ifndef _MATH_PRIVATE_H_
+#define _MATH_PRIVATE_H_
+
+#include <openlibm_complex.h>
+
+#include "cdefs-compat.h"
+#include "types-compat.h"
+#include "fpmath.h"
+#include <stdint.h>
+#include "math_private_openbsd.h"
+
+/*
+ * The original fdlibm code used statements like:
+ * n0 = ((*(int*)&one)>>29)^1; * index of high word *
+ * ix0 = *(n0+(int*)&x); * high word of x *
+ * ix1 = *((1-n0)+(int*)&x); * low word of x *
+ * to dig two 32 bit words out of the 64 bit IEEE floating point
+ * value. That is non-ANSI, and, moreover, the gcc instruction
+ * scheduler gets it wrong. We instead use the following macros.
+ * Unlike the original code, we determine the endianness at compile
+ * time, not at run time; I don't see much benefit to selecting
+ * endianness at run time.
+ */
+
+/*
+ * A union which permits us to convert between a double and two 32 bit
+ * ints.
+ */
+
+#if __FLOAT_WORD_ORDER__ == __ORDER_BIG_ENDIAN__
+
+typedef union
+{
+ double value;
+ struct
+ {
+ u_int32_t msw;
+ u_int32_t lsw;
+ } parts;
+ struct
+ {
+ u_int64_t w;
+ } xparts;
+} ieee_double_shape_type;
+
+#endif
+
+#if __FLOAT_WORD_ORDER__ == __ORDER_LITTLE_ENDIAN__
+
+typedef union
+{
+ double value;
+ struct
+ {
+ u_int32_t lsw;
+ u_int32_t msw;
+ } parts;
+ struct
+ {
+ u_int64_t w;
+ } xparts;
+} ieee_double_shape_type;
+
+#endif
+
+/* Get two 32 bit ints from a double. */
+
+#define EXTRACT_WORDS(ix0,ix1,d) \
+do { \
+ ieee_double_shape_type ew_u; \
+ ew_u.value = (d); \
+ (ix0) = ew_u.parts.msw; \
+ (ix1) = ew_u.parts.lsw; \
+} while (0)
+
+/* Get a 64-bit int from a double. */
+#define EXTRACT_WORD64(ix,d) \
+do { \
+ ieee_double_shape_type ew_u; \
+ ew_u.value = (d); \
+ (ix) = ew_u.xparts.w; \
+} while (0)
+
+/* Get the more significant 32 bit int from a double. */
+
+#define GET_HIGH_WORD(i,d) \
+do { \
+ ieee_double_shape_type gh_u; \
+ gh_u.value = (d); \
+ (i) = gh_u.parts.msw; \
+} while (0)
+
+/* Get the less significant 32 bit int from a double. */
+
+#define GET_LOW_WORD(i,d) \
+do { \
+ ieee_double_shape_type gl_u; \
+ gl_u.value = (d); \
+ (i) = gl_u.parts.lsw; \
+} while (0)
+
+/* Set a double from two 32 bit ints. */
+
+#define INSERT_WORDS(d,ix0,ix1) \
+do { \
+ ieee_double_shape_type iw_u; \
+ iw_u.parts.msw = (ix0); \
+ iw_u.parts.lsw = (ix1); \
+ (d) = iw_u.value; \
+} while (0)
+
+/* Set a double from a 64-bit int. */
+#define INSERT_WORD64(d,ix) \
+do { \
+ ieee_double_shape_type iw_u; \
+ iw_u.xparts.w = (ix); \
+ (d) = iw_u.value; \
+} while (0)
+
+/* Set the more significant 32 bits of a double from an int. */
+
+#define SET_HIGH_WORD(d,v) \
+do { \
+ ieee_double_shape_type sh_u; \
+ sh_u.value = (d); \
+ sh_u.parts.msw = (v); \
+ (d) = sh_u.value; \
+} while (0)
+
+/* Set the less significant 32 bits of a double from an int. */
+
+#define SET_LOW_WORD(d,v) \
+do { \
+ ieee_double_shape_type sl_u; \
+ sl_u.value = (d); \
+ sl_u.parts.lsw = (v); \
+ (d) = sl_u.value; \
+} while (0)
+
+/*
+ * A union which permits us to convert between a float and a 32 bit
+ * int.
+ */
+
+typedef union
+{
+ float value;
+ /* FIXME: Assumes 32 bit int. */
+ unsigned int word;
+} ieee_float_shape_type;
+
+/* Get a 32 bit int from a float. */
+
+#define GET_FLOAT_WORD(i,d) \
+do { \
+ ieee_float_shape_type gf_u; \
+ gf_u.value = (d); \
+ (i) = gf_u.word; \
+} while (0)
+
+/* Set a float from a 32 bit int. */
+
+#define SET_FLOAT_WORD(d,i) \
+do { \
+ ieee_float_shape_type sf_u; \
+ sf_u.word = (i); \
+ (d) = sf_u.value; \
+} while (0)
+
+/* Get expsign as a 16 bit int from a long double. */
+
+#define GET_LDBL_EXPSIGN(i,d) \
+do { \
+ union IEEEl2bits ge_u; \
+ ge_u.e = (d); \
+ (i) = ge_u.xbits.expsign; \
+} while (0)
+
+/* Set expsign of a long double from a 16 bit int. */
+
+#define SET_LDBL_EXPSIGN(d,v) \
+do { \
+ union IEEEl2bits se_u; \
+ se_u.e = (d); \
+ se_u.xbits.expsign = (v); \
+ (d) = se_u.e; \
+} while (0)
+
+
+//VBS
+#define STRICT_ASSIGN(type, lval, rval) ((lval) = (rval))
+
+/* VBS
+#ifdef FLT_EVAL_METHOD
+// Attempt to get strict C99 semantics for assignment with non-C99 compilers.
+#if FLT_EVAL_METHOD == 0 || __GNUC__ == 0
+#define STRICT_ASSIGN(type, lval, rval) ((lval) = (rval))
+#else
+#define STRICT_ASSIGN(type, lval, rval) do { \
+ volatile type __lval; \
+ \
+ if (sizeof(type) >= sizeof(double)) \
+ (lval) = (rval); \
+ else { \
+ __lval = (rval); \
+ (lval) = __lval; \
+ } \
+} while (0)
+#endif
+#endif
+*/
+
+/*
+ * Common routine to process the arguments to nan(), nanf(), and nanl().
+ */
+void __scan_nan(u_int32_t *__words, int __num_words, const char *__s);
+
+#ifdef __GNUCLIKE_ASM
+
+/* Asm versions of some functions. */
+
+#ifdef __amd64__
+static __inline int
+irint(double x)
+{
+ int n;
+
+ __asm__("cvtsd2si %1,%0" : "=r" (n) : "x" (x));
+ return (n);
+}
+#define HAVE_EFFICIENT_IRINT
+#endif
+
+#ifdef __i386__
+static __inline int
+irint(double x)
+{
+ int n;
+
+ __asm__("fistl %0" : "=m" (n) : "t" (x));
+ return (n);
+}
+#define HAVE_EFFICIENT_IRINT
+#endif
+
+#endif /* __GNUCLIKE_ASM */
+
+/*
+ * ieee style elementary functions
+ *
+ * We rename functions here to improve other sources' diffability
+ * against fdlibm.
+ */
+#define __ieee754_sqrt sqrt
+#define __ieee754_acos acos
+#define __ieee754_acosh acosh
+#define __ieee754_log log
+#define __ieee754_log2 log2
+#define __ieee754_atanh atanh
+#define __ieee754_asin asin
+#define __ieee754_atan2 atan2
+#define __ieee754_exp exp
+#define __ieee754_cosh cosh
+#define __ieee754_fmod fmod
+#define __ieee754_pow pow
+#define __ieee754_lgamma lgamma
+#define __ieee754_lgamma_r lgamma_r
+#define __ieee754_log10 log10
+#define __ieee754_sinh sinh
+#define __ieee754_hypot hypot
+#define __ieee754_j0 j0
+#define __ieee754_j1 j1
+#define __ieee754_y0 y0
+#define __ieee754_y1 y1
+#define __ieee754_jn jn
+#define __ieee754_yn yn
+#define __ieee754_remainder remainder
+#define __ieee754_sqrtf sqrtf
+#define __ieee754_acosf acosf
+#define __ieee754_acoshf acoshf
+#define __ieee754_logf logf
+#define __ieee754_atanhf atanhf
+#define __ieee754_asinf asinf
+#define __ieee754_atan2f atan2f
+#define __ieee754_expf expf
+#define __ieee754_coshf coshf
+#define __ieee754_fmodf fmodf
+#define __ieee754_powf powf
+#define __ieee754_lgammaf lgammaf
+#define __ieee754_lgammaf_r lgammaf_r
+#define __ieee754_log10f log10f
+#define __ieee754_log2f log2f
+#define __ieee754_sinhf sinhf
+#define __ieee754_hypotf hypotf
+#define __ieee754_j0f j0f
+#define __ieee754_j1f j1f
+#define __ieee754_y0f y0f
+#define __ieee754_y1f y1f
+#define __ieee754_jnf jnf
+#define __ieee754_ynf ynf
+#define __ieee754_remainderf remainderf
+
+/* fdlibm kernel function */
+int __kernel_rem_pio2(double*,double*,int,int,int);
+
+/* double precision kernel functions */
+#ifdef INLINE_REM_PIO2
+__inline
+#endif
+int __ieee754_rem_pio2(double,double*);
+double __kernel_sin(double,double,int);
+double __kernel_cos(double,double);
+double __kernel_tan(double,double,int);
+double __ldexp_exp(double,int);
+double complex __ldexp_cexp(double complex,int);
+
+/* float precision kernel functions */
+#ifdef INLINE_REM_PIO2F
+__inline
+#endif
+int __ieee754_rem_pio2f(float,double*);
+#ifdef INLINE_KERNEL_SINDF
+__inline
+#endif
+float __kernel_sindf(double);
+#ifdef INLINE_KERNEL_COSDF
+__inline
+#endif
+float __kernel_cosdf(double);
+#ifdef INLINE_KERNEL_TANDF
+__inline
+#endif
+float __kernel_tandf(double,int);
+float __ldexp_expf(float,int);
+float complex __ldexp_cexpf(float complex,int);
+
+/* long double precision kernel functions */
+long double __kernel_sinl(long double, long double, int);
+long double __kernel_cosl(long double, long double);
+long double __kernel_tanl(long double, long double, int);
+
+#undef OLM_DLLEXPORT
+#ifdef _WIN32
+# ifdef IMPORT_EXPORTS
+# define OLM_DLLEXPORT __declspec(dllimport)
+# else
+# define OLM_DLLEXPORT __declspec(dllexport)
+# endif
+#else
+#define OLM_DLLEXPORT __attribute__ ((visibility("default")))
+#endif
+
+
+#endif /* !_MATH_PRIVATE_H_ */
--- /dev/null
+/* $OpenBSD: math_private.h,v 1.17 2014/06/02 19:31:17 kettenis Exp $ */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/*
+ * from: @(#)fdlibm.h 5.1 93/09/24
+ */
+
+#ifndef _MATH_PRIVATE_OPENBSD_H_
+#define _MATH_PRIVATE_OPENBSD_H_
+
+#if __FLOAT_WORD_ORDER__ == __ORDER_BIG_ENDIAN__
+
+typedef union
+{
+ long double value;
+ struct {
+ u_int32_t mswhi;
+ u_int32_t mswlo;
+ u_int32_t lswhi;
+ u_int32_t lswlo;
+ } parts32;
+ struct {
+ u_int64_t msw;
+ u_int64_t lsw;
+ } parts64;
+} ieee_quad_shape_type;
+
+#endif
+
+#if __FLOAT_WORD_ORDER__ == __ORDER_LITTLE_ENDIAN__
+
+typedef union
+{
+ long double value;
+ struct {
+ u_int32_t lswlo;
+ u_int32_t lswhi;
+ u_int32_t mswlo;
+ u_int32_t mswhi;
+ } parts32;
+ struct {
+ u_int64_t lsw;
+ u_int64_t msw;
+ } parts64;
+} ieee_quad_shape_type;
+
+#endif
+
+/* Get two 64 bit ints from a long double. */
+
+#define GET_LDOUBLE_WORDS64(ix0,ix1,d) \
+do { \
+ ieee_quad_shape_type qw_u; \
+ qw_u.value = (d); \
+ (ix0) = qw_u.parts64.msw; \
+ (ix1) = qw_u.parts64.lsw; \
+} while (0)
+
+/* Set a long double from two 64 bit ints. */
+
+#define SET_LDOUBLE_WORDS64(d,ix0,ix1) \
+do { \
+ ieee_quad_shape_type qw_u; \
+ qw_u.parts64.msw = (ix0); \
+ qw_u.parts64.lsw = (ix1); \
+ (d) = qw_u.value; \
+} while (0)
+
+/* Get the more significant 64 bits of a long double mantissa. */
+
+#define GET_LDOUBLE_MSW64(v,d) \
+do { \
+ ieee_quad_shape_type sh_u; \
+ sh_u.value = (d); \
+ (v) = sh_u.parts64.msw; \
+} while (0)
+
+/* Set the more significant 64 bits of a long double mantissa from an int. */
+
+#define SET_LDOUBLE_MSW64(d,v) \
+do { \
+ ieee_quad_shape_type sh_u; \
+ sh_u.value = (d); \
+ sh_u.parts64.msw = (v); \
+ (d) = sh_u.value; \
+} while (0)
+
+/* Get the least significant 64 bits of a long double mantissa. */
+
+#define GET_LDOUBLE_LSW64(v,d) \
+do { \
+ ieee_quad_shape_type sh_u; \
+ sh_u.value = (d); \
+ (v) = sh_u.parts64.lsw; \
+} while (0)
+
+/* A union which permits us to convert between a long double and
+ three 32 bit ints. */
+
+#if __FLOAT_WORD_ORDER__ == __ORDER_BIG_ENDIAN__
+
+typedef union
+{
+ long double value;
+ struct {
+#ifdef __LP64__
+ int padh:32;
+#endif
+ int exp:16;
+ int padl:16;
+ u_int32_t msw;
+ u_int32_t lsw;
+ } parts;
+} ieee_extended_shape_type;
+
+#endif
+
+#if __FLOAT_WORD_ORDER__ == __ORDER_LITTLE_ENDIAN__
+
+typedef union
+{
+ long double value;
+ struct {
+ u_int32_t lsw;
+ u_int32_t msw;
+ int exp:16;
+ int padl:16;
+#ifdef __LP64__
+ int padh:32;
+#endif
+ } parts;
+} ieee_extended_shape_type;
+
+#endif
+
+/* Get three 32 bit ints from a double. */
+
+#define GET_LDOUBLE_WORDS(se,ix0,ix1,d) \
+do { \
+ ieee_extended_shape_type ew_u; \
+ ew_u.value = (d); \
+ (se) = ew_u.parts.exp; \
+ (ix0) = ew_u.parts.msw; \
+ (ix1) = ew_u.parts.lsw; \
+} while (0)
+
+/* Set a double from two 32 bit ints. */
+
+#define SET_LDOUBLE_WORDS(d,se,ix0,ix1) \
+do { \
+ ieee_extended_shape_type iw_u; \
+ iw_u.parts.exp = (se); \
+ iw_u.parts.msw = (ix0); \
+ iw_u.parts.lsw = (ix1); \
+ (d) = iw_u.value; \
+} while (0)
+
+/* Get the more significant 32 bits of a long double mantissa. */
+
+#define GET_LDOUBLE_MSW(v,d) \
+do { \
+ ieee_extended_shape_type sh_u; \
+ sh_u.value = (d); \
+ (v) = sh_u.parts.msw; \
+} while (0)
+
+/* Set the more significant 32 bits of a long double mantissa from an int. */
+
+#define SET_LDOUBLE_MSW(d,v) \
+do { \
+ ieee_extended_shape_type sh_u; \
+ sh_u.value = (d); \
+ sh_u.parts.msw = (v); \
+ (d) = sh_u.value; \
+} while (0)
+
+/* Get int from the exponent of a long double. */
+
+#define GET_LDOUBLE_EXP(se,d) \
+do { \
+ ieee_extended_shape_type ge_u; \
+ ge_u.value = (d); \
+ (se) = ge_u.parts.exp; \
+} while (0)
+
+/* Set exponent of a long double from an int. */
+
+#define SET_LDOUBLE_EXP(d,se) \
+do { \
+ ieee_extended_shape_type se_u; \
+ se_u.value = (d); \
+ se_u.parts.exp = (se); \
+ (d) = se_u.value; \
+} while (0)
+
+/*
+ * Common routine to process the arguments to nan(), nanf(), and nanl().
+ */
+void __scan_nan(uint32_t *__words, int __num_words, const char *__s);
+
+/*
+ * Functions internal to the math package, yet not static.
+ */
+double __exp__D(double, double);
+struct Double __log__D(double);
+long double __p1evll(long double, void *, int);
+long double __polevll(long double, void *, int);
+
+#endif /* _MATH_PRIVATE_OPENBSD_H_ */
--- /dev/null
+/*-
+ * Copyright (c) 2002, 2003 David Schultz <das@FreeBSD.ORG>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+union IEEEl2bits {
+ long double e;
+ struct {
+#ifndef __MIPSEB__
+ unsigned int manl :32;
+ unsigned int manh :20;
+ unsigned int exp :11;
+ unsigned int sign :1;
+#else
+ unsigned int sign :1;
+ unsigned int exp :11;
+ unsigned int manh :20;
+ unsigned int manl :32;
+#endif
+ } bits;
+};
+
+#define LDBL_NBIT 0
+#define mask_nbit_l(u) ((void)0)
+#define LDBL_IMPLICIT_NBIT
+
+#define LDBL_MANH_SIZE 20
+#define LDBL_MANL_SIZE 32
+
+#define LDBL_TO_ARRAY32(u, a) do { \
+ (a)[0] = (uint32_t)(u).bits.manl; \
+ (a)[1] = (uint32_t)(u).bits.manh; \
+} while(0)
+
--- /dev/null
+/* $OpenBSD: polevll.c,v 1.2 2013/11/12 20:35:09 martynas Exp $ */
+
+/*
+ * Copyright (c) 2008 Stephen L. Moshier <steve@moshier.net>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* polevll.c
+ * p1evll.c
+ *
+ * Evaluate polynomial
+ *
+ *
+ *
+ * SYNOPSIS:
+ *
+ * int N;
+ * long double x, y, coef[N+1], polevl[];
+ *
+ * y = polevll( x, coef, N );
+ *
+ *
+ *
+ * DESCRIPTION:
+ *
+ * Evaluates polynomial of degree N:
+ *
+ * 2 N
+ * y = C + C x + C x +...+ C x
+ * 0 1 2 N
+ *
+ * Coefficients are stored in reverse order:
+ *
+ * coef[0] = C , ..., coef[N] = C .
+ * N 0
+ *
+ * The function p1evll() assumes that coef[N] = 1.0 and is
+ * omitted from the array. Its calling arguments are
+ * otherwise the same as polevll().
+ *
+ *
+ * SPEED:
+ *
+ * In the interest of speed, there are no checks for out
+ * of bounds arithmetic. This routine is used by most of
+ * the functions in the library. Depending on available
+ * equipment features, the user may wish to rewrite the
+ * program in microcode or assembly language.
+ *
+ */
+
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+/*
+ * Polynomial evaluator:
+ * P[0] x^n + P[1] x^(n-1) + ... + P[n]
+ */
+long double
+__polevll(long double x, void *PP, int n)
+{
+ long double y;
+ long double *P;
+
+ P = (long double *)PP;
+ y = *P++;
+ do {
+ y = y * x + *P++;
+ } while (--n);
+
+ return (y);
+}
+
+/*
+ * Polynomial evaluator:
+ * x^n + P[0] x^(n-1) + P[1] x^(n-2) + ... + P[n]
+ */
+long double
+__p1evll(long double x, void *PP, int n)
+{
+ long double y;
+ long double *P;
+
+ P = (long double *)PP;
+ n -= 1;
+ y = x + *P++;
+ do {
+ y = y * x + *P++;
+ } while (--n);
+
+ return (y);
+}
--- /dev/null
+/*-
+ * Copyright (c) 2003 David Schultz <das@FreeBSD.ORG>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+union IEEEl2bits {
+ long double e;
+ struct {
+ unsigned int sign :1;
+ unsigned int exp :11;
+ unsigned int manh :20;
+ unsigned int manl :32;
+ } bits;
+};
+
+#define mask_nbit_l(u) ((void)0)
+#define LDBL_IMPLICIT_NBIT
+#define LDBL_NBIT 0
+
+#define LDBL_MANH_SIZE 20
+#define LDBL_MANL_SIZE 32
+
+#define LDBL_TO_ARRAY32(u, a) do { \
+ (a)[0] = (uint32_t)(u).bits.manl; \
+ (a)[1] = (uint32_t)(u).bits.manh; \
+} while(0)
--- /dev/null
+/* @(#)s_asinh.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/src/s_asinh.c,v 1.9 2008/02/22 02:30:35 das Exp $");
+
+/* asinh(x)
+ * Method :
+ * Based on
+ * asinh(x) = sign(x) * log [ |x| + sqrt(x*x+1) ]
+ * we have
+ * asinh(x) := x if 1+x*x=1,
+ * := sign(x)*(log(x)+ln2)) for large |x|, else
+ * := sign(x)*log(2|x|+1/(|x|+sqrt(x*x+1))) if|x|>2, else
+ * := sign(x)*log1p(|x| + x^2/(1 + sqrt(1+x^2)))
+ */
+
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+static const double
+one = 1.00000000000000000000e+00, /* 0x3FF00000, 0x00000000 */
+ln2 = 6.93147180559945286227e-01, /* 0x3FE62E42, 0xFEFA39EF */
+huge= 1.00000000000000000000e+300;
+
+OLM_DLLEXPORT double
+asinh(double x)
+{
+ double t,w;
+ int32_t hx,ix;
+ GET_HIGH_WORD(hx,x);
+ ix = hx&0x7fffffff;
+ if(ix>=0x7ff00000) return x+x; /* x is inf or NaN */
+ if(ix< 0x3e300000) { /* |x|<2**-28 */
+ if(huge+x>one) return x; /* return x inexact except 0 */
+ }
+ if(ix>0x41b00000) { /* |x| > 2**28 */
+ w = __ieee754_log(fabs(x))+ln2;
+ } else if (ix>0x40000000) { /* 2**28 > |x| > 2.0 */
+ t = fabs(x);
+ w = __ieee754_log(2.0*t+one/(__ieee754_sqrt(x*x+one)+t));
+ } else { /* 2.0 > |x| > 2**-28 */
+ t = x*x;
+ w =log1p(fabs(x)+t/(one+__ieee754_sqrt(one+t)));
+ }
+ if(hx>0) return w; else return -w;
+}
--- /dev/null
+/* s_asinhf.c -- float version of s_asinh.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/src/s_asinhf.c,v 1.9 2008/02/22 02:30:35 das Exp $");
+
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+static const float
+one = 1.0000000000e+00, /* 0x3F800000 */
+ln2 = 6.9314718246e-01, /* 0x3f317218 */
+huge= 1.0000000000e+30;
+
+OLM_DLLEXPORT float
+asinhf(float x)
+{
+ float t,w;
+ int32_t hx,ix;
+ GET_FLOAT_WORD(hx,x);
+ ix = hx&0x7fffffff;
+ if(ix>=0x7f800000) return x+x; /* x is inf or NaN */
+ if(ix< 0x31800000) { /* |x|<2**-28 */
+ if(huge+x>one) return x; /* return x inexact except 0 */
+ }
+ if(ix>0x4d800000) { /* |x| > 2**28 */
+ w = __ieee754_logf(fabsf(x))+ln2;
+ } else if (ix>0x40000000) { /* 2**28 > |x| > 2.0 */
+ t = fabsf(x);
+ w = __ieee754_logf((float)2.0*t+one/(__ieee754_sqrtf(x*x+one)+t));
+ } else { /* 2.0 > |x| > 2**-28 */
+ t = x*x;
+ w =log1pf(fabsf(x)+t/(one+__ieee754_sqrtf(one+t)));
+ }
+ if(hx>0) return w; else return -w;
+}
--- /dev/null
+/* @(#)s_atan.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/src/s_atan.c,v 1.13 2011/02/10 07:37:50 das Exp $");
+
+/* atan(x)
+ * Method
+ * 1. Reduce x to positive by atan(x) = -atan(-x).
+ * 2. According to the integer k=4t+0.25 chopped, t=x, the argument
+ * is further reduced to one of the following intervals and the
+ * arctangent of t is evaluated by the corresponding formula:
+ *
+ * [0,7/16] atan(x) = t-t^3*(a1+t^2*(a2+...(a10+t^2*a11)...)
+ * [7/16,11/16] atan(x) = atan(1/2) + atan( (t-0.5)/(1+t/2) )
+ * [11/16.19/16] atan(x) = atan( 1 ) + atan( (t-1)/(1+t) )
+ * [19/16,39/16] atan(x) = atan(3/2) + atan( (t-1.5)/(1+1.5t) )
+ * [39/16,INF] atan(x) = atan(INF) + atan( -1/t )
+ *
+ * Constants:
+ * The hexadecimal values are the intended ones for the following
+ * constants. The decimal values may be used, provided that the
+ * compiler will convert from decimal to binary accurately enough
+ * to produce the hexadecimal values shown.
+ */
+
+#include <float.h>
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+static const double atanhi[] = {
+ 4.63647609000806093515e-01, /* atan(0.5)hi 0x3FDDAC67, 0x0561BB4F */
+ 7.85398163397448278999e-01, /* atan(1.0)hi 0x3FE921FB, 0x54442D18 */
+ 9.82793723247329054082e-01, /* atan(1.5)hi 0x3FEF730B, 0xD281F69B */
+ 1.57079632679489655800e+00, /* atan(inf)hi 0x3FF921FB, 0x54442D18 */
+};
+
+static const double atanlo[] = {
+ 2.26987774529616870924e-17, /* atan(0.5)lo 0x3C7A2B7F, 0x222F65E2 */
+ 3.06161699786838301793e-17, /* atan(1.0)lo 0x3C81A626, 0x33145C07 */
+ 1.39033110312309984516e-17, /* atan(1.5)lo 0x3C700788, 0x7AF0CBBD */
+ 6.12323399573676603587e-17, /* atan(inf)lo 0x3C91A626, 0x33145C07 */
+};
+
+static const double aT[] = {
+ 3.33333333333329318027e-01, /* 0x3FD55555, 0x5555550D */
+ -1.99999999998764832476e-01, /* 0xBFC99999, 0x9998EBC4 */
+ 1.42857142725034663711e-01, /* 0x3FC24924, 0x920083FF */
+ -1.11111104054623557880e-01, /* 0xBFBC71C6, 0xFE231671 */
+ 9.09088713343650656196e-02, /* 0x3FB745CD, 0xC54C206E */
+ -7.69187620504482999495e-02, /* 0xBFB3B0F2, 0xAF749A6D */
+ 6.66107313738753120669e-02, /* 0x3FB10D66, 0xA0D03D51 */
+ -5.83357013379057348645e-02, /* 0xBFADDE2D, 0x52DEFD9A */
+ 4.97687799461593236017e-02, /* 0x3FA97B4B, 0x24760DEB */
+ -3.65315727442169155270e-02, /* 0xBFA2B444, 0x2C6A6C2F */
+ 1.62858201153657823623e-02, /* 0x3F90AD3A, 0xE322DA11 */
+};
+
+ static const double
+one = 1.0,
+huge = 1.0e300;
+
+OLM_DLLEXPORT double
+atan(double x)
+{
+ double w,s1,s2,z;
+ int32_t ix,hx,id;
+
+ GET_HIGH_WORD(hx,x);
+ ix = hx&0x7fffffff;
+ if(ix>=0x44100000) { /* if |x| >= 2^66 */
+ u_int32_t low;
+ GET_LOW_WORD(low,x);
+ if(ix>0x7ff00000||
+ (ix==0x7ff00000&&(low!=0)))
+ return x+x; /* NaN */
+ if(hx>0) return atanhi[3]+*(volatile double *)&atanlo[3];
+ else return -atanhi[3]-*(volatile double *)&atanlo[3];
+ } if (ix < 0x3fdc0000) { /* |x| < 0.4375 */
+ if (ix < 0x3e400000) { /* |x| < 2^-27 */
+ if(huge+x>one) return x; /* raise inexact */
+ }
+ id = -1;
+ } else {
+ x = fabs(x);
+ if (ix < 0x3ff30000) { /* |x| < 1.1875 */
+ if (ix < 0x3fe60000) { /* 7/16 <=|x|<11/16 */
+ id = 0; x = (2.0*x-one)/(2.0+x);
+ } else { /* 11/16<=|x|< 19/16 */
+ id = 1; x = (x-one)/(x+one);
+ }
+ } else {
+ if (ix < 0x40038000) { /* |x| < 2.4375 */
+ id = 2; x = (x-1.5)/(one+1.5*x);
+ } else { /* 2.4375 <= |x| < 2^66 */
+ id = 3; x = -1.0/x;
+ }
+ }}
+ /* end of argument reduction */
+ z = x*x;
+ w = z*z;
+ /* break sum from i=0 to 10 aT[i]z**(i+1) into odd and even poly */
+ s1 = z*(aT[0]+w*(aT[2]+w*(aT[4]+w*(aT[6]+w*(aT[8]+w*aT[10])))));
+ s2 = w*(aT[1]+w*(aT[3]+w*(aT[5]+w*(aT[7]+w*aT[9]))));
+ if (id<0) return x - x*(s1+s2);
+ else {
+ z = atanhi[id] - ((x*(s1+s2) - atanlo[id]) - x);
+ return (hx<0)? -z:z;
+ }
+}
+
+#if LDBL_MANT_DIG == 53
+__weak_reference(atan, atanl);
+#endif
--- /dev/null
+/* s_atanf.c -- float version of s_atan.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/src/s_atanf.c,v 1.10 2008/08/01 01:24:25 das Exp $");
+
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+static const float atanhi[] = {
+ 4.6364760399e-01, /* atan(0.5)hi 0x3eed6338 */
+ 7.8539812565e-01, /* atan(1.0)hi 0x3f490fda */
+ 9.8279368877e-01, /* atan(1.5)hi 0x3f7b985e */
+ 1.5707962513e+00, /* atan(inf)hi 0x3fc90fda */
+};
+
+static const float atanlo[] = {
+ 5.0121582440e-09, /* atan(0.5)lo 0x31ac3769 */
+ 3.7748947079e-08, /* atan(1.0)lo 0x33222168 */
+ 3.4473217170e-08, /* atan(1.5)lo 0x33140fb4 */
+ 7.5497894159e-08, /* atan(inf)lo 0x33a22168 */
+};
+
+static const float aT[] = {
+ 3.3333328366e-01,
+ -1.9999158382e-01,
+ 1.4253635705e-01,
+ -1.0648017377e-01,
+ 6.1687607318e-02,
+};
+
+static const float
+one = 1.0,
+huge = 1.0e30;
+
+OLM_DLLEXPORT float
+atanf(float x)
+{
+ float w,s1,s2,z;
+ int32_t ix,hx,id;
+
+ GET_FLOAT_WORD(hx,x);
+ ix = hx&0x7fffffff;
+ if(ix>=0x4c800000) { /* if |x| >= 2**26 */
+ if(ix>0x7f800000)
+ return x+x; /* NaN */
+ if(hx>0) return atanhi[3]+*(volatile float *)&atanlo[3];
+ else return -atanhi[3]-*(volatile float *)&atanlo[3];
+ } if (ix < 0x3ee00000) { /* |x| < 0.4375 */
+ if (ix < 0x39800000) { /* |x| < 2**-12 */
+ if(huge+x>one) return x; /* raise inexact */
+ }
+ id = -1;
+ } else {
+ x = fabsf(x);
+ if (ix < 0x3f980000) { /* |x| < 1.1875 */
+ if (ix < 0x3f300000) { /* 7/16 <=|x|<11/16 */
+ id = 0; x = ((float)2.0*x-one)/((float)2.0+x);
+ } else { /* 11/16<=|x|< 19/16 */
+ id = 1; x = (x-one)/(x+one);
+ }
+ } else {
+ if (ix < 0x401c0000) { /* |x| < 2.4375 */
+ id = 2; x = (x-(float)1.5)/(one+(float)1.5*x);
+ } else { /* 2.4375 <= |x| < 2**26 */
+ id = 3; x = -(float)1.0/x;
+ }
+ }}
+ /* end of argument reduction */
+ z = x*x;
+ w = z*z;
+ /* break sum from i=0 to 10 aT[i]z**(i+1) into odd and even poly */
+ s1 = z*(aT[0]+w*(aT[2]+w*aT[4]));
+ s2 = w*(aT[1]+w*aT[3]);
+ if (id<0) return x - x*(s1+s2);
+ else {
+ z = atanhi[id] - ((x*(s1+s2) - atanlo[id]) - x);
+ return (hx<0)? -z:z;
+ }
+}
--- /dev/null
+/* @(#)s_atan.c 5.1 93/09/24 */
+/* FreeBSD: head/lib/msun/src/s_atan.c 176451 2008-02-22 02:30:36Z das */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/src/s_atanl.c,v 1.1 2008/07/31 22:41:26 das Exp $");
+
+/*
+ * See comments in s_atan.c.
+ * Converted to long double by David Schultz <das@FreeBSD.ORG>.
+ */
+
+#include <float.h>
+#include <openlibm_math.h>
+
+#include "invtrig.h"
+#include "math_private.h"
+
+static const long double
+one = 1.0,
+huge = 1.0e300;
+
+OLM_DLLEXPORT long double
+atanl(long double x)
+{
+ union IEEEl2bits u;
+ long double w,s1,s2,z;
+ int id;
+ int16_t expsign, expt;
+ int32_t expman;
+
+ u.e = x;
+ expsign = u.xbits.expsign;
+ expt = expsign & 0x7fff;
+ if(expt >= ATAN_CONST) { /* if |x| is large, atan(x)~=pi/2 */
+ if(expt == BIAS + LDBL_MAX_EXP &&
+ ((u.bits.manh&~LDBL_NBIT)|u.bits.manl)!=0)
+ return x+x; /* NaN */
+ if(expsign>0) return atanhi[3]+atanlo[3];
+ else return -atanhi[3]-atanlo[3];
+ }
+ /* Extract the exponent and the first few bits of the mantissa. */
+ /* XXX There should be a more convenient way to do this. */
+ expman = (expt << 8) | ((u.bits.manh >> (MANH_SIZE - 9)) & 0xff);
+ if (expman < ((BIAS - 2) << 8) + 0xc0) { /* |x| < 0.4375 */
+ if (expt < ATAN_LINEAR) { /* if |x| is small, atanl(x)~=x */
+ if(huge+x>one) return x; /* raise inexact */
+ }
+ id = -1;
+ } else {
+ x = fabsl(x);
+ if (expman < (BIAS << 8) + 0x30) { /* |x| < 1.1875 */
+ if (expman < ((BIAS - 1) << 8) + 0x60) { /* 7/16 <=|x|<11/16 */
+ id = 0; x = (2.0*x-one)/(2.0+x);
+ } else { /* 11/16<=|x|< 19/16 */
+ id = 1; x = (x-one)/(x+one);
+ }
+ } else {
+ if (expman < ((BIAS + 1) << 8) + 0x38) { /* |x| < 2.4375 */
+ id = 2; x = (x-1.5)/(one+1.5*x);
+ } else { /* 2.4375 <= |x| < 2^ATAN_CONST */
+ id = 3; x = -1.0/x;
+ }
+ }}
+ /* end of argument reduction */
+ z = x*x;
+ w = z*z;
+ /* break sum aT[i]z**(i+1) into odd and even poly */
+ s1 = z*T_even(w);
+ s2 = w*T_odd(w);
+ if (id<0) return x - x*(s1+s2);
+ else {
+ z = atanhi[id] - ((x*(s1+s2) - atanlo[id]) - x);
+ return (expsign<0)? -z:z;
+ }
+}
--- /dev/null
+/* $OpenBSD: s_cabs.c,v 1.6 2013/07/03 04:46:36 espie Exp $ */
+/*
+ * Copyright (c) 2008 Martynas Venckus <martynas@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <float.h>
+#include <openlibm_complex.h>
+#include <openlibm_math.h>
+
+double
+cabs(double complex z)
+{
+ return hypot(__real__ z, __imag__ z);
+}
+
+#if LDBL_MANT_DIG == DBL_MANT_DIG
+__strong_alias(cabsl, cabs);
+#endif /* LDBL_MANT_DIG == DBL_MANT_DIG */
--- /dev/null
+/* $OpenBSD: s_cabsf.c,v 1.1 2008/09/07 20:36:09 martynas Exp $ */
+/*
+ * Copyright (c) 2008 Martynas Venckus <martynas@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <openlibm_complex.h>
+#include <openlibm_math.h>
+
+float
+cabsf(float complex z)
+{
+ return hypotf(__real__ z, __imag__ z);
+}
--- /dev/null
+/* $OpenBSD: s_cabsl.c,v 1.1 2011/07/08 19:25:31 martynas Exp $ */
+
+/*
+ * Copyright (c) 2011 Martynas Venckus <martynas@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <openlibm_complex.h>
+#include <openlibm_math.h>
+
+long double
+cabsl(long double complex z)
+{
+ return hypotl(__real__ z, __imag__ z);
+}
--- /dev/null
+/* $OpenBSD: s_cacos.c,v 1.6 2013/07/03 04:46:36 espie Exp $ */
+/*
+ * Copyright (c) 2008 Stephen L. Moshier <steve@moshier.net>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* cacos()
+ *
+ * Complex circular arc cosine
+ *
+ *
+ *
+ * SYNOPSIS:
+ *
+ * double complex cacos();
+ * double complex z, w;
+ *
+ * w = cacos (z);
+ *
+ *
+ *
+ * DESCRIPTION:
+ *
+ *
+ * w = arccos z = PI/2 - arcsin z.
+ *
+ *
+ *
+ *
+ * ACCURACY:
+ *
+ * Relative error:
+ * arithmetic domain # trials peak rms
+ * DEC -10,+10 5200 1.6e-15 2.8e-16
+ * IEEE -10,+10 30000 1.8e-14 2.2e-15
+ */
+
+#include <float.h>
+#include <openlibm_complex.h>
+#include <openlibm_math.h>
+
+double complex
+cacos(double complex z)
+{
+ double complex w;
+
+ w = casin (z);
+ w = (M_PI_2 - creal (w)) - cimag (w) * I;
+ return (w);
+}
+
+#if LDBL_MANT_DIG == DBL_MANT_DIG
+__strong_alias(cacosl, cacos);
+#endif /* LDBL_MANT_DIG == DBL_MANT_DIG */
--- /dev/null
+/* $OpenBSD: s_cacosf.c,v 1.2 2011/07/20 19:28:33 martynas Exp $ */
+/*
+ * Copyright (c) 2008 Stephen L. Moshier <steve@moshier.net>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* cacosf()
+ *
+ * Complex circular arc cosine
+ *
+ *
+ *
+ * SYNOPSIS:
+ *
+ * void cacosf();
+ * cmplxf z, w;
+ *
+ * cacosf( &z, &w );
+ *
+ *
+ *
+ * DESCRIPTION:
+ *
+ *
+ * w = arccos z = PI/2 - arcsin z.
+ *
+ *
+ *
+ *
+ * ACCURACY:
+ *
+ * Relative error:
+ * arithmetic domain # trials peak rms
+ * IEEE -10,+10 30000 9.2e-6 1.2e-6
+ *
+ */
+
+#include <openlibm_complex.h>
+#include <openlibm_math.h>
+
+float complex
+cacosf(float complex z)
+{
+ float complex w;
+
+ w = casinf( z );
+ w = ((float)M_PI_2 - crealf (w)) - cimagf (w) * I;
+ return (w);
+}
--- /dev/null
+/* $OpenBSD: s_cacosh.c,v 1.6 2013/07/03 04:46:36 espie Exp $ */
+/*
+ * Copyright (c) 2008 Stephen L. Moshier <steve@moshier.net>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* cacosh
+ *
+ * Complex inverse hyperbolic cosine
+ *
+ *
+ *
+ * SYNOPSIS:
+ *
+ * double complex cacosh();
+ * double complex z, w;
+ *
+ * w = cacosh (z);
+ *
+ *
+ *
+ * DESCRIPTION:
+ *
+ * acosh z = i acos z .
+ *
+ * ACCURACY:
+ *
+ * Relative error:
+ * arithmetic domain # trials peak rms
+ * IEEE -10,+10 30000 1.6e-14 2.1e-15
+ *
+ */
+
+#include <float.h>
+#include <openlibm_complex.h>
+#include <openlibm_math.h>
+
+double complex
+cacosh(double complex z)
+{
+ double complex w;
+
+ w = I * cacos (z);
+ return (w);
+}
+
+#if LDBL_MANT_DIG == DBL_MANT_DIG
+__strong_alias(cacoshl, cacosh);
+#endif /* LDBL_MANT_DIG == DBL_MANT_DIG */
--- /dev/null
+/* $OpenBSD: s_cacoshf.c,v 1.1 2008/09/07 20:36:09 martynas Exp $ */
+/*
+ * Copyright (c) 2008 Stephen L. Moshier <steve@moshier.net>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* cacoshf
+ *
+ * Complex inverse hyperbolic cosine
+ *
+ *
+ *
+ * SYNOPSIS:
+ *
+ * float complex cacoshf();
+ * float complex z, w;
+ *
+ * w = cacoshf (z);
+ *
+ *
+ *
+ * DESCRIPTION:
+ *
+ * acosh z = i acos z .
+ *
+ * ACCURACY:
+ *
+ * Relative error:
+ * arithmetic domain # trials peak rms
+ * IEEE -10,+10 30000 1.6e-14 2.1e-15
+ *
+ */
+
+#include <openlibm_complex.h>
+#include <openlibm_math.h>
+
+float complex
+cacoshf(float complex z)
+{
+ float complex w;
+
+ w = I * cacosf (z);
+ return (w);
+}
--- /dev/null
+/* $OpenBSD: s_cacoshl.c,v 1.1 2011/07/08 19:25:31 martynas Exp $ */
+
+/*
+ * Copyright (c) 2008 Stephen L. Moshier <steve@moshier.net>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* cacoshl
+ *
+ * Complex inverse hyperbolic cosine
+ *
+ *
+ *
+ * SYNOPSIS:
+ *
+ * long double complex cacoshl();
+ * long double complex z, w;
+ *
+ * w = cacoshl (z);
+ *
+ *
+ *
+ * DESCRIPTION:
+ *
+ * acosh z = i acos z .
+ *
+ * ACCURACY:
+ *
+ * Relative error:
+ * arithmetic domain # trials peak rms
+ * IEEE -10,+10 30000 1.6e-14 2.1e-15
+ *
+ */
+
+#include <openlibm_complex.h>
+#include <openlibm_math.h>
+
+long double complex
+cacoshl(long double complex z)
+{
+ long double complex w;
+
+ w = I * cacosl(z);
+ return (w);
+}
--- /dev/null
+/* $OpenBSD: s_cacosl.c,v 1.3 2011/07/20 21:02:51 martynas Exp $ */
+
+/*
+ * Copyright (c) 2008 Stephen L. Moshier <steve@moshier.net>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* cacosl()
+ *
+ * Complex circular arc cosine
+ *
+ *
+ *
+ * SYNOPSIS:
+ *
+ * long double complex cacosl();
+ * long double complex z, w;
+ *
+ * w = cacosl( z );
+ *
+ *
+ *
+ * DESCRIPTION:
+ *
+ *
+ * w = arccos z = PI/2 - arcsin z.
+ *
+ *
+ *
+ *
+ * ACCURACY:
+ *
+ * Relative error:
+ * arithmetic domain # trials peak rms
+ * DEC -10,+10 5200 1.6e-15 2.8e-16
+ * IEEE -10,+10 30000 1.8e-14 2.2e-15
+ */
+
+#include <openlibm_complex.h>
+#include <openlibm_math.h>
+
+static const long double PIO2L = 1.570796326794896619231321691639751442098585L;
+
+long double complex
+cacosl(long double complex z)
+{
+ long double complex w;
+
+ w = casinl(z);
+ w = (PIO2L - creall(w)) - cimagl(w) * I;
+ return (w);
+}
--- /dev/null
+/*-
+ * Copyright (c) 2005 David Schultz <das@FreeBSD.ORG>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/src/s_carg.c,v 1.1 2007/12/12 23:43:51 das Exp $");
+
+#include <openlibm_complex.h>
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+OLM_DLLEXPORT double
+carg(double complex z)
+{
+
+ return (atan2(cimag(z), creal(z)));
+}
--- /dev/null
+/*-
+ * Copyright (c) 2005 David Schultz <das@FreeBSD.ORG>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/src/s_cargf.c,v 1.1 2007/12/12 23:43:51 das Exp $");
+
+#include <openlibm_complex.h>
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+OLM_DLLEXPORT float
+cargf(float complex z)
+{
+
+ return (atan2f(cimagf(z), crealf(z)));
+}
--- /dev/null
+/*-
+ * Copyright (c) 2005-2008 David Schultz <das@FreeBSD.ORG>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/src/s_cargl.c,v 1.1 2008/07/31 22:41:26 das Exp $");
+
+#include <openlibm_complex.h>
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+OLM_DLLEXPORT long double
+cargl(long double complex z)
+{
+
+ return (atan2l(cimagl(z), creall(z)));
+}
--- /dev/null
+/* $OpenBSD: s_casin.c,v 1.6 2013/07/03 04:46:36 espie Exp $ */
+/*
+ * Copyright (c) 2008 Stephen L. Moshier <steve@moshier.net>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* casin()
+ *
+ * Complex circular arc sine
+ *
+ *
+ *
+ * SYNOPSIS:
+ *
+ * double complex casin();
+ * double complex z, w;
+ *
+ * w = casin (z);
+ *
+ *
+ *
+ * DESCRIPTION:
+ *
+ * Inverse complex sine:
+ *
+ * 2
+ * w = -i clog( iz + csqrt( 1 - z ) ).
+ *
+ * casin(z) = -i casinh(iz)
+ *
+ * ACCURACY:
+ *
+ * Relative error:
+ * arithmetic domain # trials peak rms
+ * DEC -10,+10 10100 2.1e-15 3.4e-16
+ * IEEE -10,+10 30000 2.2e-14 2.7e-15
+ * Larger relative error can be observed for z near zero.
+ * Also tested by csin(casin(z)) = z.
+ */
+
+#include <float.h>
+#include <openlibm_complex.h>
+#include <openlibm_math.h>
+
+double complex
+casin(double complex z)
+{
+ double complex w;
+ static double complex ca, ct, zz, z2;
+ double x, y;
+
+ x = creal (z);
+ y = cimag (z);
+
+ if (y == 0.0) {
+ if (fabs(x) > 1.0) {
+ w = M_PI_2 + 0.0 * I;
+ /*mtherr ("casin", DOMAIN);*/
+ }
+ else {
+ w = asin (x) + 0.0 * I;
+ }
+ return (w);
+ }
+
+ /* Power series expansion */
+ /*
+ b = cabs(z);
+ if( b < 0.125 ) {
+ z2.r = (x - y) * (x + y);
+ z2.i = 2.0 * x * y;
+
+ cn = 1.0;
+ n = 1.0;
+ ca.r = x;
+ ca.i = y;
+ sum.r = x;
+ sum.i = y;
+ do {
+ ct.r = z2.r * ca.r - z2.i * ca.i;
+ ct.i = z2.r * ca.i + z2.i * ca.r;
+ ca.r = ct.r;
+ ca.i = ct.i;
+
+ cn *= n;
+ n += 1.0;
+ cn /= n;
+ n += 1.0;
+ b = cn/n;
+
+ ct.r *= b;
+ ct.i *= b;
+ sum.r += ct.r;
+ sum.i += ct.i;
+ b = fabs(ct.r) + fabs(ct.i);
+ }
+ while( b > MACHEP );
+ w->r = sum.r;
+ w->i = sum.i;
+ return;
+ }
+ */
+
+ ca = x + y * I;
+ ct = ca * I;
+ /* sqrt( 1 - z*z) */
+ /* cmul( &ca, &ca, &zz ) */
+ /*x * x - y * y */
+ zz = (x - y) * (x + y) + (2.0 * x * y) * I;
+
+ zz = 1.0 - creal(zz) - cimag(zz) * I;
+ z2 = csqrt (zz);
+
+ zz = ct + z2;
+ zz = clog (zz);
+ /* multiply by 1/i = -i */
+ w = zz * (-1.0 * I);
+ return (w);
+}
+
+#if LDBL_MANT_DIG == DBL_MANT_DIG
+__strong_alias(casinl, casin);
+#endif /* LDBL_MANT_DIG == DBL_MANT_DIG */
--- /dev/null
+/* $OpenBSD: s_casinf.c,v 1.3 2011/07/20 19:28:33 martynas Exp $ */
+/*
+ * Copyright (c) 2008 Stephen L. Moshier <steve@moshier.net>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* casinf()
+ *
+ * Complex circular arc sine
+ *
+ *
+ *
+ * SYNOPSIS:
+ *
+ * void casinf();
+ * cmplxf z, w;
+ *
+ * casinf( &z, &w );
+ *
+ *
+ *
+ * DESCRIPTION:
+ *
+ * Inverse complex sine:
+ *
+ * 2
+ * w = -i clog( iz + csqrt( 1 - z ) ).
+ *
+ *
+ * ACCURACY:
+ *
+ * Relative error:
+ * arithmetic domain # trials peak rms
+ * IEEE -10,+10 30000 1.1e-5 1.5e-6
+ * Larger relative error can be observed for z near zero.
+ *
+ */
+
+#include <openlibm_complex.h>
+#include <openlibm_math.h>
+
+float complex
+casinf(float complex z)
+{
+ float complex w;
+ float x, y;
+ static float complex ca, ct, zz, z2;
+ /*
+ float cn, n;
+ static float a, b, s, t, u, v, y2;
+ static cmplxf sum;
+ */
+
+ x = crealf(z);
+ y = cimagf(z);
+
+ if(y == 0.0f) {
+ if(fabsf(x) > 1.0f) {
+ w = (float)M_PI_2 + 0.0f * I;
+ /*mtherr( "casinf", DOMAIN );*/
+ }
+ else {
+ w = asinf (x) + 0.0f * I;
+ }
+ return (w);
+ }
+
+ /* Power series expansion */
+ /*
+ b = cabsf(z);
+ if(b < 0.125) {
+ z2.r = (x - y) * (x + y);
+ z2.i = 2.0 * x * y;
+
+ cn = 1.0;
+ n = 1.0;
+ ca.r = x;
+ ca.i = y;
+ sum.r = x;
+ sum.i = y;
+ do {
+ ct.r = z2.r * ca.r - z2.i * ca.i;
+ ct.i = z2.r * ca.i + z2.i * ca.r;
+ ca.r = ct.r;
+ ca.i = ct.i;
+
+ cn *= n;
+ n += 1.0;
+ cn /= n;
+ n += 1.0;
+ b = cn/n;
+
+ ct.r *= b;
+ ct.i *= b;
+ sum.r += ct.r;
+ sum.i += ct.i;
+ b = fabsf(ct.r) + fabsf(ct.i);
+ }
+ while(b > MACHEPF);
+ w->r = sum.r;
+ w->i = sum.i;
+ return;
+ }
+ */
+
+
+ ca = x + y * I;
+ ct = ca * I; /* iz */
+ /* sqrt( 1 - z*z) */
+ /* cmul( &ca, &ca, &zz ) */
+ /*x * x - y * y */
+ zz = (x - y) * (x + y) + (2.0f * x * y) * I;
+ zz = 1.0f - crealf(zz) - cimagf(zz) * I;
+ z2 = csqrtf (zz);
+
+ zz = ct + z2;
+ zz = clogf (zz);
+ /* multiply by 1/i = -i */
+ w = zz * (-1.0f * I);
+ return (w);
+}
--- /dev/null
+/* $OpenBSD: s_casinh.c,v 1.6 2013/07/03 04:46:36 espie Exp $ */
+/*
+ * Copyright (c) 2008 Stephen L. Moshier <steve@moshier.net>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* casinh
+ *
+ * Complex inverse hyperbolic sine
+ *
+ *
+ *
+ * SYNOPSIS:
+ *
+ * double complex casinh();
+ * double complex z, w;
+ *
+ * w = casinh (z);
+ *
+ *
+ *
+ * DESCRIPTION:
+ *
+ * casinh z = -i casin iz .
+ *
+ * ACCURACY:
+ *
+ * Relative error:
+ * arithmetic domain # trials peak rms
+ * IEEE -10,+10 30000 1.8e-14 2.6e-15
+ *
+ */
+
+#include <float.h>
+#include <openlibm_complex.h>
+#include <openlibm_math.h>
+
+double complex
+casinh(double complex z)
+{
+ double complex w;
+
+ w = -1.0 * I * casin (z * I);
+ return (w);
+}
+
+#if LDBL_MANT_DIG == DBL_MANT_DIG
+__strong_alias(casinhl, casinh);
+#endif /* LDBL_MANT_DIG == DBL_MANT_DIG */
--- /dev/null
+/* $OpenBSD: s_casinhf.c,v 1.1 2008/09/07 20:36:09 martynas Exp $ */
+/*
+ * Copyright (c) 2008 Stephen L. Moshier <steve@moshier.net>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* casinhf
+ *
+ * Complex inverse hyperbolic sine
+ *
+ *
+ *
+ * SYNOPSIS:
+ *
+ * float complex casinhf();
+ * float complex z, w;
+ *
+ * w = casinhf (z);
+ *
+ *
+ *
+ * DESCRIPTION:
+ *
+ * casinh z = -i casin iz .
+ *
+ * ACCURACY:
+ *
+ * Relative error:
+ * arithmetic domain # trials peak rms
+ * IEEE -10,+10 30000 1.8e-14 2.6e-15
+ *
+ */
+
+#include <openlibm_complex.h>
+#include <openlibm_math.h>
+
+float complex
+casinhf(float complex z)
+{
+ float complex w;
+
+ w = -1.0f * I * casinf (z * I);
+ return (w);
+}
--- /dev/null
+/* $OpenBSD: s_casinhl.c,v 1.1 2011/07/08 19:25:31 martynas Exp $ */
+
+/*
+ * Copyright (c) 2008 Stephen L. Moshier <steve@moshier.net>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* casinhl
+ *
+ * Complex inverse hyperbolic sine
+ *
+ *
+ *
+ * SYNOPSIS:
+ *
+ * long double complex casinhf();
+ * long double complex z, w;
+ *
+ * w = casinhl (z);
+ *
+ *
+ *
+ * DESCRIPTION:
+ *
+ * casinh z = -i casin iz .
+ *
+ * ACCURACY:
+ *
+ * Relative error:
+ * arithmetic domain # trials peak rms
+ * IEEE -10,+10 30000 1.8e-14 2.6e-15
+ *
+ */
+
+#include <openlibm_complex.h>
+#include <openlibm_math.h>
+
+long double complex
+casinhl(long double complex z)
+{
+ long double complex w;
+
+ w = -1.0L * I * casinl(z * I);
+ return (w);
+}
--- /dev/null
+/* $OpenBSD: s_casinl.c,v 1.3 2011/07/20 21:02:51 martynas Exp $ */
+
+/*
+ * Copyright (c) 2008 Stephen L. Moshier <steve@moshier.net>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* casinl()
+ *
+ * Complex circular arc sine
+ *
+ *
+ *
+ * SYNOPSIS:
+ *
+ * long double complex casinl();
+ * long double complex z, w;
+ *
+ * w = casinl( z );
+ *
+ *
+ *
+ * DESCRIPTION:
+ *
+ * Inverse complex sine:
+ *
+ * 2
+ * w = -i clog( iz + csqrt( 1 - z ) ).
+ *
+ *
+ * ACCURACY:
+ *
+ * Relative error:
+ * arithmetic domain # trials peak rms
+ * DEC -10,+10 10100 2.1e-15 3.4e-16
+ * IEEE -10,+10 30000 2.2e-14 2.7e-15
+ * Larger relative error can be observed for z near zero.
+ * Also tested by csin(casin(z)) = z.
+ */
+
+#include <float.h>
+#include <openlibm_complex.h>
+#include <openlibm_math.h>
+
+#if LDBL_MANT_DIG == 64
+static const long double MACHEPL= 5.42101086242752217003726400434970855712890625E-20L;
+#elif LDBL_MANT_DIG == 113
+static const long double MACHEPL = 9.629649721936179265279889712924636592690508e-35L;
+#endif
+
+static const long double PIO2L = 1.570796326794896619231321691639751442098585L;
+
+long double complex
+casinl(long double complex z)
+{
+ long double complex w;
+ long double x, y, b;
+ static long double complex ca, ct, zz, z2;
+
+ x = creall(z);
+ y = cimagl(z);
+
+ if (y == 0.0L) {
+ if (fabsl(x) > 1.0L) {
+ w = PIO2L + 0.0L * I;
+ /*mtherr( "casinl", DOMAIN );*/
+ }
+ else {
+ w = asinl(x) + 0.0L * I;
+ }
+ return (w);
+ }
+
+ /* Power series expansion */
+ b = cabsl(z);
+ if (b < 0.125L) {
+ long double complex sum;
+ long double n, cn;
+
+ z2 = (x - y) * (x + y) + (2.0L * x * y) * I;
+ cn = 1.0L;
+ n = 1.0L;
+ ca = x + y * I;
+ sum = x + y * I;
+ do {
+ ct = z2 * ca;
+ ca = ct;
+
+ cn *= n;
+ n += 1.0L;
+ cn /= n;
+ n += 1.0L;
+ b = cn/n;
+
+ ct *= b;
+ sum += ct;
+ b = cabsl(ct);
+ }
+
+ while (b > MACHEPL);
+ w = sum;
+ return w;
+ }
+
+ ca = x + y * I;
+ ct = ca * I; /* iz */
+ /* sqrt(1 - z*z) */
+ /* cmul(&ca, &ca, &zz) */
+ /* x * x - y * y */
+ zz = (x - y) * (x + y) + (2.0L * x * y) * I;
+ zz = 1.0L - creall(zz) - cimagl(zz) * I;
+ z2 = csqrtl(zz);
+
+ zz = ct + z2;
+ zz = clogl(zz);
+ /* multiply by 1/i = -i */
+ w = zz * (-1.0L * I);
+ return (w);
+}
--- /dev/null
+/* $OpenBSD: s_catan.c,v 1.6 2013/07/03 04:46:36 espie Exp $ */
+/*
+ * Copyright (c) 2008 Stephen L. Moshier <steve@moshier.net>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* catan()
+ *
+ * Complex circular arc tangent
+ *
+ *
+ *
+ * SYNOPSIS:
+ *
+ * double complex catan();
+ * double complex z, w;
+ *
+ * w = catan (z);
+ *
+ *
+ *
+ * DESCRIPTION:
+ *
+ * If
+ * z = x + iy,
+ *
+ * then
+ * 1 ( 2x )
+ * Re w = - arctan(-----------) + k PI
+ * 2 ( 2 2)
+ * (1 - x - y )
+ *
+ * ( 2 2)
+ * 1 (x + (y+1) )
+ * Im w = - log(------------)
+ * 4 ( 2 2)
+ * (x + (y-1) )
+ *
+ * Where k is an arbitrary integer.
+ *
+ * catan(z) = -i catanh(iz).
+ *
+ * ACCURACY:
+ *
+ * Relative error:
+ * arithmetic domain # trials peak rms
+ * DEC -10,+10 5900 1.3e-16 7.8e-18
+ * IEEE -10,+10 30000 2.3e-15 8.5e-17
+ * The check catan( ctan(z) ) = z, with |x| and |y| < PI/2,
+ * had peak relative error 1.5e-16, rms relative error
+ * 2.9e-17. See also clog().
+ */
+
+#include <float.h>
+#include <openlibm_complex.h>
+#include <openlibm_math.h>
+
+#define MAXNUM 1.0e308
+
+static const double DP1 = 3.14159265160560607910E0;
+static const double DP2 = 1.98418714791870343106E-9;
+static const double DP3 = 1.14423774522196636802E-17;
+
+static double
+_redupi(double x)
+{
+ double t;
+ long i;
+
+ t = x/M_PI;
+ if(t >= 0.0)
+ t += 0.5;
+ else
+ t -= 0.5;
+
+ i = t; /* the multiple */
+ t = i;
+ t = ((x - t * DP1) - t * DP2) - t * DP3;
+ return (t);
+}
+
+double complex
+catan(double complex z)
+{
+ double complex w;
+ double a, t, x, x2, y;
+
+ x = creal (z);
+ y = cimag (z);
+
+ if ((x == 0.0) && (y > 1.0))
+ goto ovrf;
+
+ x2 = x * x;
+ a = 1.0 - x2 - (y * y);
+ if (a == 0.0)
+ goto ovrf;
+
+ t = 0.5 * atan2 (2.0 * x, a);
+ w = _redupi (t);
+
+ t = y - 1.0;
+ a = x2 + (t * t);
+ if (a == 0.0)
+ goto ovrf;
+
+ t = y + 1.0;
+ a = (x2 + (t * t))/a;
+ w = w + (0.25 * log (a)) * I;
+ return (w);
+
+ovrf:
+ /*mtherr ("catan", OVERFLOW);*/
+ w = MAXNUM + MAXNUM * I;
+ return (w);
+}
+
+#if LDBL_MANT_DIG == DBL_MANT_DIG
+__strong_alias(catanl, catan);
+#endif /* LDBL_MANT_DIG == DBL_MANT_DIG */
--- /dev/null
+/* $OpenBSD: s_catanf.c,v 1.2 2010/07/18 18:42:26 guenther Exp $ */
+/*
+ * Copyright (c) 2008 Stephen L. Moshier <steve@moshier.net>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* catanf()
+ *
+ * Complex circular arc tangent
+ *
+ *
+ *
+ * SYNOPSIS:
+ *
+ * float complex catanf();
+ * float complex z, w;
+ *
+ * w = catanf( z );
+ *
+ *
+ *
+ * DESCRIPTION:
+ *
+ * If
+ * z = x + iy,
+ *
+ * then
+ * 1 ( 2x )
+ * Re w = - arctan(-----------) + k PI
+ * 2 ( 2 2)
+ * (1 - x - y )
+ *
+ * ( 2 2)
+ * 1 (x + (y+1) )
+ * Im w = - log(------------)
+ * 4 ( 2 2)
+ * (x + (y-1) )
+ *
+ * Where k is an arbitrary integer.
+ *
+ *
+ *
+ * ACCURACY:
+ *
+ * Relative error:
+ * arithmetic domain # trials peak rms
+ * IEEE -10,+10 30000 2.3e-6 5.2e-8
+ *
+ */
+
+#include <openlibm_complex.h>
+#include <openlibm_math.h>
+
+#define MAXNUMF 1.0e38F
+
+static const double DP1 = 3.140625;
+static const double DP2 = 9.67502593994140625E-4;
+static const double DP3 = 1.509957990978376432E-7;
+
+static float
+_redupif(float xx)
+{
+ float x, t;
+ long i;
+
+ x = xx;
+ t = x/(float)M_PI;
+ if(t >= 0.0)
+ t += 0.5;
+ else
+ t -= 0.5;
+
+ i = t; /* the multiple */
+ t = i;
+ t = ((x - t * DP1) - t * DP2) - t * DP3;
+ return(t);
+}
+
+float complex
+catanf(float complex z)
+{
+ float complex w;
+ float a, t, x, x2, y;
+
+ x = crealf(z);
+ y = cimagf(z);
+
+ if((x == 0.0f) && (y > 1.0f))
+ goto ovrf;
+
+ x2 = x * x;
+ a = 1.0f - x2 - (y * y);
+ if (a == 0.0f)
+ goto ovrf;
+
+ t = 0.5f * atan2f(2.0f * x, a);
+ w = _redupif(t);
+
+ t = y - 1.0f;
+ a = x2 + (t * t);
+ if(a == 0.0f)
+ goto ovrf;
+
+ t = y + 1.0f;
+ a = (x2 + (t * t))/a;
+ w = w + (0.25f * logf (a)) * I;
+ return (w);
+
+ovrf:
+ /*mtherr( "catanf", OVERFLOW );*/
+ w = MAXNUMF + MAXNUMF * I;
+ return (w);
+}
--- /dev/null
+/* $OpenBSD: s_catanh.c,v 1.6 2013/07/03 04:46:36 espie Exp $ */
+/*
+ * Copyright (c) 2008 Stephen L. Moshier <steve@moshier.net>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* catanh
+ *
+ * Complex inverse hyperbolic tangent
+ *
+ *
+ *
+ * SYNOPSIS:
+ *
+ * double complex catanh();
+ * double complex z, w;
+ *
+ * w = catanh (z);
+ *
+ *
+ *
+ * DESCRIPTION:
+ *
+ * Inverse tanh, equal to -i catan (iz);
+ *
+ * ACCURACY:
+ *
+ * Relative error:
+ * arithmetic domain # trials peak rms
+ * IEEE -10,+10 30000 2.3e-16 6.2e-17
+ *
+ */
+
+#include <float.h>
+#include <openlibm_complex.h>
+#include <openlibm_math.h>
+
+double complex
+catanh(double complex z)
+{
+ double complex w;
+
+ w = -1.0 * I * catan (z * I);
+ return (w);
+}
+
+#if LDBL_MANT_DIG == DBL_MANT_DIG
+__strong_alias(catanhl, catanh);
+#endif /* LDBL_MANT_DIG == DBL_MANT_DIG */
--- /dev/null
+/* $OpenBSD: s_catanhf.c,v 1.1 2008/09/07 20:36:09 martynas Exp $ */
+/*
+ * Copyright (c) 2008 Stephen L. Moshier <steve@moshier.net>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* catanhf
+ *
+ * Complex inverse hyperbolic tangent
+ *
+ *
+ *
+ * SYNOPSIS:
+ *
+ * float complex catanhf();
+ * float complex z, w;
+ *
+ * w = catanhf (z);
+ *
+ *
+ *
+ * DESCRIPTION:
+ *
+ * Inverse tanh, equal to -i catan (iz);
+ *
+ * ACCURACY:
+ *
+ * Relative error:
+ * arithmetic domain # trials peak rms
+ * IEEE -10,+10 30000 2.3e-16 6.2e-17
+ *
+ */
+
+#include <openlibm_complex.h>
+#include <openlibm_math.h>
+
+float complex
+catanhf(float complex z)
+{
+ float complex w;
+
+ w = -1.0f * I * catanf (z * I);
+ return (w);
+}
--- /dev/null
+/* $OpenBSD: s_catanhl.c,v 1.1 2011/07/08 19:25:31 martynas Exp $ */
+
+/*
+ * Copyright (c) 2008 Stephen L. Moshier <steve@moshier.net>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* catanhl
+ *
+ * Complex inverse hyperbolic tangent
+ *
+ *
+ *
+ * SYNOPSIS:
+ *
+ * long double complex catanhl();
+ * long double complex z, w;
+ *
+ * w = catanhl (z);
+ *
+ *
+ *
+ * DESCRIPTION:
+ *
+ * Inverse tanh, equal to -i catan (iz);
+ *
+ * ACCURACY:
+ *
+ * Relative error:
+ * arithmetic domain # trials peak rms
+ * IEEE -10,+10 30000 2.3e-16 6.2e-17
+ *
+ */
+
+#include <openlibm_complex.h>
+#include <openlibm_math.h>
+
+long double complex
+catanhl(long double complex z)
+{
+ long double complex w;
+
+ w = -1.0L * I * catanl(z * I);
+ return (w);
+}
--- /dev/null
+/* $OpenBSD: s_catanl.c,v 1.3 2011/07/20 21:02:51 martynas Exp $ */
+
+/*
+ * Copyright (c) 2008 Stephen L. Moshier <steve@moshier.net>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* catanl()
+ *
+ * Complex circular arc tangent
+ *
+ *
+ *
+ * SYNOPSIS:
+ *
+ * long double complex catanl();
+ * long double complex z, w;
+ *
+ * w = catanl( z );
+ *
+ *
+ *
+ * DESCRIPTION:
+ *
+ * If
+ * z = x + iy,
+ *
+ * then
+ * 1 ( 2x )
+ * Re w = - arctan(-----------) + k PI
+ * 2 ( 2 2)
+ * (1 - x - y )
+ *
+ * ( 2 2)
+ * 1 (x + (y+1) )
+ * Im w = - log(------------)
+ * 4 ( 2 2)
+ * (x + (y-1) )
+ *
+ * Where k is an arbitrary integer.
+ *
+ *
+ *
+ * ACCURACY:
+ *
+ * Relative error:
+ * arithmetic domain # trials peak rms
+ * DEC -10,+10 5900 1.3e-16 7.8e-18
+ * IEEE -10,+10 30000 2.3e-15 8.5e-17
+ * The check catan( ctan(z) ) = z, with |x| and |y| < PI/2,
+ * had peak relative error 1.5e-16, rms relative error
+ * 2.9e-17. See also clog().
+ */
+
+#include <float.h>
+#include <openlibm_complex.h>
+#include <openlibm_math.h>
+
+static const long double PIL = 3.141592653589793238462643383279502884197169L;
+static const long double DP1 = 3.14159265358979323829596852490908531763125L;
+static const long double DP2 = 1.6667485837041756656403424829301998703007e-19L;
+static const long double DP3 = 1.8830410776607851167459095484560349402753e-39L;
+
+static long double
+redupil(long double x)
+{
+ long double t;
+ long i;
+
+ t = x / PIL;
+ if (t >= 0.0L)
+ t += 0.5L;
+ else
+ t -= 0.5L;
+
+ i = t; /* the multiple */
+ t = i;
+ t = ((x - t * DP1) - t * DP2) - t * DP3;
+ return (t);
+}
+
+long double complex
+catanl(long double complex z)
+{
+ long double complex w;
+ long double a, t, x, x2, y;
+
+ x = creall(z);
+ y = cimagl(z);
+
+ if ((x == 0.0L) && (y > 1.0L))
+ goto ovrf;
+
+ x2 = x * x;
+ a = 1.0L - x2 - (y * y);
+ if (a == 0.0L)
+ goto ovrf;
+
+ t = atan2l(2.0L * x, a) * 0.5L;
+ w = redupil(t);
+
+ t = y - 1.0L;
+ a = x2 + (t * t);
+ if (a == 0.0L)
+ goto ovrf;
+
+ t = y + 1.0L;
+ a = (x2 + (t * t)) / a;
+ w = w + (0.25L * logl(a)) * I;
+ return (w);
+
+ovrf:
+ /*mtherr( "catanl", OVERFLOW );*/
+ w = LDBL_MAX + LDBL_MAX * I;
+ return (w);
+}
--- /dev/null
+/* @(#)s_cbrt.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ *
+ * Optimized by Bruce D. Evans.
+ */
+
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/src/s_cbrt.c,v 1.17 2011/03/12 16:50:39 kargl Exp $");
+
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+/* cbrt(x)
+ * Return cube root of x
+ */
+static const u_int32_t
+ B1 = 715094163, /* B1 = (1023-1023/3-0.03306235651)*2**20 */
+ B2 = 696219795; /* B2 = (1023-1023/3-54/3-0.03306235651)*2**20 */
+
+/* |1/cbrt(x) - p(x)| < 2**-23.5 (~[-7.93e-8, 7.929e-8]). */
+static const double
+P0 = 1.87595182427177009643, /* 0x3ffe03e6, 0x0f61e692 */
+P1 = -1.88497979543377169875, /* 0xbffe28e0, 0x92f02420 */
+P2 = 1.621429720105354466140, /* 0x3ff9f160, 0x4a49d6c2 */
+P3 = -0.758397934778766047437, /* 0xbfe844cb, 0xbee751d9 */
+P4 = 0.145996192886612446982; /* 0x3fc2b000, 0xd4e4edd7 */
+
+OLM_DLLEXPORT double
+cbrt(double x)
+{
+ int32_t hx;
+ union {
+ double value;
+ u_int64_t bits;
+ } u;
+ double r,s,t=0.0,w;
+ u_int32_t sign;
+ u_int32_t high,low;
+
+ EXTRACT_WORDS(hx,low,x);
+ sign=hx&0x80000000; /* sign= sign(x) */
+ hx ^=sign;
+ if(hx>=0x7ff00000) return(x+x); /* cbrt(NaN,INF) is itself */
+
+ /*
+ * Rough cbrt to 5 bits:
+ * cbrt(2**e*(1+m) ~= 2**(e/3)*(1+(e%3+m)/3)
+ * where e is integral and >= 0, m is real and in [0, 1), and "/" and
+ * "%" are integer division and modulus with rounding towards minus
+ * infinity. The RHS is always >= the LHS and has a maximum relative
+ * error of about 1 in 16. Adding a bias of -0.03306235651 to the
+ * (e%3+m)/3 term reduces the error to about 1 in 32. With the IEEE
+ * floating point representation, for finite positive normal values,
+ * ordinary integer divison of the value in bits magically gives
+ * almost exactly the RHS of the above provided we first subtract the
+ * exponent bias (1023 for doubles) and later add it back. We do the
+ * subtraction virtually to keep e >= 0 so that ordinary integer
+ * division rounds towards minus infinity; this is also efficient.
+ */
+ if(hx<0x00100000) { /* zero or subnormal? */
+ if((hx|low)==0)
+ return(x); /* cbrt(0) is itself */
+ SET_HIGH_WORD(t,0x43500000); /* set t= 2**54 */
+ t*=x;
+ GET_HIGH_WORD(high,t);
+ INSERT_WORDS(t,sign|((high&0x7fffffff)/3+B2),0);
+ } else
+ INSERT_WORDS(t,sign|(hx/3+B1),0);
+
+ /*
+ * New cbrt to 23 bits:
+ * cbrt(x) = t*cbrt(x/t**3) ~= t*P(t**3/x)
+ * where P(r) is a polynomial of degree 4 that approximates 1/cbrt(r)
+ * to within 2**-23.5 when |r - 1| < 1/10. The rough approximation
+ * has produced t such than |t/cbrt(x) - 1| ~< 1/32, and cubing this
+ * gives us bounds for r = t**3/x.
+ *
+ * Try to optimize for parallel evaluation as in k_tanf.c.
+ */
+ r=(t*t)*(t/x);
+ t=t*((P0+r*(P1+r*P2))+((r*r)*r)*(P3+r*P4));
+
+ /*
+ * Round t away from zero to 23 bits (sloppily except for ensuring that
+ * the result is larger in magnitude than cbrt(x) but not much more than
+ * 2 23-bit ulps larger). With rounding towards zero, the error bound
+ * would be ~5/6 instead of ~4/6. With a maximum error of 2 23-bit ulps
+ * in the rounded t, the infinite-precision error in the Newton
+ * approximation barely affects third digit in the final error
+ * 0.667; the error in the rounded t can be up to about 3 23-bit ulps
+ * before the final error is larger than 0.667 ulps.
+ */
+ u.value=t;
+ u.bits=(u.bits+0x80000000)&0xffffffffc0000000ULL;
+ t=u.value;
+
+ /* one step Newton iteration to 53 bits with error < 0.667 ulps */
+ s=t*t; /* t*t is exact */
+ r=x/s; /* error <= 0.5 ulps; |r| < |t| */
+ w=t+t; /* t+t is exact */
+ r=(r-t)/(w+r); /* r-t is exact; w+r ~= 3*t */
+ t=t+t*r; /* error <= 0.5 + 0.5/3 + epsilon */
+
+ return(t);
+}
+
+#if (LDBL_MANT_DIG == 53)
+__weak_reference(cbrt, cbrtl);
+#endif
--- /dev/null
+/* s_cbrtf.c -- float version of s_cbrt.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ * Debugged and optimized by Bruce D. Evans.
+ */
+
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/src/s_cbrtf.c,v 1.18 2008/02/22 02:30:35 das Exp $");
+
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+/* cbrtf(x)
+ * Return cube root of x
+ */
+static const unsigned
+ B1 = 709958130, /* B1 = (127-127.0/3-0.03306235651)*2**23 */
+ B2 = 642849266; /* B2 = (127-127.0/3-24/3-0.03306235651)*2**23 */
+
+OLM_DLLEXPORT float
+cbrtf(float x)
+{
+ double r,T;
+ float t;
+ int32_t hx;
+ u_int32_t sign;
+ u_int32_t high;
+
+ GET_FLOAT_WORD(hx,x);
+ sign=hx&0x80000000; /* sign= sign(x) */
+ hx ^=sign;
+ if(hx>=0x7f800000) return(x+x); /* cbrt(NaN,INF) is itself */
+
+ /* rough cbrt to 5 bits */
+ if(hx<0x00800000) { /* zero or subnormal? */
+ if(hx==0)
+ return(x); /* cbrt(+-0) is itself */
+ SET_FLOAT_WORD(t,0x4b800000); /* set t= 2**24 */
+ t*=x;
+ GET_FLOAT_WORD(high,t);
+ SET_FLOAT_WORD(t,sign|((high&0x7fffffff)/3+B2));
+ } else
+ SET_FLOAT_WORD(t,sign|(hx/3+B1));
+
+ /*
+ * First step Newton iteration (solving t*t-x/t == 0) to 16 bits. In
+ * double precision so that its terms can be arranged for efficiency
+ * without causing overflow or underflow.
+ */
+ T=t;
+ r=T*T*T;
+ T=T*((double)x+x+r)/(x+r+r);
+
+ /*
+ * Second step Newton iteration to 47 bits. In double precision for
+ * efficiency and accuracy.
+ */
+ r=T*T*T;
+ T=T*((double)x+x+r)/(x+r+r);
+
+ /* rounding to 24 bits is perfect in round-to-nearest mode */
+ return(T);
+}
--- /dev/null
+/*-
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ * Copyright (c) 2009-2011, Bruce D. Evans, Steven G. Kargl, David Schultz.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ *
+ * The argument reduction and testing for exceptional cases was
+ * written by Steven G. Kargl with input from Bruce D. Evans
+ * and David A. Schultz.
+ */
+
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/src/s_cbrtl.c,v 1.1 2011/03/12 19:37:35 kargl Exp $");
+
+#include <float.h>
+#include <openlibm_math.h>
+// VBS
+//#include <ieeefp.h>
+
+#include "fpmath.h"
+#include "math_private.h"
+#if defined(__i386__)
+#include "i387/bsd_ieeefp.h"
+#endif
+
+#define BIAS (LDBL_MAX_EXP - 1)
+
+static const unsigned
+ B1 = 709958130; /* B1 = (127-127.0/3-0.03306235651)*2**23 */
+
+OLM_DLLEXPORT long double
+cbrtl(long double x)
+{
+ union IEEEl2bits u, v;
+ long double r, s, t, w;
+ double dr, dt, dx;
+ float ft, fx;
+ u_int32_t hx;
+ u_int16_t expsign;
+ int k;
+
+ u.e = x;
+ expsign = u.xbits.expsign;
+ k = expsign & 0x7fff;
+
+ /*
+ * If x = +-Inf, then cbrt(x) = +-Inf.
+ * If x = NaN, then cbrt(x) = NaN.
+ */
+ if (k == BIAS + LDBL_MAX_EXP)
+ return (x + x);
+
+#ifdef __i386__
+ fp_prec_t oprec;
+
+ oprec = fpgetprec();
+ if (oprec != FP_PE)
+ fpsetprec(FP_PE);
+#endif
+
+ if (k == 0) {
+ /* If x = +-0, then cbrt(x) = +-0. */
+ if ((u.bits.manh | u.bits.manl) == 0) {
+#ifdef __i386__
+ if (oprec != FP_PE)
+ fpsetprec(oprec);
+#endif
+ return (x);
+ }
+ /* Adjust subnormal numbers. */
+ u.e *= 0x1.0p514;
+ k = u.bits.exp;
+ k -= BIAS + 514;
+ } else
+ k -= BIAS;
+ u.xbits.expsign = BIAS;
+ v.e = 1;
+
+ x = u.e;
+ switch (k % 3) {
+ case 1:
+ case -2:
+ x = 2*x;
+ k--;
+ break;
+ case 2:
+ case -1:
+ x = 4*x;
+ k -= 2;
+ break;
+ }
+ v.xbits.expsign = (expsign & 0x8000) | (BIAS + k / 3);
+
+ /*
+ * The following is the guts of s_cbrtf, with the handling of
+ * special values removed and extra care for accuracy not taken,
+ * but with most of the extra accuracy not discarded.
+ */
+
+ /* ~5-bit estimate: */
+ fx = x;
+ GET_FLOAT_WORD(hx, fx);
+ SET_FLOAT_WORD(ft, ((hx & 0x7fffffff) / 3 + B1));
+
+ /* ~16-bit estimate: */
+ dx = x;
+ dt = ft;
+ dr = dt * dt * dt;
+ dt = dt * (dx + dx + dr) / (dx + dr + dr);
+
+ /* ~47-bit estimate: */
+ dr = dt * dt * dt;
+ dt = dt * (dx + dx + dr) / (dx + dr + dr);
+
+#if LDBL_MANT_DIG == 64
+ /*
+ * dt is cbrtl(x) to ~47 bits (after x has been reduced to 1 <= x < 8).
+ * Round it away from zero to 32 bits (32 so that t*t is exact, and
+ * away from zero for technical reasons).
+ */
+ volatile double vd2 = 0x1.0p32;
+ volatile double vd1 = 0x1.0p-31;
+ #define vd ((long double)vd2 + vd1)
+
+ t = dt + vd - 0x1.0p32;
+#elif LDBL_MANT_DIG == 113
+ /*
+ * Round dt away from zero to 47 bits. Since we don't trust the 47,
+ * add 2 47-bit ulps instead of 1 to round up. Rounding is slow and
+ * might be avoidable in this case, since on most machines dt will
+ * have been evaluated in 53-bit precision and the technical reasons
+ * for rounding up might not apply to either case in cbrtl() since
+ * dt is much more accurate than needed.
+ */
+ t = dt + 0x2.0p-46 + 0x1.0p60L - 0x1.0p60;
+#else
+#error "Unsupported long double format"
+#endif
+
+ /*
+ * Final step Newton iteration to 64 or 113 bits with
+ * error < 0.667 ulps
+ */
+ s=t*t; /* t*t is exact */
+ r=x/s; /* error <= 0.5 ulps; |r| < |t| */
+ w=t+t; /* t+t is exact */
+ r=(r-t)/(w+r); /* r-t is exact; w+r ~= 3*t */
+ t=t+t*r; /* error <= 0.5 + 0.5/3 + epsilon */
+
+ t *= v.e;
+#ifdef __i386__
+ if (oprec != FP_PE)
+ fpsetprec(oprec);
+#endif
+ return (t);
+}
--- /dev/null
+/* $OpenBSD: s_ccos.c,v 1.6 2013/07/03 04:46:36 espie Exp $ */
+/*
+ * Copyright (c) 2008 Stephen L. Moshier <steve@moshier.net>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* ccos()
+ *
+ * Complex circular cosine
+ *
+ *
+ *
+ * SYNOPSIS:
+ *
+ * double complex ccos();
+ * double complex z, w;
+ *
+ * w = ccos (z);
+ *
+ *
+ *
+ * DESCRIPTION:
+ *
+ * If
+ * z = x + iy,
+ *
+ * then
+ *
+ * w = cos x cosh y - i sin x sinh y.
+ *
+ *
+ *
+ * ACCURACY:
+ *
+ * Relative error:
+ * arithmetic domain # trials peak rms
+ * DEC -10,+10 8400 4.5e-17 1.3e-17
+ * IEEE -10,+10 30000 3.8e-16 1.0e-16
+ */
+
+#include <float.h>
+#include <openlibm_complex.h>
+#include <openlibm_math.h>
+
+/* calculate cosh and sinh */
+
+static void
+_cchsh(double x, double *c, double *s)
+{
+ double e, ei;
+
+ if (fabs(x) <= 0.5) {
+ *c = cosh(x);
+ *s = sinh(x);
+ }
+ else {
+ e = exp(x);
+ ei = 0.5/e;
+ e = 0.5 * e;
+ *s = e - ei;
+ *c = e + ei;
+ }
+}
+
+double complex
+ccos(double complex z)
+{
+ double complex w;
+ double ch, sh;
+
+ _cchsh( cimag(z), &ch, &sh );
+ w = cos(creal (z)) * ch - (sin (creal (z)) * sh) * I;
+ return (w);
+}
+
+#if LDBL_MANT_DIG == DBL_MANT_DIG
+__strong_alias(ccosl, ccos);
+#endif /* LDBL_MANT_DIG == DBL_MANT_DIG */
--- /dev/null
+/* $OpenBSD: s_ccosf.c,v 1.2 2010/07/18 18:42:26 guenther Exp $ */
+/*
+ * Copyright (c) 2008 Stephen L. Moshier <steve@moshier.net>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* ccosf()
+ *
+ * Complex circular cosine
+ *
+ *
+ *
+ * SYNOPSIS:
+ *
+ * void ccosf();
+ * cmplxf z, w;
+ *
+ * ccosf( &z, &w );
+ *
+ *
+ *
+ * DESCRIPTION:
+ *
+ * If
+ * z = x + iy,
+ *
+ * then
+ *
+ * w = cos x cosh y - i sin x sinh y.
+ *
+ *
+ *
+ * ACCURACY:
+ *
+ * Relative error:
+ * arithmetic domain # trials peak rms
+ * IEEE -10,+10 30000 1.8e-7 5.5e-8
+ */
+
+#include <openlibm_complex.h>
+#include <openlibm_math.h>
+
+/* calculate cosh and sinh */
+
+static void
+_cchshf(float xx, float *c, float *s)
+{
+ float x, e, ei;
+
+ x = xx;
+ if(fabsf(x) <= 0.5f) {
+ *c = coshf(x);
+ *s = sinhf(x);
+ }
+ else {
+ e = expf(x);
+ ei = 0.5f/e;
+ e = 0.5f * e;
+ *s = e - ei;
+ *c = e + ei;
+ }
+}
+
+float complex
+ccosf(float complex z)
+{
+ float complex w;
+ float ch, sh;
+
+ _cchshf( cimagf(z), &ch, &sh );
+ w = cosf( crealf(z) ) * ch + ( -sinf( crealf(z) ) * sh) * I;
+ return (w);
+}
--- /dev/null
+/*-
+ * Copyright (c) 2005 Bruce D. Evans and Steven G. Kargl
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice unmodified, this list of conditions, and the following
+ * disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Hyperbolic cosine of a complex argument z = x + i y.
+ *
+ * cosh(z) = cosh(x+iy)
+ * = cosh(x) cos(y) + i sinh(x) sin(y).
+ *
+ * Exceptional values are noted in the comments within the source code.
+ * These values and the return value were taken from n1124.pdf.
+ */
+
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/src/s_ccosh.c,v 1.2 2011/10/21 06:29:32 das Exp $");
+
+#include <openlibm_complex.h>
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+static const double huge = 0x1p1023;
+
+OLM_DLLEXPORT double complex
+ccosh(double complex z)
+{
+ double x, y, h;
+ int32_t hx, hy, ix, iy, lx, ly;
+
+ x = creal(z);
+ y = cimag(z);
+
+ EXTRACT_WORDS(hx, lx, x);
+ EXTRACT_WORDS(hy, ly, y);
+
+ ix = 0x7fffffff & hx;
+ iy = 0x7fffffff & hy;
+
+ /* Handle the nearly-non-exceptional cases where x and y are finite. */
+ if (ix < 0x7ff00000 && iy < 0x7ff00000) {
+ if ((iy | ly) == 0)
+ return (CMPLX(cosh(x), x * y));
+ if (ix < 0x40360000) /* small x: normal case */
+ return (CMPLX(cosh(x) * cos(y), sinh(x) * sin(y)));
+
+ /* |x| >= 22, so cosh(x) ~= exp(|x|) */
+ if (ix < 0x40862e42) {
+ /* x < 710: exp(|x|) won't overflow */
+ h = exp(fabs(x)) * 0.5;
+ return (CMPLX(h * cos(y), copysign(h, x) * sin(y)));
+ } else if (ix < 0x4096bbaa) {
+ /* x < 1455: scale to avoid overflow */
+ z = __ldexp_cexp(CMPLX(fabs(x), y), -1);
+ return (CMPLX(creal(z), cimag(z) * copysign(1, x)));
+ } else {
+ /* x >= 1455: the result always overflows */
+ h = huge * x;
+ return (CMPLX(h * h * cos(y), h * sin(y)));
+ }
+ }
+
+ /*
+ * cosh(+-0 +- I Inf) = dNaN + I sign(d(+-0, dNaN))0.
+ * The sign of 0 in the result is unspecified. Choice = normally
+ * the same as dNaN. Raise the invalid floating-point exception.
+ *
+ * cosh(+-0 +- I NaN) = d(NaN) + I sign(d(+-0, NaN))0.
+ * The sign of 0 in the result is unspecified. Choice = normally
+ * the same as d(NaN).
+ */
+ if ((ix | lx) == 0 && iy >= 0x7ff00000)
+ return (CMPLX(y - y, copysign(0, x * (y - y))));
+
+ /*
+ * cosh(+-Inf +- I 0) = +Inf + I (+-)(+-)0.
+ *
+ * cosh(NaN +- I 0) = d(NaN) + I sign(d(NaN, +-0))0.
+ * The sign of 0 in the result is unspecified.
+ */
+ if ((iy | ly) == 0 && ix >= 0x7ff00000) {
+ if (((hx & 0xfffff) | lx) == 0)
+ return (CMPLX(x * x, copysign(0, x) * y));
+ return (CMPLX(x * x, copysign(0, (x + x) * y)));
+ }
+
+ /*
+ * cosh(x +- I Inf) = dNaN + I dNaN.
+ * Raise the invalid floating-point exception for finite nonzero x.
+ *
+ * cosh(x + I NaN) = d(NaN) + I d(NaN).
+ * Optionally raises the invalid floating-point exception for finite
+ * nonzero x. Choice = don't raise (except for signaling NaNs).
+ */
+ if (ix < 0x7ff00000 && iy >= 0x7ff00000)
+ return (CMPLX(y - y, x * (y - y)));
+
+ /*
+ * cosh(+-Inf + I NaN) = +Inf + I d(NaN).
+ *
+ * cosh(+-Inf +- I Inf) = +Inf + I dNaN.
+ * The sign of Inf in the result is unspecified. Choice = always +.
+ * Raise the invalid floating-point exception.
+ *
+ * cosh(+-Inf + I y) = +Inf cos(y) +- I Inf sin(y)
+ */
+ if (ix >= 0x7ff00000 && ((hx & 0xfffff) | lx) == 0) {
+ if (iy >= 0x7ff00000)
+ return (CMPLX(x * x, x * (y - y)));
+ return (CMPLX((x * x) * cos(y), x * sin(y)));
+ }
+
+ /*
+ * cosh(NaN + I NaN) = d(NaN) + I d(NaN).
+ *
+ * cosh(NaN +- I Inf) = d(NaN) + I d(NaN).
+ * Optionally raises the invalid floating-point exception.
+ * Choice = raise.
+ *
+ * cosh(NaN + I y) = d(NaN) + I d(NaN).
+ * Optionally raises the invalid floating-point exception for finite
+ * nonzero y. Choice = don't raise (except for signaling NaNs).
+ */
+ return (CMPLX((x * x) * (y - y), (x + x) * (y - y)));
+}
+
+OLM_DLLEXPORT double complex
+ccos(double complex z)
+{
+
+ /* ccos(z) = ccosh(I * z) */
+ return (ccosh(CMPLX(-cimag(z), creal(z))));
+}
--- /dev/null
+/*-
+ * Copyright (c) 2005 Bruce D. Evans and Steven G. Kargl
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice unmodified, this list of conditions, and the following
+ * disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Hyperbolic cosine of a complex argument. See s_ccosh.c for details.
+ */
+
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/src/s_ccoshf.c,v 1.2 2011/10/21 06:29:32 das Exp $");
+
+#include <openlibm_complex.h>
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+static const float huge = 0x1p127;
+
+OLM_DLLEXPORT float complex
+ccoshf(float complex z)
+{
+ float x, y, h;
+ int32_t hx, hy, ix, iy;
+
+ x = crealf(z);
+ y = cimagf(z);
+
+ GET_FLOAT_WORD(hx, x);
+ GET_FLOAT_WORD(hy, y);
+
+ ix = 0x7fffffff & hx;
+ iy = 0x7fffffff & hy;
+
+ if (ix < 0x7f800000 && iy < 0x7f800000) {
+ if (iy == 0)
+ return (CMPLXF(coshf(x), x * y));
+ if (ix < 0x41100000) /* small x: normal case */
+ return (CMPLXF(coshf(x) * cosf(y), sinhf(x) * sinf(y)));
+
+ /* |x| >= 9, so cosh(x) ~= exp(|x|) */
+ if (ix < 0x42b17218) {
+ /* x < 88.7: expf(|x|) won't overflow */
+ h = expf(fabsf(x)) * 0.5f;
+ return (CMPLXF(h * cosf(y), copysignf(h, x) * sinf(y)));
+ } else if (ix < 0x4340b1e7) {
+ /* x < 192.7: scale to avoid overflow */
+ z = __ldexp_cexpf(CMPLXF(fabsf(x), y), -1);
+ return (CMPLXF(crealf(z), cimagf(z) * copysignf(1, x)));
+ } else {
+ /* x >= 192.7: the result always overflows */
+ h = huge * x;
+ return (CMPLXF(h * h * cosf(y), h * sinf(y)));
+ }
+ }
+
+ if (ix == 0 && iy >= 0x7f800000)
+ return (CMPLXF(y - y, copysignf(0, x * (y - y))));
+
+ if (iy == 0 && ix >= 0x7f800000) {
+ if ((hx & 0x7fffff) == 0)
+ return (CMPLXF(x * x, copysignf(0, x) * y));
+ return (CMPLXF(x * x, copysignf(0, (x + x) * y)));
+ }
+
+ if (ix < 0x7f800000 && iy >= 0x7f800000)
+ return (CMPLXF(y - y, x * (y - y)));
+
+ if (ix >= 0x7f800000 && (hx & 0x7fffff) == 0) {
+ if (iy >= 0x7f800000)
+ return (CMPLXF(x * x, x * (y - y)));
+ return (CMPLXF((x * x) * cosf(y), x * sinf(y)));
+ }
+
+ return (CMPLXF((x * x) * (y - y), (x + x) * (y - y)));
+}
+
+OLM_DLLEXPORT float complex
+ccosf(float complex z)
+{
+
+ return (ccoshf(CMPLXF(-cimagf(z), crealf(z))));
+}
--- /dev/null
+/* $OpenBSD: s_ccoshl.c,v 1.2 2011/07/20 19:28:33 martynas Exp $ */
+
+/*
+ * Copyright (c) 2008 Stephen L. Moshier <steve@moshier.net>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* ccoshl
+ *
+ * Complex hyperbolic cosine
+ *
+ *
+ *
+ * SYNOPSIS:
+ *
+ * long double complex ccoshl();
+ * long double complex z, w;
+ *
+ * w = ccoshl (z);
+ *
+ *
+ *
+ * DESCRIPTION:
+ *
+ * ccosh(z) = cosh x cos y + i sinh x sin y .
+ *
+ * ACCURACY:
+ *
+ * Relative error:
+ * arithmetic domain # trials peak rms
+ * IEEE -10,+10 30000 2.9e-16 8.1e-17
+ *
+ */
+
+#include <openlibm_complex.h>
+#include <openlibm_math.h>
+
+long double complex
+ccoshl(long double complex z)
+{
+ long double complex w;
+ long double x, y;
+
+ x = creall(z);
+ y = cimagl(z);
+ w = coshl(x) * cosl(y) + (sinhl(x) * sinl(y)) * I;
+ return (w);
+}
--- /dev/null
+/* $OpenBSD: s_ccosl.c,v 1.2 2011/07/20 19:28:33 martynas Exp $ */
+
+/*
+ * Copyright (c) 2008 Stephen L. Moshier <steve@moshier.net>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* ccosl()
+ *
+ * Complex circular cosine
+ *
+ *
+ *
+ * SYNOPSIS:
+ *
+ * long double complex ccosl();
+ * long double complex z, w;
+ *
+ * w = ccosl( z );
+ *
+ *
+ *
+ * DESCRIPTION:
+ *
+ * If
+ * z = x + iy,
+ *
+ * then
+ *
+ * w = cos x cosh y - i sin x sinh y.
+ *
+ *
+ *
+ * ACCURACY:
+ *
+ * Relative error:
+ * arithmetic domain # trials peak rms
+ * DEC -10,+10 8400 4.5e-17 1.3e-17
+ * IEEE -10,+10 30000 3.8e-16 1.0e-16
+ */
+
+#include <openlibm_complex.h>
+#include <openlibm_math.h>
+
+static void
+cchshl(long double x, long double *c, long double *s)
+{
+ long double e, ei;
+
+ if(fabsl(x) <= 0.5L) {
+ *c = coshl(x);
+ *s = sinhl(x);
+ } else {
+ e = expl(x);
+ ei = 0.5L/e;
+ e = 0.5L * e;
+ *s = e - ei;
+ *c = e + ei;
+ }
+}
+
+long double complex
+ccosl(long double complex z)
+{
+ long double complex w;
+ long double ch, sh;
+
+ cchshl(cimagl(z), &ch, &sh);
+ w = cosl(creall(z)) * ch + (-sinl(creall(z)) * sh) * I;
+ return (w);
+}
--- /dev/null
+/* @(#)s_ceil.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/src/s_ceil.c,v 1.11 2008/02/15 07:01:40 bde Exp $");
+
+/*
+ * ceil(x)
+ * Return x rounded toward -inf to integral value
+ * Method:
+ * Bit twiddling.
+ * Exception:
+ * Inexact flag raised if x not equal to ceil(x).
+ */
+
+#include <float.h>
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+static const double huge = 1.0e300;
+
+OLM_DLLEXPORT double
+ceil(double x)
+{
+ int32_t i0,i1,j0;
+ u_int32_t i,j;
+ EXTRACT_WORDS(i0,i1,x);
+ j0 = ((i0>>20)&0x7ff)-0x3ff;
+ if(j0<20) {
+ if(j0<0) { /* raise inexact if x != 0 */
+ if(huge+x>0.0) {/* return 0*sign(x) if |x|<1 */
+ if(i0<0) {i0=0x80000000;i1=0;}
+ else if((i0|i1)!=0) { i0=0x3ff00000;i1=0;}
+ }
+ } else {
+ i = (0x000fffff)>>j0;
+ if(((i0&i)|i1)==0) return x; /* x is integral */
+ if(huge+x>0.0) { /* raise inexact flag */
+ if(i0>0) i0 += (0x00100000)>>j0;
+ i0 &= (~i); i1=0;
+ }
+ }
+ } else if (j0>51) {
+ if(j0==0x400) return x+x; /* inf or NaN */
+ else return x; /* x is integral */
+ } else {
+ i = ((u_int32_t)(0xffffffff))>>(j0-20);
+ if((i1&i)==0) return x; /* x is integral */
+ if(huge+x>0.0) { /* raise inexact flag */
+ if(i0>0) {
+ if(j0==20) i0+=1;
+ else {
+ j = i1 + (1<<(52-j0));
+ if(j<i1) i0+=1; /* got a carry */
+ i1 = j;
+ }
+ }
+ i1 &= (~i);
+ }
+ }
+ INSERT_WORDS(x,i0,i1);
+ return x;
+}
+
+#if LDBL_MANT_DIG == 53
+__weak_reference(ceil, ceill);
+#endif
--- /dev/null
+/* s_ceilf.c -- float version of s_ceil.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/src/s_ceilf.c,v 1.8 2008/02/22 02:30:35 das Exp $");
+
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+static const float huge = 1.0e30;
+
+OLM_DLLEXPORT float
+ceilf(float x)
+{
+ int32_t i0,j0;
+ u_int32_t i;
+
+ GET_FLOAT_WORD(i0,x);
+ j0 = ((i0>>23)&0xff)-0x7f;
+ if(j0<23) {
+ if(j0<0) { /* raise inexact if x != 0 */
+ if(huge+x>(float)0.0) {/* return 0*sign(x) if |x|<1 */
+ if(i0<0) {i0=0x80000000;}
+ else if(i0!=0) { i0=0x3f800000;}
+ }
+ } else {
+ i = (0x007fffff)>>j0;
+ if((i0&i)==0) return x; /* x is integral */
+ if(huge+x>(float)0.0) { /* raise inexact flag */
+ if(i0>0) i0 += (0x00800000)>>j0;
+ i0 &= (~i);
+ }
+ }
+ } else {
+ if(j0==0x80) return x+x; /* inf or NaN */
+ else return x; /* x is integral */
+ }
+ SET_FLOAT_WORD(x,i0);
+ return x;
+}
--- /dev/null
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ *
+ * From: @(#)s_ceil.c 5.1 93/09/24
+ */
+
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/src/s_ceill.c,v 1.9 2008/02/14 15:10:33 bde Exp $");
+
+/*
+ * ceill(x)
+ * Return x rounded toward -inf to integral value
+ * Method:
+ * Bit twiddling.
+ * Exception:
+ * Inexact flag raised if x not equal to ceill(x).
+ */
+
+#include <float.h>
+#include <openlibm_math.h>
+#include <stdint.h>
+
+#include "fpmath.h"
+#include "math_private.h"
+
+#ifdef LDBL_IMPLICIT_NBIT
+#define MANH_SIZE (LDBL_MANH_SIZE + 1)
+#define INC_MANH(u, c) do { \
+ u_int64_t o = u.bits.manh; \
+ u.bits.manh += (c); \
+ if (u.bits.manh < o) \
+ u.bits.exp++; \
+} while (0)
+#else
+#define MANH_SIZE LDBL_MANH_SIZE
+#define INC_MANH(u, c) do { \
+ u_int64_t o = u.bits.manh; \
+ u.bits.manh += (c); \
+ if (u.bits.manh < o) { \
+ u.bits.exp++; \
+ u.bits.manh |= 1llu << (LDBL_MANH_SIZE - 1); \
+ } \
+} while (0)
+#endif
+
+static const long double huge = 1.0e300;
+
+OLM_DLLEXPORT long double
+ceill(long double x)
+{
+ union IEEEl2bits u = { .e = x };
+ int e = u.bits.exp - LDBL_MAX_EXP + 1;
+
+ if (e < MANH_SIZE - 1) {
+ if (e < 0) { /* raise inexact if x != 0 */
+ if (huge + x > 0.0)
+ if (u.bits.exp > 0 ||
+ (u.bits.manh | u.bits.manl) != 0)
+ u.e = u.bits.sign ? -0.0 : 1.0;
+ } else {
+ u_int64_t m = ((1llu << MANH_SIZE) - 1) >> (e + 1);
+ if (((u.bits.manh & m) | u.bits.manl) == 0)
+ return (x); /* x is integral */
+ if (!u.bits.sign) {
+#ifdef LDBL_IMPLICIT_NBIT
+ if (e == 0)
+ u.bits.exp++;
+ else
+#endif
+ INC_MANH(u, 1llu << (MANH_SIZE - e - 1));
+ }
+ if (huge + x > 0.0) { /* raise inexact flag */
+ u.bits.manh &= ~m;
+ u.bits.manl = 0;
+ }
+ }
+ } else if (e < LDBL_MANT_DIG - 1) {
+ u_int64_t m = (u_int64_t)-1 >> (64 - LDBL_MANT_DIG + e + 1);
+ if ((u.bits.manl & m) == 0)
+ return (x); /* x is integral */
+ if (!u.bits.sign) {
+ if (e == MANH_SIZE - 1)
+ INC_MANH(u, 1);
+ else {
+ u_int64_t o = u.bits.manl;
+ u.bits.manl += 1llu << (LDBL_MANT_DIG - e - 1);
+ if (u.bits.manl < o) /* got a carry */
+ INC_MANH(u, 1);
+ }
+ }
+ if (huge + x > 0.0) /* raise inexact flag */
+ u.bits.manl &= ~m;
+ }
+ return (u.e);
+}
--- /dev/null
+/*-
+ * Copyright (c) 2011 David Schultz <das@FreeBSD.ORG>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/src/s_cexp.c,v 1.3 2011/10/21 06:27:56 das Exp $");
+
+#include <openlibm_complex.h>
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+static const u_int32_t
+exp_ovfl = 0x40862e42, /* high bits of MAX_EXP * ln2 ~= 710 */
+cexp_ovfl = 0x4096b8e4; /* (MAX_EXP - MIN_DENORM_EXP) * ln2 */
+
+OLM_DLLEXPORT double complex
+cexp(double complex z)
+{
+ double x, y, exp_x;
+ u_int32_t hx, hy, lx, ly;
+
+ x = creal(z);
+ y = cimag(z);
+
+ EXTRACT_WORDS(hy, ly, y);
+ hy &= 0x7fffffff;
+
+ /* cexp(x + I 0) = exp(x) + I 0 */
+ if ((hy | ly) == 0)
+ return (CMPLX(exp(x), y));
+ EXTRACT_WORDS(hx, lx, x);
+ /* cexp(0 + I y) = cos(y) + I sin(y) */
+ if (((hx & 0x7fffffff) | lx) == 0)
+ return (CMPLX(cos(y), sin(y)));
+
+ if (hy >= 0x7ff00000) {
+ if (lx != 0 || (hx & 0x7fffffff) != 0x7ff00000) {
+ /* cexp(finite|NaN +- I Inf|NaN) = NaN + I NaN */
+ return (CMPLX(y - y, y - y));
+ } else if (hx & 0x80000000) {
+ /* cexp(-Inf +- I Inf|NaN) = 0 + I 0 */
+ return (CMPLX(0.0, 0.0));
+ } else {
+ /* cexp(+Inf +- I Inf|NaN) = Inf + I NaN */
+ return (CMPLX(x, y - y));
+ }
+ }
+
+ if (hx >= exp_ovfl && hx <= cexp_ovfl) {
+ /*
+ * x is between 709.7 and 1454.3, so we must scale to avoid
+ * overflow in exp(x).
+ */
+ return (__ldexp_cexp(z, 0));
+ } else {
+ /*
+ * Cases covered here:
+ * - x < exp_ovfl and exp(x) won't overflow (common case)
+ * - x > cexp_ovfl, so exp(x) * s overflows for all s > 0
+ * - x = +-Inf (generated by exp())
+ * - x = NaN (spurious inexact exception from y)
+ */
+ exp_x = exp(x);
+ return (CMPLX(exp_x * cos(y), exp_x * sin(y)));
+ }
+}
--- /dev/null
+/*-
+ * Copyright (c) 2011 David Schultz <das@FreeBSD.ORG>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/src/s_cexpf.c,v 1.3 2011/10/21 06:27:56 das Exp $");
+
+#include <openlibm_complex.h>
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+static const u_int32_t
+exp_ovfl = 0x42b17218, /* MAX_EXP * ln2 ~= 88.722839355 */
+cexp_ovfl = 0x43400074; /* (MAX_EXP - MIN_DENORM_EXP) * ln2 */
+
+OLM_DLLEXPORT float complex
+cexpf(float complex z)
+{
+ float x, y, exp_x;
+ u_int32_t hx, hy;
+
+ x = crealf(z);
+ y = cimagf(z);
+
+ GET_FLOAT_WORD(hy, y);
+ hy &= 0x7fffffff;
+
+ /* cexp(x + I 0) = exp(x) + I 0 */
+ if (hy == 0)
+ return (CMPLXF(expf(x), y));
+ GET_FLOAT_WORD(hx, x);
+ /* cexp(0 + I y) = cos(y) + I sin(y) */
+ if ((hx & 0x7fffffff) == 0)
+ return (CMPLXF(cosf(y), sinf(y)));
+
+ if (hy >= 0x7f800000) {
+ if ((hx & 0x7fffffff) != 0x7f800000) {
+ /* cexp(finite|NaN +- I Inf|NaN) = NaN + I NaN */
+ return (CMPLXF(y - y, y - y));
+ } else if (hx & 0x80000000) {
+ /* cexp(-Inf +- I Inf|NaN) = 0 + I 0 */
+ return (CMPLXF(0.0, 0.0));
+ } else {
+ /* cexp(+Inf +- I Inf|NaN) = Inf + I NaN */
+ return (CMPLXF(x, y - y));
+ }
+ }
+
+ if (hx >= exp_ovfl && hx <= cexp_ovfl) {
+ /*
+ * x is between 88.7 and 192, so we must scale to avoid
+ * overflow in expf(x).
+ */
+ return (__ldexp_cexpf(z, 0));
+ } else {
+ /*
+ * Cases covered here:
+ * - x < exp_ovfl and exp(x) won't overflow (common case)
+ * - x > cexp_ovfl, so exp(x) * s overflows for all s > 0
+ * - x = +-Inf (generated by exp())
+ * - x = NaN (spurious inexact exception from y)
+ */
+ exp_x = expf(x);
+ return (CMPLXF(exp_x * cosf(y), exp_x * sinf(y)));
+ }
+}
--- /dev/null
+/* $OpenBSD: s_cexpl.c,v 1.2 2011/07/20 19:28:33 martynas Exp $ */
+
+/*
+ * Copyright (c) 2008 Stephen L. Moshier <steve@moshier.net>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* cexpl()
+ *
+ * Complex exponential function
+ *
+ *
+ *
+ * SYNOPSIS:
+ *
+ * long double complex cexpl();
+ * long double complex z, w;
+ *
+ * w = cexpl( z );
+ *
+ *
+ *
+ * DESCRIPTION:
+ *
+ * Returns the exponential of the complex argument z
+ * into the complex result w.
+ *
+ * If
+ * z = x + iy,
+ * r = exp(x),
+ *
+ * then
+ *
+ * w = r cos y + i r sin y.
+ *
+ *
+ * ACCURACY:
+ *
+ * Relative error:
+ * arithmetic domain # trials peak rms
+ * DEC -10,+10 8700 3.7e-17 1.1e-17
+ * IEEE -10,+10 30000 3.0e-16 8.7e-17
+ *
+ */
+
+#include <openlibm_complex.h>
+#include <openlibm_math.h>
+
+long double complex
+cexpl(long double complex z)
+{
+ long double complex w;
+ long double r;
+
+ r = expl(creall(z));
+ w = r * cosl(cimagl(z)) + (r * sinl(cimagl(z))) * I;
+ return (w);
+}
--- /dev/null
+/*-
+ * Copyright (c) 2004 Stefan Farfeleder
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: src/lib/msun/src/s_cimag.c,v 1.3 2009/03/14 18:24:15 das Exp $
+ */
+
+#include <openlibm_complex.h>
+
+#include "math_private.h"
+
+OLM_DLLEXPORT double
+cimag(double complex z)
+{
+ return (__imag__ z);
+}
--- /dev/null
+/*-
+ * Copyright (c) 2004 Stefan Farfeleder
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: src/lib/msun/src/s_cimagf.c,v 1.3 2009/03/14 18:24:15 das Exp $
+ */
+
+#include <openlibm_complex.h>
+
+#include "math_private.h"
+
+OLM_DLLEXPORT float
+cimagf(float complex z)
+{
+ return (__imag__ z);
+}
--- /dev/null
+/*-
+ * Copyright (c) 2004 Stefan Farfeleder
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: src/lib/msun/src/s_cimagl.c,v 1.3 2009/03/14 18:24:15 das Exp $
+ */
+
+#include <openlibm_complex.h>
+
+#include "math_private.h"
+
+OLM_DLLEXPORT long double
+cimagl(long double complex z)
+{
+ return (__imag__ z);
+}
--- /dev/null
+/* $OpenBSD: s_clog.c,v 1.6 2013/07/03 04:46:36 espie Exp $ */
+/*
+ * Copyright (c) 2008 Stephen L. Moshier <steve@moshier.net>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* clog.c
+ *
+ * Complex natural logarithm
+ *
+ *
+ *
+ * SYNOPSIS:
+ *
+ * double complex clog();
+ * double complex z, w;
+ *
+ * w = clog (z);
+ *
+ *
+ *
+ * DESCRIPTION:
+ *
+ * Returns complex logarithm to the base e (2.718...) of
+ * the complex argument x.
+ *
+ * If z = x + iy, r = sqrt( x**2 + y**2 ),
+ * then
+ * w = log(r) + i arctan(y/x).
+ *
+ * The arctangent ranges from -PI to +PI.
+ *
+ *
+ * ACCURACY:
+ *
+ * Relative error:
+ * arithmetic domain # trials peak rms
+ * DEC -10,+10 7000 8.5e-17 1.9e-17
+ * IEEE -10,+10 30000 5.0e-15 1.1e-16
+ *
+ * Larger relative error can be observed for z near 1 +i0.
+ * In IEEE arithmetic the peak absolute error is 5.2e-16, rms
+ * absolute error 1.0e-16.
+ */
+
+#include <float.h>
+#include <openlibm_complex.h>
+#include <openlibm_math.h>
+
+double complex
+clog(double complex z)
+{
+ double complex w;
+ double p, rr;
+
+ /*rr = sqrt( z->r * z->r + z->i * z->i );*/
+ rr = cabs(z);
+ p = log(rr);
+ rr = atan2 (cimag (z), creal (z));
+ w = p + rr * I;
+ return (w);
+}
+
+#if LDBL_MANT_DIG == DBL_MANT_DIG
+__strong_alias(clogl, clog);
+#endif /* LDBL_MANT_DIG == DBL_MANT_DIG */
--- /dev/null
+/* $OpenBSD: s_clogf.c,v 1.2 2010/07/18 18:42:26 guenther Exp $ */
+/*
+ * Copyright (c) 2008 Stephen L. Moshier <steve@moshier.net>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* clogf.c
+ *
+ * Complex natural logarithm
+ *
+ *
+ *
+ * SYNOPSIS:
+ *
+ * void clogf();
+ * cmplxf z, w;
+ *
+ * clogf( &z, &w );
+ *
+ *
+ *
+ * DESCRIPTION:
+ *
+ * Returns complex logarithm to the base e (2.718...) of
+ * the complex argument x.
+ *
+ * If z = x + iy, r = sqrt( x**2 + y**2 ),
+ * then
+ * w = log(r) + i arctan(y/x).
+ *
+ * The arctangent ranges from -PI to +PI.
+ *
+ *
+ * ACCURACY:
+ *
+ * Relative error:
+ * arithmetic domain # trials peak rms
+ * IEEE -10,+10 30000 1.9e-6 6.2e-8
+ *
+ * Larger relative error can be observed for z near 1 +i0.
+ * In IEEE arithmetic the peak absolute error is 3.1e-7.
+ *
+ */
+
+#include <openlibm_complex.h>
+#include <openlibm_math.h>
+
+float complex
+clogf(float complex z)
+{
+ float complex w;
+ float p, rr, x, y;
+
+ x = crealf(z);
+ y = cimagf(z);
+ rr = atan2f(y, x);
+ p = cabsf(z);
+ p = logf(p);
+ w = p + rr * I;
+ return (w);
+}
--- /dev/null
+/* $OpenBSD: s_clogl.c,v 1.2 2011/07/20 19:28:33 martynas Exp $ */
+
+/*
+ * Copyright (c) 2008 Stephen L. Moshier <steve@moshier.net>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* clogl.c
+ *
+ * Complex natural logarithm
+ *
+ *
+ *
+ * SYNOPSIS:
+ *
+ * long double complex clogl();
+ * long double complex z, w;
+ *
+ * w = clogl( z );
+ *
+ *
+ *
+ * DESCRIPTION:
+ *
+ * Returns complex logarithm to the base e (2.718...) of
+ * the complex argument x.
+ *
+ * If z = x + iy, r = sqrt( x**2 + y**2 ),
+ * then
+ * w = log(r) + i arctan(y/x).
+ *
+ * The arctangent ranges from -PI to +PI.
+ *
+ *
+ * ACCURACY:
+ *
+ * Relative error:
+ * arithmetic domain # trials peak rms
+ * DEC -10,+10 7000 8.5e-17 1.9e-17
+ * IEEE -10,+10 30000 5.0e-15 1.1e-16
+ *
+ * Larger relative error can be observed for z near 1 +i0.
+ * In IEEE arithmetic the peak absolute error is 5.2e-16, rms
+ * absolute error 1.0e-16.
+ */
+
+#include <openlibm_complex.h>
+#include <openlibm_math.h>
+
+long double complex
+clogl(long double complex z)
+{
+ long double complex w;
+ long double p, rr;
+
+ /*rr = sqrt(z->r * z->r + z->i * z->i);*/
+ p = cabsl(z);
+ p = logl(p);
+ rr = atan2l(cimagl(z), creall(z));
+ w = p + rr * I;
+ return (w);
+}
--- /dev/null
+/*-
+ * Copyright (c) 2004 Stefan Farfeleder
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: src/lib/msun/src/s_conj.c,v 1.2 2008/08/07 14:39:56 das Exp $
+ */
+
+#include <openlibm_complex.h>
+
+#include "math_private.h"
+
+OLM_DLLEXPORT double complex
+conj(double complex z)
+{
+
+ return (CMPLX(creal(z), -cimag(z)));
+}
--- /dev/null
+/*-
+ * Copyright (c) 2004 Stefan Farfeleder
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: src/lib/msun/src/s_conjf.c,v 1.2 2008/08/07 14:39:56 das Exp $
+ */
+
+#include <openlibm_complex.h>
+
+#include "math_private.h"
+
+OLM_DLLEXPORT float complex
+conjf(float complex z)
+{
+
+ return (CMPLXF(crealf(z), -cimagf(z)));
+}
--- /dev/null
+/*-
+ * Copyright (c) 2004 Stefan Farfeleder
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: src/lib/msun/src/s_conjl.c,v 1.2 2008/08/07 14:39:56 das Exp $
+ */
+
+#include <openlibm_complex.h>
+
+#include "math_private.h"
+
+OLM_DLLEXPORT long double complex
+conjl(long double complex z)
+{
+
+ return (CMPLXL(creall(z), -cimagl(z)));
+}
--- /dev/null
+/* @(#)s_copysign.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/src/s_copysign.c,v 1.10 2008/02/22 02:30:35 das Exp $");
+
+/*
+ * copysign(double x, double y)
+ * copysign(x,y) returns a value with the magnitude of x and
+ * with the sign bit of y.
+ */
+
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+OLM_DLLEXPORT double
+copysign(double x, double y)
+{
+ u_int32_t hx,hy;
+ GET_HIGH_WORD(hx,x);
+ GET_HIGH_WORD(hy,y);
+ SET_HIGH_WORD(x,(hx&0x7fffffff)|(hy&0x80000000));
+ return x;
+}
--- /dev/null
+/* s_copysignf.c -- float version of s_copysign.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/src/s_copysignf.c,v 1.10 2008/02/22 02:30:35 das Exp $");
+
+/*
+ * copysignf(float x, float y)
+ * copysignf(x,y) returns a value with the magnitude of x and
+ * with the sign bit of y.
+ */
+
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+OLM_DLLEXPORT float
+copysignf(float x, float y)
+{
+ u_int32_t ix,iy;
+ GET_FLOAT_WORD(ix,x);
+ GET_FLOAT_WORD(iy,y);
+ SET_FLOAT_WORD(x,(ix&0x7fffffff)|(iy&0x80000000));
+ return x;
+}
--- /dev/null
+/*-
+ * Copyright (c) 2004 Stefan Farfeleder
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: src/lib/msun/src/s_copysignl.c,v 1.2 2007/01/07 07:54:21 das Exp $
+ */
+
+#include <openlibm_math.h>
+
+#include "fpmath.h"
+#include "math_private.h"
+
+OLM_DLLEXPORT long double
+copysignl(long double x, long double y)
+{
+ union IEEEl2bits ux, uy;
+
+ ux.e = x;
+ uy.e = y;
+ ux.bits.sign = uy.bits.sign;
+ return (ux.e);
+}
--- /dev/null
+/* @(#)s_cos.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/src/s_cos.c,v 1.13 2011/02/10 07:37:50 das Exp $");
+
+/* cos(x)
+ * Return cosine function of x.
+ *
+ * kernel function:
+ * __kernel_sin ... sine function on [-pi/4,pi/4]
+ * __kernel_cos ... cosine function on [-pi/4,pi/4]
+ * __ieee754_rem_pio2 ... argument reduction routine
+ *
+ * Method.
+ * Let S,C and T denote the sin, cos and tan respectively on
+ * [-PI/4, +PI/4]. Reduce the argument x to y1+y2 = x-k*pi/2
+ * in [-pi/4 , +pi/4], and let n = k mod 4.
+ * We have
+ *
+ * n sin(x) cos(x) tan(x)
+ * ----------------------------------------------------------
+ * 0 S C T
+ * 1 C -S -1/T
+ * 2 -S -C T
+ * 3 -C S -1/T
+ * ----------------------------------------------------------
+ *
+ * Special cases:
+ * Let trig be any of sin, cos, or tan.
+ * trig(+-INF) is NaN, with signals;
+ * trig(NaN) is that NaN;
+ *
+ * Accuracy:
+ * TRIG(x) returns trig(x) nearly rounded
+ */
+
+#include <float.h>
+#include <openlibm_math.h>
+
+//#define INLINE_REM_PIO2
+#include "math_private.h"
+//#include "e_rem_pio2.c"
+
+OLM_DLLEXPORT double
+cos(double x)
+{
+ double y[2],z=0.0;
+ int32_t n, ix;
+
+ /* High word of x. */
+ GET_HIGH_WORD(ix,x);
+
+ /* |x| ~< pi/4 */
+ ix &= 0x7fffffff;
+ if(ix <= 0x3fe921fb) {
+ if(ix<0x3e46a09e) /* if x < 2**-27 * sqrt(2) */
+ if(((int)x)==0) return 1.0; /* generate inexact */
+ return __kernel_cos(x,z);
+ }
+
+ /* cos(Inf or NaN) is NaN */
+ else if (ix>=0x7ff00000) return x-x;
+
+ /* argument reduction needed */
+ else {
+ n = __ieee754_rem_pio2(x,y);
+ switch(n&3) {
+ case 0: return __kernel_cos(y[0],y[1]);
+ case 1: return -__kernel_sin(y[0],y[1],1);
+ case 2: return -__kernel_cos(y[0],y[1]);
+ default:
+ return __kernel_sin(y[0],y[1],1);
+ }
+ }
+}
+
+#if (LDBL_MANT_DIG == 53)
+__weak_reference(cos, cosl);
+#endif
--- /dev/null
+/* s_cosf.c -- float version of s_cos.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ * Optimized by Bruce D. Evans.
+ */
+
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/src/s_cosf.c,v 1.18 2008/02/25 22:19:17 bde Exp $");
+
+#include <float.h>
+#include <openlibm_math.h>
+
+//#define INLINE_KERNEL_COSDF
+//#define INLINE_KERNEL_SINDF
+//#define INLINE_REM_PIO2F
+#include "math_private.h"
+//#include "e_rem_pio2f.c"
+//#include "k_cosf.c"
+//#include "k_sinf.c"
+
+/* Small multiples of pi/2 rounded to double precision. */
+static const double
+c1pio2 = 1*M_PI_2, /* 0x3FF921FB, 0x54442D18 */
+c2pio2 = 2*M_PI_2, /* 0x400921FB, 0x54442D18 */
+c3pio2 = 3*M_PI_2, /* 0x4012D97C, 0x7F3321D2 */
+c4pio2 = 4*M_PI_2; /* 0x401921FB, 0x54442D18 */
+
+OLM_DLLEXPORT float
+cosf(float x)
+{
+ double y;
+ int32_t n, hx, ix;
+
+ GET_FLOAT_WORD(hx,x);
+ ix = hx & 0x7fffffff;
+
+ if(ix <= 0x3f490fda) { /* |x| ~<= pi/4 */
+ if(ix<0x39800000) /* |x| < 2**-12 */
+ if(((int)x)==0) return 1.0; /* 1 with inexact if x != 0 */
+ return __kernel_cosdf(x);
+ }
+ if(ix<=0x407b53d1) { /* |x| ~<= 5*pi/4 */
+ if(ix<=0x4016cbe3) { /* |x| ~> 3*pi/4 */
+ if(hx>0)
+ return __kernel_sindf(c1pio2 - x);
+ else
+ return __kernel_sindf(x + c1pio2);
+ } else
+ return -__kernel_cosdf(x + (hx > 0 ? -c2pio2 : c2pio2));
+ }
+ if(ix<=0x40e231d5) { /* |x| ~<= 9*pi/4 */
+ if(ix<=0x40afeddf) { /* |x| ~> 7*pi/4 */
+ if(hx>0)
+ return __kernel_sindf(x - c3pio2);
+ else
+ return __kernel_sindf(-c3pio2 - x);
+ } else
+ return __kernel_cosdf(x + (hx > 0 ? -c4pio2 : c4pio2));
+ }
+
+ /* cos(Inf or NaN) is NaN */
+ else if (ix>=0x7f800000) return x-x;
+
+ /* general argument reduction needed */
+ else {
+ n = __ieee754_rem_pio2f(x,&y);
+ switch(n&3) {
+ case 0: return __kernel_cosdf(y);
+ case 1: return __kernel_sindf(-y);
+ case 2: return -__kernel_cosdf(y);
+ default:
+ return __kernel_sindf(y);
+ }
+ }
+}
--- /dev/null
+/*-
+ * Copyright (c) 2007 Steven G. Kargl
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice unmodified, this list of conditions, and the following
+ * disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/src/s_cosl.c,v 1.3 2011/05/30 19:41:28 kargl Exp $");
+
+/*
+ * Limited testing on pseudorandom numbers drawn within [-2e8:4e8] shows
+ * an accuracy of <= 0.7412 ULP.
+ */
+
+#include <float.h>
+#include <openlibm_math.h>
+
+#include "math_private.h"
+#if LDBL_MANT_DIG == 64
+#include "../ld80/e_rem_pio2l.h"
+#elif LDBL_MANT_DIG == 113
+#include "../ld128/e_rem_pio2l.h"
+#else
+#error "Unsupported long double format"
+#endif
+
+OLM_DLLEXPORT long double
+cosl(long double x)
+{
+ union IEEEl2bits z;
+ int e0;
+ long double y[2];
+ long double hi, lo;
+
+ z.e = x;
+ z.bits.sign = 0;
+
+ /* If x = +-0 or x is a subnormal number, then cos(x) = 1 */
+ if (z.bits.exp == 0)
+ return (1.0);
+
+ /* If x = NaN or Inf, then cos(x) = NaN. */
+ if (z.bits.exp == 32767)
+ return ((x - x) / (x - x));
+
+ /* Optimize the case where x is already within range. */
+ if (z.e < M_PI_4)
+ return (__kernel_cosl(z.e, 0));
+
+ e0 = __ieee754_rem_pio2l(x, y);
+ hi = y[0];
+ lo = y[1];
+
+ switch (e0 & 3) {
+ case 0:
+ hi = __kernel_cosl(hi, lo);
+ break;
+ case 1:
+ hi = - __kernel_sinl(hi, lo, 1);
+ break;
+ case 2:
+ hi = - __kernel_cosl(hi, lo);
+ break;
+ case 3:
+ hi = __kernel_sinl(hi, lo, 1);
+ break;
+ }
+
+ return (hi);
+}
--- /dev/null
+/* $OpenBSD: s_cpow.c,v 1.6 2013/07/03 04:46:36 espie Exp $ */
+/*
+ * Copyright (c) 2008 Stephen L. Moshier <steve@moshier.net>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* cpow
+ *
+ * Complex power function
+ *
+ *
+ *
+ * SYNOPSIS:
+ *
+ * double complex cpow();
+ * double complex a, z, w;
+ *
+ * w = cpow (a, z);
+ *
+ *
+ *
+ * DESCRIPTION:
+ *
+ * Raises complex A to the complex Zth power.
+ * Definition is per AMS55 # 4.2.8,
+ * analytically equivalent to cpow(a,z) = cexp(z clog(a)).
+ *
+ * ACCURACY:
+ *
+ * Relative error:
+ * arithmetic domain # trials peak rms
+ * IEEE -10,+10 30000 9.4e-15 1.5e-15
+ *
+ */
+
+#include <float.h>
+#include <openlibm_complex.h>
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+OLM_DLLEXPORT double complex
+cpow(double complex a, double complex z)
+{
+ double complex w;
+ double x, y, r, theta, absa, arga;
+
+ x = creal (z);
+ y = cimag (z);
+ absa = cabs (a);
+ if (absa == 0.0) {
+ return (0.0 + 0.0 * I);
+ }
+ arga = carg (a);
+ r = pow (absa, x);
+ theta = x * arga;
+ if (y != 0.0) {
+ r = r * exp (-y * arga);
+ theta = theta + y * log (absa);
+ }
+ w = r * cos (theta) + (r * sin (theta)) * I;
+ return (w);
+}
+
+#if LDBL_MANT_DIG == DBL_MANT_DIG
+__strong_alias(cpowl, cpow);
+#endif /* LDBL_MANT_DIG == DBL_MANT_DIG */
--- /dev/null
+/* $OpenBSD: s_cpowf.c,v 1.2 2010/07/18 18:42:26 guenther Exp $ */
+/*
+ * Copyright (c) 2008 Stephen L. Moshier <steve@moshier.net>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* cpowf
+ *
+ * Complex power function
+ *
+ *
+ *
+ * SYNOPSIS:
+ *
+ * float complex cpowf();
+ * float complex a, z, w;
+ *
+ * w = cpowf (a, z);
+ *
+ *
+ *
+ * DESCRIPTION:
+ *
+ * Raises complex A to the complex Zth power.
+ * Definition is per AMS55 # 4.2.8,
+ * analytically equivalent to cpow(a,z) = cexp(z clog(a)).
+ *
+ * ACCURACY:
+ *
+ * Relative error:
+ * arithmetic domain # trials peak rms
+ * IEEE -10,+10 30000 9.4e-15 1.5e-15
+ *
+ */
+
+#include <openlibm_complex.h>
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+OLM_DLLEXPORT float complex
+cpowf(float complex a, float complex z)
+{
+ float complex w;
+ float x, y, r, theta, absa, arga;
+
+ x = crealf(z);
+ y = cimagf(z);
+ absa = cabsf (a);
+ if (absa == 0.0f) {
+ return (0.0f + 0.0f * I);
+ }
+ arga = cargf (a);
+ r = powf (absa, x);
+ theta = x * arga;
+ if (y != 0.0f) {
+ r = r * expf (-y * arga);
+ theta = theta + y * logf (absa);
+ }
+ w = r * cosf (theta) + (r * sinf (theta)) * I;
+ return (w);
+}
--- /dev/null
+/* $OpenBSD: s_cpowl.c,v 1.2 2011/07/20 19:28:33 martynas Exp $ */
+
+/*
+ * Copyright (c) 2008 Stephen L. Moshier <steve@moshier.net>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* cpowl
+ *
+ * Complex power function
+ *
+ *
+ *
+ * SYNOPSIS:
+ *
+ * long double complex cpowl();
+ * long double complex a, z, w;
+ *
+ * w = cpowl (a, z);
+ *
+ *
+ *
+ * DESCRIPTION:
+ *
+ * Raises complex A to the complex Zth power.
+ * Definition is per AMS55 # 4.2.8,
+ * analytically equivalent to cpow(a,z) = cexp(z clog(a)).
+ *
+ * ACCURACY:
+ *
+ * Relative error:
+ * arithmetic domain # trials peak rms
+ * IEEE -10,+10 30000 9.4e-15 1.5e-15
+ *
+ */
+
+#include <openlibm_complex.h>
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+OLM_DLLEXPORT long double complex
+cpowl(long double complex a, long double complex z)
+{
+ long double complex w;
+ long double x, y, r, theta, absa, arga;
+
+ x = creall(z);
+ y = cimagl(z);
+ absa = cabsl(a);
+ if (absa == 0.0L) {
+ return (0.0L + 0.0L * I);
+ }
+ arga = cargl(a);
+ r = powl(absa, x);
+ theta = x * arga;
+ if (y != 0.0L) {
+ r = r * expl(-y * arga);
+ theta = theta + y * logl(absa);
+ }
+ w = r * cosl(theta) + (r * sinl(theta)) * I;
+ return (w);
+}
--- /dev/null
+/*-
+ * Copyright (c) 2008 David Schultz <das@FreeBSD.ORG>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/src/s_cproj.c,v 1.1 2008/08/07 15:07:48 das Exp $");
+
+#include <openlibm_complex.h>
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+OLM_DLLEXPORT double complex
+cproj(double complex z)
+{
+
+ if (!isinf(creal(z)) && !isinf(cimag(z)))
+ return (z);
+ else
+ return (CMPLX(INFINITY, copysign(0.0, cimag(z))));
+}
+
+#if LDBL_MANT_DIG == 53
+__weak_reference(cproj, cprojl);
+#endif
--- /dev/null
+/*-
+ * Copyright (c) 2008 David Schultz <das@FreeBSD.ORG>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/src/s_cprojf.c,v 1.1 2008/08/07 15:07:48 das Exp $");
+
+#include <openlibm_complex.h>
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+OLM_DLLEXPORT float complex
+cprojf(float complex z)
+{
+
+ if (!isinf(crealf(z)) && !isinf(cimagf(z)))
+ return (z);
+ else
+ return (CMPLXF(INFINITY, copysignf(0.0, cimagf(z))));
+}
--- /dev/null
+/*-
+ * Copyright (c) 2008 David Schultz <das@FreeBSD.ORG>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/src/s_cprojl.c,v 1.1 2008/08/07 15:07:48 das Exp $");
+
+#include <openlibm_complex.h>
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+OLM_DLLEXPORT long double complex
+cprojl(long double complex z)
+{
+
+ if (!isinf(creall(z)) && !isinf(cimagl(z)))
+ return (z);
+ else
+ return (CMPLXL(INFINITY, copysignl(0.0, cimagl(z))));
+}
--- /dev/null
+/*-
+ * Copyright (c) 2004 Stefan Farfeleder
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: src/lib/msun/src/s_creal.c,v 1.1 2004/05/30 09:21:56 stefanf Exp $
+ */
+
+#include <openlibm_complex.h>
+
+#include "math_private.h"
+
+OLM_DLLEXPORT double
+creal(double complex z)
+{
+ return z;
+}
--- /dev/null
+/*-
+ * Copyright (c) 2004 Stefan Farfeleder
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: src/lib/msun/src/s_crealf.c,v 1.1 2004/05/30 09:21:56 stefanf Exp $
+ */
+
+#include <openlibm_complex.h>
+
+#include "math_private.h"
+
+OLM_DLLEXPORT float
+crealf(float complex z)
+{
+ return z;
+}
--- /dev/null
+/*-
+ * Copyright (c) 2004 Stefan Farfeleder
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: src/lib/msun/src/s_creall.c,v 1.1 2004/05/30 09:21:56 stefanf Exp $
+ */
+
+#include <openlibm_complex.h>
+
+#include "math_private.h"
+
+OLM_DLLEXPORT long double
+creall(long double complex z)
+{
+ return z;
+}
--- /dev/null
+/* $OpenBSD: s_csin.c,v 1.6 2013/07/03 04:46:36 espie Exp $ */
+/*
+ * Copyright (c) 2008 Stephen L. Moshier <steve@moshier.net>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* csin()
+ *
+ * Complex circular sine
+ *
+ *
+ *
+ * SYNOPSIS:
+ *
+ * double complex csin();
+ * double complex z, w;
+ *
+ * w = csin (z);
+ *
+ *
+ *
+ * DESCRIPTION:
+ *
+ * If
+ * z = x + iy,
+ *
+ * then
+ *
+ * w = sin x cosh y + i cos x sinh y.
+ *
+ * csin(z) = -i csinh(iz).
+ *
+ * ACCURACY:
+ *
+ * Relative error:
+ * arithmetic domain # trials peak rms
+ * DEC -10,+10 8400 5.3e-17 1.3e-17
+ * IEEE -10,+10 30000 3.8e-16 1.0e-16
+ * Also tested by csin(casin(z)) = z.
+ *
+ */
+
+#include <float.h>
+#include <openlibm_complex.h>
+#include <openlibm_math.h>
+
+/* calculate cosh and sinh */
+
+static void
+cchsh(double x, double *c, double *s)
+{
+ double e, ei;
+
+ if (fabs(x) <= 0.5) {
+ *c = cosh(x);
+ *s = sinh(x);
+ }
+ else {
+ e = exp(x);
+ ei = 0.5/e;
+ e = 0.5 * e;
+ *s = e - ei;
+ *c = e + ei;
+ }
+}
+
+double complex
+csin(double complex z)
+{
+ double complex w;
+ double ch, sh;
+
+ cchsh( cimag (z), &ch, &sh );
+ w = sin (creal(z)) * ch + (cos (creal(z)) * sh) * I;
+ return (w);
+}
+
+#if LDBL_MANT_DIG == DBL_MANT_DIG
+__strong_alias(csinl, csin);
+#endif /* LDBL_MANT_DIG == DBL_MANT_DIG */
--- /dev/null
+/* $OpenBSD: s_csinf.c,v 1.2 2010/07/18 18:42:26 guenther Exp $ */
+/*
+ * Copyright (c) 2008 Stephen L. Moshier <steve@moshier.net>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* csinf()
+ *
+ * Complex circular sine
+ *
+ *
+ *
+ * SYNOPSIS:
+ *
+ * void csinf();
+ * cmplxf z, w;
+ *
+ * csinf( &z, &w );
+ *
+ *
+ *
+ * DESCRIPTION:
+ *
+ * If
+ * z = x + iy,
+ *
+ * then
+ *
+ * w = sin x cosh y + i cos x sinh y.
+ *
+ *
+ *
+ * ACCURACY:
+ *
+ * Relative error:
+ * arithmetic domain # trials peak rms
+ * IEEE -10,+10 30000 1.9e-7 5.5e-8
+ *
+ */
+
+#include <openlibm_complex.h>
+#include <openlibm_math.h>
+
+/* calculate cosh and sinh */
+
+static void
+cchshf(float xx, float *c, float *s)
+{
+ float x, e, ei;
+
+ x = xx;
+ if(fabsf(x) <= 0.5f) {
+ *c = coshf(x);
+ *s = sinhf(x);
+ }
+ else {
+ e = expf(x);
+ ei = 0.5f/e;
+ e = 0.5f * e;
+ *s = e - ei;
+ *c = e + ei;
+ }
+}
+
+float complex
+csinf(float complex z)
+{
+ float complex w;
+ float ch, sh;
+
+ cchshf(cimagf(z), &ch, &sh);
+ w = sinf(crealf(z)) * ch + (cosf(crealf(z)) * sh) * I;
+ return (w);
+}
--- /dev/null
+/*-
+ * Copyright (c) 2005 Bruce D. Evans and Steven G. Kargl
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice unmodified, this list of conditions, and the following
+ * disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Hyperbolic sine of a complex argument z = x + i y.
+ *
+ * sinh(z) = sinh(x+iy)
+ * = sinh(x) cos(y) + i cosh(x) sin(y).
+ *
+ * Exceptional values are noted in the comments within the source code.
+ * These values and the return value were taken from n1124.pdf.
+ */
+
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/src/s_csinh.c,v 1.2 2011/10/21 06:29:32 das Exp $");
+
+#include <openlibm_complex.h>
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+static const double huge = 0x1p1023;
+
+OLM_DLLEXPORT double complex
+csinh(double complex z)
+{
+ double x, y, h;
+ int32_t hx, hy, ix, iy, lx, ly;
+
+ x = creal(z);
+ y = cimag(z);
+
+ EXTRACT_WORDS(hx, lx, x);
+ EXTRACT_WORDS(hy, ly, y);
+
+ ix = 0x7fffffff & hx;
+ iy = 0x7fffffff & hy;
+
+ /* Handle the nearly-non-exceptional cases where x and y are finite. */
+ if (ix < 0x7ff00000 && iy < 0x7ff00000) {
+ if ((iy | ly) == 0)
+ return (CMPLX(sinh(x), y));
+ if (ix < 0x40360000) /* small x: normal case */
+ return (CMPLX(sinh(x) * cos(y), cosh(x) * sin(y)));
+
+ /* |x| >= 22, so cosh(x) ~= exp(|x|) */
+ if (ix < 0x40862e42) {
+ /* x < 710: exp(|x|) won't overflow */
+ h = exp(fabs(x)) * 0.5;
+ return (CMPLX(copysign(h, x) * cos(y), h * sin(y)));
+ } else if (ix < 0x4096bbaa) {
+ /* x < 1455: scale to avoid overflow */
+ z = __ldexp_cexp(CMPLX(fabs(x), y), -1);
+ return (CMPLX(creal(z) * copysign(1, x), cimag(z)));
+ } else {
+ /* x >= 1455: the result always overflows */
+ h = huge * x;
+ return (CMPLX(h * cos(y), h * h * sin(y)));
+ }
+ }
+
+ /*
+ * sinh(+-0 +- I Inf) = sign(d(+-0, dNaN))0 + I dNaN.
+ * The sign of 0 in the result is unspecified. Choice = normally
+ * the same as dNaN. Raise the invalid floating-point exception.
+ *
+ * sinh(+-0 +- I NaN) = sign(d(+-0, NaN))0 + I d(NaN).
+ * The sign of 0 in the result is unspecified. Choice = normally
+ * the same as d(NaN).
+ */
+ if ((ix | lx) == 0 && iy >= 0x7ff00000)
+ return (CMPLX(copysign(0, x * (y - y)), y - y));
+
+ /*
+ * sinh(+-Inf +- I 0) = +-Inf + I +-0.
+ *
+ * sinh(NaN +- I 0) = d(NaN) + I +-0.
+ */
+ if ((iy | ly) == 0 && ix >= 0x7ff00000) {
+ if (((hx & 0xfffff) | lx) == 0)
+ return (CMPLX(x, y));
+ return (CMPLX(x, copysign(0, y)));
+ }
+
+ /*
+ * sinh(x +- I Inf) = dNaN + I dNaN.
+ * Raise the invalid floating-point exception for finite nonzero x.
+ *
+ * sinh(x + I NaN) = d(NaN) + I d(NaN).
+ * Optionally raises the invalid floating-point exception for finite
+ * nonzero x. Choice = don't raise (except for signaling NaNs).
+ */
+ if (ix < 0x7ff00000 && iy >= 0x7ff00000)
+ return (CMPLX(y - y, x * (y - y)));
+
+ /*
+ * sinh(+-Inf + I NaN) = +-Inf + I d(NaN).
+ * The sign of Inf in the result is unspecified. Choice = normally
+ * the same as d(NaN).
+ *
+ * sinh(+-Inf +- I Inf) = +Inf + I dNaN.
+ * The sign of Inf in the result is unspecified. Choice = always +.
+ * Raise the invalid floating-point exception.
+ *
+ * sinh(+-Inf + I y) = +-Inf cos(y) + I Inf sin(y)
+ */
+ if (ix >= 0x7ff00000 && ((hx & 0xfffff) | lx) == 0) {
+ if (iy >= 0x7ff00000)
+ return (CMPLX(x * x, x * (y - y)));
+ return (CMPLX(x * cos(y), INFINITY * sin(y)));
+ }
+
+ /*
+ * sinh(NaN + I NaN) = d(NaN) + I d(NaN).
+ *
+ * sinh(NaN +- I Inf) = d(NaN) + I d(NaN).
+ * Optionally raises the invalid floating-point exception.
+ * Choice = raise.
+ *
+ * sinh(NaN + I y) = d(NaN) + I d(NaN).
+ * Optionally raises the invalid floating-point exception for finite
+ * nonzero y. Choice = don't raise (except for signaling NaNs).
+ */
+ return (CMPLX((x * x) * (y - y), (x + x) * (y - y)));
+}
+
+OLM_DLLEXPORT double complex
+csin(double complex z)
+{
+
+ /* csin(z) = -I * csinh(I * z) */
+ z = csinh(CMPLX(-cimag(z), creal(z)));
+ return (CMPLX(cimag(z), -creal(z)));
+}
--- /dev/null
+/*-
+ * Copyright (c) 2005 Bruce D. Evans and Steven G. Kargl
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice unmodified, this list of conditions, and the following
+ * disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Hyperbolic sine of a complex argument z. See s_csinh.c for details.
+ */
+
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/src/s_csinhf.c,v 1.2 2011/10/21 06:29:32 das Exp $");
+
+#include <openlibm_complex.h>
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+static const float huge = 0x1p127;
+
+OLM_DLLEXPORT float complex
+csinhf(float complex z)
+{
+ float x, y, h;
+ int32_t hx, hy, ix, iy;
+
+ x = crealf(z);
+ y = cimagf(z);
+
+ GET_FLOAT_WORD(hx, x);
+ GET_FLOAT_WORD(hy, y);
+
+ ix = 0x7fffffff & hx;
+ iy = 0x7fffffff & hy;
+
+ if (ix < 0x7f800000 && iy < 0x7f800000) {
+ if (iy == 0)
+ return (CMPLXF(sinhf(x), y));
+ if (ix < 0x41100000) /* small x: normal case */
+ return (CMPLXF(sinhf(x) * cosf(y), coshf(x) * sinf(y)));
+
+ /* |x| >= 9, so cosh(x) ~= exp(|x|) */
+ if (ix < 0x42b17218) {
+ /* x < 88.7: expf(|x|) won't overflow */
+ h = expf(fabsf(x)) * 0.5f;
+ return (CMPLXF(copysignf(h, x) * cosf(y), h * sinf(y)));
+ } else if (ix < 0x4340b1e7) {
+ /* x < 192.7: scale to avoid overflow */
+ z = __ldexp_cexpf(CMPLXF(fabsf(x), y), -1);
+ return (CMPLXF(crealf(z) * copysignf(1, x), cimagf(z)));
+ } else {
+ /* x >= 192.7: the result always overflows */
+ h = huge * x;
+ return (CMPLXF(h * cosf(y), h * h * sinf(y)));
+ }
+ }
+
+ if (ix == 0 && iy >= 0x7f800000)
+ return (CMPLXF(copysignf(0, x * (y - y)), y - y));
+
+ if (iy == 0 && ix >= 0x7f800000) {
+ if ((hx & 0x7fffff) == 0)
+ return (CMPLXF(x, y));
+ return (CMPLXF(x, copysignf(0, y)));
+ }
+
+ if (ix < 0x7f800000 && iy >= 0x7f800000)
+ return (CMPLXF(y - y, x * (y - y)));
+
+ if (ix >= 0x7f800000 && (hx & 0x7fffff) == 0) {
+ if (iy >= 0x7f800000)
+ return (CMPLXF(x * x, x * (y - y)));
+ return (CMPLXF(x * cosf(y), INFINITY * sinf(y)));
+ }
+
+ return (CMPLXF((x * x) * (y - y), (x + x) * (y - y)));
+}
+
+OLM_DLLEXPORT float complex
+csinf(float complex z)
+{
+
+ z = csinhf(CMPLXF(-cimagf(z), crealf(z)));
+ return (CMPLXF(cimagf(z), -crealf(z)));
+}
--- /dev/null
+/* $OpenBSD: s_csinhl.c,v 1.2 2011/07/20 19:28:33 martynas Exp $ */
+
+/*
+ * Copyright (c) 2008 Stephen L. Moshier <steve@moshier.net>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* csinhl
+ *
+ * Complex hyperbolic sine
+ *
+ *
+ *
+ * SYNOPSIS:
+ *
+ * long double complex csinhl();
+ * long double complex z, w;
+ *
+ * w = csinhl (z);
+ *
+ * DESCRIPTION:
+ *
+ * csinh z = (cexp(z) - cexp(-z))/2
+ * = sinh x * cos y + i cosh x * sin y .
+ *
+ * ACCURACY:
+ *
+ * Relative error:
+ * arithmetic domain # trials peak rms
+ * IEEE -10,+10 30000 3.1e-16 8.2e-17
+ *
+ */
+
+#include <openlibm_complex.h>
+#include <openlibm_math.h>
+
+long double complex
+csinhl(long double complex z)
+{
+ long double complex w;
+ long double x, y;
+
+ x = creall(z);
+ y = cimagl(z);
+ w = sinhl(x) * cosl(y) + (coshl(x) * sinl(y)) * I;
+ return (w);
+}
--- /dev/null
+/* $OpenBSD: s_csinl.c,v 1.2 2011/07/20 19:28:33 martynas Exp $ */
+
+/*
+ * Copyright (c) 2008 Stephen L. Moshier <steve@moshier.net>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* csinl()
+ *
+ * Complex circular sine
+ *
+ *
+ *
+ * SYNOPSIS:
+ *
+ * long double complex csinl();
+ * long double complex z, w;
+ *
+ * w = csinl( z );
+ *
+ *
+ *
+ * DESCRIPTION:
+ *
+ * If
+ * z = x + iy,
+ *
+ * then
+ *
+ * w = sin x cosh y + i cos x sinh y.
+ *
+ *
+ *
+ * ACCURACY:
+ *
+ * Relative error:
+ * arithmetic domain # trials peak rms
+ * DEC -10,+10 8400 5.3e-17 1.3e-17
+ * IEEE -10,+10 30000 3.8e-16 1.0e-16
+ * Also tested by csin(casin(z)) = z.
+ *
+ */
+
+#include <openlibm_complex.h>
+#include <openlibm_math.h>
+
+static void
+cchshl(long double x, long double *c, long double *s)
+{
+ long double e, ei;
+
+ if(fabsl(x) <= 0.5L) {
+ *c = coshl(x);
+ *s = sinhl(x);
+ } else {
+ e = expl(x);
+ ei = 0.5L/e;
+ e = 0.5L * e;
+ *s = e - ei;
+ *c = e + ei;
+ }
+}
+
+long double complex
+csinl(long double complex z)
+{
+ long double complex w;
+ long double ch, sh;
+
+ cchshl(cimagl(z), &ch, &sh);
+ w = sinl(creall(z)) * ch + (cosl(creall(z)) * sh) * I;
+ return (w);
+}
--- /dev/null
+/*-
+ * Copyright (c) 2007 David Schultz <das@FreeBSD.ORG>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/src/s_csqrt.c,v 1.4 2008/08/08 00:15:16 das Exp $");
+
+#include <float.h>
+#include <openlibm_complex.h>
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+/*
+ * gcc doesn't implement complex multiplication or division correctly,
+ * so we need to handle infinities specially. We turn on this pragma to
+ * notify conforming c99 compilers that the fast-but-incorrect code that
+ * gcc generates is acceptable, since the special cases have already been
+ * handled.
+ */
+#ifndef __GNUC__
+#pragma STDC CX_LIMITED_RANGE ON
+#endif
+
+/* We risk spurious overflow for components >= DBL_MAX / (1 + sqrt(2)). */
+#define THRESH 0x1.a827999fcef32p+1022
+
+OLM_DLLEXPORT double complex
+csqrt(double complex z)
+{
+ double complex result;
+ double a, b;
+ double t;
+ int scale;
+
+ a = creal(z);
+ b = cimag(z);
+
+ /* Handle special cases. */
+ if (z == 0)
+ return (CMPLX(0, b));
+ if (isinf(b))
+ return (CMPLX(INFINITY, b));
+ if (isnan(a)) {
+ t = (b - b) / (b - b); /* raise invalid if b is not a NaN */
+ return (CMPLX(a, t)); /* return NaN + NaN i */
+ }
+ if (isinf(a)) {
+ /*
+ * csqrt(inf + NaN i) = inf + NaN i
+ * csqrt(inf + y i) = inf + 0 i
+ * csqrt(-inf + NaN i) = NaN +- inf i
+ * csqrt(-inf + y i) = 0 + inf i
+ */
+ if (signbit(a))
+ return (CMPLX(fabs(b - b), copysign(a, b)));
+ else
+ return (CMPLX(a, copysign(b - b, b)));
+ }
+ /*
+ * The remaining special case (b is NaN) is handled just fine by
+ * the normal code path below.
+ */
+
+ /* Scale to avoid overflow. */
+ if (fabs(a) >= THRESH || fabs(b) >= THRESH) {
+ a *= 0.25;
+ b *= 0.25;
+ scale = 1;
+ } else {
+ scale = 0;
+ }
+
+ /* Algorithm 312, CACM vol 10, Oct 1967. */
+ if (a >= 0) {
+ t = sqrt((a + hypot(a, b)) * 0.5);
+ result = CMPLX(t, b / (2 * t));
+ } else {
+ t = sqrt((-a + hypot(a, b)) * 0.5);
+ result = CMPLX(fabs(b) / (2 * t), copysign(t, b));
+ }
+
+ /* Rescale. */
+ if (scale)
+ return (result * 2);
+ else
+ return (result);
+}
+
+#if LDBL_MANT_DIG == 53
+__weak_reference(csqrt, csqrtl);
+#endif
--- /dev/null
+/*-
+ * Copyright (c) 2007 David Schultz <das@FreeBSD.ORG>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/src/s_csqrtf.c,v 1.3 2008/08/08 00:15:16 das Exp $");
+
+#include <openlibm_complex.h>
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+/*
+ * gcc doesn't implement complex multiplication or division correctly,
+ * so we need to handle infinities specially. We turn on this pragma to
+ * notify conforming c99 compilers that the fast-but-incorrect code that
+ * gcc generates is acceptable, since the special cases have already been
+ * handled.
+ */
+#ifndef __GNUC__
+#pragma STDC CX_LIMITED_RANGE ON
+#endif
+
+OLM_DLLEXPORT float complex
+csqrtf(float complex z)
+{
+ float a = crealf(z), b = cimagf(z);
+ double t;
+
+ /* Handle special cases. */
+ if (z == 0)
+ return (CMPLXF(0, b));
+ if (isinf(b))
+ return (CMPLXF(INFINITY, b));
+ if (isnan(a)) {
+ t = (b - b) / (b - b); /* raise invalid if b is not a NaN */
+ return (CMPLXF(a, t)); /* return NaN + NaN i */
+ }
+ if (isinf(a)) {
+ /*
+ * csqrtf(inf + NaN i) = inf + NaN i
+ * csqrtf(inf + y i) = inf + 0 i
+ * csqrtf(-inf + NaN i) = NaN +- inf i
+ * csqrtf(-inf + y i) = 0 + inf i
+ */
+ if (signbit(a))
+ return (CMPLXF(fabsf(b - b), copysignf(a, b)));
+ else
+ return (CMPLXF(a, copysignf(b - b, b)));
+ }
+ /*
+ * The remaining special case (b is NaN) is handled just fine by
+ * the normal code path below.
+ */
+
+ /*
+ * We compute t in double precision to avoid overflow and to
+ * provide correct rounding in nearly all cases.
+ * This is Algorithm 312, CACM vol 10, Oct 1967.
+ */
+ if (a >= 0) {
+ t = sqrt((a + hypot(a, b)) * 0.5);
+ return (CMPLXF(t, b / (2.0 * t)));
+ } else {
+ t = sqrt((-a + hypot(a, b)) * 0.5);
+ return (CMPLXF(fabsf(b) / (2.0 * t), copysignf(t, b)));
+ }
+}
--- /dev/null
+/*-
+ * Copyright (c) 2007-2008 David Schultz <das@FreeBSD.ORG>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "cdefs-compat.h"
+
+#include <float.h>
+#include <openlibm_complex.h>
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+/*
+ * gcc doesn't implement complex multiplication or division correctly,
+ * so we need to handle infinities specially. We turn on this pragma to
+ * notify conforming c99 compilers that the fast-but-incorrect code that
+ * gcc generates is acceptable, since the special cases have already been
+ * handled.
+ */
+#ifndef __GNUC__
+#pragma STDC CX_LIMITED_RANGE ON
+#endif
+
+/* We risk spurious overflow for components >= LDBL_MAX / (1 + sqrt(2)). */
+#define THRESH (LDBL_MAX / 2.414213562373095048801688724209698L)
+
+OLM_DLLEXPORT long double complex
+csqrtl(long double complex z)
+{
+ long double complex result;
+ long double a, b;
+ long double t;
+ int scale;
+
+ a = creall(z);
+ b = cimagl(z);
+
+ /* Handle special cases. */
+ if (z == 0)
+ return (CMPLXL(0, b));
+ if (isinf(b))
+ return (CMPLXL(INFINITY, b));
+ if (isnan(a)) {
+ t = (b - b) / (b - b); /* raise invalid if b is not a NaN */
+ return (CMPLXL(a, t)); /* return NaN + NaN i */
+ }
+ if (isinf(a)) {
+ /*
+ * csqrt(inf + NaN i) = inf + NaN i
+ * csqrt(inf + y i) = inf + 0 i
+ * csqrt(-inf + NaN i) = NaN +- inf i
+ * csqrt(-inf + y i) = 0 + inf i
+ */
+ if (signbit(a))
+ return (CMPLXL(fabsl(b - b), copysignl(a, b)));
+ else
+ return (CMPLXL(a, copysignl(b - b, b)));
+ }
+ /*
+ * The remaining special case (b is NaN) is handled just fine by
+ * the normal code path below.
+ */
+
+ /* Scale to avoid overflow. */
+ if (fabsl(a) >= THRESH || fabsl(b) >= THRESH) {
+ a *= 0.25;
+ b *= 0.25;
+ scale = 1;
+ } else {
+ scale = 0;
+ }
+
+ /* Algorithm 312, CACM vol 10, Oct 1967. */
+ if (a >= 0) {
+ t = sqrtl((a + hypotl(a, b)) * 0.5);
+ result = CMPLXL(t, b / (2 * t));
+ } else {
+ t = sqrtl((-a + hypotl(a, b)) * 0.5);
+ result = CMPLXL(fabsl(b) / (2 * t), copysignl(t, b));
+ }
+
+ /* Rescale. */
+ if (scale)
+ return (result * 2);
+ else
+ return (result);
+}
--- /dev/null
+/* $OpenBSD: s_ctan.c,v 1.6 2013/07/03 04:46:36 espie Exp $ */
+/*
+ * Copyright (c) 2008 Stephen L. Moshier <steve@moshier.net>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* ctan()
+ *
+ * Complex circular tangent
+ *
+ *
+ *
+ * SYNOPSIS:
+ *
+ * double complex ctan();
+ * double complex z, w;
+ *
+ * w = ctan (z);
+ *
+ *
+ *
+ * DESCRIPTION:
+ *
+ * If
+ * z = x + iy,
+ *
+ * then
+ *
+ * sin 2x + i sinh 2y
+ * w = --------------------.
+ * cos 2x + cosh 2y
+ *
+ * On the real axis the denominator is zero at odd multiples
+ * of PI/2. The denominator is evaluated by its Taylor
+ * series near these points.
+ *
+ * ctan(z) = -i ctanh(iz).
+ *
+ * ACCURACY:
+ *
+ * Relative error:
+ * arithmetic domain # trials peak rms
+ * DEC -10,+10 5200 7.1e-17 1.6e-17
+ * IEEE -10,+10 30000 7.2e-16 1.2e-16
+ * Also tested by ctan * ccot = 1 and catan(ctan(z)) = z.
+ */
+
+#include <float.h>
+#include <openlibm_complex.h>
+#include <openlibm_math.h>
+
+#define MACHEP 1.1e-16
+#define MAXNUM 1.0e308
+
+static const double DP1 = 3.14159265160560607910E0;
+static const double DP2 = 1.98418714791870343106E-9;
+static const double DP3 = 1.14423774522196636802E-17;
+
+static double
+_redupi(double x)
+{
+ double t;
+ long i;
+
+ t = x/M_PI;
+ if (t >= 0.0)
+ t += 0.5;
+ else
+ t -= 0.5;
+
+ i = t; /* the multiple */
+ t = i;
+ t = ((x - t * DP1) - t * DP2) - t * DP3;
+ return (t);
+}
+
+/* Taylor series expansion for cosh(2y) - cos(2x) */
+
+static double
+_ctans(double complex z)
+{
+ double f, x, x2, y, y2, rn, t;
+ double d;
+
+ x = fabs (2.0 * creal (z));
+ y = fabs (2.0 * cimag(z));
+
+ x = _redupi(x);
+
+ x = x * x;
+ y = y * y;
+ x2 = 1.0;
+ y2 = 1.0;
+ f = 1.0;
+ rn = 0.0;
+ d = 0.0;
+ do {
+ rn += 1.0;
+ f *= rn;
+ rn += 1.0;
+ f *= rn;
+ x2 *= x;
+ y2 *= y;
+ t = y2 + x2;
+ t /= f;
+ d += t;
+
+ rn += 1.0;
+ f *= rn;
+ rn += 1.0;
+ f *= rn;
+ x2 *= x;
+ y2 *= y;
+ t = y2 - x2;
+ t /= f;
+ d += t;
+ }
+ while (fabs(t/d) > MACHEP)
+ ;
+ return (d);
+}
+
+double complex
+ctan(double complex z)
+{
+ double complex w;
+ double d;
+
+ d = cos (2.0 * creal (z)) + cosh (2.0 * cimag (z));
+
+ if (fabs(d) < 0.25)
+ d = _ctans (z);
+
+ if (d == 0.0) {
+ /*mtherr ("ctan", OVERFLOW);*/
+ w = MAXNUM + MAXNUM * I;
+ return (w);
+ }
+
+ w = sin (2.0 * creal(z)) / d + (sinh (2.0 * cimag(z)) / d) * I;
+ return (w);
+}
+
+#if LDBL_MANT_DIG == DBL_MANT_DIG
+__strong_alias(ctanl, ctan);
+#endif /* LDBL_MANT_DIG == DBL_MANT_DIG */
--- /dev/null
+/* $OpenBSD: s_ctanf.c,v 1.2 2011/07/20 19:28:33 martynas Exp $ */
+/*
+ * Copyright (c) 2008 Stephen L. Moshier <steve@moshier.net>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* ctanf()
+ *
+ * Complex circular tangent
+ *
+ *
+ *
+ * SYNOPSIS:
+ *
+ * void ctanf();
+ * cmplxf z, w;
+ *
+ * ctanf( &z, &w );
+ *
+ *
+ *
+ * DESCRIPTION:
+ *
+ * If
+ * z = x + iy,
+ *
+ * then
+ *
+ * sin 2x + i sinh 2y
+ * w = --------------------.
+ * cos 2x + cosh 2y
+ *
+ * On the real axis the denominator is zero at odd multiples
+ * of PI/2. The denominator is evaluated by its Taylor
+ * series near these points.
+ *
+ *
+ * ACCURACY:
+ *
+ * Relative error:
+ * arithmetic domain # trials peak rms
+ * IEEE -10,+10 30000 3.3e-7 5.1e-8
+ */
+
+#include <openlibm_complex.h>
+#include <openlibm_math.h>
+
+#define MACHEPF 3.0e-8
+#define MAXNUMF 1.0e38f
+
+static const double DP1 = 3.140625;
+static const double DP2 = 9.67502593994140625E-4;
+static const double DP3 = 1.509957990978376432E-7;
+
+static float
+_redupif(float xx)
+{
+ float x, t;
+ long i;
+
+ x = xx;
+ t = x/(float)M_PI;
+ if(t >= 0.0)
+ t += 0.5;
+ else
+ t -= 0.5;
+
+ i = t; /* the multiple */
+ t = i;
+ t = ((x - t * DP1) - t * DP2) - t * DP3;
+ return(t);
+}
+
+/* Taylor series expansion for cosh(2y) - cos(2x) */
+
+static float
+_ctansf(float complex z)
+{
+ float f, x, x2, y, y2, rn, t, d;
+
+ x = fabsf(2.0f * crealf(z));
+ y = fabsf(2.0f * cimagf(z));
+
+ x = _redupif(x);
+
+ x = x * x;
+ y = y * y;
+ x2 = 1.0f;
+ y2 = 1.0f;
+ f = 1.0f;
+ rn = 0.0f;
+ d = 0.0f;
+ do {
+ rn += 1.0f;
+ f *= rn;
+ rn += 1.0f;
+ f *= rn;
+ x2 *= x;
+ y2 *= y;
+ t = y2 + x2;
+ t /= f;
+ d += t;
+
+ rn += 1.0f;
+ f *= rn;
+ rn += 1.0f;
+ f *= rn;
+ x2 *= x;
+ y2 *= y;
+ t = y2 - x2;
+ t /= f;
+ d += t;
+ }
+ while (fabsf(t/d) > MACHEPF)
+ ;
+ return(d);
+}
+
+float complex
+ctanf(float complex z)
+{
+ float complex w;
+ float d;
+
+ d = cosf( 2.0f * crealf(z) ) + coshf( 2.0f * cimagf(z) );
+
+ if(fabsf(d) < 0.25f)
+ d = _ctansf(z);
+
+ if (d == 0.0f) {
+ /*mtherr( "ctanf", OVERFLOW );*/
+ w = MAXNUMF + MAXNUMF * I;
+ return (w);
+ }
+ w = sinf (2.0f * crealf(z)) / d + (sinhf (2.0f * cimagf(z)) / d) * I;
+ return (w);
+}
--- /dev/null
+/*-
+ * Copyright (c) 2011 David Schultz
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice unmodified, this list of conditions, and the following
+ * disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Hyperbolic tangent of a complex argument z = x + i y.
+ *
+ * The algorithm is from:
+ *
+ * W. Kahan. Branch Cuts for Complex Elementary Functions or Much
+ * Ado About Nothing's Sign Bit. In The State of the Art in
+ * Numerical Analysis, pp. 165 ff. Iserles and Powell, eds., 1987.
+ *
+ * Method:
+ *
+ * Let t = tan(x)
+ * beta = 1/cos^2(y)
+ * s = sinh(x)
+ * rho = cosh(x)
+ *
+ * We have:
+ *
+ * tanh(z) = sinh(z) / cosh(z)
+ *
+ * sinh(x) cos(y) + i cosh(x) sin(y)
+ * = ---------------------------------
+ * cosh(x) cos(y) + i sinh(x) sin(y)
+ *
+ * cosh(x) sinh(x) / cos^2(y) + i tan(y)
+ * = -------------------------------------
+ * 1 + sinh^2(x) / cos^2(y)
+ *
+ * beta rho s + i t
+ * = ----------------
+ * 1 + beta s^2
+ *
+ * Modifications:
+ *
+ * I omitted the original algorithm's handling of overflow in tan(x) after
+ * verifying with nearpi.c that this can't happen in IEEE single or double
+ * precision. I also handle large x differently.
+ */
+
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/src/s_ctanh.c,v 1.2 2011/10/21 06:30:16 das Exp $");
+
+#include <openlibm_complex.h>
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+OLM_DLLEXPORT double complex
+ctanh(double complex z)
+{
+ double x, y;
+ double t, beta, s, rho, denom;
+ u_int32_t hx, ix, lx;
+
+ x = creal(z);
+ y = cimag(z);
+
+ EXTRACT_WORDS(hx, lx, x);
+ ix = hx & 0x7fffffff;
+
+ /*
+ * ctanh(NaN + i 0) = NaN + i 0
+ *
+ * ctanh(NaN + i y) = NaN + i NaN for y != 0
+ *
+ * The imaginary part has the sign of x*sin(2*y), but there's no
+ * special effort to get this right.
+ *
+ * ctanh(+-Inf +- i Inf) = +-1 +- 0
+ *
+ * ctanh(+-Inf + i y) = +-1 + 0 sin(2y) for y finite
+ *
+ * The imaginary part of the sign is unspecified. This special
+ * case is only needed to avoid a spurious invalid exception when
+ * y is infinite.
+ */
+ if (ix >= 0x7ff00000) {
+ if ((ix & 0xfffff) | lx) /* x is NaN */
+ return (CMPLX(x, (y == 0 ? y : x * y)));
+ SET_HIGH_WORD(x, hx - 0x40000000); /* x = copysign(1, x) */
+ return (CMPLX(x, copysign(0, isinf(y) ? y : sin(y) * cos(y))));
+ }
+
+ /*
+ * ctanh(x + i NAN) = NaN + i NaN
+ * ctanh(x +- i Inf) = NaN + i NaN
+ */
+ if (!isfinite(y))
+ return (CMPLX(y - y, y - y));
+
+ /*
+ * ctanh(+-huge + i +-y) ~= +-1 +- i 2sin(2y)/exp(2x), using the
+ * approximation sinh^2(huge) ~= exp(2*huge) / 4.
+ * We use a modified formula to avoid spurious overflow.
+ */
+ if (ix >= 0x40360000) { /* x >= 22 */
+ double exp_mx = exp(-fabs(x));
+ return (CMPLX(copysign(1, x),
+ 4 * sin(y) * cos(y) * exp_mx * exp_mx));
+ }
+
+ /* Kahan's algorithm */
+ t = tan(y);
+ beta = 1.0 + t * t; /* = 1 / cos^2(y) */
+ s = sinh(x);
+ rho = sqrt(1 + s * s); /* = cosh(x) */
+ denom = 1 + beta * s * s;
+ return (CMPLX((beta * rho * s) / denom, t / denom));
+}
+
+OLM_DLLEXPORT double complex
+ctan(double complex z)
+{
+
+ /* ctan(z) = -I * ctanh(I * z) */
+ z = ctanh(CMPLX(-cimag(z), creal(z)));
+ return (CMPLX(cimag(z), -creal(z)));
+}
--- /dev/null
+/*-
+ * Copyright (c) 2011 David Schultz
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice unmodified, this list of conditions, and the following
+ * disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Hyperbolic tangent of a complex argument z. See s_ctanh.c for details.
+ */
+
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/src/s_ctanhf.c,v 1.2 2011/10/21 06:30:16 das Exp $");
+
+#include <openlibm_complex.h>
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+OLM_DLLEXPORT float complex
+ctanhf(float complex z)
+{
+ float x, y;
+ float t, beta, s, rho, denom;
+ u_int32_t hx, ix;
+
+ x = crealf(z);
+ y = cimagf(z);
+
+ GET_FLOAT_WORD(hx, x);
+ ix = hx & 0x7fffffff;
+
+ if (ix >= 0x7f800000) {
+ if (ix & 0x7fffff)
+ return (CMPLXF(x, (y == 0 ? y : x * y)));
+ SET_FLOAT_WORD(x, hx - 0x40000000);
+ return (CMPLXF(x,
+ copysignf(0, isinf(y) ? y : sinf(y) * cosf(y))));
+ }
+
+ if (!isfinite(y))
+ return (CMPLXF(y - y, y - y));
+
+ if (ix >= 0x41300000) { /* x >= 11 */
+ float exp_mx = expf(-fabsf(x));
+ return (CMPLXF(copysignf(1, x),
+ 4 * sinf(y) * cosf(y) * exp_mx * exp_mx));
+ }
+
+ t = tanf(y);
+ beta = 1.0 + t * t;
+ s = sinhf(x);
+ rho = sqrtf(1 + s * s);
+ denom = 1 + beta * s * s;
+ return (CMPLXF((beta * rho * s) / denom, t / denom));
+}
+
+OLM_DLLEXPORT float complex
+ctanf(float complex z)
+{
+
+ z = ctanhf(CMPLXF(-cimagf(z), crealf(z)));
+ return (CMPLXF(cimagf(z), -crealf(z)));
+}
+
--- /dev/null
+/* $OpenBSD: s_ctanhl.c,v 1.2 2011/07/20 19:28:33 martynas Exp $ */
+
+/*
+ * Copyright (c) 2008 Stephen L. Moshier <steve@moshier.net>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* ctanhl
+ *
+ * Complex hyperbolic tangent
+ *
+ *
+ *
+ * SYNOPSIS:
+ *
+ * long double complex ctanhl();
+ * long double complex z, w;
+ *
+ * w = ctanhl (z);
+ *
+ *
+ *
+ * DESCRIPTION:
+ *
+ * tanh z = (sinh 2x + i sin 2y) / (cosh 2x + cos 2y) .
+ *
+ * ACCURACY:
+ *
+ * Relative error:
+ * arithmetic domain # trials peak rms
+ * IEEE -10,+10 30000 1.7e-14 2.4e-16
+ *
+ */
+
+#include <openlibm_complex.h>
+#include <openlibm_math.h>
+
+long double complex
+ctanhl(long double complex z)
+{
+ long double complex w;
+ long double x, y, d;
+
+ x = creall(z);
+ y = cimagl(z);
+ d = coshl(2.0L * x) + cosl(2.0L * y);
+ w = sinhl(2.0L * x) / d + (sinl(2.0L * y) / d) * I;
+ return (w);
+}
--- /dev/null
+/* $OpenBSD: s_ctanl.c,v 1.3 2011/07/20 21:02:51 martynas Exp $ */
+
+/*
+ * Copyright (c) 2008 Stephen L. Moshier <steve@moshier.net>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* ctanl()
+ *
+ * Complex circular tangent
+ *
+ *
+ *
+ * SYNOPSIS:
+ *
+ * long double complex ctanl();
+ * long double complex z, w;
+ *
+ * w = ctanl( z );
+ *
+ *
+ *
+ * DESCRIPTION:
+ *
+ * If
+ * z = x + iy,
+ *
+ * then
+ *
+ * sin 2x + i sinh 2y
+ * w = --------------------.
+ * cos 2x + cosh 2y
+ *
+ * On the real axis the denominator is zero at odd multiples
+ * of PI/2. The denominator is evaluated by its Taylor
+ * series near these points.
+ *
+ *
+ * ACCURACY:
+ *
+ * Relative error:
+ * arithmetic domain # trials peak rms
+ * DEC -10,+10 5200 7.1e-17 1.6e-17
+ * IEEE -10,+10 30000 7.2e-16 1.2e-16
+ * Also tested by ctan * ccot = 1 and catan(ctan(z)) = z.
+ */
+
+#include <float.h>
+#include <openlibm_complex.h>
+#include <openlibm_math.h>
+
+#if LDBL_MANT_DIG == 64
+static const long double MACHEPL= 5.42101086242752217003726400434970855712890625E-20L;
+#elif LDBL_MANT_DIG == 113
+static const long double MACHEPL = 9.629649721936179265279889712924636592690508e-35L;
+#endif
+
+static const long double PIL = 3.141592653589793238462643383279502884197169L;
+static const long double DP1 = 3.14159265358979323829596852490908531763125L;
+static const long double DP2 = 1.6667485837041756656403424829301998703007e-19L;
+static const long double DP3 = 1.8830410776607851167459095484560349402753e-39L;
+
+static long double
+redupil(long double x)
+{
+ long double t;
+ long i;
+
+ t = x / PIL;
+ if (t >= 0.0L)
+ t += 0.5L;
+ else
+ t -= 0.5L;
+
+ i = t; /* the multiple */
+ t = i;
+ t = ((x - t * DP1) - t * DP2) - t * DP3;
+ return (t);
+}
+
+static long double
+ctansl(long double complex z)
+{
+ long double f, x, x2, y, y2, rn, t;
+ long double d;
+
+ x = fabsl(2.0L * creall(z));
+ y = fabsl(2.0L * cimagl(z));
+
+ x = redupil(x);
+
+ x = x * x;
+ y = y * y;
+ x2 = 1.0L;
+ y2 = 1.0L;
+ f = 1.0L;
+ rn = 0.0L;
+ d = 0.0L;
+ do {
+ rn += 1.0L;
+ f *= rn;
+ rn += 1.0L;
+ f *= rn;
+ x2 *= x;
+ y2 *= y;
+ t = y2 + x2;
+ t /= f;
+ d += t;
+
+ rn += 1.0L;
+ f *= rn;
+ rn += 1.0L;
+ f *= rn;
+ x2 *= x;
+ y2 *= y;
+ t = y2 - x2;
+ t /= f;
+ d += t;
+ }
+ while (fabsl(t/d) > MACHEPL);
+ return(d);
+}
+
+long double complex
+ctanl(long double complex z)
+{
+ long double complex w;
+ long double d, x, y;
+
+ x = creall(z);
+ y = cimagl(z);
+ d = cosl(2.0L * x) + coshl(2.0L * y);
+
+ if (fabsl(d) < 0.25L) {
+ d = fabsl(d);
+ d = ctansl(z);
+ }
+ if (d == 0.0L) {
+ /*mtherr( "ctan", OVERFLOW );*/
+ w = LDBL_MAX + LDBL_MAX * I;
+ return (w);
+ }
+
+ w = sinl(2.0L * x) / d + (sinhl(2.0L * y) / d) * I;
+ return (w);
+}
--- /dev/null
+/* @(#)s_erf.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/src/s_erf.c,v 1.8 2008/02/22 02:30:35 das Exp $");
+
+/* double erf(double x)
+ * double erfc(double x)
+ * x
+ * 2 |\
+ * erf(x) = --------- | exp(-t*t)dt
+ * sqrt(pi) \|
+ * 0
+ *
+ * erfc(x) = 1-erf(x)
+ * Note that
+ * erf(-x) = -erf(x)
+ * erfc(-x) = 2 - erfc(x)
+ *
+ * Method:
+ * 1. For |x| in [0, 0.84375]
+ * erf(x) = x + x*R(x^2)
+ * erfc(x) = 1 - erf(x) if x in [-.84375,0.25]
+ * = 0.5 + ((0.5-x)-x*R) if x in [0.25,0.84375]
+ * where R = P/Q where P is an odd poly of degree 8 and
+ * Q is an odd poly of degree 10.
+ * -57.90
+ * | R - (erf(x)-x)/x | <= 2
+ *
+ *
+ * Remark. The formula is derived by noting
+ * erf(x) = (2/sqrt(pi))*(x - x^3/3 + x^5/10 - x^7/42 + ....)
+ * and that
+ * 2/sqrt(pi) = 1.128379167095512573896158903121545171688
+ * is close to one. The interval is chosen because the fix
+ * point of erf(x) is near 0.6174 (i.e., erf(x)=x when x is
+ * near 0.6174), and by some experiment, 0.84375 is chosen to
+ * guarantee the error is less than one ulp for erf.
+ *
+ * 2. For |x| in [0.84375,1.25], let s = |x| - 1, and
+ * c = 0.84506291151 rounded to single (24 bits)
+ * erf(x) = sign(x) * (c + P1(s)/Q1(s))
+ * erfc(x) = (1-c) - P1(s)/Q1(s) if x > 0
+ * 1+(c+P1(s)/Q1(s)) if x < 0
+ * |P1/Q1 - (erf(|x|)-c)| <= 2**-59.06
+ * Remark: here we use the taylor series expansion at x=1.
+ * erf(1+s) = erf(1) + s*Poly(s)
+ * = 0.845.. + P1(s)/Q1(s)
+ * That is, we use rational approximation to approximate
+ * erf(1+s) - (c = (single)0.84506291151)
+ * Note that |P1/Q1|< 0.078 for x in [0.84375,1.25]
+ * where
+ * P1(s) = degree 6 poly in s
+ * Q1(s) = degree 6 poly in s
+ *
+ * 3. For x in [1.25,1/0.35(~2.857143)],
+ * erfc(x) = (1/x)*exp(-x*x-0.5625+R1/S1)
+ * erf(x) = 1 - erfc(x)
+ * where
+ * R1(z) = degree 7 poly in z, (z=1/x^2)
+ * S1(z) = degree 8 poly in z
+ *
+ * 4. For x in [1/0.35,28]
+ * erfc(x) = (1/x)*exp(-x*x-0.5625+R2/S2) if x > 0
+ * = 2.0 - (1/x)*exp(-x*x-0.5625+R2/S2) if -6<x<0
+ * = 2.0 - tiny (if x <= -6)
+ * erf(x) = sign(x)*(1.0 - erfc(x)) if x < 6, else
+ * erf(x) = sign(x)*(1.0 - tiny)
+ * where
+ * R2(z) = degree 6 poly in z, (z=1/x^2)
+ * S2(z) = degree 7 poly in z
+ *
+ * Note1:
+ * To compute exp(-x*x-0.5625+R/S), let s be a single
+ * precision number and s := x; then
+ * -x*x = -s*s + (s-x)*(s+x)
+ * exp(-x*x-0.5626+R/S) =
+ * exp(-s*s-0.5625)*exp((s-x)*(s+x)+R/S);
+ * Note2:
+ * Here 4 and 5 make use of the asymptotic series
+ * exp(-x*x)
+ * erfc(x) ~ ---------- * ( 1 + Poly(1/x^2) )
+ * x*sqrt(pi)
+ * We use rational approximation to approximate
+ * g(s)=f(1/x^2) = log(erfc(x)*x) - x*x + 0.5625
+ * Here is the error bound for R1/S1 and R2/S2
+ * |R1/S1 - f(x)| < 2**(-62.57)
+ * |R2/S2 - f(x)| < 2**(-61.52)
+ *
+ * 5. For inf > x >= 28
+ * erf(x) = sign(x) *(1 - tiny) (raise inexact)
+ * erfc(x) = tiny*tiny (raise underflow) if x > 0
+ * = 2 - tiny if x<0
+ *
+ * 7. Special case:
+ * erf(0) = 0, erf(inf) = 1, erf(-inf) = -1,
+ * erfc(0) = 1, erfc(inf) = 0, erfc(-inf) = 2,
+ * erfc/erf(NaN) is NaN
+ */
+
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+static const double
+tiny = 1e-300,
+half= 5.00000000000000000000e-01, /* 0x3FE00000, 0x00000000 */
+one = 1.00000000000000000000e+00, /* 0x3FF00000, 0x00000000 */
+two = 2.00000000000000000000e+00, /* 0x40000000, 0x00000000 */
+ /* c = (float)0.84506291151 */
+erx = 8.45062911510467529297e-01, /* 0x3FEB0AC1, 0x60000000 */
+/*
+ * Coefficients for approximation to erf on [0,0.84375]
+ */
+efx = 1.28379167095512586316e-01, /* 0x3FC06EBA, 0x8214DB69 */
+efx8= 1.02703333676410069053e+00, /* 0x3FF06EBA, 0x8214DB69 */
+pp0 = 1.28379167095512558561e-01, /* 0x3FC06EBA, 0x8214DB68 */
+pp1 = -3.25042107247001499370e-01, /* 0xBFD4CD7D, 0x691CB913 */
+pp2 = -2.84817495755985104766e-02, /* 0xBF9D2A51, 0xDBD7194F */
+pp3 = -5.77027029648944159157e-03, /* 0xBF77A291, 0x236668E4 */
+pp4 = -2.37630166566501626084e-05, /* 0xBEF8EAD6, 0x120016AC */
+qq1 = 3.97917223959155352819e-01, /* 0x3FD97779, 0xCDDADC09 */
+qq2 = 6.50222499887672944485e-02, /* 0x3FB0A54C, 0x5536CEBA */
+qq3 = 5.08130628187576562776e-03, /* 0x3F74D022, 0xC4D36B0F */
+qq4 = 1.32494738004321644526e-04, /* 0x3F215DC9, 0x221C1A10 */
+qq5 = -3.96022827877536812320e-06, /* 0xBED09C43, 0x42A26120 */
+/*
+ * Coefficients for approximation to erf in [0.84375,1.25]
+ */
+pa0 = -2.36211856075265944077e-03, /* 0xBF6359B8, 0xBEF77538 */
+pa1 = 4.14856118683748331666e-01, /* 0x3FDA8D00, 0xAD92B34D */
+pa2 = -3.72207876035701323847e-01, /* 0xBFD7D240, 0xFBB8C3F1 */
+pa3 = 3.18346619901161753674e-01, /* 0x3FD45FCA, 0x805120E4 */
+pa4 = -1.10894694282396677476e-01, /* 0xBFBC6398, 0x3D3E28EC */
+pa5 = 3.54783043256182359371e-02, /* 0x3FA22A36, 0x599795EB */
+pa6 = -2.16637559486879084300e-03, /* 0xBF61BF38, 0x0A96073F */
+qa1 = 1.06420880400844228286e-01, /* 0x3FBB3E66, 0x18EEE323 */
+qa2 = 5.40397917702171048937e-01, /* 0x3FE14AF0, 0x92EB6F33 */
+qa3 = 7.18286544141962662868e-02, /* 0x3FB2635C, 0xD99FE9A7 */
+qa4 = 1.26171219808761642112e-01, /* 0x3FC02660, 0xE763351F */
+qa5 = 1.36370839120290507362e-02, /* 0x3F8BEDC2, 0x6B51DD1C */
+qa6 = 1.19844998467991074170e-02, /* 0x3F888B54, 0x5735151D */
+/*
+ * Coefficients for approximation to erfc in [1.25,1/0.35]
+ */
+ra0 = -9.86494403484714822705e-03, /* 0xBF843412, 0x600D6435 */
+ra1 = -6.93858572707181764372e-01, /* 0xBFE63416, 0xE4BA7360 */
+ra2 = -1.05586262253232909814e+01, /* 0xC0251E04, 0x41B0E726 */
+ra3 = -6.23753324503260060396e+01, /* 0xC04F300A, 0xE4CBA38D */
+ra4 = -1.62396669462573470355e+02, /* 0xC0644CB1, 0x84282266 */
+ra5 = -1.84605092906711035994e+02, /* 0xC067135C, 0xEBCCABB2 */
+ra6 = -8.12874355063065934246e+01, /* 0xC0545265, 0x57E4D2F2 */
+ra7 = -9.81432934416914548592e+00, /* 0xC023A0EF, 0xC69AC25C */
+sa1 = 1.96512716674392571292e+01, /* 0x4033A6B9, 0xBD707687 */
+sa2 = 1.37657754143519042600e+02, /* 0x4061350C, 0x526AE721 */
+sa3 = 4.34565877475229228821e+02, /* 0x407B290D, 0xD58A1A71 */
+sa4 = 6.45387271733267880336e+02, /* 0x40842B19, 0x21EC2868 */
+sa5 = 4.29008140027567833386e+02, /* 0x407AD021, 0x57700314 */
+sa6 = 1.08635005541779435134e+02, /* 0x405B28A3, 0xEE48AE2C */
+sa7 = 6.57024977031928170135e+00, /* 0x401A47EF, 0x8E484A93 */
+sa8 = -6.04244152148580987438e-02, /* 0xBFAEEFF2, 0xEE749A62 */
+/*
+ * Coefficients for approximation to erfc in [1/.35,28]
+ */
+rb0 = -9.86494292470009928597e-03, /* 0xBF843412, 0x39E86F4A */
+rb1 = -7.99283237680523006574e-01, /* 0xBFE993BA, 0x70C285DE */
+rb2 = -1.77579549177547519889e+01, /* 0xC031C209, 0x555F995A */
+rb3 = -1.60636384855821916062e+02, /* 0xC064145D, 0x43C5ED98 */
+rb4 = -6.37566443368389627722e+02, /* 0xC083EC88, 0x1375F228 */
+rb5 = -1.02509513161107724954e+03, /* 0xC0900461, 0x6A2E5992 */
+rb6 = -4.83519191608651397019e+02, /* 0xC07E384E, 0x9BDC383F */
+sb1 = 3.03380607434824582924e+01, /* 0x403E568B, 0x261D5190 */
+sb2 = 3.25792512996573918826e+02, /* 0x40745CAE, 0x221B9F0A */
+sb3 = 1.53672958608443695994e+03, /* 0x409802EB, 0x189D5118 */
+sb4 = 3.19985821950859553908e+03, /* 0x40A8FFB7, 0x688C246A */
+sb5 = 2.55305040643316442583e+03, /* 0x40A3F219, 0xCEDF3BE6 */
+sb6 = 4.74528541206955367215e+02, /* 0x407DA874, 0xE79FE763 */
+sb7 = -2.24409524465858183362e+01; /* 0xC03670E2, 0x42712D62 */
+
+OLM_DLLEXPORT double
+erf(double x)
+{
+ int32_t hx,ix,i;
+ double R,S,P,Q,s,y,z,r;
+ GET_HIGH_WORD(hx,x);
+ ix = hx&0x7fffffff;
+ if(ix>=0x7ff00000) { /* erf(nan)=nan */
+ i = ((u_int32_t)hx>>31)<<1;
+ return (double)(1-i)+one/x; /* erf(+-inf)=+-1 */
+ }
+
+ if(ix < 0x3feb0000) { /* |x|<0.84375 */
+ if(ix < 0x3e300000) { /* |x|<2**-28 */
+ if (ix < 0x00800000)
+ return 0.125*(8.0*x+efx8*x); /*avoid underflow */
+ return x + efx*x;
+ }
+ z = x*x;
+ r = pp0+z*(pp1+z*(pp2+z*(pp3+z*pp4)));
+ s = one+z*(qq1+z*(qq2+z*(qq3+z*(qq4+z*qq5))));
+ y = r/s;
+ return x + x*y;
+ }
+ if(ix < 0x3ff40000) { /* 0.84375 <= |x| < 1.25 */
+ s = fabs(x)-one;
+ P = pa0+s*(pa1+s*(pa2+s*(pa3+s*(pa4+s*(pa5+s*pa6)))));
+ Q = one+s*(qa1+s*(qa2+s*(qa3+s*(qa4+s*(qa5+s*qa6)))));
+ if(hx>=0) return erx + P/Q; else return -erx - P/Q;
+ }
+ if (ix >= 0x40180000) { /* inf>|x|>=6 */
+ if(hx>=0) return one-tiny; else return tiny-one;
+ }
+ x = fabs(x);
+ s = one/(x*x);
+ if(ix< 0x4006DB6E) { /* |x| < 1/0.35 */
+ R=ra0+s*(ra1+s*(ra2+s*(ra3+s*(ra4+s*(
+ ra5+s*(ra6+s*ra7))))));
+ S=one+s*(sa1+s*(sa2+s*(sa3+s*(sa4+s*(
+ sa5+s*(sa6+s*(sa7+s*sa8)))))));
+ } else { /* |x| >= 1/0.35 */
+ R=rb0+s*(rb1+s*(rb2+s*(rb3+s*(rb4+s*(
+ rb5+s*rb6)))));
+ S=one+s*(sb1+s*(sb2+s*(sb3+s*(sb4+s*(
+ sb5+s*(sb6+s*sb7))))));
+ }
+ z = x;
+ SET_LOW_WORD(z,0);
+ r = __ieee754_exp(-z*z-0.5625)*__ieee754_exp((z-x)*(z+x)+R/S);
+ if(hx>=0) return one-r/x; else return r/x-one;
+}
+
+OLM_DLLEXPORT double
+erfc(double x)
+{
+ int32_t hx,ix;
+ double R,S,P,Q,s,y,z,r;
+ GET_HIGH_WORD(hx,x);
+ ix = hx&0x7fffffff;
+ if(ix>=0x7ff00000) { /* erfc(nan)=nan */
+ /* erfc(+-inf)=0,2 */
+ return (double)(((u_int32_t)hx>>31)<<1)+one/x;
+ }
+
+ if(ix < 0x3feb0000) { /* |x|<0.84375 */
+ if(ix < 0x3c700000) /* |x|<2**-56 */
+ return one-x;
+ z = x*x;
+ r = pp0+z*(pp1+z*(pp2+z*(pp3+z*pp4)));
+ s = one+z*(qq1+z*(qq2+z*(qq3+z*(qq4+z*qq5))));
+ y = r/s;
+ if(hx < 0x3fd00000) { /* x<1/4 */
+ return one-(x+x*y);
+ } else {
+ r = x*y;
+ r += (x-half);
+ return half - r ;
+ }
+ }
+ if(ix < 0x3ff40000) { /* 0.84375 <= |x| < 1.25 */
+ s = fabs(x)-one;
+ P = pa0+s*(pa1+s*(pa2+s*(pa3+s*(pa4+s*(pa5+s*pa6)))));
+ Q = one+s*(qa1+s*(qa2+s*(qa3+s*(qa4+s*(qa5+s*qa6)))));
+ if(hx>=0) {
+ z = one-erx; return z - P/Q;
+ } else {
+ z = erx+P/Q; return one+z;
+ }
+ }
+ if (ix < 0x403c0000) { /* |x|<28 */
+ x = fabs(x);
+ s = one/(x*x);
+ if(ix< 0x4006DB6D) { /* |x| < 1/.35 ~ 2.857143*/
+ R=ra0+s*(ra1+s*(ra2+s*(ra3+s*(ra4+s*(
+ ra5+s*(ra6+s*ra7))))));
+ S=one+s*(sa1+s*(sa2+s*(sa3+s*(sa4+s*(
+ sa5+s*(sa6+s*(sa7+s*sa8)))))));
+ } else { /* |x| >= 1/.35 ~ 2.857143 */
+ if(hx<0&&ix>=0x40180000) return two-tiny;/* x < -6 */
+ R=rb0+s*(rb1+s*(rb2+s*(rb3+s*(rb4+s*(
+ rb5+s*rb6)))));
+ S=one+s*(sb1+s*(sb2+s*(sb3+s*(sb4+s*(
+ sb5+s*(sb6+s*sb7))))));
+ }
+ z = x;
+ SET_LOW_WORD(z,0);
+ r = __ieee754_exp(-z*z-0.5625)*
+ __ieee754_exp((z-x)*(z+x)+R/S);
+ if(hx>0) return r/x; else return two-r/x;
+ } else {
+ if(hx>0) return tiny*tiny; else return two-tiny;
+ }
+}
--- /dev/null
+/* s_erff.c -- float version of s_erf.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/src/s_erff.c,v 1.8 2008/02/22 02:30:35 das Exp $");
+
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+static const float
+tiny = 1e-30,
+half= 5.0000000000e-01, /* 0x3F000000 */
+one = 1.0000000000e+00, /* 0x3F800000 */
+two = 2.0000000000e+00, /* 0x40000000 */
+/*
+ * Coefficients for approximation to erf on [0,0.84375]
+ */
+efx = 1.2837916613e-01, /* 0x3e0375d4 */
+efx8= 1.0270333290e+00, /* 0x3f8375d4 */
+/*
+ * Domain [0, 0.84375], range ~[-5.4446e-10,5.5197e-10]:
+ * |(erf(x) - x)/x - p(x)/q(x)| < 2**-31.
+ */
+pp0 = 1.28379166e-01F, /* 0x1.06eba8p-3 */
+pp1 = -3.36030394e-01F, /* -0x1.58185ap-2 */
+pp2 = -1.86260219e-03F, /* -0x1.e8451ep-10 */
+qq1 = 3.12324286e-01F, /* 0x1.3fd1f0p-2 */
+qq2 = 2.16070302e-02F, /* 0x1.620274p-6 */
+qq3 = -1.98859419e-03F, /* -0x1.04a626p-9 */
+/*
+ * Domain [0.84375, 1.25], range ~[-1.953e-11,1.940e-11]:
+ * |(erf(x) - erx) - p(x)/q(x)| < 2**-36.
+ */
+erx = 8.42697144e-01F, /* 0x1.af7600p-1. erf(1) rounded to 16 bits. */
+pa0 = 3.64939137e-06F, /* 0x1.e9d022p-19 */
+pa1 = 4.15109694e-01F, /* 0x1.a91284p-2 */
+pa2 = -1.65179938e-01F, /* -0x1.5249dcp-3 */
+pa3 = 1.10914491e-01F, /* 0x1.c64e46p-4 */
+qa1 = 6.02074385e-01F, /* 0x1.344318p-1 */
+qa2 = 5.35934687e-01F, /* 0x1.126608p-1 */
+qa3 = 1.68576106e-01F, /* 0x1.593e6ep-3 */
+qa4 = 5.62181212e-02F, /* 0x1.cc89f2p-5 */
+/*
+ * Domain [1.25,1/0.35], range ~[-7.043e-10,7.457e-10]:
+ * |log(x*erfc(x)) + x**2 + 0.5625 - r(x)/s(x)| < 2**-30
+ */
+ra0 = -9.87132732e-03F, /* -0x1.4376b2p-7 */
+ra1 = -5.53605914e-01F, /* -0x1.1b723cp-1 */
+ra2 = -2.17589188e+00F, /* -0x1.1683a0p+1 */
+ra3 = -1.43268085e+00F, /* -0x1.6ec42cp+0 */
+sa1 = 5.45995426e+00F, /* 0x1.5d6fe4p+2 */
+sa2 = 6.69798088e+00F, /* 0x1.acabb8p+2 */
+sa3 = 1.43113089e+00F, /* 0x1.6e5e98p+0 */
+sa4 = -5.77397496e-02F, /* -0x1.d90108p-5 */
+/*
+ * Domain [1/0.35, 11], range ~[-2.264e-13,2.336e-13]:
+ * |log(x*erfc(x)) + x**2 + 0.5625 - r(x)/s(x)| < 2**-42
+ */
+rb0 = -9.86494310e-03F, /* -0x1.434124p-7 */
+rb1 = -6.25171244e-01F, /* -0x1.401672p-1 */
+rb2 = -6.16498327e+00F, /* -0x1.8a8f16p+2 */
+rb3 = -1.66696873e+01F, /* -0x1.0ab70ap+4 */
+rb4 = -9.53764343e+00F, /* -0x1.313460p+3 */
+sb1 = 1.26884899e+01F, /* 0x1.96081cp+3 */
+sb2 = 4.51839523e+01F, /* 0x1.6978bcp+5 */
+sb3 = 4.72810211e+01F, /* 0x1.7a3f88p+5 */
+sb4 = 8.93033314e+00F; /* 0x1.1dc54ap+3 */
+
+
+OLM_DLLEXPORT float
+erff(float x)
+{
+ int32_t hx,ix,i;
+ float R,S,P,Q,s,y,z,r;
+ GET_FLOAT_WORD(hx,x);
+ ix = hx&0x7fffffff;
+ if(ix>=0x7f800000) { /* erf(nan)=nan */
+ i = ((u_int32_t)hx>>31)<<1;
+ return (float)(1-i)+one/x; /* erf(+-inf)=+-1 */
+ }
+
+ if(ix < 0x3f580000) { /* |x|<0.84375 */
+ if(ix < 0x38800000) { /* |x|<2**-14 */
+ if (ix < 0x04000000) /* |x|<0x1p-119 */
+ return (8*x+efx8*x)/8; /* avoid spurious underflow */
+ return x + efx*x;
+ }
+ z = x*x;
+ r = pp0+z*(pp1+z*pp2);
+ s = one+z*(qq1+z*(qq2+z*qq3));
+ y = r/s;
+ return x + x*y;
+ }
+ if(ix < 0x3fa00000) { /* 0.84375 <= |x| < 1.25 */
+ s = fabsf(x)-one;
+ P = pa0+s*(pa1+s*(pa2+s*pa3));
+ Q = one+s*(qa1+s*(qa2+s*(qa3+s*qa4)));
+ if(hx>=0) return erx + P/Q; else return -erx - P/Q;
+ }
+ if (ix >= 0x40800000) { /* inf>|x|>=4 */
+ if(hx>=0) return one-tiny; else return tiny-one;
+ }
+ x = fabsf(x);
+ s = one/(x*x);
+ if(ix< 0x4036DB6E) { /* |x| < 1/0.35 */
+ R=ra0+s*(ra1+s*(ra2+s*ra3));
+ S=one+s*(sa1+s*(sa2+s*(sa3+s*sa4)));
+ } else { /* |x| >= 1/0.35 */
+ R=rb0+s*(rb1+s*(rb2+s*(rb3+s*rb4)));
+ S=one+s*(sb1+s*(sb2+s*(sb3+s*sb4)));
+ }
+ SET_FLOAT_WORD(z,hx&0xffffe000);
+ r = expf(-z*z-0.5625F)*expf((z-x)*(z+x)+R/S);
+ if(hx>=0) return one-r/x; else return r/x-one;
+}
+
+OLM_DLLEXPORT float
+erfcf(float x)
+{
+ int32_t hx,ix;
+ float R,S,P,Q,s,y,z,r;
+ GET_FLOAT_WORD(hx,x);
+ ix = hx&0x7fffffff;
+ if(ix>=0x7f800000) { /* erfc(nan)=nan */
+ /* erfc(+-inf)=0,2 */
+ return (float)(((u_int32_t)hx>>31)<<1)+one/x;
+ }
+
+ if(ix < 0x3f580000) { /* |x|<0.84375 */
+ if(ix < 0x33800000) /* |x|<2**-56 */
+ return one-x;
+ z = x*x;
+ r = pp0+z*(pp1+z*pp2);
+ s = one+z*(qq1+z*(qq2+z*qq3));
+ y = r/s;
+ if(hx < 0x3e800000) { /* x<1/4 */
+ return one-(x+x*y);
+ } else {
+ r = x*y;
+ r += (x-half);
+ return half - r ;
+ }
+ }
+ if(ix < 0x3fa00000) { /* 0.84375 <= |x| < 1.25 */
+ s = fabsf(x)-one;
+ P = pa0+s*(pa1+s*(pa2+s*pa3));
+ Q = one+s*(qa1+s*(qa2+s*(qa3+s*qa4)));
+ if(hx>=0) {
+ z = one-erx; return z - P/Q;
+ } else {
+ z = erx+P/Q; return one+z;
+ }
+ }
+ if (ix < 0x41300000) { /* |x|<28 */
+ x = fabsf(x);
+ s = one/(x*x);
+ if(ix< 0x4036DB6D) { /* |x| < 1/.35 ~ 2.857143*/
+ R=ra0+s*(ra1+s*(ra2+s*ra3));
+ S=one+s*(sa1+s*(sa2+s*(sa3+s*sa4)));
+ } else { /* |x| >= 1/.35 ~ 2.857143 */
+ if(hx<0&&ix>=0x40a00000) return two-tiny;/* x < -5 */
+ R=rb0+s*(rb1+s*(rb2+s*(rb3+s*rb4)));
+ S=one+s*(sb1+s*(sb2+s*(sb3+s*sb4)));
+ }
+ SET_FLOAT_WORD(z,hx&0xffffe000);
+ r = expf(-z*z-0.5625F)*expf((z-x)*(z+x)+R/S);
+ if(hx>0) return r/x; else return two-r/x;
+ } else {
+ if(hx>0) return tiny*tiny; else return two-tiny;
+ }
+}
--- /dev/null
+/*-
+ * Copyright (c) 2005 David Schultz <das@FreeBSD.ORG>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/src/s_exp2.c,v 1.7 2008/02/22 02:27:34 das Exp $");
+
+#include <float.h>
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+#define TBLBITS 8
+#define TBLSIZE (1 << TBLBITS)
+
+static const double
+ huge = 0x1p1000,
+ redux = 0x1.8p52 / TBLSIZE,
+ P1 = 0x1.62e42fefa39efp-1,
+ P2 = 0x1.ebfbdff82c575p-3,
+ P3 = 0x1.c6b08d704a0a6p-5,
+ P4 = 0x1.3b2ab88f70400p-7,
+ P5 = 0x1.5d88003875c74p-10;
+
+static volatile double twom1000 = 0x1p-1000;
+
+static const double tbl[TBLSIZE * 2] = {
+/* exp2(z + eps) eps */
+ 0x1.6a09e667f3d5dp-1, 0x1.9880p-44,
+ 0x1.6b052fa751744p-1, 0x1.8000p-50,
+ 0x1.6c012750bd9fep-1, -0x1.8780p-45,
+ 0x1.6cfdcddd476bfp-1, 0x1.ec00p-46,
+ 0x1.6dfb23c651a29p-1, -0x1.8000p-50,
+ 0x1.6ef9298593ae3p-1, -0x1.c000p-52,
+ 0x1.6ff7df9519386p-1, -0x1.fd80p-45,
+ 0x1.70f7466f42da3p-1, -0x1.c880p-45,
+ 0x1.71f75e8ec5fc3p-1, 0x1.3c00p-46,
+ 0x1.72f8286eacf05p-1, -0x1.8300p-44,
+ 0x1.73f9a48a58152p-1, -0x1.0c00p-47,
+ 0x1.74fbd35d7ccfcp-1, 0x1.f880p-45,
+ 0x1.75feb564267f1p-1, 0x1.3e00p-47,
+ 0x1.77024b1ab6d48p-1, -0x1.7d00p-45,
+ 0x1.780694fde5d38p-1, -0x1.d000p-50,
+ 0x1.790b938ac1d00p-1, 0x1.3000p-49,
+ 0x1.7a11473eb0178p-1, -0x1.d000p-49,
+ 0x1.7b17b0976d060p-1, 0x1.0400p-45,
+ 0x1.7c1ed0130c133p-1, 0x1.0000p-53,
+ 0x1.7d26a62ff8636p-1, -0x1.6900p-45,
+ 0x1.7e2f336cf4e3bp-1, -0x1.2e00p-47,
+ 0x1.7f3878491c3e8p-1, -0x1.4580p-45,
+ 0x1.80427543e1b4ep-1, 0x1.3000p-44,
+ 0x1.814d2add1071ap-1, 0x1.f000p-47,
+ 0x1.82589994ccd7ep-1, -0x1.1c00p-45,
+ 0x1.8364c1eb942d0p-1, 0x1.9d00p-45,
+ 0x1.8471a4623cab5p-1, 0x1.7100p-43,
+ 0x1.857f4179f5bbcp-1, 0x1.2600p-45,
+ 0x1.868d99b4491afp-1, -0x1.2c40p-44,
+ 0x1.879cad931a395p-1, -0x1.3000p-45,
+ 0x1.88ac7d98a65b8p-1, -0x1.a800p-45,
+ 0x1.89bd0a4785800p-1, -0x1.d000p-49,
+ 0x1.8ace5422aa223p-1, 0x1.3280p-44,
+ 0x1.8be05bad619fap-1, 0x1.2b40p-43,
+ 0x1.8cf3216b54383p-1, -0x1.ed00p-45,
+ 0x1.8e06a5e08664cp-1, -0x1.0500p-45,
+ 0x1.8f1ae99157807p-1, 0x1.8280p-45,
+ 0x1.902fed0282c0ep-1, -0x1.cb00p-46,
+ 0x1.9145b0b91ff96p-1, -0x1.5e00p-47,
+ 0x1.925c353aa2ff9p-1, 0x1.5400p-48,
+ 0x1.93737b0cdc64ap-1, 0x1.7200p-46,
+ 0x1.948b82b5f98aep-1, -0x1.9000p-47,
+ 0x1.95a44cbc852cbp-1, 0x1.5680p-45,
+ 0x1.96bdd9a766f21p-1, -0x1.6d00p-44,
+ 0x1.97d829fde4e2ap-1, -0x1.1000p-47,
+ 0x1.98f33e47a23a3p-1, 0x1.d000p-45,
+ 0x1.9a0f170ca0604p-1, -0x1.8a40p-44,
+ 0x1.9b2bb4d53ff89p-1, 0x1.55c0p-44,
+ 0x1.9c49182a3f15bp-1, 0x1.6b80p-45,
+ 0x1.9d674194bb8c5p-1, -0x1.c000p-49,
+ 0x1.9e86319e3238ep-1, 0x1.7d00p-46,
+ 0x1.9fa5e8d07f302p-1, 0x1.6400p-46,
+ 0x1.a0c667b5de54dp-1, -0x1.5000p-48,
+ 0x1.a1e7aed8eb8f6p-1, 0x1.9e00p-47,
+ 0x1.a309bec4a2e27p-1, 0x1.ad80p-45,
+ 0x1.a42c980460a5dp-1, -0x1.af00p-46,
+ 0x1.a5503b23e259bp-1, 0x1.b600p-47,
+ 0x1.a674a8af46213p-1, 0x1.8880p-44,
+ 0x1.a799e1330b3a7p-1, 0x1.1200p-46,
+ 0x1.a8bfe53c12e8dp-1, 0x1.6c00p-47,
+ 0x1.a9e6b5579fcd2p-1, -0x1.9b80p-45,
+ 0x1.ab0e521356fb8p-1, 0x1.b700p-45,
+ 0x1.ac36bbfd3f381p-1, 0x1.9000p-50,
+ 0x1.ad5ff3a3c2780p-1, 0x1.4000p-49,
+ 0x1.ae89f995ad2a3p-1, -0x1.c900p-45,
+ 0x1.afb4ce622f367p-1, 0x1.6500p-46,
+ 0x1.b0e07298db790p-1, 0x1.fd40p-45,
+ 0x1.b20ce6c9a89a9p-1, 0x1.2700p-46,
+ 0x1.b33a2b84f1a4bp-1, 0x1.d470p-43,
+ 0x1.b468415b747e7p-1, -0x1.8380p-44,
+ 0x1.b59728de5593ap-1, 0x1.8000p-54,
+ 0x1.b6c6e29f1c56ap-1, 0x1.ad00p-47,
+ 0x1.b7f76f2fb5e50p-1, 0x1.e800p-50,
+ 0x1.b928cf22749b2p-1, -0x1.4c00p-47,
+ 0x1.ba5b030a10603p-1, -0x1.d700p-47,
+ 0x1.bb8e0b79a6f66p-1, 0x1.d900p-47,
+ 0x1.bcc1e904bc1ffp-1, 0x1.2a00p-47,
+ 0x1.bdf69c3f3a16fp-1, -0x1.f780p-46,
+ 0x1.bf2c25bd71db8p-1, -0x1.0a00p-46,
+ 0x1.c06286141b2e9p-1, -0x1.1400p-46,
+ 0x1.c199bdd8552e0p-1, 0x1.be00p-47,
+ 0x1.c2d1cd9fa64eep-1, -0x1.9400p-47,
+ 0x1.c40ab5fffd02fp-1, -0x1.ed00p-47,
+ 0x1.c544778fafd15p-1, 0x1.9660p-44,
+ 0x1.c67f12e57d0cbp-1, -0x1.a100p-46,
+ 0x1.c7ba88988c1b6p-1, -0x1.8458p-42,
+ 0x1.c8f6d9406e733p-1, -0x1.a480p-46,
+ 0x1.ca3405751c4dfp-1, 0x1.b000p-51,
+ 0x1.cb720dcef9094p-1, 0x1.1400p-47,
+ 0x1.ccb0f2e6d1689p-1, 0x1.0200p-48,
+ 0x1.cdf0b555dc412p-1, 0x1.3600p-48,
+ 0x1.cf3155b5bab3bp-1, -0x1.6900p-47,
+ 0x1.d072d4a0789bcp-1, 0x1.9a00p-47,
+ 0x1.d1b532b08c8fap-1, -0x1.5e00p-46,
+ 0x1.d2f87080d8a85p-1, 0x1.d280p-46,
+ 0x1.d43c8eacaa203p-1, 0x1.1a00p-47,
+ 0x1.d5818dcfba491p-1, 0x1.f000p-50,
+ 0x1.d6c76e862e6a1p-1, -0x1.3a00p-47,
+ 0x1.d80e316c9834ep-1, -0x1.cd80p-47,
+ 0x1.d955d71ff6090p-1, 0x1.4c00p-48,
+ 0x1.da9e603db32aep-1, 0x1.f900p-48,
+ 0x1.dbe7cd63a8325p-1, 0x1.9800p-49,
+ 0x1.dd321f301b445p-1, -0x1.5200p-48,
+ 0x1.de7d5641c05bfp-1, -0x1.d700p-46,
+ 0x1.dfc97337b9aecp-1, -0x1.6140p-46,
+ 0x1.e11676b197d5ep-1, 0x1.b480p-47,
+ 0x1.e264614f5a3e7p-1, 0x1.0ce0p-43,
+ 0x1.e3b333b16ee5cp-1, 0x1.c680p-47,
+ 0x1.e502ee78b3fb4p-1, -0x1.9300p-47,
+ 0x1.e653924676d68p-1, -0x1.5000p-49,
+ 0x1.e7a51fbc74c44p-1, -0x1.7f80p-47,
+ 0x1.e8f7977cdb726p-1, -0x1.3700p-48,
+ 0x1.ea4afa2a490e8p-1, 0x1.5d00p-49,
+ 0x1.eb9f4867ccae4p-1, 0x1.61a0p-46,
+ 0x1.ecf482d8e680dp-1, 0x1.5500p-48,
+ 0x1.ee4aaa2188514p-1, 0x1.6400p-51,
+ 0x1.efa1bee615a13p-1, -0x1.e800p-49,
+ 0x1.f0f9c1cb64106p-1, -0x1.a880p-48,
+ 0x1.f252b376bb963p-1, -0x1.c900p-45,
+ 0x1.f3ac948dd7275p-1, 0x1.a000p-53,
+ 0x1.f50765b6e4524p-1, -0x1.4f00p-48,
+ 0x1.f6632798844fdp-1, 0x1.a800p-51,
+ 0x1.f7bfdad9cbe38p-1, 0x1.abc0p-48,
+ 0x1.f91d802243c82p-1, -0x1.4600p-50,
+ 0x1.fa7c1819e908ep-1, -0x1.b0c0p-47,
+ 0x1.fbdba3692d511p-1, -0x1.0e00p-51,
+ 0x1.fd3c22b8f7194p-1, -0x1.0de8p-46,
+ 0x1.fe9d96b2a23eep-1, 0x1.e430p-49,
+ 0x1.0000000000000p+0, 0x0.0000p+0,
+ 0x1.00b1afa5abcbep+0, -0x1.3400p-52,
+ 0x1.0163da9fb3303p+0, -0x1.2170p-46,
+ 0x1.02168143b0282p+0, 0x1.a400p-52,
+ 0x1.02c9a3e77806cp+0, 0x1.f980p-49,
+ 0x1.037d42e11bbcap+0, -0x1.7400p-51,
+ 0x1.04315e86e7f89p+0, 0x1.8300p-50,
+ 0x1.04e5f72f65467p+0, -0x1.a3f0p-46,
+ 0x1.059b0d315855ap+0, -0x1.2840p-47,
+ 0x1.0650a0e3c1f95p+0, 0x1.1600p-48,
+ 0x1.0706b29ddf71ap+0, 0x1.5240p-46,
+ 0x1.07bd42b72a82dp+0, -0x1.9a00p-49,
+ 0x1.0874518759bd0p+0, 0x1.6400p-49,
+ 0x1.092bdf66607c8p+0, -0x1.0780p-47,
+ 0x1.09e3ecac6f383p+0, -0x1.8000p-54,
+ 0x1.0a9c79b1f3930p+0, 0x1.fa00p-48,
+ 0x1.0b5586cf988fcp+0, -0x1.ac80p-48,
+ 0x1.0c0f145e46c8ap+0, 0x1.9c00p-50,
+ 0x1.0cc922b724816p+0, 0x1.5200p-47,
+ 0x1.0d83b23395dd8p+0, -0x1.ad00p-48,
+ 0x1.0e3ec32d3d1f3p+0, 0x1.bac0p-46,
+ 0x1.0efa55fdfa9a6p+0, -0x1.4e80p-47,
+ 0x1.0fb66affed2f0p+0, -0x1.d300p-47,
+ 0x1.1073028d7234bp+0, 0x1.1500p-48,
+ 0x1.11301d0125b5bp+0, 0x1.c000p-49,
+ 0x1.11edbab5e2af9p+0, 0x1.6bc0p-46,
+ 0x1.12abdc06c31d5p+0, 0x1.8400p-49,
+ 0x1.136a814f2047dp+0, -0x1.ed00p-47,
+ 0x1.1429aaea92de9p+0, 0x1.8e00p-49,
+ 0x1.14e95934f3138p+0, 0x1.b400p-49,
+ 0x1.15a98c8a58e71p+0, 0x1.5300p-47,
+ 0x1.166a45471c3dfp+0, 0x1.3380p-47,
+ 0x1.172b83c7d5211p+0, 0x1.8d40p-45,
+ 0x1.17ed48695bb9fp+0, -0x1.5d00p-47,
+ 0x1.18af9388c8d93p+0, -0x1.c880p-46,
+ 0x1.1972658375d66p+0, 0x1.1f00p-46,
+ 0x1.1a35beb6fcba7p+0, 0x1.0480p-46,
+ 0x1.1af99f81387e3p+0, -0x1.7390p-43,
+ 0x1.1bbe084045d54p+0, 0x1.4e40p-45,
+ 0x1.1c82f95281c43p+0, -0x1.a200p-47,
+ 0x1.1d4873168b9b2p+0, 0x1.3800p-49,
+ 0x1.1e0e75eb44031p+0, 0x1.ac00p-49,
+ 0x1.1ed5022fcd938p+0, 0x1.1900p-47,
+ 0x1.1f9c18438cdf7p+0, -0x1.b780p-46,
+ 0x1.2063b88628d8fp+0, 0x1.d940p-45,
+ 0x1.212be3578a81ep+0, 0x1.8000p-50,
+ 0x1.21f49917ddd41p+0, 0x1.b340p-45,
+ 0x1.22bdda2791323p+0, 0x1.9f80p-46,
+ 0x1.2387a6e7561e7p+0, -0x1.9c80p-46,
+ 0x1.2451ffb821427p+0, 0x1.2300p-47,
+ 0x1.251ce4fb2a602p+0, -0x1.3480p-46,
+ 0x1.25e85711eceb0p+0, 0x1.2700p-46,
+ 0x1.26b4565e27d16p+0, 0x1.1d00p-46,
+ 0x1.2780e341de00fp+0, 0x1.1ee0p-44,
+ 0x1.284dfe1f5633ep+0, -0x1.4c00p-46,
+ 0x1.291ba7591bb30p+0, -0x1.3d80p-46,
+ 0x1.29e9df51fdf09p+0, 0x1.8b00p-47,
+ 0x1.2ab8a66d10e9bp+0, -0x1.27c0p-45,
+ 0x1.2b87fd0dada3ap+0, 0x1.a340p-45,
+ 0x1.2c57e39771af9p+0, -0x1.0800p-46,
+ 0x1.2d285a6e402d9p+0, -0x1.ed00p-47,
+ 0x1.2df961f641579p+0, -0x1.4200p-48,
+ 0x1.2ecafa93e2ecfp+0, -0x1.4980p-45,
+ 0x1.2f9d24abd8822p+0, -0x1.6300p-46,
+ 0x1.306fe0a31b625p+0, -0x1.2360p-44,
+ 0x1.31432edeea50bp+0, -0x1.0df8p-40,
+ 0x1.32170fc4cd7b8p+0, -0x1.2480p-45,
+ 0x1.32eb83ba8e9a2p+0, -0x1.5980p-45,
+ 0x1.33c08b2641766p+0, 0x1.ed00p-46,
+ 0x1.3496266e3fa27p+0, -0x1.c000p-50,
+ 0x1.356c55f929f0fp+0, -0x1.0d80p-44,
+ 0x1.36431a2de88b9p+0, 0x1.2c80p-45,
+ 0x1.371a7373aaa39p+0, 0x1.0600p-45,
+ 0x1.37f26231e74fep+0, -0x1.6600p-46,
+ 0x1.38cae6d05d838p+0, -0x1.ae00p-47,
+ 0x1.39a401b713ec3p+0, -0x1.4720p-43,
+ 0x1.3a7db34e5a020p+0, 0x1.8200p-47,
+ 0x1.3b57fbfec6e95p+0, 0x1.e800p-44,
+ 0x1.3c32dc313a8f2p+0, 0x1.f800p-49,
+ 0x1.3d0e544ede122p+0, -0x1.7a00p-46,
+ 0x1.3dea64c1234bbp+0, 0x1.6300p-45,
+ 0x1.3ec70df1c4eccp+0, -0x1.8a60p-43,
+ 0x1.3fa4504ac7e8cp+0, -0x1.cdc0p-44,
+ 0x1.40822c367a0bbp+0, 0x1.5b80p-45,
+ 0x1.4160a21f72e95p+0, 0x1.ec00p-46,
+ 0x1.423fb27094646p+0, -0x1.3600p-46,
+ 0x1.431f5d950a920p+0, 0x1.3980p-45,
+ 0x1.43ffa3f84b9ebp+0, 0x1.a000p-48,
+ 0x1.44e0860618919p+0, -0x1.6c00p-48,
+ 0x1.45c2042a7d201p+0, -0x1.bc00p-47,
+ 0x1.46a41ed1d0016p+0, -0x1.2800p-46,
+ 0x1.4786d668b3326p+0, 0x1.0e00p-44,
+ 0x1.486a2b5c13c00p+0, -0x1.d400p-45,
+ 0x1.494e1e192af04p+0, 0x1.c200p-47,
+ 0x1.4a32af0d7d372p+0, -0x1.e500p-46,
+ 0x1.4b17dea6db801p+0, 0x1.7800p-47,
+ 0x1.4bfdad53629e1p+0, -0x1.3800p-46,
+ 0x1.4ce41b817c132p+0, 0x1.0800p-47,
+ 0x1.4dcb299fddddbp+0, 0x1.c700p-45,
+ 0x1.4eb2d81d8ab96p+0, -0x1.ce00p-46,
+ 0x1.4f9b2769d2d02p+0, 0x1.9200p-46,
+ 0x1.508417f4531c1p+0, -0x1.8c00p-47,
+ 0x1.516daa2cf662ap+0, -0x1.a000p-48,
+ 0x1.5257de83f51eap+0, 0x1.a080p-43,
+ 0x1.5342b569d4edap+0, -0x1.6d80p-45,
+ 0x1.542e2f4f6ac1ap+0, -0x1.2440p-44,
+ 0x1.551a4ca5d94dbp+0, 0x1.83c0p-43,
+ 0x1.56070dde9116bp+0, 0x1.4b00p-45,
+ 0x1.56f4736b529dep+0, 0x1.15a0p-43,
+ 0x1.57e27dbe2c40ep+0, -0x1.9e00p-45,
+ 0x1.58d12d497c76fp+0, -0x1.3080p-45,
+ 0x1.59c0827ff0b4cp+0, 0x1.dec0p-43,
+ 0x1.5ab07dd485427p+0, -0x1.4000p-51,
+ 0x1.5ba11fba87af4p+0, 0x1.0080p-44,
+ 0x1.5c9268a59460bp+0, -0x1.6c80p-45,
+ 0x1.5d84590998e3fp+0, 0x1.69a0p-43,
+ 0x1.5e76f15ad20e1p+0, -0x1.b400p-46,
+ 0x1.5f6a320dcebcap+0, 0x1.7700p-46,
+ 0x1.605e1b976dcb8p+0, 0x1.6f80p-45,
+ 0x1.6152ae6cdf715p+0, 0x1.1000p-47,
+ 0x1.6247eb03a5531p+0, -0x1.5d00p-46,
+ 0x1.633dd1d1929b5p+0, -0x1.2d00p-46,
+ 0x1.6434634ccc313p+0, -0x1.a800p-49,
+ 0x1.652b9febc8efap+0, -0x1.8600p-45,
+ 0x1.6623882553397p+0, 0x1.1fe0p-40,
+ 0x1.671c1c708328ep+0, -0x1.7200p-44,
+ 0x1.68155d44ca97ep+0, 0x1.6800p-49,
+ 0x1.690f4b19e9471p+0, -0x1.9780p-45,
+};
+
+/*
+ * exp2(x): compute the base 2 exponential of x
+ *
+ * Accuracy: Peak error < 0.503 ulp for normalized results.
+ *
+ * Method: (accurate tables)
+ *
+ * Reduce x:
+ * x = 2**k + y, for integer k and |y| <= 1/2.
+ * Thus we have exp2(x) = 2**k * exp2(y).
+ *
+ * Reduce y:
+ * y = i/TBLSIZE + z - eps[i] for integer i near y * TBLSIZE.
+ * Thus we have exp2(y) = exp2(i/TBLSIZE) * exp2(z - eps[i]),
+ * with |z - eps[i]| <= 2**-9 + 2**-39 for the table used.
+ *
+ * We compute exp2(i/TBLSIZE) via table lookup and exp2(z - eps[i]) via
+ * a degree-5 minimax polynomial with maximum error under 1.3 * 2**-61.
+ * The values in exp2t[] and eps[] are chosen such that
+ * exp2t[i] = exp2(i/TBLSIZE + eps[i]), and eps[i] is a small offset such
+ * that exp2t[i] is accurate to 2**-64.
+ *
+ * Note that the range of i is +-TBLSIZE/2, so we actually index the tables
+ * by i0 = i + TBLSIZE/2. For cache efficiency, exp2t[] and eps[] are
+ * virtual tables, interleaved in the real table tbl[].
+ *
+ * This method is due to Gal, with many details due to Gal and Bachelis:
+ *
+ * Gal, S. and Bachelis, B. An Accurate Elementary Mathematical Library
+ * for the IEEE Floating Point Standard. TOMS 17(1), 26-46 (1991).
+ */
+OLM_DLLEXPORT double
+exp2(double x)
+{
+ double r, t, twopk, twopkp1000, z;
+ u_int32_t hx, ix, lx, i0;
+ int k;
+
+ /* Filter out exceptional cases. */
+ GET_HIGH_WORD(hx,x);
+ ix = hx & 0x7fffffff; /* high word of |x| */
+ if(ix >= 0x40900000) { /* |x| >= 1024 */
+ if(ix >= 0x7ff00000) {
+ GET_LOW_WORD(lx,x);
+ if(((ix & 0xfffff) | lx) != 0 || (hx & 0x80000000) == 0)
+ return (x + x); /* x is NaN or +Inf */
+ else
+ return (0.0); /* x is -Inf */
+ }
+ if(x >= 0x1.0p10)
+ return (huge * huge); /* overflow */
+ if(x <= -0x1.0ccp10)
+ return (twom1000 * twom1000); /* underflow */
+ } else if (ix < 0x3c900000) { /* |x| < 0x1p-54 */
+ return (1.0 + x);
+ }
+
+ /* Reduce x, computing z, i0, and k. */
+ STRICT_ASSIGN(double, t, x + redux);
+ GET_LOW_WORD(i0, t);
+ i0 += TBLSIZE / 2;
+ k = (i0 >> TBLBITS) << 20;
+ i0 = (i0 & (TBLSIZE - 1)) << 1;
+ t -= redux;
+ z = x - t;
+
+ /* Compute r = exp2(y) = exp2t[i0] * p(z - eps[i]). */
+ t = tbl[i0]; /* exp2t[i0] */
+ z -= tbl[i0 + 1]; /* eps[i0] */
+ if (k >= -(1021 << 20))
+ INSERT_WORDS(twopk, 0x3ff00000 + k, 0);
+ else
+ INSERT_WORDS(twopkp1000, 0x3ff00000 + k + (1000 << 20), 0);
+ r = t + t * z * (P1 + z * (P2 + z * (P3 + z * (P4 + z * P5))));
+
+ /* Scale by 2**(k>>20). */
+ if(k >= -(1021 << 20)) {
+ if (k == 1024 << 20)
+ return (r * 2.0 * 0x1p1023);
+ return (r * twopk);
+ } else {
+ return (r * twopkp1000 * twom1000);
+ }
+}
+
+#if (LDBL_MANT_DIG == 53)
+__weak_reference(exp2, exp2l);
+#endif
--- /dev/null
+/*-
+ * Copyright (c) 2005 David Schultz <das@FreeBSD.ORG>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/src/s_exp2f.c,v 1.9 2008/02/22 02:27:34 das Exp $");
+
+#include <float.h>
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+#define TBLBITS 4
+#define TBLSIZE (1 << TBLBITS)
+
+static const float
+ huge = 0x1p100f,
+ redux = 0x1.8p23f / TBLSIZE,
+ P1 = 0x1.62e430p-1f,
+ P2 = 0x1.ebfbe0p-3f,
+ P3 = 0x1.c6b348p-5f,
+ P4 = 0x1.3b2c9cp-7f;
+
+static volatile float twom100 = 0x1p-100f;
+
+static const double exp2ft[TBLSIZE] = {
+ 0x1.6a09e667f3bcdp-1,
+ 0x1.7a11473eb0187p-1,
+ 0x1.8ace5422aa0dbp-1,
+ 0x1.9c49182a3f090p-1,
+ 0x1.ae89f995ad3adp-1,
+ 0x1.c199bdd85529cp-1,
+ 0x1.d5818dcfba487p-1,
+ 0x1.ea4afa2a490dap-1,
+ 0x1.0000000000000p+0,
+ 0x1.0b5586cf9890fp+0,
+ 0x1.172b83c7d517bp+0,
+ 0x1.2387a6e756238p+0,
+ 0x1.306fe0a31b715p+0,
+ 0x1.3dea64c123422p+0,
+ 0x1.4bfdad5362a27p+0,
+ 0x1.5ab07dd485429p+0,
+};
+
+/*
+ * exp2f(x): compute the base 2 exponential of x
+ *
+ * Accuracy: Peak error < 0.501 ulp; location of peak: -0.030110927.
+ *
+ * Method: (equally-spaced tables)
+ *
+ * Reduce x:
+ * x = 2**k + y, for integer k and |y| <= 1/2.
+ * Thus we have exp2f(x) = 2**k * exp2(y).
+ *
+ * Reduce y:
+ * y = i/TBLSIZE + z for integer i near y * TBLSIZE.
+ * Thus we have exp2(y) = exp2(i/TBLSIZE) * exp2(z),
+ * with |z| <= 2**-(TBLSIZE+1).
+ *
+ * We compute exp2(i/TBLSIZE) via table lookup and exp2(z) via a
+ * degree-4 minimax polynomial with maximum error under 1.4 * 2**-33.
+ * Using double precision for everything except the reduction makes
+ * roundoff error insignificant and simplifies the scaling step.
+ *
+ * This method is due to Tang, but I do not use his suggested parameters:
+ *
+ * Tang, P. Table-driven Implementation of the Exponential Function
+ * in IEEE Floating-Point Arithmetic. TOMS 15(2), 144-157 (1989).
+ */
+OLM_DLLEXPORT float
+exp2f(float x)
+{
+ double tv, twopk, u, z;
+ float t;
+ u_int32_t hx, ix, i0;
+ int32_t k;
+
+ /* Filter out exceptional cases. */
+ GET_FLOAT_WORD(hx, x);
+ ix = hx & 0x7fffffff; /* high word of |x| */
+ if(ix >= 0x43000000) { /* |x| >= 128 */
+ if(ix >= 0x7f800000) {
+ if ((ix & 0x7fffff) != 0 || (hx & 0x80000000) == 0)
+ return (x + x); /* x is NaN or +Inf */
+ else
+ return (0.0); /* x is -Inf */
+ }
+ if(x >= 0x1.0p7f)
+ return (huge * huge); /* overflow */
+ if(x <= -0x1.2cp7f)
+ return (twom100 * twom100); /* underflow */
+ } else if (ix <= 0x33000000) { /* |x| <= 0x1p-25 */
+ return (1.0f + x);
+ }
+
+ /* Reduce x, computing z, i0, and k. */
+ STRICT_ASSIGN(float, t, x + redux);
+ GET_FLOAT_WORD(i0, t);
+ i0 += TBLSIZE / 2;
+ k = (i0 >> TBLBITS) << 20;
+ i0 &= TBLSIZE - 1;
+ t -= redux;
+ z = x - t;
+ INSERT_WORDS(twopk, 0x3ff00000 + k, 0);
+
+ /* Compute r = exp2(y) = exp2ft[i0] * p(z). */
+ tv = exp2ft[i0];
+ u = tv * z;
+ tv = tv + u * (P1 + z * P2) + u * (z * z) * (P3 + z * P4);
+
+ /* Scale by 2**(k>>20). */
+ return (tv * twopk);
+}
--- /dev/null
+/* @(#)s_expm1.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/src/s_expm1.c,v 1.12 2011/10/21 06:26:38 das Exp $");
+
+/* expm1(x)
+ * Returns exp(x)-1, the exponential of x minus 1.
+ *
+ * Method
+ * 1. Argument reduction:
+ * Given x, find r and integer k such that
+ *
+ * x = k*ln2 + r, |r| <= 0.5*ln2 ~ 0.34658
+ *
+ * Here a correction term c will be computed to compensate
+ * the error in r when rounded to a floating-point number.
+ *
+ * 2. Approximating expm1(r) by a special rational function on
+ * the interval [0,0.34658]:
+ * Since
+ * r*(exp(r)+1)/(exp(r)-1) = 2+ r^2/6 - r^4/360 + ...
+ * we define R1(r*r) by
+ * r*(exp(r)+1)/(exp(r)-1) = 2+ r^2/6 * R1(r*r)
+ * That is,
+ * R1(r**2) = 6/r *((exp(r)+1)/(exp(r)-1) - 2/r)
+ * = 6/r * ( 1 + 2.0*(1/(exp(r)-1) - 1/r))
+ * = 1 - r^2/60 + r^4/2520 - r^6/100800 + ...
+ * We use a special Reme algorithm on [0,0.347] to generate
+ * a polynomial of degree 5 in r*r to approximate R1. The
+ * maximum error of this polynomial approximation is bounded
+ * by 2**-61. In other words,
+ * R1(z) ~ 1.0 + Q1*z + Q2*z**2 + Q3*z**3 + Q4*z**4 + Q5*z**5
+ * where Q1 = -1.6666666666666567384E-2,
+ * Q2 = 3.9682539681370365873E-4,
+ * Q3 = -9.9206344733435987357E-6,
+ * Q4 = 2.5051361420808517002E-7,
+ * Q5 = -6.2843505682382617102E-9;
+ * z = r*r,
+ * with error bounded by
+ * | 5 | -61
+ * | 1.0+Q1*z+...+Q5*z - R1(z) | <= 2
+ * | |
+ *
+ * expm1(r) = exp(r)-1 is then computed by the following
+ * specific way which minimize the accumulation rounding error:
+ * 2 3
+ * r r [ 3 - (R1 + R1*r/2) ]
+ * expm1(r) = r + --- + --- * [--------------------]
+ * 2 2 [ 6 - r*(3 - R1*r/2) ]
+ *
+ * To compensate the error in the argument reduction, we use
+ * expm1(r+c) = expm1(r) + c + expm1(r)*c
+ * ~ expm1(r) + c + r*c
+ * Thus c+r*c will be added in as the correction terms for
+ * expm1(r+c). Now rearrange the term to avoid optimization
+ * screw up:
+ * ( 2 2 )
+ * ({ ( r [ R1 - (3 - R1*r/2) ] ) } r )
+ * expm1(r+c)~r - ({r*(--- * [--------------------]-c)-c} - --- )
+ * ({ ( 2 [ 6 - r*(3 - R1*r/2) ] ) } 2 )
+ * ( )
+ *
+ * = r - E
+ * 3. Scale back to obtain expm1(x):
+ * From step 1, we have
+ * expm1(x) = either 2^k*[expm1(r)+1] - 1
+ * = or 2^k*[expm1(r) + (1-2^-k)]
+ * 4. Implementation notes:
+ * (A). To save one multiplication, we scale the coefficient Qi
+ * to Qi*2^i, and replace z by (x^2)/2.
+ * (B). To achieve maximum accuracy, we compute expm1(x) by
+ * (i) if x < -56*ln2, return -1.0, (raise inexact if x!=inf)
+ * (ii) if k=0, return r-E
+ * (iii) if k=-1, return 0.5*(r-E)-0.5
+ * (iv) if k=1 if r < -0.25, return 2*((r+0.5)- E)
+ * else return 1.0+2.0*(r-E);
+ * (v) if (k<-2||k>56) return 2^k(1-(E-r)) - 1 (or exp(x)-1)
+ * (vi) if k <= 20, return 2^k((1-2^-k)-(E-r)), else
+ * (vii) return 2^k(1-((E+2^-k)-r))
+ *
+ * Special cases:
+ * expm1(INF) is INF, expm1(NaN) is NaN;
+ * expm1(-INF) is -1, and
+ * for finite argument, only expm1(0)=0 is exact.
+ *
+ * Accuracy:
+ * according to an error analysis, the error is always less than
+ * 1 ulp (unit in the last place).
+ *
+ * Misc. info.
+ * For IEEE double
+ * if x > 7.09782712893383973096e+02 then expm1(x) overflow
+ *
+ * Constants:
+ * The hexadecimal values are the intended ones for the following
+ * constants. The decimal values may be used, provided that the
+ * compiler will convert from decimal to binary accurately enough
+ * to produce the hexadecimal values shown.
+ */
+
+#include <float.h>
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+static const double
+one = 1.0,
+huge = 1.0e+300,
+tiny = 1.0e-300,
+o_threshold = 7.09782712893383973096e+02,/* 0x40862E42, 0xFEFA39EF */
+ln2_hi = 6.93147180369123816490e-01,/* 0x3fe62e42, 0xfee00000 */
+ln2_lo = 1.90821492927058770002e-10,/* 0x3dea39ef, 0x35793c76 */
+invln2 = 1.44269504088896338700e+00,/* 0x3ff71547, 0x652b82fe */
+/* Scaled Q's: Qn_here = 2**n * Qn_above, for R(2*z) where z = hxs = x*x/2: */
+Q1 = -3.33333333333331316428e-02, /* BFA11111 111110F4 */
+Q2 = 1.58730158725481460165e-03, /* 3F5A01A0 19FE5585 */
+Q3 = -7.93650757867487942473e-05, /* BF14CE19 9EAADBB7 */
+Q4 = 4.00821782732936239552e-06, /* 3ED0CFCA 86E65239 */
+Q5 = -2.01099218183624371326e-07; /* BE8AFDB7 6E09C32D */
+
+OLM_DLLEXPORT double
+expm1(double x)
+{
+ double y,hi,lo,c,t,e,hxs,hfx,r1,twopk;
+ int32_t k,xsb;
+ u_int32_t hx;
+
+ GET_HIGH_WORD(hx,x);
+ xsb = hx&0x80000000; /* sign bit of x */
+ hx &= 0x7fffffff; /* high word of |x| */
+
+ /* filter out huge and non-finite argument */
+ if(hx >= 0x4043687A) { /* if |x|>=56*ln2 */
+ if(hx >= 0x40862E42) { /* if |x|>=709.78... */
+ if(hx>=0x7ff00000) {
+ u_int32_t low;
+ GET_LOW_WORD(low,x);
+ if(((hx&0xfffff)|low)!=0)
+ return x+x; /* NaN */
+ else return (xsb==0)? x:-1.0;/* exp(+-inf)-1={inf,-1} */
+ }
+ if(x > o_threshold) return huge*huge; /* overflow */
+ }
+ if(xsb!=0) { /* x < -56*ln2, return -1.0 with inexact */
+ if(x+tiny<0.0) /* raise inexact */
+ return tiny-one; /* return -1 */
+ }
+ }
+
+ /* argument reduction */
+ if(hx > 0x3fd62e42) { /* if |x| > 0.5 ln2 */
+ if(hx < 0x3FF0A2B2) { /* and |x| < 1.5 ln2 */
+ if(xsb==0)
+ {hi = x - ln2_hi; lo = ln2_lo; k = 1;}
+ else
+ {hi = x + ln2_hi; lo = -ln2_lo; k = -1;}
+ } else {
+ k = invln2*x+((xsb==0)?0.5:-0.5);
+ t = k;
+ hi = x - t*ln2_hi; /* t*ln2_hi is exact here */
+ lo = t*ln2_lo;
+ }
+ STRICT_ASSIGN(double, x, hi - lo);
+ c = (hi-x)-lo;
+ }
+ else if(hx < 0x3c900000) { /* when |x|<2**-54, return x */
+ t = huge+x; /* return x with inexact flags when x!=0 */
+ return x - (t-(huge+x));
+ }
+ else k = 0;
+
+ /* x is now in primary range */
+ hfx = 0.5*x;
+ hxs = x*hfx;
+ r1 = one+hxs*(Q1+hxs*(Q2+hxs*(Q3+hxs*(Q4+hxs*Q5))));
+ t = 3.0-r1*hfx;
+ e = hxs*((r1-t)/(6.0 - x*t));
+ if(k==0) return x - (x*e-hxs); /* c is 0 */
+ else {
+ INSERT_WORDS(twopk,0x3ff00000+(k<<20),0); /* 2^k */
+ e = (x*(e-c)-c);
+ e -= hxs;
+ if(k== -1) return 0.5*(x-e)-0.5;
+ if(k==1) {
+ if(x < -0.25) return -2.0*(e-(x+0.5));
+ else return one+2.0*(x-e);
+ }
+ if (k <= -2 || k>56) { /* suffice to return exp(x)-1 */
+ y = one-(e-x);
+ if (k == 1024) y = y*2.0*0x1p1023;
+ else y = y*twopk;
+ return y-one;
+ }
+ t = one;
+ if(k<20) {
+ SET_HIGH_WORD(t,0x3ff00000 - (0x200000>>k)); /* t=1-2^-k */
+ y = t-(e-x);
+ y = y*twopk;
+ } else {
+ SET_HIGH_WORD(t,((0x3ff-k)<<20)); /* 2^-k */
+ y = x-(e+t);
+ y += one;
+ y = y*twopk;
+ }
+ }
+ return y;
+}
--- /dev/null
+/* s_expm1f.c -- float version of s_expm1.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/src/s_expm1f.c,v 1.12 2011/10/21 06:26:38 das Exp $");
+
+#include <float.h>
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+static const float
+one = 1.0,
+huge = 1.0e+30,
+tiny = 1.0e-30,
+o_threshold = 8.8721679688e+01,/* 0x42b17180 */
+ln2_hi = 6.9313812256e-01,/* 0x3f317180 */
+ln2_lo = 9.0580006145e-06,/* 0x3717f7d1 */
+invln2 = 1.4426950216e+00,/* 0x3fb8aa3b */
+/*
+ * Domain [-0.34568, 0.34568], range ~[-6.694e-10, 6.696e-10]:
+ * |6 / x * (1 + 2 * (1 / (exp(x) - 1) - 1 / x)) - q(x)| < 2**-30.04
+ * Scaled coefficients: Qn_here = 2**n * Qn_for_q (see s_expm1.c):
+ */
+Q1 = -3.3333212137e-2, /* -0x888868.0p-28 */
+Q2 = 1.5807170421e-3; /* 0xcf3010.0p-33 */
+
+OLM_DLLEXPORT float
+expm1f(float x)
+{
+ float y,hi,lo,c,t,e,hxs,hfx,r1,twopk;
+ int32_t k,xsb;
+ u_int32_t hx;
+
+ GET_FLOAT_WORD(hx,x);
+ xsb = hx&0x80000000; /* sign bit of x */
+ hx &= 0x7fffffff; /* high word of |x| */
+
+ /* filter out huge and non-finite argument */
+ if(hx >= 0x4195b844) { /* if |x|>=27*ln2 */
+ if(hx >= 0x42b17218) { /* if |x|>=88.721... */
+ if(hx>0x7f800000)
+ return x+x; /* NaN */
+ if(hx==0x7f800000)
+ return (xsb==0)? x:-1.0;/* exp(+-inf)={inf,-1} */
+ if(x > o_threshold) return huge*huge; /* overflow */
+ }
+ if(xsb!=0) { /* x < -27*ln2, return -1.0 with inexact */
+ if(x+tiny<(float)0.0) /* raise inexact */
+ return tiny-one; /* return -1 */
+ }
+ }
+
+ /* argument reduction */
+ if(hx > 0x3eb17218) { /* if |x| > 0.5 ln2 */
+ if(hx < 0x3F851592) { /* and |x| < 1.5 ln2 */
+ if(xsb==0)
+ {hi = x - ln2_hi; lo = ln2_lo; k = 1;}
+ else
+ {hi = x + ln2_hi; lo = -ln2_lo; k = -1;}
+ } else {
+ k = invln2*x+((xsb==0)?(float)0.5:(float)-0.5);
+ t = k;
+ hi = x - t*ln2_hi; /* t*ln2_hi is exact here */
+ lo = t*ln2_lo;
+ }
+ STRICT_ASSIGN(float, x, hi - lo);
+ c = (hi-x)-lo;
+ }
+ else if(hx < 0x33000000) { /* when |x|<2**-25, return x */
+ t = huge+x; /* return x with inexact flags when x!=0 */
+ return x - (t-(huge+x));
+ }
+ else k = 0;
+
+ /* x is now in primary range */
+ hfx = (float)0.5*x;
+ hxs = x*hfx;
+ r1 = one+hxs*(Q1+hxs*Q2);
+ t = (float)3.0-r1*hfx;
+ e = hxs*((r1-t)/((float)6.0 - x*t));
+ if(k==0) return x - (x*e-hxs); /* c is 0 */
+ else {
+ SET_FLOAT_WORD(twopk,0x3f800000+(k<<23)); /* 2^k */
+ e = (x*(e-c)-c);
+ e -= hxs;
+ if(k== -1) return (float)0.5*(x-e)-(float)0.5;
+ if(k==1) {
+ if(x < (float)-0.25) return -(float)2.0*(e-(x+(float)0.5));
+ else return one+(float)2.0*(x-e);
+ }
+ if (k <= -2 || k>56) { /* suffice to return exp(x)-1 */
+ y = one-(e-x);
+ if (k == 128) y = y*2.0F*0x1p127F;
+ else y = y*twopk;
+ return y-one;
+ }
+ t = one;
+ if(k<23) {
+ SET_FLOAT_WORD(t,0x3f800000 - (0x1000000>>k)); /* t=1-2^-k */
+ y = t-(e-x);
+ y = y*twopk;
+ } else {
+ SET_FLOAT_WORD(t,((0x7f-k)<<23)); /* 2^-k */
+ y = x-(e+t);
+ y += one;
+ y = y*twopk;
+ }
+ }
+ return y;
+}
--- /dev/null
+/* @(#)s_fabs.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/*
+ * fabs(x) returns the absolute value of x.
+ */
+
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+OLM_DLLEXPORT double
+fabs(double x)
+{
+ u_int32_t high;
+ GET_HIGH_WORD(high,x);
+ SET_HIGH_WORD(x,high&0x7fffffff);
+ return x;
+}
--- /dev/null
+/* s_fabsf.c -- float version of s_fabs.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/src/s_fabsf.c,v 1.8 2008/02/22 02:30:35 das Exp $");
+
+/*
+ * fabsf(x) returns the absolute value of x.
+ */
+
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+OLM_DLLEXPORT float
+fabsf(float x)
+{
+ u_int32_t ix;
+ GET_FLOAT_WORD(ix,x);
+ SET_FLOAT_WORD(x,ix&0x7fffffff);
+ return x;
+}
--- /dev/null
+/*-
+ * Copyright (c) 2003 Dag-Erling Coïdan Smørgrav
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer
+ * in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD: src/lib/msun/src/s_fabsl.c,v 1.2 2003/10/25 19:53:28 des Exp $
+ */
+
+#include <openlibm_math.h>
+#include "math_private.h"
+#include "fpmath.h"
+
+OLM_DLLEXPORT long double
+fabsl(long double x)
+{
+ union IEEEl2bits u;
+
+ u.e = x;
+ u.bits.sign = 0;
+ return (u.e);
+}
--- /dev/null
+/*-
+ * Copyright (c) 2004 David Schultz <das@FreeBSD.ORG>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/src/s_fdim.c,v 1.1 2004/06/30 07:04:01 das Exp $");
+#include <openlibm_math.h>
+#include "math_private.h"
+
+#define DECL(type, fn) \
+OLM_DLLEXPORT type \
+fn(type x, type y) \
+{ \
+ \
+ if (isnan(x)) \
+ return (x); \
+ if (isnan(y)) \
+ return (y); \
+ return (x > y ? x - y : 0.0); \
+}
+
+DECL(double, fdim)
+DECL(float, fdimf)
+DECL(long double, fdiml)
--- /dev/null
+/* @(#)s_floor.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/src/s_floor.c,v 1.11 2008/02/15 07:01:40 bde Exp $");
+
+/*
+ * floor(x)
+ * Return x rounded toward -inf to integral value
+ * Method:
+ * Bit twiddling.
+ * Exception:
+ * Inexact flag raised if x not equal to floor(x).
+ */
+
+#include <float.h>
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+static const double huge = 1.0e300;
+
+OLM_DLLEXPORT double
+floor(double x)
+{
+ int32_t i0,i1,j0;
+ u_int32_t i,j;
+ EXTRACT_WORDS(i0,i1,x);
+ j0 = ((i0>>20)&0x7ff)-0x3ff;
+ if(j0<20) {
+ if(j0<0) { /* raise inexact if x != 0 */
+ if(huge+x>0.0) {/* return 0*sign(x) if |x|<1 */
+ if(i0>=0) {i0=i1=0;}
+ else if(((i0&0x7fffffff)|i1)!=0)
+ { i0=0xbff00000;i1=0;}
+ }
+ } else {
+ i = (0x000fffff)>>j0;
+ if(((i0&i)|i1)==0) return x; /* x is integral */
+ if(huge+x>0.0) { /* raise inexact flag */
+ if(i0<0) i0 += (0x00100000)>>j0;
+ i0 &= (~i); i1=0;
+ }
+ }
+ } else if (j0>51) {
+ if(j0==0x400) return x+x; /* inf or NaN */
+ else return x; /* x is integral */
+ } else {
+ i = ((u_int32_t)(0xffffffff))>>(j0-20);
+ if((i1&i)==0) return x; /* x is integral */
+ if(huge+x>0.0) { /* raise inexact flag */
+ if(i0<0) {
+ if(j0==20) i0+=1;
+ else {
+ j = i1+(1<<(52-j0));
+ if(j<i1) i0 +=1 ; /* got a carry */
+ i1=j;
+ }
+ }
+ i1 &= (~i);
+ }
+ }
+ INSERT_WORDS(x,i0,i1);
+ return x;
+}
+
+#if LDBL_MANT_DIG == 53
+__weak_reference(floor, floorl);
+#endif
--- /dev/null
+/* s_floorf.c -- float version of s_floor.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/src/s_floorf.c,v 1.8 2008/02/22 02:30:35 das Exp $");
+
+/*
+ * floorf(x)
+ * Return x rounded toward -inf to integral value
+ * Method:
+ * Bit twiddling.
+ * Exception:
+ * Inexact flag raised if x not equal to floorf(x).
+ */
+
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+static const float huge = 1.0e30;
+
+OLM_DLLEXPORT float
+floorf(float x)
+{
+ int32_t i0,j0;
+ u_int32_t i;
+ GET_FLOAT_WORD(i0,x);
+ j0 = ((i0>>23)&0xff)-0x7f;
+ if(j0<23) {
+ if(j0<0) { /* raise inexact if x != 0 */
+ if(huge+x>(float)0.0) {/* return 0*sign(x) if |x|<1 */
+ if(i0>=0) {i0=0;}
+ else if((i0&0x7fffffff)!=0)
+ { i0=0xbf800000;}
+ }
+ } else {
+ i = (0x007fffff)>>j0;
+ if((i0&i)==0) return x; /* x is integral */
+ if(huge+x>(float)0.0) { /* raise inexact flag */
+ if(i0<0) i0 += (0x00800000)>>j0;
+ i0 &= (~i);
+ }
+ }
+ } else {
+ if(j0==0x80) return x+x; /* inf or NaN */
+ else return x; /* x is integral */
+ }
+ SET_FLOAT_WORD(x,i0);
+ return x;
+}
--- /dev/null
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ *
+ * From: @(#)s_floor.c 5.1 93/09/24
+ */
+
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/src/s_floorl.c,v 1.8 2008/02/14 15:10:34 bde Exp $");
+
+/*
+ * floorl(x)
+ * Return x rounded toward -inf to integral value
+ * Method:
+ * Bit twiddling.
+ * Exception:
+ * Inexact flag raised if x not equal to floorl(x).
+ */
+
+#include <float.h>
+#include <openlibm_math.h>
+#include <stdint.h>
+
+#include "fpmath.h"
+#include "math_private.h"
+
+#ifdef LDBL_IMPLICIT_NBIT
+#define MANH_SIZE (LDBL_MANH_SIZE + 1)
+#define INC_MANH(u, c) do { \
+ uint64_t o = u.bits.manh; \
+ u.bits.manh += (c); \
+ if (u.bits.manh < o) \
+ u.bits.exp++; \
+} while (0)
+#else
+#define MANH_SIZE LDBL_MANH_SIZE
+#define INC_MANH(u, c) do { \
+ uint64_t o = u.bits.manh; \
+ u.bits.manh += (c); \
+ if (u.bits.manh < o) { \
+ u.bits.exp++; \
+ u.bits.manh |= 1llu << (LDBL_MANH_SIZE - 1); \
+ } \
+} while (0)
+#endif
+
+static const long double huge = 1.0e300;
+
+OLM_DLLEXPORT long double
+floorl(long double x)
+{
+ union IEEEl2bits u = { .e = x };
+ int e = u.bits.exp - LDBL_MAX_EXP + 1;
+
+ if (e < MANH_SIZE - 1) {
+ if (e < 0) { /* raise inexact if x != 0 */
+ if (huge + x > 0.0)
+ if (u.bits.exp > 0 ||
+ (u.bits.manh | u.bits.manl) != 0)
+ u.e = u.bits.sign ? -1.0 : 0.0;
+ } else {
+ uint64_t m = ((1llu << MANH_SIZE) - 1) >> (e + 1);
+ if (((u.bits.manh & m) | u.bits.manl) == 0)
+ return (x); /* x is integral */
+ if (u.bits.sign) {
+#ifdef LDBL_IMPLICIT_NBIT
+ if (e == 0)
+ u.bits.exp++;
+ else
+#endif
+ INC_MANH(u, 1llu << (MANH_SIZE - e - 1));
+ }
+ if (huge + x > 0.0) { /* raise inexact flag */
+ u.bits.manh &= ~m;
+ u.bits.manl = 0;
+ }
+ }
+ } else if (e < LDBL_MANT_DIG - 1) {
+ uint64_t m = (uint64_t)-1 >> (64 - LDBL_MANT_DIG + e + 1);
+ if ((u.bits.manl & m) == 0)
+ return (x); /* x is integral */
+ if (u.bits.sign) {
+ if (e == MANH_SIZE - 1)
+ INC_MANH(u, 1);
+ else {
+ uint64_t o = u.bits.manl;
+ u.bits.manl += 1llu << (LDBL_MANT_DIG - e - 1);
+ if (u.bits.manl < o) /* got a carry */
+ INC_MANH(u, 1);
+ }
+ }
+ if (huge + x > 0.0) /* raise inexact flag */
+ u.bits.manl &= ~m;
+ }
+ return (u.e);
+}
--- /dev/null
+/*-
+ * Copyright (c) 2005-2011 David Schultz <das@FreeBSD.ORG>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/src/s_fma.c,v 1.8 2011/10/21 06:30:43 das Exp $");
+
+#include <float.h>
+#include <openlibm_fenv.h>
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+/*
+ * A struct dd represents a floating-point number with twice the precision
+ * of a double. We maintain the invariant that "hi" stores the 53 high-order
+ * bits of the result.
+ */
+struct dd {
+ double hi;
+ double lo;
+};
+
+/*
+ * Compute a+b exactly, returning the exact result in a struct dd. We assume
+ * that both a and b are finite, but make no assumptions about their relative
+ * magnitudes.
+ */
+static inline struct dd
+dd_add(double a, double b)
+{
+ struct dd ret;
+ double s;
+
+ ret.hi = a + b;
+ s = ret.hi - a;
+ ret.lo = (a - (ret.hi - s)) + (b - s);
+ return (ret);
+}
+
+/*
+ * Compute a+b, with a small tweak: The least significant bit of the
+ * result is adjusted into a sticky bit summarizing all the bits that
+ * were lost to rounding. This adjustment negates the effects of double
+ * rounding when the result is added to another number with a higher
+ * exponent. For an explanation of round and sticky bits, see any reference
+ * on FPU design, e.g.,
+ *
+ * J. Coonen. An Implementation Guide to a Proposed Standard for
+ * Floating-Point Arithmetic. Computer, vol. 13, no. 1, Jan 1980.
+ */
+static inline double
+add_adjusted(double a, double b)
+{
+ struct dd sum;
+ u_int64_t hibits, lobits;
+
+ sum = dd_add(a, b);
+ if (sum.lo != 0) {
+ EXTRACT_WORD64(hibits, sum.hi);
+ if ((hibits & 1) == 0) {
+ /* hibits += (int)copysign(1.0, sum.hi * sum.lo) */
+ EXTRACT_WORD64(lobits, sum.lo);
+ hibits += 1 - ((hibits ^ lobits) >> 62);
+ INSERT_WORD64(sum.hi, hibits);
+ }
+ }
+ return (sum.hi);
+}
+
+/*
+ * Compute ldexp(a+b, scale) with a single rounding error. It is assumed
+ * that the result will be subnormal, and care is taken to ensure that
+ * double rounding does not occur.
+ */
+static inline double
+add_and_denormalize(double a, double b, int scale)
+{
+ struct dd sum;
+ u_int64_t hibits, lobits;
+ int bits_lost;
+
+ sum = dd_add(a, b);
+
+ /*
+ * If we are losing at least two bits of accuracy to denormalization,
+ * then the first lost bit becomes a round bit, and we adjust the
+ * lowest bit of sum.hi to make it a sticky bit summarizing all the
+ * bits in sum.lo. With the sticky bit adjusted, the hardware will
+ * break any ties in the correct direction.
+ *
+ * If we are losing only one bit to denormalization, however, we must
+ * break the ties manually.
+ */
+ if (sum.lo != 0) {
+ EXTRACT_WORD64(hibits, sum.hi);
+ bits_lost = -((int)(hibits >> 52) & 0x7ff) - scale + 1;
+ if ((bits_lost != 1) ^ (int)(hibits & 1)) {
+ /* hibits += (int)copysign(1.0, sum.hi * sum.lo) */
+ EXTRACT_WORD64(lobits, sum.lo);
+ hibits += 1 - (((hibits ^ lobits) >> 62) & 2);
+ INSERT_WORD64(sum.hi, hibits);
+ }
+ }
+ return (ldexp(sum.hi, scale));
+}
+
+/*
+ * Compute a*b exactly, returning the exact result in a struct dd. We assume
+ * that both a and b are normalized, so no underflow or overflow will occur.
+ * The current rounding mode must be round-to-nearest.
+ */
+static inline struct dd
+dd_mul(double a, double b)
+{
+ static const double split = 0x1p27 + 1.0;
+ struct dd ret;
+ double ha, hb, la, lb, p, q;
+
+ p = a * split;
+ ha = a - p;
+ ha += p;
+ la = a - ha;
+
+ p = b * split;
+ hb = b - p;
+ hb += p;
+ lb = b - hb;
+
+ p = ha * hb;
+ q = ha * lb + la * hb;
+
+ ret.hi = p + q;
+ ret.lo = p - ret.hi + q + la * lb;
+ return (ret);
+}
+
+/*
+ * Fused multiply-add: Compute x * y + z with a single rounding error.
+ *
+ * We use scaling to avoid overflow/underflow, along with the
+ * canonical precision-doubling technique adapted from:
+ *
+ * Dekker, T. A Floating-Point Technique for Extending the
+ * Available Precision. Numer. Math. 18, 224-242 (1971).
+ *
+ * This algorithm is sensitive to the rounding precision. FPUs such
+ * as the i387 must be set in double-precision mode if variables are
+ * to be stored in FP registers in order to avoid incorrect results.
+ * This is the default on FreeBSD, but not on many other systems.
+ *
+ * Hardware instructions should be used on architectures that support it,
+ * since this implementation will likely be several times slower.
+ */
+OLM_DLLEXPORT double
+fma(double x, double y, double z)
+{
+ double xs, ys, zs, adj;
+ struct dd xy, r;
+ int oround;
+ int ex, ey, ez;
+ int spread;
+
+ /*
+ * Handle special cases. The order of operations and the particular
+ * return values here are crucial in handling special cases involving
+ * infinities, NaNs, overflows, and signed zeroes correctly.
+ */
+ if (x == 0.0 || y == 0.0)
+ return (x * y + z);
+ if (z == 0.0)
+ return (x * y);
+ if (!isfinite(x) || !isfinite(y))
+ return (x * y + z);
+ if (!isfinite(z))
+ return (z);
+
+ xs = frexp(x, &ex);
+ ys = frexp(y, &ey);
+ zs = frexp(z, &ez);
+ oround = fegetround();
+ spread = ex + ey - ez;
+
+ /*
+ * If x * y and z are many orders of magnitude apart, the scaling
+ * will overflow, so we handle these cases specially. Rounding
+ * modes other than FE_TONEAREST are painful.
+ */
+ if (spread < -DBL_MANT_DIG) {
+ feraiseexcept(FE_INEXACT);
+ if (!isnormal(z))
+ feraiseexcept(FE_UNDERFLOW);
+ switch (oround) {
+ case FE_TONEAREST:
+ return (z);
+ case FE_TOWARDZERO:
+ if ((x > 0.0) ^ (y < 0.0) ^ (z < 0.0))
+ return (z);
+ else
+ return (nextafter(z, 0));
+ case FE_DOWNWARD:
+ if ((x > 0.0) ^ (y < 0.0))
+ return (z);
+ else
+ return (nextafter(z, -INFINITY));
+ default: /* FE_UPWARD */
+ if ((x > 0.0) ^ (y < 0.0))
+ return (nextafter(z, INFINITY));
+ else
+ return (z);
+ }
+ }
+ if (spread <= DBL_MANT_DIG * 2)
+ zs = ldexp(zs, -spread);
+ else
+ zs = copysign(DBL_MIN, zs);
+
+ fesetround(FE_TONEAREST);
+
+ /*
+ * Basic approach for round-to-nearest:
+ *
+ * (xy.hi, xy.lo) = x * y (exact)
+ * (r.hi, r.lo) = xy.hi + z (exact)
+ * adj = xy.lo + r.lo (inexact; low bit is sticky)
+ * result = r.hi + adj (correctly rounded)
+ */
+ xy = dd_mul(xs, ys);
+ r = dd_add(xy.hi, zs);
+
+ spread = ex + ey;
+
+ if (r.hi == 0.0) {
+ /*
+ * When the addends cancel to 0, ensure that the result has
+ * the correct sign.
+ */
+ fesetround(oround);
+ volatile double vzs = zs; /* XXX gcc CSE bug workaround */
+ return (xy.hi + vzs + ldexp(xy.lo, spread));
+ }
+
+ if (oround != FE_TONEAREST) {
+ /*
+ * There is no need to worry about double rounding in directed
+ * rounding modes.
+ */
+ fesetround(oround);
+ adj = r.lo + xy.lo;
+ return (ldexp(r.hi + adj, spread));
+ }
+
+ adj = add_adjusted(r.lo, xy.lo);
+ if (spread + ilogb(r.hi) > -1023)
+ return (ldexp(r.hi + adj, spread));
+ else
+ return (add_and_denormalize(r.hi, adj, spread));
+}
+
+#if (LDBL_MANT_DIG == 53)
+__weak_reference(fma, fmal);
+#endif
--- /dev/null
+/*-
+ * Copyright (c) 2005-2011 David Schultz <das@FreeBSD.ORG>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/src/s_fmaf.c,v 1.3 2011/10/15 04:16:58 das Exp $");
+
+#include <openlibm_fenv.h>
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+/*
+ * Fused multiply-add: Compute x * y + z with a single rounding error.
+ *
+ * A double has more than twice as much precision than a float, so
+ * direct double-precision arithmetic suffices, except where double
+ * rounding occurs.
+ */
+OLM_DLLEXPORT float
+fmaf(float x, float y, float z)
+{
+ double xy, result;
+ u_int32_t hr, lr;
+
+ xy = (double)x * y;
+ result = xy + z;
+ EXTRACT_WORDS(hr, lr, result);
+ /* Common case: The double precision result is fine. */
+ if ((lr & 0x1fffffff) != 0x10000000 || /* not a halfway case */
+ (hr & 0x7ff00000) == 0x7ff00000 || /* NaN */
+ result - xy == z || /* exact */
+ fegetround() != FE_TONEAREST) /* not round-to-nearest */
+ return (result);
+
+ /*
+ * If result is inexact, and exactly halfway between two float values,
+ * we need to adjust the low-order bit in the direction of the error.
+ */
+ fesetround(FE_TOWARDZERO);
+ volatile double vxy = xy; /* XXX work around gcc CSE bug */
+ double adjusted_result = vxy + z;
+ fesetround(FE_TONEAREST);
+ if (result == adjusted_result)
+ SET_LOW_WORD(adjusted_result, lr + 1);
+ return (adjusted_result);
+}
--- /dev/null
+/*-
+ * Copyright (c) 2005-2011 David Schultz <das@FreeBSD.ORG>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/src/s_fmal.c,v 1.7 2011/10/21 06:30:43 das Exp $");
+
+#include <float.h>
+#include <openlibm_fenv.h>
+#include <openlibm_math.h>
+
+#include "fpmath.h"
+#include "math_private.h"
+
+/*
+ * A struct dd represents a floating-point number with twice the precision
+ * of a long double. We maintain the invariant that "hi" stores the high-order
+ * bits of the result.
+ */
+struct dd {
+ long double hi;
+ long double lo;
+};
+
+/*
+ * Compute a+b exactly, returning the exact result in a struct dd. We assume
+ * that both a and b are finite, but make no assumptions about their relative
+ * magnitudes.
+ */
+static inline struct dd
+dd_add(long double a, long double b)
+{
+ struct dd ret;
+ long double s;
+
+ ret.hi = a + b;
+ s = ret.hi - a;
+ ret.lo = (a - (ret.hi - s)) + (b - s);
+ return (ret);
+}
+
+/*
+ * Compute a+b, with a small tweak: The least significant bit of the
+ * result is adjusted into a sticky bit summarizing all the bits that
+ * were lost to rounding. This adjustment negates the effects of double
+ * rounding when the result is added to another number with a higher
+ * exponent. For an explanation of round and sticky bits, see any reference
+ * on FPU design, e.g.,
+ *
+ * J. Coonen. An Implementation Guide to a Proposed Standard for
+ * Floating-Point Arithmetic. Computer, vol. 13, no. 1, Jan 1980.
+ */
+static inline long double
+add_adjusted(long double a, long double b)
+{
+ struct dd sum;
+ union IEEEl2bits u;
+
+ sum = dd_add(a, b);
+ if (sum.lo != 0) {
+ u.e = sum.hi;
+ if ((u.bits.manl & 1) == 0)
+ sum.hi = nextafterl(sum.hi, INFINITY * sum.lo);
+ }
+ return (sum.hi);
+}
+
+/*
+ * Compute ldexp(a+b, scale) with a single rounding error. It is assumed
+ * that the result will be subnormal, and care is taken to ensure that
+ * double rounding does not occur.
+ */
+static inline long double
+add_and_denormalize(long double a, long double b, int scale)
+{
+ struct dd sum;
+ int bits_lost;
+ union IEEEl2bits u;
+
+ sum = dd_add(a, b);
+
+ /*
+ * If we are losing at least two bits of accuracy to denormalization,
+ * then the first lost bit becomes a round bit, and we adjust the
+ * lowest bit of sum.hi to make it a sticky bit summarizing all the
+ * bits in sum.lo. With the sticky bit adjusted, the hardware will
+ * break any ties in the correct direction.
+ *
+ * If we are losing only one bit to denormalization, however, we must
+ * break the ties manually.
+ */
+ if (sum.lo != 0) {
+ u.e = sum.hi;
+ bits_lost = -u.bits.exp - scale + 1;
+ if ((bits_lost != 1) ^ (int)(u.bits.manl & 1))
+ sum.hi = nextafterl(sum.hi, INFINITY * sum.lo);
+ }
+ return (ldexp(sum.hi, scale));
+}
+
+/*
+ * Compute a*b exactly, returning the exact result in a struct dd. We assume
+ * that both a and b are normalized, so no underflow or overflow will occur.
+ * The current rounding mode must be round-to-nearest.
+ */
+static inline struct dd
+dd_mul(long double a, long double b)
+{
+#if LDBL_MANT_DIG == 64
+ static const long double split = 0x1p32L + 1.0;
+#elif LDBL_MANT_DIG == 113
+ static const long double split = 0x1p57L + 1.0;
+#endif
+ struct dd ret;
+ long double ha, hb, la, lb, p, q;
+
+ p = a * split;
+ ha = a - p;
+ ha += p;
+ la = a - ha;
+
+ p = b * split;
+ hb = b - p;
+ hb += p;
+ lb = b - hb;
+
+ p = ha * hb;
+ q = ha * lb + la * hb;
+
+ ret.hi = p + q;
+ ret.lo = p - ret.hi + q + la * lb;
+ return (ret);
+}
+
+/*
+ * Fused multiply-add: Compute x * y + z with a single rounding error.
+ *
+ * We use scaling to avoid overflow/underflow, along with the
+ * canonical precision-doubling technique adapted from:
+ *
+ * Dekker, T. A Floating-Point Technique for Extending the
+ * Available Precision. Numer. Math. 18, 224-242 (1971).
+ */
+OLM_DLLEXPORT long double
+fmal(long double x, long double y, long double z)
+{
+ long double xs, ys, zs, adj;
+ struct dd xy, r;
+ int oround;
+ int ex, ey, ez;
+ int spread;
+
+ /*
+ * Handle special cases. The order of operations and the particular
+ * return values here are crucial in handling special cases involving
+ * infinities, NaNs, overflows, and signed zeroes correctly.
+ */
+ if (x == 0.0 || y == 0.0)
+ return (x * y + z);
+ if (z == 0.0)
+ return (x * y);
+ if (!isfinite(x) || !isfinite(y))
+ return (x * y + z);
+ if (!isfinite(z))
+ return (z);
+
+ xs = frexpl(x, &ex);
+ ys = frexpl(y, &ey);
+ zs = frexpl(z, &ez);
+ oround = fegetround();
+ spread = ex + ey - ez;
+
+ /*
+ * If x * y and z are many orders of magnitude apart, the scaling
+ * will overflow, so we handle these cases specially. Rounding
+ * modes other than FE_TONEAREST are painful.
+ */
+ if (spread < -LDBL_MANT_DIG) {
+ feraiseexcept(FE_INEXACT);
+ if (!isnormal(z))
+ feraiseexcept(FE_UNDERFLOW);
+ switch (oround) {
+ case FE_TONEAREST:
+ return (z);
+ case FE_TOWARDZERO:
+ if ((x > 0.0) ^ (y < 0.0) ^ (z < 0.0))
+ return (z);
+ else
+ return (nextafterl(z, 0));
+ case FE_DOWNWARD:
+ if ((x > 0.0) ^ (y < 0.0))
+ return (z);
+ else
+ return (nextafterl(z, -INFINITY));
+ default: /* FE_UPWARD */
+ if ((x > 0.0) ^ (y < 0.0))
+ return (nextafterl(z, INFINITY));
+ else
+ return (z);
+ }
+ }
+ if (spread <= LDBL_MANT_DIG * 2)
+ zs = ldexpl(zs, -spread);
+ else
+ zs = copysignl(LDBL_MIN, zs);
+
+ fesetround(FE_TONEAREST);
+
+ /*
+ * Basic approach for round-to-nearest:
+ *
+ * (xy.hi, xy.lo) = x * y (exact)
+ * (r.hi, r.lo) = xy.hi + z (exact)
+ * adj = xy.lo + r.lo (inexact; low bit is sticky)
+ * result = r.hi + adj (correctly rounded)
+ */
+ xy = dd_mul(xs, ys);
+ r = dd_add(xy.hi, zs);
+
+ spread = ex + ey;
+
+ if (r.hi == 0.0) {
+ /*
+ * When the addends cancel to 0, ensure that the result has
+ * the correct sign.
+ */
+ fesetround(oround);
+ volatile long double vzs = zs; /* XXX gcc CSE bug workaround */
+ return (xy.hi + vzs + ldexpl(xy.lo, spread));
+ }
+
+ if (oround != FE_TONEAREST) {
+ /*
+ * There is no need to worry about double rounding in directed
+ * rounding modes.
+ */
+ fesetround(oround);
+ adj = r.lo + xy.lo;
+ return (ldexpl(r.hi + adj, spread));
+ }
+
+ adj = add_adjusted(r.lo, xy.lo);
+ if (spread + ilogbl(r.hi) > -16383)
+ return (ldexpl(r.hi + adj, spread));
+ else
+ return (add_and_denormalize(r.hi, adj, spread));
+}
--- /dev/null
+/*-
+ * Copyright (c) 2004 David Schultz <das@FreeBSD.ORG>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/src/s_fmax.c,v 1.1 2004/06/30 07:04:01 das Exp $");
+
+#include <openlibm_math.h>
+
+#include "fpmath.h"
+#include "math_private.h"
+
+OLM_DLLEXPORT double
+fmax(double x, double y)
+{
+ union IEEEd2bits u[2];
+
+ u[0].d = x;
+ u[1].d = y;
+
+ /* Check for NaNs to avoid raising spurious exceptions. */
+ if (u[0].bits.exp == 2047 && (u[0].bits.manh | u[0].bits.manl) != 0)
+ return (y);
+ if (u[1].bits.exp == 2047 && (u[1].bits.manh | u[1].bits.manl) != 0)
+ return (x);
+
+ /* Handle comparisons of signed zeroes. */
+ if (u[0].bits.sign != u[1].bits.sign)
+ return (u[u[0].bits.sign].d);
+
+ return (x > y ? x : y);
+}
--- /dev/null
+/*-
+ * Copyright (c) 2004 David Schultz <das@FreeBSD.ORG>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/src/s_fmaxf.c,v 1.1 2004/06/30 07:04:01 das Exp $");
+
+#include <openlibm_math.h>
+
+#include "fpmath.h"
+#include "math_private.h"
+
+OLM_DLLEXPORT float
+fmaxf(float x, float y)
+{
+ union IEEEf2bits u[2];
+
+ u[0].f = x;
+ u[1].f = y;
+
+ /* Check for NaNs to avoid raising spurious exceptions. */
+ if (u[0].bits.exp == 255 && u[0].bits.man != 0)
+ return (y);
+ if (u[1].bits.exp == 255 && u[1].bits.man != 0)
+ return (x);
+
+ /* Handle comparisons of signed zeroes. */
+ if (u[0].bits.sign != u[1].bits.sign)
+ return (u[u[0].bits.sign].f);
+
+ return (x > y ? x : y);
+}
--- /dev/null
+/*-
+ * Copyright (c) 2004 David Schultz <das@FreeBSD.ORG>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/src/s_fmaxl.c,v 1.1 2004/06/30 07:04:01 das Exp $");
+
+#include <openlibm_math.h>
+
+#include "fpmath.h"
+#include "math_private.h"
+
+OLM_DLLEXPORT long double
+fmaxl(long double x, long double y)
+{
+ union IEEEl2bits u[2];
+
+ u[0].e = x;
+ mask_nbit_l(u[0]);
+ u[1].e = y;
+ mask_nbit_l(u[1]);
+
+ /* Check for NaNs to avoid raising spurious exceptions. */
+ if (u[0].bits.exp == 32767 && (u[0].bits.manh | u[0].bits.manl) != 0)
+ return (y);
+ if (u[1].bits.exp == 32767 && (u[1].bits.manh | u[1].bits.manl) != 0)
+ return (x);
+
+ /* Handle comparisons of signed zeroes. */
+ if (u[0].bits.sign != u[1].bits.sign)
+ return (u[0].bits.sign ? y : x);
+
+ return (x > y ? x : y);
+}
--- /dev/null
+/*-
+ * Copyright (c) 2004 David Schultz <das@FreeBSD.ORG>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/src/s_fmin.c,v 1.1 2004/06/30 07:04:01 das Exp $");
+
+#include <openlibm_math.h>
+
+#include "fpmath.h"
+#include "math_private.h"
+
+OLM_DLLEXPORT double
+fmin(double x, double y)
+{
+ union IEEEd2bits u[2];
+
+ u[0].d = x;
+ u[1].d = y;
+
+ /* Check for NaNs to avoid raising spurious exceptions. */
+ if (u[0].bits.exp == 2047 && (u[0].bits.manh | u[0].bits.manl) != 0)
+ return (y);
+ if (u[1].bits.exp == 2047 && (u[1].bits.manh | u[1].bits.manl) != 0)
+ return (x);
+
+ /* Handle comparisons of signed zeroes. */
+ if (u[0].bits.sign != u[1].bits.sign)
+ return (u[u[1].bits.sign].d);
+
+ return (x < y ? x : y);
+}
--- /dev/null
+/*-
+ * Copyright (c) 2004 David Schultz <das@FreeBSD.ORG>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/src/s_fminf.c,v 1.1 2004/06/30 07:04:01 das Exp $");
+
+#include <openlibm_math.h>
+
+#include "fpmath.h"
+#include "math_private.h"
+
+OLM_DLLEXPORT float
+fminf(float x, float y)
+{
+ union IEEEf2bits u[2];
+
+ u[0].f = x;
+ u[1].f = y;
+
+ /* Check for NaNs to avoid raising spurious exceptions. */
+ if (u[0].bits.exp == 255 && u[0].bits.man != 0)
+ return (y);
+ if (u[1].bits.exp == 255 && u[1].bits.man != 0)
+ return (x);
+
+ /* Handle comparisons of signed zeroes. */
+ if (u[0].bits.sign != u[1].bits.sign)
+ return (u[u[1].bits.sign].f);
+
+ return (x < y ? x : y);
+}
--- /dev/null
+/*-
+ * Copyright (c) 2004 David Schultz <das@FreeBSD.ORG>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/src/s_fminl.c,v 1.1 2004/06/30 07:04:01 das Exp $");
+
+#include <openlibm_math.h>
+
+#include "fpmath.h"
+#include "math_private.h"
+
+OLM_DLLEXPORT long double
+fminl(long double x, long double y)
+{
+ union IEEEl2bits u[2];
+
+ u[0].e = x;
+ mask_nbit_l(u[0]);
+ u[1].e = y;
+ mask_nbit_l(u[1]);
+
+ /* Check for NaNs to avoid raising spurious exceptions. */
+ if (u[0].bits.exp == 32767 && (u[0].bits.manh | u[0].bits.manl) != 0)
+ return (y);
+ if (u[1].bits.exp == 32767 && (u[1].bits.manh | u[1].bits.manl) != 0)
+ return (x);
+
+ /* Handle comparisons of signed zeroes. */
+ if (u[0].bits.sign != u[1].bits.sign)
+ return (u[1].bits.sign ? y : x);
+
+ return (x < y ? x : y);
+}
--- /dev/null
+/*-
+ * Copyright (c) 2004 David Schultz <das@FreeBSD.ORG>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#include <openlibm_math.h>
+#include "math_private.h"
+#include "fpmath.h"
+
+OLM_DLLEXPORT int
+__fpclassifyd(double d)
+{
+ union IEEEd2bits u;
+
+ u.d = d;
+ if (u.bits.exp == 2047) {
+ if (u.bits.manl == 0 && u.bits.manh == 0) {
+ return FP_INFINITE;
+ } else {
+ return FP_NAN;
+ }
+ } else if (u.bits.exp != 0) {
+ return FP_NORMAL;
+ } else if (u.bits.manl == 0 && u.bits.manh == 0) {
+ return FP_ZERO;
+ } else {
+ return FP_SUBNORMAL;
+ }
+}
+
+
+OLM_DLLEXPORT int
+__fpclassifyf(float f)
+{
+ union IEEEf2bits u;
+
+ u.f = f;
+ if (u.bits.exp == 255) {
+ if (u.bits.man == 0) {
+ return FP_INFINITE;
+ } else {
+ return FP_NAN;
+ }
+ } else if (u.bits.exp != 0) {
+ return FP_NORMAL;
+ } else if (u.bits.man == 0) {
+ return FP_ZERO;
+ } else {
+ return FP_SUBNORMAL;
+ }
+}
+
+#ifdef LONG_DOUBLE
+OLM_DLLEXPORT int
+__fpclassifyl(long double e)
+{
+ union IEEEl2bits u;
+
+ u.e = e;
+ mask_nbit_l(u);
+ if (u.bits.exp == 32767) {
+ if (u.bits.manl == 0 && u.bits.manh == 0) {
+ return FP_INFINITE;
+ } else {
+ return FP_NAN;
+ }
+ } else if (u.bits.exp != 0) {
+ return FP_NORMAL;
+ } else if (u.bits.manl == 0 && u.bits.manh == 0) {
+ return FP_ZERO;
+ } else {
+ return FP_SUBNORMAL;
+ }
+}
+#endif
+
--- /dev/null
+/* @(#)s_frexp.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/src/s_frexp.c,v 1.11 2008/02/22 02:30:35 das Exp $");
+
+/*
+ * for non-zero x
+ * x = frexp(arg,&exp);
+ * return a double fp quantity x such that 0.5 <= |x| <1.0
+ * and the corresponding binary exponent "exp". That is
+ * arg = x*2^exp.
+ * If arg is inf, 0.0, or NaN, then frexp(arg,&exp) returns arg
+ * with *exp=0.
+ */
+
+#include <float.h>
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+static const double
+two54 = 1.80143985094819840000e+16; /* 0x43500000, 0x00000000 */
+
+OLM_DLLEXPORT double
+frexp(double x, int *eptr)
+{
+ int32_t hx, ix, lx;
+ EXTRACT_WORDS(hx,lx,x);
+ ix = 0x7fffffff&hx;
+ *eptr = 0;
+ if(ix>=0x7ff00000||((ix|lx)==0)) return x; /* 0,inf,nan */
+ if (ix<0x00100000) { /* subnormal */
+ x *= two54;
+ GET_HIGH_WORD(hx,x);
+ ix = hx&0x7fffffff;
+ *eptr = -54;
+ }
+ *eptr += (ix>>20)-1022;
+ hx = (hx&0x800fffff)|0x3fe00000;
+ SET_HIGH_WORD(x,hx);
+ return x;
+}
+
+#if (LDBL_MANT_DIG == 53)
+__weak_reference(frexp, frexpl);
+#endif
--- /dev/null
+/* s_frexpf.c -- float version of s_frexp.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/src/s_frexpf.c,v 1.10 2008/02/22 02:30:35 das Exp $");
+
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+static const float
+two25 = 3.3554432000e+07; /* 0x4c000000 */
+
+OLM_DLLEXPORT float
+frexpf(float x, int *eptr)
+{
+ int32_t hx,ix;
+ GET_FLOAT_WORD(hx,x);
+ ix = 0x7fffffff&hx;
+ *eptr = 0;
+ if(ix>=0x7f800000||(ix==0)) return x; /* 0,inf,nan */
+ if (ix<0x00800000) { /* subnormal */
+ x *= two25;
+ GET_FLOAT_WORD(hx,x);
+ ix = hx&0x7fffffff;
+ *eptr = -25;
+ }
+ *eptr += (ix>>23)-126;
+ hx = (hx&0x807fffff)|0x3f000000;
+ SET_FLOAT_WORD(x,hx);
+ return x;
+}
--- /dev/null
+/*-
+ * Copyright (c) 2004-2005 David Schultz <das@FreeBSD.ORG>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: src/lib/msun/src/s_frexpl.c,v 1.1 2005/03/07 04:54:51 das Exp $
+ */
+
+#include <float.h>
+#include <openlibm_math.h>
+
+#include "fpmath.h"
+#include "math_private.h"
+
+#if LDBL_MAX_EXP != 0x4000
+#error "Unsupported long double format"
+#endif
+
+OLM_DLLEXPORT long double
+frexpl(long double x, int *ex)
+{
+ union IEEEl2bits u;
+
+ u.e = x;
+ switch (u.bits.exp) {
+ case 0: /* 0 or subnormal */
+ if ((u.bits.manl | u.bits.manh) == 0) {
+ *ex = 0;
+ } else {
+ u.e *= 0x1.0p514;
+ *ex = u.bits.exp - 0x4200;
+ u.bits.exp = 0x3ffe;
+ }
+ break;
+ case 0x7fff: /* infinity or NaN; value of *ex is unspecified */
+ break;
+ default: /* normal */
+ *ex = u.bits.exp - 0x3ffe;
+ u.bits.exp = 0x3ffe;
+ break;
+ }
+ return (u.e);
+}
--- /dev/null
+/* @(#)s_ilogb.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/src/s_ilogb.c,v 1.10 2008/02/22 02:30:35 das Exp $");
+
+/* ilogb(double x)
+ * return the binary exponent of non-zero x
+ * ilogb(0) = FP_ILOGB0
+ * ilogb(NaN) = FP_ILOGBNAN (no signal is raised)
+ * ilogb(inf) = INT_MAX (no signal is raised)
+ */
+
+#include <limits.h>
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+OLM_DLLEXPORT int
+ilogb(double x)
+{
+ int32_t hx,lx,ix;
+
+ EXTRACT_WORDS(hx,lx,x);
+ hx &= 0x7fffffff;
+ if(hx<0x00100000) {
+ if((hx|lx)==0)
+ return FP_ILOGB0;
+ else /* subnormal x */
+ if(hx==0) {
+ for (ix = -1043; lx>0; lx<<=1) ix -=1;
+ } else {
+ for (ix = -1022,hx<<=11; hx>0; hx<<=1) ix -=1;
+ }
+ return ix;
+ }
+ else if (hx<0x7ff00000) return (hx>>20)-1023;
+ else if (hx>0x7ff00000 || lx!=0) return FP_ILOGBNAN;
+ else return INT_MAX;
+}
--- /dev/null
+/* s_ilogbf.c -- float version of s_ilogb.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/src/s_ilogbf.c,v 1.8 2008/02/22 02:30:35 das Exp $");
+
+#include <limits.h>
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+OLM_DLLEXPORT int
+ilogbf(float x)
+{
+ int32_t hx,ix;
+
+ GET_FLOAT_WORD(hx,x);
+ hx &= 0x7fffffff;
+ if(hx<0x00800000) {
+ if(hx==0)
+ return FP_ILOGB0;
+ else /* subnormal x */
+ for (ix = -126,hx<<=8; hx>0; hx<<=1) ix -=1;
+ return ix;
+ }
+ else if (hx<0x7f800000) return (hx>>23)-127;
+ else if (hx>0x7f800000) return FP_ILOGBNAN;
+ else return INT_MAX;
+}
--- /dev/null
+/*
+ * From: @(#)s_ilogb.c 5.1 93/09/24
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/src/s_ilogbl.c,v 1.2 2008/02/22 02:30:35 das Exp $");
+
+#include <float.h>
+#include <limits.h>
+#include <openlibm_math.h>
+
+#include "fpmath.h"
+#include "math_private.h"
+
+OLM_DLLEXPORT int
+ilogbl(long double x)
+{
+ union IEEEl2bits u;
+ unsigned long m;
+ int b;
+
+ u.e = x;
+ if (u.bits.exp == 0) {
+ if ((u.bits.manl | u.bits.manh) == 0)
+ return (FP_ILOGB0);
+ /* denormalized */
+ if (u.bits.manh == 0) {
+ m = 1lu << (LDBL_MANL_SIZE - 1);
+ for (b = LDBL_MANH_SIZE; !(u.bits.manl & m); m >>= 1)
+ b++;
+ } else {
+ m = 1lu << (LDBL_MANH_SIZE - 1);
+ for (b = 0; !(u.bits.manh & m); m >>= 1)
+ b++;
+ }
+#ifdef LDBL_IMPLICIT_NBIT
+ b++;
+#endif
+ return (LDBL_MIN_EXP - b - 1);
+ } else if (u.bits.exp < (LDBL_MAX_EXP << 1) - 1)
+ return (u.bits.exp - LDBL_MAX_EXP + 1);
+ else if (u.bits.manl != 0 || u.bits.manh != 0)
+ return (FP_ILOGBNAN);
+ else
+ return (INT_MAX);
+}
--- /dev/null
+/*-
+ * Copyright (c) 2004 David Schultz <das@FreeBSD.ORG>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: src/lib/msun/src/s_isfinite.c,v 1.1 2004/07/09 03:32:39 das Exp $
+ */
+
+#include <openlibm_math.h>
+
+#include "fpmath.h"
+#include "math_private.h"
+
+OLM_DLLEXPORT int
+__isfinite(double d)
+{
+ union IEEEd2bits u;
+
+ u.d = d;
+ return (u.bits.exp != 2047);
+}
+
+OLM_DLLEXPORT int
+__isfinitef(float f)
+{
+ union IEEEf2bits u;
+
+ u.f = f;
+ return (u.bits.exp != 255);
+}
+
+#ifdef LONG_DOUBLE
+OLM_DLLEXPORT int
+__isfinitel(long double e)
+{
+ union IEEEl2bits u;
+
+ u.e = e;
+ return (u.bits.exp != 32767);
+}
+#endif
--- /dev/null
+/*-
+ * Copyright (c) 2004 David Schultz <das@FreeBSD.ORG>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#include <openlibm_math.h>
+
+#include "fpmath.h"
+#include "math_private.h"
+
+/* Provided by libc */
+#if 1
+OLM_DLLEXPORT int
+(isinf) (double d)
+{
+ union IEEEd2bits u;
+
+ u.d = d;
+ return (u.bits.exp == 2047 && u.bits.manl == 0 && u.bits.manh == 0);
+}
+#endif
+
+OLM_DLLEXPORT int
+__isinff(float f)
+{
+ union IEEEf2bits u;
+
+ u.f = f;
+ return (u.bits.exp == 255 && u.bits.man == 0);
+}
+
+#ifdef LONG_DOUBLE
+OLM_DLLEXPORT int
+__isinfl(long double e)
+{
+ union IEEEl2bits u;
+
+ u.e = e;
+ mask_nbit_l(u);
+ return (u.bits.exp == 32767 && u.bits.manl == 0 && u.bits.manh == 0);
+}
+#endif
+
+__weak_reference(__isinff, isinff);
--- /dev/null
+/*-
+ * Copyright (c) 2004 David Schultz <das@FreeBSD.ORG>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: src/lib/msun/src/s_isnan.c,v 1.9 2010/06/12 17:32:05 das Exp $
+ */
+
+#include <openlibm_math.h>
+
+#include "fpmath.h"
+#include "math_private.h"
+
+/* Provided by libc */
+#if 1
+OLM_DLLEXPORT int
+(isnan) (double d)
+{
+ union IEEEd2bits u;
+
+ u.d = d;
+ return (u.bits.exp == 2047 && (u.bits.manl != 0 || u.bits.manh != 0));
+}
+#endif
+
+OLM_DLLEXPORT int
+__isnanf(float f)
+{
+ union IEEEf2bits u;
+
+ u.f = f;
+ return (u.bits.exp == 255 && u.bits.man != 0);
+}
+
+#ifdef LONG_DOUBLE
+OLM_DLLEXPORT int
+__isnanl(long double e)
+{
+ union IEEEl2bits u;
+
+ u.e = e;
+ mask_nbit_l(u);
+ return (u.bits.exp == 32767 && (u.bits.manl != 0 || u.bits.manh != 0));
+}
+#endif
+
+__weak_reference(__isnanf, isnanf);
--- /dev/null
+/*-
+ * Copyright (c) 2004 David Schultz <das@FreeBSD.ORG>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: src/lib/msun/src/s_isnormal.c,v 1.1 2004/07/09 03:32:39 das Exp $
+ */
+
+#include <openlibm_math.h>
+
+#include "fpmath.h"
+#include "math_private.h"
+
+OLM_DLLEXPORT int
+__isnormal(double d)
+{
+ union IEEEd2bits u;
+
+ u.d = d;
+ return (u.bits.exp != 0 && u.bits.exp != 2047);
+}
+
+OLM_DLLEXPORT int
+__isnormalf(float f)
+{
+ union IEEEf2bits u;
+
+ u.f = f;
+ return (u.bits.exp != 0 && u.bits.exp != 255);
+}
+
+#ifdef LONG_DOUBLE
+OLM_DLLEXPORT int
+__isnormall(long double e)
+{
+ union IEEEl2bits u;
+
+ u.e = e;
+ return (u.bits.exp != 0 && u.bits.exp != 32767);
+}
+#endif
--- /dev/null
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/src/s_llrint.c,v 1.1 2005/01/11 23:12:55 das Exp $");
+
+#define type double
+#define roundit rint
+#define dtype long long
+#define fn llrint
+
+#include "s_lrint.c"
--- /dev/null
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/src/s_llrintf.c,v 1.1 2005/01/11 23:12:55 das Exp $");
+
+#define type float
+#define roundit rintf
+#define dtype long long
+#define fn llrintf
+
+#include "s_lrint.c"
--- /dev/null
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/src/s_llrintl.c,v 1.1 2008/01/14 02:12:06 das Exp $");
+
+#define type long double
+#define roundit rintl
+#define dtype long long
+#define fn llrintl
+
+#include "s_lrint.c"
--- /dev/null
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/src/s_llround.c,v 1.2 2005/04/08 00:52:27 das Exp $");
+
+#define type double
+#define roundit round
+#define dtype long long
+#define DTYPE_MIN LLONG_MIN
+#define DTYPE_MAX LLONG_MAX
+#define fn llround
+
+#include "s_lround.c"
--- /dev/null
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/src/s_llroundf.c,v 1.2 2005/04/08 00:52:27 das Exp $");
+
+#define type float
+#define roundit roundf
+#define dtype long long
+#define DTYPE_MIN LLONG_MIN
+#define DTYPE_MAX LLONG_MAX
+#define fn llroundf
+
+#include "s_lround.c"
--- /dev/null
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/src/s_llroundl.c,v 1.1 2005/04/08 01:24:08 das Exp $");
+
+#define type long double
+#define roundit roundl
+#define dtype long long
+#define DTYPE_MIN LLONG_MIN
+#define DTYPE_MAX LLONG_MAX
+#define fn llroundl
+
+#include "s_lround.c"
--- /dev/null
+/* @(#)s_log1p.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/src/s_log1p.c,v 1.10 2008/03/29 16:37:59 das Exp $");
+
+/* double log1p(double x)
+ *
+ * Method :
+ * 1. Argument Reduction: find k and f such that
+ * 1+x = 2^k * (1+f),
+ * where sqrt(2)/2 < 1+f < sqrt(2) .
+ *
+ * Note. If k=0, then f=x is exact. However, if k!=0, then f
+ * may not be representable exactly. In that case, a correction
+ * term is need. Let u=1+x rounded. Let c = (1+x)-u, then
+ * log(1+x) - log(u) ~ c/u. Thus, we proceed to compute log(u),
+ * and add back the correction term c/u.
+ * (Note: when x > 2**53, one can simply return log(x))
+ *
+ * 2. Approximation of log1p(f).
+ * Let s = f/(2+f) ; based on log(1+f) = log(1+s) - log(1-s)
+ * = 2s + 2/3 s**3 + 2/5 s**5 + .....,
+ * = 2s + s*R
+ * We use a special Reme algorithm on [0,0.1716] to generate
+ * a polynomial of degree 14 to approximate R The maximum error
+ * of this polynomial approximation is bounded by 2**-58.45. In
+ * other words,
+ * 2 4 6 8 10 12 14
+ * R(z) ~ Lp1*s +Lp2*s +Lp3*s +Lp4*s +Lp5*s +Lp6*s +Lp7*s
+ * (the values of Lp1 to Lp7 are listed in the program)
+ * and
+ * | 2 14 | -58.45
+ * | Lp1*s +...+Lp7*s - R(z) | <= 2
+ * | |
+ * Note that 2s = f - s*f = f - hfsq + s*hfsq, where hfsq = f*f/2.
+ * In order to guarantee error in log below 1ulp, we compute log
+ * by
+ * log1p(f) = f - (hfsq - s*(hfsq+R)).
+ *
+ * 3. Finally, log1p(x) = k*ln2 + log1p(f).
+ * = k*ln2_hi+(f-(hfsq-(s*(hfsq+R)+k*ln2_lo)))
+ * Here ln2 is split into two floating point number:
+ * ln2_hi + ln2_lo,
+ * where n*ln2_hi is always exact for |n| < 2000.
+ *
+ * Special cases:
+ * log1p(x) is NaN with signal if x < -1 (including -INF) ;
+ * log1p(+INF) is +INF; log1p(-1) is -INF with signal;
+ * log1p(NaN) is that NaN with no signal.
+ *
+ * Accuracy:
+ * according to an error analysis, the error is always less than
+ * 1 ulp (unit in the last place).
+ *
+ * Constants:
+ * The hexadecimal values are the intended ones for the following
+ * constants. The decimal values may be used, provided that the
+ * compiler will convert from decimal to binary accurately enough
+ * to produce the hexadecimal values shown.
+ *
+ * Note: Assuming log() return accurate answer, the following
+ * algorithm can be used to compute log1p(x) to within a few ULP:
+ *
+ * u = 1+x;
+ * if(u==1.0) return x ; else
+ * return log(u)*(x/(u-1.0));
+ *
+ * See HP-15C Advanced Functions Handbook, p.193.
+ */
+
+#include <float.h>
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+static const double
+ln2_hi = 6.93147180369123816490e-01, /* 3fe62e42 fee00000 */
+ln2_lo = 1.90821492927058770002e-10, /* 3dea39ef 35793c76 */
+two54 = 1.80143985094819840000e+16, /* 43500000 00000000 */
+Lp1 = 6.666666666666735130e-01, /* 3FE55555 55555593 */
+Lp2 = 3.999999999940941908e-01, /* 3FD99999 9997FA04 */
+Lp3 = 2.857142874366239149e-01, /* 3FD24924 94229359 */
+Lp4 = 2.222219843214978396e-01, /* 3FCC71C5 1D8E78AF */
+Lp5 = 1.818357216161805012e-01, /* 3FC74664 96CB03DE */
+Lp6 = 1.531383769920937332e-01, /* 3FC39A09 D078C69F */
+Lp7 = 1.479819860511658591e-01; /* 3FC2F112 DF3E5244 */
+
+static const double zero = 0.0;
+
+OLM_DLLEXPORT double
+log1p(double x)
+{
+ double hfsq,f,c,s,z,R,u;
+ int32_t k,hx,hu,ax;
+
+ GET_HIGH_WORD(hx,x);
+ ax = hx&0x7fffffff;
+
+ k = 1;
+ if (hx < 0x3FDA827A) { /* 1+x < sqrt(2)+ */
+ if(ax>=0x3ff00000) { /* x <= -1.0 */
+ if(x==-1.0) return -two54/zero; /* log1p(-1)=+inf */
+ else return (x-x)/(x-x); /* log1p(x<-1)=NaN */
+ }
+ if(ax<0x3e200000) { /* |x| < 2**-29 */
+ if(two54+x>zero /* raise inexact */
+ &&ax<0x3c900000) /* |x| < 2**-54 */
+ return x;
+ else
+ return x - x*x*0.5;
+ }
+ if(hx>0||hx<=((int32_t)0xbfd2bec4)) {
+ k=0;f=x;hu=1;} /* sqrt(2)/2- <= 1+x < sqrt(2)+ */
+ }
+ if (hx >= 0x7ff00000) return x+x;
+ if(k!=0) {
+ if(hx<0x43400000) {
+ STRICT_ASSIGN(double,u,1.0+x);
+ GET_HIGH_WORD(hu,u);
+ k = (hu>>20)-1023;
+ c = (k>0)? 1.0-(u-x):x-(u-1.0);/* correction term */
+ c /= u;
+ } else {
+ u = x;
+ GET_HIGH_WORD(hu,u);
+ k = (hu>>20)-1023;
+ c = 0;
+ }
+ hu &= 0x000fffff;
+ /*
+ * The approximation to sqrt(2) used in thresholds is not
+ * critical. However, the ones used above must give less
+ * strict bounds than the one here so that the k==0 case is
+ * never reached from here, since here we have committed to
+ * using the correction term but don't use it if k==0.
+ */
+ if(hu<0x6a09e) { /* u ~< sqrt(2) */
+ SET_HIGH_WORD(u,hu|0x3ff00000); /* normalize u */
+ } else {
+ k += 1;
+ SET_HIGH_WORD(u,hu|0x3fe00000); /* normalize u/2 */
+ hu = (0x00100000-hu)>>2;
+ }
+ f = u-1.0;
+ }
+ hfsq=0.5*f*f;
+ if(hu==0) { /* |f| < 2**-20 */
+ if(f==zero) {
+ if(k==0) {
+ return zero;
+ } else {
+ c += k*ln2_lo;
+ return k*ln2_hi+c;
+ }
+ }
+ R = hfsq*(1.0-0.66666666666666666*f);
+ if(k==0) return f-R; else
+ return k*ln2_hi-((R-(k*ln2_lo+c))-f);
+ }
+ s = f/(2.0+f);
+ z = s*s;
+ R = z*(Lp1+z*(Lp2+z*(Lp3+z*(Lp4+z*(Lp5+z*(Lp6+z*Lp7))))));
+ if(k==0) return f-(hfsq-s*(hfsq+R)); else
+ return k*ln2_hi-((hfsq-(s*(hfsq+R)+(k*ln2_lo+c)))-f);
+}
--- /dev/null
+/* s_log1pf.c -- float version of s_log1p.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/src/s_log1pf.c,v 1.12 2008/03/29 16:37:59 das Exp $");
+
+#include <float.h>
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+static const float
+ln2_hi = 6.9313812256e-01, /* 0x3f317180 */
+ln2_lo = 9.0580006145e-06, /* 0x3717f7d1 */
+two25 = 3.355443200e+07, /* 0x4c000000 */
+Lp1 = 6.6666668653e-01, /* 3F2AAAAB */
+Lp2 = 4.0000000596e-01, /* 3ECCCCCD */
+Lp3 = 2.8571429849e-01, /* 3E924925 */
+Lp4 = 2.2222198546e-01, /* 3E638E29 */
+Lp5 = 1.8183572590e-01, /* 3E3A3325 */
+Lp6 = 1.5313838422e-01, /* 3E1CD04F */
+Lp7 = 1.4798198640e-01; /* 3E178897 */
+
+static const float zero = 0.0;
+
+OLM_DLLEXPORT float
+log1pf(float x)
+{
+ float hfsq,f,c,s,z,R,u;
+ int32_t k,hx,hu,ax;
+
+ GET_FLOAT_WORD(hx,x);
+ ax = hx&0x7fffffff;
+
+ k = 1;
+ if (hx < 0x3ed413d0) { /* 1+x < sqrt(2)+ */
+ if(ax>=0x3f800000) { /* x <= -1.0 */
+ if(x==(float)-1.0) return -two25/zero; /* log1p(-1)=+inf */
+ else return (x-x)/(x-x); /* log1p(x<-1)=NaN */
+ }
+ if(ax<0x38000000) { /* |x| < 2**-15 */
+ if(two25+x>zero /* raise inexact */
+ &&ax<0x33800000) /* |x| < 2**-24 */
+ return x;
+ else
+ return x - x*x*(float)0.5;
+ }
+ if(hx>0||hx<=((int32_t)0xbe95f619)) {
+ k=0;f=x;hu=1;} /* sqrt(2)/2- <= 1+x < sqrt(2)+ */
+ }
+ if (hx >= 0x7f800000) return x+x;
+ if(k!=0) {
+ if(hx<0x5a000000) {
+ STRICT_ASSIGN(float,u,(float)1.0+x);
+ GET_FLOAT_WORD(hu,u);
+ k = (hu>>23)-127;
+ /* correction term */
+ c = (k>0)? (float)1.0-(u-x):x-(u-(float)1.0);
+ c /= u;
+ } else {
+ u = x;
+ GET_FLOAT_WORD(hu,u);
+ k = (hu>>23)-127;
+ c = 0;
+ }
+ hu &= 0x007fffff;
+ /*
+ * The approximation to sqrt(2) used in thresholds is not
+ * critical. However, the ones used above must give less
+ * strict bounds than the one here so that the k==0 case is
+ * never reached from here, since here we have committed to
+ * using the correction term but don't use it if k==0.
+ */
+ if(hu<0x3504f4) { /* u < sqrt(2) */
+ SET_FLOAT_WORD(u,hu|0x3f800000);/* normalize u */
+ } else {
+ k += 1;
+ SET_FLOAT_WORD(u,hu|0x3f000000); /* normalize u/2 */
+ hu = (0x00800000-hu)>>2;
+ }
+ f = u-(float)1.0;
+ }
+ hfsq=(float)0.5*f*f;
+ if(hu==0) { /* |f| < 2**-20 */
+ if(f==zero) {
+ if(k==0) {
+ return zero;
+ } else {
+ c += k*ln2_lo;
+ return k*ln2_hi+c;
+ }
+ }
+ R = hfsq*((float)1.0-(float)0.66666666666666666*f);
+ if(k==0) return f-R; else
+ return k*ln2_hi-((R-(k*ln2_lo+c))-f);
+ }
+ s = f/((float)2.0+f);
+ z = s*s;
+ R = z*(Lp1+z*(Lp2+z*(Lp3+z*(Lp4+z*(Lp5+z*(Lp6+z*Lp7))))));
+ if(k==0) return f-(hfsq-s*(hfsq+R)); else
+ return k*ln2_hi-((hfsq-(s*(hfsq+R)+(k*ln2_lo+c)))-f);
+}
--- /dev/null
+/* @(#)s_logb.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/src/s_logb.c,v 1.12 2008/02/08 01:22:13 bde Exp $");
+
+/*
+ * double logb(x)
+ * IEEE 754 logb. Included to pass IEEE test suite. Not recommend.
+ * Use ilogb instead.
+ */
+
+#include <float.h>
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+static const double
+two54 = 1.80143985094819840000e+16; /* 43500000 00000000 */
+
+OLM_DLLEXPORT double
+logb(double x)
+{
+ int32_t lx,ix;
+ EXTRACT_WORDS(ix,lx,x);
+ ix &= 0x7fffffff; /* high |x| */
+ if((ix|lx)==0) return -1.0/fabs(x);
+ if(ix>=0x7ff00000) return x*x;
+ if(ix<0x00100000) {
+ x *= two54; /* convert subnormal x to normal */
+ GET_HIGH_WORD(ix,x);
+ ix &= 0x7fffffff;
+ return (double) ((ix>>20)-1023-54);
+ } else
+ return (double) ((ix>>20)-1023);
+}
+
+#if (LDBL_MANT_DIG == 53)
+__weak_reference(logb, logbl);
+#endif
--- /dev/null
+/* s_logbf.c -- float version of s_logb.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/src/s_logbf.c,v 1.9 2008/02/22 02:30:35 das Exp $");
+
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+static const float
+two25 = 3.355443200e+07; /* 0x4c000000 */
+
+OLM_DLLEXPORT float
+logbf(float x)
+{
+ int32_t ix;
+ GET_FLOAT_WORD(ix,x);
+ ix &= 0x7fffffff; /* high |x| */
+ if(ix==0) return (float)-1.0/fabsf(x);
+ if(ix>=0x7f800000) return x*x;
+ if(ix<0x00800000) {
+ x *= two25; /* convert subnormal x to normal */
+ GET_FLOAT_WORD(ix,x);
+ ix &= 0x7fffffff;
+ return (float) ((ix>>23)-127-25);
+ } else
+ return (float) ((ix>>23)-127);
+}
--- /dev/null
+/*
+ * From: @(#)s_ilogb.c 5.1 93/09/24
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include <float.h>
+#include <limits.h>
+#include <openlibm_math.h>
+
+#include "fpmath.h"
+#include "math_private.h"
+
+OLM_DLLEXPORT long double
+logbl(long double x)
+{
+ union IEEEl2bits u;
+ unsigned long m;
+ int b;
+
+ u.e = x;
+ if (u.bits.exp == 0) {
+ if ((u.bits.manl | u.bits.manh) == 0) { /* x == 0 */
+ u.bits.sign = 1;
+ return (1.0L / u.e);
+ }
+ /* denormalized */
+ if (u.bits.manh == 0) {
+ m = 1lu << (LDBL_MANL_SIZE - 1);
+ for (b = LDBL_MANH_SIZE; !(u.bits.manl & m); m >>= 1)
+ b++;
+ } else {
+ m = 1lu << (LDBL_MANH_SIZE - 1);
+ for (b = 0; !(u.bits.manh & m); m >>= 1)
+ b++;
+ }
+#ifdef LDBL_IMPLICIT_NBIT
+ b++;
+#endif
+ return ((long double)(LDBL_MIN_EXP - b - 1));
+ }
+ if (u.bits.exp < (LDBL_MAX_EXP << 1) - 1) /* normal */
+ return ((long double)(u.bits.exp - LDBL_MAX_EXP + 1));
+ else /* +/- inf or nan */
+ return (x * x);
+}
--- /dev/null
+/*-
+ * Copyright (c) 2005 David Schultz <das@FreeBSD.ORG>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "cdefs-compat.h"
+
+#include <openlibm_fenv.h>
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+#ifndef type
+//__FBSDID("$FreeBSD: src/lib/msun/src/s_lrint.c,v 1.1 2005/01/11 23:12:55 das Exp $");
+#define type double
+#define roundit rint
+#define dtype long
+#define fn lrint
+#endif
+
+/*
+ * C99 says we should not raise a spurious inexact exception when an
+ * invalid exception is raised. Unfortunately, the set of inputs
+ * that overflows depends on the rounding mode when 'dtype' has more
+ * significant bits than 'type'. Hence, we bend over backwards for the
+ * sake of correctness; an MD implementation could be more efficient.
+ */
+OLM_DLLEXPORT dtype
+fn(type x)
+{
+ fenv_t env;
+ dtype d;
+
+ feholdexcept(&env);
+ d = (dtype)roundit(x);
+ if (fetestexcept(FE_INVALID))
+ feclearexcept(FE_INEXACT);
+ feupdateenv(&env);
+ return (d);
+}
--- /dev/null
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/src/s_lrintf.c,v 1.1 2005/01/11 23:12:55 das Exp $");
+
+#define type float
+#define roundit rintf
+#define dtype long
+#define fn lrintf
+
+#include "s_lrint.c"
--- /dev/null
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/src/s_lrintl.c,v 1.1 2008/01/14 02:12:06 das Exp $");
+
+#define type long double
+#define roundit rintl
+#define dtype long
+#define fn lrintl
+
+#include "s_lrint.c"
--- /dev/null
+/*-
+ * Copyright (c) 2005 David Schultz <das@FreeBSD.ORG>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "cdefs-compat.h"
+
+#include <limits.h>
+#include <openlibm_fenv.h>
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+#ifndef type
+//__FBSDID("$FreeBSD: src/lib/msun/src/s_lround.c,v 1.2 2005/04/08 00:52:16 das Exp $");
+#define type double
+#define roundit round
+#define dtype long
+#define DTYPE_MIN LONG_MIN
+#define DTYPE_MAX LONG_MAX
+#define fn lround
+#endif
+
+/*
+ * If type has more precision than dtype, the endpoints dtype_(min|max) are
+ * of the form xxx.5; they are "out of range" because lround() rounds away
+ * from 0. On the other hand, if type has less precision than dtype, then
+ * all values that are out of range are integral, so we might as well assume
+ * that everything is in range. At compile time, INRANGE(x) should reduce to
+ * two floating-point comparisons in the former case, or TRUE otherwise.
+ */
+static const type dtype_min = DTYPE_MIN - 0.5;
+static const type dtype_max = DTYPE_MAX + 0.5;
+#define INRANGE(x) (dtype_max - DTYPE_MAX != 0.5 || \
+ ((x) > dtype_min && (x) < dtype_max))
+
+OLM_DLLEXPORT dtype
+fn(type x)
+{
+
+ if (INRANGE(x)) {
+ x = roundit(x);
+ return ((dtype)x);
+ } else {
+ feraiseexcept(FE_INVALID);
+ return (DTYPE_MAX);
+ }
+}
--- /dev/null
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/src/s_lroundf.c,v 1.2 2005/04/08 00:52:27 das Exp $");
+
+#define type float
+#define roundit roundf
+#define dtype long
+#define DTYPE_MIN LONG_MIN
+#define DTYPE_MAX LONG_MAX
+#define fn lroundf
+
+#include "s_lround.c"
--- /dev/null
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/src/s_lroundl.c,v 1.1 2005/04/08 01:24:08 das Exp $");
+
+#define type long double
+#define roundit roundl
+#define dtype long
+#define DTYPE_MIN LONG_MIN
+#define DTYPE_MAX LONG_MAX
+#define fn lroundl
+
+#include "s_lround.c"
--- /dev/null
+/* @(#)s_modf.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/*
+ * modf(double x, double *iptr)
+ * return fraction part of x, and return x's integral part in *iptr.
+ * Method:
+ * Bit twiddling.
+ *
+ * Exception:
+ * No exception.
+ */
+
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+static const double one = 1.0;
+
+OLM_DLLEXPORT double
+modf(double x, double *iptr)
+{
+ int32_t i0,i1,j0;
+ u_int32_t i;
+ EXTRACT_WORDS(i0,i1,x);
+ j0 = ((i0>>20)&0x7ff)-0x3ff; /* exponent of x */
+ if(j0<20) { /* integer part in high x */
+ if(j0<0) { /* |x|<1 */
+ INSERT_WORDS(*iptr,i0&0x80000000,0); /* *iptr = +-0 */
+ return x;
+ } else {
+ i = (0x000fffff)>>j0;
+ if(((i0&i)|i1)==0) { /* x is integral */
+ u_int32_t high;
+ *iptr = x;
+ GET_HIGH_WORD(high,x);
+ INSERT_WORDS(x,high&0x80000000,0); /* return +-0 */
+ return x;
+ } else {
+ INSERT_WORDS(*iptr,i0&(~i),0);
+ return x - *iptr;
+ }
+ }
+ } else if (j0>51) { /* no fraction part */
+ u_int32_t high;
+ if (j0 == 0x400) { /* inf/NaN */
+ *iptr = x;
+ return 0.0 / x;
+ }
+ *iptr = x*one;
+ GET_HIGH_WORD(high,x);
+ INSERT_WORDS(x,high&0x80000000,0); /* return +-0 */
+ return x;
+ } else { /* fraction part in low x */
+ i = ((u_int32_t)(0xffffffff))>>(j0-20);
+ if((i1&i)==0) { /* x is integral */
+ u_int32_t high;
+ *iptr = x;
+ GET_HIGH_WORD(high,x);
+ INSERT_WORDS(x,high&0x80000000,0); /* return +-0 */
+ return x;
+ } else {
+ INSERT_WORDS(*iptr,i0,i1&(~i));
+ return x - *iptr;
+ }
+ }
+}
--- /dev/null
+/* s_modff.c -- float version of s_modf.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/src/s_modff.c,v 1.9 2008/02/22 02:30:35 das Exp $");
+
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+static const float one = 1.0;
+
+OLM_DLLEXPORT float
+modff(float x, float *iptr)
+{
+ int32_t i0,j0;
+ u_int32_t i;
+ GET_FLOAT_WORD(i0,x);
+ j0 = ((i0>>23)&0xff)-0x7f; /* exponent of x */
+ if(j0<23) { /* integer part in x */
+ if(j0<0) { /* |x|<1 */
+ SET_FLOAT_WORD(*iptr,i0&0x80000000); /* *iptr = +-0 */
+ return x;
+ } else {
+ i = (0x007fffff)>>j0;
+ if((i0&i)==0) { /* x is integral */
+ u_int32_t ix;
+ *iptr = x;
+ GET_FLOAT_WORD(ix,x);
+ SET_FLOAT_WORD(x,ix&0x80000000); /* return +-0 */
+ return x;
+ } else {
+ SET_FLOAT_WORD(*iptr,i0&(~i));
+ return x - *iptr;
+ }
+ }
+ } else { /* no fraction part */
+ u_int32_t ix;
+ *iptr = x*one;
+ if (x != x) /* NaN */
+ return x;
+ GET_FLOAT_WORD(ix,x);
+ SET_FLOAT_WORD(x,ix&0x80000000); /* return +-0 */
+ return x;
+ }
+}
--- /dev/null
+/*-
+ * Copyright (c) 2007 David Schultz <das@FreeBSD.ORG>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * Derived from s_modf.c, which has the following Copyright:
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ *
+ * $FreeBSD: src/lib/msun/src/s_modfl.c,v 1.1 2007/01/07 07:54:21 das Exp $
+ */
+
+#include <float.h>
+#include <openlibm_math.h>
+
+#include "fpmath.h"
+#include "math_private.h"
+
+#if LDBL_MANL_SIZE > 32
+#define MASK ((u_int64_t)-1)
+#else
+#define MASK ((u_int32_t)-1)
+#endif
+/* Return the last n bits of a word, representing the fractional part. */
+#define GETFRAC(bits, n) ((bits) & ~(MASK << (n)))
+/* The number of fraction bits in manh, not counting the integer bit */
+#define HIBITS (LDBL_MANT_DIG - LDBL_MANL_SIZE)
+
+static const long double zero[] = { 0.0L, -0.0L };
+
+OLM_DLLEXPORT long double
+modfl(long double x, long double *iptr)
+{
+ union IEEEl2bits ux;
+ int e;
+
+ ux.e = x;
+ e = ux.bits.exp - LDBL_MAX_EXP + 1;
+ if (e < HIBITS) { /* Integer part is in manh. */
+ if (e < 0) { /* |x|<1 */
+ *iptr = zero[ux.bits.sign];
+ return (x);
+ } else {
+ if ((GETFRAC(ux.bits.manh, HIBITS - 1 - e) |
+ ux.bits.manl) == 0) { /* X is an integer. */
+ *iptr = x;
+ return (zero[ux.bits.sign]);
+ } else {
+ /* Clear all but the top e+1 bits. */
+ ux.bits.manh >>= HIBITS - 1 - e;
+ ux.bits.manh <<= HIBITS - 1 - e;
+ ux.bits.manl = 0;
+ *iptr = ux.e;
+ return (x - ux.e);
+ }
+ }
+ } else if (e >= LDBL_MANT_DIG - 1) { /* x has no fraction part. */
+ *iptr = x;
+ if (x != x) /* Handle NaNs. */
+ return (x);
+ return (zero[ux.bits.sign]);
+ } else { /* Fraction part is in manl. */
+ if (GETFRAC(ux.bits.manl, LDBL_MANT_DIG - 1 - e) == 0) {
+ /* x is integral. */
+ *iptr = x;
+ return (zero[ux.bits.sign]);
+ } else {
+ /* Clear all but the top e+1 bits. */
+ ux.bits.manl >>= LDBL_MANT_DIG - 1 - e;
+ ux.bits.manl <<= LDBL_MANT_DIG - 1 - e;
+ *iptr = ux.e;
+ return (x - ux.e);
+ }
+ }
+}
--- /dev/null
+/*-
+ * Copyright (c) 2007 David Schultz
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: src/lib/msun/src/s_nan.c,v 1.2 2007/12/18 23:46:32 das Exp $
+ */
+
+//VBS
+//#include <sys/endian.h>
+#include <ctype.h>
+#include <float.h>
+#include <openlibm_math.h>
+#include <stdint.h>
+#include <string.h> //for memset
+
+#include "math_private.h"
+
+#if !defined(__APPLE__) && !defined(__FreeBSD__) && !defined(__DragonFly__)
+static __inline int digittoint(int c) {
+ if ('0' <= c && c <= '9')
+ return (c - '0');
+ else if ('A' <= c && c <= 'F')
+ return (c - 'A' + 10);
+ else if ('a' <= c && c <= 'f')
+ return (c - 'a' + 10);
+ return 0;
+}
+#endif
+
+
+/*
+ * Scan a string of hexadecimal digits (the format nan(3) expects) and
+ * make a bit array (using the local endianness). We stop when we
+ * encounter an invalid character, NUL, etc. If we overflow, we do
+ * the same as gcc's __builtin_nan(), namely, discard the high order bits.
+ *
+ * The format this routine accepts needs to be compatible with what is used
+ * in contrib/gdtoa/hexnan.c (for strtod/scanf) and what is used in
+ * __builtin_nan(). In fact, we're only 100% compatible for strings we
+ * consider valid, so we might be violating the C standard. But it's
+ * impossible to use nan(3) portably anyway, so this seems good enough.
+ */
+OLM_DLLEXPORT void
+__scan_nan(u_int32_t *words, int num_words, const char *s)
+{
+ int si; /* index into s */
+ int bitpos; /* index into words (in bits) */
+
+ memset(words, 0, num_words * sizeof(u_int32_t));
+
+ /* Allow a leading '0x'. (It's expected, but redundant.) */
+ if (s[0] == '0' && (s[1] == 'x' || s[1] == 'X'))
+ s += 2;
+
+ /* Scan forwards in the string, looking for the end of the sequence. */
+ for (si = 0; isxdigit(s[si]); si++)
+ ;
+
+ /* Scan backwards, filling in the bits in words[] as we go. */
+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+ for (bitpos = 0; bitpos < 32 * num_words; bitpos += 4) {
+#else
+ for (bitpos = 32 * num_words - 4; bitpos >= 0; bitpos -= 4) {
+#endif
+ if (--si < 0)
+ break;
+ words[bitpos / 32] |= digittoint(s[si]) << (bitpos % 32);
+ }
+}
+
+OLM_DLLEXPORT double
+nan(const char *s)
+{
+ union {
+ double d;
+ u_int32_t bits[2];
+ } u;
+
+ __scan_nan(u.bits, 2, s);
+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+ u.bits[1] |= 0x7ff80000;
+#else
+ u.bits[0] |= 0x7ff80000;
+#endif
+ return (u.d);
+}
+
+OLM_DLLEXPORT float
+nanf(const char *s)
+{
+ union {
+ float f;
+ u_int32_t bits[1];
+ } u;
+
+ __scan_nan(u.bits, 1, s);
+ u.bits[0] |= 0x7fc00000;
+ return (u.f);
+}
+
+#if (LDBL_MANT_DIG == 53)
+__weak_reference(nan, nanl);
+#endif
--- /dev/null
+/*-
+ * Copyright (c) 2004 David Schultz <das@FreeBSD.ORG>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/src/s_nearbyint.c,v 1.2 2008/01/14 02:12:06 das Exp $");
+
+#include <openlibm_fenv.h>
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+/*
+ * We save and restore the floating-point environment to avoid raising
+ * an inexact exception. We can get away with using fesetenv()
+ * instead of feclearexcept()/feupdateenv() to restore the environment
+ * because the only exception defined for rint() is overflow, and
+ * rounding can't overflow as long as emax >= p.
+ */
+#define DECL(type, fn, rint) \
+OLM_DLLEXPORT type \
+fn(type x) \
+{ \
+ type ret; \
+ fenv_t env; \
+ \
+ fegetenv(&env); \
+ ret = rint(x); \
+ fesetenv(&env); \
+ return (ret); \
+}
+
+DECL(double, nearbyint, rint)
+DECL(float, nearbyintf, rintf)
--- /dev/null
+/* @(#)s_nextafter.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/src/s_nextafter.c,v 1.12 2008/02/22 02:30:35 das Exp $");
+
+/* IEEE functions
+ * nextafter(x,y)
+ * return the next machine floating-point number of x in the
+ * direction toward y.
+ * Special cases:
+ */
+
+#include <float.h>
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+OLM_DLLEXPORT double
+nextafter(double x, double y)
+{
+ volatile double t;
+ int32_t hx,hy,ix,iy;
+ u_int32_t lx,ly;
+
+ EXTRACT_WORDS(hx,lx,x);
+ EXTRACT_WORDS(hy,ly,y);
+ ix = hx&0x7fffffff; /* |x| */
+ iy = hy&0x7fffffff; /* |y| */
+
+ if(((ix>=0x7ff00000)&&((ix-0x7ff00000)|lx)!=0) || /* x is nan */
+ ((iy>=0x7ff00000)&&((iy-0x7ff00000)|ly)!=0)) /* y is nan */
+ return x+y;
+ if(x==y) return y; /* x=y, return y */
+ if((ix|lx)==0) { /* x == 0 */
+ INSERT_WORDS(x,hy&0x80000000,1); /* return +-minsubnormal */
+ t = x*x;
+ if(t==x) return t; else return x; /* raise underflow flag */
+ }
+ if(hx>=0) { /* x > 0 */
+ if(hx>hy||((hx==hy)&&(lx>ly))) { /* x > y, x -= ulp */
+ if(lx==0) hx -= 1;
+ lx -= 1;
+ } else { /* x < y, x += ulp */
+ lx += 1;
+ if(lx==0) hx += 1;
+ }
+ } else { /* x < 0 */
+ if(hy>=0||hx>hy||((hx==hy)&&(lx>ly))){/* x < y, x -= ulp */
+ if(lx==0) hx -= 1;
+ lx -= 1;
+ } else { /* x > y, x += ulp */
+ lx += 1;
+ if(lx==0) hx += 1;
+ }
+ }
+ hy = hx&0x7ff00000;
+ if(hy>=0x7ff00000) return x+x; /* overflow */
+ if(hy<0x00100000) { /* underflow */
+ t = x*x;
+ if(t!=x) { /* raise underflow flag */
+ INSERT_WORDS(y,hx,lx);
+ return y;
+ }
+ }
+ INSERT_WORDS(x,hx,lx);
+ return x;
+}
+
+#if (LDBL_MANT_DIG == 53)
+__weak_reference(nextafter, nexttoward);
+__weak_reference(nextafter, nexttowardl);
+__weak_reference(nextafter, nextafterl);
+#endif
--- /dev/null
+/* s_nextafterf.c -- float version of s_nextafter.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/src/s_nextafterf.c,v 1.11 2008/02/22 02:30:35 das Exp $");
+
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+OLM_DLLEXPORT float
+nextafterf(float x, float y)
+{
+ volatile float t;
+ int32_t hx,hy,ix,iy;
+
+ GET_FLOAT_WORD(hx,x);
+ GET_FLOAT_WORD(hy,y);
+ ix = hx&0x7fffffff; /* |x| */
+ iy = hy&0x7fffffff; /* |y| */
+
+ if((ix>0x7f800000) || /* x is nan */
+ (iy>0x7f800000)) /* y is nan */
+ return x+y;
+ if(x==y) return y; /* x=y, return y */
+ if(ix==0) { /* x == 0 */
+ SET_FLOAT_WORD(x,(hy&0x80000000)|1);/* return +-minsubnormal */
+ t = x*x;
+ if(t==x) return t; else return x; /* raise underflow flag */
+ }
+ if(hx>=0) { /* x > 0 */
+ if(hx>hy) { /* x > y, x -= ulp */
+ hx -= 1;
+ } else { /* x < y, x += ulp */
+ hx += 1;
+ }
+ } else { /* x < 0 */
+ if(hy>=0||hx>hy){ /* x < y, x -= ulp */
+ hx -= 1;
+ } else { /* x > y, x += ulp */
+ hx += 1;
+ }
+ }
+ hy = hx&0x7f800000;
+ if(hy>=0x7f800000) return x+x; /* overflow */
+ if(hy<0x00800000) { /* underflow */
+ t = x*x;
+ if(t!=x) { /* raise underflow flag */
+ SET_FLOAT_WORD(y,hx);
+ return y;
+ }
+ }
+ SET_FLOAT_WORD(x,hx);
+ return x;
+}
--- /dev/null
+/* @(#)s_nextafter.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/src/s_nextafterl.c,v 1.2 2008/02/22 02:30:36 das Exp $");
+
+/* IEEE functions
+ * nextafter(x,y)
+ * return the next machine floating-point number of x in the
+ * direction toward y.
+ * Special cases:
+ */
+
+#include <float.h>
+#include <openlibm_math.h>
+
+#include "fpmath.h"
+#include "math_private.h"
+
+#if LDBL_MAX_EXP != 0x4000
+#error "Unsupported long double format"
+#endif
+
+OLM_DLLEXPORT long double
+nextafterl(long double x, long double y)
+{
+ volatile long double t;
+ union IEEEl2bits ux, uy;
+
+ ux.e = x;
+ uy.e = y;
+
+ if ((ux.bits.exp == 0x7fff &&
+ ((ux.bits.manh&~LDBL_NBIT)|ux.bits.manl) != 0) ||
+ (uy.bits.exp == 0x7fff &&
+ ((uy.bits.manh&~LDBL_NBIT)|uy.bits.manl) != 0))
+ return x+y; /* x or y is nan */
+ if(x==y) return y; /* x=y, return y */
+ if(x==0.0) {
+ ux.bits.manh = 0; /* return +-minsubnormal */
+ ux.bits.manl = 1;
+ ux.bits.sign = uy.bits.sign;
+ t = ux.e*ux.e;
+ if(t==ux.e) return t; else return ux.e; /* raise underflow flag */
+ }
+ if((x>0.0) ^ (x<y)) { /* x -= ulp */
+ if(ux.bits.manl==0) {
+ if ((ux.bits.manh&~LDBL_NBIT)==0)
+ ux.bits.exp -= 1;
+ ux.bits.manh = (ux.bits.manh - 1) | (ux.bits.manh & LDBL_NBIT);
+ }
+ ux.bits.manl -= 1;
+ } else { /* x += ulp */
+ ux.bits.manl += 1;
+ if(ux.bits.manl==0) {
+ ux.bits.manh = (ux.bits.manh + 1) | (ux.bits.manh & LDBL_NBIT);
+ if ((ux.bits.manh&~LDBL_NBIT)==0)
+ ux.bits.exp += 1;
+ }
+ }
+ if(ux.bits.exp==0x7fff) return x+x; /* overflow */
+ if(ux.bits.exp==0) { /* underflow */
+ mask_nbit_l(ux);
+ t = ux.e * ux.e;
+ if(t!=ux.e) /* raise underflow flag */
+ return ux.e;
+ }
+ return ux.e;
+}
+
+__strong_reference(nextafterl, nexttowardl);
--- /dev/null
+/* @(#)s_nextafter.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/src/s_nexttoward.c,v 1.3 2011/02/10 07:38:13 das Exp $");
+
+/*
+ * We assume that a long double has a 15-bit exponent. On systems
+ * where long double is the same as double, nexttoward() is an alias
+ * for nextafter(), so we don't use this routine.
+ */
+
+#include <float.h>
+#include <openlibm_math.h>
+
+#include "fpmath.h"
+#include "math_private.h"
+
+#if LDBL_MAX_EXP != 0x4000
+#error "Unsupported long double format"
+#endif
+
+OLM_DLLEXPORT double
+nexttoward(double x, long double y)
+{
+ union IEEEl2bits uy;
+ volatile double t;
+ int32_t hx,ix;
+ u_int32_t lx;
+
+ EXTRACT_WORDS(hx,lx,x);
+ ix = hx&0x7fffffff; /* |x| */
+ uy.e = y;
+
+ if(((ix>=0x7ff00000)&&((ix-0x7ff00000)|lx)!=0) ||
+ (uy.bits.exp == 0x7fff &&
+ ((uy.bits.manh&~LDBL_NBIT)|uy.bits.manl) != 0))
+ return x+y; /* x or y is nan */
+ if(x==y) return (double)y; /* x=y, return y */
+ if(x==0.0) {
+ INSERT_WORDS(x,uy.bits.sign<<31,1); /* return +-minsubnormal */
+ t = x*x;
+ if(t==x) return t; else return x; /* raise underflow flag */
+ }
+ if((hx>0.0) ^ (x < y)) { /* x -= ulp */
+ if(lx==0) hx -= 1;
+ lx -= 1;
+ } else { /* x += ulp */
+ lx += 1;
+ if(lx==0) hx += 1;
+ }
+ ix = hx&0x7ff00000;
+ if(ix>=0x7ff00000) return x+x; /* overflow */
+ if(ix<0x00100000) { /* underflow */
+ t = x*x;
+ if(t!=x) { /* raise underflow flag */
+ INSERT_WORDS(x,hx,lx);
+ return x;
+ }
+ }
+ INSERT_WORDS(x,hx,lx);
+ return x;
+}
--- /dev/null
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/src/s_nexttowardf.c,v 1.3 2011/02/10 07:38:38 das Exp $");
+
+#include <float.h>
+#include <openlibm_math.h>
+
+#include "fpmath.h"
+#include "math_private.h"
+
+#define LDBL_INFNAN_EXP (LDBL_MAX_EXP * 2 - 1)
+
+#ifdef LONG_DOUBLE
+OLM_DLLEXPORT float
+nexttowardf(float x, long double y)
+{
+ union IEEEl2bits uy;
+ volatile float t;
+ int32_t hx,ix;
+
+ GET_FLOAT_WORD(hx,x);
+ ix = hx&0x7fffffff; /* |x| */
+ uy.e = y;
+
+ if((ix>0x7f800000) ||
+ (uy.bits.exp == LDBL_INFNAN_EXP &&
+ ((uy.bits.manh&~LDBL_NBIT)|uy.bits.manl) != 0))
+ return x+y; /* x or y is nan */
+ if(x==y) return (float)y; /* x=y, return y */
+ if(ix==0) { /* x == 0 */
+ SET_FLOAT_WORD(x,(uy.bits.sign<<31)|1);/* return +-minsubnormal */
+ t = x*x;
+ if(t==x) return t; else return x; /* raise underflow flag */
+ }
+ if((hx>=0) ^ (x < y)) /* x -= ulp */
+ hx -= 1;
+ else /* x += ulp */
+ hx += 1;
+ ix = hx&0x7f800000;
+ if(ix>=0x7f800000) return x+x; /* overflow */
+ if(ix<0x00800000) { /* underflow */
+ t = x*x;
+ if(t!=x) { /* raise underflow flag */
+ SET_FLOAT_WORD(x,hx);
+ return x;
+ }
+ }
+ SET_FLOAT_WORD(x,hx);
+ return x;
+}
+#endif
--- /dev/null
+/* @(#)e_fmod.c 1.3 95/01/18 */
+/*-
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunSoft, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/src/s_remquo.c,v 1.2 2008/03/30 20:47:26 das Exp $");
+
+#include <float.h>
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+static const double Zero[] = {0.0, -0.0,};
+
+/*
+ * Return the IEEE remainder and set *quo to the last n bits of the
+ * quotient, rounded to the nearest integer. We choose n=31 because
+ * we wind up computing all the integer bits of the quotient anyway as
+ * a side-effect of computing the remainder by the shift and subtract
+ * method. In practice, this is far more bits than are needed to use
+ * remquo in reduction algorithms.
+ */
+OLM_DLLEXPORT double
+remquo(double x, double y, int *quo)
+{
+ int32_t n,hx,hy,hz,ix,iy,sx,i;
+ u_int32_t lx,ly,lz,q,sxy;
+
+ EXTRACT_WORDS(hx,lx,x);
+ EXTRACT_WORDS(hy,ly,y);
+ sxy = (hx ^ hy) & 0x80000000;
+ sx = hx&0x80000000; /* sign of x */
+ hx ^=sx; /* |x| */
+ hy &= 0x7fffffff; /* |y| */
+
+ /* purge off exception values */
+ if((hy|ly)==0||(hx>=0x7ff00000)|| /* y=0,or x not finite */
+ ((hy|((ly|-ly)>>31))>0x7ff00000)) /* or y is NaN */
+ return (x*y)/(x*y);
+ if(hx<=hy) {
+ if((hx<hy)||(lx<ly)) {
+ q = 0;
+ goto fixup; /* |x|<|y| return x or x-y */
+ }
+ if(lx==ly) {
+ *quo = 1;
+ return Zero[(u_int32_t)sx>>31]; /* |x|=|y| return x*0*/
+ }
+ }
+
+ /* determine ix = ilogb(x) */
+ if(hx<0x00100000) { /* subnormal x */
+ if(hx==0) {
+ for (ix = -1043, i=lx; i>0; i<<=1) ix -=1;
+ } else {
+ for (ix = -1022,i=(hx<<11); i>0; i<<=1) ix -=1;
+ }
+ } else ix = (hx>>20)-1023;
+
+ /* determine iy = ilogb(y) */
+ if(hy<0x00100000) { /* subnormal y */
+ if(hy==0) {
+ for (iy = -1043, i=ly; i>0; i<<=1) iy -=1;
+ } else {
+ for (iy = -1022,i=(hy<<11); i>0; i<<=1) iy -=1;
+ }
+ } else iy = (hy>>20)-1023;
+
+ /* set up {hx,lx}, {hy,ly} and align y to x */
+ if(ix >= -1022)
+ hx = 0x00100000|(0x000fffff&hx);
+ else { /* subnormal x, shift x to normal */
+ n = -1022-ix;
+ if(n<=31) {
+ hx = (hx<<n)|(lx>>(32-n));
+ lx <<= n;
+ } else {
+ hx = lx<<(n-32);
+ lx = 0;
+ }
+ }
+ if(iy >= -1022)
+ hy = 0x00100000|(0x000fffff&hy);
+ else { /* subnormal y, shift y to normal */
+ n = -1022-iy;
+ if(n<=31) {
+ hy = (hy<<n)|(ly>>(32-n));
+ ly <<= n;
+ } else {
+ hy = ly<<(n-32);
+ ly = 0;
+ }
+ }
+
+ /* fix point fmod */
+ n = ix - iy;
+ q = 0;
+ while(n--) {
+ hz=hx-hy;lz=lx-ly; if(lx<ly) hz -= 1;
+ if(hz<0){hx = hx+hx+(lx>>31); lx = lx+lx;}
+ else {hx = hz+hz+(lz>>31); lx = lz+lz; q++;}
+ q <<= 1;
+ }
+ hz=hx-hy;lz=lx-ly; if(lx<ly) hz -= 1;
+ if(hz>=0) {hx=hz;lx=lz;q++;}
+
+ /* convert back to floating value and restore the sign */
+ if((hx|lx)==0) { /* return sign(x)*0 */
+ *quo = (sxy ? -q : q);
+ return Zero[(u_int32_t)sx>>31];
+ }
+ while(hx<0x00100000) { /* normalize x */
+ hx = hx+hx+(lx>>31); lx = lx+lx;
+ iy -= 1;
+ }
+ if(iy>= -1022) { /* normalize output */
+ hx = ((hx-0x00100000)|((iy+1023)<<20));
+ } else { /* subnormal output */
+ n = -1022 - iy;
+ if(n<=20) {
+ lx = (lx>>n)|((u_int32_t)hx<<(32-n));
+ hx >>= n;
+ } else if (n<=31) {
+ lx = (hx<<(32-n))|(lx>>n); hx = sx;
+ } else {
+ lx = hx>>(n-32); hx = sx;
+ }
+ }
+fixup:
+ INSERT_WORDS(x,hx,lx);
+ y = fabs(y);
+ if (y < 0x1p-1021) {
+ if (x+x>y || (x+x==y && (q & 1))) {
+ q++;
+ x-=y;
+ }
+ } else if (x>0.5*y || (x==0.5*y && (q & 1))) {
+ q++;
+ x-=y;
+ }
+ GET_HIGH_WORD(hx,x);
+ SET_HIGH_WORD(x,hx^sx);
+ q &= 0x7fffffff;
+ *quo = (sxy ? -q : q);
+ return x;
+}
+
+#if LDBL_MANT_DIG == 53
+__weak_reference(remquo, remquol);
+#endif
--- /dev/null
+/* @(#)e_fmod.c 1.3 95/01/18 */
+/*-
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunSoft, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/src/s_remquof.c,v 1.1 2005/03/25 04:40:44 das Exp $");
+
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+static const float Zero[] = {0.0, -0.0,};
+
+/*
+ * Return the IEEE remainder and set *quo to the last n bits of the
+ * quotient, rounded to the nearest integer. We choose n=31 because
+ * we wind up computing all the integer bits of the quotient anyway as
+ * a side-effect of computing the remainder by the shift and subtract
+ * method. In practice, this is far more bits than are needed to use
+ * remquo in reduction algorithms.
+ */
+OLM_DLLEXPORT float
+remquof(float x, float y, int *quo)
+{
+ int32_t n,hx,hy,hz,ix,iy,sx,i;
+ u_int32_t q,sxy;
+
+ GET_FLOAT_WORD(hx,x);
+ GET_FLOAT_WORD(hy,y);
+ sxy = (hx ^ hy) & 0x80000000;
+ sx = hx&0x80000000; /* sign of x */
+ hx ^=sx; /* |x| */
+ hy &= 0x7fffffff; /* |y| */
+
+ /* purge off exception values */
+ if(hy==0||hx>=0x7f800000||hy>0x7f800000) /* y=0,NaN;or x not finite */
+ return (x*y)/(x*y);
+ if(hx<hy) {
+ q = 0;
+ goto fixup; /* |x|<|y| return x or x-y */
+ } else if(hx==hy) {
+ *quo = 1;
+ return Zero[(u_int32_t)sx>>31]; /* |x|=|y| return x*0*/
+ }
+
+ /* determine ix = ilogb(x) */
+ if(hx<0x00800000) { /* subnormal x */
+ for (ix = -126,i=(hx<<8); i>0; i<<=1) ix -=1;
+ } else ix = (hx>>23)-127;
+
+ /* determine iy = ilogb(y) */
+ if(hy<0x00800000) { /* subnormal y */
+ for (iy = -126,i=(hy<<8); i>0; i<<=1) iy -=1;
+ } else iy = (hy>>23)-127;
+
+ /* set up {hx,lx}, {hy,ly} and align y to x */
+ if(ix >= -126)
+ hx = 0x00800000|(0x007fffff&hx);
+ else { /* subnormal x, shift x to normal */
+ n = -126-ix;
+ hx <<= n;
+ }
+ if(iy >= -126)
+ hy = 0x00800000|(0x007fffff&hy);
+ else { /* subnormal y, shift y to normal */
+ n = -126-iy;
+ hy <<= n;
+ }
+
+ /* fix point fmod */
+ n = ix - iy;
+ q = 0;
+ while(n--) {
+ hz=hx-hy;
+ if(hz<0) hx = hx << 1;
+ else {hx = hz << 1; q++;}
+ q <<= 1;
+ }
+ hz=hx-hy;
+ if(hz>=0) {hx=hz;q++;}
+
+ /* convert back to floating value and restore the sign */
+ if(hx==0) { /* return sign(x)*0 */
+ *quo = (sxy ? -q : q);
+ return Zero[(u_int32_t)sx>>31];
+ }
+ while(hx<0x00800000) { /* normalize x */
+ hx <<= 1;
+ iy -= 1;
+ }
+ if(iy>= -126) { /* normalize output */
+ hx = ((hx-0x00800000)|((iy+127)<<23));
+ } else { /* subnormal output */
+ n = -126 - iy;
+ hx >>= n;
+ }
+fixup:
+ SET_FLOAT_WORD(x,hx);
+ y = fabsf(y);
+ if (y < 0x1p-125f) {
+ if (x+x>y || (x+x==y && (q & 1))) {
+ q++;
+ x-=y;
+ }
+ } else if (x>0.5f*y || (x==0.5f*y && (q & 1))) {
+ q++;
+ x-=y;
+ }
+ GET_FLOAT_WORD(hx,x);
+ SET_FLOAT_WORD(x,hx^sx);
+ q &= 0x7fffffff;
+ *quo = (sxy ? -q : q);
+ return x;
+}
--- /dev/null
+/* @(#)e_fmod.c 1.3 95/01/18 */
+/*-
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunSoft, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/src/s_remquol.c,v 1.2 2008/07/31 20:09:47 das Exp $");
+
+#include <float.h>
+#include <openlibm_math.h>
+#include <stdint.h>
+
+#include "fpmath.h"
+#include "math_private.h"
+
+#define BIAS (LDBL_MAX_EXP - 1)
+
+#if LDBL_MANL_SIZE > 32
+typedef u_int64_t manl_t;
+#else
+typedef u_int32_t manl_t;
+#endif
+
+#if LDBL_MANH_SIZE > 32
+typedef u_int64_t manh_t;
+#else
+typedef u_int32_t manh_t;
+#endif
+
+/*
+ * These macros add and remove an explicit integer bit in front of the
+ * fractional mantissa, if the architecture doesn't have such a bit by
+ * default already.
+ */
+#ifdef LDBL_IMPLICIT_NBIT
+#define SET_NBIT(hx) ((hx) | (1ULL << LDBL_MANH_SIZE))
+#define HFRAC_BITS LDBL_MANH_SIZE
+#else
+#define SET_NBIT(hx) (hx)
+#define HFRAC_BITS (LDBL_MANH_SIZE - 1)
+#endif
+
+#define MANL_SHIFT (LDBL_MANL_SIZE - 1)
+
+static const long double Zero[] = {0.0L, -0.0L};
+
+/*
+ * Return the IEEE remainder and set *quo to the last n bits of the
+ * quotient, rounded to the nearest integer. We choose n=31 because
+ * we wind up computing all the integer bits of the quotient anyway as
+ * a side-effect of computing the remainder by the shift and subtract
+ * method. In practice, this is far more bits than are needed to use
+ * remquo in reduction algorithms.
+ *
+ * Assumptions:
+ * - The low part of the mantissa fits in a manl_t exactly.
+ * - The high part of the mantissa fits in an int64_t with enough room
+ * for an explicit integer bit in front of the fractional bits.
+ */
+OLM_DLLEXPORT long double
+remquol(long double x, long double y, int *quo)
+{
+ union IEEEl2bits ux, uy;
+ int64_t hx,hz; /* We need a carry bit even if LDBL_MANH_SIZE is 32. */
+ manh_t hy;
+ manl_t lx,ly,lz;
+ int ix,iy,n,q,sx,sxy;
+
+ ux.e = x;
+ uy.e = y;
+ sx = ux.bits.sign;
+ sxy = sx ^ uy.bits.sign;
+ ux.bits.sign = 0; /* |x| */
+ uy.bits.sign = 0; /* |y| */
+ x = ux.e;
+
+ /* purge off exception values */
+ if((uy.bits.exp|uy.bits.manh|uy.bits.manl)==0 || /* y=0 */
+ (ux.bits.exp == BIAS + LDBL_MAX_EXP) || /* or x not finite */
+ (uy.bits.exp == BIAS + LDBL_MAX_EXP &&
+ ((uy.bits.manh&~LDBL_NBIT)|uy.bits.manl)!=0)) /* or y is NaN */
+ return (x*y)/(x*y);
+ if(ux.bits.exp<=uy.bits.exp) {
+ if((ux.bits.exp<uy.bits.exp) ||
+ (ux.bits.manh<=uy.bits.manh &&
+ (ux.bits.manh<uy.bits.manh ||
+ ux.bits.manl<uy.bits.manl))) {
+ q = 0;
+ goto fixup; /* |x|<|y| return x or x-y */
+ }
+ if(ux.bits.manh==uy.bits.manh && ux.bits.manl==uy.bits.manl) {
+ *quo = 1;
+ return Zero[sx]; /* |x|=|y| return x*0*/
+ }
+ }
+
+ /* determine ix = ilogb(x) */
+ if(ux.bits.exp == 0) { /* subnormal x */
+ ux.e *= 0x1.0p512;
+ ix = ux.bits.exp - (BIAS + 512);
+ } else {
+ ix = ux.bits.exp - BIAS;
+ }
+
+ /* determine iy = ilogb(y) */
+ if(uy.bits.exp == 0) { /* subnormal y */
+ uy.e *= 0x1.0p512;
+ iy = uy.bits.exp - (BIAS + 512);
+ } else {
+ iy = uy.bits.exp - BIAS;
+ }
+
+ /* set up {hx,lx}, {hy,ly} and align y to x */
+ hx = SET_NBIT(ux.bits.manh);
+ hy = SET_NBIT(uy.bits.manh);
+ lx = ux.bits.manl;
+ ly = uy.bits.manl;
+
+ /* fix point fmod */
+ n = ix - iy;
+ q = 0;
+
+ while(n--) {
+ hz=hx-hy;lz=lx-ly; if(lx<ly) hz -= 1;
+ if(hz<0){hx = hx+hx+(lx>>MANL_SHIFT); lx = lx+lx;}
+ else {hx = hz+hz+(lz>>MANL_SHIFT); lx = lz+lz; q++;}
+ q <<= 1;
+ }
+ hz=hx-hy;lz=lx-ly; if(lx<ly) hz -= 1;
+ if(hz>=0) {hx=hz;lx=lz;q++;}
+
+ /* convert back to floating value and restore the sign */
+ if((hx|lx)==0) { /* return sign(x)*0 */
+ *quo = (sxy ? -q : q);
+ return Zero[sx];
+ }
+ while(hx<(1ULL<<HFRAC_BITS)) { /* normalize x */
+ hx = hx+hx+(lx>>MANL_SHIFT); lx = lx+lx;
+ iy -= 1;
+ }
+ ux.bits.manh = hx; /* The integer bit is truncated here if needed. */
+ ux.bits.manl = lx;
+ if (iy < LDBL_MIN_EXP) {
+ ux.bits.exp = iy + (BIAS + 512);
+ ux.e *= 0x1p-512;
+ } else {
+ ux.bits.exp = iy + BIAS;
+ }
+ ux.bits.sign = 0;
+ x = ux.e;
+fixup:
+ y = fabsl(y);
+ if (y < LDBL_MIN * 2) {
+ if (x+x>y || (x+x==y && (q & 1))) {
+ q++;
+ x-=y;
+ }
+ } else if (x>0.5*y || (x==0.5*y && (q & 1))) {
+ q++;
+ x-=y;
+ }
+
+ ux.e = x;
+ ux.bits.sign ^= sx;
+ x = ux.e;
+
+ q &= 0x7fffffff;
+ *quo = (sxy ? -q : q);
+ return x;
+}
--- /dev/null
+/* @(#)s_rint.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/src/s_rint.c,v 1.16 2008/02/22 02:30:35 das Exp $");
+
+/*
+ * rint(x)
+ * Return x rounded to integral value according to the prevailing
+ * rounding mode.
+ * Method:
+ * Using floating addition.
+ * Exception:
+ * Inexact flag raised if x not equal to rint(x).
+ */
+
+#include <float.h>
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+static const double
+TWO52[2]={
+ 4.50359962737049600000e+15, /* 0x43300000, 0x00000000 */
+ -4.50359962737049600000e+15, /* 0xC3300000, 0x00000000 */
+};
+
+OLM_DLLEXPORT double
+rint(double x)
+{
+ int32_t i0,j0,sx;
+ u_int32_t i,i1;
+ double w,t;
+ EXTRACT_WORDS(i0,i1,x);
+ sx = (i0>>31)&1;
+ j0 = ((i0>>20)&0x7ff)-0x3ff;
+ if(j0<20) {
+ if(j0<0) {
+ if(((i0&0x7fffffff)|i1)==0) return x;
+ i1 |= (i0&0x0fffff);
+ i0 &= 0xfffe0000;
+ i0 |= ((i1|-i1)>>12)&0x80000;
+ SET_HIGH_WORD(x,i0);
+ STRICT_ASSIGN(double,w,TWO52[sx]+x);
+ t = w-TWO52[sx];
+ GET_HIGH_WORD(i0,t);
+ SET_HIGH_WORD(t,(i0&0x7fffffff)|(sx<<31));
+ return t;
+ } else {
+ i = (0x000fffff)>>j0;
+ if(((i0&i)|i1)==0) return x; /* x is integral */
+ i>>=1;
+ if(((i0&i)|i1)!=0) {
+ /*
+ * Some bit is set after the 0.5 bit. To avoid the
+ * possibility of errors from double rounding in
+ * w = TWO52[sx]+x, adjust the 0.25 bit to a lower
+ * guard bit. We do this for all j0<=51. The
+ * adjustment is trickiest for j0==18 and j0==19
+ * since then it spans the word boundary.
+ */
+ if(j0==19) i1 = 0x40000000; else
+ if(j0==18) i1 = 0x80000000; else
+ i0 = (i0&(~i))|((0x20000)>>j0);
+ }
+ }
+ } else if (j0>51) {
+ if(j0==0x400) return x+x; /* inf or NaN */
+ else return x; /* x is integral */
+ } else {
+ i = ((u_int32_t)(0xffffffff))>>(j0-20);
+ if((i1&i)==0) return x; /* x is integral */
+ i>>=1;
+ if((i1&i)!=0) i1 = (i1&(~i))|((0x40000000)>>(j0-20));
+ }
+ INSERT_WORDS(x,i0,i1);
+ STRICT_ASSIGN(double,w,TWO52[sx]+x);
+ return w-TWO52[sx];
+}
+
+#if (LDBL_MANT_DIG == 53)
+__weak_reference(rint, rintl);
+#endif
--- /dev/null
+/* s_rintf.c -- float version of s_rint.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/src/s_rintf.c,v 1.12 2008/02/22 02:30:35 das Exp $");
+
+#include <float.h>
+#include <openlibm_math.h>
+#include <stdint.h>
+
+#include "math_private.h"
+
+static const float
+TWO23[2]={
+ 8.3886080000e+06, /* 0x4b000000 */
+ -8.3886080000e+06, /* 0xcb000000 */
+};
+
+OLM_DLLEXPORT float
+rintf(float x)
+{
+ int32_t i0,j0,sx;
+ float w,t;
+ GET_FLOAT_WORD(i0,x);
+ sx = (i0>>31)&1;
+ j0 = ((i0>>23)&0xff)-0x7f;
+ if(j0<23) {
+ if(j0<0) {
+ if((i0&0x7fffffff)==0) return x;
+ STRICT_ASSIGN(float,w,TWO23[sx]+x);
+ t = w-TWO23[sx];
+ GET_FLOAT_WORD(i0,t);
+ SET_FLOAT_WORD(t,(i0&0x7fffffff)|(sx<<31));
+ return t;
+ }
+ STRICT_ASSIGN(float,w,TWO23[sx]+x);
+ return w-TWO23[sx];
+ }
+ if(j0==0x80) return x+x; /* inf or NaN */
+ else return x; /* x is integral */
+}
--- /dev/null
+/*-
+ * Copyright (c) 2008 David Schultz <das@FreeBSD.ORG>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/src/s_rintl.c,v 1.5 2008/02/22 11:59:05 bde Exp $");
+
+#include <float.h>
+#include <openlibm_fenv.h>
+#include <openlibm_math.h>
+
+#include "fpmath.h"
+
+//VBS
+#include "math_private.h"
+
+
+#if LDBL_MAX_EXP != 0x4000
+/* We also require the usual bias, min exp and expsign packing. */
+#error "Unsupported long double format"
+#endif
+
+#define BIAS (LDBL_MAX_EXP - 1)
+
+static const float
+shift[2] = {
+#if LDBL_MANT_DIG == 64
+ 0x1.0p63, -0x1.0p63
+#elif LDBL_MANT_DIG == 113
+ 0x1.0p112, -0x1.0p112
+#else
+#error "Unsupported long double format"
+#endif
+};
+static const float zero[2] = { 0.0, -0.0 };
+
+OLM_DLLEXPORT long double
+rintl(long double x)
+{
+ union IEEEl2bits u;
+ u_int32_t expsign;
+ int ex, sign;
+
+ u.e = x;
+ expsign = u.xbits.expsign;
+ ex = expsign & 0x7fff;
+
+ if (ex >= BIAS + LDBL_MANT_DIG - 1) {
+ if (ex == BIAS + LDBL_MAX_EXP)
+ return (x + x); /* Inf, NaN, or unsupported format */
+ return (x); /* finite and already an integer */
+ }
+ sign = expsign >> 15;
+
+ /*
+ * The following code assumes that intermediate results are
+ * evaluated in long double precision. If they are evaluated in
+ * greater precision, double rounding may occur, and if they are
+ * evaluated in less precision (as on i386), results will be
+ * wildly incorrect.
+ */
+ x += shift[sign];
+ x -= shift[sign];
+
+ /*
+ * If the result is +-0, then it must have the same sign as x, but
+ * the above calculation doesn't always give this. Fix up the sign.
+ */
+ if (ex < BIAS && x == 0.0L)
+ return (zero[sign]);
+
+ return (x);
+}
+
+/*
+ * We save and restore the floating-point environment to avoid raising
+ * an inexact exception. We can get away with using fesetenv()
+ * instead of feclearexcept()/feupdateenv() to restore the environment
+ * because the only exception defined for rint() is overflow, and
+ * rounding can't overflow as long as emax >= p.
+ */
+#define DECL(type, fn, rint) \
+OLM_DLLEXPORT type \
+fn(type x) \
+{ \
+ type ret; \
+ fenv_t env; \
+ \
+ fegetenv(&env); \
+ ret = rint(x); \
+ fesetenv(&env); \
+ return (ret); \
+}
+DECL(long double, nearbyintl, rintl)
--- /dev/null
+/*-
+ * Copyright (c) 2003, Steven G. Kargl
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice unmodified, this list of conditions, and the following
+ * disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/src/s_round.c,v 1.4 2005/12/02 13:45:06 bde Exp $");
+
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+OLM_DLLEXPORT double
+round(double x)
+{
+ double t;
+ uint32_t hx;
+
+ GET_HIGH_WORD(hx, x);
+ if ((hx & 0x7fffffff) == 0x7ff00000)
+ return (x + x);
+
+ if (!(hx & 0x80000000)) {
+ t = floor(x);
+ if (t - x <= -0.5)
+ t += 1;
+ return (t);
+ } else {
+ t = floor(-x);
+ if (t + x <= -0.5)
+ t += 1;
+ return (-t);
+ }
+}
--- /dev/null
+/*-
+ * Copyright (c) 2003, Steven G. Kargl
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice unmodified, this list of conditions, and the following
+ * disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/src/s_roundf.c,v 1.4 2005/12/02 13:45:06 bde Exp $");
+
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+OLM_DLLEXPORT float
+roundf(float x)
+{
+ float t;
+
+ if (!isfinite(x))
+ return (x);
+
+ if (x >= 0.0) {
+ t = floorf(x);
+ if (t - x <= -0.5)
+ t += 1.0;
+ return (t);
+ } else {
+ t = floorf(-x);
+ if (t + x <= -0.5)
+ t += 1.0;
+ return (-t);
+ }
+}
--- /dev/null
+/*-
+ * Copyright (c) 2003, Steven G. Kargl
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice unmodified, this list of conditions, and the following
+ * disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/src/s_roundl.c,v 1.2 2005/12/02 13:45:06 bde Exp $");
+
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+OLM_DLLEXPORT long double
+roundl(long double x)
+{
+ long double t;
+
+ if (!isfinite(x))
+ return (x);
+
+ if (x >= 0.0) {
+ t = floorl(x);
+ if (t - x <= -0.5)
+ t += 1.0;
+ return (t);
+ } else {
+ t = floorl(-x);
+ if (t + x <= -0.5)
+ t += 1.0;
+ return (-t);
+ }
+}
--- /dev/null
+/*-
+ * Copyright (c) 2004 David Schultz <das@FreeBSD.ORG>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/src/s_scalbln.c,v 1.2 2005/03/07 04:57:50 das Exp $");
+
+#include <limits.h>
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+OLM_DLLEXPORT double
+scalbln (double x, long n)
+{
+ int in;
+
+ in = (int)n;
+ if (in != n) {
+ if (n > 0)
+ in = INT_MAX;
+ else
+ in = INT_MIN;
+ }
+ return (scalbn(x, in));
+}
+
+OLM_DLLEXPORT float
+scalblnf (float x, long n)
+{
+ int in;
+
+ in = (int)n;
+ if (in != n) {
+ if (n > 0)
+ in = INT_MAX;
+ else
+ in = INT_MIN;
+ }
+ return (scalbnf(x, in));
+}
+
+OLM_DLLEXPORT long double
+scalblnl (long double x, long n)
+{
+ int in;
+
+ in = (int)n;
+ if (in != n) {
+ if (n > 0)
+ in = INT_MAX;
+ else
+ in = INT_MIN;
+ }
+ return (scalbnl(x, (int)n));
+}
--- /dev/null
+/* @(#)s_scalbn.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/*
+ * scalbn (double x, int n)
+ * scalbn(x,n) returns x* 2**n computed by exponent
+ * manipulation rather than by actually performing an
+ * exponentiation or a multiplication.
+ */
+
+#include "cdefs-compat.h"
+
+#include <float.h>
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+static const double
+two54 = 1.80143985094819840000e+16, /* 0x43500000, 0x00000000 */
+twom54 = 5.55111512312578270212e-17, /* 0x3C900000, 0x00000000 */
+huge = 1.0e+300,
+tiny = 1.0e-300;
+
+OLM_DLLEXPORT double
+scalbn (double x, int n)
+{
+ int32_t k,hx,lx;
+ EXTRACT_WORDS(hx,lx,x);
+ k = (hx&0x7ff00000)>>20; /* extract exponent */
+ if (k==0) { /* 0 or subnormal x */
+ if ((lx|(hx&0x7fffffff))==0) return x; /* +-0 */
+ x *= two54;
+ GET_HIGH_WORD(hx,x);
+ k = ((hx&0x7ff00000)>>20) - 54;
+ if (n< -50000) return tiny*x; /*underflow*/
+ }
+ if (k==0x7ff) return x+x; /* NaN or Inf */
+ k = k+n;
+ if (k > 0x7fe) return huge*copysign(huge,x); /* overflow */
+ if (k > 0) /* normal result */
+ {SET_HIGH_WORD(x,(hx&0x800fffff)|(k<<20)); return x;}
+ if (k <= -54) {
+ if (n > 50000) /* in case integer overflow in n+k */
+ return huge*copysign(huge,x); /*overflow*/
+ else return tiny*copysign(tiny,x); /*underflow*/
+ }
+ k += 54; /* subnormal result */
+ SET_HIGH_WORD(x,(hx&0x800fffff)|(k<<20));
+ return x*twom54;
+}
+
+#if (LDBL_MANT_DIG == 53)
+__weak_reference(scalbn, ldexpl);
+__weak_reference(scalbn, scalbnl);
+#endif
+
+__strong_reference(scalbn, ldexp);
--- /dev/null
+/* s_scalbnf.c -- float version of s_scalbn.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+
+#include "cdefs-compat.h"
+
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+static const float
+two25 = 3.355443200e+07, /* 0x4c000000 */
+twom25 = 2.9802322388e-08, /* 0x33000000 */
+huge = 1.0e+30,
+tiny = 1.0e-30;
+
+OLM_DLLEXPORT float
+scalbnf (float x, int n)
+{
+ int32_t k,ix;
+ GET_FLOAT_WORD(ix,x);
+ k = (ix&0x7f800000)>>23; /* extract exponent */
+ if (k==0) { /* 0 or subnormal x */
+ if ((ix&0x7fffffff)==0) return x; /* +-0 */
+ x *= two25;
+ GET_FLOAT_WORD(ix,x);
+ k = ((ix&0x7f800000)>>23) - 25;
+ if (n< -50000) return tiny*x; /*underflow*/
+ }
+ if (k==0xff) return x+x; /* NaN or Inf */
+ k = k+n;
+ if (k > 0xfe) return huge*copysignf(huge,x); /* overflow */
+ if (k > 0) /* normal result */
+ {SET_FLOAT_WORD(x,(ix&0x807fffff)|(k<<23)); return x;}
+ if (k <= -25) {
+ if (n > 50000) /* in case integer overflow in n+k */
+ return huge*copysignf(huge,x); /*overflow*/
+ else return tiny*copysignf(tiny,x); /*underflow*/
+ }
+ k += 25; /* subnormal result */
+ SET_FLOAT_WORD(x,(ix&0x807fffff)|(k<<23));
+ return x*twom25;
+}
+
+__strong_reference(scalbnf, ldexpf);
--- /dev/null
+/* @(#)s_scalbn.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/*
+ * scalbnl (long double x, int n)
+ * scalbnl(x,n) returns x* 2**n computed by exponent
+ * manipulation rather than by actually performing an
+ * exponentiation or a multiplication.
+ */
+
+/*
+ * We assume that a long double has a 15-bit exponent. On systems
+ * where long double is the same as double, scalbnl() is an alias
+ * for scalbn(), so we don't use this routine.
+ */
+
+#include "cdefs-compat.h"
+
+#include <float.h>
+#include <openlibm_math.h>
+
+#include "fpmath.h"
+#include "math_private.h"
+
+#if LDBL_MAX_EXP != 0x4000
+#error "Unsupported long double format"
+#endif
+
+static const long double
+huge = 0x1p16000L,
+tiny = 0x1p-16000L;
+
+OLM_DLLEXPORT long double
+scalbnl (long double x, int n)
+{
+ union IEEEl2bits u;
+ int k;
+ u.e = x;
+ k = u.bits.exp; /* extract exponent */
+ if (k==0) { /* 0 or subnormal x */
+ if ((u.bits.manh|u.bits.manl)==0) return x; /* +-0 */
+ u.e *= 0x1p+128;
+ k = u.bits.exp - 128;
+ if (n< -50000) return tiny*x; /*underflow*/
+ }
+ if (k==0x7fff) return x+x; /* NaN or Inf */
+ k = k+n;
+ if (k >= 0x7fff) return huge*copysignl(huge,x); /* overflow */
+ if (k > 0) /* normal result */
+ {u.bits.exp = k; return u.e;}
+ if (k <= -128) {
+ if (n > 50000) /* in case integer overflow in n+k */
+ return huge*copysign(huge,x); /*overflow*/
+ else return tiny*copysign(tiny,x); /*underflow*/
+ }
+ k += 128; /* subnormal result */
+ u.bits.exp = k;
+ return u.e*0x1p-128;
+}
+
+__strong_reference(scalbnl, ldexpl);
--- /dev/null
+/*-
+ * Copyright (c) 2003 Mike Barcroft <mike@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: src/lib/msun/src/s_signbit.c,v 1.1 2004/07/19 08:16:10 das Exp $
+ */
+
+#include <openlibm_math.h>
+
+#include "fpmath.h"
+#include "math_private.h"
+
+OLM_DLLEXPORT int
+__signbit(double d)
+{
+ union IEEEd2bits u;
+
+ u.d = d;
+ return (u.bits.sign);
+}
+
+OLM_DLLEXPORT int
+__signbitf(float f)
+{
+ union IEEEf2bits u;
+
+ u.f = f;
+ return (u.bits.sign);
+}
+
+#ifdef LONG_DOUBLE
+OLM_DLLEXPORT int
+__signbitl(long double e)
+{
+ union IEEEl2bits u;
+
+ u.e = e;
+ return (u.bits.sign);
+}
+#endif
--- /dev/null
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+#ifndef OPENLIBM_ONLY_THREAD_SAFE
+int signgam = 0;
+#endif
--- /dev/null
+/* @(#)s_sin.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/src/s_sin.c,v 1.13 2011/02/10 07:37:50 das Exp $");
+
+/* sin(x)
+ * Return sine function of x.
+ *
+ * kernel function:
+ * __kernel_sin ... sine function on [-pi/4,pi/4]
+ * __kernel_cos ... cose function on [-pi/4,pi/4]
+ * __ieee754_rem_pio2 ... argument reduction routine
+ *
+ * Method.
+ * Let S,C and T denote the sin, cos and tan respectively on
+ * [-PI/4, +PI/4]. Reduce the argument x to y1+y2 = x-k*pi/2
+ * in [-pi/4 , +pi/4], and let n = k mod 4.
+ * We have
+ *
+ * n sin(x) cos(x) tan(x)
+ * ----------------------------------------------------------
+ * 0 S C T
+ * 1 C -S -1/T
+ * 2 -S -C T
+ * 3 -C S -1/T
+ * ----------------------------------------------------------
+ *
+ * Special cases:
+ * Let trig be any of sin, cos, or tan.
+ * trig(+-INF) is NaN, with signals;
+ * trig(NaN) is that NaN;
+ *
+ * Accuracy:
+ * TRIG(x) returns trig(x) nearly rounded
+ */
+
+#include <float.h>
+#include <openlibm_math.h>
+
+//#define INLINE_REM_PIO2
+#include "math_private.h"
+//#include "e_rem_pio2.c"
+
+OLM_DLLEXPORT double
+sin(double x)
+{
+ double y[2],z=0.0;
+ int32_t n, ix;
+
+ /* High word of x. */
+ GET_HIGH_WORD(ix,x);
+
+ /* |x| ~< pi/4 */
+ ix &= 0x7fffffff;
+ if(ix <= 0x3fe921fb) {
+ if(ix<0x3e500000) /* |x| < 2**-26 */
+ {if((int)x==0) return x;} /* generate inexact */
+ return __kernel_sin(x,z,0);
+ }
+
+ /* sin(Inf or NaN) is NaN */
+ else if (ix>=0x7ff00000) return x-x;
+
+ /* argument reduction needed */
+ else {
+ n = __ieee754_rem_pio2(x,y);
+ switch(n&3) {
+ case 0: return __kernel_sin(y[0],y[1],1);
+ case 1: return __kernel_cos(y[0],y[1]);
+ case 2: return -__kernel_sin(y[0],y[1],1);
+ default:
+ return -__kernel_cos(y[0],y[1]);
+ }
+ }
+}
+
+#if (LDBL_MANT_DIG == 53)
+__weak_reference(sin, sinl);
+#endif
--- /dev/null
+/* @(#)s_sincos.c 5.1 13/07/15 */
+/*
+ * ====================================================
+ * Copyright (C) 2013 Elliot Saba. All rights reserved.
+ *
+ * Developed at the University of Washington.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+ #include "cdefs-compat.h"
+
+/* sincos(x, s, c)
+ * Several applications need sine and cosine of the same
+ * angle x. This function computes both at the same time,
+ * and stores the results in *sin and *cos.
+ *
+ * kernel function:
+ * __kernel_sin ... sine function on [-pi/4,pi/4]
+ * __kernel_cos ... cose function on [-pi/4,pi/4]
+ * __ieee754_rem_pio2 ... argument reduction routine
+ *
+ * Method.
+ * Borrow liberally from s_sin.c and s_cos.c, merging
+ * efforts where applicable and returning their values in
+ * appropriate variables, thereby slightly reducing the
+ * amount of work relative to just calling sin/cos(x)
+ * separately
+ *
+ * Special cases:
+ * Let trig be any of sin, cos, or tan.
+ * sincos(+-INF, s, c) is NaN, with signals;
+ * sincos(NaN, s, c) is that NaN;
+ */
+
+#include <float.h>
+#include <openlibm_math.h>
+
+//#define INLINE_REM_PIO2
+#include "math_private.h"
+//#include "e_rem_pio2.c"
+
+/* Constants used in polynomial approximation of sin/cos */
+static const double
+one = 1.00000000000000000000e+00, /* 0x3FF00000, 0x00000000 */
+half = 5.00000000000000000000e-01, /* 0x3FE00000, 0x00000000 */
+S1 = -1.66666666666666324348e-01, /* 0xBFC55555, 0x55555549 */
+S2 = 8.33333333332248946124e-03, /* 0x3F811111, 0x1110F8A6 */
+S3 = -1.98412698298579493134e-04, /* 0xBF2A01A0, 0x19C161D5 */
+S4 = 2.75573137070700676789e-06, /* 0x3EC71DE3, 0x57B1FE7D */
+S5 = -2.50507602534068634195e-08, /* 0xBE5AE5E6, 0x8A2B9CEB */
+S6 = 1.58969099521155010221e-10, /* 0x3DE5D93A, 0x5ACFD57C */
+C1 = 4.16666666666666019037e-02, /* 0x3FA55555, 0x5555554C */
+C2 = -1.38888888888741095749e-03, /* 0xBF56C16C, 0x16C15177 */
+C3 = 2.48015872894767294178e-05, /* 0x3EFA01A0, 0x19CB1590 */
+C4 = -2.75573143513906633035e-07, /* 0xBE927E4F, 0x809C52AD */
+C5 = 2.08757232129817482790e-09, /* 0x3E21EE9E, 0xBDB4B1C4 */
+C6 = -1.13596475577881948265e-11; /* 0xBDA8FAE9, 0xBE8838D4 */
+
+static void
+__kernel_sincos( double x, double y, int iy, double * k_s, double * k_c )
+{
+ /* Inline calculation of sin/cos, as we can save
+ some work, and we will always need to calculate
+ both values, no matter the result of switch */
+ double z, w, r, v, hz;
+ z = x*x;
+ w = z*z;
+
+ /* cos-specific computation; equivalent to calling
+ __kernel_cos(x,y) and storing in k_c*/
+ r = z*(C1+z*(C2+z*C3)) + w*w*(C4+z*(C5+z*C6));
+ hz = 0.5*z;
+ v = one-hz;
+
+ *k_c = v + (((one-v)-hz) + (z*r-x*y));
+
+ /* sin-specific computation; equivalent to calling
+ __kernel_sin(x,y,1) and storing in k_s*/
+ r = S2+z*(S3+z*S4) + z*w*(S5+z*S6);
+ v = z*x;
+ if(iy == 0)
+ *k_s = x+v*(S1+z*r);
+ else
+ *k_s = x-((z*(half*y-v*r)-y)-v*S1);
+}
+
+OLM_DLLEXPORT void
+sincos(double x, double * s, double * c)
+{
+ double y[2];
+ int32_t ix;
+
+ /* Store high word of x in ix */
+ GET_HIGH_WORD(ix,x);
+
+ /* |x| ~< pi/4 */
+ ix &= 0x7fffffff;
+ if(ix <= 0x3fe921fb) {
+ /* Check for small x for sin and cos */
+ if(ix<0x3e46a09e) {
+ /* Check for exact zero */
+ if( (int)x==0 ) {
+ *s = x;
+ *c = 1.0;
+ return;
+ }
+ }
+ /* Call kernel function with 0 extra */
+ __kernel_sincos(x,0.0,0, s, c);
+ } else if( ix >= 0x7ff00000 ) {
+ /* sincos(Inf or NaN) is NaN */
+ *s = x-x;
+ *c = x-x;
+ }
+
+ /*argument reduction needed*/
+ else {
+ double k_c, k_s;
+
+ /* Calculate remainer, then sub out to kernel */
+ int32_t n = __ieee754_rem_pio2(x,y);
+ __kernel_sincos( y[0], y[1], 1, &k_s, &k_c );
+
+ /* Figure out permutation of sin/cos outputs to true outputs */
+ switch(n&3) {
+ case 0:
+ *c = k_c;
+ *s = k_s;
+ break;
+ case 1:
+ *c = -k_s;
+ *s = k_c;
+ break;
+ case 2:
+ *c = -k_c;
+ *s = -k_s;
+ break;
+ default:
+ *c = k_s;
+ *s = -k_c;
+ break;
+ }
+ }
+}
+
+#if (LDBL_MANT_DIG == 53)
+__weak_reference(sincos, sincosl);
+#endif
--- /dev/null
+/* s_sincosf.c -- float version of s_sincos.c
+ *
+ * Copyright (C) 2013 Elliot Saba
+ * Developed at the University of Washington
+ *
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+*/
+
+#include "cdefs-compat.h"
+
+#include <float.h>
+#include <openlibm_math.h>
+
+//#define INLINE_KERNEL_COSDF
+//#define INLINE_KERNEL_SINDF
+//#define INLINE_REM_PIO2F
+#include "math_private.h"
+//#include "e_rem_pio2f.c"
+//#include "k_cosf.c"
+//#include "k_sinf.c"
+
+
+/* Constants used in shortcircuits in sincosf */
+static const double
+sc1pio2 = 1*M_PI_2, /* 0x3FF921FB, 0x54442D18 */
+sc2pio2 = 2*M_PI_2, /* 0x400921FB, 0x54442D18 */
+sc3pio2 = 3*M_PI_2, /* 0x4012D97C, 0x7F3321D2 */
+sc4pio2 = 4*M_PI_2, /* 0x401921FB, 0x54442D18 */
+
+/* Constants used in polynomial approximation of sin/cos */
+one = 1.0,
+S1 = -0x15555554cbac77.0p-55, /* -0.166666666416265235595 */
+S2 = 0x111110896efbb2.0p-59, /* 0.0083333293858894631756 */
+S3 = -0x1a00f9e2cae774.0p-65, /* -0.000198393348360966317347 */
+S4 = 0x16cd878c3b46a7.0p-71, /* 0.0000027183114939898219064 */
+C0 = -0x1ffffffd0c5e81.0p-54, /* -0.499999997251031003120 */
+C1 = 0x155553e1053a42.0p-57, /* 0.0416666233237390631894 */
+C2 = -0x16c087e80f1e27.0p-62, /* -0.00138867637746099294692 */
+C3 = 0x199342e0ee5069.0p-68; /* 0.0000243904487962774090654 */
+
+static void
+__kernel_sincosdf( double x, float * s, float * c )
+{
+ double r, w, z, v;
+ z = x*x;
+ w = z*z;
+
+ /* cos-specific computation; equivalent to calling
+ __kernel_cos(x,y) and storing in k_c*/
+ r = C2+z*C3;
+ double k_c = ((one+z*C0) + w*C1) + (w*z)*r;
+
+ /* sin-specific computation; equivalent to calling
+ __kernel_sin(x,y,1) and storing in k_s*/
+ r = S3+z*S4;
+ v = z*x;
+ double k_s = (x + v*(S1+z*S2)) + v*w*r;
+
+ *c = k_c;
+ *s = k_s;
+}
+
+OLM_DLLEXPORT void
+sincosf(float x, float * s, float * c) {
+ // Worst approximation of sin and cos NA
+ *s = x;
+ *c = x;
+
+ double y;
+ float k_c, k_s;
+ int32_t n, hx, ix;
+
+ GET_FLOAT_WORD(hx,x);
+ ix = hx & 0x7fffffff;
+
+ if(ix <= 0x3f490fda) { /* |x| ~<= pi/4 */
+ if(ix<0x39800000) { /* |x| < 2**-12 */
+ /* Check if x is exactly zero */
+ if(((int)x)==0) {
+ *s = x;
+ *c = 1.0f;
+ return;
+ }
+ }
+ __kernel_sincosdf(x, s, c);
+ return;
+ }
+ /* |x| ~<= 5*pi/4 */
+ if (ix<=0x407b53d1) {
+ /* |x| ~<= 3pi/4 */
+ if(ix<=0x4016cbe3) {
+ if(hx>0) {
+ __kernel_sincosdf( sc1pio2 - x, c, s );
+ }
+ else {
+ __kernel_sincosdf( sc1pio2 + x, c, &k_s );
+ *s = -k_s;
+ }
+ } else {
+
+ if(hx>0) {
+ __kernel_sincosdf( sc2pio2 - x, s, &k_c );
+ *c = -k_c;
+ } else {
+ __kernel_sincosdf( -sc2pio2 - x, s, &k_c );
+ *c = -k_c;
+ }
+ }
+ return;
+ }
+
+ /* |x| ~<= 9*pi/4 */
+ if(ix<=0x40e231d5) {
+ /* |x| ~> 7*pi/4 */
+ if(ix<=0x40afeddf) {
+ if(hx>0) {
+ __kernel_sincosdf( x - sc3pio2, c, &k_s );
+ *s = -k_s;
+ } else {
+ __kernel_sincosdf( x + sc3pio2, &k_c, s );
+ *c = -k_c;
+ }
+ }
+ else {
+ if( hx > 0 ) {
+ __kernel_sincosdf( x - sc4pio2, s, c );
+ } else {
+ __kernel_sincosdf( x + sc4pio2, s, c );
+ }
+ }
+ return;
+ }
+
+ /* cos(Inf or NaN) is NaN */
+ else if(ix>=0x7f800000) {
+ *c = *s = x-x;
+ } else {
+ /* general argument reduction needed */
+ n = __ieee754_rem_pio2f(x,&y);
+
+ switch(n&3) {
+ case 0:
+ __kernel_sincosdf( y, s, c );
+ break;
+ case 1:
+ __kernel_sincosdf( -y, c, s );
+ break;
+ case 2:
+ __kernel_sincosdf( -y, s, &k_c);
+ *c = -k_c;
+ break;
+ default:
+ __kernel_sincosdf( -y, &k_c, &k_s );
+ *c = -k_c;
+ *s = -k_s;
+ break;
+ }
+ }
+
+}
--- /dev/null
+/* s_sincosl.c -- long double version of s_sincos.c
+ *
+ * Copyright (C) 2013 Elliot Saba
+ * Developed at the University of Washington
+ *
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+*/
+
+#include "cdefs-compat.h"
+
+#include <float.h>
+#include <openlibm_math.h>
+
+#include "math_private.h"
+#if LDBL_MANT_DIG == 64
+#include "../ld80/e_rem_pio2l.h"
+#elif LDBL_MANT_DIG == 113
+#include "../ld128/e_rem_pio2l.h"
+#else
+#error "Unsupported long double format"
+#endif
+
+OLM_DLLEXPORT void
+sincosl( long double x, long double * s, long double * c )
+{
+ *s = sinl( x );
+ *c = cosl( x );
+}
--- /dev/null
+/* s_sinf.c -- float version of s_sin.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ * Optimized by Bruce D. Evans.
+ */
+
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/src/s_sinf.c,v 1.17 2008/02/25 22:19:17 bde Exp $");
+
+#include <float.h>
+#include <openlibm_math.h>
+
+//#define INLINE_KERNEL_COSDF
+//#define INLINE_KERNEL_SINDF
+//#define INLINE_REM_PIO2F
+#include "math_private.h"
+//#include "e_rem_pio2f.c"
+//#include "k_cosf.c"
+//#include "k_sinf.c"
+
+/* Small multiples of pi/2 rounded to double precision. */
+static const double
+s1pio2 = 1*M_PI_2, /* 0x3FF921FB, 0x54442D18 */
+s2pio2 = 2*M_PI_2, /* 0x400921FB, 0x54442D18 */
+s3pio2 = 3*M_PI_2, /* 0x4012D97C, 0x7F3321D2 */
+s4pio2 = 4*M_PI_2; /* 0x401921FB, 0x54442D18 */
+
+OLM_DLLEXPORT float
+sinf(float x)
+{
+ double y;
+ int32_t n, hx, ix;
+
+ GET_FLOAT_WORD(hx,x);
+ ix = hx & 0x7fffffff;
+
+ if(ix <= 0x3f490fda) { /* |x| ~<= pi/4 */
+ if(ix<0x39800000) /* |x| < 2**-12 */
+ if(((int)x)==0) return x; /* x with inexact if x != 0 */
+ return __kernel_sindf(x);
+ }
+ if(ix<=0x407b53d1) { /* |x| ~<= 5*pi/4 */
+ if(ix<=0x4016cbe3) { /* |x| ~<= 3pi/4 */
+ if(hx>0)
+ return __kernel_cosdf(x - s1pio2);
+ else
+ return -__kernel_cosdf(x + s1pio2);
+ } else
+ return __kernel_sindf((hx > 0 ? s2pio2 : -s2pio2) - x);
+ }
+ if(ix<=0x40e231d5) { /* |x| ~<= 9*pi/4 */
+ if(ix<=0x40afeddf) { /* |x| ~<= 7*pi/4 */
+ if(hx>0)
+ return -__kernel_cosdf(x - s3pio2);
+ else
+ return __kernel_cosdf(x + s3pio2);
+ } else
+ return __kernel_sindf(x + (hx > 0 ? -s4pio2 : s4pio2));
+ }
+
+ /* sin(Inf or NaN) is NaN */
+ else if (ix>=0x7f800000) return x-x;
+
+ /* general argument reduction needed */
+ else {
+ n = __ieee754_rem_pio2f(x,&y);
+ switch(n&3) {
+ case 0: return __kernel_sindf(y);
+ case 1: return __kernel_cosdf(y);
+ case 2: return __kernel_sindf(-y);
+ default:
+ return -__kernel_cosdf(y);
+ }
+ }
+}
--- /dev/null
+/*-
+ * Copyright (c) 2007 Steven G. Kargl
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice unmodified, this list of conditions, and the following
+ * disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/src/s_sinl.c,v 1.3 2011/05/30 19:41:28 kargl Exp $");
+
+#include <float.h>
+#include <openlibm_math.h>
+
+#include "math_private.h"
+#if LDBL_MANT_DIG == 64
+#include "../ld80/e_rem_pio2l.h"
+#elif LDBL_MANT_DIG == 113
+#include "../ld128/e_rem_pio2l.h"
+#else
+#error "Unsupported long double format"
+#endif
+
+OLM_DLLEXPORT long double
+sinl(long double x)
+{
+ union IEEEl2bits z;
+ int e0, s;
+ long double y[2];
+ long double hi, lo;
+
+ z.e = x;
+ s = z.bits.sign;
+ z.bits.sign = 0;
+
+ /* If x = +-0 or x is a subnormal number, then sin(x) = x */
+ if (z.bits.exp == 0)
+ return (x);
+
+ /* If x = NaN or Inf, then sin(x) = NaN. */
+ if (z.bits.exp == 32767)
+ return ((x - x) / (x - x));
+
+ /* Optimize the case where x is already within range. */
+ if (z.e < M_PI_4) {
+ hi = __kernel_sinl(z.e, 0, 0);
+ return (s ? -hi : hi);
+ }
+
+ e0 = __ieee754_rem_pio2l(x, y);
+ hi = y[0];
+ lo = y[1];
+
+ switch (e0 & 3) {
+ case 0:
+ hi = __kernel_sinl(hi, lo, 1);
+ break;
+ case 1:
+ hi = __kernel_cosl(hi, lo);
+ break;
+ case 2:
+ hi = - __kernel_sinl(hi, lo, 1);
+ break;
+ case 3:
+ hi = - __kernel_cosl(hi, lo);
+ break;
+ }
+
+ return (hi);
+}
--- /dev/null
+/* @(#)s_tan.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/src/s_tan.c,v 1.13 2011/02/10 07:37:50 das Exp $");
+
+/* tan(x)
+ * Return tangent function of x.
+ *
+ * kernel function:
+ * __kernel_tan ... tangent function on [-pi/4,pi/4]
+ * __ieee754_rem_pio2 ... argument reduction routine
+ *
+ * Method.
+ * Let S,C and T denote the sin, cos and tan respectively on
+ * [-PI/4, +PI/4]. Reduce the argument x to y1+y2 = x-k*pi/2
+ * in [-pi/4 , +pi/4], and let n = k mod 4.
+ * We have
+ *
+ * n sin(x) cos(x) tan(x)
+ * ----------------------------------------------------------
+ * 0 S C T
+ * 1 C -S -1/T
+ * 2 -S -C T
+ * 3 -C S -1/T
+ * ----------------------------------------------------------
+ *
+ * Special cases:
+ * Let trig be any of sin, cos, or tan.
+ * trig(+-INF) is NaN, with signals;
+ * trig(NaN) is that NaN;
+ *
+ * Accuracy:
+ * TRIG(x) returns trig(x) nearly rounded
+ */
+
+#include <float.h>
+#include <openlibm_math.h>
+
+//#define INLINE_REM_PIO2
+#include "math_private.h"
+//#include "e_rem_pio2.c"
+
+OLM_DLLEXPORT double
+tan(double x)
+{
+ double y[2],z=0.0;
+ int32_t n, ix;
+
+ /* High word of x. */
+ GET_HIGH_WORD(ix,x);
+
+ /* |x| ~< pi/4 */
+ ix &= 0x7fffffff;
+ if(ix <= 0x3fe921fb) {
+ if(ix<0x3e400000) /* x < 2**-27 */
+ if((int)x==0) return x; /* generate inexact */
+ return __kernel_tan(x,z,1);
+ }
+
+ /* tan(Inf or NaN) is NaN */
+ else if (ix>=0x7ff00000) return x-x; /* NaN */
+
+ /* argument reduction needed */
+ else {
+ n = __ieee754_rem_pio2(x,y);
+ return __kernel_tan(y[0],y[1],1-((n&1)<<1)); /* 1 -- n even
+ -1 -- n odd */
+ }
+}
+
+#if (LDBL_MANT_DIG == 53)
+__weak_reference(tan, tanl);
+#endif
--- /dev/null
+/* s_tanf.c -- float version of s_tan.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ * Optimized by Bruce D. Evans.
+ */
+
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/src/s_tanf.c,v 1.17 2008/02/25 22:19:17 bde Exp $");
+
+#include <float.h>
+#include <openlibm_math.h>
+
+//#define INLINE_KERNEL_TANDF
+//#define INLINE_REM_PIO2F
+#include "math_private.h"
+//#include "e_rem_pio2f.c"
+//#include "k_tanf.c"
+
+/* Small multiples of pi/2 rounded to double precision. */
+static const double
+t1pio2 = 1*M_PI_2, /* 0x3FF921FB, 0x54442D18 */
+t2pio2 = 2*M_PI_2, /* 0x400921FB, 0x54442D18 */
+t3pio2 = 3*M_PI_2, /* 0x4012D97C, 0x7F3321D2 */
+t4pio2 = 4*M_PI_2; /* 0x401921FB, 0x54442D18 */
+
+OLM_DLLEXPORT float
+tanf(float x)
+{
+ double y;
+ int32_t n, hx, ix;
+
+ GET_FLOAT_WORD(hx,x);
+ ix = hx & 0x7fffffff;
+
+ if(ix <= 0x3f490fda) { /* |x| ~<= pi/4 */
+ if(ix<0x39800000) /* |x| < 2**-12 */
+ if(((int)x)==0) return x; /* x with inexact if x != 0 */
+ return __kernel_tandf(x,1);
+ }
+ if(ix<=0x407b53d1) { /* |x| ~<= 5*pi/4 */
+ if(ix<=0x4016cbe3) /* |x| ~<= 3pi/4 */
+ return __kernel_tandf(x + (hx>0 ? -t1pio2 : t1pio2), -1);
+ else
+ return __kernel_tandf(x + (hx>0 ? -t2pio2 : t2pio2), 1);
+ }
+ if(ix<=0x40e231d5) { /* |x| ~<= 9*pi/4 */
+ if(ix<=0x40afeddf) /* |x| ~<= 7*pi/4 */
+ return __kernel_tandf(x + (hx>0 ? -t3pio2 : t3pio2), -1);
+ else
+ return __kernel_tandf(x + (hx>0 ? -t4pio2 : t4pio2), 1);
+ }
+
+ /* tan(Inf or NaN) is NaN */
+ else if (ix>=0x7f800000) return x-x;
+
+ /* general argument reduction needed */
+ else {
+ n = __ieee754_rem_pio2f(x,&y);
+ /* integer parameter: 1 -- n even; -1 -- n odd */
+ return __kernel_tandf(y,1-((n&1)<<1));
+ }
+}
--- /dev/null
+/* @(#)s_tanh.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/src/s_tanh.c,v 1.9 2008/02/22 02:30:36 das Exp $");
+
+/* Tanh(x)
+ * Return the Hyperbolic Tangent of x
+ *
+ * Method :
+ * x -x
+ * e - e
+ * 0. tanh(x) is defined to be -----------
+ * x -x
+ * e + e
+ * 1. reduce x to non-negative by tanh(-x) = -tanh(x).
+ * 2. 0 <= x < 2**-28 : tanh(x) := x with inexact if x != 0
+ * -t
+ * 2**-28 <= x < 1 : tanh(x) := -----; t = expm1(-2x)
+ * t + 2
+ * 2
+ * 1 <= x < 22 : tanh(x) := 1 - -----; t = expm1(2x)
+ * t + 2
+ * 22 <= x <= INF : tanh(x) := 1.
+ *
+ * Special cases:
+ * tanh(NaN) is NaN;
+ * only tanh(0)=0 is exact for finite argument.
+ */
+
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+static const double one = 1.0, two = 2.0, tiny = 1.0e-300, huge = 1.0e300;
+
+OLM_DLLEXPORT double
+tanh(double x)
+{
+ double t,z;
+ int32_t jx,ix;
+
+ GET_HIGH_WORD(jx,x);
+ ix = jx&0x7fffffff;
+
+ /* x is INF or NaN */
+ if(ix>=0x7ff00000) {
+ if (jx>=0) return one/x+one; /* tanh(+-inf)=+-1 */
+ else return one/x-one; /* tanh(NaN) = NaN */
+ }
+
+ /* |x| < 22 */
+ if (ix < 0x40360000) { /* |x|<22 */
+ if (ix<0x3e300000) { /* |x|<2**-28 */
+ if(huge+x>one) return x; /* tanh(tiny) = tiny with inexact */
+ }
+ if (ix>=0x3ff00000) { /* |x|>=1 */
+ t = expm1(two*fabs(x));
+ z = one - two/(t+two);
+ } else {
+ t = expm1(-two*fabs(x));
+ z= -t/(t+two);
+ }
+ /* |x| >= 22, return +-1 */
+ } else {
+ z = one - tiny; /* raise inexact flag */
+ }
+ return (jx>=0)? z: -z;
+}
--- /dev/null
+/* s_tanhf.c -- float version of s_tanh.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/src/s_tanhf.c,v 1.9 2008/02/22 02:30:36 das Exp $");
+
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+static const float one=1.0, two=2.0, tiny = 1.0e-30, huge = 1.0e30;
+OLM_DLLEXPORT float
+tanhf(float x)
+{
+ float t,z;
+ int32_t jx,ix;
+
+ GET_FLOAT_WORD(jx,x);
+ ix = jx&0x7fffffff;
+
+ /* x is INF or NaN */
+ if(ix>=0x7f800000) {
+ if (jx>=0) return one/x+one; /* tanh(+-inf)=+-1 */
+ else return one/x-one; /* tanh(NaN) = NaN */
+ }
+
+ /* |x| < 9 */
+ if (ix < 0x41100000) { /* |x|<9 */
+ if (ix<0x39800000) { /* |x|<2**-12 */
+ if(huge+x>one) return x; /* tanh(tiny) = tiny with inexact */
+ }
+ if (ix>=0x3f800000) { /* |x|>=1 */
+ t = expm1f(two*fabsf(x));
+ z = one - two/(t+two);
+ } else {
+ t = expm1f(-two*fabsf(x));
+ z= -t/(t+two);
+ }
+ /* |x| >= 9, return +-1 */
+ } else {
+ z = one - tiny; /* raise inexact flag */
+ }
+ return (jx>=0)? z: -z;
+}
--- /dev/null
+/*-
+ * Copyright (c) 2007 Steven G. Kargl
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice unmodified, this list of conditions, and the following
+ * disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/src/s_tanl.c,v 1.3 2011/05/30 19:41:28 kargl Exp $");
+
+/*
+ * Limited testing on pseudorandom numbers drawn within [0:4e8] shows
+ * an accuracy of <= 1.5 ULP where 247024 values of x out of 40 million
+ * possibles resulted in tan(x) that exceeded 0.5 ULP (ie., 0.6%).
+ */
+
+#include <float.h>
+#include <openlibm_math.h>
+
+#include "math_private.h"
+#if LDBL_MANT_DIG == 64
+#include "../ld80/e_rem_pio2l.h"
+#elif LDBL_MANT_DIG == 113
+#include "../ld128/e_rem_pio2l.h"
+#else
+#error "Unsupported long double format"
+#endif
+
+OLM_DLLEXPORT long double
+tanl(long double x)
+{
+ union IEEEl2bits z;
+ int e0, s;
+ long double y[2];
+ long double hi, lo;
+
+ z.e = x;
+ s = z.bits.sign;
+ z.bits.sign = 0;
+
+ /* If x = +-0 or x is subnormal, then tan(x) = x. */
+ if (z.bits.exp == 0)
+ return (x);
+
+ /* If x = NaN or Inf, then tan(x) = NaN. */
+ if (z.bits.exp == 32767)
+ return ((x - x) / (x - x));
+
+ /* Optimize the case where x is already within range. */
+ if (z.e < M_PI_4) {
+ hi = __kernel_tanl(z.e, 0, 0);
+ return (s ? -hi : hi);
+ }
+
+ e0 = __ieee754_rem_pio2l(x, y);
+ hi = y[0];
+ lo = y[1];
+
+ switch (e0 & 3) {
+ case 0:
+ case 2:
+ hi = __kernel_tanl(hi, lo, 0);
+ break;
+ case 1:
+ case 3:
+ hi = __kernel_tanl(hi, lo, 1);
+ break;
+ }
+
+ return (hi);
+}
--- /dev/null
+/*-
+ * Copyright (c) 2008 David Schultz <das@FreeBSD.ORG>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/src/s_tgammaf.c,v 1.1 2008/02/18 17:27:10 das Exp $");
+
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+/*
+ * We simply call tgamma() rather than bloating the math library with
+ * a float-optimized version of it. The reason is that tgammaf() is
+ * essentially useless, since the function is superexponential and
+ * floats have very limited range.
+ */
+OLM_DLLEXPORT float
+tgammaf(float x)
+{
+
+ return (tgamma(x));
+}
--- /dev/null
+/* @(#)s_floor.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/src/s_trunc.c,v 1.4 2008/02/22 02:27:34 das Exp $");
+
+/*
+ * trunc(x)
+ * Return x rounded toward 0 to integral value
+ * Method:
+ * Bit twiddling.
+ * Exception:
+ * Inexact flag raised if x not equal to trunc(x).
+ */
+
+#include <float.h>
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+static const double huge = 1.0e300;
+
+OLM_DLLEXPORT double
+trunc(double x)
+{
+ int32_t i0,i1,j0;
+ u_int32_t i;
+ EXTRACT_WORDS(i0,i1,x);
+ j0 = ((i0>>20)&0x7ff)-0x3ff;
+ if(j0<20) {
+ if(j0<0) { /* raise inexact if x != 0 */
+ if(huge+x>0.0) {/* |x|<1, so return 0*sign(x) */
+ i0 &= 0x80000000U;
+ i1 = 0;
+ }
+ } else {
+ i = (0x000fffff)>>j0;
+ if(((i0&i)|i1)==0) return x; /* x is integral */
+ if(huge+x>0.0) { /* raise inexact flag */
+ i0 &= (~i); i1=0;
+ }
+ }
+ } else if (j0>51) {
+ if(j0==0x400) return x+x; /* inf or NaN */
+ else return x; /* x is integral */
+ } else {
+ i = ((u_int32_t)(0xffffffff))>>(j0-20);
+ if((i1&i)==0) return x; /* x is integral */
+ if(huge+x>0.0) /* raise inexact flag */
+ i1 &= (~i);
+ }
+ INSERT_WORDS(x,i0,i1);
+ return x;
+}
+
+#if LDBL_MANT_DIG == 53
+__weak_reference(trunc, truncl);
+#endif
--- /dev/null
+/* @(#)s_floor.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/src/s_truncf.c,v 1.1 2004/06/20 09:25:43 das Exp $");
+
+/*
+ * truncf(x)
+ * Return x rounded toward 0 to integral value
+ * Method:
+ * Bit twiddling.
+ * Exception:
+ * Inexact flag raised if x not equal to truncf(x).
+ */
+
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+static const float huge = 1.0e30F;
+
+OLM_DLLEXPORT float
+truncf(float x)
+{
+ int32_t i0,j0;
+ u_int32_t i;
+ GET_FLOAT_WORD(i0,x);
+ j0 = ((i0>>23)&0xff)-0x7f;
+ if(j0<23) {
+ if(j0<0) { /* raise inexact if x != 0 */
+ if(huge+x>0.0F) /* |x|<1, so return 0*sign(x) */
+ i0 &= 0x80000000;
+ } else {
+ i = (0x007fffff)>>j0;
+ if((i0&i)==0) return x; /* x is integral */
+ if(huge+x>0.0F) /* raise inexact flag */
+ i0 &= (~i);
+ }
+ } else {
+ if(j0==0x80) return x+x; /* inf or NaN */
+ else return x; /* x is integral */
+ }
+ SET_FLOAT_WORD(x,i0);
+ return x;
+}
--- /dev/null
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ *
+ * From: @(#)s_floor.c 5.1 93/09/24
+ */
+
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/src/s_truncl.c,v 1.9 2008/02/14 15:10:34 bde Exp $");
+
+/*
+ * truncl(x)
+ * Return x rounded toward 0 to integral value
+ * Method:
+ * Bit twiddling.
+ * Exception:
+ * Inexact flag raised if x not equal to truncl(x).
+ */
+
+#include <float.h>
+#include <openlibm_math.h>
+#include <stdint.h>
+
+#include "fpmath.h"
+#include "math_private.h"
+
+#ifdef LDBL_IMPLICIT_NBIT
+#define MANH_SIZE (LDBL_MANH_SIZE + 1)
+#else
+#define MANH_SIZE LDBL_MANH_SIZE
+#endif
+
+static const long double huge = 1.0e300;
+static const float zero[] = { 0.0, -0.0 };
+
+OLM_DLLEXPORT long double
+truncl(long double x)
+{
+ union IEEEl2bits u = { .e = x };
+ int e = u.bits.exp - LDBL_MAX_EXP + 1;
+
+ if (e < MANH_SIZE - 1) {
+ if (e < 0) { /* raise inexact if x != 0 */
+ if (huge + x > 0.0)
+ u.e = zero[u.bits.sign];
+ } else {
+ uint64_t m = ((1llu << MANH_SIZE) - 1) >> (e + 1);
+ if (((u.bits.manh & m) | u.bits.manl) == 0)
+ return (x); /* x is integral */
+ if (huge + x > 0.0) { /* raise inexact flag */
+ u.bits.manh &= ~m;
+ u.bits.manl = 0;
+ }
+ }
+ } else if (e < LDBL_MANT_DIG - 1) {
+ uint64_t m = (uint64_t)-1 >> (64 - LDBL_MANT_DIG + e + 1);
+ if ((u.bits.manl & m) == 0)
+ return (x); /* x is integral */
+ if (huge + x > 0.0) /* raise inexact flag */
+ u.bits.manl &= ~m;
+ }
+ return (u.e);
+}
--- /dev/null
+#ifndef _TYPES_COMPAT_H_
+#define _TYPES_COMPAT_H_
+
+#include <stdint.h>
+#include <limits.h>
+
+typedef uint8_t u_int8_t;
+typedef uint16_t u_int16_t;
+typedef uint32_t u_int32_t;
+typedef uint64_t u_int64_t;
+
+
+#endif
--- /dev/null
+/*
+ * cabs() wrapper for hypot().
+ *
+ * Written by J.T. Conklin, <jtc@wimsey.com>
+ * Placed into the Public Domain, 1994.
+ */
+
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/src/w_cabs.c,v 1.7 2008/03/30 20:03:06 das Exp $");
+
+#include <float.h>
+#include <openlibm_complex.h>
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+OLM_DLLEXPORT double
+cabs(double complex z)
+{
+ return hypot(creal(z), cimag(z));
+}
+
+#if LDBL_MANT_DIG == 53
+__weak_reference(cabs, cabsl);
+#endif
--- /dev/null
+/*
+ * cabsf() wrapper for hypotf().
+ *
+ * Written by J.T. Conklin, <jtc@wimsey.com>
+ * Placed into the Public Domain, 1994.
+ */
+
+#include <openlibm_complex.h>
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+OLM_DLLEXPORT float
+cabsf(z)
+ float complex z;
+{
+
+ return hypotf(crealf(z), cimagf(z));
+}
--- /dev/null
+/*
+ * cabs() wrapper for hypot().
+ *
+ * Written by J.T. Conklin, <jtc@wimsey.com>
+ * Placed into the Public Domain, 1994.
+ *
+ * Modified by Steven G. Kargl for the long double type.
+ */
+
+#include "cdefs-compat.h"
+//__FBSDID("$FreeBSD: src/lib/msun/src/w_cabsl.c,v 1.1 2008/03/30 20:02:03 das Exp $");
+
+#include <openlibm_complex.h>
+#include <openlibm_math.h>
+
+#include "math_private.h"
+
+OLM_DLLEXPORT long double
+cabsl(long double complex z)
+{
+ return hypotl(creall(z), cimagl(z));
+}
--- /dev/null
+/test-float
+/test-float-system
+/test-float.dSYM
+/test-double
+/test-double-system
+/test-double.dSYM
+/bench-openlibm
+/bench-syslibm
+/*.exe
--- /dev/null
+OPENLIBM_HOME=$(abspath ..)
+include ../Make.inc
+
+# Set rpath of tests to builddir for loading shared library
+OPENLIBM_LIB = -L.. -lopenlibm
+ifneq ($(OS),WINNT)
+ifneq ($(OS),Darwin)
+OPENLIBM_LIB += -Wl,-rpath=$(OPENLIBM_HOME)
+endif
+endif
+
+all: test-double test-float # test-double-system test-float-system
+
+bench: bench-syslibm bench-openlibm
+
+test-double: test-double.c libm-test.c libm-test-ulps.h
+ $(CC) $(CPPFLAGS) $(CFLAGS) $(CFLAGS_add) $(LDFLAGS) $(LDFLAGS_arch) $@.c -D__BSD_VISIBLE -I ../include -I../src $(OPENLIBM_LIB) -o $@
+
+test-float: test-float.c libm-test.c libm-test-ulps.h
+ $(CC) $(CPPFLAGS) $(CFLAGS) $(CFLAGS_add) $(LDFLAGS) $(LDFLAGS_arch) $@.c -D__BSD_VISIBLE -I ../include -I../src $(OPENLIBM_LIB) -o $@
+
+test-double-system: test-double.c libm-test.c libm-test-ulps.h
+ $(CC) $(CPPFLAGS) $(CFLAGS) $(CFLAGS_add) $(LDFLAGS) $(LDFLAGS_arch) $< -DSYS_MATH_H -lm -o $@
+
+test-float-system: test-float.c libm-test.c libm-test-ulps.h
+ $(CC) $(CPPFLAGS) $(CFLAGS) $(CFLAGS_add) $(LDFLAGS) $(LDFLAGS_arch) $< -DSYS_MATH_H -lm -o $@
+
+bench-openlibm: libm-bench.cpp
+ $(CC) $(CPPFLAGS) $(CFLAGS) $(CFLAGS_add) $(LDFLAGS) $(LDFLAGS_arch) $< $(OPENLIBM_LIB) -o $@
+
+bench-syslibm: libm-bench.cpp
+ $(CC) $(CPPFLAGS) $(CFLAGS) $(CFLAGS_add) $(LDFLAGS) $(LDFLAGS_arch) $< -lm -o $@
+
+clean:
+ rm -fr test-double test-float test-double-system test-float-system bench-openlibm bench-syslibm *.dSYM
--- /dev/null
+#include <stdio.h>
+#include <math.h>
+
+int main();
+int main2();
+int main3();
+int main4();
+
+int main() {
+ printf("+inf:\n");
+ float fx = (float)INFINITY; unsigned int *fxi = (unsigned int*)&fx;
+ double dx = (double)INFINITY; long unsigned long int *dxi = (long unsigned long int*)&dx;
+ long double ldx = (long double)INFINITY; long unsigned long int *ldxi1 = (long unsigned long int*)&ldx; long unsigned long int *ldxi2 = &(ldxi1[1]);
+ printf("\t\tf d ld\n");
+ printf("correct:\t%x %x %x\n", isinf(fx), isinf(dx), isinf(ldx));
+ printf("as floats:\t%x %x %x\n", isinf(*(float*)fxi), isinf(*(float*)dxi), isinf(*(float*)ldxi1));
+ printf("as double:\t%x %x %x\n", isinf(*(double*)fxi), isinf(*(double*)dxi), isinf(*(double*)ldxi1));
+ printf("as long double:\t%x %x %x\n", isinf(*(long double*)fxi), isinf(*(long double*)dxi), isinf(*(long double*)ldxi1));
+ printf("sizes ?4 8 12?:\t%d %d %d\n", (int)sizeof(fx), (int)sizeof(dx), (int)sizeof(ldx));
+ printf("sizes:\t%d %d %d\n", (int)sizeof(*fxi), (int)sizeof(*dxi), (int)sizeof(*ldxi1)*2);
+ printf("bit repr:\n f: %x\n d: %llx\n ld: %llx%llx\n", *fxi, *dxi, (0xFFFF)&*ldxi2, *ldxi1);
+ printf("\n");
+ main2();
+ return 0;
+}
+
+int main2() {
+ printf("-inf:\n");
+ float fx = (float)-INFINITY; unsigned int *fxi = (unsigned int*)&fx;
+ double dx = (double)-INFINITY; long unsigned long int *dxi = (long unsigned long int*)&dx;
+ long double ldx = (long double)-INFINITY; long unsigned long int *ldxi1 = (long unsigned long int*)&ldx; long unsigned long int *ldxi2 = &(ldxi1[1]);
+ printf("\t\tf d ld\n");
+ printf("correct:\t%x %x %x\n", isinf(fx), isinf(dx), isinf(ldx));
+ printf("as floats:\t%x %x %x\n", isinf(*(float*)fxi), isinf(*(float*)dxi), isinf(*(float*)ldxi1));
+ printf("as double:\t%x %x %x\n", isinf(*(double*)fxi), isinf(*(double*)dxi), isinf(*(double*)ldxi1));
+ printf("as long double:\t%x %x %x\n", isinf(*(long double*)fxi), isinf(*(long double*)dxi), isinf(*(long double*)ldxi1));
+ printf("sizes ?4 8 12?:\t%d %d %d\n", (int)sizeof(fx), (int)sizeof(dx), (int)sizeof(ldx));
+ printf("bit repr:\n f: %x\n d: %llx\n ld: %llx%llx\n", *fxi, *dxi, (0xFFFF)&*ldxi2, *ldxi1);
+ printf("\n");
+ main3();
+ return 0;
+}
+
+int main3() {
+ printf("+NaN:\n");
+ float fx = (float)NAN; unsigned int *fxi = (unsigned int*)&fx;
+ double dx = (double)NAN; long unsigned long int *dxi = (long unsigned long int*)&dx;
+ long double ldx = (long double)NAN; long unsigned long int *ldxi1 = (long unsigned long int*)&ldx; long unsigned long int *ldxi2 = &(ldxi1[1]);
+ printf("\t\tf d ld\n");
+ printf("correct:\t%x %x %x\n", isnan(fx), isnan(dx), isnan(ldx));
+ printf("as floats:\t%x %x %x\n", isnan(*(float*)fxi), isnan(*(float*)dxi), isnan(*(float*)ldxi1));
+ printf("as double:\t%x %x %x\n", isnan(*(double*)fxi), isnan(*(double*)dxi), isnan(*(double*)ldxi1));
+ printf("as long double:\t%x %x %x\n", isnan(*(long double*)fxi), isnan(*(long double*)dxi), isnan(*(long double*)ldxi1));
+ printf("sizes ?4 8 12?:\t%d %d %d\n", (int)sizeof(fx), (int)sizeof(dx), (int)sizeof(ldx));
+ printf("sizes:\t%d %d %d\n", (int)sizeof(*fxi), (int)sizeof(*dxi), (int)sizeof(*ldxi1)*2);
+ printf("bit repr:\n f: %x\n d: %llx\n ld: %llx%llx\n", *fxi, *dxi, (0xFFFF)&*ldxi2, *ldxi1);
+ printf("\n");
+ main4();
+ return 0;
+}
+
+int main4() {
+ printf("-NaN:\n");
+ float fx = (float)-NAN; unsigned int *fxi = (unsigned int*)&fx;
+ double dx = (double)-NAN; long unsigned long int *dxi = (long unsigned long int*)&dx;
+ long double ldx = (long double)-NAN; long unsigned long int *ldxi1 = (long unsigned long int*)&ldx; long unsigned long int *ldxi2 = &(ldxi1[1]);
+ printf("\t\tf d ld\n");
+ printf("correct:\t%x %x %x\n", isnan(fx), isnan(dx), isnan(ldx));
+ printf("as floats:\t%x %x %x\n", isnan(*(float*)fxi), isnan(*(float*)dxi), isnan(*(float*)ldxi1));
+ printf("as double:\t%x %x %x\n", isnan(*(double*)fxi), isnan(*(double*)dxi), isnan(*(double*)ldxi1));
+ printf("as long double:\t%x %x %x\n", isnan(*(long double*)fxi), isnan(*(long double*)dxi), isnan(*(long double*)ldxi1));
+ printf("sizes ?4 8 12?:\t%d %d %d\n", (int)sizeof(fx), (int)sizeof(dx), (int)sizeof(ldx));
+ printf("bit repr:\n f: %x\n d: %llx\n ld: %llx%llx\n", *fxi, *dxi, (0xFFFF)&*ldxi2, *ldxi1);
+ printf("\n");
+ return 0;
+}
--- /dev/null
+// Copyright (C) Dahua Lin, 2014. Provided under the MIT license.
+
+// Benchmark on libm functions
+
+#include <math.h>
+#include <time.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+
+// Timing facilities
+
+#ifdef __MACH__
+
+#include <mach/mach_time.h>
+
+class stimer
+{
+public:
+ typedef uint64_t time_type;
+
+ stimer()
+ {
+ ::mach_timebase_info(&m_baseinfo);
+ }
+
+ time_type current() const
+ {
+ return ::mach_absolute_time();
+ }
+
+ double span(const time_type& t0, const time_type& t1) const
+ {
+ uint64_t d = (m_baseinfo.numer * (t1 - t0)) / m_baseinfo.denom;
+ return static_cast<double>(d) / 1.0e9;
+ }
+
+private:
+ mach_timebase_info_data_t m_baseinfo;
+};
+
+#else
+
+class stimer
+{
+public:
+ typedef timespec time_type;
+
+ time_type current() const
+ {
+ time_type t;
+ ::clock_gettime(CLOCK_REALTIME, &t);
+ return t;
+ }
+
+ double span(const time_type& t0, const time_type& t1) const
+ {
+ return double(t1.tv_sec - t0.tv_sec) +
+ double(t1.tv_nsec - t0.tv_nsec) * 1.0e-9;
+ }
+};
+
+#endif
+
+
+inline double sec2mps(double s, long n)
+{
+ return n / (s * 1e6);
+}
+
+
+const long ARR_LEN = 1024;
+
+double a[ARR_LEN];
+double b[ARR_LEN];
+double r[ARR_LEN];
+
+#define TFUN1(FNAME) \
+ void test_##FNAME(long n) { \
+ for (int j = 0; j < ARR_LEN; ++j) r[j] = FNAME(a[j]); \
+ stimer tm; \
+ stimer::time_type t0 = tm.current(); \
+ for(int i = 0; i < n; ++i) { \
+ for (int j = 0; j < ARR_LEN; ++j) r[j] = FNAME(a[j]); \
+ } \
+ double s = tm.span(t0, tm.current()); \
+ double mps = sec2mps(s, n * ARR_LEN); \
+ printf(" %-8s: %7.4f MPS\n", #FNAME, mps); }
+
+#define TFUN2(FNAME) \
+ void test_##FNAME(long n) { \
+ for (int j = 0; j < ARR_LEN; ++j) r[j] = FNAME(a[j], b[j]); \
+ stimer tm; \
+ stimer::time_type t0 = tm.current(); \
+ for(int i = 0; i < n; ++i) { \
+ for (int j = 0; j < ARR_LEN; ++j) r[j] = FNAME(a[j], b[j]); \
+ } \
+ double s = tm.span(t0, tm.current()); \
+ double mps = sec2mps(s, n * ARR_LEN); \
+ printf(" %-8s: %7.4f MPS\n", #FNAME, mps); }
+
+
+#define TCALL(FNAME) test_##FNAME(20000)
+
+// define benchmark functions
+
+TFUN2(pow)
+TFUN2(hypot)
+
+TFUN1(exp)
+TFUN1(log)
+TFUN1(log10)
+TFUN1(sin)
+TFUN1(cos)
+TFUN1(tan)
+TFUN1(asin)
+TFUN1(acos)
+TFUN1(atan)
+TFUN2(atan2)
+
+int main(int argc, char *argv[])
+{
+ // initialize array contents
+ for (int i = 0; i < ARR_LEN; ++i)
+ {
+ a[i] = rand() / (double) RAND_MAX;
+ b[i] = rand() / (double) RAND_MAX;
+ }
+
+ TCALL(pow);
+ TCALL(hypot);
+ TCALL(exp);
+ TCALL(log);
+ TCALL(log10);
+ TCALL(sin);
+ TCALL(cos);
+ TCALL(tan);
+ TCALL(asin);
+ TCALL(acos);
+ TCALL(atan);
+ TCALL(atan2);
+
+ return 0;
+}
--- /dev/null
+/* This file is automatically generated
+ from libm-test-ulps with gen-libm-test.pl.
+ Don't change it - change instead the master files. */
+
+
+/* Maximal error of functions. */
+#define DELTAacos CHOOSE(1150, 1, 1, 1150, 0, 0) /* acos */
+#define DELTAacosh CHOOSE(1, 0, 0, 1, 0, 0) /* acosh */
+#define DELTAasin CHOOSE(1, 1, 0, 1, 0, 0) /* asin */
+#define DELTAasinh CHOOSE(656, 0, 0, 656, 0, 0) /* asinh */
+#define DELTAatan CHOOSE(549, 0, 0, 549, 0, 0) /* atan */
+#define DELTAatanh CHOOSE(1605, 1, 0, 1605, 1, 0) /* atanh */
+#define DELTAatan2 CHOOSE(549, 0, 0, 549, 0, 0) /* atan2 */
+#define DELTAcabs CHOOSE(560, 1, 1, 560, 1, 1) /* cabs */
+#define DELTAcacos CHOOSE(BUILD_COMPLEX (151, 329), BUILD_COMPLEX (1, 0), BUILD_COMPLEX (1, 2), BUILD_COMPLEX (151, 329), BUILD_COMPLEX (1, 0), BUILD_COMPLEX (1, 2)) /* cacos */
+#define DELTAcacosh CHOOSE(BUILD_COMPLEX (328, 151), BUILD_COMPLEX (1, 1), BUILD_COMPLEX (4, 4), BUILD_COMPLEX (328, 151), BUILD_COMPLEX (1, 1), BUILD_COMPLEX (4, 4)) /* cacosh */
+#define DELTAcasin CHOOSE(BUILD_COMPLEX (603, 329), BUILD_COMPLEX (3, 0), BUILD_COMPLEX (2, 2), BUILD_COMPLEX (603, 329), BUILD_COMPLEX (3, 0), BUILD_COMPLEX (2, 2)) /* casin */
+#define DELTAcasinh CHOOSE(BUILD_COMPLEX (892, 12), BUILD_COMPLEX (5, 3), BUILD_COMPLEX (1, 6), BUILD_COMPLEX (892, 12), BUILD_COMPLEX (5, 3), BUILD_COMPLEX (1, 6)) /* casinh */
+#define DELTAcatan CHOOSE(BUILD_COMPLEX (251, 474), BUILD_COMPLEX (0, 1), BUILD_COMPLEX (0, 1), BUILD_COMPLEX (251, 474), BUILD_COMPLEX (0, 1), BUILD_COMPLEX (0, 1)) /* catan */
+#define DELTAcatanh CHOOSE(BUILD_COMPLEX (66, 447), BUILD_COMPLEX (2, 0), BUILD_COMPLEX (1, 0), BUILD_COMPLEX (66, 447), BUILD_COMPLEX (2, 0), BUILD_COMPLEX (1, 0)) /* catanh */
+#define DELTAcbrt CHOOSE(716, 1, 0, 716, 1, 0) /* cbrt */
+#define DELTAccos CHOOSE(BUILD_COMPLEX (5, 1901), BUILD_COMPLEX (1, 1), BUILD_COMPLEX (1, 1), BUILD_COMPLEX (5, 1901), BUILD_COMPLEX (1, 1), BUILD_COMPLEX (1, 1)) /* ccos */
+#define DELTAccosh CHOOSE(BUILD_COMPLEX (1467, 1183), BUILD_COMPLEX (1, 1), BUILD_COMPLEX (1, 1), BUILD_COMPLEX (1467, 1183), BUILD_COMPLEX (1, 1), BUILD_COMPLEX (1, 1)) /* ccosh */
+#define DELTAcexp CHOOSE(BUILD_COMPLEX (940, 1067), 0, BUILD_COMPLEX (1, 0), BUILD_COMPLEX (940, 1067), 0, BUILD_COMPLEX (1, 0)) /* cexp */
+#define DELTAclog CHOOSE(BUILD_COMPLEX (0, 1), 0, 0, BUILD_COMPLEX (0, 1), 0, 0) /* clog */
+#define DELTAclog10 CHOOSE(BUILD_COMPLEX (1403, 186), BUILD_COMPLEX (2, 1), BUILD_COMPLEX (1, 1), BUILD_COMPLEX (1403, 186), BUILD_COMPLEX (2, 1), BUILD_COMPLEX (1, 1)) /* clog10 */
+#define DELTAcos CHOOSE(529, 2, 1, 529, 2, 1) /* cos */
+#define DELTAcosh CHOOSE(309, 0, 0, 309, 0, 0) /* cosh */
+#define DELTAcpow CHOOSE(BUILD_COMPLEX (2, 9), BUILD_COMPLEX (1, 1.104), BUILD_COMPLEX (4, 2.5333), BUILD_COMPLEX (2, 9), BUILD_COMPLEX (1, 1.104), BUILD_COMPLEX (4, 2.5333)) /* cpow */
+#define DELTAcsin CHOOSE(BUILD_COMPLEX (966, 168), 0, 0, BUILD_COMPLEX (966, 168), 0, 0) /* csin */
+#define DELTAcsinh CHOOSE(BUILD_COMPLEX (413, 477), BUILD_COMPLEX (1, 1), BUILD_COMPLEX (1, 1), BUILD_COMPLEX (413, 477), BUILD_COMPLEX (1, 1), BUILD_COMPLEX (1, 1)) /* csinh */
+#define DELTAcsqrt CHOOSE(BUILD_COMPLEX (237, 128), BUILD_COMPLEX (1, 0), 0, BUILD_COMPLEX (237, 128), BUILD_COMPLEX (1, 0), 0) /* csqrt */
+#define DELTActan CHOOSE(BUILD_COMPLEX (690, 367), BUILD_COMPLEX (1, 1), BUILD_COMPLEX (1, 1), BUILD_COMPLEX (690, 367), BUILD_COMPLEX (1, 1), BUILD_COMPLEX (1, 1)) /* ctan */
+#define DELTActanh CHOOSE(BUILD_COMPLEX (286, 3074), BUILD_COMPLEX (0, 1), BUILD_COMPLEX (1, 1), BUILD_COMPLEX (286, 3074), BUILD_COMPLEX (0, 1), BUILD_COMPLEX (1, 1)) /* ctanh */
+#define DELTAerfc CHOOSE(36, 24, 12, 36, 24, 12) /* erfc */
+#define DELTAexp CHOOSE(754, 0, 0, 754, 0, 0) /* exp */
+#define DELTAexp10 CHOOSE(1182, 1, 0, 1182, 1, 0) /* exp10 */
+#define DELTAexp2 CHOOSE(462, 0, 0, 462, 0, 0) /* exp2 */
+#define DELTAexpm1 CHOOSE(825, 1, 1, 825, 0, 0) /* expm1 */
+#define DELTAfmod CHOOSE(4096, 2, 1, 4096, 2, 1) /* fmod */
+#define DELTAgamma CHOOSE(1, 1, 0, 1, 1, 0) /* gamma */
+#define DELTAhypot CHOOSE(560, 1, 1, 560, 0, 0) /* hypot */
+#define DELTAj0 CHOOSE(0, 2, 2, 0, 2, 1) /* j0 */
+#define DELTAj1 CHOOSE(2, 2, 2, 2, 2, 1) /* j1 */
+#define DELTAjn CHOOSE(2, 6, 4, 2, 5, 2) /* jn */
+#define DELTAlgamma CHOOSE(1, 1, 2, 1, 1, 2) /* lgamma */
+#define DELTAlog CHOOSE(2341, 1, 1, 2341, 1, 1) /* log */
+#define DELTAlog10 CHOOSE(2033, 1, 1, 2033, 1, 1) /* log10 */
+#define DELTAlog1p CHOOSE(585, 1, 1, 585, 1, 1) /* log1p */
+#define DELTAlog2 CHOOSE(1688, 1, 1, 1688, 1, 1) /* log2 */
+#define DELTApow CHOOSE(725, 0, 0, 725, 0, 0) /* pow */
+#define DELTAsin CHOOSE(627, 0, 0, 627, 0, 0) /* sin */
+#define DELTAsincos CHOOSE(627, 1, 1, 627, 1, 1) /* sincos */
+#define DELTAsinh CHOOSE(1029, 1, 1, 1028, 0, 1) /* sinh */
+#define DELTAsqrt CHOOSE(489, 0, 0, 489, 0, 0) /* sqrt */
+#define DELTAtan CHOOSE(1401, 1, 1, 1401, 0.5, 0) /* tan */
+#define DELTAtanh CHOOSE(521, 1, 1, 521, 0, 0) /* tanh */
+#define DELTAtgamma CHOOSE(2, 2, 1, 2, 2, 1) /* tgamma */
+#define DELTAy0 CHOOSE(2, 3, 1, 2, 3, 1) /* y0 */
+#define DELTAy1 CHOOSE(2, 3, 2, 2, 3, 2) /* y1 */
+#define DELTAyn CHOOSE(7, 6, 3, 7, 6, 3) /* yn */
+
+/* Error of single function calls. */
+#define DELTA16 CHOOSE(1, 0, 0, 1, 0, 0) /* acosh (7) == 2.633915793849633417250092694615937 */
+#define DELTA24 CHOOSE(1, 1, 0, 1, 0, 0) /* asin (0.5) == pi/6 */
+#define DELTA25 CHOOSE(1, 1, 0, 1, 0, 0) /* asin (-0.5) == -pi/6 */
+#define DELTA26 CHOOSE(1, 0, 0, 1, 0, 0) /* asin (1.0) == pi/2 */
+#define DELTA27 CHOOSE(1, 0, 0, 1, 0, 0) /* asin (-1.0) == -pi/2 */
+#define DELTA28 CHOOSE(1, 1, 0, 1, 0, 0) /* asin (0.7) == 0.77539749661075306374035335271498708 */
+#define DELTA34 CHOOSE(656, 1, 0, 656, 0, 0) /* asinh (0.7) == 0.652666566082355786 */
+#define DELTA42 CHOOSE(549, 0, 0, 549, 0, 0) /* atan (0.7) == 0.61072596438920861654375887649023613 */
+#define DELTA50 CHOOSE(1605, 1, 0, 1605, 1, 0) /* atanh (0.7) == 0.8673005276940531944 */
+#define DELTA74 CHOOSE(549, 0, 0, 549, 0, 0) /* atan2 (0.7, 1) == 0.61072596438920861654375887649023613 */
+#define DELTA78 CHOOSE(1, 0, 0, 1, 0, 0) /* atan2 (0.4, 0.0003) == 1.5700463269355215717704032607580829 */
+#define DELTA85 CHOOSE(0, 0, 1, 0, 0, 1) /* cabs (0.7 + 12.4 i) == 12.419742348374220601176836866763271 */
+#define DELTA86 CHOOSE(0, 0, 1, 0, 0, 1) /* cabs (-12.4 + 0.7 i) == 12.419742348374220601176836866763271 */
+#define DELTA87 CHOOSE(0, 0, 1, 0, 0, 1) /* cabs (-0.7 + 12.4 i) == 12.419742348374220601176836866763271 */
+#define DELTA88 CHOOSE(0, 0, 1, 0, 0, 1) /* cabs (-12.4 - 0.7 i) == 12.419742348374220601176836866763271 */
+#define DELTA89 CHOOSE(0, 0, 1, 0, 0, 1) /* cabs (-0.7 - 12.4 i) == 12.419742348374220601176836866763271 */
+#define DELTA96 CHOOSE(560, 1, 0, 560, 1, 0) /* cabs (0.7 + 1.2 i) == 1.3892443989449804508432547041028554 */
+#define DELTA130 CHOOSE(BUILD_COMPLEX (151, 329), BUILD_COMPLEX (1, 0), BUILD_COMPLEX (1, 2), BUILD_COMPLEX (151, 329), BUILD_COMPLEX (1, 0), BUILD_COMPLEX (1, 2)) /* cacos (0.7 + 1.2 i) == 1.1351827477151551088992008271819053 - 1.0927647857577371459105272080819308 i */
+#define DELTA131 CHOOSE(BUILD_COMPLEX (0, 1), 0, 0, BUILD_COMPLEX (0, 1), 0, 0) /* cacos (-2 - 3 i) == 2.1414491111159960199416055713254211 + 1.9833870299165354323470769028940395 i */
+#define DELTA165 CHOOSE(BUILD_COMPLEX (328, 151), BUILD_COMPLEX (1, 0), 0, BUILD_COMPLEX (328, 151), BUILD_COMPLEX (1, 0), 0) /* cacosh (0.7 + 1.2 i) == 1.0927647857577371459105272080819308 + 1.1351827477151551088992008271819053 i */
+#define DELTA166 CHOOSE(BUILD_COMPLEX (6, 1), BUILD_COMPLEX (1, 1), BUILD_COMPLEX (4, 4), BUILD_COMPLEX (6, 1), BUILD_COMPLEX (1, 1), BUILD_COMPLEX (4, 4)) /* cacosh (-2 - 3 i) == -1.9833870299165354323470769028940395 + 2.1414491111159960199416055713254211 i */
+#define DELTA225 CHOOSE(BUILD_COMPLEX (603, 329), BUILD_COMPLEX (3, 0), BUILD_COMPLEX (2, 2), BUILD_COMPLEX (603, 329), BUILD_COMPLEX (3, 0), BUILD_COMPLEX (2, 2)) /* casin (0.7 + 1.2 i) == 0.4356135790797415103321208644578462 + 1.0927647857577371459105272080819308 i */
+#define DELTA226 CHOOSE(BUILD_COMPLEX (0, 1), 0, 0, BUILD_COMPLEX (0, 1), 0, 0) /* casin (-2 - 3 i) == -0.57065278432109940071028387968566963 - 1.9833870299165354323470769028940395 i */
+#define DELTA262 CHOOSE(BUILD_COMPLEX (892, 12), 0, BUILD_COMPLEX (0, 1), BUILD_COMPLEX (892, 12), 0, BUILD_COMPLEX (0, 1)) /* casinh (0.7 + 1.2 i) == 0.97865459559367387689317593222160964 + 0.91135418953156011567903546856170941 i */
+#define DELTA263 CHOOSE(BUILD_COMPLEX (6, 6), BUILD_COMPLEX (5, 3), BUILD_COMPLEX (1, 6), BUILD_COMPLEX (6, 6), BUILD_COMPLEX (5, 3), BUILD_COMPLEX (1, 6)) /* casinh (-2 - 3 i) == -1.9686379257930962917886650952454982 - 0.96465850440760279204541105949953237 i */
+#define DELTA301 CHOOSE(BUILD_COMPLEX (251, 474), 0, BUILD_COMPLEX (0, 1), BUILD_COMPLEX (251, 474), 0, BUILD_COMPLEX (0, 1)) /* catan (0.7 + 1.2 i) == 1.0785743834118921877443707996386368 + 0.57705737765343067644394541889341712 i */
+#define DELTA302 CHOOSE(BUILD_COMPLEX (0, 7), BUILD_COMPLEX (0, 1), BUILD_COMPLEX (0, 1), BUILD_COMPLEX (0, 7), BUILD_COMPLEX (0, 1), BUILD_COMPLEX (0, 1)) /* catan (-2 - 3 i) == -1.4099210495965755225306193844604208 - 0.22907268296853876629588180294200276 i */
+#define DELTA340 CHOOSE(BUILD_COMPLEX (66, 447), BUILD_COMPLEX (1, 0), 0, BUILD_COMPLEX (66, 447), BUILD_COMPLEX (1, 0), 0) /* catanh (0.7 + 1.2 i) == 0.2600749516525135959200648705635915 + 0.97024030779509898497385130162655963 i */
+#define DELTA341 CHOOSE(BUILD_COMPLEX (6, 0), BUILD_COMPLEX (2, 0), BUILD_COMPLEX (1, 0), BUILD_COMPLEX (6, 0), BUILD_COMPLEX (2, 0), BUILD_COMPLEX (1, 0)) /* catanh (-2 - 3 i) == -0.14694666622552975204743278515471595 - 1.3389725222944935611241935759091443 i */
+#define DELTA347 CHOOSE(716, 0, 0, 716, 0, 0) /* cbrt (-0.001) == -0.1 */
+#define DELTA349 CHOOSE(1, 0, 0, 1, 0, 0) /* cbrt (-27.0) == -3.0 */
+#define DELTA350 CHOOSE(306, 0, 0, 306, 0, 0) /* cbrt (0.970299) == 0.99 */
+#define DELTA351 CHOOSE(346, 1, 0, 346, 1, 0) /* cbrt (0.7) == 0.8879040017426007084 */
+#define DELTA389 CHOOSE(BUILD_COMPLEX (5, 1901), BUILD_COMPLEX (1, 1), BUILD_COMPLEX (1, 0), BUILD_COMPLEX (5, 1901), BUILD_COMPLEX (1, 1), BUILD_COMPLEX (1, 0)) /* ccos (0.7 + 1.2 i) == 1.3848657645312111080 - 0.97242170335830028619 i */
+#define DELTA390 CHOOSE(BUILD_COMPLEX (0, 1), 0, BUILD_COMPLEX (0, 1), BUILD_COMPLEX (0, 1), 0, BUILD_COMPLEX (0, 1)) /* ccos (-2 - 3 i) == -4.1896256909688072301 - 9.1092278937553365979 i */
+#define DELTA428 CHOOSE(BUILD_COMPLEX (1467, 1183), BUILD_COMPLEX (1, 0), BUILD_COMPLEX (1, 0), BUILD_COMPLEX (1467, 1183), BUILD_COMPLEX (1, 0), BUILD_COMPLEX (1, 0)) /* ccosh (0.7 + 1.2 i) == 0.4548202223691477654 + 0.7070296600921537682 i */
+#define DELTA429 CHOOSE(BUILD_COMPLEX (0, 1), BUILD_COMPLEX (0, 1), BUILD_COMPLEX (0, 1), BUILD_COMPLEX (0, 1), BUILD_COMPLEX (0, 1), BUILD_COMPLEX (0, 1)) /* ccosh (-2 - 3 i) == -3.7245455049153225654 + 0.5118225699873846088 i */
+#define DELTA469 CHOOSE(BUILD_COMPLEX (940, 0), 0, BUILD_COMPLEX (1, 0), BUILD_COMPLEX (940, 0), 0, BUILD_COMPLEX (1, 0)) /* cexp (0.7 + 1.2 i) == 0.72969890915032360123451688642930727 + 1.8768962328348102821139467908203072 i */
+#define DELTA470 CHOOSE(BUILD_COMPLEX (4, 18), 0, 0, BUILD_COMPLEX (4, 18), 0, 0) /* cexp (-2.0 - 3.0 i) == -0.13398091492954261346140525546115575 - 0.019098516261135196432576240858800925 i */
+#define DELTA515 CHOOSE(BUILD_COMPLEX (0, 1), 0, 0, BUILD_COMPLEX (0, 1), 0, 0) /* clog (-2 - 3 i) == 1.2824746787307683680267437207826593 - 2.1587989303424641704769327722648368 i */
+#define DELTA520 CHOOSE(0, BUILD_COMPLEX (0, 1), 0, 0, BUILD_COMPLEX (0, 1), 0) /* clog10 (-inf + inf i) == inf + 3/4 pi*log10(e) i */
+#define DELTA521 CHOOSE(0, BUILD_COMPLEX (0, 1), BUILD_COMPLEX (0, 1), 0, BUILD_COMPLEX (0, 1), BUILD_COMPLEX (0, 1)) /* clog10 (inf + inf i) == inf + pi/4*log10(e) i */
+#define DELTA522 CHOOSE(0, BUILD_COMPLEX (0, 1), BUILD_COMPLEX (0, 1), 0, BUILD_COMPLEX (0, 1), BUILD_COMPLEX (0, 1)) /* clog10 (inf - inf i) == inf - pi/4*log10(e) i */
+#define DELTA523 CHOOSE(0, BUILD_COMPLEX (0, 1), BUILD_COMPLEX (0, 1), 0, BUILD_COMPLEX (0, 1), BUILD_COMPLEX (0, 1)) /* clog10 (0 + inf i) == inf + pi/2*log10(e) i */
+#define DELTA524 CHOOSE(0, BUILD_COMPLEX (0, 1), BUILD_COMPLEX (0, 1), 0, BUILD_COMPLEX (0, 1), BUILD_COMPLEX (0, 1)) /* clog10 (3 + inf i) == inf + pi/2*log10(e) i */
+#define DELTA525 CHOOSE(0, BUILD_COMPLEX (0, 1), BUILD_COMPLEX (0, 1), 0, BUILD_COMPLEX (0, 1), BUILD_COMPLEX (0, 1)) /* clog10 (-0 + inf i) == inf + pi/2*log10(e) i */
+#define DELTA526 CHOOSE(0, BUILD_COMPLEX (0, 1), BUILD_COMPLEX (0, 1), 0, BUILD_COMPLEX (0, 1), BUILD_COMPLEX (0, 1)) /* clog10 (-3 + inf i) == inf + pi/2*log10(e) i */
+#define DELTA527 CHOOSE(0, BUILD_COMPLEX (0, 1), BUILD_COMPLEX (0, 1), 0, BUILD_COMPLEX (0, 1), BUILD_COMPLEX (0, 1)) /* clog10 (0 - inf i) == inf - pi/2*log10(e) i */
+#define DELTA528 CHOOSE(0, BUILD_COMPLEX (0, 1), BUILD_COMPLEX (0, 1), 0, BUILD_COMPLEX (0, 1), BUILD_COMPLEX (0, 1)) /* clog10 (3 - inf i) == inf - pi/2*log10(e) i */
+#define DELTA529 CHOOSE(0, BUILD_COMPLEX (0, 1), BUILD_COMPLEX (0, 1), 0, BUILD_COMPLEX (0, 1), BUILD_COMPLEX (0, 1)) /* clog10 (-0 - inf i) == inf - pi/2*log10(e) i */
+#define DELTA530 CHOOSE(0, BUILD_COMPLEX (0, 1), BUILD_COMPLEX (0, 1), 0, BUILD_COMPLEX (0, 1), BUILD_COMPLEX (0, 1)) /* clog10 (-3 - inf i) == inf - pi/2*log10(e) i */
+#define DELTA531 CHOOSE(0, BUILD_COMPLEX (0, 1), BUILD_COMPLEX (0, 1), 0, BUILD_COMPLEX (0, 1), BUILD_COMPLEX (0, 1)) /* clog10 (-inf + 0 i) == inf + pi*log10(e) i */
+#define DELTA532 CHOOSE(0, BUILD_COMPLEX (0, 1), BUILD_COMPLEX (0, 1), 0, BUILD_COMPLEX (0, 1), BUILD_COMPLEX (0, 1)) /* clog10 (-inf + 1 i) == inf + pi*log10(e) i */
+#define DELTA533 CHOOSE(0, BUILD_COMPLEX (0, 1), BUILD_COMPLEX (0, 1), 0, BUILD_COMPLEX (0, 1), BUILD_COMPLEX (0, 1)) /* clog10 (-inf - 0 i) == inf - pi*log10(e) i */
+#define DELTA534 CHOOSE(0, BUILD_COMPLEX (0, 1), BUILD_COMPLEX (0, 1), 0, BUILD_COMPLEX (0, 1), BUILD_COMPLEX (0, 1)) /* clog10 (-inf - 1 i) == inf - pi*log10(e) i */
+#define DELTA552 CHOOSE(BUILD_COMPLEX (1403, 186), BUILD_COMPLEX (2, 1), BUILD_COMPLEX (1, 0), BUILD_COMPLEX (1403, 186), BUILD_COMPLEX (2, 1), BUILD_COMPLEX (1, 0)) /* clog10 (0.7 + 1.2 i) == 0.1427786545038868803 + 0.4528483579352493248 i */
+#define DELTA553 CHOOSE(BUILD_COMPLEX (0, 1), BUILD_COMPLEX (0, 1), 0, BUILD_COMPLEX (0, 1), BUILD_COMPLEX (0, 1), 0) /* clog10 (-2 - 3 i) == 0.5569716761534183846 - 0.9375544629863747085 i */
+#define DELTA582 CHOOSE(0, 1, 0.5, 0, 1, 0.5) /* cos (M_PI_6l * 2.0) == 0.5 */
+#define DELTA583 CHOOSE(0.5, 2, 1, 0.5, 2, 1) /* cos (M_PI_6l * 4.0) == -0.5 */
+#define DELTA584 CHOOSE(0.25, 0.2758, 0.3667, 0.25, 0.2758, 0.3667) /* cos (pi/2) == 0 */
+#define DELTA585 CHOOSE(529, 1, 0, 529, 1, 0) /* cos (0.7) == 0.76484218728448842625585999019186495 */
+#define DELTA591 CHOOSE(309, 0, 0, 309, 0, 0) /* cosh (0.7) == 1.255169005630943018 */
+#define DELTA594 CHOOSE(BUILD_COMPLEX (0, 9), BUILD_COMPLEX (0, 1.104), BUILD_COMPLEX (0, 2.5333), BUILD_COMPLEX (0, 9), BUILD_COMPLEX (0, 1.104), BUILD_COMPLEX (0, 2.5333)) /* cpow (e + 0 i, 0 + 2 * M_PIl i) == 1.0 + 0.0 i */
+#define DELTA595 CHOOSE(BUILD_COMPLEX (2, 5), BUILD_COMPLEX (1, 0), BUILD_COMPLEX (4, 1), BUILD_COMPLEX (2, 5), BUILD_COMPLEX (1, 0), BUILD_COMPLEX (4, 1)) /* cpow (2 + 3 i, 4 + 0 i) == -119.0 - 120.0 i */
+#define DELTA652 CHOOSE(BUILD_COMPLEX (966, 168), 0, 0, BUILD_COMPLEX (966, 168), 0, 0) /* csin (0.7 + 1.2 i) == 1.1664563419657581376 + 1.1544997246948547371 i */
+#define DELTA691 CHOOSE(BUILD_COMPLEX (413, 477), BUILD_COMPLEX (1, 0), BUILD_COMPLEX (1, 0), BUILD_COMPLEX (413, 477), BUILD_COMPLEX (1, 0), BUILD_COMPLEX (1, 0)) /* csinh (0.7 + 1.2 i) == 0.27487868678117583582 + 1.1698665727426565139 i */
+#define DELTA692 CHOOSE(BUILD_COMPLEX (0, 2), BUILD_COMPLEX (1, 1), BUILD_COMPLEX (0, 1), BUILD_COMPLEX (0, 2), BUILD_COMPLEX (1, 1), BUILD_COMPLEX (0, 1)) /* csinh (-2 - 3 i) == 3.5905645899857799520 - 0.5309210862485198052 i */
+#define DELTA732 CHOOSE(BUILD_COMPLEX (237, 128), BUILD_COMPLEX (1, 0), 0, BUILD_COMPLEX (237, 128), BUILD_COMPLEX (1, 0), 0) /* csqrt (0.7 + 1.2 i) == 1.022067610030026450706487883081139 + 0.58704531296356521154977678719838035 i */
+#define DELTA733 CHOOSE(BUILD_COMPLEX (1, 0), 0, 0, BUILD_COMPLEX (1, 0), 0, 0) /* csqrt (-2 - 3 i) == 0.89597747612983812471573375529004348 - 1.6741492280355400404480393008490519 i */
+#define DELTA734 CHOOSE(BUILD_COMPLEX (1, 0), 0, 0, BUILD_COMPLEX (1, 0), 0, 0) /* csqrt (-2 + 3 i) == 0.89597747612983812471573375529004348 + 1.6741492280355400404480393008490519 i */
+#define DELTA766 CHOOSE(BUILD_COMPLEX (690, 367), BUILD_COMPLEX (1, 1), BUILD_COMPLEX (1, 0), BUILD_COMPLEX (690, 367), BUILD_COMPLEX (1, 1), BUILD_COMPLEX (1, 0)) /* ctan (0.7 + 1.2 i) == 0.1720734197630349001 + 0.9544807059989405538 i */
+#define DELTA767 CHOOSE(BUILD_COMPLEX (439, 2), 0, BUILD_COMPLEX (0, 1), BUILD_COMPLEX (439, 2), 0, BUILD_COMPLEX (0, 1)) /* ctan (-2 - 3 i) == 0.0037640256415042482 - 1.0032386273536098014 i */
+#define DELTA799 CHOOSE(0, BUILD_COMPLEX (0, 0.5), BUILD_COMPLEX (0, 1), 0, BUILD_COMPLEX (0, 0.5), BUILD_COMPLEX (0, 1)) /* ctanh (0 + pi/4 i) == 0.0 + 1.0 i */
+#define DELTA800 CHOOSE(BUILD_COMPLEX (286, 3074), BUILD_COMPLEX (0, 1), BUILD_COMPLEX (1, 0), BUILD_COMPLEX (286, 3074), BUILD_COMPLEX (0, 1), BUILD_COMPLEX (1, 0)) /* ctanh (0.7 + 1.2 i) == 1.3472197399061191630 + 0.4778641038326365540 i */
+#define DELTA801 CHOOSE(BUILD_COMPLEX (5, 25), 0, BUILD_COMPLEX (0, 1), BUILD_COMPLEX (5, 25), 0, BUILD_COMPLEX (0, 1)) /* ctanh (-2 - 3 i) == -0.9653858790221331242 + 0.0098843750383224937 i */
+#define DELTA817 CHOOSE(1, 1, 0, 1, 1, 0) /* erfc (0.7) == 0.32219880616258152702 */
+#define DELTA818 CHOOSE(3, 1, 2, 3, 1, 2) /* erfc (1.2) == 0.089686021770364619762 */
+#define DELTA819 CHOOSE(0, 1, 1, 0, 1, 0) /* erfc (2.0) == 0.0046777349810472658379 */
+#define DELTA820 CHOOSE(12, 24, 12, 12, 24, 12) /* erfc (4.1) == 0.67000276540848983727e-8 */
+#define DELTA821 CHOOSE(36, 0, 0, 36, 0, 0) /* erfc (9) == 0.41370317465138102381e-36 */
+#define DELTA830 CHOOSE(412, 0, 0, 412, 0, 0) /* exp (0.7) == 2.0137527074704765216 */
+#define DELTA831 CHOOSE(16, 0, 0, 16, 0, 0) /* exp (50.0) == 5184705528587072464087.45332293348538 */
+#define DELTA832 CHOOSE(754, 0, 0, 754, 0, 0) /* exp (1000.0) == 0.197007111401704699388887935224332313e435 */
+#define DELTA838 CHOOSE(8, 0, 0, 8, 0, 0) /* exp10 (3) == 1000 */
+#define DELTA839 CHOOSE(818, 0, 0, 818, 0, 0) /* exp10 (-1) == 0.1 */
+#define DELTA842 CHOOSE(1182, 1, 0, 1182, 1, 0) /* exp10 (0.7) == 5.0118723362727228500155418688494574 */
+#define DELTA852 CHOOSE(462, 0, 0, 462, 0, 0) /* exp2 (0.7) == 1.6245047927124710452 */
+#define DELTA859 CHOOSE(825, 0, 0, 825, 0, 0) /* expm1 (0.7) == 1.0137527074704765216 */
+#define DELTA972 CHOOSE(4096, 2, 1, 4096, 2, 1) /* fmod (6.5, 2.3) == 1.9 */
+#define DELTA973 CHOOSE(4096, 2, 1, 4096, 2, 1) /* fmod (-6.5, 2.3) == -1.9 */
+#define DELTA974 CHOOSE(4096, 2, 1, 4096, 2, 1) /* fmod (6.5, -2.3) == 1.9 */
+#define DELTA975 CHOOSE(4096, 2, 1, 4096, 2, 1) /* fmod (-6.5, -2.3) == -1.9 */
+#define DELTA1004 CHOOSE(1, 1, 0, 1, 1, 0) /* gamma (-0.5) == log(2*sqrt(pi)) */
+#define DELTA1013 CHOOSE(406, 0, 1, 406, 0, 0) /* hypot (0.7, 12.4) == 12.419742348374220601176836866763271 */
+#define DELTA1014 CHOOSE(406, 0, 1, 406, 0, 0) /* hypot (-0.7, 12.4) == 12.419742348374220601176836866763271 */
+#define DELTA1015 CHOOSE(406, 0, 1, 406, 0, 0) /* hypot (0.7, -12.4) == 12.419742348374220601176836866763271 */
+#define DELTA1016 CHOOSE(406, 0, 1, 406, 0, 0) /* hypot (-0.7, -12.4) == 12.419742348374220601176836866763271 */
+#define DELTA1017 CHOOSE(406, 0, 1, 406, 0, 0) /* hypot (12.4, 0.7) == 12.419742348374220601176836866763271 */
+#define DELTA1018 CHOOSE(406, 0, 1, 406, 0, 0) /* hypot (-12.4, 0.7) == 12.419742348374220601176836866763271 */
+#define DELTA1019 CHOOSE(406, 0, 1, 406, 0, 0) /* hypot (12.4, -0.7) == 12.419742348374220601176836866763271 */
+#define DELTA1020 CHOOSE(406, 0, 1, 406, 0, 0) /* hypot (-12.4, -0.7) == 12.419742348374220601176836866763271 */
+#define DELTA1024 CHOOSE(560, 1, 0, 560, 0, 0) /* hypot (0.7, 1.2) == 1.3892443989449804508432547041028554 */
+#define DELTA1053 CHOOSE(0, 2, 2, 0, 1, 1) /* j0 (2.0) == 0.22389077914123566805 */
+#define DELTA1054 CHOOSE(0, 0, 1, 0, 0, 1) /* j0 (8.0) == 0.17165080713755390609 */
+#define DELTA1055 CHOOSE(0, 2, 2, 0, 2, 1) /* j0 (10.0) == -0.24593576445134833520 */
+#define DELTA1064 CHOOSE(0, 1, 0, 0, 1, 0) /* j1 (2.0) == 0.57672480775687338720 */
+#define DELTA1065 CHOOSE(1, 1, 1, 1, 0, 1) /* j1 (8.0) == 0.23463634685391462438 */
+#define DELTA1066 CHOOSE(2, 2, 2, 2, 2, 1) /* j1 (10.0) == 0.043472746168861436670 */
+#define DELTA1075 CHOOSE(0, 2, 2, 0, 1, 1) /* jn (0, 2.0) == 0.22389077914123566805 */
+#define DELTA1076 CHOOSE(1, 0, 1, 1, 0, 1) /* jn (0, 8.0) == 0.17165080713755390609 */
+#define DELTA1077 CHOOSE(2, 2, 1, 2, 2, 1) /* jn (0, 10.0) == -0.24593576445134833520 */
+#define DELTA1086 CHOOSE(0, 1, 0, 0, 1, 0) /* jn (1, 2.0) == 0.57672480775687338720 */
+#define DELTA1087 CHOOSE(1, 1, 1, 1, 0, 1) /* jn (1, 8.0) == 0.23463634685391462438 */
+#define DELTA1088 CHOOSE(2, 2, 2, 2, 2, 1) /* jn (1, 10.0) == 0.043472746168861436670 */
+#define DELTA1091 CHOOSE(1, 0, 0, 1, 0, 0) /* jn (3, -1.0) == -0.019563353982668405919 */
+#define DELTA1093 CHOOSE(1, 1, 0, 1, 1, 0) /* jn (3, 0.1) == 0.000020820315754756261429 */
+#define DELTA1094 CHOOSE(0, 2, 1, 0, 2, 0) /* jn (3, 0.7) == 0.0069296548267508408077 */
+#define DELTA1095 CHOOSE(1, 0, 0, 1, 0, 0) /* jn (3, 1.0) == 0.019563353982668405919 */
+#define DELTA1096 CHOOSE(0, 1, 1, 0, 1, 1) /* jn (3, 2.0) == 0.12894324947440205110 */
+#define DELTA1097 CHOOSE(1, 3, 1, 1, 3, 1) /* jn (3, 10.0) == 0.058379379305186812343 */
+#define DELTA1100 CHOOSE(1, 1, 1, 1, 1, 1) /* jn (10, -1.0) == 0.26306151236874532070e-9 */
+#define DELTA1102 CHOOSE(1, 6, 4, 1, 5, 2) /* jn (10, 0.1) == 0.26905328954342155795e-19 */
+#define DELTA1103 CHOOSE(2, 4, 1, 2, 4, 1) /* jn (10, 0.7) == 0.75175911502153953928e-11 */
+#define DELTA1104 CHOOSE(1, 1, 1, 1, 1, 1) /* jn (10, 1.0) == 0.26306151236874532070e-9 */
+#define DELTA1105 CHOOSE(1, 2, 2, 1, 2, 1) /* jn (10, 2.0) == 0.25153862827167367096e-6 */
+#define DELTA1106 CHOOSE(2, 4, 3, 2, 4, 2) /* jn (10, 10.0) == 0.20748610663335885770 */
+#define DELTA1126 CHOOSE(1, 1, 0, 1, 1, 0) /* lgamma (-0.5) == log(2*sqrt(pi)) */
+#define DELTA1128 CHOOSE(0, 1, 1, 0, 1, 1) /* lgamma (0.7) == 0.26086724653166651439 */
+#define DELTA1130 CHOOSE(1, 1, 2, 1, 1, 2) /* lgamma (1.2) == -0.853740900033158497197e-1 */
+#define DELTA1163 CHOOSE(1, 0, 0.5, 1, 0, 0.5) /* log (e) == 1 */
+#define DELTA1164 CHOOSE(1, 0, 0, 1, 0, 0) /* log (1.0 / M_El) == -1 */
+#define DELTA1167 CHOOSE(2341, 1, 1, 2341, 1, 1) /* log (0.7) == -0.35667494393873237891263871124118447 */
+#define DELTA1178 CHOOSE(1, 0, 1, 1, 0, 1) /* log10 (e) == log10(e) */
+#define DELTA1179 CHOOSE(2033, 1, 0, 2033, 1, 0) /* log10 (0.7) == -0.15490195998574316929 */
+#define DELTA1186 CHOOSE(1, 0, 0, 1, 0, 0) /* log1p (M_El - 1.0) == 1 */
+#define DELTA1187 CHOOSE(585, 1, 1, 585, 1, 1) /* log1p (-0.3) == -0.35667494393873237891263871124118447 */
+#define DELTA1198 CHOOSE(1688, 1, 1, 1688, 1, 1) /* log2 (0.7) == -0.51457317282975824043 */
+#define DELTA1398 CHOOSE(725, 0, 0, 725, 0, 0) /* pow (0.7, 1.2) == 0.65180494056638638188 */
+#define DELTA1524 CHOOSE(627, 0, 0, 627, 0, 0) /* sin (0.7) == 0.64421768723769105367261435139872014 */
+#define DELTA1536 CHOOSE(0.25, 0.2758, 0.3667, 0.25, 0.2758, 0.3667) /* sincos (pi/2, &sin_res, &cos_res) puts 0 in cos_res */
+#define DELTA1539 CHOOSE(1, 1, 1, 1, 1, 1) /* sincos (M_PI_6l*2.0, &sin_res, &cos_res) puts 0.86602540378443864676372317075293616 in sin_res */
+#define DELTA1540 CHOOSE(0, 1, 0.5, 0, 1, 0.5) /* sincos (M_PI_6l*2.0, &sin_res, &cos_res) puts 0.5 in cos_res */
+#define DELTA1541 CHOOSE(627, 0, 0, 627, 0, 0) /* sincos (0.7, &sin_res, &cos_res) puts 0.64421768723769105367261435139872014 in sin_res */
+#define DELTA1542 CHOOSE(528, 1, 0, 528, 1, 0) /* sincos (0.7, &sin_res, &cos_res) puts 0.76484218728448842625585999019186495 in cos_res */
+#define DELTA1548 CHOOSE(1029, 1, 1, 1028, 0, 1) /* sinh (0.7) == 0.75858370183953350346 */
+#define DELTA1562 CHOOSE(325, 0, 0, 325, 0, 0) /* sqrt (15239.9025) == 123.45 */
+#define DELTA1569 CHOOSE(0, 0.5, 0, 0, 0.5, 0) /* tan (pi/4) == 1 */
+#define DELTA1570 CHOOSE(1401, 1, 1, 1401, 0, 0) /* tan (0.7) == 0.84228838046307944812813500221293775 */
+#define DELTA1576 CHOOSE(521, 1, 1, 521, 0, 0) /* tanh (0.7) == 0.60436777711716349631 */
+#define DELTA1577 CHOOSE(1, 1, 1, 1, 0, 0) /* tanh (-0.7) == -0.60436777711716349631 */
+#define DELTA1587 CHOOSE(0, 0, 1, 0, 0, 1) /* tgamma (0.5) == sqrt (pi) */
+#define DELTA1588 CHOOSE(2, 2, 1, 2, 2, 1) /* tgamma (-0.5) == -2 sqrt (pi) */
+#define DELTA1590 CHOOSE(2, 0, 0, 2, 0, 0) /* tgamma (4) == 6 */
+#define DELTA1591 CHOOSE(0, 1, 1, 0, 1, 1) /* tgamma (0.7) == 1.29805533264755778568 */
+#define DELTA1614 CHOOSE(0, 1, 1, 0, 1, 1) /* y0 (0.1) == -1.5342386513503668441 */
+#define DELTA1615 CHOOSE(2, 3, 1, 2, 3, 1) /* y0 (0.7) == -0.19066492933739506743 */
+#define DELTA1616 CHOOSE(0, 2, 1, 0, 2, 1) /* y0 (1.0) == 0.088256964215676957983 */
+#define DELTA1617 CHOOSE(0, 1, 1, 0, 1, 1) /* y0 (1.5) == 0.38244892379775884396 */
+#define DELTA1618 CHOOSE(0, 1, 0, 0, 1, 0) /* y0 (2.0) == 0.51037567264974511960 */
+#define DELTA1619 CHOOSE(1, 1, 1, 1, 1, 1) /* y0 (8.0) == 0.22352148938756622053 */
+#define DELTA1620 CHOOSE(1, 2, 1, 2, 2, 1) /* y0 (10.0) == 0.055671167283599391424 */
+#define DELTA1625 CHOOSE(1, 1, 1, 1, 1, 1) /* y1 (0.1) == -6.4589510947020269877 */
+#define DELTA1626 CHOOSE(0, 1, 1, 0, 1, 0) /* y1 (0.7) == -1.1032498719076333697 */
+#define DELTA1627 CHOOSE(0, 1, 0, 0, 1, 0) /* y1 (1.0) == -0.78121282130028871655 */
+#define DELTA1628 CHOOSE(0, 0, 1, 0, 0, 1) /* y1 (1.5) == -0.41230862697391129595 */
+#define DELTA1629 CHOOSE(1, 1, 2, 1, 1, 2) /* y1 (2.0) == -0.10703243154093754689 */
+#define DELTA1630 CHOOSE(2, 1, 2, 2, 0, 2) /* y1 (8.0) == -0.15806046173124749426 */
+#define DELTA1631 CHOOSE(0, 3, 2, 0, 3, 2) /* y1 (10.0) == 0.24901542420695388392 */
+#define DELTA1636 CHOOSE(0, 1, 1, 0, 1, 1) /* yn (0, 0.1) == -1.5342386513503668441 */
+#define DELTA1637 CHOOSE(2, 3, 1, 2, 3, 1) /* yn (0, 0.7) == -0.19066492933739506743 */
+#define DELTA1638 CHOOSE(0, 2, 1, 0, 2, 1) /* yn (0, 1.0) == 0.088256964215676957983 */
+#define DELTA1639 CHOOSE(0, 1, 1, 0, 1, 1) /* yn (0, 1.5) == 0.38244892379775884396 */
+#define DELTA1640 CHOOSE(0, 1, 0, 0, 1, 0) /* yn (0, 2.0) == 0.51037567264974511960 */
+#define DELTA1641 CHOOSE(1, 1, 1, 1, 1, 1) /* yn (0, 8.0) == 0.22352148938756622053 */
+#define DELTA1642 CHOOSE(1, 2, 1, 1, 2, 1) /* yn (0, 10.0) == 0.055671167283599391424 */
+#define DELTA1647 CHOOSE(1, 1, 1, 1, 1, 1) /* yn (1, 0.1) == -6.4589510947020269877 */
+#define DELTA1648 CHOOSE(0, 1, 1, 0, 1, 0) /* yn (1, 0.7) == -1.1032498719076333697 */
+#define DELTA1649 CHOOSE(0, 1, 0, 0, 1, 0) /* yn (1, 1.0) == -0.78121282130028871655 */
+#define DELTA1650 CHOOSE(0, 0, 1, 0, 0, 1) /* yn (1, 1.5) == -0.41230862697391129595 */
+#define DELTA1651 CHOOSE(1, 1, 2, 1, 1, 2) /* yn (1, 2.0) == -0.10703243154093754689 */
+#define DELTA1652 CHOOSE(2, 1, 2, 2, 0, 2) /* yn (1, 8.0) == -0.15806046173124749426 */
+#define DELTA1653 CHOOSE(0, 3, 2, 0, 3, 2) /* yn (1, 10.0) == 0.24901542420695388392 */
+#define DELTA1656 CHOOSE(2, 1, 2, 2, 1, 1) /* yn (3, 0.1) == -5099.3323786129048894 */
+#define DELTA1657 CHOOSE(2, 3, 1, 2, 3, 1) /* yn (3, 0.7) == -15.819479052819633505 */
+#define DELTA1659 CHOOSE(0, 1, 1, 0, 1, 1) /* yn (3, 2.0) == -1.1277837768404277861 */
+#define DELTA1660 CHOOSE(0, 1, 1, 0, 1, 1) /* yn (3, 10.0) == -0.25136265718383732978 */
+#define DELTA1663 CHOOSE(2, 2, 2, 2, 2, 1) /* yn (10, 0.1) == -0.11831335132045197885e19 */
+#define DELTA1664 CHOOSE(7, 6, 3, 7, 6, 3) /* yn (10, 0.7) == -0.42447194260703866924e10 */
+#define DELTA1665 CHOOSE(0, 1, 2, 0, 1, 1) /* yn (10, 1.0) == -0.12161801427868918929e9 */
+#define DELTA1666 CHOOSE(1, 3, 1, 1, 2, 1) /* yn (10, 2.0) == -129184.54220803928264 */
+#define DELTA1667 CHOOSE(0, 2, 1, 0, 2, 1) /* yn (10, 10.0) == -0.35981415218340272205 */
--- /dev/null
+/* Copyright (C) 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Andreas Jaeger <aj@arthur.rhein-neckar.de>, 1997.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+/* Part of testsuite for libm.
+
+ This file is processed by a perl script. The resulting file has to
+ be included by a master file that defines:
+
+ Makros:
+ FUNC(function): converts general function name (like cos) to
+ name with correct suffix (e.g. cosl or cosf)
+ MATHCONST(x): like FUNC but for constants (e.g convert 0.0 to 0.0L)
+ FLOAT: floating point type to test
+ - TEST_MSG: informal message to be displayed
+ CHOOSE(Clongdouble,Cdouble,Cfloat,Cinlinelongdouble,Cinlinedouble,Cinlinefloat):
+ chooses one of the parameters as delta for testing
+ equality
+ PRINTF_EXPR Floating point conversion specification to print a variable
+ of type FLOAT with printf. PRINTF_EXPR just contains
+ the specifier, not the percent and width arguments,
+ e.g. "f".
+ PRINTF_XEXPR Like PRINTF_EXPR, but print in hexadecimal format.
+ PRINTF_NEXPR Like PRINTF_EXPR, but print nice. */
+
+/* This testsuite has currently tests for:
+ acos, acosh, asin, asinh, atan, atan2, atanh,
+ cbrt, ceil, copysign, cos, cosh, erf, erfc, exp, exp10, exp2, expm1,
+ fabs, fdim, floor, fma, fmax, fmin, fmod, fpclassify,
+ frexp, gamma, hypot,
+ ilogb, isfinite, isinf, isnan, isnormal,
+ isless, islessequal, isgreater, isgreaterequal, islessgreater, isunordered,
+ j0, j1, jn,
+ ldexp, lgamma, log, log10, log1p, log2, logb,
+ modf, nearbyint, nextafter,
+ pow, remainder, remquo, rint, lrint, llrint,
+ round, lround, llround,
+ scalb, scalbn, scalbln, signbit, sin, sincos, sinh, sqrt, tan, tanh, tgamma, trunc,
+ y0, y1, yn
+
+ and for the following complex math functions:
+ cabs, cacos, cacosh, carg, casin, casinh, catan, catanh,
+ ccos, ccosh, cexp, clog, cpow, cproj, csin, csinh, csqrt, ctan, ctanh.
+
+ At the moment the following functions aren't tested:
+ drem, significand, nan
+
+ Parameter handling is primitive in the moment:
+ --verbose=[0..3] for different levels of output:
+ 0: only error count
+ 1: basic report on failed tests (default)
+ 2: full report on all tests
+ -v for full output (equals --verbose=3)
+ -u for generation of an ULPs file
+ */
+
+/* "Philosophy":
+
+ This suite tests some aspects of the correct implementation of
+ mathematical functions in libm. Some simple, specific parameters
+ are tested for correctness but there's no exhaustive
+ testing. Handling of specific inputs (e.g. infinity, not-a-number)
+ is also tested. Correct handling of exceptions is checked
+ against. These implemented tests should check all cases that are
+ specified in ISO C99.
+
+ Exception testing: At the moment only divide-by-zero and invalid
+ exceptions are tested. Overflow/underflow and inexact exceptions
+ aren't checked at the moment.
+
+ NaN values: There exist signalling and quiet NaNs. This implementation
+ only uses signalling NaN as parameter but does not differenciate
+ between the two kinds of NaNs as result.
+
+ Inline functions: Inlining functions should give an improvement in
+ speed - but not in precission. The inlined functions return
+ reasonable values for a reasonable range of input values. The
+ result is not necessarily correct for all values and exceptions are
+ not correctly raised in all cases. Problematic input and return
+ values are infinity, not-a-number and minus zero. This suite
+ therefore does not check these specific inputs and the exception
+ handling for inlined mathematical functions - just the "reasonable"
+ values are checked.
+
+ Beware: The tests might fail for any of the following reasons:
+ - Tests are wrong
+ - Functions are wrong
+ - Floating Point Unit not working properly
+ - Compiler has errors
+
+ With e.g. gcc 2.7.2.2 the test for cexp fails because of a compiler error.
+
+
+ To Do: All parameter should be numbers that can be represented as
+ exact floating point values. Currently some values cannot be represented
+ exactly and therefore the result is not the expected result.
+*/
+
+#ifndef _GNU_SOURCE
+# define _GNU_SOURCE
+#endif
+
+#include "libm-test-ulps.h"
+#include <float.h>
+#ifdef SYS_MATH_H
+#include <math.h>
+#include <fenv.h>
+#else
+#include <openlibm.h>
+#endif
+
+#if 0 /* XXX scp XXX */
+#define FE_INEXACT FE_INEXACT
+#define FE_DIVBYZERO FE_DIVBYZERO
+#define FE_UNDERFLOW FE_UNDERFLOW
+#define FE_OVERFLOW FE_OVERFLOW
+#define FE_INVALID FE_INVALID
+#endif
+
+#include <limits.h>
+
+#include <errno.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#if 0 /* XXX scp XXX */
+#include <argp.h>
+#endif
+
+// Some native libm implementations don't have sincos defined, so we have to do it ourselves
+void FUNC(sincos) (FLOAT x, FLOAT * s, FLOAT * c);
+
+#ifdef __APPLE__
+#ifdef SYS_MATH_H
+void sincos(FLOAT x, FLOAT * s, FLOAT * c)
+{
+ *s = sin(x);
+ *c = cos(x);
+}
+#endif
+#endif
+
+/* Possible exceptions */
+#define NO_EXCEPTION 0x0
+#define INVALID_EXCEPTION 0x1
+#define DIVIDE_BY_ZERO_EXCEPTION 0x2
+/* The next flags signals that those exceptions are allowed but not required. */
+#define INVALID_EXCEPTION_OK 0x4
+#define DIVIDE_BY_ZERO_EXCEPTION_OK 0x8
+#define EXCEPTIONS_OK INVALID_EXCEPTION_OK+DIVIDE_BY_ZERO_EXCEPTION_OK
+/* Some special test flags, passed togther with exceptions. */
+#define IGNORE_ZERO_INF_SIGN 0x10
+
+/* Various constants (we must supply them precalculated for accuracy). */
+#define M_PI_6l .52359877559829887307710723054658383L
+#define M_E2l 7.389056098930650227230427460575008L
+#define M_E3l 20.085536923187667740928529654581719L
+#define M_2_SQRT_PIl 3.5449077018110320545963349666822903L /* 2 sqrt (M_PIl) */
+#define M_SQRT_PIl 1.7724538509055160272981674833411451L /* sqrt (M_PIl) */
+#define M_LOG_SQRT_PIl 0.57236494292470008707171367567652933L /* log(sqrt(M_PIl)) */
+#define M_LOG_2_SQRT_PIl 1.265512123484645396488945797134706L /* log(2*sqrt(M_PIl)) */
+#define M_PI_34l (M_PIl - M_PI_4l) /* 3*pi/4 */
+#define M_PI_34_LOG10El (M_PIl - M_PI_4l) * M_LOG10El
+#define M_PI2_LOG10El M_PI_2l * M_LOG10El
+#define M_PI4_LOG10El M_PI_4l * M_LOG10El
+#define M_PI_LOG10El M_PIl * M_LOG10El
+
+#if 1 /* XXX scp XXX */
+# define M_El 2.7182818284590452353602874713526625L /* e */
+# define M_LOG2El 1.4426950408889634073599246810018922L /* log_2 e */
+# define M_LOG10El 0.4342944819032518276511289189166051L /* log_10 e */
+# define M_LN2l 0.6931471805599453094172321214581766L /* log_e 2 */
+# define M_LN10l 2.3025850929940456840179914546843642L /* log_e 10 */
+# define M_PIl 3.1415926535897932384626433832795029L /* pi */
+# define M_PI_2l 1.5707963267948966192313216916397514L /* pi/2 */
+# define M_PI_4l 0.7853981633974483096156608458198757L /* pi/4 */
+# define M_1_PIl 0.3183098861837906715377675267450287L /* 1/pi */
+# define M_2_PIl 0.6366197723675813430755350534900574L /* 2/pi */
+# define M_2_SQRTPIl 1.1283791670955125738961589031215452L /* 2/sqrt(pi) */
+# define M_SQRT2l 1.4142135623730950488016887242096981L /* sqrt(2) */
+# define M_SQRT1_2l 0.7071067811865475244008443621048490L /* 1/sqrt(2) */
+#endif
+
+static FILE *ulps_file; /* File to document difference. */
+static int output_ulps; /* Should ulps printed? */
+
+static int noErrors; /* number of errors */
+static int noTests; /* number of tests (without testing exceptions) */
+static int noExcTests; /* number of tests for exception flags */
+static int noXFails; /* number of expected failures. */
+static int noXPasses; /* number of unexpected passes. */
+
+static int verbose;
+static int output_max_error; /* Should the maximal errors printed? */
+static int output_points; /* Should the single function results printed? */
+static int ignore_max_ulp; /* Should we ignore max_ulp? */
+
+static FLOAT minus_zero, plus_zero;
+static FLOAT plus_infty, minus_infty, nan_value;
+
+static FLOAT max_error, real_max_error, imag_max_error;
+
+
+#if 0 /* XXX scp XXX */
+#define BUILD_COMPLEX(real, imag) \
+ ({ __complex__ FLOAT __retval; \
+ __real__ __retval = (real); \
+ __imag__ __retval = (imag); \
+ __retval; })
+
+#define BUILD_COMPLEX_INT(real, imag) \
+ ({ __complex__ int __retval; \
+ __real__ __retval = (real); \
+ __imag__ __retval = (imag); \
+ __retval; })
+#endif
+
+
+#define MANT_DIG CHOOSE ((LDBL_MANT_DIG-1), (DBL_MANT_DIG-1), (FLT_MANT_DIG-1), \
+ (LDBL_MANT_DIG-1), (DBL_MANT_DIG-1), (FLT_MANT_DIG-1))
+
+
+static void
+init_max_error (void)
+{
+ max_error = 0;
+ real_max_error = 0;
+ imag_max_error = 0;
+ feclearexcept (FE_ALL_EXCEPT);
+}
+
+static void
+set_max_error (FLOAT current, FLOAT *curr_max_error)
+{
+ if (current > *curr_max_error)
+ *curr_max_error = current;
+}
+
+
+/* Should the message print to screen? This depends on the verbose flag,
+ and the test status. */
+static int
+print_screen (int ok, int xfail)
+{
+ if (output_points
+ && (verbose > 1
+ || (verbose == 1 && ok == xfail)))
+ return 1;
+ return 0;
+}
+
+
+/* Should the message print to screen? This depends on the verbose flag,
+ and the test status. */
+static int
+print_screen_max_error (int ok, int xfail)
+{
+ if (output_max_error
+ && (verbose > 1
+ || ((verbose == 1) && (ok == xfail))))
+ return 1;
+ return 0;
+}
+
+/* Update statistic counters. */
+static void
+update_stats (int ok, int xfail)
+{
+ ++noTests;
+ if (ok && xfail)
+ ++noXPasses;
+ else if (!ok && xfail)
+ ++noXFails;
+ else if (!ok && !xfail)
+ ++noErrors;
+}
+
+static void
+print_ulps (const char *test_name, FLOAT ulp)
+{
+ if (output_ulps)
+ {
+ fprintf (ulps_file, "Test \"%s\":\n", test_name);
+ fprintf (ulps_file, "%s: % .4" PRINTF_NEXPR "\n",
+ CHOOSE("ldouble", "double", "float",
+ "ildouble", "idouble", "ifloat"), ulp);
+ }
+}
+
+static void
+print_function_ulps (const char *function_name, FLOAT ulp)
+{
+ if (output_ulps)
+ {
+ fprintf (ulps_file, "Function: \"%s\":\n", function_name);
+ fprintf (ulps_file, "%s: % .4" PRINTF_NEXPR "\n",
+ CHOOSE("ldouble", "double", "float",
+ "ildouble", "idouble", "ifloat"), ulp);
+ }
+}
+
+
+#if 0 /* XXX scp XXX */
+static void
+print_complex_function_ulps (const char *function_name, FLOAT real_ulp,
+ FLOAT imag_ulp)
+{
+ if (output_ulps)
+ {
+ if (real_ulp != 0.0)
+ {
+ fprintf (ulps_file, "Function: Real part of \"%s\":\n", function_name);
+ fprintf (ulps_file, "%s: % .4" PRINTF_NEXPR "\n",
+ CHOOSE("ldouble", "double", "float",
+ "ildouble", "idouble", "ifloat"), real_ulp);
+ }
+ if (imag_ulp != 0.0)
+ {
+ fprintf (ulps_file, "Function: Imaginary part of \"%s\":\n", function_name);
+ fprintf (ulps_file, "%s: % .4" PRINTF_NEXPR "\n",
+ CHOOSE("ldouble", "double", "float",
+ "ildouble", "idouble", "ifloat"), imag_ulp);
+ }
+
+
+ }
+}
+#endif
+
+
+static void
+print_max_error (const char *func_name, FLOAT allowed, int xfail)
+{
+ int ok = 0;
+
+ if (max_error == 0.0 || (max_error <= allowed && !ignore_max_ulp))
+ {
+ ok = 1;
+ }
+
+ if (!ok)
+ print_function_ulps (func_name, max_error);
+
+
+ if (print_screen_max_error (ok, xfail))
+ {
+ printf ("Maximal error of `%s'\n", func_name);
+ printf (" is : % .4" PRINTF_NEXPR " ulp\n", max_error);
+ printf (" accepted: % .4" PRINTF_NEXPR " ulp\n", allowed);
+ }
+
+ update_stats (ok, xfail);
+}
+
+
+#if 0 /* XXX scp XXX */
+static void
+print_complex_max_error (const char *func_name, __complex__ FLOAT allowed,
+ __complex__ int xfail)
+{
+ int ok = 0;
+
+ if ((real_max_error <= __real__ allowed)
+ && (imag_max_error <= __imag__ allowed))
+ {
+ ok = 1;
+ }
+
+ if (!ok)
+ print_complex_function_ulps (func_name, real_max_error, imag_max_error);
+
+
+ if (print_screen_max_error (ok, xfail))
+ {
+ printf ("Maximal error of real part of: %s\n", func_name);
+ printf (" is : % .4" PRINTF_NEXPR " ulp\n", real_max_error);
+ printf (" accepted: % .4" PRINTF_NEXPR " ulp\n", __real__ allowed);
+ printf ("Maximal error of imaginary part of: %s\n", func_name);
+ printf (" is : % .4" PRINTF_NEXPR " ulp\n", imag_max_error);
+ printf (" accepted: % .4" PRINTF_NEXPR " ulp\n", __imag__ allowed);
+ }
+
+ update_stats (ok, xfail);
+}
+#endif
+
+
+/* Test whether a given exception was raised. */
+static void
+test_single_exception (const char *test_name,
+ int exception,
+ int exc_flag,
+ int fe_flag,
+ const char *flag_name)
+{
+/* Don't perform these checks if we're compiling with clang, because clang
+ doesn't bother to set floating-point exceptions properly */
+#ifndef __clang__
+#ifndef TEST_INLINE
+ int ok = 1;
+ if (exception & exc_flag)
+ {
+ if (fetestexcept (fe_flag))
+ {
+ if (print_screen (1, 0))
+ printf ("Pass: %s: Exception \"%s\" set\n", test_name, flag_name);
+ }
+ else
+ {
+ ok = 0;
+ if (print_screen (0, 0))
+ printf ("Failure: %s: Exception \"%s\" not set\n",
+ test_name, flag_name);
+ }
+ }
+ else
+ {
+ if (fetestexcept (fe_flag))
+ {
+ ok = 0;
+ if (print_screen (0, 0))
+ printf ("Failure: %s: Exception \"%s\" set\n",
+ test_name, flag_name);
+ }
+ else
+ {
+ if (print_screen (1, 0))
+ printf ("%s: Exception \"%s\" not set\n", test_name,
+ flag_name);
+ }
+ }
+ if (!ok)
+ ++noErrors;
+
+#endif
+#endif // __clang__
+}
+
+
+/* Test whether exceptions given by EXCEPTION are raised. Ignore thereby
+ allowed but not required exceptions.
+*/
+static void
+test_exceptions (const char *test_name, int exception)
+{
+ ++noExcTests;
+#ifdef FE_DIVBYZERO
+ if ((exception & DIVIDE_BY_ZERO_EXCEPTION_OK) == 0)
+ test_single_exception (test_name, exception,
+ DIVIDE_BY_ZERO_EXCEPTION, FE_DIVBYZERO,
+ "Divide by zero");
+#endif
+#ifdef FE_INVALID
+ if ((exception & INVALID_EXCEPTION_OK) == 0)
+ test_single_exception (test_name, exception, INVALID_EXCEPTION, FE_INVALID,
+ "Invalid operation");
+#endif
+ feclearexcept (FE_ALL_EXCEPT);
+}
+
+
+static void
+check_float_internal (const char *test_name, FLOAT computed, FLOAT expected,
+ FLOAT max_ulp, int xfail, int exceptions,
+ FLOAT *curr_max_error)
+{
+ int ok = 0;
+ int print_diff = 0;
+ FLOAT diff = 0;
+ FLOAT ulp = 0;
+
+ test_exceptions (test_name, exceptions);
+ if (isnan (computed) && isnan (expected))
+ ok = 1;
+ else if (isinf (computed) && isinf (expected))
+ {
+ /* Test for sign of infinities. */
+ if ((exceptions & IGNORE_ZERO_INF_SIGN) == 0
+ && signbit (computed) != signbit (expected))
+ {
+ ok = 0;
+ printf ("infinity has wrong sign.\n");
+ }
+ else
+ ok = 1;
+ }
+ /* Don't calc ulp for NaNs or infinities. */
+ else if (isinf (computed) || isnan (computed) || isinf (expected) || isnan (expected))
+ ok = 0;
+ else
+ {
+ diff = FUNC(fabs) (computed - expected);
+ /* ilogb (0) isn't allowed. */
+ if (expected == 0.0)
+ ulp = diff / FUNC(ldexp) (1.0, - MANT_DIG);
+ else
+ ulp = diff / FUNC(ldexp) (1.0, FUNC(ilogb) (expected) - MANT_DIG);
+ set_max_error (ulp, curr_max_error);
+ print_diff = 1;
+ if ((exceptions & IGNORE_ZERO_INF_SIGN) == 0
+ && computed == 0.0 && expected == 0.0
+ && signbit(computed) != signbit (expected))
+ ok = 0;
+ else if (ulp == 0.0 || (ulp <= max_ulp && !ignore_max_ulp))
+ ok = 1;
+ else
+ {
+ ok = 0;
+ print_ulps (test_name, ulp);
+ }
+
+ }
+ if (print_screen (ok, xfail))
+ {
+ if (!ok)
+ printf ("Failure: ");
+ printf ("Test: %s\n", test_name);
+ printf ("Result:\n");
+ printf (" is: % .20" PRINTF_EXPR " % .20" PRINTF_XEXPR "\n",
+ computed, computed);
+ printf (" should be: % .20" PRINTF_EXPR " % .20" PRINTF_XEXPR "\n",
+ expected, expected);
+ if (print_diff)
+ {
+ printf (" difference: % .20" PRINTF_EXPR " % .20" PRINTF_XEXPR
+ "\n", diff, diff);
+ printf (" ulp : % .4" PRINTF_NEXPR "\n", ulp);
+ printf (" max.ulp : % .4" PRINTF_NEXPR "\n", max_ulp);
+ }
+ }
+ update_stats (ok, xfail);
+}
+
+
+static void
+check_float (const char *test_name, FLOAT computed, FLOAT expected,
+ FLOAT max_ulp, int xfail, int exceptions)
+{
+ check_float_internal (test_name, computed, expected, max_ulp, xfail,
+ exceptions, &max_error);
+}
+
+#if 0 /* XXX scp XXX */
+static void
+check_complex (const char *test_name, __complex__ FLOAT computed,
+ __complex__ FLOAT expected,
+ __complex__ FLOAT max_ulp, __complex__ int xfail,
+ int exception)
+{
+ FLOAT part_comp, part_exp, part_max_ulp;
+ int part_xfail;
+ char str[200];
+
+ sprintf (str, "Real part of: %s", test_name);
+ part_comp = __real__ computed;
+ part_exp = __real__ expected;
+ part_max_ulp = __real__ max_ulp;
+ part_xfail = __real__ xfail;
+
+ check_float_internal (str, part_comp, part_exp, part_max_ulp, part_xfail,
+ exception, &real_max_error);
+
+ sprintf (str, "Imaginary part of: %s", test_name);
+ part_comp = __imag__ computed;
+ part_exp = __imag__ expected;
+ part_max_ulp = __imag__ max_ulp;
+ part_xfail = __imag__ xfail;
+
+ /* Don't check again for exceptions, just pass through the
+ zero/inf sign test. */
+ check_float_internal (str, part_comp, part_exp, part_max_ulp, part_xfail,
+ exception & IGNORE_ZERO_INF_SIGN,
+ &imag_max_error);
+}
+#endif
+
+/* Check that computed and expected values are equal (int values). */
+static void
+check_int (const char *test_name, int computed, int expected, int max_ulp,
+ int xfail, int exceptions)
+{
+ int diff = computed - expected;
+ int ok = 0;
+
+ test_exceptions (test_name, exceptions);
+ noTests++;
+ if (abs (diff) <= max_ulp)
+ ok = 1;
+
+ if (!ok)
+ print_ulps (test_name, diff);
+
+ if (print_screen (ok, xfail))
+ {
+ if (!ok)
+ printf ("Failure: ");
+ printf ("Test: %s\n", test_name);
+ printf ("Result:\n");
+ printf (" is: %d\n", computed);
+ printf (" should be: %d\n", expected);
+ }
+
+ update_stats (ok, xfail);
+}
+
+
+/* Check that computed and expected values are equal (long int values). */
+static void
+check_long (const char *test_name, long int computed, long int expected,
+ long int max_ulp, int xfail, int exceptions)
+{
+ long int diff = computed - expected;
+ int ok = 0;
+
+ test_exceptions (test_name, exceptions);
+ noTests++;
+ if (labs (diff) <= max_ulp)
+ ok = 1;
+
+ if (!ok)
+ print_ulps (test_name, diff);
+
+ if (print_screen (ok, xfail))
+ {
+ if (!ok)
+ printf ("Failure: ");
+ printf ("Test: %s\n", test_name);
+ printf ("Result:\n");
+ printf (" is: %ld\n", computed);
+ printf (" should be: %ld\n", expected);
+ }
+
+ update_stats (ok, xfail);
+}
+
+
+/* Check that computed value is true/false. */
+static void
+check_bool (const char *test_name, int computed, int expected,
+ long int max_ulp, int xfail, int exceptions)
+{
+ int ok = 0;
+
+ test_exceptions (test_name, exceptions);
+ noTests++;
+ if ((computed == 0) == (expected == 0))
+ ok = 1;
+
+ if (print_screen (ok, xfail))
+ {
+ if (!ok)
+ printf ("Failure: ");
+ printf ("Test: %s\n", test_name);
+ printf ("Result:\n");
+ printf (" is: %d\n", computed);
+ printf (" should be: %d\n", expected);
+ }
+
+ update_stats (ok, xfail);
+}
+
+
+/* check that computed and expected values are equal (long int values) */
+static void
+check_longlong (const char *test_name, long long int computed,
+ long long int expected,
+ long long int max_ulp, int xfail,
+ int exceptions)
+{
+ long long int diff = computed - expected;
+ int ok = 0;
+
+ test_exceptions (test_name, exceptions);
+ noTests++;
+ if (llabs (diff) <= max_ulp)
+ ok = 1;
+
+ if (!ok)
+ print_ulps (test_name, diff);
+
+ if (print_screen (ok, xfail))
+ {
+ if (!ok)
+ printf ("Failure:");
+ printf ("Test: %s\n", test_name);
+ printf ("Result:\n");
+ printf (" is: %lld\n", computed);
+ printf (" should be: %lld\n", expected);
+ }
+
+ update_stats (ok, xfail);
+}
+
+
+#if 0 /* XXX scp XXX */
+/* This is to prevent messages from the SVID libm emulation. */
+int
+matherr (struct exception *x __attribute__ ((unused)))
+{
+ return 1;
+}
+#endif
+
+/****************************************************************************
+ Tests for single functions of libm.
+ Please keep them alphabetically sorted!
+****************************************************************************/
+
+static void
+acos_test (void)
+{
+ errno = 0;
+ FUNC(acos) (0);
+ if (errno == ENOSYS)
+ /* Function not implemented. */
+ return;
+
+ init_max_error ();
+
+ check_float ("acos (inf) == NaN plus invalid exception", FUNC(acos) (plus_infty), nan_value, 0, 0, INVALID_EXCEPTION);
+ check_float ("acos (-inf) == NaN plus invalid exception", FUNC(acos) (minus_infty), nan_value, 0, 0, INVALID_EXCEPTION);
+ check_float ("acos (NaN) == NaN", FUNC(acos) (nan_value), nan_value, 0, 0, 0);
+
+ /* |x| > 1: */
+ check_float ("acos (1.1) == NaN plus invalid exception", FUNC(acos) (1.1L), nan_value, 0, 0, INVALID_EXCEPTION);
+ check_float ("acos (-1.1) == NaN plus invalid exception", FUNC(acos) (-1.1L), nan_value, 0, 0, INVALID_EXCEPTION);
+
+ check_float ("acos (0) == pi/2", FUNC(acos) (0), M_PI_2l, 0, 0, 0);
+ check_float ("acos (-0) == pi/2", FUNC(acos) (minus_zero), M_PI_2l, 0, 0, 0);
+ check_float ("acos (1) == 0", FUNC(acos) (1), 0, 0, 0, 0);
+ check_float ("acos (-1) == pi", FUNC(acos) (-1), M_PIl, 0, 0, 0);
+ check_float ("acos (0.5) == M_PI_6l*2.0", FUNC(acos) (0.5), M_PI_6l*2.0, 1, 0, 0);
+ check_float ("acos (-0.5) == M_PI_6l*4.0", FUNC(acos) (-0.5), M_PI_6l*4.0, 0, 0, 0);
+ check_float ("acos (0.7) == 0.79539883018414355549096833892476432", FUNC(acos) (0.7L), 0.79539883018414355549096833892476432L, 0, 0, 0);
+
+ print_max_error ("acos", DELTAacos, 0);
+}
+
+static void
+acosh_test (void)
+{
+ errno = 0;
+ FUNC(acosh) (7);
+ if (errno == ENOSYS)
+ /* Function not implemented. */
+ return;
+
+ init_max_error ();
+
+ check_float ("acosh (inf) == inf", FUNC(acosh) (plus_infty), plus_infty, 0, 0, 0);
+ check_float ("acosh (-inf) == NaN plus invalid exception", FUNC(acosh) (minus_infty), nan_value, 0, 0, INVALID_EXCEPTION);
+
+ /* x < 1: */
+ check_float ("acosh (-1.1) == NaN plus invalid exception", FUNC(acosh) (-1.1L), nan_value, 0, 0, INVALID_EXCEPTION);
+
+ check_float ("acosh (1) == 0", FUNC(acosh) (1), 0, 0, 0, 0);
+ check_float ("acosh (7) == 2.633915793849633417250092694615937", FUNC(acosh) (7), 2.633915793849633417250092694615937L, DELTA16, 0, 0);
+
+ print_max_error ("acosh", DELTAacosh, 0);
+}
+
+static void
+asin_test (void)
+{
+ errno = 0;
+ FUNC(asin) (0);
+ if (errno == ENOSYS)
+ /* Function not implemented. */
+ return;
+
+ init_max_error ();
+
+ check_float ("asin (inf) == NaN plus invalid exception", FUNC(asin) (plus_infty), nan_value, 0, 0, INVALID_EXCEPTION);
+ check_float ("asin (-inf) == NaN plus invalid exception", FUNC(asin) (minus_infty), nan_value, 0, 0, INVALID_EXCEPTION);
+ check_float ("asin (NaN) == NaN", FUNC(asin) (nan_value), nan_value, 0, 0, 0);
+
+ /* asin x == NaN plus invalid exception for |x| > 1. */
+ check_float ("asin (1.1) == NaN plus invalid exception", FUNC(asin) (1.1L), nan_value, 0, 0, INVALID_EXCEPTION);
+ check_float ("asin (-1.1) == NaN plus invalid exception", FUNC(asin) (-1.1L), nan_value, 0, 0, INVALID_EXCEPTION);
+
+ check_float ("asin (0) == 0", FUNC(asin) (0), 0, 0, 0, 0);
+ check_float ("asin (-0) == -0", FUNC(asin) (minus_zero), minus_zero, 0, 0, 0);
+ check_float ("asin (0.5) == pi/6", FUNC(asin) (0.5), M_PI_6l, DELTA24, 0, 0);
+ check_float ("asin (-0.5) == -pi/6", FUNC(asin) (-0.5), -M_PI_6l, DELTA25, 0, 0);
+ check_float ("asin (1.0) == pi/2", FUNC(asin) (1.0), M_PI_2l, DELTA26, 0, 0);
+ check_float ("asin (-1.0) == -pi/2", FUNC(asin) (-1.0), -M_PI_2l, DELTA27, 0, 0);
+ check_float ("asin (0.7) == 0.77539749661075306374035335271498708", FUNC(asin) (0.7L), 0.77539749661075306374035335271498708L, DELTA28, 0, 0);
+
+ print_max_error ("asin", DELTAasin, 0);
+}
+
+static void
+asinh_test (void)
+{
+ errno = 0;
+ FUNC(asinh) (0.7L);
+ if (errno == ENOSYS)
+ /* Function not implemented. */
+ return;
+
+ init_max_error ();
+
+ check_float ("asinh (0) == 0", FUNC(asinh) (0), 0, 0, 0, 0);
+ check_float ("asinh (-0) == -0", FUNC(asinh) (minus_zero), minus_zero, 0, 0, 0);
+#ifndef TEST_INLINE
+ check_float ("asinh (inf) == inf", FUNC(asinh) (plus_infty), plus_infty, 0, 0, 0);
+ check_float ("asinh (-inf) == -inf", FUNC(asinh) (minus_infty), minus_infty, 0, 0, 0);
+#endif
+ check_float ("asinh (NaN) == NaN", FUNC(asinh) (nan_value), nan_value, 0, 0, 0);
+ check_float ("asinh (0.7) == 0.652666566082355786", FUNC(asinh) (0.7L), 0.652666566082355786L, DELTA34, 0, 0);
+
+ print_max_error ("asinh", DELTAasinh, 0);
+}
+
+static void
+atan_test (void)
+{
+ errno = 0;
+ FUNC(atan) (0);
+ if (errno == ENOSYS)
+ /* Function not implemented. */
+ return;
+
+ init_max_error ();
+
+ check_float ("atan (0) == 0", FUNC(atan) (0), 0, 0, 0, 0);
+ check_float ("atan (-0) == -0", FUNC(atan) (minus_zero), minus_zero, 0, 0, 0);
+
+ check_float ("atan (inf) == pi/2", FUNC(atan) (plus_infty), M_PI_2l, 0, 0, 0);
+ check_float ("atan (-inf) == -pi/2", FUNC(atan) (minus_infty), -M_PI_2l, 0, 0, 0);
+ check_float ("atan (NaN) == NaN", FUNC(atan) (nan_value), nan_value, 0, 0, 0);
+
+ check_float ("atan (1) == pi/4", FUNC(atan) (1), M_PI_4l, 0, 0, 0);
+ check_float ("atan (-1) == -pi/4", FUNC(atan) (-1), -M_PI_4l, 0, 0, 0);
+
+ check_float ("atan (0.7) == 0.61072596438920861654375887649023613", FUNC(atan) (0.7L), 0.61072596438920861654375887649023613L, DELTA42, 0, 0);
+
+ print_max_error ("atan", DELTAatan, 0);
+}
+
+
+
+static void
+atanh_test (void)
+{
+ errno = 0;
+ FUNC(atanh) (0.7L);
+ if (errno == ENOSYS)
+ /* Function not implemented. */
+ return;
+
+ init_max_error ();
+
+
+ check_float ("atanh (0) == 0", FUNC(atanh) (0), 0, 0, 0, 0);
+ check_float ("atanh (-0) == -0", FUNC(atanh) (minus_zero), minus_zero, 0, 0, 0);
+
+ check_float ("atanh (1) == inf plus division by zero exception", FUNC(atanh) (1), plus_infty, 0, 0, DIVIDE_BY_ZERO_EXCEPTION);
+ check_float ("atanh (-1) == -inf plus division by zero exception", FUNC(atanh) (-1), minus_infty, 0, 0, DIVIDE_BY_ZERO_EXCEPTION);
+ check_float ("atanh (NaN) == NaN", FUNC(atanh) (nan_value), nan_value, 0, 0, 0);
+
+ /* atanh (x) == NaN plus invalid exception if |x| > 1. */
+ check_float ("atanh (1.1) == NaN plus invalid exception", FUNC(atanh) (1.1L), nan_value, 0, 0, INVALID_EXCEPTION);
+ check_float ("atanh (-1.1) == NaN plus invalid exception", FUNC(atanh) (-1.1L), nan_value, 0, 0, INVALID_EXCEPTION);
+
+ check_float ("atanh (0.7) == 0.8673005276940531944", FUNC(atanh) (0.7L), 0.8673005276940531944L, DELTA50, 0, 0);
+
+ print_max_error ("atanh", DELTAatanh, 0);
+}
+
+static void
+atan2_test (void)
+{
+ errno = 0;
+ FUNC(atan2) (-0, 1);
+ if (errno == ENOSYS)
+ /* Function not implemented. */
+ return;
+
+ init_max_error ();
+
+ /* atan2 (0,x) == 0 for x > 0. */
+ check_float ("atan2 (0, 1) == 0", FUNC(atan2) (0, 1), 0, 0, 0, 0);
+
+ /* atan2 (-0,x) == -0 for x > 0. */
+ check_float ("atan2 (-0, 1) == -0", FUNC(atan2) (minus_zero, 1), minus_zero, 0, 0, 0);
+
+ check_float ("atan2 (0, 0) == 0", FUNC(atan2) (0, 0), 0, 0, 0, 0);
+ check_float ("atan2 (-0, 0) == -0", FUNC(atan2) (minus_zero, 0), minus_zero, 0, 0, 0);
+
+ /* atan2 (+0,x) == +pi for x < 0. */
+ check_float ("atan2 (0, -1) == pi", FUNC(atan2) (0, -1), M_PIl, 0, 0, 0);
+
+ /* atan2 (-0,x) == -pi for x < 0. */
+ check_float ("atan2 (-0, -1) == -pi", FUNC(atan2) (minus_zero, -1), -M_PIl, 0, 0, 0);
+
+ check_float ("atan2 (0, -0) == pi", FUNC(atan2) (0, minus_zero), M_PIl, 0, 0, 0);
+ check_float ("atan2 (-0, -0) == -pi", FUNC(atan2) (minus_zero, minus_zero), -M_PIl, 0, 0, 0);
+
+ /* atan2 (y,+0) == pi/2 for y > 0. */
+ check_float ("atan2 (1, 0) == pi/2", FUNC(atan2) (1, 0), M_PI_2l, 0, 0, 0);
+
+ /* atan2 (y,-0) == pi/2 for y > 0. */
+ check_float ("atan2 (1, -0) == pi/2", FUNC(atan2) (1, minus_zero), M_PI_2l, 0, 0, 0);
+
+ /* atan2 (y,+0) == -pi/2 for y < 0. */
+ check_float ("atan2 (-1, 0) == -pi/2", FUNC(atan2) (-1, 0), -M_PI_2l, 0, 0, 0);
+
+ /* atan2 (y,-0) == -pi/2 for y < 0. */
+ check_float ("atan2 (-1, -0) == -pi/2", FUNC(atan2) (-1, minus_zero), -M_PI_2l, 0, 0, 0);
+
+ /* atan2 (y,inf) == +0 for finite y > 0. */
+ check_float ("atan2 (1, inf) == 0", FUNC(atan2) (1, plus_infty), 0, 0, 0, 0);
+
+ /* atan2 (y,inf) == -0 for finite y < 0. */
+ check_float ("atan2 (-1, inf) == -0", FUNC(atan2) (-1, plus_infty), minus_zero, 0, 0, 0);
+
+ /* atan2(+inf, x) == pi/2 for finite x. */
+ check_float ("atan2 (inf, -1) == pi/2", FUNC(atan2) (plus_infty, -1), M_PI_2l, 0, 0, 0);
+
+ /* atan2(-inf, x) == -pi/2 for finite x. */
+ check_float ("atan2 (-inf, 1) == -pi/2", FUNC(atan2) (minus_infty, 1), -M_PI_2l, 0, 0, 0);
+
+ /* atan2 (y,-inf) == +pi for finite y > 0. */
+ check_float ("atan2 (1, -inf) == pi", FUNC(atan2) (1, minus_infty), M_PIl, 0, 0, 0);
+
+ /* atan2 (y,-inf) == -pi for finite y < 0. */
+ check_float ("atan2 (-1, -inf) == -pi", FUNC(atan2) (-1, minus_infty), -M_PIl, 0, 0, 0);
+
+ check_float ("atan2 (inf, inf) == pi/4", FUNC(atan2) (plus_infty, plus_infty), M_PI_4l, 0, 0, 0);
+ check_float ("atan2 (-inf, inf) == -pi/4", FUNC(atan2) (minus_infty, plus_infty), -M_PI_4l, 0, 0, 0);
+ check_float ("atan2 (inf, -inf) == 3/4 pi", FUNC(atan2) (plus_infty, minus_infty), M_PI_34l, 0, 0, 0);
+ check_float ("atan2 (-inf, -inf) == -3/4 pi", FUNC(atan2) (minus_infty, minus_infty), -M_PI_34l, 0, 0, 0);
+ check_float ("atan2 (NaN, NaN) == NaN", FUNC(atan2) (nan_value, nan_value), nan_value, 0, 0, 0);
+
+ check_float ("atan2 (0.7, 1) == 0.61072596438920861654375887649023613", FUNC(atan2) (0.7L, 1), 0.61072596438920861654375887649023613L, DELTA74, 0, 0);
+ check_float ("atan2 (-0.7, 1.0) == -0.61072596438920861654375887649023613", FUNC(atan2) (-0.7L, 1.0L), -0.61072596438920861654375887649023613L, 0, 0, 0);
+ check_float ("atan2 (0.7, -1.0) == 2.530866689200584621918884506789267", FUNC(atan2) (0.7L, -1.0L), 2.530866689200584621918884506789267L, 0, 0, 0);
+ check_float ("atan2 (-0.7, -1.0) == -2.530866689200584621918884506789267", FUNC(atan2) (-0.7L, -1.0L), -2.530866689200584621918884506789267L, 0, 0, 0);
+ check_float ("atan2 (0.4, 0.0003) == 1.5700463269355215717704032607580829", FUNC(atan2) (0.4L, 0.0003L), 1.5700463269355215717704032607580829L, DELTA78, 0, 0);
+ check_float ("atan2 (1.4, -0.93) == 2.1571487668237843754887415992772736", FUNC(atan2) (1.4L, -0.93L), 2.1571487668237843754887415992772736L, 0, 0, 0);
+
+ print_max_error ("atan2", DELTAatan2, 0);
+}
+
+
+#if 0 /* XXX scp XXX */
+static void
+cabs_test (void)
+{
+ errno = 0;
+ FUNC(cabs) (BUILD_COMPLEX (0.7L, 12.4L));
+ if (errno == ENOSYS)
+ /* Function not implemented. */
+ return;
+
+ init_max_error ();
+
+ /* cabs (x + iy) is specified as hypot (x,y) */
+
+ /* cabs (+inf + i x) == +inf. */
+ check_float ("cabs (inf + 1.0 i) == inf", FUNC(cabs) (BUILD_COMPLEX (plus_infty, 1.0)), plus_infty, 0, 0, 0);
+ /* cabs (-inf + i x) == +inf. */
+ check_float ("cabs (-inf + 1.0 i) == inf", FUNC(cabs) (BUILD_COMPLEX (minus_infty, 1.0)), plus_infty, 0, 0, 0);
+
+ check_float ("cabs (-inf + NaN i) == inf", FUNC(cabs) (BUILD_COMPLEX (minus_infty, nan_value)), plus_infty, 0, 0, 0);
+ check_float ("cabs (-inf + NaN i) == inf", FUNC(cabs) (BUILD_COMPLEX (minus_infty, nan_value)), plus_infty, 0, 0, 0);
+
+ check_float ("cabs (NaN + NaN i) == NaN", FUNC(cabs) (BUILD_COMPLEX (nan_value, nan_value)), nan_value, 0, 0, 0);
+
+ /* cabs (x,y) == cabs (y,x). */
+ check_float ("cabs (0.7 + 12.4 i) == 12.419742348374220601176836866763271", FUNC(cabs) (BUILD_COMPLEX (0.7L, 12.4L)), 12.419742348374220601176836866763271L, DELTA85, 0, 0);
+ /* cabs (x,y) == cabs (-x,y). */
+ check_float ("cabs (-12.4 + 0.7 i) == 12.419742348374220601176836866763271", FUNC(cabs) (BUILD_COMPLEX (-12.4L, 0.7L)), 12.419742348374220601176836866763271L, DELTA86, 0, 0);
+ /* cabs (x,y) == cabs (-y,x). */
+ check_float ("cabs (-0.7 + 12.4 i) == 12.419742348374220601176836866763271", FUNC(cabs) (BUILD_COMPLEX (-0.7L, 12.4L)), 12.419742348374220601176836866763271L, DELTA87, 0, 0);
+ /* cabs (x,y) == cabs (-x,-y). */
+ check_float ("cabs (-12.4 - 0.7 i) == 12.419742348374220601176836866763271", FUNC(cabs) (BUILD_COMPLEX (-12.4L, -0.7L)), 12.419742348374220601176836866763271L, DELTA88, 0, 0);
+ /* cabs (x,y) == cabs (-y,-x). */
+ check_float ("cabs (-0.7 - 12.4 i) == 12.419742348374220601176836866763271", FUNC(cabs) (BUILD_COMPLEX (-0.7L, -12.4L)), 12.419742348374220601176836866763271L, DELTA89, 0, 0);
+ /* cabs (x,0) == fabs (x). */
+ check_float ("cabs (-0.7 + 0 i) == 0.7", FUNC(cabs) (BUILD_COMPLEX (-0.7L, 0)), 0.7L, 0, 0, 0);
+ check_float ("cabs (0.7 + 0 i) == 0.7", FUNC(cabs) (BUILD_COMPLEX (0.7L, 0)), 0.7L, 0, 0, 0);
+ check_float ("cabs (-1.0 + 0 i) == 1.0", FUNC(cabs) (BUILD_COMPLEX (-1.0L, 0)), 1.0L, 0, 0, 0);
+ check_float ("cabs (1.0 + 0 i) == 1.0", FUNC(cabs) (BUILD_COMPLEX (1.0L, 0)), 1.0L, 0, 0, 0);
+ check_float ("cabs (-5.7e7 + 0 i) == 5.7e7", FUNC(cabs) (BUILD_COMPLEX (-5.7e7L, 0)), 5.7e7L, 0, 0, 0);
+ check_float ("cabs (5.7e7 + 0 i) == 5.7e7", FUNC(cabs) (BUILD_COMPLEX (5.7e7L, 0)), 5.7e7L, 0, 0, 0);
+
+ check_float ("cabs (0.7 + 1.2 i) == 1.3892443989449804508432547041028554", FUNC(cabs) (BUILD_COMPLEX (0.7L, 1.2L)), 1.3892443989449804508432547041028554L, DELTA96, 0, 0);
+
+ print_max_error ("cabs", DELTAcabs, 0);
+}
+
+static void
+cacos_test (void)
+{
+ errno = 0;
+ FUNC(cacos) (BUILD_COMPLEX (0.7L, 1.2L));
+ if (errno == ENOSYS)
+ /* Function not implemented. */
+ return;
+
+ init_max_error ();
+
+
+ check_complex ("cacos (0 + 0 i) == pi/2 - 0 i", FUNC(cacos) (BUILD_COMPLEX (0, 0)), BUILD_COMPLEX (M_PI_2l, minus_zero), 0, 0, 0);
+ check_complex ("cacos (-0 + 0 i) == pi/2 - 0 i", FUNC(cacos) (BUILD_COMPLEX (minus_zero, 0)), BUILD_COMPLEX (M_PI_2l, minus_zero), 0, 0, 0);
+ check_complex ("cacos (-0 - 0 i) == pi/2 + 0.0 i", FUNC(cacos) (BUILD_COMPLEX (minus_zero, minus_zero)), BUILD_COMPLEX (M_PI_2l, 0.0), 0, 0, 0);
+ check_complex ("cacos (0 - 0 i) == pi/2 + 0.0 i", FUNC(cacos) (BUILD_COMPLEX (0, minus_zero)), BUILD_COMPLEX (M_PI_2l, 0.0), 0, 0, 0);
+
+ check_complex ("cacos (-inf + inf i) == 3/4 pi - inf i", FUNC(cacos) (BUILD_COMPLEX (minus_infty, plus_infty)), BUILD_COMPLEX (M_PI_34l, minus_infty), 0, 0, 0);
+ check_complex ("cacos (-inf - inf i) == 3/4 pi + inf i", FUNC(cacos) (BUILD_COMPLEX (minus_infty, minus_infty)), BUILD_COMPLEX (M_PI_34l, plus_infty), 0, 0, 0);
+
+ check_complex ("cacos (inf + inf i) == pi/4 - inf i", FUNC(cacos) (BUILD_COMPLEX (plus_infty, plus_infty)), BUILD_COMPLEX (M_PI_4l, minus_infty), 0, 0, 0);
+ check_complex ("cacos (inf - inf i) == pi/4 + inf i", FUNC(cacos) (BUILD_COMPLEX (plus_infty, minus_infty)), BUILD_COMPLEX (M_PI_4l, plus_infty), 0, 0, 0);
+
+ check_complex ("cacos (-10.0 + inf i) == pi/2 - inf i", FUNC(cacos) (BUILD_COMPLEX (-10.0, plus_infty)), BUILD_COMPLEX (M_PI_2l, minus_infty), 0, 0, 0);
+ check_complex ("cacos (-10.0 - inf i) == pi/2 + inf i", FUNC(cacos) (BUILD_COMPLEX (-10.0, minus_infty)), BUILD_COMPLEX (M_PI_2l, plus_infty), 0, 0, 0);
+ check_complex ("cacos (0 + inf i) == pi/2 - inf i", FUNC(cacos) (BUILD_COMPLEX (0, plus_infty)), BUILD_COMPLEX (M_PI_2l, minus_infty), 0, 0, 0);
+ check_complex ("cacos (0 - inf i) == pi/2 + inf i", FUNC(cacos) (BUILD_COMPLEX (0, minus_infty)), BUILD_COMPLEX (M_PI_2l, plus_infty), 0, 0, 0);
+ check_complex ("cacos (0.1 + inf i) == pi/2 - inf i", FUNC(cacos) (BUILD_COMPLEX (0.1L, plus_infty)), BUILD_COMPLEX (M_PI_2l, minus_infty), 0, 0, 0);
+ check_complex ("cacos (0.1 - inf i) == pi/2 + inf i", FUNC(cacos) (BUILD_COMPLEX (0.1L, minus_infty)), BUILD_COMPLEX (M_PI_2l, plus_infty), 0, 0, 0);
+
+ check_complex ("cacos (-inf + 0 i) == pi - inf i", FUNC(cacos) (BUILD_COMPLEX (minus_infty, 0)), BUILD_COMPLEX (M_PIl, minus_infty), 0, 0, 0);
+ check_complex ("cacos (-inf - 0 i) == pi + inf i", FUNC(cacos) (BUILD_COMPLEX (minus_infty, minus_zero)), BUILD_COMPLEX (M_PIl, plus_infty), 0, 0, 0);
+ check_complex ("cacos (-inf + 100 i) == pi - inf i", FUNC(cacos) (BUILD_COMPLEX (minus_infty, 100)), BUILD_COMPLEX (M_PIl, minus_infty), 0, 0, 0);
+ check_complex ("cacos (-inf - 100 i) == pi + inf i", FUNC(cacos) (BUILD_COMPLEX (minus_infty, -100)), BUILD_COMPLEX (M_PIl, plus_infty), 0, 0, 0);
+
+ check_complex ("cacos (inf + 0 i) == 0.0 - inf i", FUNC(cacos) (BUILD_COMPLEX (plus_infty, 0)), BUILD_COMPLEX (0.0, minus_infty), 0, 0, 0);
+ check_complex ("cacos (inf - 0 i) == 0.0 + inf i", FUNC(cacos) (BUILD_COMPLEX (plus_infty, minus_zero)), BUILD_COMPLEX (0.0, plus_infty), 0, 0, 0);
+ check_complex ("cacos (inf + 0.5 i) == 0.0 - inf i", FUNC(cacos) (BUILD_COMPLEX (plus_infty, 0.5)), BUILD_COMPLEX (0.0, minus_infty), 0, 0, 0);
+ check_complex ("cacos (inf - 0.5 i) == 0.0 + inf i", FUNC(cacos) (BUILD_COMPLEX (plus_infty, -0.5)), BUILD_COMPLEX (0.0, plus_infty), 0, 0, 0);
+
+ check_complex ("cacos (inf + NaN i) == NaN + inf i plus sign of zero/inf not specified", FUNC(cacos) (BUILD_COMPLEX (plus_infty, nan_value)), BUILD_COMPLEX (nan_value, plus_infty), 0, 0, IGNORE_ZERO_INF_SIGN);
+ check_complex ("cacos (-inf + NaN i) == NaN + inf i plus sign of zero/inf not specified", FUNC(cacos) (BUILD_COMPLEX (minus_infty, nan_value)), BUILD_COMPLEX (nan_value, plus_infty), 0, 0, IGNORE_ZERO_INF_SIGN);
+
+ check_complex ("cacos (0 + NaN i) == pi/2 + NaN i", FUNC(cacos) (BUILD_COMPLEX (0, nan_value)), BUILD_COMPLEX (M_PI_2l, nan_value), 0, 0, 0);
+ check_complex ("cacos (-0 + NaN i) == pi/2 + NaN i", FUNC(cacos) (BUILD_COMPLEX (minus_zero, nan_value)), BUILD_COMPLEX (M_PI_2l, nan_value), 0, 0, 0);
+
+ check_complex ("cacos (NaN + inf i) == NaN - inf i", FUNC(cacos) (BUILD_COMPLEX (nan_value, plus_infty)), BUILD_COMPLEX (nan_value, minus_infty), 0, 0, 0);
+ check_complex ("cacos (NaN - inf i) == NaN + inf i", FUNC(cacos) (BUILD_COMPLEX (nan_value, minus_infty)), BUILD_COMPLEX (nan_value, plus_infty), 0, 0, 0);
+
+ check_complex ("cacos (10.5 + NaN i) == NaN + NaN i plus invalid exception allowed", FUNC(cacos) (BUILD_COMPLEX (10.5, nan_value)), BUILD_COMPLEX (nan_value, nan_value), 0, 0, INVALID_EXCEPTION_OK);
+ check_complex ("cacos (-10.5 + NaN i) == NaN + NaN i plus invalid exception allowed", FUNC(cacos) (BUILD_COMPLEX (-10.5, nan_value)), BUILD_COMPLEX (nan_value, nan_value), 0, 0, INVALID_EXCEPTION_OK);
+
+ check_complex ("cacos (NaN + 0.75 i) == NaN + NaN i plus invalid exception allowed", FUNC(cacos) (BUILD_COMPLEX (nan_value, 0.75)), BUILD_COMPLEX (nan_value, nan_value), 0, 0, INVALID_EXCEPTION_OK);
+ check_complex ("cacos (NaN - 0.75 i) == NaN + NaN i plus invalid exception allowed", FUNC(cacos) (BUILD_COMPLEX (nan_value, -0.75)), BUILD_COMPLEX (nan_value, nan_value), 0, 0, INVALID_EXCEPTION_OK);
+
+ check_complex ("cacos (NaN + NaN i) == NaN + NaN i", FUNC(cacos) (BUILD_COMPLEX (nan_value, nan_value)), BUILD_COMPLEX (nan_value, nan_value), 0, 0, 0);
+
+ check_complex ("cacos (0.7 + 1.2 i) == 1.1351827477151551088992008271819053 - 1.0927647857577371459105272080819308 i", FUNC(cacos) (BUILD_COMPLEX (0.7L, 1.2L)), BUILD_COMPLEX (1.1351827477151551088992008271819053L, -1.0927647857577371459105272080819308L), DELTA130, 0, 0);
+ check_complex ("cacos (-2 - 3 i) == 2.1414491111159960199416055713254211 + 1.9833870299165354323470769028940395 i", FUNC(cacos) (BUILD_COMPLEX (-2, -3)), BUILD_COMPLEX (2.1414491111159960199416055713254211L, 1.9833870299165354323470769028940395L), DELTA131, 0, 0);
+
+ print_complex_max_error ("cacos", DELTAcacos, 0);
+}
+
+
+static void
+cacosh_test (void)
+{
+ errno = 0;
+ FUNC(cacosh) (BUILD_COMPLEX (0.7L, 1.2L));
+ if (errno == ENOSYS)
+ /* Function not implemented. */
+ return;
+
+ init_max_error ();
+
+
+ check_complex ("cacosh (0 + 0 i) == 0.0 + pi/2 i", FUNC(cacosh) (BUILD_COMPLEX (0, 0)), BUILD_COMPLEX (0.0, M_PI_2l), 0, 0, 0);
+ check_complex ("cacosh (-0 + 0 i) == 0.0 + pi/2 i", FUNC(cacosh) (BUILD_COMPLEX (minus_zero, 0)), BUILD_COMPLEX (0.0, M_PI_2l), 0, 0, 0);
+ check_complex ("cacosh (0 - 0 i) == 0.0 - pi/2 i", FUNC(cacosh) (BUILD_COMPLEX (0, minus_zero)), BUILD_COMPLEX (0.0, -M_PI_2l), 0, 0, 0);
+ check_complex ("cacosh (-0 - 0 i) == 0.0 - pi/2 i", FUNC(cacosh) (BUILD_COMPLEX (minus_zero, minus_zero)), BUILD_COMPLEX (0.0, -M_PI_2l), 0, 0, 0);
+ check_complex ("cacosh (-inf + inf i) == inf + 3/4 pi i", FUNC(cacosh) (BUILD_COMPLEX (minus_infty, plus_infty)), BUILD_COMPLEX (plus_infty, M_PI_34l), 0, 0, 0);
+ check_complex ("cacosh (-inf - inf i) == inf - 3/4 pi i", FUNC(cacosh) (BUILD_COMPLEX (minus_infty, minus_infty)), BUILD_COMPLEX (plus_infty, -M_PI_34l), 0, 0, 0);
+
+ check_complex ("cacosh (inf + inf i) == inf + pi/4 i", FUNC(cacosh) (BUILD_COMPLEX (plus_infty, plus_infty)), BUILD_COMPLEX (plus_infty, M_PI_4l), 0, 0, 0);
+ check_complex ("cacosh (inf - inf i) == inf - pi/4 i", FUNC(cacosh) (BUILD_COMPLEX (plus_infty, minus_infty)), BUILD_COMPLEX (plus_infty, -M_PI_4l), 0, 0, 0);
+
+ check_complex ("cacosh (-10.0 + inf i) == inf + pi/2 i", FUNC(cacosh) (BUILD_COMPLEX (-10.0, plus_infty)), BUILD_COMPLEX (plus_infty, M_PI_2l), 0, 0, 0);
+ check_complex ("cacosh (-10.0 - inf i) == inf - pi/2 i", FUNC(cacosh) (BUILD_COMPLEX (-10.0, minus_infty)), BUILD_COMPLEX (plus_infty, -M_PI_2l), 0, 0, 0);
+ check_complex ("cacosh (0 + inf i) == inf + pi/2 i", FUNC(cacosh) (BUILD_COMPLEX (0, plus_infty)), BUILD_COMPLEX (plus_infty, M_PI_2l), 0, 0, 0);
+ check_complex ("cacosh (0 - inf i) == inf - pi/2 i", FUNC(cacosh) (BUILD_COMPLEX (0, minus_infty)), BUILD_COMPLEX (plus_infty, -M_PI_2l), 0, 0, 0);
+ check_complex ("cacosh (0.1 + inf i) == inf + pi/2 i", FUNC(cacosh) (BUILD_COMPLEX (0.1L, plus_infty)), BUILD_COMPLEX (plus_infty, M_PI_2l), 0, 0, 0);
+ check_complex ("cacosh (0.1 - inf i) == inf - pi/2 i", FUNC(cacosh) (BUILD_COMPLEX (0.1L, minus_infty)), BUILD_COMPLEX (plus_infty, -M_PI_2l), 0, 0, 0);
+
+ check_complex ("cacosh (-inf + 0 i) == inf + pi i", FUNC(cacosh) (BUILD_COMPLEX (minus_infty, 0)), BUILD_COMPLEX (plus_infty, M_PIl), 0, 0, 0);
+ check_complex ("cacosh (-inf - 0 i) == inf - pi i", FUNC(cacosh) (BUILD_COMPLEX (minus_infty, minus_zero)), BUILD_COMPLEX (plus_infty, -M_PIl), 0, 0, 0);
+ check_complex ("cacosh (-inf + 100 i) == inf + pi i", FUNC(cacosh) (BUILD_COMPLEX (minus_infty, 100)), BUILD_COMPLEX (plus_infty, M_PIl), 0, 0, 0);
+ check_complex ("cacosh (-inf - 100 i) == inf - pi i", FUNC(cacosh) (BUILD_COMPLEX (minus_infty, -100)), BUILD_COMPLEX (plus_infty, -M_PIl), 0, 0, 0);
+
+ check_complex ("cacosh (inf + 0 i) == inf + 0.0 i", FUNC(cacosh) (BUILD_COMPLEX (plus_infty, 0)), BUILD_COMPLEX (plus_infty, 0.0), 0, 0, 0);
+ check_complex ("cacosh (inf - 0 i) == inf - 0 i", FUNC(cacosh) (BUILD_COMPLEX (plus_infty, minus_zero)), BUILD_COMPLEX (plus_infty, minus_zero), 0, 0, 0);
+ check_complex ("cacosh (inf + 0.5 i) == inf + 0.0 i", FUNC(cacosh) (BUILD_COMPLEX (plus_infty, 0.5)), BUILD_COMPLEX (plus_infty, 0.0), 0, 0, 0);
+ check_complex ("cacosh (inf - 0.5 i) == inf - 0 i", FUNC(cacosh) (BUILD_COMPLEX (plus_infty, -0.5)), BUILD_COMPLEX (plus_infty, minus_zero), 0, 0, 0);
+
+ check_complex ("cacosh (inf + NaN i) == inf + NaN i", FUNC(cacosh) (BUILD_COMPLEX (plus_infty, nan_value)), BUILD_COMPLEX (plus_infty, nan_value), 0, 0, 0);
+ check_complex ("cacosh (-inf + NaN i) == inf + NaN i", FUNC(cacosh) (BUILD_COMPLEX (minus_infty, nan_value)), BUILD_COMPLEX (plus_infty, nan_value), 0, 0, 0);
+
+ check_complex ("cacosh (0 + NaN i) == NaN + NaN i", FUNC(cacosh) (BUILD_COMPLEX (0, nan_value)), BUILD_COMPLEX (nan_value, nan_value), 0, 0, 0);
+ check_complex ("cacosh (-0 + NaN i) == NaN + NaN i", FUNC(cacosh) (BUILD_COMPLEX (minus_zero, nan_value)), BUILD_COMPLEX (nan_value, nan_value), 0, 0, 0);
+
+ check_complex ("cacosh (NaN + inf i) == inf + NaN i", FUNC(cacosh) (BUILD_COMPLEX (nan_value, plus_infty)), BUILD_COMPLEX (plus_infty, nan_value), 0, 0, 0);
+ check_complex ("cacosh (NaN - inf i) == inf + NaN i", FUNC(cacosh) (BUILD_COMPLEX (nan_value, minus_infty)), BUILD_COMPLEX (plus_infty, nan_value), 0, 0, 0);
+
+ check_complex ("cacosh (10.5 + NaN i) == NaN + NaN i plus invalid exception allowed", FUNC(cacosh) (BUILD_COMPLEX (10.5, nan_value)), BUILD_COMPLEX (nan_value, nan_value), 0, 0, INVALID_EXCEPTION_OK);
+ check_complex ("cacosh (-10.5 + NaN i) == NaN + NaN i plus invalid exception allowed", FUNC(cacosh) (BUILD_COMPLEX (-10.5, nan_value)), BUILD_COMPLEX (nan_value, nan_value), 0, 0, INVALID_EXCEPTION_OK);
+
+ check_complex ("cacosh (NaN + 0.75 i) == NaN + NaN i plus invalid exception allowed", FUNC(cacosh) (BUILD_COMPLEX (nan_value, 0.75)), BUILD_COMPLEX (nan_value, nan_value), 0, 0, INVALID_EXCEPTION_OK);
+ check_complex ("cacosh (NaN - 0.75 i) == NaN + NaN i plus invalid exception allowed", FUNC(cacosh) (BUILD_COMPLEX (nan_value, -0.75)), BUILD_COMPLEX (nan_value, nan_value), 0, 0, INVALID_EXCEPTION_OK);
+
+ check_complex ("cacosh (NaN + NaN i) == NaN + NaN i", FUNC(cacosh) (BUILD_COMPLEX (nan_value, nan_value)), BUILD_COMPLEX (nan_value, nan_value), 0, 0, 0);
+
+ check_complex ("cacosh (0.7 + 1.2 i) == 1.0927647857577371459105272080819308 + 1.1351827477151551088992008271819053 i", FUNC(cacosh) (BUILD_COMPLEX (0.7L, 1.2L)), BUILD_COMPLEX (1.0927647857577371459105272080819308L, 1.1351827477151551088992008271819053L), DELTA165, 0, 0);
+ check_complex ("cacosh (-2 - 3 i) == -1.9833870299165354323470769028940395 + 2.1414491111159960199416055713254211 i", FUNC(cacosh) (BUILD_COMPLEX (-2, -3)), BUILD_COMPLEX (-1.9833870299165354323470769028940395L, 2.1414491111159960199416055713254211L), DELTA166, 0, 0);
+
+ print_complex_max_error ("cacosh", DELTAcacosh, 0);
+}
+
+static void
+carg_test (void)
+{
+ init_max_error ();
+
+ /* carg (x + iy) is specified as atan2 (y, x) */
+
+ /* carg (x + i 0) == 0 for x > 0. */
+ check_float ("carg (2.0 + 0 i) == 0", FUNC(carg) (BUILD_COMPLEX (2.0, 0)), 0, 0, 0, 0);
+ /* carg (x - i 0) == -0 for x > 0. */
+ check_float ("carg (2.0 - 0 i) == -0", FUNC(carg) (BUILD_COMPLEX (2.0, minus_zero)), minus_zero, 0, 0, 0);
+
+ check_float ("carg (0 + 0 i) == 0", FUNC(carg) (BUILD_COMPLEX (0, 0)), 0, 0, 0, 0);
+ check_float ("carg (0 - 0 i) == -0", FUNC(carg) (BUILD_COMPLEX (0, minus_zero)), minus_zero, 0, 0, 0);
+
+ /* carg (x + i 0) == +pi for x < 0. */
+ check_float ("carg (-2.0 + 0 i) == pi", FUNC(carg) (BUILD_COMPLEX (-2.0, 0)), M_PIl, 0, 0, 0);
+
+ /* carg (x - i 0) == -pi for x < 0. */
+ check_float ("carg (-2.0 - 0 i) == -pi", FUNC(carg) (BUILD_COMPLEX (-2.0, minus_zero)), -M_PIl, 0, 0, 0);
+
+ check_float ("carg (-0 + 0 i) == pi", FUNC(carg) (BUILD_COMPLEX (minus_zero, 0)), M_PIl, 0, 0, 0);
+ check_float ("carg (-0 - 0 i) == -pi", FUNC(carg) (BUILD_COMPLEX (minus_zero, minus_zero)), -M_PIl, 0, 0, 0);
+
+ /* carg (+0 + i y) == pi/2 for y > 0. */
+ check_float ("carg (0 + 2.0 i) == pi/2", FUNC(carg) (BUILD_COMPLEX (0, 2.0)), M_PI_2l, 0, 0, 0);
+
+ /* carg (-0 + i y) == pi/2 for y > 0. */
+ check_float ("carg (-0 + 2.0 i) == pi/2", FUNC(carg) (BUILD_COMPLEX (minus_zero, 2.0)), M_PI_2l, 0, 0, 0);
+
+ /* carg (+0 + i y) == -pi/2 for y < 0. */
+ check_float ("carg (0 - 2.0 i) == -pi/2", FUNC(carg) (BUILD_COMPLEX (0, -2.0)), -M_PI_2l, 0, 0, 0);
+
+ /* carg (-0 + i y) == -pi/2 for y < 0. */
+ check_float ("carg (-0 - 2.0 i) == -pi/2", FUNC(carg) (BUILD_COMPLEX (minus_zero, -2.0)), -M_PI_2l, 0, 0, 0);
+
+ /* carg (inf + i y) == +0 for finite y > 0. */
+ check_float ("carg (inf + 2.0 i) == 0", FUNC(carg) (BUILD_COMPLEX (plus_infty, 2.0)), 0, 0, 0, 0);
+
+ /* carg (inf + i y) == -0 for finite y < 0. */
+ check_float ("carg (inf - 2.0 i) == -0", FUNC(carg) (BUILD_COMPLEX (plus_infty, -2.0)), minus_zero, 0, 0, 0);
+
+ /* carg(x + i inf) == pi/2 for finite x. */
+ check_float ("carg (10.0 + inf i) == pi/2", FUNC(carg) (BUILD_COMPLEX (10.0, plus_infty)), M_PI_2l, 0, 0, 0);
+
+ /* carg(x - i inf) == -pi/2 for finite x. */
+ check_float ("carg (10.0 - inf i) == -pi/2", FUNC(carg) (BUILD_COMPLEX (10.0, minus_infty)), -M_PI_2l, 0, 0, 0);
+
+ /* carg (-inf + i y) == +pi for finite y > 0. */
+ check_float ("carg (-inf + 10.0 i) == pi", FUNC(carg) (BUILD_COMPLEX (minus_infty, 10.0)), M_PIl, 0, 0, 0);
+
+ /* carg (-inf + i y) == -pi for finite y < 0. */
+ check_float ("carg (-inf - 10.0 i) == -pi", FUNC(carg) (BUILD_COMPLEX (minus_infty, -10.0)), -M_PIl, 0, 0, 0);
+
+ check_float ("carg (inf + inf i) == pi/4", FUNC(carg) (BUILD_COMPLEX (plus_infty, plus_infty)), M_PI_4l, 0, 0, 0);
+
+ check_float ("carg (inf - inf i) == -pi/4", FUNC(carg) (BUILD_COMPLEX (plus_infty, minus_infty)), -M_PI_4l, 0, 0, 0);
+
+ check_float ("carg (-inf + inf i) == 3 * M_PI_4l", FUNC(carg) (BUILD_COMPLEX (minus_infty, plus_infty)), 3 * M_PI_4l, 0, 0, 0);
+
+ check_float ("carg (-inf - inf i) == -3 * M_PI_4l", FUNC(carg) (BUILD_COMPLEX (minus_infty, minus_infty)), -3 * M_PI_4l, 0, 0, 0);
+
+ check_float ("carg (NaN + NaN i) == NaN", FUNC(carg) (BUILD_COMPLEX (nan_value, nan_value)), nan_value, 0, 0, 0);
+
+ print_max_error ("carg", 0, 0);
+}
+
+static void
+casin_test (void)
+{
+ errno = 0;
+ FUNC(casin) (BUILD_COMPLEX (0.7L, 1.2L));
+ if (errno == ENOSYS)
+ /* Function not implemented. */
+ return;
+
+ init_max_error ();
+
+ check_complex ("casin (0 + 0 i) == 0.0 + 0.0 i", FUNC(casin) (BUILD_COMPLEX (0, 0)), BUILD_COMPLEX (0.0, 0.0), 0, 0, 0);
+ check_complex ("casin (-0 + 0 i) == -0 + 0.0 i", FUNC(casin) (BUILD_COMPLEX (minus_zero, 0)), BUILD_COMPLEX (minus_zero, 0.0), 0, 0, 0);
+ check_complex ("casin (0 - 0 i) == 0.0 - 0 i", FUNC(casin) (BUILD_COMPLEX (0, minus_zero)), BUILD_COMPLEX (0.0, minus_zero), 0, 0, 0);
+ check_complex ("casin (-0 - 0 i) == -0 - 0 i", FUNC(casin) (BUILD_COMPLEX (minus_zero, minus_zero)), BUILD_COMPLEX (minus_zero, minus_zero), 0, 0, 0);
+
+ check_complex ("casin (inf + inf i) == pi/4 + inf i", FUNC(casin) (BUILD_COMPLEX (plus_infty, plus_infty)), BUILD_COMPLEX (M_PI_4l, plus_infty), 0, 0, 0);
+ check_complex ("casin (inf - inf i) == pi/4 - inf i", FUNC(casin) (BUILD_COMPLEX (plus_infty, minus_infty)), BUILD_COMPLEX (M_PI_4l, minus_infty), 0, 0, 0);
+ check_complex ("casin (-inf + inf i) == -pi/4 + inf i", FUNC(casin) (BUILD_COMPLEX (minus_infty, plus_infty)), BUILD_COMPLEX (-M_PI_4l, plus_infty), 0, 0, 0);
+ check_complex ("casin (-inf - inf i) == -pi/4 - inf i", FUNC(casin) (BUILD_COMPLEX (minus_infty, minus_infty)), BUILD_COMPLEX (-M_PI_4l, minus_infty), 0, 0, 0);
+
+ check_complex ("casin (-10.0 + inf i) == -0 + inf i", FUNC(casin) (BUILD_COMPLEX (-10.0, plus_infty)), BUILD_COMPLEX (minus_zero, plus_infty), 0, 0, 0);
+ check_complex ("casin (-10.0 - inf i) == -0 - inf i", FUNC(casin) (BUILD_COMPLEX (-10.0, minus_infty)), BUILD_COMPLEX (minus_zero, minus_infty), 0, 0, 0);
+ check_complex ("casin (0 + inf i) == 0.0 + inf i", FUNC(casin) (BUILD_COMPLEX (0, plus_infty)), BUILD_COMPLEX (0.0, plus_infty), 0, 0, 0);
+ check_complex ("casin (0 - inf i) == 0.0 - inf i", FUNC(casin) (BUILD_COMPLEX (0, minus_infty)), BUILD_COMPLEX (0.0, minus_infty), 0, 0, 0);
+ check_complex ("casin (-0 + inf i) == -0 + inf i", FUNC(casin) (BUILD_COMPLEX (minus_zero, plus_infty)), BUILD_COMPLEX (minus_zero, plus_infty), 0, 0, 0);
+ check_complex ("casin (-0 - inf i) == -0 - inf i", FUNC(casin) (BUILD_COMPLEX (minus_zero, minus_infty)), BUILD_COMPLEX (minus_zero, minus_infty), 0, 0, 0);
+ check_complex ("casin (0.1 + inf i) == 0.0 + inf i", FUNC(casin) (BUILD_COMPLEX (0.1L, plus_infty)), BUILD_COMPLEX (0.0, plus_infty), 0, 0, 0);
+ check_complex ("casin (0.1 - inf i) == 0.0 - inf i", FUNC(casin) (BUILD_COMPLEX (0.1L, minus_infty)), BUILD_COMPLEX (0.0, minus_infty), 0, 0, 0);
+
+ check_complex ("casin (-inf + 0 i) == -pi/2 + inf i", FUNC(casin) (BUILD_COMPLEX (minus_infty, 0)), BUILD_COMPLEX (-M_PI_2l, plus_infty), 0, 0, 0);
+ check_complex ("casin (-inf - 0 i) == -pi/2 - inf i", FUNC(casin) (BUILD_COMPLEX (minus_infty, minus_zero)), BUILD_COMPLEX (-M_PI_2l, minus_infty), 0, 0, 0);
+ check_complex ("casin (-inf + 100 i) == -pi/2 + inf i", FUNC(casin) (BUILD_COMPLEX (minus_infty, 100)), BUILD_COMPLEX (-M_PI_2l, plus_infty), 0, 0, 0);
+ check_complex ("casin (-inf - 100 i) == -pi/2 - inf i", FUNC(casin) (BUILD_COMPLEX (minus_infty, -100)), BUILD_COMPLEX (-M_PI_2l, minus_infty), 0, 0, 0);
+
+ check_complex ("casin (inf + 0 i) == pi/2 + inf i", FUNC(casin) (BUILD_COMPLEX (plus_infty, 0)), BUILD_COMPLEX (M_PI_2l, plus_infty), 0, 0, 0);
+ check_complex ("casin (inf - 0 i) == pi/2 - inf i", FUNC(casin) (BUILD_COMPLEX (plus_infty, minus_zero)), BUILD_COMPLEX (M_PI_2l, minus_infty), 0, 0, 0);
+ check_complex ("casin (inf + 0.5 i) == pi/2 + inf i", FUNC(casin) (BUILD_COMPLEX (plus_infty, 0.5)), BUILD_COMPLEX (M_PI_2l, plus_infty), 0, 0, 0);
+ check_complex ("casin (inf - 0.5 i) == pi/2 - inf i", FUNC(casin) (BUILD_COMPLEX (plus_infty, -0.5)), BUILD_COMPLEX (M_PI_2l, minus_infty), 0, 0, 0);
+
+ check_complex ("casin (NaN + inf i) == NaN + inf i", FUNC(casin) (BUILD_COMPLEX (nan_value, plus_infty)), BUILD_COMPLEX (nan_value, plus_infty), 0, 0, 0);
+ check_complex ("casin (NaN - inf i) == NaN - inf i", FUNC(casin) (BUILD_COMPLEX (nan_value, minus_infty)), BUILD_COMPLEX (nan_value, minus_infty), 0, 0, 0);
+
+ check_complex ("casin (0.0 + NaN i) == 0.0 + NaN i", FUNC(casin) (BUILD_COMPLEX (0.0, nan_value)), BUILD_COMPLEX (0.0, nan_value), 0, 0, 0);
+ check_complex ("casin (-0 + NaN i) == -0 + NaN i", FUNC(casin) (BUILD_COMPLEX (minus_zero, nan_value)), BUILD_COMPLEX (minus_zero, nan_value), 0, 0, 0);
+
+ check_complex ("casin (inf + NaN i) == NaN + inf i plus sign of zero/inf not specified", FUNC(casin) (BUILD_COMPLEX (plus_infty, nan_value)), BUILD_COMPLEX (nan_value, plus_infty), 0, 0, IGNORE_ZERO_INF_SIGN);
+ check_complex ("casin (-inf + NaN i) == NaN + inf i plus sign of zero/inf not specified", FUNC(casin) (BUILD_COMPLEX (minus_infty, nan_value)), BUILD_COMPLEX (nan_value, plus_infty), 0, 0, IGNORE_ZERO_INF_SIGN);
+
+ check_complex ("casin (NaN + 10.5 i) == NaN + NaN i plus invalid exception allowed", FUNC(casin) (BUILD_COMPLEX (nan_value, 10.5)), BUILD_COMPLEX (nan_value, nan_value), 0, 0, INVALID_EXCEPTION_OK);
+ check_complex ("casin (NaN - 10.5 i) == NaN + NaN i plus invalid exception allowed", FUNC(casin) (BUILD_COMPLEX (nan_value, -10.5)), BUILD_COMPLEX (nan_value, nan_value), 0, 0, INVALID_EXCEPTION_OK);
+
+ check_complex ("casin (0.75 + NaN i) == NaN + NaN i plus invalid exception allowed", FUNC(casin) (BUILD_COMPLEX (0.75, nan_value)), BUILD_COMPLEX (nan_value, nan_value), 0, 0, INVALID_EXCEPTION_OK);
+ check_complex ("casin (-0.75 + NaN i) == NaN + NaN i plus invalid exception allowed", FUNC(casin) (BUILD_COMPLEX (-0.75, nan_value)), BUILD_COMPLEX (nan_value, nan_value), 0, 0, INVALID_EXCEPTION_OK);
+
+ check_complex ("casin (NaN + NaN i) == NaN + NaN i", FUNC(casin) (BUILD_COMPLEX (nan_value, nan_value)), BUILD_COMPLEX (nan_value, nan_value), 0, 0, 0);
+
+ check_complex ("casin (0.7 + 1.2 i) == 0.4356135790797415103321208644578462 + 1.0927647857577371459105272080819308 i", FUNC(casin) (BUILD_COMPLEX (0.7L, 1.2L)), BUILD_COMPLEX (0.4356135790797415103321208644578462L, 1.0927647857577371459105272080819308L), DELTA225, 0, 0);
+ check_complex ("casin (-2 - 3 i) == -0.57065278432109940071028387968566963 - 1.9833870299165354323470769028940395 i", FUNC(casin) (BUILD_COMPLEX (-2, -3)), BUILD_COMPLEX (-0.57065278432109940071028387968566963L, -1.9833870299165354323470769028940395L), DELTA226, 0, 0);
+
+ print_complex_max_error ("casin", DELTAcasin, 0);
+}
+
+
+static void
+casinh_test (void)
+{
+ errno = 0;
+ FUNC(casinh) (BUILD_COMPLEX (0.7L, 1.2L));
+ if (errno == ENOSYS)
+ /* Function not implemented. */
+ return;
+
+ init_max_error ();
+
+ check_complex ("casinh (0 + 0 i) == 0.0 + 0.0 i", FUNC(casinh) (BUILD_COMPLEX (0, 0)), BUILD_COMPLEX (0.0, 0.0), 0, 0, 0);
+ check_complex ("casinh (-0 + 0 i) == -0 + 0 i", FUNC(casinh) (BUILD_COMPLEX (minus_zero, 0)), BUILD_COMPLEX (minus_zero, 0), 0, 0, 0);
+ check_complex ("casinh (0 - 0 i) == 0.0 - 0 i", FUNC(casinh) (BUILD_COMPLEX (0, minus_zero)), BUILD_COMPLEX (0.0, minus_zero), 0, 0, 0);
+ check_complex ("casinh (-0 - 0 i) == -0 - 0 i", FUNC(casinh) (BUILD_COMPLEX (minus_zero, minus_zero)), BUILD_COMPLEX (minus_zero, minus_zero), 0, 0, 0);
+
+ check_complex ("casinh (inf + inf i) == inf + pi/4 i", FUNC(casinh) (BUILD_COMPLEX (plus_infty, plus_infty)), BUILD_COMPLEX (plus_infty, M_PI_4l), 0, 0, 0);
+ check_complex ("casinh (inf - inf i) == inf - pi/4 i", FUNC(casinh) (BUILD_COMPLEX (plus_infty, minus_infty)), BUILD_COMPLEX (plus_infty, -M_PI_4l), 0, 0, 0);
+ check_complex ("casinh (-inf + inf i) == -inf + pi/4 i", FUNC(casinh) (BUILD_COMPLEX (minus_infty, plus_infty)), BUILD_COMPLEX (minus_infty, M_PI_4l), 0, 0, 0);
+ check_complex ("casinh (-inf - inf i) == -inf - pi/4 i", FUNC(casinh) (BUILD_COMPLEX (minus_infty, minus_infty)), BUILD_COMPLEX (minus_infty, -M_PI_4l), 0, 0, 0);
+
+ check_complex ("casinh (-10.0 + inf i) == -inf + pi/2 i", FUNC(casinh) (BUILD_COMPLEX (-10.0, plus_infty)), BUILD_COMPLEX (minus_infty, M_PI_2l), 0, 0, 0);
+ check_complex ("casinh (-10.0 - inf i) == -inf - pi/2 i", FUNC(casinh) (BUILD_COMPLEX (-10.0, minus_infty)), BUILD_COMPLEX (minus_infty, -M_PI_2l), 0, 0, 0);
+ check_complex ("casinh (0 + inf i) == inf + pi/2 i", FUNC(casinh) (BUILD_COMPLEX (0, plus_infty)), BUILD_COMPLEX (plus_infty, M_PI_2l), 0, 0, 0);
+ check_complex ("casinh (0 - inf i) == inf - pi/2 i", FUNC(casinh) (BUILD_COMPLEX (0, minus_infty)), BUILD_COMPLEX (plus_infty, -M_PI_2l), 0, 0, 0);
+ check_complex ("casinh (-0 + inf i) == -inf + pi/2 i", FUNC(casinh) (BUILD_COMPLEX (minus_zero, plus_infty)), BUILD_COMPLEX (minus_infty, M_PI_2l), 0, 0, 0);
+ check_complex ("casinh (-0 - inf i) == -inf - pi/2 i", FUNC(casinh) (BUILD_COMPLEX (minus_zero, minus_infty)), BUILD_COMPLEX (minus_infty, -M_PI_2l), 0, 0, 0);
+ check_complex ("casinh (0.1 + inf i) == inf + pi/2 i", FUNC(casinh) (BUILD_COMPLEX (0.1L, plus_infty)), BUILD_COMPLEX (plus_infty, M_PI_2l), 0, 0, 0);
+ check_complex ("casinh (0.1 - inf i) == inf - pi/2 i", FUNC(casinh) (BUILD_COMPLEX (0.1L, minus_infty)), BUILD_COMPLEX (plus_infty, -M_PI_2l), 0, 0, 0);
+
+ check_complex ("casinh (-inf + 0 i) == -inf + 0.0 i", FUNC(casinh) (BUILD_COMPLEX (minus_infty, 0)), BUILD_COMPLEX (minus_infty, 0.0), 0, 0, 0);
+ check_complex ("casinh (-inf - 0 i) == -inf - 0 i", FUNC(casinh) (BUILD_COMPLEX (minus_infty, minus_zero)), BUILD_COMPLEX (minus_infty, minus_zero), 0, 0, 0);
+ check_complex ("casinh (-inf + 100 i) == -inf + 0.0 i", FUNC(casinh) (BUILD_COMPLEX (minus_infty, 100)), BUILD_COMPLEX (minus_infty, 0.0), 0, 0, 0);
+ check_complex ("casinh (-inf - 100 i) == -inf - 0 i", FUNC(casinh) (BUILD_COMPLEX (minus_infty, -100)), BUILD_COMPLEX (minus_infty, minus_zero), 0, 0, 0);
+
+ check_complex ("casinh (inf + 0 i) == inf + 0.0 i", FUNC(casinh) (BUILD_COMPLEX (plus_infty, 0)), BUILD_COMPLEX (plus_infty, 0.0), 0, 0, 0);
+ check_complex ("casinh (inf - 0 i) == inf - 0 i", FUNC(casinh) (BUILD_COMPLEX (plus_infty, minus_zero)), BUILD_COMPLEX (plus_infty, minus_zero), 0, 0, 0);
+ check_complex ("casinh (inf + 0.5 i) == inf + 0.0 i", FUNC(casinh) (BUILD_COMPLEX (plus_infty, 0.5)), BUILD_COMPLEX (plus_infty, 0.0), 0, 0, 0);
+ check_complex ("casinh (inf - 0.5 i) == inf - 0 i", FUNC(casinh) (BUILD_COMPLEX (plus_infty, -0.5)), BUILD_COMPLEX (plus_infty, minus_zero), 0, 0, 0);
+
+ check_complex ("casinh (inf + NaN i) == inf + NaN i", FUNC(casinh) (BUILD_COMPLEX (plus_infty, nan_value)), BUILD_COMPLEX (plus_infty, nan_value), 0, 0, 0);
+ check_complex ("casinh (-inf + NaN i) == -inf + NaN i", FUNC(casinh) (BUILD_COMPLEX (minus_infty, nan_value)), BUILD_COMPLEX (minus_infty, nan_value), 0, 0, 0);
+
+ check_complex ("casinh (NaN + 0 i) == NaN + 0.0 i", FUNC(casinh) (BUILD_COMPLEX (nan_value, 0)), BUILD_COMPLEX (nan_value, 0.0), 0, 0, 0);
+ check_complex ("casinh (NaN - 0 i) == NaN - 0 i", FUNC(casinh) (BUILD_COMPLEX (nan_value, minus_zero)), BUILD_COMPLEX (nan_value, minus_zero), 0, 0, 0);
+
+ check_complex ("casinh (NaN + inf i) == inf + NaN i plus sign of zero/inf not specified", FUNC(casinh) (BUILD_COMPLEX (nan_value, plus_infty)), BUILD_COMPLEX (plus_infty, nan_value), 0, 0, IGNORE_ZERO_INF_SIGN);
+ check_complex ("casinh (NaN - inf i) == inf + NaN i plus sign of zero/inf not specified", FUNC(casinh) (BUILD_COMPLEX (nan_value, minus_infty)), BUILD_COMPLEX (plus_infty, nan_value), 0, 0, IGNORE_ZERO_INF_SIGN);
+
+ check_complex ("casinh (10.5 + NaN i) == NaN + NaN i plus invalid exception allowed", FUNC(casinh) (BUILD_COMPLEX (10.5, nan_value)), BUILD_COMPLEX (nan_value, nan_value), 0, 0, INVALID_EXCEPTION_OK);
+ check_complex ("casinh (-10.5 + NaN i) == NaN + NaN i plus invalid exception allowed", FUNC(casinh) (BUILD_COMPLEX (-10.5, nan_value)), BUILD_COMPLEX (nan_value, nan_value), 0, 0, INVALID_EXCEPTION_OK);
+
+ check_complex ("casinh (NaN + 0.75 i) == NaN + NaN i plus invalid exception allowed", FUNC(casinh) (BUILD_COMPLEX (nan_value, 0.75)), BUILD_COMPLEX (nan_value, nan_value), 0, 0, INVALID_EXCEPTION_OK);
+ check_complex ("casinh (-0.75 + NaN i) == NaN + NaN i plus invalid exception allowed", FUNC(casinh) (BUILD_COMPLEX (-0.75, nan_value)), BUILD_COMPLEX (nan_value, nan_value), 0, 0, INVALID_EXCEPTION_OK);
+
+ check_complex ("casinh (NaN + NaN i) == NaN + NaN i", FUNC(casinh) (BUILD_COMPLEX (nan_value, nan_value)), BUILD_COMPLEX (nan_value, nan_value), 0, 0, 0);
+
+ check_complex ("casinh (0.7 + 1.2 i) == 0.97865459559367387689317593222160964 + 0.91135418953156011567903546856170941 i", FUNC(casinh) (BUILD_COMPLEX (0.7L, 1.2L)), BUILD_COMPLEX (0.97865459559367387689317593222160964L, 0.91135418953156011567903546856170941L), DELTA262, 0, 0);
+ check_complex ("casinh (-2 - 3 i) == -1.9686379257930962917886650952454982 - 0.96465850440760279204541105949953237 i", FUNC(casinh) (BUILD_COMPLEX (-2, -3)), BUILD_COMPLEX (-1.9686379257930962917886650952454982L, -0.96465850440760279204541105949953237L), DELTA263, 0, 0);
+
+ print_complex_max_error ("casinh", DELTAcasinh, 0);
+}
+
+
+static void
+catan_test (void)
+{
+ errno = 0;
+ FUNC(catan) (BUILD_COMPLEX (0.7L, 1.2L));
+ if (errno == ENOSYS)
+ /* Function not implemented. */
+ return;
+
+ init_max_error ();
+
+ check_complex ("catan (0 + 0 i) == 0 + 0 i", FUNC(catan) (BUILD_COMPLEX (0, 0)), BUILD_COMPLEX (0, 0), 0, 0, 0);
+ check_complex ("catan (-0 + 0 i) == -0 + 0 i", FUNC(catan) (BUILD_COMPLEX (minus_zero, 0)), BUILD_COMPLEX (minus_zero, 0), 0, 0, 0);
+ check_complex ("catan (0 - 0 i) == 0 - 0 i", FUNC(catan) (BUILD_COMPLEX (0, minus_zero)), BUILD_COMPLEX (0, minus_zero), 0, 0, 0);
+ check_complex ("catan (-0 - 0 i) == -0 - 0 i", FUNC(catan) (BUILD_COMPLEX (minus_zero, minus_zero)), BUILD_COMPLEX (minus_zero, minus_zero), 0, 0, 0);
+
+ check_complex ("catan (inf + inf i) == pi/2 + 0 i", FUNC(catan) (BUILD_COMPLEX (plus_infty, plus_infty)), BUILD_COMPLEX (M_PI_2l, 0), 0, 0, 0);
+ check_complex ("catan (inf - inf i) == pi/2 - 0 i", FUNC(catan) (BUILD_COMPLEX (plus_infty, minus_infty)), BUILD_COMPLEX (M_PI_2l, minus_zero), 0, 0, 0);
+ check_complex ("catan (-inf + inf i) == -pi/2 + 0 i", FUNC(catan) (BUILD_COMPLEX (minus_infty, plus_infty)), BUILD_COMPLEX (-M_PI_2l, 0), 0, 0, 0);
+ check_complex ("catan (-inf - inf i) == -pi/2 - 0 i", FUNC(catan) (BUILD_COMPLEX (minus_infty, minus_infty)), BUILD_COMPLEX (-M_PI_2l, minus_zero), 0, 0, 0);
+
+
+ check_complex ("catan (inf - 10.0 i) == pi/2 - 0 i", FUNC(catan) (BUILD_COMPLEX (plus_infty, -10.0)), BUILD_COMPLEX (M_PI_2l, minus_zero), 0, 0, 0);
+ check_complex ("catan (-inf - 10.0 i) == -pi/2 - 0 i", FUNC(catan) (BUILD_COMPLEX (minus_infty, -10.0)), BUILD_COMPLEX (-M_PI_2l, minus_zero), 0, 0, 0);
+ check_complex ("catan (inf - 0 i) == pi/2 - 0 i", FUNC(catan) (BUILD_COMPLEX (plus_infty, minus_zero)), BUILD_COMPLEX (M_PI_2l, minus_zero), 0, 0, 0);
+ check_complex ("catan (-inf - 0 i) == -pi/2 - 0 i", FUNC(catan) (BUILD_COMPLEX (minus_infty, minus_zero)), BUILD_COMPLEX (-M_PI_2l, minus_zero), 0, 0, 0);
+ check_complex ("catan (inf + 0.0 i) == pi/2 + 0 i", FUNC(catan) (BUILD_COMPLEX (plus_infty, 0.0)), BUILD_COMPLEX (M_PI_2l, 0), 0, 0, 0);
+ check_complex ("catan (-inf + 0.0 i) == -pi/2 + 0 i", FUNC(catan) (BUILD_COMPLEX (minus_infty, 0.0)), BUILD_COMPLEX (-M_PI_2l, 0), 0, 0, 0);
+ check_complex ("catan (inf + 0.1 i) == pi/2 + 0 i", FUNC(catan) (BUILD_COMPLEX (plus_infty, 0.1L)), BUILD_COMPLEX (M_PI_2l, 0), 0, 0, 0);
+ check_complex ("catan (-inf + 0.1 i) == -pi/2 + 0 i", FUNC(catan) (BUILD_COMPLEX (minus_infty, 0.1L)), BUILD_COMPLEX (-M_PI_2l, 0), 0, 0, 0);
+
+ check_complex ("catan (0.0 - inf i) == pi/2 - 0 i", FUNC(catan) (BUILD_COMPLEX (0.0, minus_infty)), BUILD_COMPLEX (M_PI_2l, minus_zero), 0, 0, 0);
+ check_complex ("catan (-0 - inf i) == -pi/2 - 0 i", FUNC(catan) (BUILD_COMPLEX (minus_zero, minus_infty)), BUILD_COMPLEX (-M_PI_2l, minus_zero), 0, 0, 0);
+ check_complex ("catan (100.0 - inf i) == pi/2 - 0 i", FUNC(catan) (BUILD_COMPLEX (100.0, minus_infty)), BUILD_COMPLEX (M_PI_2l, minus_zero), 0, 0, 0);
+ check_complex ("catan (-100.0 - inf i) == -pi/2 - 0 i", FUNC(catan) (BUILD_COMPLEX (-100.0, minus_infty)), BUILD_COMPLEX (-M_PI_2l, minus_zero), 0, 0, 0);
+
+ check_complex ("catan (0.0 + inf i) == pi/2 + 0 i", FUNC(catan) (BUILD_COMPLEX (0.0, plus_infty)), BUILD_COMPLEX (M_PI_2l, 0), 0, 0, 0);
+ check_complex ("catan (-0 + inf i) == -pi/2 + 0 i", FUNC(catan) (BUILD_COMPLEX (minus_zero, plus_infty)), BUILD_COMPLEX (-M_PI_2l, 0), 0, 0, 0);
+ check_complex ("catan (0.5 + inf i) == pi/2 + 0 i", FUNC(catan) (BUILD_COMPLEX (0.5, plus_infty)), BUILD_COMPLEX (M_PI_2l, 0), 0, 0, 0);
+ check_complex ("catan (-0.5 + inf i) == -pi/2 + 0 i", FUNC(catan) (BUILD_COMPLEX (-0.5, plus_infty)), BUILD_COMPLEX (-M_PI_2l, 0), 0, 0, 0);
+
+ check_complex ("catan (NaN + 0.0 i) == NaN + 0 i", FUNC(catan) (BUILD_COMPLEX (nan_value, 0.0)), BUILD_COMPLEX (nan_value, 0), 0, 0, 0);
+ check_complex ("catan (NaN - 0 i) == NaN - 0 i", FUNC(catan) (BUILD_COMPLEX (nan_value, minus_zero)), BUILD_COMPLEX (nan_value, minus_zero), 0, 0, 0);
+
+ check_complex ("catan (NaN + inf i) == NaN + 0 i", FUNC(catan) (BUILD_COMPLEX (nan_value, plus_infty)), BUILD_COMPLEX (nan_value, 0), 0, 0, 0);
+ check_complex ("catan (NaN - inf i) == NaN - 0 i", FUNC(catan) (BUILD_COMPLEX (nan_value, minus_infty)), BUILD_COMPLEX (nan_value, minus_zero), 0, 0, 0);
+
+ check_complex ("catan (0.0 + NaN i) == NaN + NaN i", FUNC(catan) (BUILD_COMPLEX (0.0, nan_value)), BUILD_COMPLEX (nan_value, nan_value), 0, 0, 0);
+ check_complex ("catan (-0 + NaN i) == NaN + NaN i", FUNC(catan) (BUILD_COMPLEX (minus_zero, nan_value)), BUILD_COMPLEX (nan_value, nan_value), 0, 0, 0);
+
+ check_complex ("catan (inf + NaN i) == pi/2 + 0 i plus sign of zero/inf not specified", FUNC(catan) (BUILD_COMPLEX (plus_infty, nan_value)), BUILD_COMPLEX (M_PI_2l, 0), 0, 0, IGNORE_ZERO_INF_SIGN);
+ check_complex ("catan (-inf + NaN i) == -pi/2 + 0 i plus sign of zero/inf not specified", FUNC(catan) (BUILD_COMPLEX (minus_infty, nan_value)), BUILD_COMPLEX (-M_PI_2l, 0), 0, 0, IGNORE_ZERO_INF_SIGN);
+
+ check_complex ("catan (NaN + 10.5 i) == NaN + NaN i plus invalid exception allowed", FUNC(catan) (BUILD_COMPLEX (nan_value, 10.5)), BUILD_COMPLEX (nan_value, nan_value), 0, 0, INVALID_EXCEPTION_OK);
+ check_complex ("catan (NaN - 10.5 i) == NaN + NaN i plus invalid exception allowed", FUNC(catan) (BUILD_COMPLEX (nan_value, -10.5)), BUILD_COMPLEX (nan_value, nan_value), 0, 0, INVALID_EXCEPTION_OK);
+
+ check_complex ("catan (0.75 + NaN i) == NaN + NaN i plus invalid exception allowed", FUNC(catan) (BUILD_COMPLEX (0.75, nan_value)), BUILD_COMPLEX (nan_value, nan_value), 0, 0, INVALID_EXCEPTION_OK);
+ check_complex ("catan (-0.75 + NaN i) == NaN + NaN i plus invalid exception allowed", FUNC(catan) (BUILD_COMPLEX (-0.75, nan_value)), BUILD_COMPLEX (nan_value, nan_value), 0, 0, INVALID_EXCEPTION_OK);
+
+ check_complex ("catan (NaN + NaN i) == NaN + NaN i", FUNC(catan) (BUILD_COMPLEX (nan_value, nan_value)), BUILD_COMPLEX (nan_value, nan_value), 0, 0, 0);
+
+ check_complex ("catan (0.7 + 1.2 i) == 1.0785743834118921877443707996386368 + 0.57705737765343067644394541889341712 i", FUNC(catan) (BUILD_COMPLEX (0.7L, 1.2L)), BUILD_COMPLEX (1.0785743834118921877443707996386368L, 0.57705737765343067644394541889341712L), DELTA301, 0, 0);
+
+ check_complex ("catan (-2 - 3 i) == -1.4099210495965755225306193844604208 - 0.22907268296853876629588180294200276 i", FUNC(catan) (BUILD_COMPLEX (-2, -3)), BUILD_COMPLEX (-1.4099210495965755225306193844604208L, -0.22907268296853876629588180294200276L), DELTA302, 0, 0);
+
+ print_complex_max_error ("catan", DELTAcatan, 0);
+}
+
+static void
+catanh_test (void)
+{
+ errno = 0;
+ FUNC(catanh) (BUILD_COMPLEX (0.7L, 1.2L));
+ if (errno == ENOSYS)
+ /* Function not implemented. */
+ return;
+
+ init_max_error ();
+
+ check_complex ("catanh (0 + 0 i) == 0.0 + 0.0 i", FUNC(catanh) (BUILD_COMPLEX (0, 0)), BUILD_COMPLEX (0.0, 0.0), 0, 0, 0);
+ check_complex ("catanh (-0 + 0 i) == -0 + 0.0 i", FUNC(catanh) (BUILD_COMPLEX (minus_zero, 0)), BUILD_COMPLEX (minus_zero, 0.0), 0, 0, 0);
+ check_complex ("catanh (0 - 0 i) == 0.0 - 0 i", FUNC(catanh) (BUILD_COMPLEX (0, minus_zero)), BUILD_COMPLEX (0.0, minus_zero), 0, 0, 0);
+ check_complex ("catanh (-0 - 0 i) == -0 - 0 i", FUNC(catanh) (BUILD_COMPLEX (minus_zero, minus_zero)), BUILD_COMPLEX (minus_zero, minus_zero), 0, 0, 0);
+
+ check_complex ("catanh (inf + inf i) == 0.0 + pi/2 i", FUNC(catanh) (BUILD_COMPLEX (plus_infty, plus_infty)), BUILD_COMPLEX (0.0, M_PI_2l), 0, 0, 0);
+ check_complex ("catanh (inf - inf i) == 0.0 - pi/2 i", FUNC(catanh) (BUILD_COMPLEX (plus_infty, minus_infty)), BUILD_COMPLEX (0.0, -M_PI_2l), 0, 0, 0);
+ check_complex ("catanh (-inf + inf i) == -0 + pi/2 i", FUNC(catanh) (BUILD_COMPLEX (minus_infty, plus_infty)), BUILD_COMPLEX (minus_zero, M_PI_2l), 0, 0, 0);
+ check_complex ("catanh (-inf - inf i) == -0 - pi/2 i", FUNC(catanh) (BUILD_COMPLEX (minus_infty, minus_infty)), BUILD_COMPLEX (minus_zero, -M_PI_2l), 0, 0, 0);
+
+ check_complex ("catanh (-10.0 + inf i) == -0 + pi/2 i", FUNC(catanh) (BUILD_COMPLEX (-10.0, plus_infty)), BUILD_COMPLEX (minus_zero, M_PI_2l), 0, 0, 0);
+ check_complex ("catanh (-10.0 - inf i) == -0 - pi/2 i", FUNC(catanh) (BUILD_COMPLEX (-10.0, minus_infty)), BUILD_COMPLEX (minus_zero, -M_PI_2l), 0, 0, 0);
+ check_complex ("catanh (-0 + inf i) == -0 + pi/2 i", FUNC(catanh) (BUILD_COMPLEX (minus_zero, plus_infty)), BUILD_COMPLEX (minus_zero, M_PI_2l), 0, 0, 0);
+ check_complex ("catanh (-0 - inf i) == -0 - pi/2 i", FUNC(catanh) (BUILD_COMPLEX (minus_zero, minus_infty)), BUILD_COMPLEX (minus_zero, -M_PI_2l), 0, 0, 0);
+ check_complex ("catanh (0 + inf i) == 0.0 + pi/2 i", FUNC(catanh) (BUILD_COMPLEX (0, plus_infty)), BUILD_COMPLEX (0.0, M_PI_2l), 0, 0, 0);
+ check_complex ("catanh (0 - inf i) == 0.0 - pi/2 i", FUNC(catanh) (BUILD_COMPLEX (0, minus_infty)), BUILD_COMPLEX (0.0, -M_PI_2l), 0, 0, 0);
+ check_complex ("catanh (0.1 + inf i) == 0.0 + pi/2 i", FUNC(catanh) (BUILD_COMPLEX (0.1L, plus_infty)), BUILD_COMPLEX (0.0, M_PI_2l), 0, 0, 0);
+ check_complex ("catanh (0.1 - inf i) == 0.0 - pi/2 i", FUNC(catanh) (BUILD_COMPLEX (0.1L, minus_infty)), BUILD_COMPLEX (0.0, -M_PI_2l), 0, 0, 0);
+
+ check_complex ("catanh (-inf + 0 i) == -0 + pi/2 i", FUNC(catanh) (BUILD_COMPLEX (minus_infty, 0)), BUILD_COMPLEX (minus_zero, M_PI_2l), 0, 0, 0);
+ check_complex ("catanh (-inf - 0 i) == -0 - pi/2 i", FUNC(catanh) (BUILD_COMPLEX (minus_infty, minus_zero)), BUILD_COMPLEX (minus_zero, -M_PI_2l), 0, 0, 0);
+ check_complex ("catanh (-inf + 100 i) == -0 + pi/2 i", FUNC(catanh) (BUILD_COMPLEX (minus_infty, 100)), BUILD_COMPLEX (minus_zero, M_PI_2l), 0, 0, 0);
+ check_complex ("catanh (-inf - 100 i) == -0 - pi/2 i", FUNC(catanh) (BUILD_COMPLEX (minus_infty, -100)), BUILD_COMPLEX (minus_zero, -M_PI_2l), 0, 0, 0);
+
+ check_complex ("catanh (inf + 0 i) == 0.0 + pi/2 i", FUNC(catanh) (BUILD_COMPLEX (plus_infty, 0)), BUILD_COMPLEX (0.0, M_PI_2l), 0, 0, 0);
+ check_complex ("catanh (inf - 0 i) == 0.0 - pi/2 i", FUNC(catanh) (BUILD_COMPLEX (plus_infty, minus_zero)), BUILD_COMPLEX (0.0, -M_PI_2l), 0, 0, 0);
+ check_complex ("catanh (inf + 0.5 i) == 0.0 + pi/2 i", FUNC(catanh) (BUILD_COMPLEX (plus_infty, 0.5)), BUILD_COMPLEX (0.0, M_PI_2l), 0, 0, 0);
+ check_complex ("catanh (inf - 0.5 i) == 0.0 - pi/2 i", FUNC(catanh) (BUILD_COMPLEX (plus_infty, -0.5)), BUILD_COMPLEX (0.0, -M_PI_2l), 0, 0, 0);
+
+ check_complex ("catanh (0 + NaN i) == 0.0 + NaN i", FUNC(catanh) (BUILD_COMPLEX (0, nan_value)), BUILD_COMPLEX (0.0, nan_value), 0, 0, 0);
+ check_complex ("catanh (-0 + NaN i) == -0 + NaN i", FUNC(catanh) (BUILD_COMPLEX (minus_zero, nan_value)), BUILD_COMPLEX (minus_zero, nan_value), 0, 0, 0);
+
+ check_complex ("catanh (inf + NaN i) == 0.0 + NaN i", FUNC(catanh) (BUILD_COMPLEX (plus_infty, nan_value)), BUILD_COMPLEX (0.0, nan_value), 0, 0, 0);
+ check_complex ("catanh (-inf + NaN i) == -0 + NaN i", FUNC(catanh) (BUILD_COMPLEX (minus_infty, nan_value)), BUILD_COMPLEX (minus_zero, nan_value), 0, 0, 0);
+
+ check_complex ("catanh (NaN + 0 i) == NaN + NaN i", FUNC(catanh) (BUILD_COMPLEX (nan_value, 0)), BUILD_COMPLEX (nan_value, nan_value), 0, 0, 0);
+ check_complex ("catanh (NaN - 0 i) == NaN + NaN i", FUNC(catanh) (BUILD_COMPLEX (nan_value, minus_zero)), BUILD_COMPLEX (nan_value, nan_value), 0, 0, 0);
+
+ check_complex ("catanh (NaN + inf i) == 0.0 + pi/2 i plus sign of zero/inf not specified", FUNC(catanh) (BUILD_COMPLEX (nan_value, plus_infty)), BUILD_COMPLEX (0.0, M_PI_2l), 0, 0, IGNORE_ZERO_INF_SIGN);
+ check_complex ("catanh (NaN - inf i) == 0.0 - pi/2 i plus sign of zero/inf not specified", FUNC(catanh) (BUILD_COMPLEX (nan_value, minus_infty)), BUILD_COMPLEX (0.0, -M_PI_2l), 0, 0, IGNORE_ZERO_INF_SIGN);
+
+ check_complex ("catanh (10.5 + NaN i) == NaN + NaN i plus invalid exception allowed", FUNC(catanh) (BUILD_COMPLEX (10.5, nan_value)), BUILD_COMPLEX (nan_value, nan_value), 0, 0, INVALID_EXCEPTION_OK);
+ check_complex ("catanh (-10.5 + NaN i) == NaN + NaN i plus invalid exception allowed", FUNC(catanh) (BUILD_COMPLEX (-10.5, nan_value)), BUILD_COMPLEX (nan_value, nan_value), 0, 0, INVALID_EXCEPTION_OK);
+
+ check_complex ("catanh (NaN + 0.75 i) == NaN + NaN i plus invalid exception allowed", FUNC(catanh) (BUILD_COMPLEX (nan_value, 0.75)), BUILD_COMPLEX (nan_value, nan_value), 0, 0, INVALID_EXCEPTION_OK);
+ check_complex ("catanh (NaN - 0.75 i) == NaN + NaN i plus invalid exception allowed", FUNC(catanh) (BUILD_COMPLEX (nan_value, -0.75)), BUILD_COMPLEX (nan_value, nan_value), 0, 0, INVALID_EXCEPTION_OK);
+
+ check_complex ("catanh (NaN + NaN i) == NaN + NaN i", FUNC(catanh) (BUILD_COMPLEX (nan_value, nan_value)), BUILD_COMPLEX (nan_value, nan_value), 0, 0, 0);
+
+ check_complex ("catanh (0.7 + 1.2 i) == 0.2600749516525135959200648705635915 + 0.97024030779509898497385130162655963 i", FUNC(catanh) (BUILD_COMPLEX (0.7L, 1.2L)), BUILD_COMPLEX (0.2600749516525135959200648705635915L, 0.97024030779509898497385130162655963L), DELTA340, 0, 0);
+ check_complex ("catanh (-2 - 3 i) == -0.14694666622552975204743278515471595 - 1.3389725222944935611241935759091443 i", FUNC(catanh) (BUILD_COMPLEX (-2, -3)), BUILD_COMPLEX (-0.14694666622552975204743278515471595L, -1.3389725222944935611241935759091443L), DELTA341, 0, 0);
+
+ print_complex_max_error ("catanh", DELTAcatanh, 0);
+}
+#endif
+
+static void
+cbrt_test (void)
+{
+ errno = 0;
+ FUNC(cbrt) (8);
+ if (errno == ENOSYS)
+ /* Function not implemented. */
+ return;
+
+ init_max_error ();
+
+ check_float ("cbrt (0.0) == 0.0", FUNC(cbrt) (0.0), 0.0, 0, 0, 0);
+ check_float ("cbrt (-0) == -0", FUNC(cbrt) (minus_zero), minus_zero, 0, 0, 0);
+
+ check_float ("cbrt (inf) == inf", FUNC(cbrt) (plus_infty), plus_infty, 0, 0, 0);
+ check_float ("cbrt (-inf) == -inf", FUNC(cbrt) (minus_infty), minus_infty, 0, 0, 0);
+ check_float ("cbrt (NaN) == NaN", FUNC(cbrt) (nan_value), nan_value, 0, 0, 0);
+
+ check_float ("cbrt (-0.001) == -0.1", FUNC(cbrt) (-0.001L), -0.1L, DELTA347, 0, 0);
+ check_float ("cbrt (8) == 2", FUNC(cbrt) (8), 2, 0, 0, 0);
+ check_float ("cbrt (-27.0) == -3.0", FUNC(cbrt) (-27.0), -3.0, DELTA349, 0, 0);
+ check_float ("cbrt (0.970299) == 0.99", FUNC(cbrt) (0.970299L), 0.99L, DELTA350, 0, 0);
+ check_float ("cbrt (0.7) == 0.8879040017426007084", FUNC(cbrt) (0.7L), 0.8879040017426007084L, DELTA351, 0, 0);
+
+ print_max_error ("cbrt", DELTAcbrt, 0);
+}
+
+#if 0 /* XXX scp XXX */
+static void
+ccos_test (void)
+{
+ errno = 0;
+ FUNC(ccos) (BUILD_COMPLEX (0, 0));
+ if (errno == ENOSYS)
+ /* Function not implemented. */
+ return;
+
+ init_max_error ();
+
+ check_complex ("ccos (0.0 + 0.0 i) == 1.0 - 0 i", FUNC(ccos) (BUILD_COMPLEX (0.0, 0.0)), BUILD_COMPLEX (1.0, minus_zero), 0, 0, 0);
+ check_complex ("ccos (-0 + 0.0 i) == 1.0 + 0.0 i", FUNC(ccos) (BUILD_COMPLEX (minus_zero, 0.0)), BUILD_COMPLEX (1.0, 0.0), 0, 0, 0);
+ check_complex ("ccos (0.0 - 0 i) == 1.0 + 0.0 i", FUNC(ccos) (BUILD_COMPLEX (0.0, minus_zero)), BUILD_COMPLEX (1.0, 0.0), 0, 0, 0);
+ check_complex ("ccos (-0 - 0 i) == 1.0 - 0 i", FUNC(ccos) (BUILD_COMPLEX (minus_zero, minus_zero)), BUILD_COMPLEX (1.0, minus_zero), 0, 0, 0);
+
+ check_complex ("ccos (inf + 0.0 i) == NaN + 0.0 i plus invalid exception and sign of zero/inf not specified", FUNC(ccos) (BUILD_COMPLEX (plus_infty, 0.0)), BUILD_COMPLEX (nan_value, 0.0), 0, 0, INVALID_EXCEPTION|IGNORE_ZERO_INF_SIGN);
+ check_complex ("ccos (inf - 0 i) == NaN + 0.0 i plus invalid exception and sign of zero/inf not specified", FUNC(ccos) (BUILD_COMPLEX (plus_infty, minus_zero)), BUILD_COMPLEX (nan_value, 0.0), 0, 0, INVALID_EXCEPTION|IGNORE_ZERO_INF_SIGN);
+ check_complex ("ccos (-inf + 0.0 i) == NaN + 0.0 i plus invalid exception and sign of zero/inf not specified", FUNC(ccos) (BUILD_COMPLEX (minus_infty, 0.0)), BUILD_COMPLEX (nan_value, 0.0), 0, 0, INVALID_EXCEPTION|IGNORE_ZERO_INF_SIGN);
+ check_complex ("ccos (-inf - 0 i) == NaN + 0.0 i plus invalid exception and sign of zero/inf not specified", FUNC(ccos) (BUILD_COMPLEX (minus_infty, minus_zero)), BUILD_COMPLEX (nan_value, 0.0), 0, 0, INVALID_EXCEPTION|IGNORE_ZERO_INF_SIGN);
+
+ check_complex ("ccos (0.0 + inf i) == inf - 0 i", FUNC(ccos) (BUILD_COMPLEX (0.0, plus_infty)), BUILD_COMPLEX (plus_infty, minus_zero), 0, 0, 0);
+ check_complex ("ccos (0.0 - inf i) == inf + 0.0 i", FUNC(ccos) (BUILD_COMPLEX (0.0, minus_infty)), BUILD_COMPLEX (plus_infty, 0.0), 0, 0, 0);
+ check_complex ("ccos (-0 + inf i) == inf + 0.0 i", FUNC(ccos) (BUILD_COMPLEX (minus_zero, plus_infty)), BUILD_COMPLEX (plus_infty, 0.0), 0, 0, 0);
+ check_complex ("ccos (-0 - inf i) == inf - 0 i", FUNC(ccos) (BUILD_COMPLEX (minus_zero, minus_infty)), BUILD_COMPLEX (plus_infty, minus_zero), 0, 0, 0);
+
+ check_complex ("ccos (inf + inf i) == inf + NaN i plus invalid exception", FUNC(ccos) (BUILD_COMPLEX (plus_infty, plus_infty)), BUILD_COMPLEX (plus_infty, nan_value), 0, 0, INVALID_EXCEPTION);
+ check_complex ("ccos (-inf + inf i) == inf + NaN i plus invalid exception", FUNC(ccos) (BUILD_COMPLEX (minus_infty, plus_infty)), BUILD_COMPLEX (plus_infty, nan_value), 0, 0, INVALID_EXCEPTION);
+ check_complex ("ccos (inf - inf i) == inf + NaN i plus invalid exception", FUNC(ccos) (BUILD_COMPLEX (plus_infty, minus_infty)), BUILD_COMPLEX (plus_infty, nan_value), 0, 0, INVALID_EXCEPTION);
+ check_complex ("ccos (-inf - inf i) == inf + NaN i plus invalid exception", FUNC(ccos) (BUILD_COMPLEX (minus_infty, minus_infty)), BUILD_COMPLEX (plus_infty, nan_value), 0, 0, INVALID_EXCEPTION);
+
+ check_complex ("ccos (4.625 + inf i) == -inf + inf i", FUNC(ccos) (BUILD_COMPLEX (4.625, plus_infty)), BUILD_COMPLEX (minus_infty, plus_infty), 0, 0, 0);
+ check_complex ("ccos (4.625 - inf i) == -inf - inf i", FUNC(ccos) (BUILD_COMPLEX (4.625, minus_infty)), BUILD_COMPLEX (minus_infty, minus_infty), 0, 0, 0);
+ check_complex ("ccos (-4.625 + inf i) == -inf - inf i", FUNC(ccos) (BUILD_COMPLEX (-4.625, plus_infty)), BUILD_COMPLEX (minus_infty, minus_infty), 0, 0, 0);
+ check_complex ("ccos (-4.625 - inf i) == -inf + inf i", FUNC(ccos) (BUILD_COMPLEX (-4.625, minus_infty)), BUILD_COMPLEX (minus_infty, plus_infty), 0, 0, 0);
+
+ check_complex ("ccos (inf + 6.75 i) == NaN + NaN i plus invalid exception", FUNC(ccos) (BUILD_COMPLEX (plus_infty, 6.75)), BUILD_COMPLEX (nan_value, nan_value), 0, 0, INVALID_EXCEPTION);
+ check_complex ("ccos (inf - 6.75 i) == NaN + NaN i plus invalid exception", FUNC(ccos) (BUILD_COMPLEX (plus_infty, -6.75)), BUILD_COMPLEX (nan_value, nan_value), 0, 0, INVALID_EXCEPTION);
+ check_complex ("ccos (-inf + 6.75 i) == NaN + NaN i plus invalid exception", FUNC(ccos) (BUILD_COMPLEX (minus_infty, 6.75)), BUILD_COMPLEX (nan_value, nan_value), 0, 0, INVALID_EXCEPTION);
+ check_complex ("ccos (-inf - 6.75 i) == NaN + NaN i plus invalid exception", FUNC(ccos) (BUILD_COMPLEX (minus_infty, -6.75)), BUILD_COMPLEX (nan_value, nan_value), 0, 0, INVALID_EXCEPTION);
+
+ check_complex ("ccos (NaN + 0.0 i) == NaN + 0.0 i plus sign of zero/inf not specified", FUNC(ccos) (BUILD_COMPLEX (nan_value, 0.0)), BUILD_COMPLEX (nan_value, 0.0), 0, 0, IGNORE_ZERO_INF_SIGN);
+ check_complex ("ccos (NaN - 0 i) == NaN + 0.0 i plus sign of zero/inf not specified", FUNC(ccos) (BUILD_COMPLEX (nan_value, minus_zero)), BUILD_COMPLEX (nan_value, 0.0), 0, 0, IGNORE_ZERO_INF_SIGN);
+
+ check_complex ("ccos (NaN + inf i) == inf + NaN i", FUNC(ccos) (BUILD_COMPLEX (nan_value, plus_infty)), BUILD_COMPLEX (plus_infty, nan_value), 0, 0, 0);
+ check_complex ("ccos (NaN - inf i) == inf + NaN i", FUNC(ccos) (BUILD_COMPLEX (nan_value, minus_infty)), BUILD_COMPLEX (plus_infty, nan_value), 0, 0, 0);
+
+ check_complex ("ccos (NaN + 9.0 i) == NaN + NaN i plus invalid exception allowed", FUNC(ccos) (BUILD_COMPLEX (nan_value, 9.0)), BUILD_COMPLEX (nan_value, nan_value), 0, 0, INVALID_EXCEPTION_OK);
+ check_complex ("ccos (NaN - 9.0 i) == NaN + NaN i plus invalid exception allowed", FUNC(ccos) (BUILD_COMPLEX (nan_value, -9.0)), BUILD_COMPLEX (nan_value, nan_value), 0, 0, INVALID_EXCEPTION_OK);
+
+ check_complex ("ccos (0.0 + NaN i) == NaN + 0.0 i plus sign of zero/inf not specified", FUNC(ccos) (BUILD_COMPLEX (0.0, nan_value)), BUILD_COMPLEX (nan_value, 0.0), 0, 0, IGNORE_ZERO_INF_SIGN);
+ check_complex ("ccos (-0 + NaN i) == NaN + 0.0 i plus sign of zero/inf not specified", FUNC(ccos) (BUILD_COMPLEX (minus_zero, nan_value)), BUILD_COMPLEX (nan_value, 0.0), 0, 0, IGNORE_ZERO_INF_SIGN);
+
+ check_complex ("ccos (10.0 + NaN i) == NaN + NaN i plus invalid exception allowed", FUNC(ccos) (BUILD_COMPLEX (10.0, nan_value)), BUILD_COMPLEX (nan_value, nan_value), 0, 0, INVALID_EXCEPTION_OK);
+ check_complex ("ccos (-10.0 + NaN i) == NaN + NaN i plus invalid exception allowed", FUNC(ccos) (BUILD_COMPLEX (-10.0, nan_value)), BUILD_COMPLEX (nan_value, nan_value), 0, 0, INVALID_EXCEPTION_OK);
+
+ check_complex ("ccos (inf + NaN i) == NaN + NaN i plus invalid exception allowed", FUNC(ccos) (BUILD_COMPLEX (plus_infty, nan_value)), BUILD_COMPLEX (nan_value, nan_value), 0, 0, INVALID_EXCEPTION_OK);
+ check_complex ("ccos (-inf + NaN i) == NaN + NaN i plus invalid exception allowed", FUNC(ccos) (BUILD_COMPLEX (minus_infty, nan_value)), BUILD_COMPLEX (nan_value, nan_value), 0, 0, INVALID_EXCEPTION_OK);
+
+ check_complex ("ccos (NaN + NaN i) == NaN + NaN i", FUNC(ccos) (BUILD_COMPLEX (nan_value, nan_value)), BUILD_COMPLEX (nan_value, nan_value), 0, 0, 0);
+
+ check_complex ("ccos (0.7 + 1.2 i) == 1.3848657645312111080 - 0.97242170335830028619 i", FUNC(ccos) (BUILD_COMPLEX (0.7L, 1.2L)), BUILD_COMPLEX (1.3848657645312111080L, -0.97242170335830028619L), DELTA389, 0, 0);
+
+ check_complex ("ccos (-2 - 3 i) == -4.1896256909688072301 - 9.1092278937553365979 i", FUNC(ccos) (BUILD_COMPLEX (-2, -3)), BUILD_COMPLEX (-4.1896256909688072301L, -9.1092278937553365979L), DELTA390, 0, 0);
+
+ print_complex_max_error ("ccos", DELTAccos, 0);
+}
+
+
+static void
+ccosh_test (void)
+{
+ errno = 0;
+ FUNC(ccosh) (BUILD_COMPLEX (0.7L, 1.2L));
+ if (errno == ENOSYS)
+ /* Function not implemented. */
+ return;
+
+ init_max_error ();
+
+ check_complex ("ccosh (0.0 + 0.0 i) == 1.0 + 0.0 i", FUNC(ccosh) (BUILD_COMPLEX (0.0, 0.0)), BUILD_COMPLEX (1.0, 0.0), 0, 0, 0);
+ check_complex ("ccosh (-0 + 0.0 i) == 1.0 - 0 i", FUNC(ccosh) (BUILD_COMPLEX (minus_zero, 0.0)), BUILD_COMPLEX (1.0, minus_zero), 0, 0, 0);
+ check_complex ("ccosh (0.0 - 0 i) == 1.0 - 0 i", FUNC(ccosh) (BUILD_COMPLEX (0.0, minus_zero)), BUILD_COMPLEX (1.0, minus_zero), 0, 0, 0);
+ check_complex ("ccosh (-0 - 0 i) == 1.0 + 0.0 i", FUNC(ccosh) (BUILD_COMPLEX (minus_zero, minus_zero)), BUILD_COMPLEX (1.0, 0.0), 0, 0, 0);
+
+ check_complex ("ccosh (0.0 + inf i) == NaN + 0.0 i plus invalid exception and sign of zero/inf not specified", FUNC(ccosh) (BUILD_COMPLEX (0.0, plus_infty)), BUILD_COMPLEX (nan_value, 0.0), 0, 0, INVALID_EXCEPTION|IGNORE_ZERO_INF_SIGN);
+ check_complex ("ccosh (-0 + inf i) == NaN + 0.0 i plus invalid exception and sign of zero/inf not specified", FUNC(ccosh) (BUILD_COMPLEX (minus_zero, plus_infty)), BUILD_COMPLEX (nan_value, 0.0), 0, 0, INVALID_EXCEPTION|IGNORE_ZERO_INF_SIGN);
+ check_complex ("ccosh (0.0 - inf i) == NaN + 0.0 i plus invalid exception and sign of zero/inf not specified", FUNC(ccosh) (BUILD_COMPLEX (0.0, minus_infty)), BUILD_COMPLEX (nan_value, 0.0), 0, 0, INVALID_EXCEPTION|IGNORE_ZERO_INF_SIGN);
+ check_complex ("ccosh (-0 - inf i) == NaN + 0.0 i plus invalid exception and sign of zero/inf not specified", FUNC(ccosh) (BUILD_COMPLEX (minus_zero, minus_infty)), BUILD_COMPLEX (nan_value, 0.0), 0, 0, INVALID_EXCEPTION|IGNORE_ZERO_INF_SIGN);
+
+ check_complex ("ccosh (inf + 0.0 i) == inf + 0.0 i", FUNC(ccosh) (BUILD_COMPLEX (plus_infty, 0.0)), BUILD_COMPLEX (plus_infty, 0.0), 0, 0, 0);
+ check_complex ("ccosh (-inf + 0.0 i) == inf - 0 i", FUNC(ccosh) (BUILD_COMPLEX (minus_infty, 0.0)), BUILD_COMPLEX (plus_infty, minus_zero), 0, 0, 0);
+ check_complex ("ccosh (inf - 0 i) == inf - 0 i", FUNC(ccosh) (BUILD_COMPLEX (plus_infty, minus_zero)), BUILD_COMPLEX (plus_infty, minus_zero), 0, 0, 0);
+ check_complex ("ccosh (-inf - 0 i) == inf + 0.0 i", FUNC(ccosh) (BUILD_COMPLEX (minus_infty, minus_zero)), BUILD_COMPLEX (plus_infty, 0.0), 0, 0, 0);
+
+ check_complex ("ccosh (inf + inf i) == inf + NaN i plus invalid exception", FUNC(ccosh) (BUILD_COMPLEX (plus_infty, plus_infty)), BUILD_COMPLEX (plus_infty, nan_value), 0, 0, INVALID_EXCEPTION);
+ check_complex ("ccosh (-inf + inf i) == inf + NaN i plus invalid exception", FUNC(ccosh) (BUILD_COMPLEX (minus_infty, plus_infty)), BUILD_COMPLEX (plus_infty, nan_value), 0, 0, INVALID_EXCEPTION);
+ check_complex ("ccosh (inf - inf i) == inf + NaN i plus invalid exception", FUNC(ccosh) (BUILD_COMPLEX (plus_infty, minus_infty)), BUILD_COMPLEX (plus_infty, nan_value), 0, 0, INVALID_EXCEPTION);
+ check_complex ("ccosh (-inf - inf i) == inf + NaN i plus invalid exception", FUNC(ccosh) (BUILD_COMPLEX (minus_infty, minus_infty)), BUILD_COMPLEX (plus_infty, nan_value), 0, 0, INVALID_EXCEPTION);
+
+ check_complex ("ccosh (inf + 4.625 i) == -inf - inf i", FUNC(ccosh) (BUILD_COMPLEX (plus_infty, 4.625)), BUILD_COMPLEX (minus_infty, minus_infty), 0, 0, 0);
+ check_complex ("ccosh (-inf + 4.625 i) == -inf + inf i", FUNC(ccosh) (BUILD_COMPLEX (minus_infty, 4.625)), BUILD_COMPLEX (minus_infty, plus_infty), 0, 0, 0);
+ check_complex ("ccosh (inf - 4.625 i) == -inf + inf i", FUNC(ccosh) (BUILD_COMPLEX (plus_infty, -4.625)), BUILD_COMPLEX (minus_infty, plus_infty), 0, 0, 0);
+ check_complex ("ccosh (-inf - 4.625 i) == -inf - inf i", FUNC(ccosh) (BUILD_COMPLEX (minus_infty, -4.625)), BUILD_COMPLEX (minus_infty, minus_infty), 0, 0, 0);
+
+ check_complex ("ccosh (6.75 + inf i) == NaN + NaN i plus invalid exception", FUNC(ccosh) (BUILD_COMPLEX (6.75, plus_infty)), BUILD_COMPLEX (nan_value, nan_value), 0, 0, INVALID_EXCEPTION);
+ check_complex ("ccosh (-6.75 + inf i) == NaN + NaN i plus invalid exception", FUNC(ccosh) (BUILD_COMPLEX (-6.75, plus_infty)), BUILD_COMPLEX (nan_value, nan_value), 0, 0, INVALID_EXCEPTION);
+ check_complex ("ccosh (6.75 - inf i) == NaN + NaN i plus invalid exception", FUNC(ccosh) (BUILD_COMPLEX (6.75, minus_infty)), BUILD_COMPLEX (nan_value, nan_value), 0, 0, INVALID_EXCEPTION);
+ check_complex ("ccosh (-6.75 - inf i) == NaN + NaN i plus invalid exception", FUNC(ccosh) (BUILD_COMPLEX (-6.75, minus_infty)), BUILD_COMPLEX (nan_value, nan_value), 0, 0, INVALID_EXCEPTION);
+
+ check_complex ("ccosh (0.0 + NaN i) == NaN + 0.0 i plus sign of zero/inf not specified", FUNC(ccosh) (BUILD_COMPLEX (0.0, nan_value)), BUILD_COMPLEX (nan_value, 0.0), 0, 0, IGNORE_ZERO_INF_SIGN);
+ check_complex ("ccosh (-0 + NaN i) == NaN + 0.0 i plus sign of zero/inf not specified", FUNC(ccosh) (BUILD_COMPLEX (minus_zero, nan_value)), BUILD_COMPLEX (nan_value, 0.0), 0, 0, IGNORE_ZERO_INF_SIGN);
+
+ check_complex ("ccosh (inf + NaN i) == inf + NaN i", FUNC(ccosh) (BUILD_COMPLEX (plus_infty, nan_value)), BUILD_COMPLEX (plus_infty, nan_value), 0, 0, 0);
+ check_complex ("ccosh (-inf + NaN i) == inf + NaN i", FUNC(ccosh) (BUILD_COMPLEX (minus_infty, nan_value)), BUILD_COMPLEX (plus_infty, nan_value), 0, 0, 0);
+
+ check_complex ("ccosh (9.0 + NaN i) == NaN + NaN i plus invalid exception allowed", FUNC(ccosh) (BUILD_COMPLEX (9.0, nan_value)), BUILD_COMPLEX (nan_value, nan_value), 0, 0, INVALID_EXCEPTION_OK);
+ check_complex ("ccosh (-9.0 + NaN i) == NaN + NaN i plus invalid exception allowed", FUNC(ccosh) (BUILD_COMPLEX (-9.0, nan_value)), BUILD_COMPLEX (nan_value, nan_value), 0, 0, INVALID_EXCEPTION_OK);
+
+ check_complex ("ccosh (NaN + 0.0 i) == NaN + 0.0 i plus sign of zero/inf not specified", FUNC(ccosh) (BUILD_COMPLEX (nan_value, 0.0)), BUILD_COMPLEX (nan_value, 0.0), 0, 0, IGNORE_ZERO_INF_SIGN);
+ check_complex ("ccosh (NaN - 0 i) == NaN + 0.0 i plus sign of zero/inf not specified", FUNC(ccosh) (BUILD_COMPLEX (nan_value, minus_zero)), BUILD_COMPLEX (nan_value, 0.0), 0, 0, IGNORE_ZERO_INF_SIGN);
+
+ check_complex ("ccosh (NaN + 10.0 i) == NaN + NaN i plus invalid exception allowed", FUNC(ccosh) (BUILD_COMPLEX (nan_value, 10.0)), BUILD_COMPLEX (nan_value, nan_value), 0, 0, INVALID_EXCEPTION_OK);
+ check_complex ("ccosh (NaN - 10.0 i) == NaN + NaN i plus invalid exception allowed", FUNC(ccosh) (BUILD_COMPLEX (nan_value, -10.0)), BUILD_COMPLEX (nan_value, nan_value), 0, 0, INVALID_EXCEPTION_OK);
+
+ check_complex ("ccosh (NaN + inf i) == NaN + NaN i plus invalid exception allowed", FUNC(ccosh) (BUILD_COMPLEX (nan_value, plus_infty)), BUILD_COMPLEX (nan_value, nan_value), 0, 0, INVALID_EXCEPTION_OK);
+ check_complex ("ccosh (NaN - inf i) == NaN + NaN i plus invalid exception allowed", FUNC(ccosh) (BUILD_COMPLEX (nan_value, minus_infty)), BUILD_COMPLEX (nan_value, nan_value), 0, 0, INVALID_EXCEPTION_OK);
+
+ check_complex ("ccosh (NaN + NaN i) == NaN + NaN i", FUNC(ccosh) (BUILD_COMPLEX (nan_value, nan_value)), BUILD_COMPLEX (nan_value, nan_value), 0, 0, 0);
+
+ check_complex ("ccosh (0.7 + 1.2 i) == 0.4548202223691477654 + 0.7070296600921537682 i", FUNC(ccosh) (BUILD_COMPLEX (0.7L, 1.2L)), BUILD_COMPLEX (0.4548202223691477654L, 0.7070296600921537682L), DELTA428, 0, 0);
+
+ check_complex ("ccosh (-2 - 3 i) == -3.7245455049153225654 + 0.5118225699873846088 i", FUNC(ccosh) (BUILD_COMPLEX (-2, -3)), BUILD_COMPLEX (-3.7245455049153225654L, 0.5118225699873846088L), DELTA429, 0, 0);
+
+ print_complex_max_error ("ccosh", DELTAccosh, 0);
+}
+#endif
+
+
+static void
+ceil_test (void)
+{
+ init_max_error ();
+
+ check_float ("ceil (0.0) == 0.0", FUNC(ceil) (0.0), 0.0, 0, 0, 0);
+ check_float ("ceil (-0) == -0", FUNC(ceil) (minus_zero), minus_zero, 0, 0, 0);
+ check_float ("ceil (inf) == inf", FUNC(ceil) (plus_infty), plus_infty, 0, 0, 0);
+ check_float ("ceil (-inf) == -inf", FUNC(ceil) (minus_infty), minus_infty, 0, 0, 0);
+ check_float ("ceil (NaN) == NaN", FUNC(ceil) (nan_value), nan_value, 0, 0, 0);
+
+ check_float ("ceil (pi) == 4.0", FUNC(ceil) (M_PIl), 4.0, 0, 0, 0);
+ check_float ("ceil (-pi) == -3.0", FUNC(ceil) (-M_PIl), -3.0, 0, 0, 0);
+
+ print_max_error ("ceil", 0, 0);
+}
+
+
+#if 0 /* XXX scp XXX */
+static void
+cexp_test (void)
+{
+ errno = 0;
+ FUNC(cexp) (BUILD_COMPLEX (0, 0));
+ if (errno == ENOSYS)
+ /* Function not implemented. */
+ return;
+
+ init_max_error ();
+
+ check_complex ("cexp (+0 + +0 i) == 1 + 0.0 i", FUNC(cexp) (BUILD_COMPLEX (plus_zero, plus_zero)), BUILD_COMPLEX (1, 0.0), 0, 0, 0);
+ check_complex ("cexp (-0 + +0 i) == 1 + 0.0 i", FUNC(cexp) (BUILD_COMPLEX (minus_zero, plus_zero)), BUILD_COMPLEX (1, 0.0), 0, 0, 0);
+ check_complex ("cexp (+0 - 0 i) == 1 - 0 i", FUNC(cexp) (BUILD_COMPLEX (plus_zero, minus_zero)), BUILD_COMPLEX (1, minus_zero), 0, 0, 0);
+ check_complex ("cexp (-0 - 0 i) == 1 - 0 i", FUNC(cexp) (BUILD_COMPLEX (minus_zero, minus_zero)), BUILD_COMPLEX (1, minus_zero), 0, 0, 0);
+
+ check_complex ("cexp (inf + +0 i) == inf + 0.0 i", FUNC(cexp) (BUILD_COMPLEX (plus_infty, plus_zero)), BUILD_COMPLEX (plus_infty, 0.0), 0, 0, 0);
+ check_complex ("cexp (inf - 0 i) == inf - 0 i", FUNC(cexp) (BUILD_COMPLEX (plus_infty, minus_zero)), BUILD_COMPLEX (plus_infty, minus_zero), 0, 0, 0);
+
+ check_complex ("cexp (-inf + +0 i) == 0.0 + 0.0 i", FUNC(cexp) (BUILD_COMPLEX (minus_infty, plus_zero)), BUILD_COMPLEX (0.0, 0.0), 0, 0, 0);
+ check_complex ("cexp (-inf - 0 i) == 0.0 - 0 i", FUNC(cexp) (BUILD_COMPLEX (minus_infty, minus_zero)), BUILD_COMPLEX (0.0, minus_zero), 0, 0, 0);
+
+ check_complex ("cexp (0.0 + inf i) == NaN + NaN i plus invalid exception", FUNC(cexp) (BUILD_COMPLEX (0.0, plus_infty)), BUILD_COMPLEX (nan_value, nan_value), 0, 0, INVALID_EXCEPTION);
+ check_complex ("cexp (-0 + inf i) == NaN + NaN i plus invalid exception", FUNC(cexp) (BUILD_COMPLEX (minus_zero, plus_infty)), BUILD_COMPLEX (nan_value, nan_value), 0, 0, INVALID_EXCEPTION);
+
+ check_complex ("cexp (0.0 - inf i) == NaN + NaN i plus invalid exception", FUNC(cexp) (BUILD_COMPLEX (0.0, minus_infty)), BUILD_COMPLEX (nan_value, nan_value), 0, 0, INVALID_EXCEPTION);
+ check_complex ("cexp (-0 - inf i) == NaN + NaN i plus invalid exception", FUNC(cexp) (BUILD_COMPLEX (minus_zero, minus_infty)), BUILD_COMPLEX (nan_value, nan_value), 0, 0, INVALID_EXCEPTION);
+
+ check_complex ("cexp (100.0 + inf i) == NaN + NaN i plus invalid exception", FUNC(cexp) (BUILD_COMPLEX (100.0, plus_infty)), BUILD_COMPLEX (nan_value, nan_value), 0, 0, INVALID_EXCEPTION);
+ check_complex ("cexp (-100.0 + inf i) == NaN + NaN i plus invalid exception", FUNC(cexp) (BUILD_COMPLEX (-100.0, plus_infty)), BUILD_COMPLEX (nan_value, nan_value), 0, 0, INVALID_EXCEPTION);
+
+ check_complex ("cexp (100.0 - inf i) == NaN + NaN i plus invalid exception", FUNC(cexp) (BUILD_COMPLEX (100.0, minus_infty)), BUILD_COMPLEX (nan_value, nan_value), 0, 0, INVALID_EXCEPTION);
+ check_complex ("cexp (-100.0 - inf i) == NaN + NaN i plus invalid exception", FUNC(cexp) (BUILD_COMPLEX (-100.0, minus_infty)), BUILD_COMPLEX (nan_value, nan_value), 0, 0, INVALID_EXCEPTION);
+
+ check_complex ("cexp (-inf + 2.0 i) == -0 + 0.0 i", FUNC(cexp) (BUILD_COMPLEX (minus_infty, 2.0)), BUILD_COMPLEX (minus_zero, 0.0), 0, 0, 0);
+ check_complex ("cexp (-inf + 4.0 i) == -0 - 0 i", FUNC(cexp) (BUILD_COMPLEX (minus_infty, 4.0)), BUILD_COMPLEX (minus_zero, minus_zero), 0, 0, 0);
+ check_complex ("cexp (inf + 2.0 i) == -inf + inf i", FUNC(cexp) (BUILD_COMPLEX (plus_infty, 2.0)), BUILD_COMPLEX (minus_infty, plus_infty), 0, 0, 0);
+ check_complex ("cexp (inf + 4.0 i) == -inf - inf i", FUNC(cexp) (BUILD_COMPLEX (plus_infty, 4.0)), BUILD_COMPLEX (minus_infty, minus_infty), 0, 0, 0);
+
+ check_complex ("cexp (inf + inf i) == inf + NaN i plus invalid exception and sign of zero/inf not specified", FUNC(cexp) (BUILD_COMPLEX (plus_infty, plus_infty)), BUILD_COMPLEX (plus_infty, nan_value), 0, 0, INVALID_EXCEPTION|IGNORE_ZERO_INF_SIGN);
+ check_complex ("cexp (inf - inf i) == inf + NaN i plus invalid exception and sign of zero/inf not specified", FUNC(cexp) (BUILD_COMPLEX (plus_infty, minus_infty)), BUILD_COMPLEX (plus_infty, nan_value), 0, 0, INVALID_EXCEPTION|IGNORE_ZERO_INF_SIGN);
+
+ check_complex ("cexp (-inf + inf i) == 0.0 + 0.0 i plus sign of zero/inf not specified", FUNC(cexp) (BUILD_COMPLEX (minus_infty, plus_infty)), BUILD_COMPLEX (0.0, 0.0), 0, 0, IGNORE_ZERO_INF_SIGN);
+ check_complex ("cexp (-inf - inf i) == 0.0 - 0 i plus sign of zero/inf not specified", FUNC(cexp) (BUILD_COMPLEX (minus_infty, minus_infty)), BUILD_COMPLEX (0.0, minus_zero), 0, 0, IGNORE_ZERO_INF_SIGN);
+
+ check_complex ("cexp (-inf + NaN i) == 0 + 0 i plus sign of zero/inf not specified", FUNC(cexp) (BUILD_COMPLEX (minus_infty, nan_value)), BUILD_COMPLEX (0, 0), 0, 0, IGNORE_ZERO_INF_SIGN);
+
+ check_complex ("cexp (inf + NaN i) == inf + NaN i", FUNC(cexp) (BUILD_COMPLEX (plus_infty, nan_value)), BUILD_COMPLEX (plus_infty, nan_value), 0, 0, 0);
+
+ check_complex ("cexp (NaN + 0.0 i) == NaN + NaN i plus invalid exception allowed", FUNC(cexp) (BUILD_COMPLEX (nan_value, 0.0)), BUILD_COMPLEX (nan_value, nan_value), 0, 0, INVALID_EXCEPTION_OK);
+ check_complex ("cexp (NaN + 1.0 i) == NaN + NaN i plus invalid exception allowed", FUNC(cexp) (BUILD_COMPLEX (nan_value, 1.0)), BUILD_COMPLEX (nan_value, nan_value), 0, 0, INVALID_EXCEPTION_OK);
+
+ check_complex ("cexp (NaN + inf i) == NaN + NaN i plus invalid exception allowed", FUNC(cexp) (BUILD_COMPLEX (nan_value, plus_infty)), BUILD_COMPLEX (nan_value, nan_value), 0, 0, INVALID_EXCEPTION_OK);
+ check_complex ("cexp (0 + NaN i) == NaN + NaN i plus invalid exception allowed", FUNC(cexp) (BUILD_COMPLEX (0, nan_value)), BUILD_COMPLEX (nan_value, nan_value), 0, 0, INVALID_EXCEPTION_OK);
+ check_complex ("cexp (1 + NaN i) == NaN + NaN i plus invalid exception allowed", FUNC(cexp) (BUILD_COMPLEX (1, nan_value)), BUILD_COMPLEX (nan_value, nan_value), 0, 0, INVALID_EXCEPTION_OK);
+ check_complex ("cexp (NaN + NaN i) == NaN + NaN i", FUNC(cexp) (BUILD_COMPLEX (nan_value, nan_value)), BUILD_COMPLEX (nan_value, nan_value), 0, 0, 0);
+
+ check_complex ("cexp (0.7 + 1.2 i) == 0.72969890915032360123451688642930727 + 1.8768962328348102821139467908203072 i", FUNC(cexp) (BUILD_COMPLEX (0.7L, 1.2L)), BUILD_COMPLEX (0.72969890915032360123451688642930727L, 1.8768962328348102821139467908203072L), DELTA469, 0, 0);
+ check_complex ("cexp (-2.0 - 3.0 i) == -0.13398091492954261346140525546115575 - 0.019098516261135196432576240858800925 i", FUNC(cexp) (BUILD_COMPLEX (-2.0, -3.0)), BUILD_COMPLEX (-0.13398091492954261346140525546115575L, -0.019098516261135196432576240858800925L), DELTA470, 0, 0);
+
+ print_complex_max_error ("cexp", DELTAcexp, 0);
+}
+
+static void
+cimag_test (void)
+{
+ init_max_error ();
+ check_float ("cimag (1.0 + 0.0 i) == 0.0", FUNC(cimag) (BUILD_COMPLEX (1.0, 0.0)), 0.0, 0, 0, 0);
+ check_float ("cimag (1.0 - 0 i) == -0", FUNC(cimag) (BUILD_COMPLEX (1.0, minus_zero)), minus_zero, 0, 0, 0);
+ check_float ("cimag (1.0 + NaN i) == NaN", FUNC(cimag) (BUILD_COMPLEX (1.0, nan_value)), nan_value, 0, 0, 0);
+ check_float ("cimag (NaN + NaN i) == NaN", FUNC(cimag) (BUILD_COMPLEX (nan_value, nan_value)), nan_value, 0, 0, 0);
+ check_float ("cimag (1.0 + inf i) == inf", FUNC(cimag) (BUILD_COMPLEX (1.0, plus_infty)), plus_infty, 0, 0, 0);
+ check_float ("cimag (1.0 - inf i) == -inf", FUNC(cimag) (BUILD_COMPLEX (1.0, minus_infty)), minus_infty, 0, 0, 0);
+ check_float ("cimag (2.0 + 3.0 i) == 3.0", FUNC(cimag) (BUILD_COMPLEX (2.0, 3.0)), 3.0, 0, 0, 0);
+
+ print_max_error ("cimag", 0, 0);
+}
+
+static void
+clog_test (void)
+{
+ errno = 0;
+ FUNC(clog) (BUILD_COMPLEX (-2, -3));
+ if (errno == ENOSYS)
+ /* Function not implemented. */
+ return;
+
+ init_max_error ();
+
+ check_complex ("clog (-0 + 0 i) == -inf + pi i plus division by zero exception", FUNC(clog) (BUILD_COMPLEX (minus_zero, 0)), BUILD_COMPLEX (minus_infty, M_PIl), 0, 0, DIVIDE_BY_ZERO_EXCEPTION);
+ check_complex ("clog (-0 - 0 i) == -inf - pi i plus division by zero exception", FUNC(clog) (BUILD_COMPLEX (minus_zero, minus_zero)), BUILD_COMPLEX (minus_infty, -M_PIl), 0, 0, DIVIDE_BY_ZERO_EXCEPTION);
+
+ check_complex ("clog (0 + 0 i) == -inf + 0.0 i plus division by zero exception", FUNC(clog) (BUILD_COMPLEX (0, 0)), BUILD_COMPLEX (minus_infty, 0.0), 0, 0, DIVIDE_BY_ZERO_EXCEPTION);
+ check_complex ("clog (0 - 0 i) == -inf - 0 i plus division by zero exception", FUNC(clog) (BUILD_COMPLEX (0, minus_zero)), BUILD_COMPLEX (minus_infty, minus_zero), 0, 0, DIVIDE_BY_ZERO_EXCEPTION);
+
+ check_complex ("clog (-inf + inf i) == inf + 3/4 pi i", FUNC(clog) (BUILD_COMPLEX (minus_infty, plus_infty)), BUILD_COMPLEX (plus_infty, M_PI_34l), 0, 0, 0);
+ check_complex ("clog (-inf - inf i) == inf - 3/4 pi i", FUNC(clog) (BUILD_COMPLEX (minus_infty, minus_infty)), BUILD_COMPLEX (plus_infty, -M_PI_34l), 0, 0, 0);
+
+ check_complex ("clog (inf + inf i) == inf + pi/4 i", FUNC(clog) (BUILD_COMPLEX (plus_infty, plus_infty)), BUILD_COMPLEX (plus_infty, M_PI_4l), 0, 0, 0);
+ check_complex ("clog (inf - inf i) == inf - pi/4 i", FUNC(clog) (BUILD_COMPLEX (plus_infty, minus_infty)), BUILD_COMPLEX (plus_infty, -M_PI_4l), 0, 0, 0);
+
+ check_complex ("clog (0 + inf i) == inf + pi/2 i", FUNC(clog) (BUILD_COMPLEX (0, plus_infty)), BUILD_COMPLEX (plus_infty, M_PI_2l), 0, 0, 0);
+ check_complex ("clog (3 + inf i) == inf + pi/2 i", FUNC(clog) (BUILD_COMPLEX (3, plus_infty)), BUILD_COMPLEX (plus_infty, M_PI_2l), 0, 0, 0);
+ check_complex ("clog (-0 + inf i) == inf + pi/2 i", FUNC(clog) (BUILD_COMPLEX (minus_zero, plus_infty)), BUILD_COMPLEX (plus_infty, M_PI_2l), 0, 0, 0);
+ check_complex ("clog (-3 + inf i) == inf + pi/2 i", FUNC(clog) (BUILD_COMPLEX (-3, plus_infty)), BUILD_COMPLEX (plus_infty, M_PI_2l), 0, 0, 0);
+ check_complex ("clog (0 - inf i) == inf - pi/2 i", FUNC(clog) (BUILD_COMPLEX (0, minus_infty)), BUILD_COMPLEX (plus_infty, -M_PI_2l), 0, 0, 0);
+ check_complex ("clog (3 - inf i) == inf - pi/2 i", FUNC(clog) (BUILD_COMPLEX (3, minus_infty)), BUILD_COMPLEX (plus_infty, -M_PI_2l), 0, 0, 0);
+ check_complex ("clog (-0 - inf i) == inf - pi/2 i", FUNC(clog) (BUILD_COMPLEX (minus_zero, minus_infty)), BUILD_COMPLEX (plus_infty, -M_PI_2l), 0, 0, 0);
+ check_complex ("clog (-3 - inf i) == inf - pi/2 i", FUNC(clog) (BUILD_COMPLEX (-3, minus_infty)), BUILD_COMPLEX (plus_infty, -M_PI_2l), 0, 0, 0);
+
+ check_complex ("clog (-inf + 0 i) == inf + pi i", FUNC(clog) (BUILD_COMPLEX (minus_infty, 0)), BUILD_COMPLEX (plus_infty, M_PIl), 0, 0, 0);
+ check_complex ("clog (-inf + 1 i) == inf + pi i", FUNC(clog) (BUILD_COMPLEX (minus_infty, 1)), BUILD_COMPLEX (plus_infty, M_PIl), 0, 0, 0);
+ check_complex ("clog (-inf - 0 i) == inf - pi i", FUNC(clog) (BUILD_COMPLEX (minus_infty, minus_zero)), BUILD_COMPLEX (plus_infty, -M_PIl), 0, 0, 0);
+ check_complex ("clog (-inf - 1 i) == inf - pi i", FUNC(clog) (BUILD_COMPLEX (minus_infty, -1)), BUILD_COMPLEX (plus_infty, -M_PIl), 0, 0, 0);
+
+ check_complex ("clog (inf + 0 i) == inf + 0.0 i", FUNC(clog) (BUILD_COMPLEX (plus_infty, 0)), BUILD_COMPLEX (plus_infty, 0.0), 0, 0, 0);
+ check_complex ("clog (inf + 1 i) == inf + 0.0 i", FUNC(clog) (BUILD_COMPLEX (plus_infty, 1)), BUILD_COMPLEX (plus_infty, 0.0), 0, 0, 0);
+ check_complex ("clog (inf - 0 i) == inf - 0 i", FUNC(clog) (BUILD_COMPLEX (plus_infty, minus_zero)), BUILD_COMPLEX (plus_infty, minus_zero), 0, 0, 0);
+ check_complex ("clog (inf - 1 i) == inf - 0 i", FUNC(clog) (BUILD_COMPLEX (plus_infty, -1)), BUILD_COMPLEX (plus_infty, minus_zero), 0, 0, 0);
+
+ check_complex ("clog (inf + NaN i) == inf + NaN i", FUNC(clog) (BUILD_COMPLEX (plus_infty, nan_value)), BUILD_COMPLEX (plus_infty, nan_value), 0, 0, 0);
+ check_complex ("clog (-inf + NaN i) == inf + NaN i", FUNC(clog) (BUILD_COMPLEX (minus_infty, nan_value)), BUILD_COMPLEX (plus_infty, nan_value), 0, 0, 0);
+
+ check_complex ("clog (NaN + inf i) == inf + NaN i", FUNC(clog) (BUILD_COMPLEX (nan_value, plus_infty)), BUILD_COMPLEX (plus_infty, nan_value), 0, 0, 0);
+ check_complex ("clog (NaN - inf i) == inf + NaN i", FUNC(clog) (BUILD_COMPLEX (nan_value, minus_infty)), BUILD_COMPLEX (plus_infty, nan_value), 0, 0, 0);
+
+ check_complex ("clog (0 + NaN i) == NaN + NaN i plus invalid exception allowed", FUNC(clog) (BUILD_COMPLEX (0, nan_value)), BUILD_COMPLEX (nan_value, nan_value), 0, 0, INVALID_EXCEPTION_OK);
+ check_complex ("clog (3 + NaN i) == NaN + NaN i plus invalid exception allowed", FUNC(clog) (BUILD_COMPLEX (3, nan_value)), BUILD_COMPLEX (nan_value, nan_value), 0, 0, INVALID_EXCEPTION_OK);
+ check_complex ("clog (-0 + NaN i) == NaN + NaN i plus invalid exception allowed", FUNC(clog) (BUILD_COMPLEX (minus_zero, nan_value)), BUILD_COMPLEX (nan_value, nan_value), 0, 0, INVALID_EXCEPTION_OK);
+ check_complex ("clog (-3 + NaN i) == NaN + NaN i plus invalid exception allowed", FUNC(clog) (BUILD_COMPLEX (-3, nan_value)), BUILD_COMPLEX (nan_value, nan_value), 0, 0, INVALID_EXCEPTION_OK);
+
+ check_complex ("clog (NaN + 0 i) == NaN + NaN i plus invalid exception allowed", FUNC(clog) (BUILD_COMPLEX (nan_value, 0)), BUILD_COMPLEX (nan_value, nan_value), 0, 0, INVALID_EXCEPTION_OK);
+ check_complex ("clog (NaN + 5 i) == NaN + NaN i plus invalid exception allowed", FUNC(clog) (BUILD_COMPLEX (nan_value, 5)), BUILD_COMPLEX (nan_value, nan_value), 0, 0, INVALID_EXCEPTION_OK);
+ check_complex ("clog (NaN - 0 i) == NaN + NaN i plus invalid exception allowed", FUNC(clog) (BUILD_COMPLEX (nan_value, minus_zero)), BUILD_COMPLEX (nan_value, nan_value), 0, 0, INVALID_EXCEPTION_OK);
+ check_complex ("clog (NaN - 5 i) == NaN + NaN i plus invalid exception allowed", FUNC(clog) (BUILD_COMPLEX (nan_value, -5)), BUILD_COMPLEX (nan_value, nan_value), 0, 0, INVALID_EXCEPTION_OK);
+
+ check_complex ("clog (NaN + NaN i) == NaN + NaN i", FUNC(clog) (BUILD_COMPLEX (nan_value, nan_value)), BUILD_COMPLEX (nan_value, nan_value), 0, 0, 0);
+ check_complex ("clog (-2 - 3 i) == 1.2824746787307683680267437207826593 - 2.1587989303424641704769327722648368 i", FUNC(clog) (BUILD_COMPLEX (-2, -3)), BUILD_COMPLEX (1.2824746787307683680267437207826593L, -2.1587989303424641704769327722648368L), DELTA515, 0, 0);
+
+ print_complex_max_error ("clog", DELTAclog, 0);
+}
+
+
+static void
+clog10_test (void)
+{
+ errno = 0;
+ FUNC(clog10) (BUILD_COMPLEX (0.7L, 1.2L));
+ if (errno == ENOSYS)
+ /* Function not implemented. */
+ return;
+
+ init_max_error ();
+
+ check_complex ("clog10 (-0 + 0 i) == -inf + pi i plus division by zero exception", FUNC(clog10) (BUILD_COMPLEX (minus_zero, 0)), BUILD_COMPLEX (minus_infty, M_PIl), 0, 0, DIVIDE_BY_ZERO_EXCEPTION);
+ check_complex ("clog10 (-0 - 0 i) == -inf - pi i plus division by zero exception", FUNC(clog10) (BUILD_COMPLEX (minus_zero, minus_zero)), BUILD_COMPLEX (minus_infty, -M_PIl), 0, 0, DIVIDE_BY_ZERO_EXCEPTION);
+
+ check_complex ("clog10 (0 + 0 i) == -inf + 0.0 i plus division by zero exception", FUNC(clog10) (BUILD_COMPLEX (0, 0)), BUILD_COMPLEX (minus_infty, 0.0), 0, 0, DIVIDE_BY_ZERO_EXCEPTION);
+ check_complex ("clog10 (0 - 0 i) == -inf - 0 i plus division by zero exception", FUNC(clog10) (BUILD_COMPLEX (0, minus_zero)), BUILD_COMPLEX (minus_infty, minus_zero), 0, 0, DIVIDE_BY_ZERO_EXCEPTION);
+
+ check_complex ("clog10 (-inf + inf i) == inf + 3/4 pi*log10(e) i", FUNC(clog10) (BUILD_COMPLEX (minus_infty, plus_infty)), BUILD_COMPLEX (plus_infty, M_PI_34_LOG10El), DELTA520, 0, 0);
+
+ check_complex ("clog10 (inf + inf i) == inf + pi/4*log10(e) i", FUNC(clog10) (BUILD_COMPLEX (plus_infty, plus_infty)), BUILD_COMPLEX (plus_infty, M_PI4_LOG10El), DELTA521, 0, 0);
+ check_complex ("clog10 (inf - inf i) == inf - pi/4*log10(e) i", FUNC(clog10) (BUILD_COMPLEX (plus_infty, minus_infty)), BUILD_COMPLEX (plus_infty, -M_PI4_LOG10El), DELTA522, 0, 0);
+
+ check_complex ("clog10 (0 + inf i) == inf + pi/2*log10(e) i", FUNC(clog10) (BUILD_COMPLEX (0, plus_infty)), BUILD_COMPLEX (plus_infty, M_PI2_LOG10El), DELTA523, 0, 0);
+ check_complex ("clog10 (3 + inf i) == inf + pi/2*log10(e) i", FUNC(clog10) (BUILD_COMPLEX (3, plus_infty)), BUILD_COMPLEX (plus_infty, M_PI2_LOG10El), DELTA524, 0, 0);
+ check_complex ("clog10 (-0 + inf i) == inf + pi/2*log10(e) i", FUNC(clog10) (BUILD_COMPLEX (minus_zero, plus_infty)), BUILD_COMPLEX (plus_infty, M_PI2_LOG10El), DELTA525, 0, 0);
+ check_complex ("clog10 (-3 + inf i) == inf + pi/2*log10(e) i", FUNC(clog10) (BUILD_COMPLEX (-3, plus_infty)), BUILD_COMPLEX (plus_infty, M_PI2_LOG10El), DELTA526, 0, 0);
+ check_complex ("clog10 (0 - inf i) == inf - pi/2*log10(e) i", FUNC(clog10) (BUILD_COMPLEX (0, minus_infty)), BUILD_COMPLEX (plus_infty, -M_PI2_LOG10El), DELTA527, 0, 0);
+ check_complex ("clog10 (3 - inf i) == inf - pi/2*log10(e) i", FUNC(clog10) (BUILD_COMPLEX (3, minus_infty)), BUILD_COMPLEX (plus_infty, -M_PI2_LOG10El), DELTA528, 0, 0);
+ check_complex ("clog10 (-0 - inf i) == inf - pi/2*log10(e) i", FUNC(clog10) (BUILD_COMPLEX (minus_zero, minus_infty)), BUILD_COMPLEX (plus_infty, -M_PI2_LOG10El), DELTA529, 0, 0);
+ check_complex ("clog10 (-3 - inf i) == inf - pi/2*log10(e) i", FUNC(clog10) (BUILD_COMPLEX (-3, minus_infty)), BUILD_COMPLEX (plus_infty, -M_PI2_LOG10El), DELTA530, 0, 0);
+
+ check_complex ("clog10 (-inf + 0 i) == inf + pi*log10(e) i", FUNC(clog10) (BUILD_COMPLEX (minus_infty, 0)), BUILD_COMPLEX (plus_infty, M_PI_LOG10El), DELTA531, 0, 0);
+ check_complex ("clog10 (-inf + 1 i) == inf + pi*log10(e) i", FUNC(clog10) (BUILD_COMPLEX (minus_infty, 1)), BUILD_COMPLEX (plus_infty, M_PI_LOG10El), DELTA532, 0, 0);
+ check_complex ("clog10 (-inf - 0 i) == inf - pi*log10(e) i", FUNC(clog10) (BUILD_COMPLEX (minus_infty, minus_zero)), BUILD_COMPLEX (plus_infty, -M_PI_LOG10El), DELTA533, 0, 0);
+ check_complex ("clog10 (-inf - 1 i) == inf - pi*log10(e) i", FUNC(clog10) (BUILD_COMPLEX (minus_infty, -1)), BUILD_COMPLEX (plus_infty, -M_PI_LOG10El), DELTA534, 0, 0);
+
+ check_complex ("clog10 (inf + 0 i) == inf + 0.0 i", FUNC(clog10) (BUILD_COMPLEX (plus_infty, 0)), BUILD_COMPLEX (plus_infty, 0.0), 0, 0, 0);
+ check_complex ("clog10 (inf + 1 i) == inf + 0.0 i", FUNC(clog10) (BUILD_COMPLEX (plus_infty, 1)), BUILD_COMPLEX (plus_infty, 0.0), 0, 0, 0);
+ check_complex ("clog10 (inf - 0 i) == inf - 0 i", FUNC(clog10) (BUILD_COMPLEX (plus_infty, minus_zero)), BUILD_COMPLEX (plus_infty, minus_zero), 0, 0, 0);
+ check_complex ("clog10 (inf - 1 i) == inf - 0 i", FUNC(clog10) (BUILD_COMPLEX (plus_infty, -1)), BUILD_COMPLEX (plus_infty, minus_zero), 0, 0, 0);
+
+ check_complex ("clog10 (inf + NaN i) == inf + NaN i", FUNC(clog10) (BUILD_COMPLEX (plus_infty, nan_value)), BUILD_COMPLEX (plus_infty, nan_value), 0, 0, 0);
+ check_complex ("clog10 (-inf + NaN i) == inf + NaN i", FUNC(clog10) (BUILD_COMPLEX (minus_infty, nan_value)), BUILD_COMPLEX (plus_infty, nan_value), 0, 0, 0);
+
+ check_complex ("clog10 (NaN + inf i) == inf + NaN i", FUNC(clog10) (BUILD_COMPLEX (nan_value, plus_infty)), BUILD_COMPLEX (plus_infty, nan_value), 0, 0, 0);
+ check_complex ("clog10 (NaN - inf i) == inf + NaN i", FUNC(clog10) (BUILD_COMPLEX (nan_value, minus_infty)), BUILD_COMPLEX (plus_infty, nan_value), 0, 0, 0);
+
+ check_complex ("clog10 (0 + NaN i) == NaN + NaN i plus invalid exception allowed", FUNC(clog10) (BUILD_COMPLEX (0, nan_value)), BUILD_COMPLEX (nan_value, nan_value), 0, 0, INVALID_EXCEPTION_OK);
+ check_complex ("clog10 (3 + NaN i) == NaN + NaN i plus invalid exception allowed", FUNC(clog10) (BUILD_COMPLEX (3, nan_value)), BUILD_COMPLEX (nan_value, nan_value), 0, 0, INVALID_EXCEPTION_OK);
+ check_complex ("clog10 (-0 + NaN i) == NaN + NaN i plus invalid exception allowed", FUNC(clog10) (BUILD_COMPLEX (minus_zero, nan_value)), BUILD_COMPLEX (nan_value, nan_value), 0, 0, INVALID_EXCEPTION_OK);
+ check_complex ("clog10 (-3 + NaN i) == NaN + NaN i plus invalid exception allowed", FUNC(clog10) (BUILD_COMPLEX (-3, nan_value)), BUILD_COMPLEX (nan_value, nan_value), 0, 0, INVALID_EXCEPTION_OK);
+
+ check_complex ("clog10 (NaN + 0 i) == NaN + NaN i plus invalid exception allowed", FUNC(clog10) (BUILD_COMPLEX (nan_value, 0)), BUILD_COMPLEX (nan_value, nan_value), 0, 0, INVALID_EXCEPTION_OK);
+ check_complex ("clog10 (NaN + 5 i) == NaN + NaN i plus invalid exception allowed", FUNC(clog10) (BUILD_COMPLEX (nan_value, 5)), BUILD_COMPLEX (nan_value, nan_value), 0, 0, INVALID_EXCEPTION_OK);
+ check_complex ("clog10 (NaN - 0 i) == NaN + NaN i plus invalid exception allowed", FUNC(clog10) (BUILD_COMPLEX (nan_value, minus_zero)), BUILD_COMPLEX (nan_value, nan_value), 0, 0, INVALID_EXCEPTION_OK);
+ check_complex ("clog10 (NaN - 5 i) == NaN + NaN i plus invalid exception allowed", FUNC(clog10) (BUILD_COMPLEX (nan_value, -5)), BUILD_COMPLEX (nan_value, nan_value), 0, 0, INVALID_EXCEPTION_OK);
+
+ check_complex ("clog10 (NaN + NaN i) == NaN + NaN i", FUNC(clog10) (BUILD_COMPLEX (nan_value, nan_value)), BUILD_COMPLEX (nan_value, nan_value), 0, 0, 0);
+
+ check_complex ("clog10 (0.7 + 1.2 i) == 0.1427786545038868803 + 0.4528483579352493248 i", FUNC(clog10) (BUILD_COMPLEX (0.7L, 1.2L)), BUILD_COMPLEX (0.1427786545038868803L, 0.4528483579352493248L), DELTA552, 0, 0);
+ check_complex ("clog10 (-2 - 3 i) == 0.5569716761534183846 - 0.9375544629863747085 i", FUNC(clog10) (BUILD_COMPLEX (-2, -3)), BUILD_COMPLEX (0.5569716761534183846L, -0.9375544629863747085L), DELTA553, 0, 0);
+
+ print_complex_max_error ("clog10", DELTAclog10, 0);
+}
+
+static void
+conj_test (void)
+{
+ init_max_error ();
+ check_complex ("conj (0.0 + 0.0 i) == 0.0 - 0 i", FUNC(conj) (BUILD_COMPLEX (0.0, 0.0)), BUILD_COMPLEX (0.0, minus_zero), 0, 0, 0);
+ check_complex ("conj (0.0 - 0 i) == 0.0 + 0.0 i", FUNC(conj) (BUILD_COMPLEX (0.0, minus_zero)), BUILD_COMPLEX (0.0, 0.0), 0, 0, 0);
+ check_complex ("conj (NaN + NaN i) == NaN + NaN i", FUNC(conj) (BUILD_COMPLEX (nan_value, nan_value)), BUILD_COMPLEX (nan_value, nan_value), 0, 0, 0);
+ check_complex ("conj (inf - inf i) == inf + inf i", FUNC(conj) (BUILD_COMPLEX (plus_infty, minus_infty)), BUILD_COMPLEX (plus_infty, plus_infty), 0, 0, 0);
+ check_complex ("conj (inf + inf i) == inf - inf i", FUNC(conj) (BUILD_COMPLEX (plus_infty, plus_infty)), BUILD_COMPLEX (plus_infty, minus_infty), 0, 0, 0);
+ check_complex ("conj (1.0 + 2.0 i) == 1.0 - 2.0 i", FUNC(conj) (BUILD_COMPLEX (1.0, 2.0)), BUILD_COMPLEX (1.0, -2.0), 0, 0, 0);
+ check_complex ("conj (3.0 - 4.0 i) == 3.0 + 4.0 i", FUNC(conj) (BUILD_COMPLEX (3.0, -4.0)), BUILD_COMPLEX (3.0, 4.0), 0, 0, 0);
+
+ print_complex_max_error ("conj", 0, 0);
+}
+#endif
+
+
+static void
+copysign_test (void)
+{
+ init_max_error ();
+
+ check_float ("copysign (0, 4) == 0", FUNC(copysign) (0, 4), 0, 0, 0, 0);
+ check_float ("copysign (0, -4) == -0", FUNC(copysign) (0, -4), minus_zero, 0, 0, 0);
+ check_float ("copysign (-0, 4) == 0", FUNC(copysign) (minus_zero, 4), 0, 0, 0, 0);
+ check_float ("copysign (-0, -4) == -0", FUNC(copysign) (minus_zero, -4), minus_zero, 0, 0, 0);
+
+ check_float ("copysign (inf, 0) == inf", FUNC(copysign) (plus_infty, 0), plus_infty, 0, 0, 0);
+ check_float ("copysign (inf, -0) == -inf", FUNC(copysign) (plus_infty, minus_zero), minus_infty, 0, 0, 0);
+ check_float ("copysign (-inf, 0) == inf", FUNC(copysign) (minus_infty, 0), plus_infty, 0, 0, 0);
+ check_float ("copysign (-inf, -0) == -inf", FUNC(copysign) (minus_infty, minus_zero), minus_infty, 0, 0, 0);
+
+ check_float ("copysign (0, inf) == 0", FUNC(copysign) (0, plus_infty), 0, 0, 0, 0);
+ check_float ("copysign (0, -0) == -0", FUNC(copysign) (0, minus_zero), minus_zero, 0, 0, 0);
+ check_float ("copysign (-0, inf) == 0", FUNC(copysign) (minus_zero, plus_infty), 0, 0, 0, 0);
+ check_float ("copysign (-0, -0) == -0", FUNC(copysign) (minus_zero, minus_zero), minus_zero, 0, 0, 0);
+
+ /* XXX More correctly we would have to check the sign of the NaN. */
+ check_float ("copysign (NaN, 0) == NaN", FUNC(copysign) (nan_value, 0), nan_value, 0, 0, 0);
+ check_float ("copysign (NaN, -0) == NaN", FUNC(copysign) (nan_value, minus_zero), nan_value, 0, 0, 0);
+ check_float ("copysign (-NaN, 0) == NaN", FUNC(copysign) (-nan_value, 0), nan_value, 0, 0, 0);
+ check_float ("copysign (-NaN, -0) == NaN", FUNC(copysign) (-nan_value, minus_zero), nan_value, 0, 0, 0);
+
+ print_max_error ("copysign", 0, 0);
+}
+
+static void
+cos_test (void)
+{
+ errno = 0;
+ FUNC(cos) (0);
+ if (errno == ENOSYS)
+ /* Function not implemented. */
+ return;
+
+ init_max_error ();
+
+ check_float ("cos (0) == 1", FUNC(cos) (0), 1, 0, 0, 0);
+ check_float ("cos (-0) == 1", FUNC(cos) (minus_zero), 1, 0, 0, 0);
+ check_float ("cos (inf) == NaN plus invalid exception", FUNC(cos) (plus_infty), nan_value, 0, 0, INVALID_EXCEPTION);
+ check_float ("cos (-inf) == NaN plus invalid exception", FUNC(cos) (minus_infty), nan_value, 0, 0, INVALID_EXCEPTION);
+ check_float ("cos (NaN) == NaN", FUNC(cos) (nan_value), nan_value, 0, 0, 0);
+
+ check_float ("cos (M_PI_6l * 2.0) == 0.5", FUNC(cos) (M_PI_6l * 2.0), 0.5, DELTA582, 0, 0);
+ check_float ("cos (M_PI_6l * 4.0) == -0.5", FUNC(cos) (M_PI_6l * 4.0), -0.5, DELTA583, 0, 0);
+ check_float ("cos (pi/2) == 0", FUNC(cos) (M_PI_2l), 0, DELTA584, 0, 0);
+
+ check_float ("cos (0.7) == 0.76484218728448842625585999019186495", FUNC(cos) (0.7L), 0.76484218728448842625585999019186495L, DELTA585, 0, 0);
+
+ print_max_error ("cos", DELTAcos, 0);
+}
+
+static void
+cosh_test (void)
+{
+ errno = 0;
+ FUNC(cosh) (0.7L);
+ if (errno == ENOSYS)
+ /* Function not implemented. */
+ return;
+
+ init_max_error ();
+ check_float ("cosh (0) == 1", FUNC(cosh) (0), 1, 0, 0, 0);
+ check_float ("cosh (-0) == 1", FUNC(cosh) (minus_zero), 1, 0, 0, 0);
+
+#ifndef TEST_INLINE
+ check_float ("cosh (inf) == inf", FUNC(cosh) (plus_infty), plus_infty, 0, 0, 0);
+ check_float ("cosh (-inf) == inf", FUNC(cosh) (minus_infty), plus_infty, 0, 0, 0);
+#endif
+ check_float ("cosh (NaN) == NaN", FUNC(cosh) (nan_value), nan_value, 0, 0, 0);
+
+ check_float ("cosh (0.7) == 1.255169005630943018", FUNC(cosh) (0.7L), 1.255169005630943018L, DELTA591, 0, 0);
+ print_max_error ("cosh", DELTAcosh, 0);
+}
+
+
+#if 0 /* XXX scp XXX */
+static void
+cpow_test (void)
+{
+ errno = 0;
+ FUNC(cpow) (BUILD_COMPLEX (1, 0), BUILD_COMPLEX (0, 0));
+ if (errno == ENOSYS)
+ /* Function not implemented. */
+ return;
+
+ init_max_error ();
+
+ check_complex ("cpow (1 + 0 i, 0 + 0 i) == 1.0 + 0.0 i", FUNC(cpow) (BUILD_COMPLEX (1, 0), BUILD_COMPLEX (0, 0)), BUILD_COMPLEX (1.0, 0.0), 0, 0, 0);
+ check_complex ("cpow (2 + 0 i, 10 + 0 i) == 1024.0 + 0.0 i", FUNC(cpow) (BUILD_COMPLEX (2, 0), BUILD_COMPLEX (10, 0)), BUILD_COMPLEX (1024.0, 0.0), 0, 0, 0);
+
+ check_complex ("cpow (e + 0 i, 0 + 2 * M_PIl i) == 1.0 + 0.0 i", FUNC(cpow) (BUILD_COMPLEX (M_El, 0), BUILD_COMPLEX (0, 2 * M_PIl)), BUILD_COMPLEX (1.0, 0.0), DELTA594, 0, 0);
+ check_complex ("cpow (2 + 3 i, 4 + 0 i) == -119.0 - 120.0 i", FUNC(cpow) (BUILD_COMPLEX (2, 3), BUILD_COMPLEX (4, 0)), BUILD_COMPLEX (-119.0, -120.0), DELTA595, 0, 0);
+
+ check_complex ("cpow (NaN + NaN i, NaN + NaN i) == NaN + NaN i", FUNC(cpow) (BUILD_COMPLEX (nan_value, nan_value), BUILD_COMPLEX (nan_value, nan_value)), BUILD_COMPLEX (nan_value, nan_value), 0, 0, 0);
+
+ print_complex_max_error ("cpow", DELTAcpow, 0);
+}
+
+static void
+cproj_test (void)
+{
+ init_max_error ();
+ check_complex ("cproj (0.0 + 0.0 i) == 0.0 + 0.0 i", FUNC(cproj) (BUILD_COMPLEX (0.0, 0.0)), BUILD_COMPLEX (0.0, 0.0), 0, 0, 0);
+ check_complex ("cproj (-0 - 0 i) == -0 - 0 i", FUNC(cproj) (BUILD_COMPLEX (minus_zero, minus_zero)), BUILD_COMPLEX (minus_zero, minus_zero), 0, 0, 0);
+ check_complex ("cproj (0.0 - 0 i) == 0.0 - 0 i", FUNC(cproj) (BUILD_COMPLEX (0.0, minus_zero)), BUILD_COMPLEX (0.0, minus_zero), 0, 0, 0);
+ check_complex ("cproj (-0 + 0.0 i) == -0 + 0.0 i", FUNC(cproj) (BUILD_COMPLEX (minus_zero, 0.0)), BUILD_COMPLEX (minus_zero, 0.0), 0, 0, 0);
+
+ check_complex ("cproj (NaN + NaN i) == NaN + NaN i", FUNC(cproj) (BUILD_COMPLEX (nan_value, nan_value)), BUILD_COMPLEX (nan_value, nan_value), 0, 0, 0);
+
+ check_complex ("cproj (inf + inf i) == inf + 0.0 i", FUNC(cproj) (BUILD_COMPLEX (plus_infty, plus_infty)), BUILD_COMPLEX (plus_infty, 0.0), 0, 0, 0);
+ check_complex ("cproj (inf - inf i) == inf - 0 i", FUNC(cproj) (BUILD_COMPLEX (plus_infty, minus_infty)), BUILD_COMPLEX (plus_infty, minus_zero), 0, 0, 0);
+ check_complex ("cproj (-inf + inf i) == inf + 0.0 i", FUNC(cproj) (BUILD_COMPLEX (minus_infty, plus_infty)), BUILD_COMPLEX (plus_infty, 0.0), 0, 0, 0);
+ check_complex ("cproj (-inf - inf i) == inf - 0 i", FUNC(cproj) (BUILD_COMPLEX (minus_infty, minus_infty)), BUILD_COMPLEX (plus_infty, minus_zero), 0, 0, 0);
+
+ check_complex ("cproj (1.0 + 0.0 i) == 1.0 + 0.0 i", FUNC(cproj) (BUILD_COMPLEX (1.0, 0.0)), BUILD_COMPLEX (1.0, 0.0), 0, 0, 0);
+ check_complex ("cproj (2.0 + 3.0 i) == 0.2857142857142857142857142857142857 + 0.42857142857142857142857142857142855 i", FUNC(cproj) (BUILD_COMPLEX (2.0, 3.0)), BUILD_COMPLEX (0.2857142857142857142857142857142857L, 0.42857142857142857142857142857142855L), 0, 0, 0);
+
+ print_complex_max_error ("cproj", 0, 0);
+}
+
+static void
+creal_test (void)
+{
+ init_max_error ();
+ check_float ("creal (0.0 + 1.0 i) == 0.0", FUNC(creal) (BUILD_COMPLEX (0.0, 1.0)), 0.0, 0, 0, 0);
+ check_float ("creal (-0 + 1.0 i) == -0", FUNC(creal) (BUILD_COMPLEX (minus_zero, 1.0)), minus_zero, 0, 0, 0);
+ check_float ("creal (NaN + 1.0 i) == NaN", FUNC(creal) (BUILD_COMPLEX (nan_value, 1.0)), nan_value, 0, 0, 0);
+ check_float ("creal (NaN + NaN i) == NaN", FUNC(creal) (BUILD_COMPLEX (nan_value, nan_value)), nan_value, 0, 0, 0);
+ check_float ("creal (inf + 1.0 i) == inf", FUNC(creal) (BUILD_COMPLEX (plus_infty, 1.0)), plus_infty, 0, 0, 0);
+ check_float ("creal (-inf + 1.0 i) == -inf", FUNC(creal) (BUILD_COMPLEX (minus_infty, 1.0)), minus_infty, 0, 0, 0);
+ check_float ("creal (2.0 + 3.0 i) == 2.0", FUNC(creal) (BUILD_COMPLEX (2.0, 3.0)), 2.0, 0, 0, 0);
+
+ print_max_error ("creal", 0, 0);
+}
+
+static void
+csin_test (void)
+{
+ errno = 0;
+ FUNC(csin) (BUILD_COMPLEX (0.7L, 1.2L));
+ if (errno == ENOSYS)
+ /* Function not implemented. */
+ return;
+
+ init_max_error ();
+
+ check_complex ("csin (0.0 + 0.0 i) == 0.0 + 0.0 i", FUNC(csin) (BUILD_COMPLEX (0.0, 0.0)), BUILD_COMPLEX (0.0, 0.0), 0, 0, 0);
+ check_complex ("csin (-0 + 0.0 i) == -0 + 0.0 i", FUNC(csin) (BUILD_COMPLEX (minus_zero, 0.0)), BUILD_COMPLEX (minus_zero, 0.0), 0, 0, 0);
+ check_complex ("csin (0.0 - 0 i) == 0 - 0 i", FUNC(csin) (BUILD_COMPLEX (0.0, minus_zero)), BUILD_COMPLEX (0, minus_zero), 0, 0, 0);
+ check_complex ("csin (-0 - 0 i) == -0 - 0 i", FUNC(csin) (BUILD_COMPLEX (minus_zero, minus_zero)), BUILD_COMPLEX (minus_zero, minus_zero), 0, 0, 0);
+
+ check_complex ("csin (0.0 + inf i) == 0.0 + inf i", FUNC(csin) (BUILD_COMPLEX (0.0, plus_infty)), BUILD_COMPLEX (0.0, plus_infty), 0, 0, 0);
+ check_complex ("csin (-0 + inf i) == -0 + inf i", FUNC(csin) (BUILD_COMPLEX (minus_zero, plus_infty)), BUILD_COMPLEX (minus_zero, plus_infty), 0, 0, 0);
+ check_complex ("csin (0.0 - inf i) == 0.0 - inf i", FUNC(csin) (BUILD_COMPLEX (0.0, minus_infty)), BUILD_COMPLEX (0.0, minus_infty), 0, 0, 0);
+ check_complex ("csin (-0 - inf i) == -0 - inf i", FUNC(csin) (BUILD_COMPLEX (minus_zero, minus_infty)), BUILD_COMPLEX (minus_zero, minus_infty), 0, 0, 0);
+
+ check_complex ("csin (inf + 0.0 i) == NaN + 0.0 i plus invalid exception and sign of zero/inf not specified", FUNC(csin) (BUILD_COMPLEX (plus_infty, 0.0)), BUILD_COMPLEX (nan_value, 0.0), 0, 0, INVALID_EXCEPTION|IGNORE_ZERO_INF_SIGN);
+ check_complex ("csin (-inf + 0.0 i) == NaN + 0.0 i plus invalid exception and sign of zero/inf not specified", FUNC(csin) (BUILD_COMPLEX (minus_infty, 0.0)), BUILD_COMPLEX (nan_value, 0.0), 0, 0, INVALID_EXCEPTION|IGNORE_ZERO_INF_SIGN);
+ check_complex ("csin (inf - 0 i) == NaN + 0.0 i plus invalid exception and sign of zero/inf not specified", FUNC(csin) (BUILD_COMPLEX (plus_infty, minus_zero)), BUILD_COMPLEX (nan_value, 0.0), 0, 0, INVALID_EXCEPTION|IGNORE_ZERO_INF_SIGN);
+ check_complex ("csin (-inf - 0 i) == NaN + 0.0 i plus invalid exception and sign of zero/inf not specified", FUNC(csin) (BUILD_COMPLEX (minus_infty, minus_zero)), BUILD_COMPLEX (nan_value, 0.0), 0, 0, INVALID_EXCEPTION|IGNORE_ZERO_INF_SIGN);
+
+ check_complex ("csin (inf + inf i) == NaN + inf i plus invalid exception and sign of zero/inf not specified", FUNC(csin) (BUILD_COMPLEX (plus_infty, plus_infty)), BUILD_COMPLEX (nan_value, plus_infty), 0, 0, INVALID_EXCEPTION|IGNORE_ZERO_INF_SIGN);
+ check_complex ("csin (-inf + inf i) == NaN + inf i plus invalid exception and sign of zero/inf not specified", FUNC(csin) (BUILD_COMPLEX (minus_infty, plus_infty)), BUILD_COMPLEX (nan_value, plus_infty), 0, 0, INVALID_EXCEPTION|IGNORE_ZERO_INF_SIGN);
+ check_complex ("csin (inf - inf i) == NaN + inf i plus invalid exception and sign of zero/inf not specified", FUNC(csin) (BUILD_COMPLEX (plus_infty, minus_infty)), BUILD_COMPLEX (nan_value, plus_infty), 0, 0, INVALID_EXCEPTION|IGNORE_ZERO_INF_SIGN);
+ check_complex ("csin (-inf - inf i) == NaN + inf i plus invalid exception and sign of zero/inf not specified", FUNC(csin) (BUILD_COMPLEX (minus_infty, minus_infty)), BUILD_COMPLEX (nan_value, plus_infty), 0, 0, INVALID_EXCEPTION|IGNORE_ZERO_INF_SIGN);
+
+ check_complex ("csin (inf + 6.75 i) == NaN + NaN i plus invalid exception", FUNC(csin) (BUILD_COMPLEX (plus_infty, 6.75)), BUILD_COMPLEX (nan_value, nan_value), 0, 0, INVALID_EXCEPTION);
+ check_complex ("csin (inf - 6.75 i) == NaN + NaN i plus invalid exception", FUNC(csin) (BUILD_COMPLEX (plus_infty, -6.75)), BUILD_COMPLEX (nan_value, nan_value), 0, 0, INVALID_EXCEPTION);
+ check_complex ("csin (-inf + 6.75 i) == NaN + NaN i plus invalid exception", FUNC(csin) (BUILD_COMPLEX (minus_infty, 6.75)), BUILD_COMPLEX (nan_value, nan_value), 0, 0, INVALID_EXCEPTION);
+ check_complex ("csin (-inf - 6.75 i) == NaN + NaN i plus invalid exception", FUNC(csin) (BUILD_COMPLEX (minus_infty, -6.75)), BUILD_COMPLEX (nan_value, nan_value), 0, 0, INVALID_EXCEPTION);
+
+ check_complex ("csin (4.625 + inf i) == -inf - inf i", FUNC(csin) (BUILD_COMPLEX (4.625, plus_infty)), BUILD_COMPLEX (minus_infty, minus_infty), 0, 0, 0);
+ check_complex ("csin (4.625 - inf i) == -inf + inf i", FUNC(csin) (BUILD_COMPLEX (4.625, minus_infty)), BUILD_COMPLEX (minus_infty, plus_infty), 0, 0, 0);
+ check_complex ("csin (-4.625 + inf i) == inf - inf i", FUNC(csin) (BUILD_COMPLEX (-4.625, plus_infty)), BUILD_COMPLEX (plus_infty, minus_infty), 0, 0, 0);
+ check_complex ("csin (-4.625 - inf i) == inf + inf i", FUNC(csin) (BUILD_COMPLEX (-4.625, minus_infty)), BUILD_COMPLEX (plus_infty, plus_infty), 0, 0, 0);
+
+ check_complex ("csin (NaN + 0.0 i) == NaN + 0.0 i plus sign of zero/inf not specified", FUNC(csin) (BUILD_COMPLEX (nan_value, 0.0)), BUILD_COMPLEX (nan_value, 0.0), 0, 0, IGNORE_ZERO_INF_SIGN);
+ check_complex ("csin (NaN - 0 i) == NaN + 0.0 i plus sign of zero/inf not specified", FUNC(csin) (BUILD_COMPLEX (nan_value, minus_zero)), BUILD_COMPLEX (nan_value, 0.0), 0, 0, IGNORE_ZERO_INF_SIGN);
+
+ check_complex ("csin (NaN + inf i) == NaN + inf i plus sign of zero/inf not specified", FUNC(csin) (BUILD_COMPLEX (nan_value, plus_infty)), BUILD_COMPLEX (nan_value, plus_infty), 0, 0, IGNORE_ZERO_INF_SIGN);
+ check_complex ("csin (NaN - inf i) == NaN + inf i plus sign of zero/inf not specified", FUNC(csin) (BUILD_COMPLEX (nan_value, minus_infty)), BUILD_COMPLEX (nan_value, plus_infty), 0, 0, IGNORE_ZERO_INF_SIGN);
+
+ check_complex ("csin (NaN + 9.0 i) == NaN + NaN i plus invalid exception allowed", FUNC(csin) (BUILD_COMPLEX (nan_value, 9.0)), BUILD_COMPLEX (nan_value, nan_value), 0, 0, INVALID_EXCEPTION_OK);
+ check_complex ("csin (NaN - 9.0 i) == NaN + NaN i plus invalid exception allowed", FUNC(csin) (BUILD_COMPLEX (nan_value, -9.0)), BUILD_COMPLEX (nan_value, nan_value), 0, 0, INVALID_EXCEPTION_OK);
+
+ check_complex ("csin (0.0 + NaN i) == 0.0 + NaN i", FUNC(csin) (BUILD_COMPLEX (0.0, nan_value)), BUILD_COMPLEX (0.0, nan_value), 0, 0, 0);
+ check_complex ("csin (-0 + NaN i) == -0 + NaN i", FUNC(csin) (BUILD_COMPLEX (minus_zero, nan_value)), BUILD_COMPLEX (minus_zero, nan_value), 0, 0, 0);
+
+ check_complex ("csin (10.0 + NaN i) == NaN + NaN i plus invalid exception allowed", FUNC(csin) (BUILD_COMPLEX (10.0, nan_value)), BUILD_COMPLEX (nan_value, nan_value), 0, 0, INVALID_EXCEPTION_OK);
+ check_complex ("csin (NaN - 10.0 i) == NaN + NaN i plus invalid exception allowed", FUNC(csin) (BUILD_COMPLEX (nan_value, -10.0)), BUILD_COMPLEX (nan_value, nan_value), 0, 0, INVALID_EXCEPTION_OK);
+
+ check_complex ("csin (inf + NaN i) == NaN + NaN i plus invalid exception allowed", FUNC(csin) (BUILD_COMPLEX (plus_infty, nan_value)), BUILD_COMPLEX (nan_value, nan_value), 0, 0, INVALID_EXCEPTION_OK);
+ check_complex ("csin (-inf + NaN i) == NaN + NaN i plus invalid exception allowed", FUNC(csin) (BUILD_COMPLEX (minus_infty, nan_value)), BUILD_COMPLEX (nan_value, nan_value), 0, 0, INVALID_EXCEPTION_OK);
+
+ check_complex ("csin (NaN + NaN i) == NaN + NaN i", FUNC(csin) (BUILD_COMPLEX (nan_value, nan_value)), BUILD_COMPLEX (nan_value, nan_value), 0, 0, 0);
+
+ check_complex ("csin (0.7 + 1.2 i) == 1.1664563419657581376 + 1.1544997246948547371 i", FUNC(csin) (BUILD_COMPLEX (0.7L, 1.2L)), BUILD_COMPLEX (1.1664563419657581376L, 1.1544997246948547371L), DELTA652, 0, 0);
+
+ check_complex ("csin (-2 - 3 i) == -9.1544991469114295734 + 4.1689069599665643507 i", FUNC(csin) (BUILD_COMPLEX (-2, -3)), BUILD_COMPLEX (-9.1544991469114295734L, 4.1689069599665643507L), 0, 0, 0);
+
+ print_complex_max_error ("csin", DELTAcsin, 0);
+}
+
+
+static void
+csinh_test (void)
+{
+ errno = 0;
+ FUNC(csinh) (BUILD_COMPLEX (0.7L, 1.2L));
+ if (errno == ENOSYS)
+ /* Function not implemented. */
+ return;
+
+ init_max_error ();
+
+ check_complex ("csinh (0.0 + 0.0 i) == 0.0 + 0.0 i", FUNC(csinh) (BUILD_COMPLEX (0.0, 0.0)), BUILD_COMPLEX (0.0, 0.0), 0, 0, 0);
+ check_complex ("csinh (-0 + 0.0 i) == -0 + 0.0 i", FUNC(csinh) (BUILD_COMPLEX (minus_zero, 0.0)), BUILD_COMPLEX (minus_zero, 0.0), 0, 0, 0);
+ check_complex ("csinh (0.0 - 0 i) == 0.0 - 0 i", FUNC(csinh) (BUILD_COMPLEX (0.0, minus_zero)), BUILD_COMPLEX (0.0, minus_zero), 0, 0, 0);
+ check_complex ("csinh (-0 - 0 i) == -0 - 0 i", FUNC(csinh) (BUILD_COMPLEX (minus_zero, minus_zero)), BUILD_COMPLEX (minus_zero, minus_zero), 0, 0, 0);
+
+ check_complex ("csinh (0.0 + inf i) == 0.0 + NaN i plus invalid exception and sign of zero/inf not specified", FUNC(csinh) (BUILD_COMPLEX (0.0, plus_infty)), BUILD_COMPLEX (0.0, nan_value), 0, 0, INVALID_EXCEPTION|IGNORE_ZERO_INF_SIGN);
+ check_complex ("csinh (-0 + inf i) == 0.0 + NaN i plus invalid exception and sign of zero/inf not specified", FUNC(csinh) (BUILD_COMPLEX (minus_zero, plus_infty)), BUILD_COMPLEX (0.0, nan_value), 0, 0, INVALID_EXCEPTION|IGNORE_ZERO_INF_SIGN);
+ check_complex ("csinh (0.0 - inf i) == 0.0 + NaN i plus invalid exception and sign of zero/inf not specified", FUNC(csinh) (BUILD_COMPLEX (0.0, minus_infty)), BUILD_COMPLEX (0.0, nan_value), 0, 0, INVALID_EXCEPTION|IGNORE_ZERO_INF_SIGN);
+ check_complex ("csinh (-0 - inf i) == 0.0 + NaN i plus invalid exception and sign of zero/inf not specified", FUNC(csinh) (BUILD_COMPLEX (minus_zero, minus_infty)), BUILD_COMPLEX (0.0, nan_value), 0, 0, INVALID_EXCEPTION|IGNORE_ZERO_INF_SIGN);
+
+ check_complex ("csinh (inf + 0.0 i) == inf + 0.0 i", FUNC(csinh) (BUILD_COMPLEX (plus_infty, 0.0)), BUILD_COMPLEX (plus_infty, 0.0), 0, 0, 0);
+ check_complex ("csinh (-inf + 0.0 i) == -inf + 0.0 i", FUNC(csinh) (BUILD_COMPLEX (minus_infty, 0.0)), BUILD_COMPLEX (minus_infty, 0.0), 0, 0, 0);
+ check_complex ("csinh (inf - 0 i) == inf - 0 i", FUNC(csinh) (BUILD_COMPLEX (plus_infty, minus_zero)), BUILD_COMPLEX (plus_infty, minus_zero), 0, 0, 0);
+ check_complex ("csinh (-inf - 0 i) == -inf - 0 i", FUNC(csinh) (BUILD_COMPLEX (minus_infty, minus_zero)), BUILD_COMPLEX (minus_infty, minus_zero), 0, 0, 0);
+
+ check_complex ("csinh (inf + inf i) == inf + NaN i plus invalid exception and sign of zero/inf not specified", FUNC(csinh) (BUILD_COMPLEX (plus_infty, plus_infty)), BUILD_COMPLEX (plus_infty, nan_value), 0, 0, INVALID_EXCEPTION|IGNORE_ZERO_INF_SIGN);
+ check_complex ("csinh (-inf + inf i) == inf + NaN i plus invalid exception and sign of zero/inf not specified", FUNC(csinh) (BUILD_COMPLEX (minus_infty, plus_infty)), BUILD_COMPLEX (plus_infty, nan_value), 0, 0, INVALID_EXCEPTION|IGNORE_ZERO_INF_SIGN);
+ check_complex ("csinh (inf - inf i) == inf + NaN i plus invalid exception and sign of zero/inf not specified", FUNC(csinh) (BUILD_COMPLEX (plus_infty, minus_infty)), BUILD_COMPLEX (plus_infty, nan_value), 0, 0, INVALID_EXCEPTION|IGNORE_ZERO_INF_SIGN);
+ check_complex ("csinh (-inf - inf i) == inf + NaN i plus invalid exception and sign of zero/inf not specified", FUNC(csinh) (BUILD_COMPLEX (minus_infty, minus_infty)), BUILD_COMPLEX (plus_infty, nan_value), 0, 0, INVALID_EXCEPTION|IGNORE_ZERO_INF_SIGN);
+
+ check_complex ("csinh (inf + 4.625 i) == -inf - inf i", FUNC(csinh) (BUILD_COMPLEX (plus_infty, 4.625)), BUILD_COMPLEX (minus_infty, minus_infty), 0, 0, 0);
+ check_complex ("csinh (-inf + 4.625 i) == inf - inf i", FUNC(csinh) (BUILD_COMPLEX (minus_infty, 4.625)), BUILD_COMPLEX (plus_infty, minus_infty), 0, 0, 0);
+ check_complex ("csinh (inf - 4.625 i) == -inf + inf i", FUNC(csinh) (BUILD_COMPLEX (plus_infty, -4.625)), BUILD_COMPLEX (minus_infty, plus_infty), 0, 0, 0);
+ check_complex ("csinh (-inf - 4.625 i) == inf + inf i", FUNC(csinh) (BUILD_COMPLEX (minus_infty, -4.625)), BUILD_COMPLEX (plus_infty, plus_infty), 0, 0, 0);
+
+ check_complex ("csinh (6.75 + inf i) == NaN + NaN i plus invalid exception", FUNC(csinh) (BUILD_COMPLEX (6.75, plus_infty)), BUILD_COMPLEX (nan_value, nan_value), 0, 0, INVALID_EXCEPTION);
+ check_complex ("csinh (-6.75 + inf i) == NaN + NaN i plus invalid exception", FUNC(csinh) (BUILD_COMPLEX (-6.75, plus_infty)), BUILD_COMPLEX (nan_value, nan_value), 0, 0, INVALID_EXCEPTION);
+ check_complex ("csinh (6.75 - inf i) == NaN + NaN i plus invalid exception", FUNC(csinh) (BUILD_COMPLEX (6.75, minus_infty)), BUILD_COMPLEX (nan_value, nan_value), 0, 0, INVALID_EXCEPTION);
+ check_complex ("csinh (-6.75 - inf i) == NaN + NaN i plus invalid exception", FUNC(csinh) (BUILD_COMPLEX (-6.75, minus_infty)), BUILD_COMPLEX (nan_value, nan_value), 0, 0, INVALID_EXCEPTION);
+
+ check_complex ("csinh (0.0 + NaN i) == 0.0 + NaN i plus sign of zero/inf not specified", FUNC(csinh) (BUILD_COMPLEX (0.0, nan_value)), BUILD_COMPLEX (0.0, nan_value), 0, 0, IGNORE_ZERO_INF_SIGN);
+ check_complex ("csinh (-0 + NaN i) == 0.0 + NaN i plus sign of zero/inf not specified", FUNC(csinh) (BUILD_COMPLEX (minus_zero, nan_value)), BUILD_COMPLEX (0.0, nan_value), 0, 0, IGNORE_ZERO_INF_SIGN);
+
+ check_complex ("csinh (inf + NaN i) == inf + NaN i plus sign of zero/inf not specified", FUNC(csinh) (BUILD_COMPLEX (plus_infty, nan_value)), BUILD_COMPLEX (plus_infty, nan_value), 0, 0, IGNORE_ZERO_INF_SIGN);
+ check_complex ("csinh (-inf + NaN i) == inf + NaN i plus sign of zero/inf not specified", FUNC(csinh) (BUILD_COMPLEX (minus_infty, nan_value)), BUILD_COMPLEX (plus_infty, nan_value), 0, 0, IGNORE_ZERO_INF_SIGN);
+
+ check_complex ("csinh (9.0 + NaN i) == NaN + NaN i plus invalid exception allowed", FUNC(csinh) (BUILD_COMPLEX (9.0, nan_value)), BUILD_COMPLEX (nan_value, nan_value), 0, 0, INVALID_EXCEPTION_OK);
+ check_complex ("csinh (-9.0 + NaN i) == NaN + NaN i plus invalid exception allowed", FUNC(csinh) (BUILD_COMPLEX (-9.0, nan_value)), BUILD_COMPLEX (nan_value, nan_value), 0, 0, INVALID_EXCEPTION_OK);
+
+ check_complex ("csinh (NaN + 0.0 i) == NaN + 0.0 i", FUNC(csinh) (BUILD_COMPLEX (nan_value, 0.0)), BUILD_COMPLEX (nan_value, 0.0), 0, 0, 0);
+ check_complex ("csinh (NaN - 0 i) == NaN - 0 i", FUNC(csinh) (BUILD_COMPLEX (nan_value, minus_zero)), BUILD_COMPLEX (nan_value, minus_zero), 0, 0, 0);
+
+ check_complex ("csinh (NaN + 10.0 i) == NaN + NaN i plus invalid exception allowed", FUNC(csinh) (BUILD_COMPLEX (nan_value, 10.0)), BUILD_COMPLEX (nan_value, nan_value), 0, 0, INVALID_EXCEPTION_OK);
+ check_complex ("csinh (NaN - 10.0 i) == NaN + NaN i plus invalid exception allowed", FUNC(csinh) (BUILD_COMPLEX (nan_value, -10.0)), BUILD_COMPLEX (nan_value, nan_value), 0, 0, INVALID_EXCEPTION_OK);
+
+ check_complex ("csinh (NaN + inf i) == NaN + NaN i plus invalid exception allowed", FUNC(csinh) (BUILD_COMPLEX (nan_value, plus_infty)), BUILD_COMPLEX (nan_value, nan_value), 0, 0, INVALID_EXCEPTION_OK);
+ check_complex ("csinh (NaN - inf i) == NaN + NaN i plus invalid exception allowed", FUNC(csinh) (BUILD_COMPLEX (nan_value, minus_infty)), BUILD_COMPLEX (nan_value, nan_value), 0, 0, INVALID_EXCEPTION_OK);
+
+ check_complex ("csinh (NaN + NaN i) == NaN + NaN i", FUNC(csinh) (BUILD_COMPLEX (nan_value, nan_value)), BUILD_COMPLEX (nan_value, nan_value), 0, 0, 0);
+
+ check_complex ("csinh (0.7 + 1.2 i) == 0.27487868678117583582 + 1.1698665727426565139 i", FUNC(csinh) (BUILD_COMPLEX (0.7L, 1.2L)), BUILD_COMPLEX (0.27487868678117583582L, 1.1698665727426565139L), DELTA691, 0, 0);
+ check_complex ("csinh (-2 - 3 i) == 3.5905645899857799520 - 0.5309210862485198052 i", FUNC(csinh) (BUILD_COMPLEX (-2, -3)), BUILD_COMPLEX (3.5905645899857799520L, -0.5309210862485198052L), DELTA692, 0, 0);
+
+ print_complex_max_error ("csinh", DELTAcsinh, 0);
+}
+
+static void
+csqrt_test (void)
+{
+ errno = 0;
+ FUNC(csqrt) (BUILD_COMPLEX (-1, 0));
+ if (errno == ENOSYS)
+ /* Function not implemented. */
+ return;
+
+ init_max_error ();
+
+ check_complex ("csqrt (0 + 0 i) == 0.0 + 0.0 i", FUNC(csqrt) (BUILD_COMPLEX (0, 0)), BUILD_COMPLEX (0.0, 0.0), 0, 0, 0);
+ check_complex ("csqrt (0 - 0 i) == 0 - 0 i", FUNC(csqrt) (BUILD_COMPLEX (0, minus_zero)), BUILD_COMPLEX (0, minus_zero), 0, 0, 0);
+ check_complex ("csqrt (-0 + 0 i) == 0.0 + 0.0 i", FUNC(csqrt) (BUILD_COMPLEX (minus_zero, 0)), BUILD_COMPLEX (0.0, 0.0), 0, 0, 0);
+ check_complex ("csqrt (-0 - 0 i) == 0.0 - 0 i", FUNC(csqrt) (BUILD_COMPLEX (minus_zero, minus_zero)), BUILD_COMPLEX (0.0, minus_zero), 0, 0, 0);
+
+ check_complex ("csqrt (-inf + 0 i) == 0.0 + inf i", FUNC(csqrt) (BUILD_COMPLEX (minus_infty, 0)), BUILD_COMPLEX (0.0, plus_infty), 0, 0, 0);
+ check_complex ("csqrt (-inf + 6 i) == 0.0 + inf i", FUNC(csqrt) (BUILD_COMPLEX (minus_infty, 6)), BUILD_COMPLEX (0.0, plus_infty), 0, 0, 0);
+ check_complex ("csqrt (-inf - 0 i) == 0.0 - inf i", FUNC(csqrt) (BUILD_COMPLEX (minus_infty, minus_zero)), BUILD_COMPLEX (0.0, minus_infty), 0, 0, 0);
+ check_complex ("csqrt (-inf - 6 i) == 0.0 - inf i", FUNC(csqrt) (BUILD_COMPLEX (minus_infty, -6)), BUILD_COMPLEX (0.0, minus_infty), 0, 0, 0);
+
+ check_complex ("csqrt (inf + 0 i) == inf + 0.0 i", FUNC(csqrt) (BUILD_COMPLEX (plus_infty, 0)), BUILD_COMPLEX (plus_infty, 0.0), 0, 0, 0);
+ check_complex ("csqrt (inf + 6 i) == inf + 0.0 i", FUNC(csqrt) (BUILD_COMPLEX (plus_infty, 6)), BUILD_COMPLEX (plus_infty, 0.0), 0, 0, 0);
+ check_complex ("csqrt (inf - 0 i) == inf - 0 i", FUNC(csqrt) (BUILD_COMPLEX (plus_infty, minus_zero)), BUILD_COMPLEX (plus_infty, minus_zero), 0, 0, 0);
+ check_complex ("csqrt (inf - 6 i) == inf - 0 i", FUNC(csqrt) (BUILD_COMPLEX (plus_infty, -6)), BUILD_COMPLEX (plus_infty, minus_zero), 0, 0, 0);
+
+ check_complex ("csqrt (0 + inf i) == inf + inf i", FUNC(csqrt) (BUILD_COMPLEX (0, plus_infty)), BUILD_COMPLEX (plus_infty, plus_infty), 0, 0, 0);
+ check_complex ("csqrt (4 + inf i) == inf + inf i", FUNC(csqrt) (BUILD_COMPLEX (4, plus_infty)), BUILD_COMPLEX (plus_infty, plus_infty), 0, 0, 0);
+ check_complex ("csqrt (inf + inf i) == inf + inf i", FUNC(csqrt) (BUILD_COMPLEX (plus_infty, plus_infty)), BUILD_COMPLEX (plus_infty, plus_infty), 0, 0, 0);
+ check_complex ("csqrt (-0 + inf i) == inf + inf i", FUNC(csqrt) (BUILD_COMPLEX (minus_zero, plus_infty)), BUILD_COMPLEX (plus_infty, plus_infty), 0, 0, 0);
+ check_complex ("csqrt (-4 + inf i) == inf + inf i", FUNC(csqrt) (BUILD_COMPLEX (-4, plus_infty)), BUILD_COMPLEX (plus_infty, plus_infty), 0, 0, 0);
+ check_complex ("csqrt (-inf + inf i) == inf + inf i", FUNC(csqrt) (BUILD_COMPLEX (minus_infty, plus_infty)), BUILD_COMPLEX (plus_infty, plus_infty), 0, 0, 0);
+ check_complex ("csqrt (0 - inf i) == inf - inf i", FUNC(csqrt) (BUILD_COMPLEX (0, minus_infty)), BUILD_COMPLEX (plus_infty, minus_infty), 0, 0, 0);
+ check_complex ("csqrt (4 - inf i) == inf - inf i", FUNC(csqrt) (BUILD_COMPLEX (4, minus_infty)), BUILD_COMPLEX (plus_infty, minus_infty), 0, 0, 0);
+ check_complex ("csqrt (inf - inf i) == inf - inf i", FUNC(csqrt) (BUILD_COMPLEX (plus_infty, minus_infty)), BUILD_COMPLEX (plus_infty, minus_infty), 0, 0, 0);
+ check_complex ("csqrt (-0 - inf i) == inf - inf i", FUNC(csqrt) (BUILD_COMPLEX (minus_zero, minus_infty)), BUILD_COMPLEX (plus_infty, minus_infty), 0, 0, 0);
+ check_complex ("csqrt (-4 - inf i) == inf - inf i", FUNC(csqrt) (BUILD_COMPLEX (-4, minus_infty)), BUILD_COMPLEX (plus_infty, minus_infty), 0, 0, 0);
+ check_complex ("csqrt (-inf - inf i) == inf - inf i", FUNC(csqrt) (BUILD_COMPLEX (minus_infty, minus_infty)), BUILD_COMPLEX (plus_infty, minus_infty), 0, 0, 0);
+
+ check_complex ("csqrt (-inf + NaN i) == NaN + inf i plus sign of zero/inf not specified", FUNC(csqrt) (BUILD_COMPLEX (minus_infty, nan_value)), BUILD_COMPLEX (nan_value, plus_infty), 0, 0, IGNORE_ZERO_INF_SIGN);
+
+ check_complex ("csqrt (inf + NaN i) == inf + NaN i", FUNC(csqrt) (BUILD_COMPLEX (plus_infty, nan_value)), BUILD_COMPLEX (plus_infty, nan_value), 0, 0, 0);
+
+ check_complex ("csqrt (0 + NaN i) == NaN + NaN i plus invalid exception allowed", FUNC(csqrt) (BUILD_COMPLEX (0, nan_value)), BUILD_COMPLEX (nan_value, nan_value), 0, 0, INVALID_EXCEPTION_OK);
+ check_complex ("csqrt (1 + NaN i) == NaN + NaN i plus invalid exception allowed", FUNC(csqrt) (BUILD_COMPLEX (1, nan_value)), BUILD_COMPLEX (nan_value, nan_value), 0, 0, INVALID_EXCEPTION_OK);
+ check_complex ("csqrt (-0 + NaN i) == NaN + NaN i plus invalid exception allowed", FUNC(csqrt) (BUILD_COMPLEX (minus_zero, nan_value)), BUILD_COMPLEX (nan_value, nan_value), 0, 0, INVALID_EXCEPTION_OK);
+ check_complex ("csqrt (-1 + NaN i) == NaN + NaN i plus invalid exception allowed", FUNC(csqrt) (BUILD_COMPLEX (-1, nan_value)), BUILD_COMPLEX (nan_value, nan_value), 0, 0, INVALID_EXCEPTION_OK);
+
+ check_complex ("csqrt (NaN + 0 i) == NaN + NaN i plus invalid exception allowed", FUNC(csqrt) (BUILD_COMPLEX (nan_value, 0)), BUILD_COMPLEX (nan_value, nan_value), 0, 0, INVALID_EXCEPTION_OK);
+ check_complex ("csqrt (NaN + 8 i) == NaN + NaN i plus invalid exception allowed", FUNC(csqrt) (BUILD_COMPLEX (nan_value, 8)), BUILD_COMPLEX (nan_value, nan_value), 0, 0, INVALID_EXCEPTION_OK);
+ check_complex ("csqrt (NaN - 0 i) == NaN + NaN i plus invalid exception allowed", FUNC(csqrt) (BUILD_COMPLEX (nan_value, minus_zero)), BUILD_COMPLEX (nan_value, nan_value), 0, 0, INVALID_EXCEPTION_OK);
+ check_complex ("csqrt (NaN - 8 i) == NaN + NaN i plus invalid exception allowed", FUNC(csqrt) (BUILD_COMPLEX (nan_value, -8)), BUILD_COMPLEX (nan_value, nan_value), 0, 0, INVALID_EXCEPTION_OK);
+
+ check_complex ("csqrt (NaN + NaN i) == NaN + NaN i", FUNC(csqrt) (BUILD_COMPLEX (nan_value, nan_value)), BUILD_COMPLEX (nan_value, nan_value), 0, 0, 0);
+
+ check_complex ("csqrt (16.0 - 30.0 i) == 5.0 - 3.0 i", FUNC(csqrt) (BUILD_COMPLEX (16.0, -30.0)), BUILD_COMPLEX (5.0, -3.0), 0, 0, 0);
+ check_complex ("csqrt (-1 + 0 i) == 0.0 + 1.0 i", FUNC(csqrt) (BUILD_COMPLEX (-1, 0)), BUILD_COMPLEX (0.0, 1.0), 0, 0, 0);
+ check_complex ("csqrt (0 + 2 i) == 1.0 + 1.0 i", FUNC(csqrt) (BUILD_COMPLEX (0, 2)), BUILD_COMPLEX (1.0, 1.0), 0, 0, 0);
+ check_complex ("csqrt (119 + 120 i) == 12.0 + 5.0 i", FUNC(csqrt) (BUILD_COMPLEX (119, 120)), BUILD_COMPLEX (12.0, 5.0), 0, 0, 0);
+ check_complex ("csqrt (0.7 + 1.2 i) == 1.022067610030026450706487883081139 + 0.58704531296356521154977678719838035 i", FUNC(csqrt) (BUILD_COMPLEX (0.7L, 1.2L)), BUILD_COMPLEX (1.022067610030026450706487883081139L, 0.58704531296356521154977678719838035L), DELTA732, 0, 0);
+ check_complex ("csqrt (-2 - 3 i) == 0.89597747612983812471573375529004348 - 1.6741492280355400404480393008490519 i", FUNC(csqrt) (BUILD_COMPLEX (-2, -3)), BUILD_COMPLEX (0.89597747612983812471573375529004348L, -1.6741492280355400404480393008490519L), DELTA733, 0, 0);
+ check_complex ("csqrt (-2 + 3 i) == 0.89597747612983812471573375529004348 + 1.6741492280355400404480393008490519 i", FUNC(csqrt) (BUILD_COMPLEX (-2, 3)), BUILD_COMPLEX (0.89597747612983812471573375529004348L, 1.6741492280355400404480393008490519L), DELTA734, 0, 0);
+
+ print_complex_max_error ("csqrt", DELTAcsqrt, 0);
+}
+
+static void
+ctan_test (void)
+{
+ errno = 0;
+ FUNC(ctan) (BUILD_COMPLEX (0.7L, 1.2L));
+ if (errno == ENOSYS)
+ /* Function not implemented. */
+ return;
+
+ init_max_error ();
+
+ check_complex ("ctan (0 + 0 i) == 0.0 + 0.0 i", FUNC(ctan) (BUILD_COMPLEX (0, 0)), BUILD_COMPLEX (0.0, 0.0), 0, 0, 0);
+ check_complex ("ctan (0 - 0 i) == 0.0 - 0 i", FUNC(ctan) (BUILD_COMPLEX (0, minus_zero)), BUILD_COMPLEX (0.0, minus_zero), 0, 0, 0);
+ check_complex ("ctan (-0 + 0 i) == -0 + 0.0 i", FUNC(ctan) (BUILD_COMPLEX (minus_zero, 0)), BUILD_COMPLEX (minus_zero, 0.0), 0, 0, 0);
+ check_complex ("ctan (-0 - 0 i) == -0 - 0 i", FUNC(ctan) (BUILD_COMPLEX (minus_zero, minus_zero)), BUILD_COMPLEX (minus_zero, minus_zero), 0, 0, 0);
+
+ check_complex ("ctan (0 + inf i) == 0.0 + 1.0 i", FUNC(ctan) (BUILD_COMPLEX (0, plus_infty)), BUILD_COMPLEX (0.0, 1.0), 0, 0, 0);
+ check_complex ("ctan (1 + inf i) == 0.0 + 1.0 i", FUNC(ctan) (BUILD_COMPLEX (1, plus_infty)), BUILD_COMPLEX (0.0, 1.0), 0, 0, 0);
+ check_complex ("ctan (-0 + inf i) == -0 + 1.0 i", FUNC(ctan) (BUILD_COMPLEX (minus_zero, plus_infty)), BUILD_COMPLEX (minus_zero, 1.0), 0, 0, 0);
+ check_complex ("ctan (-1 + inf i) == -0 + 1.0 i", FUNC(ctan) (BUILD_COMPLEX (-1, plus_infty)), BUILD_COMPLEX (minus_zero, 1.0), 0, 0, 0);
+
+ check_complex ("ctan (0 - inf i) == 0.0 - 1.0 i", FUNC(ctan) (BUILD_COMPLEX (0, minus_infty)), BUILD_COMPLEX (0.0, -1.0), 0, 0, 0);
+ check_complex ("ctan (1 - inf i) == 0.0 - 1.0 i", FUNC(ctan) (BUILD_COMPLEX (1, minus_infty)), BUILD_COMPLEX (0.0, -1.0), 0, 0, 0);
+ check_complex ("ctan (-0 - inf i) == -0 - 1.0 i", FUNC(ctan) (BUILD_COMPLEX (minus_zero, minus_infty)), BUILD_COMPLEX (minus_zero, -1.0), 0, 0, 0);
+ check_complex ("ctan (-1 - inf i) == -0 - 1.0 i", FUNC(ctan) (BUILD_COMPLEX (-1, minus_infty)), BUILD_COMPLEX (minus_zero, -1.0), 0, 0, 0);
+
+ check_complex ("ctan (inf + 0 i) == NaN + NaN i plus invalid exception", FUNC(ctan) (BUILD_COMPLEX (plus_infty, 0)), BUILD_COMPLEX (nan_value, nan_value), 0, 0, INVALID_EXCEPTION);
+ check_complex ("ctan (inf + 2 i) == NaN + NaN i plus invalid exception", FUNC(ctan) (BUILD_COMPLEX (plus_infty, 2)), BUILD_COMPLEX (nan_value, nan_value), 0, 0, INVALID_EXCEPTION);
+ check_complex ("ctan (-inf + 0 i) == NaN + NaN i plus invalid exception", FUNC(ctan) (BUILD_COMPLEX (minus_infty, 0)), BUILD_COMPLEX (nan_value, nan_value), 0, 0, INVALID_EXCEPTION);
+ check_complex ("ctan (-inf + 2 i) == NaN + NaN i plus invalid exception", FUNC(ctan) (BUILD_COMPLEX (minus_infty, 2)), BUILD_COMPLEX (nan_value, nan_value), 0, 0, INVALID_EXCEPTION);
+ check_complex ("ctan (inf - 0 i) == NaN + NaN i plus invalid exception", FUNC(ctan) (BUILD_COMPLEX (plus_infty, minus_zero)), BUILD_COMPLEX (nan_value, nan_value), 0, 0, INVALID_EXCEPTION);
+ check_complex ("ctan (inf - 2 i) == NaN + NaN i plus invalid exception", FUNC(ctan) (BUILD_COMPLEX (plus_infty, -2)), BUILD_COMPLEX (nan_value, nan_value), 0, 0, INVALID_EXCEPTION);
+ check_complex ("ctan (-inf - 0 i) == NaN + NaN i plus invalid exception", FUNC(ctan) (BUILD_COMPLEX (minus_infty, minus_zero)), BUILD_COMPLEX (nan_value, nan_value), 0, 0, INVALID_EXCEPTION);
+ check_complex ("ctan (-inf - 2 i) == NaN + NaN i plus invalid exception", FUNC(ctan) (BUILD_COMPLEX (minus_infty, -2)), BUILD_COMPLEX (nan_value, nan_value), 0, 0, INVALID_EXCEPTION);
+
+ check_complex ("ctan (NaN + inf i) == 0.0 + 1.0 i plus sign of zero/inf not specified", FUNC(ctan) (BUILD_COMPLEX (nan_value, plus_infty)), BUILD_COMPLEX (0.0, 1.0), 0, 0, IGNORE_ZERO_INF_SIGN);
+ check_complex ("ctan (NaN - inf i) == 0.0 - 1.0 i plus sign of zero/inf not specified", FUNC(ctan) (BUILD_COMPLEX (nan_value, minus_infty)), BUILD_COMPLEX (0.0, -1.0), 0, 0, IGNORE_ZERO_INF_SIGN);
+
+ check_complex ("ctan (0 + NaN i) == 0.0 + NaN i", FUNC(ctan) (BUILD_COMPLEX (0, nan_value)), BUILD_COMPLEX (0.0, nan_value), 0, 0, 0);
+ check_complex ("ctan (-0 + NaN i) == -0 + NaN i", FUNC(ctan) (BUILD_COMPLEX (minus_zero, nan_value)), BUILD_COMPLEX (minus_zero, nan_value), 0, 0, 0);
+
+ check_complex ("ctan (0.5 + NaN i) == NaN + NaN i plus invalid exception allowed", FUNC(ctan) (BUILD_COMPLEX (0.5, nan_value)), BUILD_COMPLEX (nan_value, nan_value), 0, 0, INVALID_EXCEPTION_OK);
+ check_complex ("ctan (-4.5 + NaN i) == NaN + NaN i plus invalid exception allowed", FUNC(ctan) (BUILD_COMPLEX (-4.5, nan_value)), BUILD_COMPLEX (nan_value, nan_value), 0, 0, INVALID_EXCEPTION_OK);
+
+ check_complex ("ctan (NaN + 0 i) == NaN + NaN i plus invalid exception allowed", FUNC(ctan) (BUILD_COMPLEX (nan_value, 0)), BUILD_COMPLEX (nan_value, nan_value), 0, 0, INVALID_EXCEPTION_OK);
+ check_complex ("ctan (NaN + 5 i) == NaN + NaN i plus invalid exception allowed", FUNC(ctan) (BUILD_COMPLEX (nan_value, 5)), BUILD_COMPLEX (nan_value, nan_value), 0, 0, INVALID_EXCEPTION_OK);
+ check_complex ("ctan (NaN - 0 i) == NaN + NaN i plus invalid exception allowed", FUNC(ctan) (BUILD_COMPLEX (nan_value, minus_zero)), BUILD_COMPLEX (nan_value, nan_value), 0, 0, INVALID_EXCEPTION_OK);
+ check_complex ("ctan (NaN - 0.25 i) == NaN + NaN i plus invalid exception allowed", FUNC(ctan) (BUILD_COMPLEX (nan_value, -0.25)), BUILD_COMPLEX (nan_value, nan_value), 0, 0, INVALID_EXCEPTION_OK);
+
+ check_complex ("ctan (NaN + NaN i) == NaN + NaN i", FUNC(ctan) (BUILD_COMPLEX (nan_value, nan_value)), BUILD_COMPLEX (nan_value, nan_value), 0, 0, 0);
+
+ check_complex ("ctan (0.7 + 1.2 i) == 0.1720734197630349001 + 0.9544807059989405538 i", FUNC(ctan) (BUILD_COMPLEX (0.7L, 1.2L)), BUILD_COMPLEX (0.1720734197630349001L, 0.9544807059989405538L), DELTA766, 0, 0);
+ check_complex ("ctan (-2 - 3 i) == 0.0037640256415042482 - 1.0032386273536098014 i", FUNC(ctan) (BUILD_COMPLEX (-2, -3)), BUILD_COMPLEX (0.0037640256415042482L, -1.0032386273536098014L), DELTA767, 0, 0);
+
+ print_complex_max_error ("ctan", DELTActan, 0);
+}
+
+
+static void
+ctanh_test (void)
+{
+ errno = 0;
+ FUNC(ctanh) (BUILD_COMPLEX (0, 0));
+ if (errno == ENOSYS)
+ /* Function not implemented. */
+ return;
+
+ init_max_error ();
+
+ check_complex ("ctanh (0 + 0 i) == 0.0 + 0.0 i", FUNC(ctanh) (BUILD_COMPLEX (0, 0)), BUILD_COMPLEX (0.0, 0.0), 0, 0, 0);
+ check_complex ("ctanh (0 - 0 i) == 0.0 - 0 i", FUNC(ctanh) (BUILD_COMPLEX (0, minus_zero)), BUILD_COMPLEX (0.0, minus_zero), 0, 0, 0);
+ check_complex ("ctanh (-0 + 0 i) == -0 + 0.0 i", FUNC(ctanh) (BUILD_COMPLEX (minus_zero, 0)), BUILD_COMPLEX (minus_zero, 0.0), 0, 0, 0);
+ check_complex ("ctanh (-0 - 0 i) == -0 - 0 i", FUNC(ctanh) (BUILD_COMPLEX (minus_zero, minus_zero)), BUILD_COMPLEX (minus_zero, minus_zero), 0, 0, 0);
+
+ check_complex ("ctanh (inf + 0 i) == 1.0 + 0.0 i", FUNC(ctanh) (BUILD_COMPLEX (plus_infty, 0)), BUILD_COMPLEX (1.0, 0.0), 0, 0, 0);
+ check_complex ("ctanh (inf + 1 i) == 1.0 + 0.0 i", FUNC(ctanh) (BUILD_COMPLEX (plus_infty, 1)), BUILD_COMPLEX (1.0, 0.0), 0, 0, 0);
+ check_complex ("ctanh (inf - 0 i) == 1.0 - 0 i", FUNC(ctanh) (BUILD_COMPLEX (plus_infty, minus_zero)), BUILD_COMPLEX (1.0, minus_zero), 0, 0, 0);
+ check_complex ("ctanh (inf - 1 i) == 1.0 - 0 i", FUNC(ctanh) (BUILD_COMPLEX (plus_infty, -1)), BUILD_COMPLEX (1.0, minus_zero), 0, 0, 0);
+ check_complex ("ctanh (-inf + 0 i) == -1.0 + 0.0 i", FUNC(ctanh) (BUILD_COMPLEX (minus_infty, 0)), BUILD_COMPLEX (-1.0, 0.0), 0, 0, 0);
+ check_complex ("ctanh (-inf + 1 i) == -1.0 + 0.0 i", FUNC(ctanh) (BUILD_COMPLEX (minus_infty, 1)), BUILD_COMPLEX (-1.0, 0.0), 0, 0, 0);
+ check_complex ("ctanh (-inf - 0 i) == -1.0 - 0 i", FUNC(ctanh) (BUILD_COMPLEX (minus_infty, minus_zero)), BUILD_COMPLEX (-1.0, minus_zero), 0, 0, 0);
+ check_complex ("ctanh (-inf - 1 i) == -1.0 - 0 i", FUNC(ctanh) (BUILD_COMPLEX (minus_infty, -1)), BUILD_COMPLEX (-1.0, minus_zero), 0, 0, 0);
+
+ check_complex ("ctanh (0 + inf i) == NaN + NaN i plus invalid exception", FUNC(ctanh) (BUILD_COMPLEX (0, plus_infty)), BUILD_COMPLEX (nan_value, nan_value), 0, 0, INVALID_EXCEPTION);
+ check_complex ("ctanh (2 + inf i) == NaN + NaN i plus invalid exception", FUNC(ctanh) (BUILD_COMPLEX (2, plus_infty)), BUILD_COMPLEX (nan_value, nan_value), 0, 0, INVALID_EXCEPTION);
+ check_complex ("ctanh (0 - inf i) == NaN + NaN i plus invalid exception", FUNC(ctanh) (BUILD_COMPLEX (0, minus_infty)), BUILD_COMPLEX (nan_value, nan_value), 0, 0, INVALID_EXCEPTION);
+ check_complex ("ctanh (2 - inf i) == NaN + NaN i plus invalid exception", FUNC(ctanh) (BUILD_COMPLEX (2, minus_infty)), BUILD_COMPLEX (nan_value, nan_value), 0, 0, INVALID_EXCEPTION);
+ check_complex ("ctanh (-0 + inf i) == NaN + NaN i plus invalid exception", FUNC(ctanh) (BUILD_COMPLEX (minus_zero, plus_infty)), BUILD_COMPLEX (nan_value, nan_value), 0, 0, INVALID_EXCEPTION);
+ check_complex ("ctanh (-2 + inf i) == NaN + NaN i plus invalid exception", FUNC(ctanh) (BUILD_COMPLEX (-2, plus_infty)), BUILD_COMPLEX (nan_value, nan_value), 0, 0, INVALID_EXCEPTION);
+ check_complex ("ctanh (-0 - inf i) == NaN + NaN i plus invalid exception", FUNC(ctanh) (BUILD_COMPLEX (minus_zero, minus_infty)), BUILD_COMPLEX (nan_value, nan_value), 0, 0, INVALID_EXCEPTION);
+ check_complex ("ctanh (-2 - inf i) == NaN + NaN i plus invalid exception", FUNC(ctanh) (BUILD_COMPLEX (-2, minus_infty)), BUILD_COMPLEX (nan_value, nan_value), 0, 0, INVALID_EXCEPTION);
+
+ check_complex ("ctanh (inf + NaN i) == 1.0 + 0.0 i plus sign of zero/inf not specified", FUNC(ctanh) (BUILD_COMPLEX (plus_infty, nan_value)), BUILD_COMPLEX (1.0, 0.0), 0, 0, IGNORE_ZERO_INF_SIGN);
+ check_complex ("ctanh (-inf + NaN i) == -1.0 + 0.0 i plus sign of zero/inf not specified", FUNC(ctanh) (BUILD_COMPLEX (minus_infty, nan_value)), BUILD_COMPLEX (-1.0, 0.0), 0, 0, IGNORE_ZERO_INF_SIGN);
+
+ check_complex ("ctanh (NaN + 0 i) == NaN + 0.0 i", FUNC(ctanh) (BUILD_COMPLEX (nan_value, 0)), BUILD_COMPLEX (nan_value, 0.0), 0, 0, 0);
+ check_complex ("ctanh (NaN - 0 i) == NaN - 0 i", FUNC(ctanh) (BUILD_COMPLEX (nan_value, minus_zero)), BUILD_COMPLEX (nan_value, minus_zero), 0, 0, 0);
+
+ check_complex ("ctanh (NaN + 0.5 i) == NaN + NaN i plus invalid exception allowed", FUNC(ctanh) (BUILD_COMPLEX (nan_value, 0.5)), BUILD_COMPLEX (nan_value, nan_value), 0, 0, INVALID_EXCEPTION_OK);
+ check_complex ("ctanh (NaN - 4.5 i) == NaN + NaN i plus invalid exception allowed", FUNC(ctanh) (BUILD_COMPLEX (nan_value, -4.5)), BUILD_COMPLEX (nan_value, nan_value), 0, 0, INVALID_EXCEPTION_OK);
+
+ check_complex ("ctanh (0 + NaN i) == NaN + NaN i plus invalid exception allowed", FUNC(ctanh) (BUILD_COMPLEX (0, nan_value)), BUILD_COMPLEX (nan_value, nan_value), 0, 0, INVALID_EXCEPTION_OK);
+ check_complex ("ctanh (5 + NaN i) == NaN + NaN i plus invalid exception allowed", FUNC(ctanh) (BUILD_COMPLEX (5, nan_value)), BUILD_COMPLEX (nan_value, nan_value), 0, 0, INVALID_EXCEPTION_OK);
+ check_complex ("ctanh (-0 + NaN i) == NaN + NaN i plus invalid exception allowed", FUNC(ctanh) (BUILD_COMPLEX (minus_zero, nan_value)), BUILD_COMPLEX (nan_value, nan_value), 0, 0, INVALID_EXCEPTION_OK);
+ check_complex ("ctanh (-0.25 + NaN i) == NaN + NaN i plus invalid exception allowed", FUNC(ctanh) (BUILD_COMPLEX (-0.25, nan_value)), BUILD_COMPLEX (nan_value, nan_value), 0, 0, INVALID_EXCEPTION_OK);
+
+ check_complex ("ctanh (NaN + NaN i) == NaN + NaN i", FUNC(ctanh) (BUILD_COMPLEX (nan_value, nan_value)), BUILD_COMPLEX (nan_value, nan_value), 0, 0, 0);
+
+ check_complex ("ctanh (0 + pi/4 i) == 0.0 + 1.0 i", FUNC(ctanh) (BUILD_COMPLEX (0, M_PI_4l)), BUILD_COMPLEX (0.0, 1.0), DELTA799, 0, 0);
+
+ check_complex ("ctanh (0.7 + 1.2 i) == 1.3472197399061191630 + 0.4778641038326365540 i", FUNC(ctanh) (BUILD_COMPLEX (0.7L, 1.2L)), BUILD_COMPLEX (1.3472197399061191630L, 0.4778641038326365540L), DELTA800, 0, 0);
+ check_complex ("ctanh (-2 - 3 i) == -0.9653858790221331242 + 0.0098843750383224937 i", FUNC(ctanh) (BUILD_COMPLEX (-2, -3)), BUILD_COMPLEX (-0.9653858790221331242L, 0.0098843750383224937L), DELTA801, 0, 0);
+
+ print_complex_max_error ("ctanh", DELTActanh, 0);
+}
+#endif
+
+static void
+erf_test (void)
+{
+ errno = 0;
+ FUNC(erf) (0);
+ if (errno == ENOSYS)
+ /* Function not implemented. */
+ return;
+
+ init_max_error ();
+
+ check_float ("erf (0) == 0", FUNC(erf) (0), 0, 0, 0, 0);
+ check_float ("erf (-0) == -0", FUNC(erf) (minus_zero), minus_zero, 0, 0, 0);
+ check_float ("erf (inf) == 1", FUNC(erf) (plus_infty), 1, 0, 0, 0);
+ check_float ("erf (-inf) == -1", FUNC(erf) (minus_infty), -1, 0, 0, 0);
+ check_float ("erf (NaN) == NaN", FUNC(erf) (nan_value), nan_value, 0, 0, 0);
+
+ check_float ("erf (0.7) == 0.67780119383741847297", FUNC(erf) (0.7L), 0.67780119383741847297L, 0, 0, 0);
+
+ check_float ("erf (1.2) == 0.91031397822963538024", FUNC(erf) (1.2L), 0.91031397822963538024L, 0, 0, 0);
+ check_float ("erf (2.0) == 0.99532226501895273416", FUNC(erf) (2.0), 0.99532226501895273416L, 0, 0, 0);
+ check_float ("erf (4.1) == 0.99999999329997234592", FUNC(erf) (4.1L), 0.99999999329997234592L, 0, 0, 0);
+ check_float ("erf (27) == 1.0", FUNC(erf) (27), 1.0L, 0, 0, 0);
+
+ print_max_error ("erf", 0, 0);
+}
+
+
+static void
+erfc_test (void)
+{
+ errno = 0;
+ FUNC(erfc) (0);
+ if (errno == ENOSYS)
+ /* Function not implemented. */
+ return;
+
+ init_max_error ();
+
+ check_float ("erfc (inf) == 0.0", FUNC(erfc) (plus_infty), 0.0, 0, 0, 0);
+ check_float ("erfc (-inf) == 2.0", FUNC(erfc) (minus_infty), 2.0, 0, 0, 0);
+ check_float ("erfc (0.0) == 1.0", FUNC(erfc) (0.0), 1.0, 0, 0, 0);
+ check_float ("erfc (-0) == 1.0", FUNC(erfc) (minus_zero), 1.0, 0, 0, 0);
+ check_float ("erfc (NaN) == NaN", FUNC(erfc) (nan_value), nan_value, 0, 0, 0);
+
+ check_float ("erfc (0.7) == 0.32219880616258152702", FUNC(erfc) (0.7L), 0.32219880616258152702L, DELTA817, 0, 0);
+
+ check_float ("erfc (1.2) == 0.089686021770364619762", FUNC(erfc) (1.2L), 0.089686021770364619762L, DELTA818, 0, 0);
+ check_float ("erfc (2.0) == 0.0046777349810472658379", FUNC(erfc) (2.0), 0.0046777349810472658379L, DELTA819, 0, 0);
+ check_float ("erfc (4.1) == 0.67000276540848983727e-8", FUNC(erfc) (4.1L), 0.67000276540848983727e-8L, DELTA820, 0, 0);
+ check_float ("erfc (9) == 0.41370317465138102381e-36", FUNC(erfc) (9), 0.41370317465138102381e-36L, DELTA821, 0, 0);
+
+ print_max_error ("erfc", DELTAerfc, 0);
+}
+
+static void
+exp_test (void)
+{
+ errno = 0;
+ FUNC(exp) (0);
+ if (errno == ENOSYS)
+ /* Function not implemented. */
+ return;
+
+ init_max_error ();
+
+ check_float ("exp (0) == 1", FUNC(exp) (0), 1, 0, 0, 0);
+ check_float ("exp (-0) == 1", FUNC(exp) (minus_zero), 1, 0, 0, 0);
+
+#ifndef TEST_INLINE
+ check_float ("exp (inf) == inf", FUNC(exp) (plus_infty), plus_infty, 0, 0, 0);
+ check_float ("exp (-inf) == 0", FUNC(exp) (minus_infty), 0, 0, 0, 0);
+#endif
+ check_float ("exp (NaN) == NaN", FUNC(exp) (nan_value), nan_value, 0, 0, 0);
+ check_float ("exp (1) == e", FUNC(exp) (1), M_El, 0, 0, 0);
+
+ check_float ("exp (2) == e^2", FUNC(exp) (2), M_E2l, 0, 0, 0);
+ check_float ("exp (3) == e^3", FUNC(exp) (3), M_E3l, 0, 0, 0);
+ check_float ("exp (0.7) == 2.0137527074704765216", FUNC(exp) (0.7L), 2.0137527074704765216L, DELTA830, 0, 0);
+ check_float ("exp (50.0) == 5184705528587072464087.45332293348538", FUNC(exp) (50.0L), 5184705528587072464087.45332293348538L, DELTA831, 0, 0);
+#ifdef TEST_LDOUBLE
+ /* The result can only be represented in long double. */
+ check_float ("exp (1000.0) == 0.197007111401704699388887935224332313e435", FUNC(exp) (1000.0L), 0.197007111401704699388887935224332313e435L, DELTA832, 0, 0);
+#endif
+ print_max_error ("exp", DELTAexp, 0);
+}
+
+
+#if 0 /* XXX scp XXX */
+static void
+exp10_test (void)
+{
+ errno = 0;
+ FUNC(exp10) (0);
+ if (errno == ENOSYS)
+ /* Function not implemented. */
+ return;
+
+ init_max_error ();
+
+ check_float ("exp10 (0) == 1", FUNC(exp10) (0), 1, 0, 0, 0);
+ check_float ("exp10 (-0) == 1", FUNC(exp10) (minus_zero), 1, 0, 0, 0);
+
+ check_float ("exp10 (inf) == inf", FUNC(exp10) (plus_infty), plus_infty, 0, 0, 0);
+ check_float ("exp10 (-inf) == 0", FUNC(exp10) (minus_infty), 0, 0, 0, 0);
+ check_float ("exp10 (NaN) == NaN", FUNC(exp10) (nan_value), nan_value, 0, 0, 0);
+ check_float ("exp10 (3) == 1000", FUNC(exp10) (3), 1000, DELTA838, 0, 0);
+ check_float ("exp10 (-1) == 0.1", FUNC(exp10) (-1), 0.1L, DELTA839, 0, 0);
+ check_float ("exp10 (1e6) == inf", FUNC(exp10) (1e6), plus_infty, 0, 0, 0);
+ check_float ("exp10 (-1e6) == 0", FUNC(exp10) (-1e6), 0, 0, 0, 0);
+ check_float ("exp10 (0.7) == 5.0118723362727228500155418688494574", FUNC(exp10) (0.7L), 5.0118723362727228500155418688494574L, DELTA842, 0, 0);
+
+ print_max_error ("exp10", DELTAexp10, 0);
+}
+#endif
+
+static void
+exp2_test (void)
+{
+ errno = 0;
+ FUNC(exp2) (0);
+ if (errno == ENOSYS)
+ /* Function not implemented. */
+ return;
+
+ init_max_error ();
+
+ check_float ("exp2 (0) == 1", FUNC(exp2) (0), 1, 0, 0, 0);
+ check_float ("exp2 (-0) == 1", FUNC(exp2) (minus_zero), 1, 0, 0, 0);
+ check_float ("exp2 (inf) == inf", FUNC(exp2) (plus_infty), plus_infty, 0, 0, 0);
+ check_float ("exp2 (-inf) == 0", FUNC(exp2) (minus_infty), 0, 0, 0, 0);
+ check_float ("exp2 (NaN) == NaN", FUNC(exp2) (nan_value), nan_value, 0, 0, 0);
+
+ check_float ("exp2 (10) == 1024", FUNC(exp2) (10), 1024, 0, 0, 0);
+ check_float ("exp2 (-1) == 0.5", FUNC(exp2) (-1), 0.5, 0, 0, 0);
+ check_float ("exp2 (1e6) == inf", FUNC(exp2) (1e6), plus_infty, 0, 0, 0);
+ check_float ("exp2 (-1e6) == 0", FUNC(exp2) (-1e6), 0, 0, 0, 0);
+ check_float ("exp2 (0.7) == 1.6245047927124710452", FUNC(exp2) (0.7L), 1.6245047927124710452L, DELTA852, 0, 0);
+
+ print_max_error ("exp2", DELTAexp2, 0);
+}
+
+static void
+expm1_test (void)
+{
+ errno = 0;
+ FUNC(expm1) (0);
+ if (errno == ENOSYS)
+ /* Function not implemented. */
+ return;
+
+ init_max_error ();
+
+ check_float ("expm1 (0) == 0", FUNC(expm1) (0), 0, 0, 0, 0);
+ check_float ("expm1 (-0) == -0", FUNC(expm1) (minus_zero), minus_zero, 0, 0, 0);
+
+#ifndef TEST_INLINE
+ check_float ("expm1 (inf) == inf", FUNC(expm1) (plus_infty), plus_infty, 0, 0, 0);
+ check_float ("expm1 (-inf) == -1", FUNC(expm1) (minus_infty), -1, 0, 0, 0);
+#endif
+ check_float ("expm1 (NaN) == NaN", FUNC(expm1) (nan_value), nan_value, 0, 0, 0);
+
+ check_float ("expm1 (1) == M_El - 1.0", FUNC(expm1) (1), M_El - 1.0, 1, 0, 0);
+ check_float ("expm1 (0.7) == 1.0137527074704765216", FUNC(expm1) (0.7L), 1.0137527074704765216L, DELTA859, 0, 0);
+
+ print_max_error ("expm1", DELTAexpm1, 0);
+}
+
+static void
+fabs_test (void)
+{
+ init_max_error ();
+
+ check_float ("fabs (0) == 0", FUNC(fabs) ((FLOAT)0.0), 0, 0, 0, 0);
+ check_float ("fabs (-0) == 0", FUNC(fabs) (minus_zero), 0, 0, 0, 0);
+
+ check_float ("fabs (inf) == inf", FUNC(fabs) (plus_infty), plus_infty, 0, 0, 0);
+ check_float ("fabs (-inf) == inf", FUNC(fabs) (minus_infty), plus_infty, 0, 0, 0);
+ check_float ("fabs (NaN) == NaN", FUNC(fabs) (nan_value), nan_value, 0, 0, 0);
+
+ check_float ("fabs (38.0) == 38.0", FUNC(fabs) ((FLOAT)38.0), 38.0, 0, 0, 0);
+ check_float ("fabs (-e) == e", FUNC(fabs) ((FLOAT)-M_El), M_El, 0, 0, 0);
+
+ print_max_error ("fabs", 0, 0);
+}
+
+static void
+fdim_test (void)
+{
+ init_max_error ();
+
+ check_float ("fdim (0, 0) == 0", FUNC(fdim) (0, 0), 0, 0, 0, 0);
+ check_float ("fdim (9, 0) == 9", FUNC(fdim) (9, 0), 9, 0, 0, 0);
+ check_float ("fdim (0, 9) == 0", FUNC(fdim) (0, 9), 0, 0, 0, 0);
+ check_float ("fdim (-9, 0) == 0", FUNC(fdim) (-9, 0), 0, 0, 0, 0);
+ check_float ("fdim (0, -9) == 9", FUNC(fdim) (0, -9), 9, 0, 0, 0);
+
+ check_float ("fdim (inf, 9) == inf", FUNC(fdim) (plus_infty, 9), plus_infty, 0, 0, 0);
+ check_float ("fdim (inf, -9) == inf", FUNC(fdim) (plus_infty, -9), plus_infty, 0, 0, 0);
+ check_float ("fdim (-inf, 9) == 0", FUNC(fdim) (minus_infty, 9), 0, 0, 0, 0);
+ check_float ("fdim (-inf, -9) == 0", FUNC(fdim) (minus_infty, -9), 0, 0, 0, 0);
+ check_float ("fdim (9, -inf) == inf", FUNC(fdim) (9, minus_infty), plus_infty, 0, 0, 0);
+ check_float ("fdim (-9, -inf) == inf", FUNC(fdim) (-9, minus_infty), plus_infty, 0, 0, 0);
+ check_float ("fdim (9, inf) == 0", FUNC(fdim) (9, plus_infty), 0, 0, 0, 0);
+ check_float ("fdim (-9, inf) == 0", FUNC(fdim) (-9, plus_infty), 0, 0, 0, 0);
+
+ check_float ("fdim (0, NaN) == NaN", FUNC(fdim) (0, nan_value), nan_value, 0, 0, 0);
+ check_float ("fdim (9, NaN) == NaN", FUNC(fdim) (9, nan_value), nan_value, 0, 0, 0);
+ check_float ("fdim (-9, NaN) == NaN", FUNC(fdim) (-9, nan_value), nan_value, 0, 0, 0);
+ check_float ("fdim (NaN, 9) == NaN", FUNC(fdim) (nan_value, 9), nan_value, 0, 0, 0);
+ check_float ("fdim (NaN, -9) == NaN", FUNC(fdim) (nan_value, -9), nan_value, 0, 0, 0);
+ check_float ("fdim (inf, NaN) == NaN", FUNC(fdim) (plus_infty, nan_value), nan_value, 0, 0, 0);
+ check_float ("fdim (-inf, NaN) == NaN", FUNC(fdim) (minus_infty, nan_value), nan_value, 0, 0, 0);
+ check_float ("fdim (NaN, inf) == NaN", FUNC(fdim) (nan_value, plus_infty), nan_value, 0, 0, 0);
+ check_float ("fdim (NaN, -inf) == NaN", FUNC(fdim) (nan_value, minus_infty), nan_value, 0, 0, 0);
+ check_float ("fdim (NaN, NaN) == NaN", FUNC(fdim) (nan_value, nan_value), nan_value, 0, 0, 0);
+
+ print_max_error ("fdim", 0, 0);
+}
+
+static void
+floor_test (void)
+{
+ init_max_error ();
+
+ check_float ("floor (0.0) == 0.0", FUNC(floor) (0.0), 0.0, 0, 0, 0);
+ check_float ("floor (-0) == -0", FUNC(floor) (minus_zero), minus_zero, 0, 0, 0);
+ check_float ("floor (inf) == inf", FUNC(floor) (plus_infty), plus_infty, 0, 0, 0);
+ check_float ("floor (-inf) == -inf", FUNC(floor) (minus_infty), minus_infty, 0, 0, 0);
+ check_float ("floor (NaN) == NaN", FUNC(floor) (nan_value), nan_value, 0, 0, 0);
+
+ check_float ("floor (pi) == 3.0", FUNC(floor) (M_PIl), 3.0, 0, 0, 0);
+ check_float ("floor (-pi) == -4.0", FUNC(floor) (-M_PIl), -4.0, 0, 0, 0);
+
+ print_max_error ("floor", 0, 0);
+}
+
+static void
+fma_test (void)
+{
+ init_max_error ();
+
+ check_float ("fma (1.0, 2.0, 3.0) == 5.0", FUNC(fma) (1.0, 2.0, 3.0), 5.0, 0, 0, 0);
+ check_float ("fma (NaN, 2.0, 3.0) == NaN", FUNC(fma) (nan_value, 2.0, 3.0), nan_value, 0, 0, 0);
+ check_float ("fma (1.0, NaN, 3.0) == NaN", FUNC(fma) (1.0, nan_value, 3.0), nan_value, 0, 0, 0);
+ check_float ("fma (1.0, 2.0, NaN) == NaN plus invalid exception allowed", FUNC(fma) (1.0, 2.0, nan_value), nan_value, 0, 0, INVALID_EXCEPTION_OK);
+ check_float ("fma (inf, 0.0, NaN) == NaN plus invalid exception allowed", FUNC(fma) (plus_infty, 0.0, nan_value), nan_value, 0, 0, INVALID_EXCEPTION_OK);
+ check_float ("fma (-inf, 0.0, NaN) == NaN plus invalid exception allowed", FUNC(fma) (minus_infty, 0.0, nan_value), nan_value, 0, 0, INVALID_EXCEPTION_OK);
+ check_float ("fma (0.0, inf, NaN) == NaN plus invalid exception allowed", FUNC(fma) (0.0, plus_infty, nan_value), nan_value, 0, 0, INVALID_EXCEPTION_OK);
+ check_float ("fma (0.0, -inf, NaN) == NaN plus invalid exception allowed", FUNC(fma) (0.0, minus_infty, nan_value), nan_value, 0, 0, INVALID_EXCEPTION_OK);
+ check_float ("fma (inf, 0.0, 1.0) == NaN plus invalid exception", FUNC(fma) (plus_infty, 0.0, 1.0), nan_value, 0, 0, INVALID_EXCEPTION);
+ check_float ("fma (-inf, 0.0, 1.0) == NaN plus invalid exception", FUNC(fma) (minus_infty, 0.0, 1.0), nan_value, 0, 0, INVALID_EXCEPTION);
+ check_float ("fma (0.0, inf, 1.0) == NaN plus invalid exception", FUNC(fma) (0.0, plus_infty, 1.0), nan_value, 0, 0, INVALID_EXCEPTION);
+ check_float ("fma (0.0, -inf, 1.0) == NaN plus invalid exception", FUNC(fma) (0.0, minus_infty, 1.0), nan_value, 0, 0, INVALID_EXCEPTION);
+
+ check_float ("fma (inf, inf, -inf) == NaN plus invalid exception", FUNC(fma) (plus_infty, plus_infty, minus_infty), nan_value, 0, 0, INVALID_EXCEPTION);
+ check_float ("fma (-inf, inf, inf) == NaN plus invalid exception", FUNC(fma) (minus_infty, plus_infty, plus_infty), nan_value, 0, 0, INVALID_EXCEPTION);
+ check_float ("fma (inf, -inf, inf) == NaN plus invalid exception", FUNC(fma) (plus_infty, minus_infty, plus_infty), nan_value, 0, 0, INVALID_EXCEPTION);
+ check_float ("fma (-inf, -inf, -inf) == NaN plus invalid exception", FUNC(fma) (minus_infty, minus_infty, minus_infty), nan_value, 0, 0, INVALID_EXCEPTION);
+
+ print_max_error ("fma", 0, 0);
+}
+
+
+static void
+fmax_test (void)
+{
+ init_max_error ();
+
+ check_float ("fmax (0, 0) == 0", FUNC(fmax) (0, 0), 0, 0, 0, 0);
+ check_float ("fmax (-0, -0) == -0", FUNC(fmax) (minus_zero, minus_zero), minus_zero, 0, 0, 0);
+ check_float ("fmax (9, 0) == 9", FUNC(fmax) (9, 0), 9, 0, 0, 0);
+ check_float ("fmax (0, 9) == 9", FUNC(fmax) (0, 9), 9, 0, 0, 0);
+ check_float ("fmax (-9, 0) == 0", FUNC(fmax) (-9, 0), 0, 0, 0, 0);
+ check_float ("fmax (0, -9) == 0", FUNC(fmax) (0, -9), 0, 0, 0, 0);
+
+ check_float ("fmax (inf, 9) == inf", FUNC(fmax) (plus_infty, 9), plus_infty, 0, 0, 0);
+ check_float ("fmax (0, inf) == inf", FUNC(fmax) (0, plus_infty), plus_infty, 0, 0, 0);
+ check_float ("fmax (-9, inf) == inf", FUNC(fmax) (-9, plus_infty), plus_infty, 0, 0, 0);
+ check_float ("fmax (inf, -9) == inf", FUNC(fmax) (plus_infty, -9), plus_infty, 0, 0, 0);
+
+ check_float ("fmax (-inf, 9) == 9", FUNC(fmax) (minus_infty, 9), 9, 0, 0, 0);
+ check_float ("fmax (-inf, -9) == -9", FUNC(fmax) (minus_infty, -9), -9, 0, 0, 0);
+ check_float ("fmax (9, -inf) == 9", FUNC(fmax) (9, minus_infty), 9, 0, 0, 0);
+ check_float ("fmax (-9, -inf) == -9", FUNC(fmax) (-9, minus_infty), -9, 0, 0, 0);
+
+ check_float ("fmax (0, NaN) == 0", FUNC(fmax) (0, nan_value), 0, 0, 0, 0);
+ check_float ("fmax (9, NaN) == 9", FUNC(fmax) (9, nan_value), 9, 0, 0, 0);
+ check_float ("fmax (-9, NaN) == -9", FUNC(fmax) (-9, nan_value), -9, 0, 0, 0);
+ check_float ("fmax (NaN, 0) == 0", FUNC(fmax) (nan_value, 0), 0, 0, 0, 0);
+ check_float ("fmax (NaN, 9) == 9", FUNC(fmax) (nan_value, 9), 9, 0, 0, 0);
+ check_float ("fmax (NaN, -9) == -9", FUNC(fmax) (nan_value, -9), -9, 0, 0, 0);
+ check_float ("fmax (inf, NaN) == inf", FUNC(fmax) (plus_infty, nan_value), plus_infty, 0, 0, 0);
+ check_float ("fmax (-inf, NaN) == -inf", FUNC(fmax) (minus_infty, nan_value), minus_infty, 0, 0, 0);
+ check_float ("fmax (NaN, inf) == inf", FUNC(fmax) (nan_value, plus_infty), plus_infty, 0, 0, 0);
+ check_float ("fmax (NaN, -inf) == -inf", FUNC(fmax) (nan_value, minus_infty), minus_infty, 0, 0, 0);
+ check_float ("fmax (NaN, NaN) == NaN", FUNC(fmax) (nan_value, nan_value), nan_value, 0, 0, 0);
+
+ print_max_error ("fmax", 0, 0);
+}
+
+
+static void
+fmin_test (void)
+{
+ init_max_error ();
+
+ check_float ("fmin (0, 0) == 0", FUNC(fmin) (0, 0), 0, 0, 0, 0);
+ check_float ("fmin (-0, -0) == -0", FUNC(fmin) (minus_zero, minus_zero), minus_zero, 0, 0, 0);
+ check_float ("fmin (9, 0) == 0", FUNC(fmin) (9, 0), 0, 0, 0, 0);
+ check_float ("fmin (0, 9) == 0", FUNC(fmin) (0, 9), 0, 0, 0, 0);
+ check_float ("fmin (-9, 0) == -9", FUNC(fmin) (-9, 0), -9, 0, 0, 0);
+ check_float ("fmin (0, -9) == -9", FUNC(fmin) (0, -9), -9, 0, 0, 0);
+
+ check_float ("fmin (inf, 9) == 9", FUNC(fmin) (plus_infty, 9), 9, 0, 0, 0);
+ check_float ("fmin (9, inf) == 9", FUNC(fmin) (9, plus_infty), 9, 0, 0, 0);
+ check_float ("fmin (inf, -9) == -9", FUNC(fmin) (plus_infty, -9), -9, 0, 0, 0);
+ check_float ("fmin (-9, inf) == -9", FUNC(fmin) (-9, plus_infty), -9, 0, 0, 0);
+ check_float ("fmin (-inf, 9) == -inf", FUNC(fmin) (minus_infty, 9), minus_infty, 0, 0, 0);
+ check_float ("fmin (-inf, -9) == -inf", FUNC(fmin) (minus_infty, -9), minus_infty, 0, 0, 0);
+ check_float ("fmin (9, -inf) == -inf", FUNC(fmin) (9, minus_infty), minus_infty, 0, 0, 0);
+ check_float ("fmin (-9, -inf) == -inf", FUNC(fmin) (-9, minus_infty), minus_infty, 0, 0, 0);
+
+ check_float ("fmin (0, NaN) == 0", FUNC(fmin) (0, nan_value), 0, 0, 0, 0);
+ check_float ("fmin (9, NaN) == 9", FUNC(fmin) (9, nan_value), 9, 0, 0, 0);
+ check_float ("fmin (-9, NaN) == -9", FUNC(fmin) (-9, nan_value), -9, 0, 0, 0);
+ check_float ("fmin (NaN, 0) == 0", FUNC(fmin) (nan_value, 0), 0, 0, 0, 0);
+ check_float ("fmin (NaN, 9) == 9", FUNC(fmin) (nan_value, 9), 9, 0, 0, 0);
+ check_float ("fmin (NaN, -9) == -9", FUNC(fmin) (nan_value, -9), -9, 0, 0, 0);
+ check_float ("fmin (inf, NaN) == inf", FUNC(fmin) (plus_infty, nan_value), plus_infty, 0, 0, 0);
+ check_float ("fmin (-inf, NaN) == -inf", FUNC(fmin) (minus_infty, nan_value), minus_infty, 0, 0, 0);
+ check_float ("fmin (NaN, inf) == inf", FUNC(fmin) (nan_value, plus_infty), plus_infty, 0, 0, 0);
+ check_float ("fmin (NaN, -inf) == -inf", FUNC(fmin) (nan_value, minus_infty), minus_infty, 0, 0, 0);
+ check_float ("fmin (NaN, NaN) == NaN", FUNC(fmin) (nan_value, nan_value), nan_value, 0, 0, 0);
+
+ print_max_error ("fmin", 0, 0);
+}
+
+
+static void
+fmod_test (void)
+{
+ errno = 0;
+ FUNC(fmod) (6.5, 2.3L);
+ if (errno == ENOSYS)
+ /* Function not implemented. */
+ return;
+
+ init_max_error ();
+
+ /* fmod (+0, y) == +0 for y != 0. */
+ check_float ("fmod (0, 3) == 0", FUNC(fmod) (0, 3), 0, 0, 0, 0);
+
+ /* fmod (-0, y) == -0 for y != 0. */
+ check_float ("fmod (-0, 3) == -0", FUNC(fmod) (minus_zero, 3), minus_zero, 0, 0, 0);
+
+ /* fmod (+inf, y) == NaN plus invalid exception. */
+ check_float ("fmod (inf, 3) == NaN plus invalid exception", FUNC(fmod) (plus_infty, 3), nan_value, 0, 0, INVALID_EXCEPTION);
+ /* fmod (-inf, y) == NaN plus invalid exception. */
+ check_float ("fmod (-inf, 3) == NaN plus invalid exception", FUNC(fmod) (minus_infty, 3), nan_value, 0, 0, INVALID_EXCEPTION);
+ /* fmod (x, +0) == NaN plus invalid exception. */
+ check_float ("fmod (3, 0) == NaN plus invalid exception", FUNC(fmod) (3, 0), nan_value, 0, 0, INVALID_EXCEPTION);
+ /* fmod (x, -0) == NaN plus invalid exception. */
+ check_float ("fmod (3, -0) == NaN plus invalid exception", FUNC(fmod) (3, minus_zero), nan_value, 0, 0, INVALID_EXCEPTION);
+
+ /* fmod (x, +inf) == x for x not infinite. */
+ check_float ("fmod (3.0, inf) == 3.0", FUNC(fmod) (3.0, plus_infty), 3.0, 0, 0, 0);
+ /* fmod (x, -inf) == x for x not infinite. */
+ check_float ("fmod (3.0, -inf) == 3.0", FUNC(fmod) (3.0, minus_infty), 3.0, 0, 0, 0);
+
+ check_float ("fmod (NaN, NaN) == NaN", FUNC(fmod) (nan_value, nan_value), nan_value, 0, 0, 0);
+
+ check_float ("fmod (6.5, 2.3) == 1.9", FUNC(fmod) (6.5, 2.3L), 1.9L, DELTA972, 0, 0);
+ check_float ("fmod (-6.5, 2.3) == -1.9", FUNC(fmod) (-6.5, 2.3L), -1.9L, DELTA973, 0, 0);
+ check_float ("fmod (6.5, -2.3) == 1.9", FUNC(fmod) (6.5, -2.3L), 1.9L, DELTA974, 0, 0);
+ check_float ("fmod (-6.5, -2.3) == -1.9", FUNC(fmod) (-6.5, -2.3L), -1.9L, DELTA975, 0, 0);
+
+ print_max_error ("fmod", DELTAfmod, 0);
+}
+
+static void
+fpclassify_test (void)
+{
+ init_max_error ();
+
+ check_int ("fpclassify (NaN) == FP_NAN", fpclassify (nan_value), FP_NAN, 0, 0, 0);
+ check_int ("fpclassify (inf) == FP_INFINITE", fpclassify (plus_infty), FP_INFINITE, 0, 0, 0);
+ check_int ("fpclassify (-inf) == FP_INFINITE", fpclassify (minus_infty), FP_INFINITE, 0, 0, 0);
+ check_int ("fpclassify (+0) == FP_ZERO", fpclassify (plus_zero), FP_ZERO, 0, 0, 0);
+ check_int ("fpclassify (-0) == FP_ZERO", fpclassify (minus_zero), FP_ZERO, 0, 0, 0);
+ check_int ("fpclassify (1000) == FP_NORMAL", fpclassify (1000.0), FP_NORMAL, 0, 0, 0);
+
+ print_max_error ("fpclassify", 0, 0);
+}
+
+
+static void
+frexp_test (void)
+{
+ int x;
+
+ init_max_error ();
+
+ check_float ("frexp (inf, &x) == inf", FUNC(frexp) (plus_infty, &x), plus_infty, 0, 0, 0);
+ check_float ("frexp (-inf, &x) == -inf", FUNC(frexp) (minus_infty, &x), minus_infty, 0, 0, 0);
+ check_float ("frexp (NaN, &x) == NaN", FUNC(frexp) (nan_value, &x), nan_value, 0, 0, 0);
+
+ check_float ("frexp (0.0, &x) == 0.0", FUNC(frexp) (0.0, &x), 0.0, 0, 0, 0);
+ check_int ("frexp (0.0, &x) sets x to 0.0", x, 0.0, 0, 0, 0);
+ check_float ("frexp (-0, &x) == -0", FUNC(frexp) (minus_zero, &x), minus_zero, 0, 0, 0);
+ check_int ("frexp (-0, &x) sets x to 0.0", x, 0.0, 0, 0, 0);
+
+ check_float ("frexp (12.8, &x) == 0.8", FUNC(frexp) (12.8L, &x), 0.8L, 0, 0, 0);
+ check_int ("frexp (12.8, &x) sets x to 4", x, 4, 0, 0, 0);
+ check_float ("frexp (-27.34, &x) == -0.854375", FUNC(frexp) (-27.34L, &x), -0.854375L, 0, 0, 0);
+ check_int ("frexp (-27.34, &x) sets x to 5", x, 5, 0, 0, 0);
+
+ print_max_error ("frexp", 0, 0);
+}
+
+#define gamma lgamma /* XXX scp XXX */
+#define gammaf lgammaf /* XXX scp XXX */
+static void
+gamma_test (void)
+{
+ errno = 0;
+ FUNC(gamma) (1);
+
+ if (errno == ENOSYS)
+ /* Function not implemented. */
+ return;
+ feclearexcept (FE_ALL_EXCEPT);
+
+ init_max_error ();
+
+ signgam = 0;
+ check_float ("gamma (inf) == inf", FUNC(gamma) (plus_infty), plus_infty, 0, 0, 0);
+ signgam = 0;
+ check_float ("gamma (0) == inf plus division by zero exception", FUNC(gamma) (0), plus_infty, 0, 0, DIVIDE_BY_ZERO_EXCEPTION);
+ signgam = 0;
+ check_float ("gamma (-3) == inf plus division by zero exception", FUNC(gamma) (-3), plus_infty, 0, 0, DIVIDE_BY_ZERO_EXCEPTION);
+ signgam = 0;
+ check_float ("gamma (-inf) == inf", FUNC(gamma) (minus_infty), plus_infty, 0, 0, 0);
+ signgam = 0;
+ check_float ("gamma (NaN) == NaN", FUNC(gamma) (nan_value), nan_value, 0, 0, 0);
+
+ signgam = 0;
+ check_float ("gamma (1) == 0", FUNC(gamma) (1), 0, 0, 0, 0);
+ check_int ("gamma (1) sets signgam to 1", signgam, 1, 0, 0, 0);
+ signgam = 0;
+ check_float ("gamma (3) == M_LN2l", FUNC(gamma) (3), M_LN2l, 0, 0, 0);
+ check_int ("gamma (3) sets signgam to 1", signgam, 1, 0, 0, 0);
+
+ signgam = 0;
+ check_float ("gamma (0.5) == log(sqrt(pi))", FUNC(gamma) (0.5), M_LOG_SQRT_PIl, 0, 0, 0);
+ check_int ("gamma (0.5) sets signgam to 1", signgam, 1, 0, 0, 0);
+ signgam = 0;
+ check_float ("gamma (-0.5) == log(2*sqrt(pi))", FUNC(gamma) (-0.5), M_LOG_2_SQRT_PIl, DELTA1004, 0, 0);
+ check_int ("gamma (-0.5) sets signgam to -1", signgam, -1, 0, 0, 0);
+
+ print_max_error ("gamma", DELTAgamma, 0);
+}
+#undef gamma /* XXX scp XXX */
+#undef gammaf /* XXX scp XXX */
+
+static void
+hypot_test (void)
+{
+ errno = 0;
+ FUNC(hypot) (0.7L, 12.4L);
+ if (errno == ENOSYS)
+ /* Function not implemented. */
+ return;
+
+ init_max_error ();
+
+ check_float ("hypot (inf, 1) == inf plus sign of zero/inf not specified", FUNC(hypot) (plus_infty, 1), plus_infty, 0, 0, IGNORE_ZERO_INF_SIGN);
+ check_float ("hypot (-inf, 1) == inf plus sign of zero/inf not specified", FUNC(hypot) (minus_infty, 1), plus_infty, 0, 0, IGNORE_ZERO_INF_SIGN);
+
+#ifndef TEST_INLINE
+ check_float ("hypot (inf, NaN) == inf", FUNC(hypot) (plus_infty, nan_value), plus_infty, 0, 0, 0);
+ check_float ("hypot (-inf, NaN) == inf", FUNC(hypot) (minus_infty, nan_value), plus_infty, 0, 0, 0);
+ check_float ("hypot (NaN, inf) == inf", FUNC(hypot) (nan_value, plus_infty), plus_infty, 0, 0, 0);
+ check_float ("hypot (NaN, -inf) == inf", FUNC(hypot) (nan_value, minus_infty), plus_infty, 0, 0, 0);
+#endif
+
+ check_float ("hypot (NaN, NaN) == NaN", FUNC(hypot) (nan_value, nan_value), nan_value, 0, 0, 0);
+
+ /* hypot (x,y) == hypot (+-x, +-y) */
+ check_float ("hypot (0.7, 12.4) == 12.419742348374220601176836866763271", FUNC(hypot) (0.7L, 12.4L), 12.419742348374220601176836866763271L, DELTA1013, 0, 0);
+ check_float ("hypot (-0.7, 12.4) == 12.419742348374220601176836866763271", FUNC(hypot) (-0.7L, 12.4L), 12.419742348374220601176836866763271L, DELTA1014, 0, 0);
+ check_float ("hypot (0.7, -12.4) == 12.419742348374220601176836866763271", FUNC(hypot) (0.7L, -12.4L), 12.419742348374220601176836866763271L, DELTA1015, 0, 0);
+ check_float ("hypot (-0.7, -12.4) == 12.419742348374220601176836866763271", FUNC(hypot) (-0.7L, -12.4L), 12.419742348374220601176836866763271L, DELTA1016, 0, 0);
+ check_float ("hypot (12.4, 0.7) == 12.419742348374220601176836866763271", FUNC(hypot) (12.4L, 0.7L), 12.419742348374220601176836866763271L, DELTA1017, 0, 0);
+ check_float ("hypot (-12.4, 0.7) == 12.419742348374220601176836866763271", FUNC(hypot) (-12.4L, 0.7L), 12.419742348374220601176836866763271L, DELTA1018, 0, 0);
+ check_float ("hypot (12.4, -0.7) == 12.419742348374220601176836866763271", FUNC(hypot) (12.4L, -0.7L), 12.419742348374220601176836866763271L, DELTA1019, 0, 0);
+ check_float ("hypot (-12.4, -0.7) == 12.419742348374220601176836866763271", FUNC(hypot) (-12.4L, -0.7L), 12.419742348374220601176836866763271L, DELTA1020, 0, 0);
+
+ /* hypot (x,0) == fabs (x) */
+ check_float ("hypot (0.7, 0) == 0.7", FUNC(hypot) (0.7L, 0), 0.7L, 0, 0, 0);
+ check_float ("hypot (-0.7, 0) == 0.7", FUNC(hypot) (-0.7L, 0), 0.7L, 0, 0, 0);
+ check_float ("hypot (-5.7e7, 0) == 5.7e7", FUNC(hypot) (-5.7e7, 0), 5.7e7L, 0, 0, 0);
+
+ check_float ("hypot (0.7, 1.2) == 1.3892443989449804508432547041028554", FUNC(hypot) (0.7L, 1.2L), 1.3892443989449804508432547041028554L, DELTA1024, 0, 0);
+
+ print_max_error ("hypot", DELTAhypot, 0);
+}
+
+
+static void
+ilogb_test (void)
+{
+ init_max_error ();
+
+ check_int ("ilogb (1) == 0", FUNC(ilogb) (1), 0, 0, 0, 0);
+ check_int ("ilogb (e) == 1", FUNC(ilogb) (M_El), 1, 0, 0, 0);
+ check_int ("ilogb (1024) == 10", FUNC(ilogb) (1024), 10, 0, 0, 0);
+ check_int ("ilogb (-2000) == 10", FUNC(ilogb) (-2000), 10, 0, 0, 0);
+
+ /* XXX We have a problem here: the standard does not tell us whether
+ exceptions are allowed/required. ignore them for now. */
+
+ check_int ("ilogb (0.0) == FP_ILOGB0 plus exceptions allowed", FUNC(ilogb) (0.0), FP_ILOGB0, 0, 0, EXCEPTIONS_OK);
+ check_int ("ilogb (NaN) == FP_ILOGBNAN plus exceptions allowed", FUNC(ilogb) (nan_value), FP_ILOGBNAN, 0, 0, EXCEPTIONS_OK);
+ check_int ("ilogb (inf) == INT_MAX plus exceptions allowed", FUNC(ilogb) (plus_infty), INT_MAX, 0, 0, EXCEPTIONS_OK);
+ check_int ("ilogb (-inf) == INT_MAX plus exceptions allowed", FUNC(ilogb) (minus_infty), INT_MAX, 0, 0, EXCEPTIONS_OK);
+
+ print_max_error ("ilogb", 0, 0);
+}
+
+static void
+isfinite_test (void)
+{
+ init_max_error ();
+
+ check_bool ("isfinite (0) == true", isfinite (0.0), 1, 0, 0, 0);
+ check_bool ("isfinite (-0) == true", isfinite (minus_zero), 1, 0, 0, 0);
+ check_bool ("isfinite (10) == true", isfinite (10.0), 1, 0, 0, 0);
+ check_bool ("isfinite (inf) == false", isfinite (plus_infty), 0, 0, 0, 0);
+ check_bool ("isfinite (-inf) == false", isfinite (minus_infty), 0, 0, 0, 0);
+ check_bool ("isfinite (NaN) == false", isfinite (nan_value), 0, 0, 0, 0);
+
+ print_max_error ("isfinite", 0, 0);
+}
+
+static void
+isnormal_test (void)
+{
+ init_max_error ();
+
+ check_bool ("isnormal (0) == false", isnormal (0.0), 0, 0, 0, 0);
+ check_bool ("isnormal (-0) == false", isnormal (minus_zero), 0, 0, 0, 0);
+ check_bool ("isnormal (10) == true", isnormal (10.0), 1, 0, 0, 0);
+ check_bool ("isnormal (inf) == false", isnormal (plus_infty), 0, 0, 0, 0);
+ check_bool ("isnormal (-inf) == false", isnormal (minus_infty), 0, 0, 0, 0);
+ check_bool ("isnormal (NaN) == false", isnormal (nan_value), 0, 0, 0, 0);
+
+ print_max_error ("isnormal", 0, 0);
+}
+
+static void
+j0_test (void)
+{
+ FLOAT s, c;
+ errno = 0;
+ FUNC (sincos) (0, &s, &c);
+ if (errno == ENOSYS)
+ /* Required function not implemented. */
+ return;
+ FUNC(j0) (0);
+ if (errno == ENOSYS)
+ /* Function not implemented. */
+ return;
+
+ init_max_error ();
+
+ /* j0 is the Bessel function of the first kind of order 0 */
+ check_float ("j0 (NaN) == NaN", FUNC(j0) (nan_value), nan_value, 0, 0, 0);
+ check_float ("j0 (inf) == 0", FUNC(j0) (plus_infty), 0, 0, 0, 0);
+ check_float ("j0 (-1.0) == 0.76519768655796655145", FUNC(j0) (-1.0), 0.76519768655796655145L, 0, 0, 0);
+ check_float ("j0 (0.0) == 1.0", FUNC(j0) (0.0), 1.0, 0, 0, 0);
+ check_float ("j0 (0.1) == 0.99750156206604003228", FUNC(j0) (0.1L), 0.99750156206604003228L, 0, 0, 0);
+ check_float ("j0 (0.7) == 0.88120088860740528084", FUNC(j0) (0.7L), 0.88120088860740528084L, 0, 0, 0);
+ check_float ("j0 (1.0) == 0.76519768655796655145", FUNC(j0) (1.0), 0.76519768655796655145L, 0, 0, 0);
+ check_float ("j0 (1.5) == 0.51182767173591812875", FUNC(j0) (1.5), 0.51182767173591812875L, 0, 0, 0);
+ check_float ("j0 (2.0) == 0.22389077914123566805", FUNC(j0) (2.0), 0.22389077914123566805L, DELTA1053, 0, 0);
+ check_float ("j0 (8.0) == 0.17165080713755390609", FUNC(j0) (8.0), 0.17165080713755390609L, DELTA1054, 0, 0);
+ check_float ("j0 (10.0) == -0.24593576445134833520", FUNC(j0) (10.0), -0.24593576445134833520L, DELTA1055, 0, 0);
+
+ print_max_error ("j0", DELTAj0, 0);
+}
+
+
+static void
+j1_test (void)
+{
+ FLOAT s, c;
+ errno = 0;
+ FUNC (sincos) (0, &s, &c);
+ if (errno == ENOSYS)
+ /* Required function not implemented. */
+ return;
+ FUNC(j1) (0);
+ if (errno == ENOSYS)
+ /* Function not implemented. */
+ return;
+
+ /* j1 is the Bessel function of the first kind of order 1 */
+
+ init_max_error ();
+
+ check_float ("j1 (NaN) == NaN", FUNC(j1) (nan_value), nan_value, 0, 0, 0);
+ check_float ("j1 (inf) == 0", FUNC(j1) (plus_infty), 0, 0, 0, 0);
+
+ check_float ("j1 (-1.0) == -0.44005058574493351596", FUNC(j1) (-1.0), -0.44005058574493351596L, 0, 0, 0);
+ check_float ("j1 (0.0) == 0.0", FUNC(j1) (0.0), 0.0, 0, 0, 0);
+ check_float ("j1 (0.1) == 0.049937526036241997556", FUNC(j1) (0.1L), 0.049937526036241997556L, 0, 0, 0);
+ check_float ("j1 (0.7) == 0.32899574154005894785", FUNC(j1) (0.7L), 0.32899574154005894785L, 0, 0, 0);
+ check_float ("j1 (1.0) == 0.44005058574493351596", FUNC(j1) (1.0), 0.44005058574493351596L, 0, 0, 0);
+ check_float ("j1 (1.5) == 0.55793650791009964199", FUNC(j1) (1.5), 0.55793650791009964199L, 0, 0, 0);
+ check_float ("j1 (2.0) == 0.57672480775687338720", FUNC(j1) (2.0), 0.57672480775687338720L, DELTA1064, 0, 0);
+ check_float ("j1 (8.0) == 0.23463634685391462438", FUNC(j1) (8.0), 0.23463634685391462438L, DELTA1065, 0, 0);
+ check_float ("j1 (10.0) == 0.043472746168861436670", FUNC(j1) (10.0), 0.043472746168861436670L, DELTA1066, 0, 0);
+
+ print_max_error ("j1", DELTAj1, 0);
+}
+
+static void
+jn_test (void)
+{
+ FLOAT s, c;
+ errno = 0;
+ FUNC (sincos) (0, &s, &c);
+ if (errno == ENOSYS)
+ /* Required function not implemented. */
+ return;
+ FUNC(jn) (1, 1);
+ if (errno == ENOSYS)
+ /* Function not implemented. */
+ return;
+
+ /* jn is the Bessel function of the first kind of order n. */
+ init_max_error ();
+
+ /* jn (0, x) == j0 (x) */
+ check_float ("jn (0, NaN) == NaN", FUNC(jn) (0, nan_value), nan_value, 0, 0, 0);
+ check_float ("jn (0, inf) == 0", FUNC(jn) (0, plus_infty), 0, 0, 0, 0);
+ check_float ("jn (0, -1.0) == 0.76519768655796655145", FUNC(jn) (0, -1.0), 0.76519768655796655145L, 0, 0, 0);
+ check_float ("jn (0, 0.0) == 1.0", FUNC(jn) (0, 0.0), 1.0, 0, 0, 0);
+ check_float ("jn (0, 0.1) == 0.99750156206604003228", FUNC(jn) (0, 0.1L), 0.99750156206604003228L, 0, 0, 0);
+ check_float ("jn (0, 0.7) == 0.88120088860740528084", FUNC(jn) (0, 0.7L), 0.88120088860740528084L, 0, 0, 0);
+ check_float ("jn (0, 1.0) == 0.76519768655796655145", FUNC(jn) (0, 1.0), 0.76519768655796655145L, 0, 0, 0);
+ check_float ("jn (0, 1.5) == 0.51182767173591812875", FUNC(jn) (0, 1.5), 0.51182767173591812875L, 0, 0, 0);
+ check_float ("jn (0, 2.0) == 0.22389077914123566805", FUNC(jn) (0, 2.0), 0.22389077914123566805L, DELTA1075, 0, 0);
+ check_float ("jn (0, 8.0) == 0.17165080713755390609", FUNC(jn) (0, 8.0), 0.17165080713755390609L, DELTA1076, 0, 0);
+ check_float ("jn (0, 10.0) == -0.24593576445134833520", FUNC(jn) (0, 10.0), -0.24593576445134833520L, DELTA1077, 0, 0);
+
+ /* jn (1, x) == j1 (x) */
+ check_float ("jn (1, NaN) == NaN", FUNC(jn) (1, nan_value), nan_value, 0, 0, 0);
+ check_float ("jn (1, inf) == 0", FUNC(jn) (1, plus_infty), 0, 0, 0, 0);
+
+ check_float ("jn (1, -1.0) == -0.44005058574493351596", FUNC(jn) (1, -1.0), -0.44005058574493351596L, 0, 0, 0);
+ check_float ("jn (1, 0.0) == 0.0", FUNC(jn) (1, 0.0), 0.0, 0, 0, 0);
+ check_float ("jn (1, 0.1) == 0.049937526036241997556", FUNC(jn) (1, 0.1L), 0.049937526036241997556L, 0, 0, 0);
+ check_float ("jn (1, 0.7) == 0.32899574154005894785", FUNC(jn) (1, 0.7L), 0.32899574154005894785L, 0, 0, 0);
+ check_float ("jn (1, 1.0) == 0.44005058574493351596", FUNC(jn) (1, 1.0), 0.44005058574493351596L, 0, 0, 0);
+ check_float ("jn (1, 1.5) == 0.55793650791009964199", FUNC(jn) (1, 1.5), 0.55793650791009964199L, 0, 0, 0);
+ check_float ("jn (1, 2.0) == 0.57672480775687338720", FUNC(jn) (1, 2.0), 0.57672480775687338720L, DELTA1086, 0, 0);
+ check_float ("jn (1, 8.0) == 0.23463634685391462438", FUNC(jn) (1, 8.0), 0.23463634685391462438L, DELTA1087, 0, 0);
+ check_float ("jn (1, 10.0) == 0.043472746168861436670", FUNC(jn) (1, 10.0), 0.043472746168861436670L, DELTA1088, 0, 0);
+
+ /* jn (3, x) */
+ check_float ("jn (3, NaN) == NaN", FUNC(jn) (3, nan_value), nan_value, 0, 0, 0);
+ check_float ("jn (3, inf) == 0", FUNC(jn) (3, plus_infty), 0, 0, 0, 0);
+
+ check_float ("jn (3, -1.0) == -0.019563353982668405919", FUNC(jn) (3, -1.0), -0.019563353982668405919L, DELTA1091, 0, 0);
+ check_float ("jn (3, 0.0) == 0.0", FUNC(jn) (3, 0.0), 0.0, 0, 0, 0);
+ check_float ("jn (3, 0.1) == 0.000020820315754756261429", FUNC(jn) (3, 0.1L), 0.000020820315754756261429L, DELTA1093, 0, 0);
+ check_float ("jn (3, 0.7) == 0.0069296548267508408077", FUNC(jn) (3, 0.7L), 0.0069296548267508408077L, DELTA1094, 0, 0);
+ check_float ("jn (3, 1.0) == 0.019563353982668405919", FUNC(jn) (3, 1.0), 0.019563353982668405919L, DELTA1095, 0, 0);
+ check_float ("jn (3, 2.0) == 0.12894324947440205110", FUNC(jn) (3, 2.0), 0.12894324947440205110L, DELTA1096, 0, 0);
+ check_float ("jn (3, 10.0) == 0.058379379305186812343", FUNC(jn) (3, 10.0), 0.058379379305186812343L, DELTA1097, 0, 0);
+
+ /* jn (10, x) */
+ check_float ("jn (10, NaN) == NaN", FUNC(jn) (10, nan_value), nan_value, 0, 0, 0);
+ check_float ("jn (10, inf) == 0", FUNC(jn) (10, plus_infty), 0, 0, 0, 0);
+
+ check_float ("jn (10, -1.0) == 0.26306151236874532070e-9", FUNC(jn) (10, -1.0), 0.26306151236874532070e-9L, DELTA1100, 0, 0);
+ check_float ("jn (10, 0.0) == 0.0", FUNC(jn) (10, 0.0), 0.0, 0, 0, 0);
+ check_float ("jn (10, 0.1) == 0.26905328954342155795e-19", FUNC(jn) (10, 0.1L), 0.26905328954342155795e-19L, DELTA1102, 0, 0);
+ check_float ("jn (10, 0.7) == 0.75175911502153953928e-11", FUNC(jn) (10, 0.7L), 0.75175911502153953928e-11L, DELTA1103, 0, 0);
+ check_float ("jn (10, 1.0) == 0.26306151236874532070e-9", FUNC(jn) (10, 1.0), 0.26306151236874532070e-9L, DELTA1104, 0, 0);
+ check_float ("jn (10, 2.0) == 0.25153862827167367096e-6", FUNC(jn) (10, 2.0), 0.25153862827167367096e-6L, DELTA1105, 0, 0);
+ check_float ("jn (10, 10.0) == 0.20748610663335885770", FUNC(jn) (10, 10.0), 0.20748610663335885770L, DELTA1106, 0, 0);
+
+ print_max_error ("jn", DELTAjn, 0);
+}
+
+
+static void
+ldexp_test (void)
+{
+ check_float ("ldexp (0, 0) == 0", FUNC(ldexp) (0, 0), 0, 0, 0, 0);
+ check_float ("ldexp (-0, 0) == -0", FUNC(ldexp) (minus_zero, 0), minus_zero, 0, 0, 0);
+
+ check_float ("ldexp (inf, 1) == inf", FUNC(ldexp) (plus_infty, 1), plus_infty, 0, 0, 0);
+ check_float ("ldexp (-inf, 1) == -inf", FUNC(ldexp) (minus_infty, 1), minus_infty, 0, 0, 0);
+ check_float ("ldexp (NaN, 1) == NaN", FUNC(ldexp) (nan_value, 1), nan_value, 0, 0, 0);
+
+ check_float ("ldexp (0.8, 4) == 12.8", FUNC(ldexp) (0.8L, 4), 12.8L, 0, 0, 0);
+ check_float ("ldexp (-0.854375, 5) == -27.34", FUNC(ldexp) (-0.854375L, 5), -27.34L, 0, 0, 0);
+
+ /* ldexp (x, 0) == x. */
+ check_float ("ldexp (1.0, 0) == 1.0", FUNC(ldexp) (1.0L, 0L), 1.0L, 0, 0, 0);
+}
+
+static void
+lgamma_test (void)
+{
+ errno = 0;
+ FUNC(lgamma) (0);
+ if (errno == ENOSYS)
+ /* Function not implemented. */
+ return;
+ feclearexcept (FE_ALL_EXCEPT);
+
+ init_max_error ();
+
+ signgam = 0;
+ check_float ("lgamma (inf) == inf", FUNC(lgamma) (plus_infty), plus_infty, 0, 0, 0);
+ signgam = 0;
+ check_float ("lgamma (0) == inf plus division by zero exception", FUNC(lgamma) (0), plus_infty, 0, 0, DIVIDE_BY_ZERO_EXCEPTION);
+ signgam = 0;
+ check_float ("lgamma (NaN) == NaN", FUNC(lgamma) (nan_value), nan_value, 0, 0, 0);
+
+ /* lgamma (x) == +inf plus divide by zero exception for integer x <= 0. */
+ signgam = 0;
+ check_float ("lgamma (-3) == inf plus division by zero exception", FUNC(lgamma) (-3), plus_infty, 0, 0, DIVIDE_BY_ZERO_EXCEPTION);
+ signgam = 0;
+ check_float ("lgamma (-inf) == inf", FUNC(lgamma) (minus_infty), plus_infty, 0, 0, 0);
+
+ signgam = 0;
+ check_float ("lgamma (1) == 0", FUNC(lgamma) (1), 0, 0, 0, 0);
+ check_int ("lgamma (1) sets signgam to 1", signgam, 1, 0, 0, 0);
+
+ signgam = 0;
+ check_float ("lgamma (3) == M_LN2l", FUNC(lgamma) (3), M_LN2l, 0, 0, 0);
+ check_int ("lgamma (3) sets signgam to 1", signgam, 1, 0, 0, 0);
+
+ signgam = 0;
+ check_float ("lgamma (0.5) == log(sqrt(pi))", FUNC(lgamma) (0.5), M_LOG_SQRT_PIl, 0, 0, 0);
+ check_int ("lgamma (0.5) sets signgam to 1", signgam, 1, 0, 0, 0);
+ signgam = 0;
+ check_float ("lgamma (-0.5) == log(2*sqrt(pi))", FUNC(lgamma) (-0.5), M_LOG_2_SQRT_PIl, DELTA1126, 0, 0);
+ check_int ("lgamma (-0.5) sets signgam to -1", signgam, -1, 0, 0, 0);
+ signgam = 0;
+ check_float ("lgamma (0.7) == 0.26086724653166651439", FUNC(lgamma) (0.7L), 0.26086724653166651439L, DELTA1128, 0, 0);
+ check_int ("lgamma (0.7) sets signgam to 1", signgam, 1, 0, 0, 0);
+ signgam = 0;
+ check_float ("lgamma (1.2) == -0.853740900033158497197e-1", FUNC(lgamma) (1.2L), -0.853740900033158497197e-1L, DELTA1130, 0, 0);
+ check_int ("lgamma (1.2) sets signgam to 1", signgam, 1, 0, 0, 0);
+
+ print_max_error ("lgamma", DELTAlgamma, 0);
+}
+
+static void
+lrint_test (void)
+{
+ /* XXX this test is incomplete. We need to have a way to specifiy
+ the rounding method and test the critical cases. So far, only
+ unproblematic numbers are tested. */
+
+ init_max_error ();
+
+ check_long ("lrint (0.0) == 0", FUNC(lrint) (0.0), 0, 0, 0, 0);
+ check_long ("lrint (-0) == 0", FUNC(lrint) (minus_zero), 0, 0, 0, 0);
+ check_long ("lrint (0.2) == 0", FUNC(lrint) (0.2L), 0, 0, 0, 0);
+ check_long ("lrint (-0.2) == 0", FUNC(lrint) (-0.2L), 0, 0, 0, 0);
+
+ check_long ("lrint (1.4) == 1", FUNC(lrint) (1.4L), 1, 0, 0, 0);
+ check_long ("lrint (-1.4) == -1", FUNC(lrint) (-1.4L), -1, 0, 0, 0);
+
+ check_long ("lrint (8388600.3) == 8388600", FUNC(lrint) (8388600.3L), 8388600, 0, 0, 0);
+ check_long ("lrint (-8388600.3) == -8388600", FUNC(lrint) (-8388600.3L), -8388600, 0, 0, 0);
+
+ print_max_error ("lrint", 0, 0);
+}
+
+static void
+llrint_test (void)
+{
+ /* XXX this test is incomplete. We need to have a way to specifiy
+ the rounding method and test the critical cases. So far, only
+ unproblematic numbers are tested. */
+
+ init_max_error ();
+
+ check_longlong ("llrint (0.0) == 0", FUNC(llrint) (0.0), 0, 0, 0, 0);
+ check_longlong ("llrint (-0) == 0", FUNC(llrint) (minus_zero), 0, 0, 0, 0);
+ check_longlong ("llrint (0.2) == 0", FUNC(llrint) (0.2L), 0, 0, 0, 0);
+ check_longlong ("llrint (-0.2) == 0", FUNC(llrint) (-0.2L), 0, 0, 0, 0);
+
+ check_longlong ("llrint (1.4) == 1", FUNC(llrint) (1.4L), 1, 0, 0, 0);
+ check_longlong ("llrint (-1.4) == -1", FUNC(llrint) (-1.4L), -1, 0, 0, 0);
+
+ check_longlong ("llrint (8388600.3) == 8388600", FUNC(llrint) (8388600.3L), 8388600, 0, 0, 0);
+ check_longlong ("llrint (-8388600.3) == -8388600", FUNC(llrint) (-8388600.3L), -8388600, 0, 0, 0);
+
+ /* Test boundary conditions. */
+ /* 0x1FFFFF */
+ check_longlong ("llrint (2097151.0) == 2097151LL", FUNC(llrint) (2097151.0), 2097151LL, 0, 0, 0);
+ /* 0x800000 */
+ check_longlong ("llrint (8388608.0) == 8388608LL", FUNC(llrint) (8388608.0), 8388608LL, 0, 0, 0);
+ /* 0x1000000 */
+ check_longlong ("llrint (16777216.0) == 16777216LL", FUNC(llrint) (16777216.0), 16777216LL, 0, 0, 0);
+ /* 0x20000000000 */
+ check_longlong ("llrint (2199023255552.0) == 2199023255552LL", FUNC(llrint) (2199023255552.0), 2199023255552LL, 0, 0, 0);
+ /* 0x40000000000 */
+ check_longlong ("llrint (4398046511104.0) == 4398046511104LL", FUNC(llrint) (4398046511104.0), 4398046511104LL, 0, 0, 0);
+ /* 0x10000000000000 */
+ check_longlong ("llrint (4503599627370496.0) == 4503599627370496LL", FUNC(llrint) (4503599627370496.0), 4503599627370496LL, 0, 0, 0);
+ /* 0x10000080000000 */
+ check_longlong ("llrint (4503601774854144.0) == 4503601774854144LL", FUNC(llrint) (4503601774854144.0), 4503601774854144LL, 0, 0, 0);
+ /* 0x20000000000000 */
+ check_longlong ("llrint (9007199254740992.0) == 9007199254740992LL", FUNC(llrint) (9007199254740992.0), 9007199254740992LL, 0, 0, 0);
+ /* 0x80000000000000 */
+ check_longlong ("llrint (36028797018963968.0) == 36028797018963968LL", FUNC(llrint) (36028797018963968.0), 36028797018963968LL, 0, 0, 0);
+ /* 0x100000000000000 */
+ check_longlong ("llrint (72057594037927936.0) == 72057594037927936LL", FUNC(llrint) (72057594037927936.0), 72057594037927936LL, 0, 0, 0);
+
+ print_max_error ("llrint", 0, 0);
+}
+
+static void
+log_test (void)
+{
+ errno = 0;
+ FUNC(log) (1);
+ if (errno == ENOSYS)
+ /* Function not implemented. */
+ return;
+ init_max_error ();
+
+ check_float ("log (0) == -inf plus division by zero exception", FUNC(log) (0), minus_infty, 0, 0, DIVIDE_BY_ZERO_EXCEPTION);
+ check_float ("log (-0) == -inf plus division by zero exception", FUNC(log) (minus_zero), minus_infty, 0, 0, DIVIDE_BY_ZERO_EXCEPTION);
+
+ check_float ("log (1) == 0", FUNC(log) (1), 0, 0, 0, 0);
+
+ check_float ("log (-1) == NaN plus invalid exception", FUNC(log) (-1), nan_value, 0, 0, INVALID_EXCEPTION);
+ check_float ("log (inf) == inf", FUNC(log) (plus_infty), plus_infty, 0, 0, 0);
+
+ check_float ("log (e) == 1", FUNC(log) (M_El), 1, DELTA1163, 0, 0);
+ check_float ("log (1.0 / M_El) == -1", FUNC(log) (1.0 / M_El), -1, DELTA1164, 0, 0);
+ check_float ("log (2) == M_LN2l", FUNC(log) (2), M_LN2l, 0, 0, 0);
+ check_float ("log (10) == M_LN10l", FUNC(log) (10), M_LN10l, 0, 0, 0);
+ check_float ("log (0.7) == -0.35667494393873237891263871124118447", FUNC(log) (0.7L), -0.35667494393873237891263871124118447L, DELTA1167, 0, 0);
+
+ print_max_error ("log", DELTAlog, 0);
+}
+
+
+static void
+log10_test (void)
+{
+ errno = 0;
+ FUNC(log10) (1);
+ if (errno == ENOSYS)
+ /* Function not implemented. */
+ return;
+
+ init_max_error ();
+
+ check_float ("log10 (0) == -inf plus division by zero exception", FUNC(log10) (0), minus_infty, 0, 0, DIVIDE_BY_ZERO_EXCEPTION);
+ check_float ("log10 (-0) == -inf plus division by zero exception", FUNC(log10) (minus_zero), minus_infty, 0, 0, DIVIDE_BY_ZERO_EXCEPTION);
+
+ check_float ("log10 (1) == 0", FUNC(log10) (1), 0, 0, 0, 0);
+
+ /* log10 (x) == NaN plus invalid exception if x < 0. */
+ check_float ("log10 (-1) == NaN plus invalid exception", FUNC(log10) (-1), nan_value, 0, 0, INVALID_EXCEPTION);
+
+ check_float ("log10 (inf) == inf", FUNC(log10) (plus_infty), plus_infty, 0, 0, 0);
+ check_float ("log10 (NaN) == NaN", FUNC(log10) (nan_value), nan_value, 0, 0, 0);
+
+ check_float ("log10 (0.1) == -1", FUNC(log10) (0.1L), -1, 0, 0, 0);
+ check_float ("log10 (10.0) == 1", FUNC(log10) (10.0), 1, 0, 0, 0);
+ check_float ("log10 (100.0) == 2", FUNC(log10) (100.0), 2, 0, 0, 0);
+ check_float ("log10 (10000.0) == 4", FUNC(log10) (10000.0), 4, 0, 0, 0);
+ check_float ("log10 (e) == log10(e)", FUNC(log10) (M_El), M_LOG10El, DELTA1178, 0, 0);
+ check_float ("log10 (0.7) == -0.15490195998574316929", FUNC(log10) (0.7L), -0.15490195998574316929L, DELTA1179, 0, 0);
+
+ print_max_error ("log10", DELTAlog10, 0);
+}
+
+
+static void
+log1p_test (void)
+{
+ errno = 0;
+ FUNC(log1p) (0);
+ if (errno == ENOSYS)
+ /* Function not implemented. */
+ return;
+
+ init_max_error ();
+
+ check_float ("log1p (0) == 0", FUNC(log1p) (0), 0, 0, 0, 0);
+ check_float ("log1p (-0) == -0", FUNC(log1p) (minus_zero), minus_zero, 0, 0, 0);
+
+ check_float ("log1p (-1) == -inf plus division by zero exception", FUNC(log1p) (-1), minus_infty, 0, 0, DIVIDE_BY_ZERO_EXCEPTION);
+ check_float ("log1p (-2) == NaN plus invalid exception", FUNC(log1p) (-2), nan_value, 0, 0, INVALID_EXCEPTION);
+
+ check_float ("log1p (inf) == inf", FUNC(log1p) (plus_infty), plus_infty, 0, 0, 0);
+ check_float ("log1p (NaN) == NaN", FUNC(log1p) (nan_value), nan_value, 0, 0, 0);
+
+ check_float ("log1p (M_El - 1.0) == 1", FUNC(log1p) (M_El - 1.0), 1, DELTA1186, 0, 0);
+
+ check_float ("log1p (-0.3) == -0.35667494393873237891263871124118447", FUNC(log1p) (-0.3L), -0.35667494393873237891263871124118447L, DELTA1187, 0, 0);
+
+ print_max_error ("log1p", DELTAlog1p, 0);
+}
+
+
+static void
+log2_test (void)
+{
+ errno = 0;
+ FUNC(log2) (1);
+ if (errno == ENOSYS)
+ /* Function not implemented. */
+ return;
+
+ init_max_error ();
+
+ check_float ("log2 (0) == -inf plus division by zero exception", FUNC(log2) (0), minus_infty, 0, 0, DIVIDE_BY_ZERO_EXCEPTION);
+ check_float ("log2 (-0) == -inf plus division by zero exception", FUNC(log2) (minus_zero), minus_infty, 0, 0, DIVIDE_BY_ZERO_EXCEPTION);
+
+ check_float ("log2 (1) == 0", FUNC(log2) (1), 0, 0, 0, 0);
+
+ check_float ("log2 (-1) == NaN plus invalid exception", FUNC(log2) (-1), nan_value, 0, 0, INVALID_EXCEPTION);
+
+ check_float ("log2 (inf) == inf", FUNC(log2) (plus_infty), plus_infty, 0, 0, 0);
+ check_float ("log2 (NaN) == NaN", FUNC(log2) (nan_value), nan_value, 0, 0, 0);
+
+ check_float ("log2 (e) == M_LOG2El", FUNC(log2) (M_El), M_LOG2El, 0, 0, 0);
+ check_float ("log2 (2.0) == 1", FUNC(log2) (2.0), 1, 0, 0, 0);
+ check_float ("log2 (16.0) == 4", FUNC(log2) (16.0), 4, 0, 0, 0);
+ check_float ("log2 (256.0) == 8", FUNC(log2) (256.0), 8, 0, 0, 0);
+ check_float ("log2 (0.7) == -0.51457317282975824043", FUNC(log2) (0.7L), -0.51457317282975824043L, DELTA1198, 0, 0);
+
+ print_max_error ("log2", DELTAlog2, 0);
+}
+
+
+static void
+logb_test (void)
+{
+ init_max_error ();
+
+ check_float ("logb (inf) == inf", FUNC(logb) (plus_infty), plus_infty, 0, 0, 0);
+ check_float ("logb (-inf) == inf", FUNC(logb) (minus_infty), plus_infty, 0, 0, 0);
+
+ check_float ("logb (0) == -inf plus division by zero exception", FUNC(logb) (0), minus_infty, 0, 0, DIVIDE_BY_ZERO_EXCEPTION);
+
+ check_float ("logb (-0) == -inf plus division by zero exception", FUNC(logb) (minus_zero), minus_infty, 0, 0, DIVIDE_BY_ZERO_EXCEPTION);
+ check_float ("logb (NaN) == NaN", FUNC(logb) (nan_value), nan_value, 0, 0, 0);
+
+ check_float ("logb (1) == 0", FUNC(logb) (1), 0, 0, 0, 0);
+ check_float ("logb (e) == 1", FUNC(logb) (M_El), 1, 0, 0, 0);
+ check_float ("logb (1024) == 10", FUNC(logb) (1024), 10, 0, 0, 0);
+ check_float ("logb (-2000) == 10", FUNC(logb) (-2000), 10, 0, 0, 0);
+
+ print_max_error ("logb", 0, 0);
+}
+
+static void
+lround_test (void)
+{
+ init_max_error ();
+
+ check_long ("lround (0) == 0", FUNC(lround) (0), 0, 0, 0, 0);
+ check_long ("lround (-0) == 0", FUNC(lround) (minus_zero), 0, 0, 0, 0);
+ check_long ("lround (0.2) == 0.0", FUNC(lround) (0.2L), 0.0, 0, 0, 0);
+ check_long ("lround (-0.2) == 0", FUNC(lround) (-0.2L), 0, 0, 0, 0);
+ check_long ("lround (0.5) == 1", FUNC(lround) (0.5), 1, 0, 0, 0);
+ check_long ("lround (-0.5) == -1", FUNC(lround) (-0.5), -1, 0, 0, 0);
+ check_long ("lround (0.8) == 1", FUNC(lround) (0.8L), 1, 0, 0, 0);
+ check_long ("lround (-0.8) == -1", FUNC(lround) (-0.8L), -1, 0, 0, 0);
+ check_long ("lround (1.5) == 2", FUNC(lround) (1.5), 2, 0, 0, 0);
+ check_long ("lround (-1.5) == -2", FUNC(lround) (-1.5), -2, 0, 0, 0);
+ check_long ("lround (22514.5) == 22515", FUNC(lround) (22514.5), 22515, 0, 0, 0);
+ check_long ("lround (-22514.5) == -22515", FUNC(lround) (-22514.5), -22515, 0, 0, 0);
+#ifndef TEST_FLOAT
+ check_long ("lround (2097152.5) == 2097153", FUNC(lround) (2097152.5), 2097153, 0, 0, 0);
+ check_long ("lround (-2097152.5) == -2097153", FUNC(lround) (-2097152.5), -2097153, 0, 0, 0);
+#endif
+ print_max_error ("lround", 0, 0);
+}
+
+
+static void
+llround_test (void)
+{
+ init_max_error ();
+
+ check_longlong ("llround (0) == 0", FUNC(llround) (0), 0, 0, 0, 0);
+ check_longlong ("llround (-0) == 0", FUNC(llround) (minus_zero), 0, 0, 0, 0);
+ check_longlong ("llround (0.2) == 0.0", FUNC(llround) (0.2L), 0.0, 0, 0, 0);
+ check_longlong ("llround (-0.2) == 0", FUNC(llround) (-0.2L), 0, 0, 0, 0);
+ check_longlong ("llround (0.5) == 1", FUNC(llround) (0.5), 1, 0, 0, 0);
+ check_longlong ("llround (-0.5) == -1", FUNC(llround) (-0.5), -1, 0, 0, 0);
+ check_longlong ("llround (0.8) == 1", FUNC(llround) (0.8L), 1, 0, 0, 0);
+ check_longlong ("llround (-0.8) == -1", FUNC(llround) (-0.8L), -1, 0, 0, 0);
+ check_longlong ("llround (1.5) == 2", FUNC(llround) (1.5), 2, 0, 0, 0);
+ check_longlong ("llround (-1.5) == -2", FUNC(llround) (-1.5), -2, 0, 0, 0);
+ check_longlong ("llround (22514.5) == 22515", FUNC(llround) (22514.5), 22515, 0, 0, 0);
+ check_longlong ("llround (-22514.5) == -22515", FUNC(llround) (-22514.5), -22515, 0, 0, 0);
+#ifndef TEST_FLOAT
+ check_longlong ("llround (2097152.5) == 2097153", FUNC(llround) (2097152.5), 2097153, 0, 0, 0);
+ check_longlong ("llround (-2097152.5) == -2097153", FUNC(llround) (-2097152.5), -2097153, 0, 0, 0);
+ check_longlong ("llround (34359738368.5) == 34359738369ll", FUNC(llround) (34359738368.5), 34359738369ll, 0, 0, 0);
+ check_longlong ("llround (-34359738368.5) == -34359738369ll", FUNC(llround) (-34359738368.5), -34359738369ll, 0, 0, 0);
+#endif
+
+ /* Test boundary conditions. */
+ /* 0x1FFFFF */
+ check_longlong ("llround (2097151.0) == 2097151LL", FUNC(llround) (2097151.0), 2097151LL, 0, 0, 0);
+ /* 0x800000 */
+ check_longlong ("llround (8388608.0) == 8388608LL", FUNC(llround) (8388608.0), 8388608LL, 0, 0, 0);
+ /* 0x1000000 */
+ check_longlong ("llround (16777216.0) == 16777216LL", FUNC(llround) (16777216.0), 16777216LL, 0, 0, 0);
+ /* 0x20000000000 */
+ check_longlong ("llround (2199023255552.0) == 2199023255552LL", FUNC(llround) (2199023255552.0), 2199023255552LL, 0, 0, 0);
+ /* 0x40000000000 */
+ check_longlong ("llround (4398046511104.0) == 4398046511104LL", FUNC(llround) (4398046511104.0), 4398046511104LL, 0, 0, 0);
+ /* 0x10000000000000 */
+ check_longlong ("llround (4503599627370496.0) == 4503599627370496LL", FUNC(llround) (4503599627370496.0), 4503599627370496LL, 0, 0, 0);
+ /* 0x10000080000000 */
+ check_longlong ("llrint (4503601774854144.0) == 4503601774854144LL", FUNC(llrint) (4503601774854144.0), 4503601774854144LL, 0, 0, 0);
+ /* 0x20000000000000 */
+ check_longlong ("llround (9007199254740992.0) == 9007199254740992LL", FUNC(llround) (9007199254740992.0), 9007199254740992LL, 0, 0, 0);
+ /* 0x80000000000000 */
+ check_longlong ("llround (36028797018963968.0) == 36028797018963968LL", FUNC(llround) (36028797018963968.0), 36028797018963968LL, 0, 0, 0);
+ /* 0x100000000000000 */
+ check_longlong ("llround (72057594037927936.0) == 72057594037927936LL", FUNC(llround) (72057594037927936.0), 72057594037927936LL, 0, 0, 0);
+
+#ifndef TEST_FLOAT
+ /* 0x100000000 */
+ check_longlong ("llround (4294967295.5) == 4294967296LL", FUNC(llround) (4294967295.5), 4294967296LL, 0, 0, 0);
+ /* 0x200000000 */
+ check_longlong ("llround (8589934591.5) == 8589934592LL", FUNC(llround) (8589934591.5), 8589934592LL, 0, 0, 0);
+#endif
+
+ print_max_error ("llround", 0, 0);
+}
+
+static void
+modf_test (void)
+{
+ FLOAT x;
+
+ init_max_error ();
+
+ check_float ("modf (inf, &x) == 0", FUNC(modf) (plus_infty, &x), 0, 0, 0, 0);
+ check_float ("modf (inf, &x) sets x to plus_infty", x, plus_infty, 0, 0, 0);
+ check_float ("modf (-inf, &x) == -0", FUNC(modf) (minus_infty, &x), minus_zero, 0, 0, 0);
+ check_float ("modf (-inf, &x) sets x to minus_infty", x, minus_infty, 0, 0, 0);
+ check_float ("modf (NaN, &x) == NaN", FUNC(modf) (nan_value, &x), nan_value, 0, 0, 0);
+ check_float ("modf (NaN, &x) sets x to nan_value", x, nan_value, 0, 0, 0);
+ check_float ("modf (0, &x) == 0", FUNC(modf) (0, &x), 0, 0, 0, 0);
+ check_float ("modf (0, &x) sets x to 0", x, 0, 0, 0, 0);
+ check_float ("modf (1.5, &x) == 0.5", FUNC(modf) (1.5, &x), 0.5, 0, 0, 0);
+ check_float ("modf (1.5, &x) sets x to 1", x, 1, 0, 0, 0);
+ check_float ("modf (2.5, &x) == 0.5", FUNC(modf) (2.5, &x), 0.5, 0, 0, 0);
+ check_float ("modf (2.5, &x) sets x to 2", x, 2, 0, 0, 0);
+ check_float ("modf (-2.5, &x) == -0.5", FUNC(modf) (-2.5, &x), -0.5, 0, 0, 0);
+ check_float ("modf (-2.5, &x) sets x to -2", x, -2, 0, 0, 0);
+ check_float ("modf (20, &x) == 0", FUNC(modf) (20, &x), 0, 0, 0, 0);
+ check_float ("modf (20, &x) sets x to 20", x, 20, 0, 0, 0);
+ check_float ("modf (21, &x) == 0", FUNC(modf) (21, &x), 0, 0, 0, 0);
+ check_float ("modf (21, &x) sets x to 21", x, 21, 0, 0, 0);
+ check_float ("modf (89.5, &x) == 0.5", FUNC(modf) (89.5, &x), 0.5, 0, 0, 0);
+ check_float ("modf (89.5, &x) sets x to 89", x, 89, 0, 0, 0);
+
+ print_max_error ("modf", 0, 0);
+}
+
+static void
+nearbyint_test (void)
+{
+ init_max_error ();
+
+ check_float ("nearbyint (0.0) == 0.0", FUNC(nearbyint) (0.0), 0.0, 0, 0, 0);
+ check_float ("nearbyint (-0) == -0", FUNC(nearbyint) (minus_zero), minus_zero, 0, 0, 0);
+ check_float ("nearbyint (inf) == inf", FUNC(nearbyint) (plus_infty), plus_infty, 0, 0, 0);
+ check_float ("nearbyint (-inf) == -inf", FUNC(nearbyint) (minus_infty), minus_infty, 0, 0, 0);
+ check_float ("nearbyint (NaN) == NaN", FUNC(nearbyint) (nan_value), nan_value, 0, 0, 0);
+
+ /* Default rounding mode is round to nearest. */
+ check_float ("nearbyint (0.5) == 0.0", FUNC(nearbyint) (0.5), 0.0, 0, 0, 0);
+ check_float ("nearbyint (1.5) == 2.0", FUNC(nearbyint) (1.5), 2.0, 0, 0, 0);
+ check_float ("nearbyint (-0.5) == -0", FUNC(nearbyint) (-0.5), minus_zero, 0, 0, 0);
+ check_float ("nearbyint (-1.5) == -2.0", FUNC(nearbyint) (-1.5), -2.0, 0, 0, 0);
+
+ print_max_error ("nearbyint", 0, 0);
+}
+
+static void
+nextafter_test (void)
+{
+
+ init_max_error ();
+
+ check_float ("nextafter (0, 0) == 0", FUNC(nextafter) (0, 0), 0, 0, 0, 0);
+ check_float ("nextafter (-0, 0) == 0", FUNC(nextafter) (minus_zero, 0), 0, 0, 0, 0);
+ check_float ("nextafter (0, -0) == -0", FUNC(nextafter) (0, minus_zero), minus_zero, 0, 0, 0);
+ check_float ("nextafter (-0, -0) == -0", FUNC(nextafter) (minus_zero, minus_zero), minus_zero, 0, 0, 0);
+
+ check_float ("nextafter (9, 9) == 9", FUNC(nextafter) (9, 9), 9, 0, 0, 0);
+ check_float ("nextafter (-9, -9) == -9", FUNC(nextafter) (-9, -9), -9, 0, 0, 0);
+ check_float ("nextafter (inf, inf) == inf", FUNC(nextafter) (plus_infty, plus_infty), plus_infty, 0, 0, 0);
+ check_float ("nextafter (-inf, -inf) == -inf", FUNC(nextafter) (minus_infty, minus_infty), minus_infty, 0, 0, 0);
+
+ check_float ("nextafter (NaN, 1.1) == NaN", FUNC(nextafter) (nan_value, 1.1L), nan_value, 0, 0, 0);
+ check_float ("nextafter (1.1, NaN) == NaN", FUNC(nextafter) (1.1L, nan_value), nan_value, 0, 0, 0);
+ check_float ("nextafter (NaN, NaN) == NaN", FUNC(nextafter) (nan_value, nan_value), nan_value, 0, 0, 0);
+
+ /* XXX We need the hexadecimal FP number representation here for further
+ tests. */
+
+ print_max_error ("nextafter", 0, 0);
+}
+
+
+#if 0 /* XXX scp XXX */
+static void
+nexttoward_test (void)
+{
+ init_max_error ();
+ check_float ("nexttoward (0, 0) == 0", FUNC(nexttoward) (0, 0), 0, 0, 0, 0);
+ check_float ("nexttoward (-0, 0) == 0", FUNC(nexttoward) (minus_zero, 0), 0, 0, 0, 0);
+ check_float ("nexttoward (0, -0) == -0", FUNC(nexttoward) (0, minus_zero), minus_zero, 0, 0, 0);
+ check_float ("nexttoward (-0, -0) == -0", FUNC(nexttoward) (minus_zero, minus_zero), minus_zero, 0, 0, 0);
+
+ check_float ("nexttoward (9, 9) == 9", FUNC(nexttoward) (9, 9), 9, 0, 0, 0);
+ check_float ("nexttoward (-9, -9) == -9", FUNC(nexttoward) (-9, -9), -9, 0, 0, 0);
+ check_float ("nexttoward (inf, inf) == inf", FUNC(nexttoward) (plus_infty, plus_infty), plus_infty, 0, 0, 0);
+ check_float ("nexttoward (-inf, -inf) == -inf", FUNC(nexttoward) (minus_infty, minus_infty), minus_infty, 0, 0, 0);
+
+ check_float ("nexttoward (NaN, 1.1) == NaN", FUNC(nexttoward) (nan_value, 1.1L), nan_value, 0, 0, 0);
+ check_float ("nexttoward (1.1, NaN) == NaN", FUNC(nexttoward) (1.1L, nan_value), nan_value, 0, 0, 0);
+ check_float ("nexttoward (NaN, NaN) == NaN", FUNC(nexttoward) (nan_value, nan_value), nan_value, 0, 0, 0);
+
+ /* XXX We need the hexadecimal FP number representation here for further
+ tests. */
+
+ print_max_error ("nexttoward", 0, 0);
+}
+#endif
+
+
+static void
+pow_test (void)
+{
+
+ errno = 0;
+ FUNC(pow) (0, 0);
+ if (errno == ENOSYS)
+ /* Function not implemented. */
+ return;
+
+ init_max_error ();
+
+ check_float ("pow (0, 0) == 1", FUNC(pow) (0, 0), 1, 0, 0, 0);
+ check_float ("pow (0, -0) == 1", FUNC(pow) (0, minus_zero), 1, 0, 0, 0);
+ check_float ("pow (-0, 0) == 1", FUNC(pow) (minus_zero, 0), 1, 0, 0, 0);
+ check_float ("pow (-0, -0) == 1", FUNC(pow) (minus_zero, minus_zero), 1, 0, 0, 0);
+
+ check_float ("pow (10, 0) == 1", FUNC(pow) (10, 0), 1, 0, 0, 0);
+ check_float ("pow (10, -0) == 1", FUNC(pow) (10, minus_zero), 1, 0, 0, 0);
+ check_float ("pow (-10, 0) == 1", FUNC(pow) (-10, 0), 1, 0, 0, 0);
+ check_float ("pow (-10, -0) == 1", FUNC(pow) (-10, minus_zero), 1, 0, 0, 0);
+
+ check_float ("pow (NaN, 0) == 1", FUNC(pow) (nan_value, 0), 1, 0, 0, 0);
+ check_float ("pow (NaN, -0) == 1", FUNC(pow) (nan_value, minus_zero), 1, 0, 0, 0);
+
+
+#ifndef TEST_INLINE
+ check_float ("pow (1.1, inf) == inf", FUNC(pow) (1.1L, plus_infty), plus_infty, 0, 0, 0);
+ check_float ("pow (inf, inf) == inf", FUNC(pow) (plus_infty, plus_infty), plus_infty, 0, 0, 0);
+ check_float ("pow (-1.1, inf) == inf", FUNC(pow) (-1.1L, plus_infty), plus_infty, 0, 0, 0);
+ check_float ("pow (-inf, inf) == inf", FUNC(pow) (minus_infty, plus_infty), plus_infty, 0, 0, 0);
+
+ check_float ("pow (0.9, inf) == 0", FUNC(pow) (0.9L, plus_infty), 0, 0, 0, 0);
+ check_float ("pow (1e-7, inf) == 0", FUNC(pow) (1e-7L, plus_infty), 0, 0, 0, 0);
+ check_float ("pow (-0.9, inf) == 0", FUNC(pow) (-0.9L, plus_infty), 0, 0, 0, 0);
+ check_float ("pow (-1e-7, inf) == 0", FUNC(pow) (-1e-7L, plus_infty), 0, 0, 0, 0);
+
+ check_float ("pow (1.1, -inf) == 0", FUNC(pow) (1.1L, minus_infty), 0, 0, 0, 0);
+ check_float ("pow (inf, -inf) == 0", FUNC(pow) (plus_infty, minus_infty), 0, 0, 0, 0);
+ check_float ("pow (-1.1, -inf) == 0", FUNC(pow) (-1.1L, minus_infty), 0, 0, 0, 0);
+ check_float ("pow (-inf, -inf) == 0", FUNC(pow) (minus_infty, minus_infty), 0, 0, 0, 0);
+
+ check_float ("pow (0.9, -inf) == inf", FUNC(pow) (0.9L, minus_infty), plus_infty, 0, 0, 0);
+ check_float ("pow (1e-7, -inf) == inf", FUNC(pow) (1e-7L, minus_infty), plus_infty, 0, 0, 0);
+ check_float ("pow (-0.9, -inf) == inf", FUNC(pow) (-0.9L, minus_infty), plus_infty, 0, 0, 0);
+ check_float ("pow (-1e-7, -inf) == inf", FUNC(pow) (-1e-7L, minus_infty), plus_infty, 0, 0, 0);
+
+ check_float ("pow (inf, 1e-7) == inf", FUNC(pow) (plus_infty, 1e-7L), plus_infty, 0, 0, 0);
+ check_float ("pow (inf, 1) == inf", FUNC(pow) (plus_infty, 1), plus_infty, 0, 0, 0);
+ check_float ("pow (inf, 1e7) == inf", FUNC(pow) (plus_infty, 1e7L), plus_infty, 0, 0, 0);
+
+ check_float ("pow (inf, -1e-7) == 0", FUNC(pow) (plus_infty, -1e-7L), 0, 0, 0, 0);
+ check_float ("pow (inf, -1) == 0", FUNC(pow) (plus_infty, -1), 0, 0, 0, 0);
+ check_float ("pow (inf, -1e7) == 0", FUNC(pow) (plus_infty, -1e7L), 0, 0, 0, 0);
+
+ check_float ("pow (-inf, 1) == -inf", FUNC(pow) (minus_infty, 1), minus_infty, 0, 0, 0);
+ check_float ("pow (-inf, 11) == -inf", FUNC(pow) (minus_infty, 11), minus_infty, 0, 0, 0);
+ check_float ("pow (-inf, 1001) == -inf", FUNC(pow) (minus_infty, 1001), minus_infty, 0, 0, 0);
+
+ check_float ("pow (-inf, 2) == inf", FUNC(pow) (minus_infty, 2), plus_infty, 0, 0, 0);
+ check_float ("pow (-inf, 12) == inf", FUNC(pow) (minus_infty, 12), plus_infty, 0, 0, 0);
+ check_float ("pow (-inf, 1002) == inf", FUNC(pow) (minus_infty, 1002), plus_infty, 0, 0, 0);
+ check_float ("pow (-inf, 0.1) == inf", FUNC(pow) (minus_infty, 0.1L), plus_infty, 0, 0, 0);
+ check_float ("pow (-inf, 1.1) == inf", FUNC(pow) (minus_infty, 1.1L), plus_infty, 0, 0, 0);
+ check_float ("pow (-inf, 11.1) == inf", FUNC(pow) (minus_infty, 11.1L), plus_infty, 0, 0, 0);
+ check_float ("pow (-inf, 1001.1) == inf", FUNC(pow) (minus_infty, 1001.1L), plus_infty, 0, 0, 0);
+
+ check_float ("pow (-inf, -1) == -0", FUNC(pow) (minus_infty, -1), minus_zero, 0, 0, 0);
+ check_float ("pow (-inf, -11) == -0", FUNC(pow) (minus_infty, -11), minus_zero, 0, 0, 0);
+ check_float ("pow (-inf, -1001) == -0", FUNC(pow) (minus_infty, -1001), minus_zero, 0, 0, 0);
+
+ check_float ("pow (-inf, -2) == 0", FUNC(pow) (minus_infty, -2), 0, 0, 0, 0);
+ check_float ("pow (-inf, -12) == 0", FUNC(pow) (minus_infty, -12), 0, 0, 0, 0);
+ check_float ("pow (-inf, -1002) == 0", FUNC(pow) (minus_infty, -1002), 0, 0, 0, 0);
+ check_float ("pow (-inf, -0.1) == 0", FUNC(pow) (minus_infty, -0.1L), 0, 0, 0, 0);
+ check_float ("pow (-inf, -1.1) == 0", FUNC(pow) (minus_infty, -1.1L), 0, 0, 0, 0);
+ check_float ("pow (-inf, -11.1) == 0", FUNC(pow) (minus_infty, -11.1L), 0, 0, 0, 0);
+ check_float ("pow (-inf, -1001.1) == 0", FUNC(pow) (minus_infty, -1001.1L), 0, 0, 0, 0);
+#endif
+
+ check_float ("pow (NaN, NaN) == NaN", FUNC(pow) (nan_value, nan_value), nan_value, 0, 0, 0);
+ check_float ("pow (0, NaN) == NaN", FUNC(pow) (0, nan_value), nan_value, 0, 0, 0);
+ check_float ("pow (1, NaN) == 1", FUNC(pow) (1, nan_value), 1, 0, 0, 0);
+ check_float ("pow (-1, NaN) == NaN", FUNC(pow) (-1, nan_value), nan_value, 0, 0, 0);
+ check_float ("pow (NaN, 1) == NaN", FUNC(pow) (nan_value, 1), nan_value, 0, 0, 0);
+ check_float ("pow (NaN, -1) == NaN", FUNC(pow) (nan_value, -1), nan_value, 0, 0, 0);
+
+ /* pow (x, NaN) == NaN. */
+ check_float ("pow (3.0, NaN) == NaN", FUNC(pow) (3.0, nan_value), nan_value, 0, 0, 0);
+
+ check_float ("pow (1, inf) == 1", FUNC(pow) (1, plus_infty), 1, 0, 0, 0);
+ check_float ("pow (-1, inf) == 1", FUNC(pow) (-1, plus_infty), 1, 0, 0, 0);
+ check_float ("pow (1, -inf) == 1", FUNC(pow) (1, minus_infty), 1, 0, 0, 0);
+ check_float ("pow (-1, -inf) == 1", FUNC(pow) (-1, minus_infty), 1, 0, 0, 0);
+
+ check_float ("pow (-0.1, 1.1) == NaN plus invalid exception", FUNC(pow) (-0.1L, 1.1L), nan_value, 0, 0, INVALID_EXCEPTION);
+ check_float ("pow (-0.1, -1.1) == NaN plus invalid exception", FUNC(pow) (-0.1L, -1.1L), nan_value, 0, 0, INVALID_EXCEPTION);
+ check_float ("pow (-10.1, 1.1) == NaN plus invalid exception", FUNC(pow) (-10.1L, 1.1L), nan_value, 0, 0, INVALID_EXCEPTION);
+ check_float ("pow (-10.1, -1.1) == NaN plus invalid exception", FUNC(pow) (-10.1L, -1.1L), nan_value, 0, 0, INVALID_EXCEPTION);
+
+ check_float ("pow (0, -1) == inf plus division by zero exception", FUNC(pow) (0, -1), plus_infty, 0, 0, DIVIDE_BY_ZERO_EXCEPTION);
+ check_float ("pow (0, -11) == inf plus division by zero exception", FUNC(pow) (0, -11), plus_infty, 0, 0, DIVIDE_BY_ZERO_EXCEPTION);
+ check_float ("pow (-0, -1) == -inf plus division by zero exception", FUNC(pow) (minus_zero, -1), minus_infty, 0, 0, DIVIDE_BY_ZERO_EXCEPTION);
+ check_float ("pow (-0, -11) == -inf plus division by zero exception", FUNC(pow) (minus_zero, -11), minus_infty, 0, 0, DIVIDE_BY_ZERO_EXCEPTION);
+
+ check_float ("pow (0, -2) == inf plus division by zero exception", FUNC(pow) (0, -2), plus_infty, 0, 0, DIVIDE_BY_ZERO_EXCEPTION);
+ check_float ("pow (0, -11.1) == inf plus division by zero exception", FUNC(pow) (0, -11.1L), plus_infty, 0, 0, DIVIDE_BY_ZERO_EXCEPTION);
+ check_float ("pow (-0, -2) == inf plus division by zero exception", FUNC(pow) (minus_zero, -2), plus_infty, 0, 0, DIVIDE_BY_ZERO_EXCEPTION);
+ check_float ("pow (-0, -11.1) == inf plus division by zero exception", FUNC(pow) (minus_zero, -11.1L), plus_infty, 0, 0, DIVIDE_BY_ZERO_EXCEPTION);
+
+
+ check_float ("pow (0, 1) == 0", FUNC(pow) (0, 1), 0, 0, 0, 0);
+ check_float ("pow (0, 11) == 0", FUNC(pow) (0, 11), 0, 0, 0, 0);
+
+ check_float ("pow (-0, 1) == -0", FUNC(pow) (minus_zero, 1), minus_zero, 0, 0, 0);
+ check_float ("pow (-0, 11) == -0", FUNC(pow) (minus_zero, 11), minus_zero, 0, 0, 0);
+
+
+ check_float ("pow (0, 2) == 0", FUNC(pow) (0, 2), 0, 0, 0, 0);
+ check_float ("pow (0, 11.1) == 0", FUNC(pow) (0, 11.1L), 0, 0, 0, 0);
+
+
+ check_float ("pow (-0, 2) == 0", FUNC(pow) (minus_zero, 2), 0, 0, 0, 0);
+ check_float ("pow (-0, 11.1) == 0", FUNC(pow) (minus_zero, 11.1L), 0, 0, 0, 0);
+
+#ifndef TEST_INLINE
+ /* pow (x, +inf) == +inf for |x| > 1. */
+ check_float ("pow (1.5, inf) == inf", FUNC(pow) (1.5, plus_infty), plus_infty, 0, 0, 0);
+
+ /* pow (x, +inf) == +0 for |x| < 1. */
+ check_float ("pow (0.5, inf) == 0.0", FUNC(pow) (0.5, plus_infty), 0.0, 0, 0, 0);
+
+ /* pow (x, -inf) == +0 for |x| > 1. */
+ check_float ("pow (1.5, -inf) == 0.0", FUNC(pow) (1.5, minus_infty), 0.0, 0, 0, 0);
+
+ /* pow (x, -inf) == +inf for |x| < 1. */
+ check_float ("pow (0.5, -inf) == inf", FUNC(pow) (0.5, minus_infty), plus_infty, 0, 0, 0);
+#endif
+
+ /* pow (+inf, y) == +inf for y > 0. */
+ check_float ("pow (inf, 2) == inf", FUNC(pow) (plus_infty, 2), plus_infty, 0, 0, 0);
+
+ /* pow (+inf, y) == +0 for y < 0. */
+ check_float ("pow (inf, -1) == 0.0", FUNC(pow) (plus_infty, -1), 0.0, 0, 0, 0);
+
+ /* pow (-inf, y) == -inf for y an odd integer > 0. */
+ check_float ("pow (-inf, 27) == -inf", FUNC(pow) (minus_infty, 27), minus_infty, 0, 0, 0);
+
+ /* pow (-inf, y) == +inf for y > 0 and not an odd integer. */
+ check_float ("pow (-inf, 28) == inf", FUNC(pow) (minus_infty, 28), plus_infty, 0, 0, 0);
+
+ /* pow (-inf, y) == -0 for y an odd integer < 0. */
+ check_float ("pow (-inf, -3) == -0", FUNC(pow) (minus_infty, -3), minus_zero, 0, 0, 0);
+ /* pow (-inf, y) == +0 for y < 0 and not an odd integer. */
+ check_float ("pow (-inf, -2.0) == 0.0", FUNC(pow) (minus_infty, -2.0), 0.0, 0, 0, 0);
+
+ /* pow (+0, y) == +0 for y an odd integer > 0. */
+ check_float ("pow (0.0, 27) == 0.0", FUNC(pow) (0.0, 27), 0.0, 0, 0, 0);
+
+ /* pow (-0, y) == -0 for y an odd integer > 0. */
+ check_float ("pow (-0, 27) == -0", FUNC(pow) (minus_zero, 27), minus_zero, 0, 0, 0);
+
+ /* pow (+0, y) == +0 for y > 0 and not an odd integer. */
+ check_float ("pow (0.0, 4) == 0.0", FUNC(pow) (0.0, 4), 0.0, 0, 0, 0);
+
+ /* pow (-0, y) == +0 for y > 0 and not an odd integer. */
+ check_float ("pow (-0, 4) == 0.0", FUNC(pow) (minus_zero, 4), 0.0, 0, 0, 0);
+
+ check_float ("pow (0.7, 1.2) == 0.65180494056638638188", FUNC(pow) (0.7L, 1.2L), 0.65180494056638638188L, DELTA1398, 0, 0);
+
+#if defined TEST_DOUBLE || defined TEST_LDOUBLE
+ check_float ("pow (-7.49321e+133, -9.80818e+16) == 0", FUNC(pow) (-7.49321e+133, -9.80818e+16), 0, 0, 0, 0);
+#endif
+
+ print_max_error ("pow", DELTApow, 0);
+}
+
+static void
+remainder_test (void)
+{
+ errno = 0;
+ FUNC(remainder) (1.625, 1.0);
+ if (errno == ENOSYS)
+ /* Function not implemented. */
+ return;
+
+ init_max_error ();
+
+ check_float ("remainder (1, 0) == NaN plus invalid exception", FUNC(remainder) (1, 0), nan_value, 0, 0, INVALID_EXCEPTION);
+ check_float ("remainder (1, -0) == NaN plus invalid exception", FUNC(remainder) (1, minus_zero), nan_value, 0, 0, INVALID_EXCEPTION);
+ check_float ("remainder (inf, 1) == NaN plus invalid exception", FUNC(remainder) (plus_infty, 1), nan_value, 0, 0, INVALID_EXCEPTION);
+ check_float ("remainder (-inf, 1) == NaN plus invalid exception", FUNC(remainder) (minus_infty, 1), nan_value, 0, 0, INVALID_EXCEPTION);
+ check_float ("remainder (NaN, NaN) == NaN", FUNC(remainder) (nan_value, nan_value), nan_value, 0, 0, 0);
+
+ check_float ("remainder (1.625, 1.0) == -0.375", FUNC(remainder) (1.625, 1.0), -0.375, 0, 0, 0);
+ check_float ("remainder (-1.625, 1.0) == 0.375", FUNC(remainder) (-1.625, 1.0), 0.375, 0, 0, 0);
+ check_float ("remainder (1.625, -1.0) == -0.375", FUNC(remainder) (1.625, -1.0), -0.375, 0, 0, 0);
+ check_float ("remainder (-1.625, -1.0) == 0.375", FUNC(remainder) (-1.625, -1.0), 0.375, 0, 0, 0);
+ check_float ("remainder (5.0, 2.0) == 1.0", FUNC(remainder) (5.0, 2.0), 1.0, 0, 0, 0);
+ check_float ("remainder (3.0, 2.0) == -1.0", FUNC(remainder) (3.0, 2.0), -1.0, 0, 0, 0);
+
+ print_max_error ("remainder", 0, 0);
+}
+
+static void
+remquo_test (void)
+{
+ /* x is needed. */
+ int x;
+
+ errno = 0;
+ FUNC(remquo) (1.625, 1.0, &x);
+ if (errno == ENOSYS)
+ /* Function not implemented. */
+ return;
+
+ init_max_error ();
+
+ check_float ("remquo (1, 0, &x) == NaN plus invalid exception", FUNC(remquo) (1, 0, &x), nan_value, 0, 0, INVALID_EXCEPTION);
+ check_float ("remquo (1, -0, &x) == NaN plus invalid exception", FUNC(remquo) (1, minus_zero, &x), nan_value, 0, 0, INVALID_EXCEPTION);
+ check_float ("remquo (inf, 1, &x) == NaN plus invalid exception", FUNC(remquo) (plus_infty, 1, &x), nan_value, 0, 0, INVALID_EXCEPTION);
+ check_float ("remquo (-inf, 1, &x) == NaN plus invalid exception", FUNC(remquo) (minus_infty, 1, &x), nan_value, 0, 0, INVALID_EXCEPTION);
+ check_float ("remquo (NaN, NaN, &x) == NaN", FUNC(remquo) (nan_value, nan_value, &x), nan_value, 0, 0, 0);
+
+ check_float ("remquo (1.625, 1.0, &x) == -0.375", FUNC(remquo) (1.625, 1.0, &x), -0.375, 0, 0, 0);
+ check_int ("remquo (1.625, 1.0, &x) sets x to 2", x, 2, 0, 0, 0);
+ check_float ("remquo (-1.625, 1.0, &x) == 0.375", FUNC(remquo) (-1.625, 1.0, &x), 0.375, 0, 0, 0);
+ check_int ("remquo (-1.625, 1.0, &x) sets x to -2", x, -2, 0, 0, 0);
+ check_float ("remquo (1.625, -1.0, &x) == -0.375", FUNC(remquo) (1.625, -1.0, &x), -0.375, 0, 0, 0);
+ check_int ("remquo (1.625, -1.0, &x) sets x to -2", x, -2, 0, 0, 0);
+ check_float ("remquo (-1.625, -1.0, &x) == 0.375", FUNC(remquo) (-1.625, -1.0, &x), 0.375, 0, 0, 0);
+ check_int ("remquo (-1.625, -1.0, &x) sets x to 2", x, 2, 0, 0, 0);
+
+ check_float ("remquo (5, 2, &x) == 1", FUNC(remquo) (5, 2, &x), 1, 0, 0, 0);
+ check_int ("remquo (5, 2, &x) sets x to 2", x, 2, 0, 0, 0);
+ check_float ("remquo (3, 2, &x) == -1", FUNC(remquo) (3, 2, &x), -1, 0, 0, 0);
+ check_int ("remquo (3, 2, &x) sets x to 2", x, 2, 0, 0, 0);
+
+ print_max_error ("remquo", 0, 0);
+}
+
+static void
+rint_test (void)
+{
+ init_max_error ();
+
+ check_float ("rint (0.0) == 0.0", FUNC(rint) (0.0), 0.0, 0, 0, 0);
+ check_float ("rint (-0) == -0", FUNC(rint) (minus_zero), minus_zero, 0, 0, 0);
+ check_float ("rint (inf) == inf", FUNC(rint) (plus_infty), plus_infty, 0, 0, 0);
+ check_float ("rint (-inf) == -inf", FUNC(rint) (minus_infty), minus_infty, 0, 0, 0);
+
+ /* Default rounding mode is round to even. */
+ check_float ("rint (0.5) == 0.0", FUNC(rint) (0.5), 0.0, 0, 0, 0);
+ check_float ("rint (1.5) == 2.0", FUNC(rint) (1.5), 2.0, 0, 0, 0);
+ check_float ("rint (2.5) == 2.0", FUNC(rint) (2.5), 2.0, 0, 0, 0);
+ check_float ("rint (3.5) == 4.0", FUNC(rint) (3.5), 4.0, 0, 0, 0);
+ check_float ("rint (4.5) == 4.0", FUNC(rint) (4.5), 4.0, 0, 0, 0);
+ check_float ("rint (-0.5) == -0.0", FUNC(rint) (-0.5), -0.0, 0, 0, 0);
+ check_float ("rint (-1.5) == -2.0", FUNC(rint) (-1.5), -2.0, 0, 0, 0);
+ check_float ("rint (-2.5) == -2.0", FUNC(rint) (-2.5), -2.0, 0, 0, 0);
+ check_float ("rint (-3.5) == -4.0", FUNC(rint) (-3.5), -4.0, 0, 0, 0);
+ check_float ("rint (-4.5) == -4.0", FUNC(rint) (-4.5), -4.0, 0, 0, 0);
+
+ print_max_error ("rint", 0, 0);
+}
+
+static void
+round_test (void)
+{
+ init_max_error ();
+
+ check_float ("round (0) == 0", FUNC(round) (0), 0, 0, 0, 0);
+ check_float ("round (-0) == -0", FUNC(round) (minus_zero), minus_zero, 0, 0, 0);
+ check_float ("round (0.2) == 0.0", FUNC(round) (0.2L), 0.0, 0, 0, 0);
+ check_float ("round (-0.2) == -0", FUNC(round) (-0.2L), minus_zero, 0, 0, 0);
+ check_float ("round (0.5) == 1.0", FUNC(round) (0.5), 1.0, 0, 0, 0);
+ check_float ("round (-0.5) == -1.0", FUNC(round) (-0.5), -1.0, 0, 0, 0);
+ check_float ("round (0.8) == 1.0", FUNC(round) (0.8L), 1.0, 0, 0, 0);
+ check_float ("round (-0.8) == -1.0", FUNC(round) (-0.8L), -1.0, 0, 0, 0);
+ check_float ("round (1.5) == 2.0", FUNC(round) (1.5), 2.0, 0, 0, 0);
+ check_float ("round (-1.5) == -2.0", FUNC(round) (-1.5), -2.0, 0, 0, 0);
+ check_float ("round (2097152.5) == 2097153", FUNC(round) (2097152.5), 2097153, 0, 0, 0);
+ check_float ("round (-2097152.5) == -2097153", FUNC(round) (-2097152.5), -2097153, 0, 0, 0);
+
+ print_max_error ("round", 0, 0);
+}
+
+
+static void
+scalbn_test (void)
+{
+
+ init_max_error ();
+
+ check_float ("scalbn (0, 0) == 0", FUNC(scalbn) (0, 0), 0, 0, 0, 0);
+ check_float ("scalbn (-0, 0) == -0", FUNC(scalbn) (minus_zero, 0), minus_zero, 0, 0, 0);
+
+ check_float ("scalbn (inf, 1) == inf", FUNC(scalbn) (plus_infty, 1), plus_infty, 0, 0, 0);
+ check_float ("scalbn (-inf, 1) == -inf", FUNC(scalbn) (minus_infty, 1), minus_infty, 0, 0, 0);
+ check_float ("scalbn (NaN, 1) == NaN", FUNC(scalbn) (nan_value, 1), nan_value, 0, 0, 0);
+
+ check_float ("scalbn (0.8, 4) == 12.8", FUNC(scalbn) (0.8L, 4), 12.8L, 0, 0, 0);
+ check_float ("scalbn (-0.854375, 5) == -27.34", FUNC(scalbn) (-0.854375L, 5), -27.34L, 0, 0, 0);
+
+ check_float ("scalbn (1, 0) == 1", FUNC(scalbn) (1, 0L), 1, 0, 0, 0);
+
+ print_max_error ("scalbn", 0, 0);
+}
+
+static void
+scalbln_test (void)
+{
+
+ init_max_error ();
+
+ check_float ("scalbln (0, 0) == 0", FUNC(scalbln) (0, 0), 0, 0, 0, 0);
+ check_float ("scalbln (-0, 0) == -0", FUNC(scalbln) (minus_zero, 0), minus_zero, 0, 0, 0);
+
+ check_float ("scalbln (inf, 1) == inf", FUNC(scalbln) (plus_infty, 1), plus_infty, 0, 0, 0);
+ check_float ("scalbln (-inf, 1) == -inf", FUNC(scalbln) (minus_infty, 1), minus_infty, 0, 0, 0);
+ check_float ("scalbln (NaN, 1) == NaN", FUNC(scalbln) (nan_value, 1), nan_value, 0, 0, 0);
+
+ check_float ("scalbln (0.8, 4) == 12.8", FUNC(scalbln) (0.8L, 4), 12.8L, 0, 0, 0);
+ check_float ("scalbln (-0.854375, 5) == -27.34", FUNC(scalbln) (-0.854375L, 5), -27.34L, 0, 0, 0);
+
+ check_float ("scalbln (1, 0) == 1", FUNC(scalbln) (1, 0L), 1, 0, 0, 0);
+
+ print_max_error ("scalbn", 0, 0);
+}
+
+static void
+signbit_test (void)
+{
+
+ init_max_error ();
+
+ check_bool ("signbit (0) == false", signbit (0.0), 0, 0, 0, 0);
+ check_bool ("signbit (-0) == true", signbit (minus_zero), 1, 0, 0, 0);
+ check_bool ("signbit (inf) == false", signbit (plus_infty), 0, 0, 0, 0);
+ check_bool ("signbit (-inf) == true", signbit (minus_infty), 1, 0, 0, 0);
+
+ /* signbit (x) != 0 for x < 0. */
+ check_bool ("signbit (-1) == true", signbit (-1.0), 1, 0, 0, 0);
+ /* signbit (x) == 0 for x >= 0. */
+ check_bool ("signbit (1) == false", signbit (1.0), 0, 0, 0, 0);
+
+ print_max_error ("signbit", 0, 0);
+}
+
+static void
+sin_test (void)
+{
+ errno = 0;
+ FUNC(sin) (0);
+ if (errno == ENOSYS)
+ /* Function not implemented. */
+ return;
+
+ init_max_error ();
+
+ check_float ("sin (0) == 0", FUNC(sin) (0), 0, 0, 0, 0);
+ check_float ("sin (-0) == -0", FUNC(sin) (minus_zero), minus_zero, 0, 0, 0);
+ check_float ("sin (inf) == NaN plus invalid exception", FUNC(sin) (plus_infty), nan_value, 0, 0, INVALID_EXCEPTION);
+ check_float ("sin (-inf) == NaN plus invalid exception", FUNC(sin) (minus_infty), nan_value, 0, 0, INVALID_EXCEPTION);
+ check_float ("sin (NaN) == NaN", FUNC(sin) (nan_value), nan_value, 0, 0, 0);
+
+ check_float ("sin (pi/6) == 0.5", FUNC(sin) (M_PI_6l), 0.5, 0, 0, 0);
+ check_float ("sin (-pi/6) == -0.5", FUNC(sin) (-M_PI_6l), -0.5, 0, 0, 0);
+ check_float ("sin (pi/2) == 1", FUNC(sin) (M_PI_2l), 1, 0, 0, 0);
+ check_float ("sin (-pi/2) == -1", FUNC(sin) (-M_PI_2l), -1, 0, 0, 0);
+ check_float ("sin (0.7) == 0.64421768723769105367261435139872014", FUNC(sin) (0.7L), 0.64421768723769105367261435139872014L, DELTA1524, 0, 0);
+
+ print_max_error ("sin", DELTAsin, 0);
+
+}
+
+
+static void
+sincos_test (void)
+{
+ FLOAT sin_res, cos_res;
+
+ errno = 0;
+ FUNC(sincos) (0, &sin_res, &cos_res);
+ if (errno == ENOSYS)
+ /* Function not implemented. */
+ return;
+
+ init_max_error ();
+
+ /* sincos is treated differently because it returns void. */
+ FUNC (sincos) (0, &sin_res, &cos_res);
+ check_float ("sincos (0, &sin_res, &cos_res) puts 0 in sin_res", sin_res, 0, 0, 0, 0);
+ check_float ("sincos (0, &sin_res, &cos_res) puts 1 in cos_res", cos_res, 1, 0, 0, 0);
+
+ FUNC (sincos) (minus_zero, &sin_res, &cos_res);
+ check_float ("sincos (-0, &sin_res, &cos_res) puts -0 in sin_res", sin_res, minus_zero, 0, 0, 0);
+ check_float ("sincos (-0, &sin_res, &cos_res) puts 1 in cos_res", cos_res, 1, 0, 0, 0);
+ FUNC (sincos) (plus_infty, &sin_res, &cos_res);
+ check_float ("sincos (inf, &sin_res, &cos_res) puts NaN in sin_res plus invalid exception", sin_res, nan_value, 0, 0, INVALID_EXCEPTION);
+ check_float ("sincos (inf, &sin_res, &cos_res) puts NaN in cos_res", cos_res, nan_value, 0, 0, 0);
+ FUNC (sincos) (minus_infty, &sin_res, &cos_res);
+ check_float ("sincos (-inf, &sin_res, &cos_res) puts NaN in sin_res plus invalid exception", sin_res, nan_value, 0, 0, INVALID_EXCEPTION);
+ check_float ("sincos (-inf, &sin_res, &cos_res) puts NaN in cos_res", cos_res, nan_value, 0, 0, 0);
+ FUNC (sincos) (nan_value, &sin_res, &cos_res);
+ check_float ("sincos (NaN, &sin_res, &cos_res) puts NaN in sin_res", sin_res, nan_value, 0, 0, 0);
+ check_float ("sincos (NaN, &sin_res, &cos_res) puts NaN in cos_res", cos_res, nan_value, 0, 0, 0);
+
+ FUNC (sincos) (M_PI_2l, &sin_res, &cos_res);
+ check_float ("sincos (pi/2, &sin_res, &cos_res) puts 1 in sin_res", sin_res, 1, 0, 0, 0);
+ check_float ("sincos (pi/2, &sin_res, &cos_res) puts 0 in cos_res", cos_res, 0, DELTA1536, 0, 0);
+ FUNC (sincos) (M_PI_6l, &sin_res, &cos_res);
+ check_float ("sincos (pi/6, &sin_res, &cos_res) puts 0.5 in sin_res", sin_res, 0.5, 0, 0, 0);
+ check_float ("sincos (pi/6, &sin_res, &cos_res) puts 0.86602540378443864676372317075293616 in cos_res", cos_res, 0.86602540378443864676372317075293616L, 0, 0, 0);
+ FUNC (sincos) (M_PI_6l*2.0, &sin_res, &cos_res);
+ check_float ("sincos (M_PI_6l*2.0, &sin_res, &cos_res) puts 0.86602540378443864676372317075293616 in sin_res", sin_res, 0.86602540378443864676372317075293616L, DELTA1539, 0, 0);
+ check_float ("sincos (M_PI_6l*2.0, &sin_res, &cos_res) puts 0.5 in cos_res", cos_res, 0.5, DELTA1540, 0, 0);
+ FUNC (sincos) (0.7L, &sin_res, &cos_res);
+ check_float ("sincos (0.7, &sin_res, &cos_res) puts 0.64421768723769105367261435139872014 in sin_res", sin_res, 0.64421768723769105367261435139872014L, DELTA1541, 0, 0);
+ check_float ("sincos (0.7, &sin_res, &cos_res) puts 0.76484218728448842625585999019186495 in cos_res", cos_res, 0.76484218728448842625585999019186495L, DELTA1542, 0, 0);
+
+ print_max_error ("sincos", DELTAsincos, 0);
+}
+
+static void
+sinh_test (void)
+{
+ errno = 0;
+ FUNC(sinh) (0.7L);
+ if (errno == ENOSYS)
+ /* Function not implemented. */
+ return;
+
+ init_max_error ();
+ check_float ("sinh (0) == 0", FUNC(sinh) (0), 0, 0, 0, 0);
+ check_float ("sinh (-0) == -0", FUNC(sinh) (minus_zero), minus_zero, 0, 0, 0);
+
+#ifndef TEST_INLINE
+ check_float ("sinh (inf) == inf", FUNC(sinh) (plus_infty), plus_infty, 0, 0, 0);
+ check_float ("sinh (-inf) == -inf", FUNC(sinh) (minus_infty), minus_infty, 0, 0, 0);
+#endif
+ check_float ("sinh (NaN) == NaN", FUNC(sinh) (nan_value), nan_value, 0, 0, 0);
+
+ check_float ("sinh (0.7) == 0.75858370183953350346", FUNC(sinh) (0.7L), 0.75858370183953350346L, DELTA1548, 0, 0);
+#if 0 /* XXX scp XXX */
+ check_float ("sinh (0x8p-32) == 1.86264514923095703232705808926175479e-9", FUNC(sinh) (0x8p-32L), 1.86264514923095703232705808926175479e-9L, 0, 0, 0);
+#endif
+
+ print_max_error ("sinh", DELTAsinh, 0);
+}
+
+static void
+sqrt_test (void)
+{
+ errno = 0;
+ FUNC(sqrt) (1);
+ if (errno == ENOSYS)
+ /* Function not implemented. */
+ return;
+
+ init_max_error ();
+
+ check_float ("sqrt (0) == 0", FUNC(sqrt) (0), 0, 0, 0, 0);
+ check_float ("sqrt (NaN) == NaN", FUNC(sqrt) (nan_value), nan_value, 0, 0, 0);
+ check_float ("sqrt (inf) == inf", FUNC(sqrt) (plus_infty), plus_infty, 0, 0, 0);
+
+ check_float ("sqrt (-0) == -0", FUNC(sqrt) (minus_zero), minus_zero, 0, 0, 0);
+
+ /* sqrt (x) == NaN plus invalid exception for x < 0. */
+ check_float ("sqrt (-1) == NaN plus invalid exception", FUNC(sqrt) (-1), nan_value, 0, 0, INVALID_EXCEPTION);
+ check_float ("sqrt (-inf) == NaN plus invalid exception", FUNC(sqrt) (minus_infty), nan_value, 0, 0, INVALID_EXCEPTION);
+ check_float ("sqrt (NaN) == NaN", FUNC(sqrt) (nan_value), nan_value, 0, 0, 0);
+
+ check_float ("sqrt (2209) == 47", FUNC(sqrt) (2209), 47, 0, 0, 0);
+ check_float ("sqrt (4) == 2", FUNC(sqrt) (4), 2, 0, 0, 0);
+ check_float ("sqrt (2) == M_SQRT2l", FUNC(sqrt) (2), M_SQRT2l, 0, 0, 0);
+ check_float ("sqrt (0.25) == 0.5", FUNC(sqrt) (0.25), 0.5, 0, 0, 0);
+ check_float ("sqrt (6642.25) == 81.5", FUNC(sqrt) (6642.25), 81.5, 0, 0, 0);
+ check_float ("sqrt (15239.9025) == 123.45", FUNC(sqrt) (15239.9025L), 123.45L, DELTA1562, 0, 0);
+ check_float ("sqrt (0.7) == 0.83666002653407554797817202578518747", FUNC(sqrt) (0.7L), 0.83666002653407554797817202578518747L, 0, 0, 0);
+
+ print_max_error ("sqrt", DELTAsqrt, 0);
+}
+
+static void
+tan_test (void)
+{
+ errno = 0;
+ FUNC(tan) (0);
+ if (errno == ENOSYS)
+ /* Function not implemented. */
+ return;
+
+ init_max_error ();
+
+ check_float ("tan (0) == 0", FUNC(tan) (0), 0, 0, 0, 0);
+ check_float ("tan (-0) == -0", FUNC(tan) (minus_zero), minus_zero, 0, 0, 0);
+ check_float ("tan (inf) == NaN plus invalid exception", FUNC(tan) (plus_infty), nan_value, 0, 0, INVALID_EXCEPTION);
+ check_float ("tan (-inf) == NaN plus invalid exception", FUNC(tan) (minus_infty), nan_value, 0, 0, INVALID_EXCEPTION);
+ check_float ("tan (NaN) == NaN", FUNC(tan) (nan_value), nan_value, 0, 0, 0);
+
+ check_float ("tan (pi/4) == 1", FUNC(tan) (M_PI_4l), 1, DELTA1569, 0, 0);
+ check_float ("tan (0.7) == 0.84228838046307944812813500221293775", FUNC(tan) (0.7L), 0.84228838046307944812813500221293775L, DELTA1570, 0, 0);
+
+ print_max_error ("tan", DELTAtan, 0);
+}
+
+static void
+tanh_test (void)
+{
+ errno = 0;
+ FUNC(tanh) (0.7L);
+ if (errno == ENOSYS)
+ /* Function not implemented. */
+ return;
+
+ init_max_error ();
+
+ check_float ("tanh (0) == 0", FUNC(tanh) (0), 0, 0, 0, 0);
+ check_float ("tanh (-0) == -0", FUNC(tanh) (minus_zero), minus_zero, 0, 0, 0);
+
+#ifndef TEST_INLINE
+ check_float ("tanh (inf) == 1", FUNC(tanh) (plus_infty), 1, 0, 0, 0);
+ check_float ("tanh (-inf) == -1", FUNC(tanh) (minus_infty), -1, 0, 0, 0);
+#endif
+ check_float ("tanh (NaN) == NaN", FUNC(tanh) (nan_value), nan_value, 0, 0, 0);
+
+ check_float ("tanh (0.7) == 0.60436777711716349631", FUNC(tanh) (0.7L), 0.60436777711716349631L, DELTA1576, 0, 0);
+ check_float ("tanh (-0.7) == -0.60436777711716349631", FUNC(tanh) (-0.7L), -0.60436777711716349631L, DELTA1577, 0, 0);
+
+ check_float ("tanh (1.0) == 0.7615941559557648881194582826047935904", FUNC(tanh) (1.0L), 0.7615941559557648881194582826047935904L, 0, 0, 0);
+ check_float ("tanh (-1.0) == -0.7615941559557648881194582826047935904", FUNC(tanh) (-1.0L), -0.7615941559557648881194582826047935904L, 0, 0, 0);
+
+ /* 2^-57 */
+ check_float ("tanh (6.938893903907228377647697925567626953125e-18) == 6.938893903907228377647697925567626953125e-18", FUNC(tanh) (6.938893903907228377647697925567626953125e-18L), 6.938893903907228377647697925567626953125e-18L, 0, 0, 0);
+
+ print_max_error ("tanh", DELTAtanh, 0);
+}
+
+static void
+tgamma_test (void)
+{
+ errno = 0;
+ FUNC(tgamma) (1);
+ if (errno == ENOSYS)
+ /* Function not implemented. */
+ return;
+ feclearexcept (FE_ALL_EXCEPT);
+
+ init_max_error ();
+
+ check_float ("tgamma (inf) == inf", FUNC(tgamma) (plus_infty), plus_infty, 0, 0, 0);
+ check_float ("tgamma (0) == inf plus divide-by-zero", FUNC(tgamma) (0), plus_infty, 0, 0, DIVIDE_BY_ZERO_EXCEPTION);
+ check_float ("tgamma (-0) == inf plus divide-by-zero", FUNC(tgamma) (minus_zero), minus_infty, 0, 0, DIVIDE_BY_ZERO_EXCEPTION);
+ /* tgamma (x) == NaN plus invalid exception for integer x <= 0. */
+ check_float ("tgamma (-2) == NaN plus invalid exception", FUNC(tgamma) (-2), nan_value, 0, 0, INVALID_EXCEPTION);
+ check_float ("tgamma (-inf) == NaN plus invalid exception", FUNC(tgamma) (minus_infty), nan_value, 0, 0, INVALID_EXCEPTION);
+ check_float ("tgamma (NaN) == NaN", FUNC(tgamma) (nan_value), nan_value, 0, 0, 0);
+
+ check_float ("tgamma (0.5) == sqrt (pi)", FUNC(tgamma) (0.5), M_SQRT_PIl, DELTA1587, 0, 0);
+ check_float ("tgamma (-0.5) == -2 sqrt (pi)", FUNC(tgamma) (-0.5), -M_2_SQRT_PIl, DELTA1588, 0, 0);
+
+ check_float ("tgamma (1) == 1", FUNC(tgamma) (1), 1, 0, 0, 0);
+ check_float ("tgamma (4) == 6", FUNC(tgamma) (4), 6, DELTA1590, 0, 0);
+
+ check_float ("tgamma (0.7) == 1.29805533264755778568", FUNC(tgamma) (0.7L), 1.29805533264755778568L, DELTA1591, 0, 0);
+ check_float ("tgamma (1.2) == 0.91816874239976061064", FUNC(tgamma) (1.2L), 0.91816874239976061064L, 0, 0, 0);
+
+ print_max_error ("tgamma", DELTAtgamma, 0);
+}
+
+static void
+trunc_test (void)
+{
+ init_max_error ();
+
+ check_float ("trunc (inf) == inf", FUNC(trunc) (plus_infty), plus_infty, 0, 0, 0);
+ check_float ("trunc (-inf) == -inf", FUNC(trunc) (minus_infty), minus_infty, 0, 0, 0);
+ check_float ("trunc (NaN) == NaN", FUNC(trunc) (nan_value), nan_value, 0, 0, 0);
+
+ check_float ("trunc (0) == 0", FUNC(trunc) (0), 0, 0, 0, 0);
+ check_float ("trunc (-0) == -0", FUNC(trunc) (minus_zero), minus_zero, 0, 0, 0);
+ check_float ("trunc (0.625) == 0", FUNC(trunc) (0.625), 0, 0, 0, 0);
+ check_float ("trunc (-0.625) == -0", FUNC(trunc) (-0.625), minus_zero, 0, 0, 0);
+ check_float ("trunc (1) == 1", FUNC(trunc) (1), 1, 0, 0, 0);
+ check_float ("trunc (-1) == -1", FUNC(trunc) (-1), -1, 0, 0, 0);
+ check_float ("trunc (1.625) == 1", FUNC(trunc) (1.625), 1, 0, 0, 0);
+ check_float ("trunc (-1.625) == -1", FUNC(trunc) (-1.625), -1, 0, 0, 0);
+
+ check_float ("trunc (1048580.625) == 1048580", FUNC(trunc) (1048580.625L), 1048580L, 0, 0, 0);
+ check_float ("trunc (-1048580.625) == -1048580", FUNC(trunc) (-1048580.625L), -1048580L, 0, 0, 0);
+
+ check_float ("trunc (8388610.125) == 8388610.0", FUNC(trunc) (8388610.125L), 8388610.0L, 0, 0, 0);
+ check_float ("trunc (-8388610.125) == -8388610.0", FUNC(trunc) (-8388610.125L), -8388610.0L, 0, 0, 0);
+
+ check_float ("trunc (4294967296.625) == 4294967296.0", FUNC(trunc) (4294967296.625L), 4294967296.0L, 0, 0, 0);
+ check_float ("trunc (-4294967296.625) == -4294967296.0", FUNC(trunc) (-4294967296.625L), -4294967296.0L, 0, 0, 0);
+
+
+ print_max_error ("trunc", 0, 0);
+}
+
+static void
+y0_test (void)
+{
+ FLOAT s, c;
+ errno = 0;
+ FUNC (sincos) (0, &s, &c);
+ if (errno == ENOSYS)
+ /* Required function not implemented. */
+ return;
+ FUNC(y0) (1);
+ if (errno == ENOSYS)
+ /* Function not implemented. */
+ return;
+
+ /* y0 is the Bessel function of the second kind of order 0 */
+ init_max_error ();
+
+ check_float ("y0 (-1.0) == NaN", FUNC(y0) (-1.0), nan_value, 0, 0, INVALID_EXCEPTION);
+ check_float ("y0 (0.0) == -inf", FUNC(y0) (0.0), minus_infty, 0, 0, DIVIDE_BY_ZERO_EXCEPTION);
+ check_float ("y0 (NaN) == NaN", FUNC(y0) (nan_value), nan_value, 0, 0, 0);
+ check_float ("y0 (inf) == 0", FUNC(y0) (plus_infty), 0, 0, 0, 0);
+
+ check_float ("y0 (0.1) == -1.5342386513503668441", FUNC(y0) (0.1L), -1.5342386513503668441L, DELTA1614, 0, 0);
+ check_float ("y0 (0.7) == -0.19066492933739506743", FUNC(y0) (0.7L), -0.19066492933739506743L, DELTA1615, 0, 0);
+ check_float ("y0 (1.0) == 0.088256964215676957983", FUNC(y0) (1.0), 0.088256964215676957983L, DELTA1616, 0, 0);
+ check_float ("y0 (1.5) == 0.38244892379775884396", FUNC(y0) (1.5), 0.38244892379775884396L, DELTA1617, 0, 0);
+ check_float ("y0 (2.0) == 0.51037567264974511960", FUNC(y0) (2.0), 0.51037567264974511960L, DELTA1618, 0, 0);
+ check_float ("y0 (8.0) == 0.22352148938756622053", FUNC(y0) (8.0), 0.22352148938756622053L, DELTA1619, 0, 0);
+ check_float ("y0 (10.0) == 0.055671167283599391424", FUNC(y0) (10.0), 0.055671167283599391424L, DELTA1620, 0, 0);
+
+ print_max_error ("y0", DELTAy0, 0);
+}
+
+
+static void
+y1_test (void)
+{
+ FLOAT s, c;
+ errno = 0;
+ FUNC (sincos) (0, &s, &c);
+ if (errno == ENOSYS)
+ /* Required function not implemented. */
+ return;
+ FUNC(y1) (1);
+ if (errno == ENOSYS)
+ /* Function not implemented. */
+ return;
+
+ /* y1 is the Bessel function of the second kind of order 1 */
+ init_max_error ();
+
+ check_float ("y1 (-1.0) == NaN", FUNC(y1) (-1.0), nan_value, 0, 0, INVALID_EXCEPTION);
+ check_float ("y1 (0.0) == -inf", FUNC(y1) (0.0), minus_infty, 0, 0, DIVIDE_BY_ZERO_EXCEPTION);
+ check_float ("y1 (inf) == 0", FUNC(y1) (plus_infty), 0, 0, 0, 0);
+ check_float ("y1 (NaN) == NaN", FUNC(y1) (nan_value), nan_value, 0, 0, 0);
+
+ check_float ("y1 (0.1) == -6.4589510947020269877", FUNC(y1) (0.1L), -6.4589510947020269877L, DELTA1625, 0, 0);
+ check_float ("y1 (0.7) == -1.1032498719076333697", FUNC(y1) (0.7L), -1.1032498719076333697L, DELTA1626, 0, 0);
+ check_float ("y1 (1.0) == -0.78121282130028871655", FUNC(y1) (1.0), -0.78121282130028871655L, DELTA1627, 0, 0);
+ check_float ("y1 (1.5) == -0.41230862697391129595", FUNC(y1) (1.5), -0.41230862697391129595L, DELTA1628, 0, 0);
+ check_float ("y1 (2.0) == -0.10703243154093754689", FUNC(y1) (2.0), -0.10703243154093754689L, DELTA1629, 0, 0);
+ check_float ("y1 (8.0) == -0.15806046173124749426", FUNC(y1) (8.0), -0.15806046173124749426L, DELTA1630, 0, 0);
+ check_float ("y1 (10.0) == 0.24901542420695388392", FUNC(y1) (10.0), 0.24901542420695388392L, DELTA1631, 0, 0);
+
+ print_max_error ("y1", DELTAy1, 0);
+}
+
+static void
+yn_test (void)
+{
+ FLOAT s, c;
+ errno = 0;
+ FUNC (sincos) (0, &s, &c);
+ if (errno == ENOSYS)
+ /* Required function not implemented. */
+ return;
+ FUNC(yn) (1, 1);
+ if (errno == ENOSYS)
+ /* Function not implemented. */
+ return;
+
+ /* yn is the Bessel function of the second kind of order n */
+ init_max_error ();
+
+ /* yn (0, x) == y0 (x) */
+ check_float ("yn (0, -1.0) == NaN", FUNC(yn) (0, -1.0), nan_value, 0, 0, INVALID_EXCEPTION);
+ check_float ("yn (0, 0.0) == -inf", FUNC(yn) (0, 0.0), minus_infty, 0, 0, DIVIDE_BY_ZERO_EXCEPTION);
+ check_float ("yn (0, NaN) == NaN", FUNC(yn) (0, nan_value), nan_value, 0, 0, 0);
+ check_float ("yn (0, inf) == 0", FUNC(yn) (0, plus_infty), 0, 0, 0, 0);
+
+ check_float ("yn (0, 0.1) == -1.5342386513503668441", FUNC(yn) (0, 0.1L), -1.5342386513503668441L, DELTA1636, 0, 0);
+ check_float ("yn (0, 0.7) == -0.19066492933739506743", FUNC(yn) (0, 0.7L), -0.19066492933739506743L, DELTA1637, 0, 0);
+ check_float ("yn (0, 1.0) == 0.088256964215676957983", FUNC(yn) (0, 1.0), 0.088256964215676957983L, DELTA1638, 0, 0);
+ check_float ("yn (0, 1.5) == 0.38244892379775884396", FUNC(yn) (0, 1.5), 0.38244892379775884396L, DELTA1639, 0, 0);
+ check_float ("yn (0, 2.0) == 0.51037567264974511960", FUNC(yn) (0, 2.0), 0.51037567264974511960L, DELTA1640, 0, 0);
+ check_float ("yn (0, 8.0) == 0.22352148938756622053", FUNC(yn) (0, 8.0), 0.22352148938756622053L, DELTA1641, 0, 0);
+ check_float ("yn (0, 10.0) == 0.055671167283599391424", FUNC(yn) (0, 10.0), 0.055671167283599391424L, DELTA1642, 0, 0);
+
+ /* yn (1, x) == y1 (x) */
+ check_float ("yn (1, -1.0) == NaN", FUNC(yn) (1, -1.0), nan_value, 0, 0, INVALID_EXCEPTION);
+ check_float ("yn (1, 0.0) == -inf", FUNC(yn) (1, 0.0), minus_infty, 0, 0, DIVIDE_BY_ZERO_EXCEPTION);
+ check_float ("yn (1, inf) == 0", FUNC(yn) (1, plus_infty), 0, 0, 0, 0);
+ check_float ("yn (1, NaN) == NaN", FUNC(yn) (1, nan_value), nan_value, 0, 0, 0);
+
+ check_float ("yn (1, 0.1) == -6.4589510947020269877", FUNC(yn) (1, 0.1L), -6.4589510947020269877L, DELTA1647, 0, 0);
+ check_float ("yn (1, 0.7) == -1.1032498719076333697", FUNC(yn) (1, 0.7L), -1.1032498719076333697L, DELTA1648, 0, 0);
+ check_float ("yn (1, 1.0) == -0.78121282130028871655", FUNC(yn) (1, 1.0), -0.78121282130028871655L, DELTA1649, 0, 0);
+ check_float ("yn (1, 1.5) == -0.41230862697391129595", FUNC(yn) (1, 1.5), -0.41230862697391129595L, DELTA1650, 0, 0);
+ check_float ("yn (1, 2.0) == -0.10703243154093754689", FUNC(yn) (1, 2.0), -0.10703243154093754689L, DELTA1651, 0, 0);
+ check_float ("yn (1, 8.0) == -0.15806046173124749426", FUNC(yn) (1, 8.0), -0.15806046173124749426L, DELTA1652, 0, 0);
+ check_float ("yn (1, 10.0) == 0.24901542420695388392", FUNC(yn) (1, 10.0), 0.24901542420695388392L, DELTA1653, 0, 0);
+
+ /* yn (3, x) */
+ check_float ("yn (3, inf) == 0", FUNC(yn) (3, plus_infty), 0, 0, 0, 0);
+ check_float ("yn (3, NaN) == NaN", FUNC(yn) (3, nan_value), nan_value, 0, 0, 0);
+
+ check_float ("yn (3, 0.1) == -5099.3323786129048894", FUNC(yn) (3, 0.1L), -5099.3323786129048894L, DELTA1656, 0, 0);
+ check_float ("yn (3, 0.7) == -15.819479052819633505", FUNC(yn) (3, 0.7L), -15.819479052819633505L, DELTA1657, 0, 0);
+ check_float ("yn (3, 1.0) == -5.8215176059647288478", FUNC(yn) (3, 1.0), -5.8215176059647288478L, 0, 0, 0);
+ check_float ("yn (3, 2.0) == -1.1277837768404277861", FUNC(yn) (3, 2.0), -1.1277837768404277861L, DELTA1659, 0, 0);
+ check_float ("yn (3, 10.0) == -0.25136265718383732978", FUNC(yn) (3, 10.0), -0.25136265718383732978L, DELTA1660, 0, 0);
+
+ /* yn (10, x) */
+ check_float ("yn (10, inf) == 0", FUNC(yn) (10, plus_infty), 0, 0, 0, 0);
+ check_float ("yn (10, NaN) == NaN", FUNC(yn) (10, nan_value), nan_value, 0, 0, 0);
+
+ check_float ("yn (10, 0.1) == -0.11831335132045197885e19", FUNC(yn) (10, 0.1L), -0.11831335132045197885e19L, DELTA1663, 0, 0);
+ check_float ("yn (10, 0.7) == -0.42447194260703866924e10", FUNC(yn) (10, 0.7L), -0.42447194260703866924e10L, DELTA1664, 0, 0);
+ check_float ("yn (10, 1.0) == -0.12161801427868918929e9", FUNC(yn) (10, 1.0), -0.12161801427868918929e9L, DELTA1665, 0, 0);
+ check_float ("yn (10, 2.0) == -129184.54220803928264", FUNC(yn) (10, 2.0), -129184.54220803928264L, DELTA1666, 0, 0);
+ check_float ("yn (10, 10.0) == -0.35981415218340272205", FUNC(yn) (10, 10.0), -0.35981415218340272205L, DELTA1667, 0, 0);
+
+ print_max_error ("yn", DELTAyn, 0);
+
+}
+
+
+
+static void
+initialize (void)
+{
+ plus_zero = 0.0;
+ nan_value = plus_zero / plus_zero; /* Suppress GCC warning */
+
+ minus_zero = FUNC(copysign) (0.0, -1.0);
+ plus_infty = CHOOSE (HUGE_VALL, HUGE_VAL, HUGE_VALF,
+ HUGE_VALL, HUGE_VAL, HUGE_VALF);
+ minus_infty = CHOOSE (-HUGE_VALL, -HUGE_VAL, -HUGE_VALF,
+ -HUGE_VALL, -HUGE_VAL, -HUGE_VALF);
+
+ (void) &plus_zero;
+ (void) &nan_value;
+ (void) &minus_zero;
+ (void) &plus_infty;
+ (void) &minus_infty;
+
+ /* Clear all exceptions. From now on we must not get random exceptions. */
+ feclearexcept (FE_ALL_EXCEPT);
+}
+
+#if 0 /* XXX scp XXX */
+/* Definitions of arguments for argp functions. */
+static const struct argp_option options[] =
+{
+ { "verbose", 'v', "NUMBER", 0, "Level of verbosity (0..3)"},
+ { "ulps-file", 'u', NULL, 0, "Output ulps to file ULPs"},
+ { "no-max-error", 'f', NULL, 0,
+ "Don't output maximal errors of functions"},
+ { "no-points", 'p', NULL, 0,
+ "Don't output results of functions invocations"},
+ { "ignore-max-ulp", 'i', "yes/no", 0,
+ "Ignore given maximal errors"},
+ { NULL, 0, NULL, 0, NULL }
+};
+
+/* Short description of program. */
+static const char doc[] = "Math test suite: " TEST_MSG ;
+
+/* Prototype for option handler. */
+static error_t parse_opt (int key, char *arg, struct argp_state *state);
+
+/* Data structure to communicate with argp functions. */
+static struct argp argp =
+{
+ options, parse_opt, NULL, doc,
+};
+
+
+/* Handle program arguments. */
+static error_t
+parse_opt (int key, char *arg, struct argp_state *state)
+{
+ switch (key)
+ {
+ case 'f':
+ output_max_error = 0;
+ break;
+ case 'i':
+ if (strcmp (arg, "yes") == 0)
+ ignore_max_ulp = 1;
+ else if (strcmp (arg, "no") == 0)
+ ignore_max_ulp = 0;
+ break;
+ case 'p':
+ output_points = 0;
+ break;
+ case 'u':
+ output_ulps = 1;
+ break;
+ case 'v':
+ if (optarg)
+ verbose = (unsigned int) strtoul (optarg, NULL, 0);
+ else
+ verbose = 3;
+ break;
+ default:
+ return ARGP_ERR_UNKNOWN;
+ }
+ return 0;
+}
+#endif
+
+#if 0
+/* function to check our ulp calculation. */
+void
+check_ulp (void)
+{
+ int i;
+
+ FLOAT u, diff, ulp;
+ /* This gives one ulp. */
+ u = FUNC(nextafter) (10, 20);
+ check_equal (10.0, u, 1, &diff, &ulp);
+ printf ("One ulp: % .4" PRINTF_NEXPR "\n", ulp);
+
+ /* This gives one more ulp. */
+ u = FUNC(nextafter) (u, 20);
+ check_equal (10.0, u, 2, &diff, &ulp);
+ printf ("two ulp: % .4" PRINTF_NEXPR "\n", ulp);
+
+ /* And now calculate 100 ulp. */
+ for (i = 2; i < 100; i++)
+ u = FUNC(nextafter) (u, 20);
+ check_equal (10.0, u, 100, &diff, &ulp);
+ printf ("100 ulp: % .4" PRINTF_NEXPR "\n", ulp);
+}
+#endif
+
+int
+main (int argc, char **argv)
+{
+#if 0 /* XXX scp XXX */
+ int remaining;
+#endif
+
+ verbose = 1;
+ output_ulps = 0;
+ output_max_error = 1;
+ output_points = 1;
+ /* XXX set to 0 for releases. */
+ ignore_max_ulp = 0;
+
+#if 0 /* XXX scp XXX */
+ /* Parse and process arguments. */
+ argp_parse (&argp, argc, argv, 0, &remaining, NULL);
+
+ if (remaining != argc)
+ {
+ fprintf (stderr, "wrong number of arguments");
+ argp_help (&argp, stdout, ARGP_HELP_SEE, program_invocation_short_name);
+ exit (EXIT_FAILURE);
+ }
+#endif
+
+ if (output_ulps)
+ {
+ ulps_file = fopen ("ULPs", "a");
+ if (ulps_file == NULL)
+ {
+ perror ("can't open file `ULPs' for writing: ");
+ exit (1);
+ }
+ }
+
+
+ initialize ();
+ printf (TEST_MSG);
+
+#if 0
+ check_ulp ();
+#endif
+
+ /* Keep the tests a wee bit ordered (according to ISO C99). */
+ /* Classification macros: */
+ fpclassify_test ();
+ isfinite_test ();
+ isnormal_test ();
+ signbit_test ();
+
+ /* Trigonometric functions: */
+ acos_test ();
+ asin_test ();
+ atan_test ();
+ atan2_test ();
+ cos_test ();
+ sin_test ();
+ sincos_test ();
+ tan_test ();
+
+ /* Hyperbolic functions: */
+ acosh_test ();
+ asinh_test ();
+ atanh_test ();
+ cosh_test ();
+ sinh_test ();
+ tanh_test ();
+
+ /* Exponential and logarithmic functions: */
+ exp_test ();
+#if 0 /* XXX scp XXX */
+ exp10_test ();
+#endif
+ exp2_test ();
+ expm1_test ();
+ frexp_test ();
+ ldexp_test ();
+ log_test ();
+ log10_test ();
+ log1p_test ();
+ log2_test ();
+ logb_test ();
+ modf_test ();
+ ilogb_test ();
+ scalbn_test ();
+ scalbln_test ();
+
+ /* Power and absolute value functions: */
+ cbrt_test ();
+ fabs_test ();
+ hypot_test ();
+ pow_test ();
+ sqrt_test ();
+
+ /* Error and gamma functions: */
+ erf_test ();
+ erfc_test ();
+ gamma_test ();
+ lgamma_test ();
+ tgamma_test ();
+
+ /* Nearest integer functions: */
+ ceil_test ();
+ floor_test ();
+ nearbyint_test ();
+ rint_test ();
+ lrint_test ();
+ llrint_test ();
+ round_test ();
+ lround_test ();
+ llround_test ();
+ trunc_test ();
+
+ /* Remainder functions: */
+ fmod_test ();
+ remainder_test ();
+ remquo_test ();
+
+ /* Manipulation functions: */
+ copysign_test ();
+ nextafter_test ();
+#if 0 /* XXX scp XXX */
+ nexttoward_test ();
+#endif
+
+ /* maximum, minimum and positive difference functions */
+ fdim_test ();
+ fmax_test ();
+ fmin_test ();
+
+ /* Multiply and add: */
+ fma_test ();
+
+#if 0 /* XXX scp XXX */
+ /* Complex functions: */
+ cabs_test ();
+ cacos_test ();
+ cacosh_test ();
+ carg_test ();
+ casin_test ();
+ casinh_test ();
+ catan_test ();
+ catanh_test ();
+ ccos_test ();
+ ccosh_test ();
+ cexp_test ();
+ cimag_test ();
+ clog10_test ();
+ clog_test ();
+ conj_test ();
+ cpow_test ();
+ cproj_test ();
+ creal_test ();
+ csin_test ();
+ csinh_test ();
+ csqrt_test ();
+ ctan_test ();
+ ctanh_test ();
+#endif
+
+ /* Bessel functions: */
+ j0_test ();
+ j1_test ();
+ jn_test ();
+ y0_test ();
+ y1_test ();
+ yn_test ();
+
+ if (output_ulps)
+ fclose (ulps_file);
+
+ printf ("\nTest suite completed:\n");
+ printf (" %d test cases plus %d tests for exception flags executed.\n",
+ noTests, noExcTests);
+ if (noXFails)
+ printf (" %d expected failures occurred.\n", noXFails);
+ if (noXPasses)
+ printf (" %d unexpected passes occurred.\n", noXPasses);
+ if (noErrors)
+ {
+ printf (" %d errors occurred.\n", noErrors);
+ return 1;
+ }
+ printf (" All tests passed successfully.\n");
+
+ return 0;
+}
+
+/*
+ * Local Variables:
+ * mode:c
+ * End:
+ */
--- /dev/null
+/* Copyright (C) 1997, 1999 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Andreas Jaeger <aj@suse.de>, 1997.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#define FUNC(function) function
+#define FLOAT double
+#define TEST_MSG "testing double (without inline functions)\n"
+#define MATHCONST(x) x
+#define CHOOSE(Clongdouble,Cdouble,Cfloat,Cinlinelongdouble,Cinlinedouble,Cinlinefloat) Cdouble
+#define PRINTF_EXPR "e"
+#define PRINTF_XEXPR "a"
+#define PRINTF_NEXPR "f"
+#define TEST_DOUBLE 1
+
+#ifndef __NO_MATH_INLINES
+# define __NO_MATH_INLINES
+#endif
+
+#include "libm-test.c"
--- /dev/null
+/* Copyright (C) 1997, 1999 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Andreas Jaeger <aj@suse.de>, 1997.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#define FUNC(function) function ## f
+#define FLOAT float
+#define TEST_MSG "testing float (without inline functions)\n"
+#define MATHCONST(x) x
+#define CHOOSE(Clongdouble,Cdouble,Cfloat,Cinlinelongdouble,Cinlinedouble,Cinlinefloat) Cfloat
+#define PRINTF_EXPR "e"
+#define PRINTF_XEXPR "a"
+#define PRINTF_NEXPR "f"
+#define TEST_FLOAT 1
+
+#ifndef __NO_MATH_INLINES
+# define __NO_MATH_INLINES
+#endif
+
+#include "libm-test.c"