浏览代码

sync to msun

Viral B. Shah 9 年之前
父节点
当前提交
2c35ee6e7b
共有 100 个文件被更改,包括 5389 次插入1604 次删除
  1. 0 4
      Make.inc
  2. 3 1
      arm/Make.files
  3. 35 0
      arm/fenv-softfp.c
  4. 36 0
      arm/fenv-vfp.c
  5. 295 14
      arm/fenv.c
  6. 185 0
      include/openlibm_acle_compat_arm.h
  7. 30 3
      include/openlibm_compat.h
  8. 4 2
      include/openlibm_fenv_amd64.h
  9. 85 41
      include/openlibm_fenv_arm.h
  10. 54 0
      include/openlibm_fenv_mangle_arm.h
  11. 184 0
      include/openlibm_fenv_softfloat.h
  12. 115 94
      include/openlibm_math.h
  13. 2 3
      ld80/Make.files
  14. 322 389
      ld80/e_lgammal_r.c
  15. 3 3
      ld80/invtrig.c
  16. 3 3
      ld80/k_cosl.c
  17. 3 3
      ld80/k_sinl.c
  18. 4 5
      ld80/k_tanl.c
  19. 291 384
      ld80/s_erfl.c
  20. 40 47
      ld80/s_exp2l.c
  21. 284 0
      ld80/s_expl.c
  22. 717 0
      ld80/s_logl.c
  23. 5 4
      ld80/s_nanl.c
  24. 2 2
      src/Make.files
  25. 67 0
      src/arm_fpmath.h
  26. 639 0
      src/catrig.c
  27. 393 0
      src/catrigf.c
  28. 46 0
      src/digittoint.c
  29. 4 4
      src/e_acos.c
  30. 4 5
      src/e_acosf.c
  31. 9 4
      src/e_acosh.c
  32. 4 5
      src/e_acoshf.c
  33. 89 0
      src/e_acoshl.c
  34. 4 4
      src/e_acosl.c
  35. 4 4
      src/e_asin.c
  36. 4 5
      src/e_asinf.c
  37. 4 4
      src/e_asinl.c
  38. 5 5
      src/e_atan2.c
  39. 4 5
      src/e_atan2f.c
  40. 4 4
      src/e_atan2l.c
  41. 9 4
      src/e_atanh.c
  42. 4 5
      src/e_atanhf.c
  43. 74 0
      src/e_atanhl.c
  44. 9 4
      src/e_cosh.c
  45. 4 5
      src/e_coshf.c
  46. 130 0
      src/e_coshl.c
  47. 9 12
      src/e_exp.c
  48. 7 6
      src/e_expf.c
  49. 4 5
      src/e_fmod.c
  50. 4 5
      src/e_fmodf.c
  51. 8 9
      src/e_fmodl.c
  52. 33 0
      src/e_gamma.c
  53. 32 0
      src/e_gamma_r.c
  54. 34 0
      src/e_gammaf.c
  55. 33 0
      src/e_gammaf_r.c
  56. 4 4
      src/e_hypot.c
  57. 4 5
      src/e_hypotf.c
  58. 6 6
      src/e_hypotl.c
  59. 25 22
      src/e_j0.c
  60. 19 12
      src/e_j0f.c
  61. 24 21
      src/e_j1.c
  62. 20 12
      src/e_j1f.c
  63. 12 9
      src/e_jn.c
  64. 12 8
      src/e_jnf.c
  65. 11 8
      src/e_lgamma.c
  66. 81 76
      src/e_lgamma_r.c
  67. 6 9
      src/e_lgammaf.c
  68. 127 143
      src/e_lgammaf_r.c
  69. 18 8
      src/e_lgammal.c
  70. 11 5
      src/e_log.c
  71. 11 5
      src/e_log10.c
  72. 6 9
      src/e_log10f.c
  73. 11 5
      src/e_log2.c
  74. 6 9
      src/e_log2f.c
  75. 6 6
      src/e_logf.c
  76. 11 17
      src/e_pow.c
  77. 7 13
      src/e_powf.c
  78. 7 4
      src/e_rem_pio2.c
  79. 8 5
      src/e_rem_pio2f.c
  80. 4 4
      src/e_remainder.c
  81. 4 5
      src/e_remainderf.c
  82. 4 5
      src/e_remainderl.c
  83. 47 0
      src/e_scalb.c
  84. 43 0
      src/e_scalbf.c
  85. 9 4
      src/e_sinh.c
  86. 4 5
      src/e_sinhf.c
  87. 131 0
      src/e_sinhl.c
  88. 4 4
      src/e_sqrt.c
  89. 5 2
      src/e_sqrtf.c
  90. 5 8
      src/e_sqrtl.c
  91. 184 0
      src/fenv-softfloat.h
  92. 13 1
      src/fpmath.h
  93. 63 0
      src/imprecise.c
  94. 4 5
      src/k_cos.c
  95. 6 8
      src/k_cosf.c
  96. 8 8
      src/k_exp.c
  97. 9 9
      src/k_expf.c
  98. 2 2
      src/k_log.h
  99. 2 2
      src/k_logf.h
  100. 5 5
      src/k_rem_pio2.c

+ 0 - 4
Make.inc

@@ -91,14 +91,10 @@ endif
 ifeq ($(ARCH),i686)
 override ARCH := i387
 endif
-
 ifeq ($(ARCH),x86_64)
 override ARCH := amd64
 endif
 
-# The optimization flag may be overriden with the environment variable CFLAGS.
-CFLAGS ?= -O2
-
 ifneq (,$(findstring MINGW,$(OS)))
 override OS=WINNT
 endif

+ 3 - 1
arm/Make.files

@@ -1 +1,3 @@
-$(CUR_SRCS) = fenv.c
+#$(CUR_SRCS) = fenv-softfp.c
+$(CUR_SRCS) = fenv-vfp.c
+

+ 35 - 0
arm/fenv-softfp.c

@@ -0,0 +1,35 @@
+/*-
+ * Copyright (c) 2013 Andrew Turner <andrew@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_MANGLE(x)	__softfp_ ##x
+#include <openlibm_fenv_mangle_arm.h>
+#ifndef DLLEXORT
+#define DLLEXPORT __attribute__ ((visibility("default")))
+#endif
+#include "fenv.c"
+

+ 36 - 0
arm/fenv-vfp.c

@@ -0,0 +1,36 @@
+/*-
+ * Copyright (c) 2013 Andrew Turner <andrew@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_MANGLE(x)	__vfp_ ##x
+#include <openlibm_fenv_mangle_arm.h>
+#define	__ARM_PCS_VFP
+#ifndef DLLEXORT
+#define DLLEXPORT __attribute__ ((visibility("default")))
+#endif
+#include "fenv.c"
+

+ 295 - 14
arm/fenv.c

@@ -1,5 +1,6 @@
 /*-
  * Copyright (c) 2004 David Schultz <das@FreeBSD.ORG>
+ * Copyright (c) 2013 Andrew Turner <andrew@FreeBSD.ORG>
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -23,30 +24,310 @@
  * 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 $
+ * $FreeBSD$
  */
 
+//VBS
 #define	__fenv_static
+
 #include <openlibm_fenv.h>
 
-#ifdef __GNUC_GNU_INLINE__
-#error "This file must be compiled with C99 'inline' semantics"
+#include <openlibm_acle_compat_arm.h>
+
+#if __ARM_ARCH >= 6
+#define FENV_ARMv6
 #endif
 
+/* When SOFTFP_ABI is defined we are using the softfp ABI. */
+#if defined(__VFP_FP__) && !defined(__ARM_PCS_VFP)
+#define SOFTFP_ABI
+#endif
+
+
+#ifndef FENV_MANGLE
 /*
  * 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;
+#endif
+
+
+/* If this is a non-mangled softfp version special processing is required */
+#if defined(FENV_MANGLE) || !defined(SOFTFP_ABI) || !defined(FENV_ARMv6)
+
+/*
+ * The following macros map between the softfloat emulator's flags and
+ * the hardware's FPSR.  The hardware this file was written for doesn't
+ * have rounding control bits, so we stick those in the system ID byte.
+ */
+#ifndef __ARM_PCS_VFP
+#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 <openlibm_fenv_softfloat.h>
+#endif
+
+#ifdef __GNUC_GNU_INLINE__
+#error "This file must be compiled with C99 'inline' semantics"
+#endif
+
+extern inline DLLEXPORT int feclearexcept(int __excepts);
+extern inline DLLEXPORT int fegetexceptflag(fexcept_t *__flagp, int __excepts);
+extern inline DLLEXPORT int fesetexceptflag(const fexcept_t *__flagp, int __excepts);
+extern inline DLLEXPORT int feraiseexcept(int __excepts);
+extern inline DLLEXPORT int fetestexcept(int __excepts);
+extern inline DLLEXPORT int fegetround(void);
+extern inline DLLEXPORT int fesetround(int __round);
+extern inline DLLEXPORT int fegetenv(fenv_t *__envp);
+extern inline DLLEXPORT int feholdexcept(fenv_t *__envp);
+extern inline DLLEXPORT int fesetenv(const fenv_t *__envp);
+extern inline DLLEXPORT int feupdateenv(const fenv_t *__envp);
+extern inline DLLEXPORT int feenableexcept(int __mask);
+extern inline DLLEXPORT int fedisableexcept(int __mask);
+extern inline DLLEXPORT int fegetexcept(void);
+
+#else /* !FENV_MANGLE && SOFTFP_ABI */
+/* Set by libc when the VFP unit is enabled */
+extern int _libc_arm_fpu_present;
+
+int __softfp_feclearexcept(int __excepts);
+int __softfp_fegetexceptflag(fexcept_t *__flagp, int __excepts);
+int __softfp_fesetexceptflag(const fexcept_t *__flagp, int __excepts);
+int __softfp_feraiseexcept(int __excepts);
+int __softfp_fetestexcept(int __excepts);
+int __softfp_fegetround(void);
+int __softfp_fesetround(int __round);
+int __softfp_fegetenv(fenv_t *__envp);
+int __softfp_feholdexcept(fenv_t *__envp);
+int __softfp_fesetenv(const fenv_t *__envp);
+int __softfp_feupdateenv(const fenv_t *__envp);
+int __softfp_feenableexcept(int __mask);
+int __softfp_fedisableexcept(int __mask);
+int __softfp_fegetexcept(void);
+
+int __vfp_feclearexcept(int __excepts);
+int __vfp_fegetexceptflag(fexcept_t *__flagp, int __excepts);
+int __vfp_fesetexceptflag(const fexcept_t *__flagp, int __excepts);
+int __vfp_feraiseexcept(int __excepts);
+int __vfp_fetestexcept(int __excepts);
+int __vfp_fegetround(void);
+int __vfp_fesetround(int __round);
+int __vfp_fegetenv(fenv_t *__envp);
+int __vfp_feholdexcept(fenv_t *__envp);
+int __vfp_fesetenv(const fenv_t *__envp);
+int __vfp_feupdateenv(const fenv_t *__envp);
+int __vfp_feenableexcept(int __mask);
+int __vfp_fedisableexcept(int __mask);
+int __vfp_fegetexcept(void);
+
+static int
+__softfp_round_to_vfp(int round)
+{
+
+	switch (round) {
+	case FE_TONEAREST:
+	default:
+		return VFP_FE_TONEAREST;
+	case FE_TOWARDZERO:
+		return VFP_FE_TOWARDZERO;
+	case FE_UPWARD:
+		return VFP_FE_UPWARD;
+	case FE_DOWNWARD:
+		return VFP_FE_DOWNWARD;
+	}
+}
+
+static int
+__softfp_round_from_vfp(int round)
+{
+
+	switch (round) {
+	case VFP_FE_TONEAREST:
+	default:
+		return FE_TONEAREST;
+	case VFP_FE_TOWARDZERO:
+		return FE_TOWARDZERO;
+	case VFP_FE_UPWARD:
+		return FE_UPWARD;
+	case VFP_FE_DOWNWARD:
+		return FE_DOWNWARD;
+	}
+}
+
+DLLEXPORT 
+int feclearexcept(int __excepts)
+{
+
+	if (_libc_arm_fpu_present)
+		__vfp_feclearexcept(__excepts);
+	__softfp_feclearexcept(__excepts);
+
+	return (0);
+}
+
+DLLEXPORT 
+int fegetexceptflag(fexcept_t *__flagp, int __excepts)
+{
+	fexcept_t __vfp_flagp;
+
+	__vfp_flagp = 0;
+	if (_libc_arm_fpu_present)
+		__vfp_fegetexceptflag(&__vfp_flagp, __excepts);
+	__softfp_fegetexceptflag(__flagp, __excepts);
+
+	*__flagp |= __vfp_flagp;
+
+	return (0);
+}
+
+DLLEXPORT 
+int fesetexceptflag(const fexcept_t *__flagp, int __excepts)
+{
+
+	if (_libc_arm_fpu_present)
+		__vfp_fesetexceptflag(__flagp, __excepts);
+	__softfp_fesetexceptflag(__flagp, __excepts);
+
+	return (0);
+}
+
+DLLEXPORT 
+int feraiseexcept(int __excepts)
+{
+
+	if (_libc_arm_fpu_present)
+		__vfp_feraiseexcept(__excepts);
+	__softfp_feraiseexcept(__excepts);
+
+	return (0);
+}
+
+DLLEXPORT 
+int fetestexcept(int __excepts)
+{
+	int __got_excepts;
+
+	__got_excepts = 0;
+	if (_libc_arm_fpu_present)
+		__got_excepts = __vfp_fetestexcept(__excepts);
+	__got_excepts |= __softfp_fetestexcept(__excepts);
+
+	return (__got_excepts);
+}
+
+DLLEXPORT 
+int fegetround(void)
+{
+
+	if (_libc_arm_fpu_present)
+		return __softfp_round_from_vfp(__vfp_fegetround());
+	return __softfp_fegetround();
+}
+
+DLLEXPORT 
+int fesetround(int __round)
+{
+
+	if (_libc_arm_fpu_present)
+		__vfp_fesetround(__softfp_round_to_vfp(__round));
+	__softfp_fesetround(__round);
+
+	return (0);
+}
+
+DLLEXPORT 
+int fegetenv(fenv_t *__envp)
+{
+	fenv_t __vfp_envp;
+
+	__vfp_envp = 0;
+	if (_libc_arm_fpu_present)
+		__vfp_fegetenv(&__vfp_envp);
+	__softfp_fegetenv(__envp);
+	*__envp |= __vfp_envp;
+
+	return (0);
+}
+
+DLLEXPORT 
+int feholdexcept(fenv_t *__envp)
+{
+	fenv_t __vfp_envp;
+
+	__vfp_envp = 0;
+	if (_libc_arm_fpu_present)
+		__vfp_feholdexcept(&__vfp_envp);
+	__softfp_feholdexcept(__envp);
+	*__envp |= __vfp_envp;
+
+	return (0);
+}
+
+DLLEXPORT 
+int fesetenv(const fenv_t *__envp)
+{
+
+	if (_libc_arm_fpu_present)
+		__vfp_fesetenv(__envp);
+	__softfp_fesetenv(__envp);
+
+	return (0);
+}
+
+DLLEXPORT 
+int feupdateenv(const fenv_t *__envp)
+{
+
+	if (_libc_arm_fpu_present)
+		__vfp_feupdateenv(__envp);
+	__softfp_feupdateenv(__envp);
+
+	return (0);
+}
+
+DLLEXPORT 
+int feenableexcept(int __mask)
+{
+	int __unmasked;
+
+	__unmasked = 0;
+	if (_libc_arm_fpu_present)
+		__unmasked = __vfp_feenableexcept(__mask);
+	__unmasked |= __softfp_feenableexcept(__mask);
+
+	return (__unmasked);
+}
+
+DLLEXPORT 
+int fedisableexcept(int __mask)
+{
+	int __unmasked;
+
+	__unmasked = 0;
+	if (_libc_arm_fpu_present)
+		__unmasked = __vfp_fedisableexcept(__mask);
+	__unmasked |= __softfp_fedisableexcept(__mask);
+
+	return (__unmasked);
+}
+
+DLLEXPORT 
+int fegetexcept(void)
+{
+	int __unmasked;
+
+	__unmasked = 0;
+	if (_libc_arm_fpu_present)
+		__unmasked = __vfp_fegetexcept();
+	__unmasked |= __softfp_fegetexcept();
+
+	return (__unmasked);
+}
+
+#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);

+ 185 - 0
include/openlibm_acle_compat_arm.h

@@ -0,0 +1,185 @@
+/*
+ * Copyright (c) 2014 ARM Ltd
+ * 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. The name of the company may not be used to endorse or promote
+ *    products derived from this software without specific prior written
+ *    permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY ARM LTD ``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 ARM LTD 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/sys/arm/include/acle-compat.h 269956 2014-08-14 04:20:13Z imp $
+ */
+
+#ifndef __ARM_ARCH
+
+/* ACLE standardises a set of pre-defines that describe the ARM architecture.
+   These were mostly implemented in GCC around GCC-4.8; older versions
+   have no, or only partial support.  To provide a level of backwards
+   compatibility we try to work out what the definitions should be, given
+   the older pre-defines that GCC did produce.  This isn't complete, but
+   it should be enough for use by routines that depend on this header.  */
+
+/* No need to handle ARMv8, GCC had ACLE support before that.  */
+
+#define __ARM_ACLE 101
+
+# ifdef __ARM_ARCH_7__
+/* The common subset of ARMv7 in all profiles.  */
+#  define __ARM_ARCH 7
+#  define __ARM_ARCH_ISA_THUMB 2
+#  define __ARM_FEATURE_CLZ
+#  define __ARM_FEATURE_LDREX 7
+#  define __ARM_FEATURE_UNALIGNED
+# endif
+
+# if defined (__ARM_ARCH_7A__) || defined (__ARM_ARCH_7R__)
+#  define __ARM_ARCH 7
+#  define __ARM_ARCH_ISA_THUMB 2
+#  define __ARM_ARCH_ISA_ARM
+#  define __ARM_FEATURE_CLZ
+#  define __ARM_FEATURE_SIMD32
+#  define __ARM_FEATURE_DSP
+#  define __ARM_FEATURE_QBIT
+#  define __ARM_FEATURE_SAT
+#  define __ARM_FEATURE_LDREX 15
+#  define __ARM_FEATURE_UNALIGNED
+#  ifdef __ARM_ARCH_7A__
+#   define __ARM_ARCH_PROFILE 'A'
+#  else
+#   define __ARM_ARCH_PROFILE 'R'
+#  endif
+# endif
+
+# ifdef __ARM_ARCH_7EM__
+#  define __ARM_ARCH 7
+#  define __ARM_ARCH_ISA_THUMB 2
+#  define __ARM_FEATURE_CLZ
+#  define __ARM_FEATURE_SIMD32
+#  define __ARM_FEATURE_DSP
+#  define __ARM_FEATURE_QBIT
+#  define __ARM_FEATURE_SAT
+#  define __ARM_FEATURE_LDREX 7
+#  define __ARM_FEATURE_UNALIGNED
+#  define __ARM_ARCH_PROFILE 'M'
+# endif
+
+# ifdef __ARM_ARCH_7M__
+#  define __ARM_ARCH 7
+#  define __ARM_ARCH_ISA_THUMB 2
+#  define __ARM_FEATURE_CLZ
+#  define __ARM_FEATURE_QBIT
+#  define __ARM_FEATURE_SAT
+#  define __ARM_FEATURE_LDREX 7
+#  define __ARM_FEATURE_UNALIGNED
+#  define __ARM_ARCH_PROFILE 'M'
+# endif
+
+# ifdef __ARM_ARCH_6T2__
+#  define __ARM_ARCH 6
+#  define __ARM_ARCH_ISA_THUMB 2
+#  define __ARM_ARCH_ISA_ARM
+#  define __ARM_FEATURE_CLZ
+#  define __ARM_FEATURE_SIMD32
+#  define __ARM_FEATURE_DSP
+#  define __ARM_FEATURE_QBIT
+#  define __ARM_FEATURE_SAT
+#  define __ARM_FEATURE_LDREX 4
+#  define __ARM_FEATURE_UNALIGNED
+# endif
+
+# ifdef __ARM_ARCH_6M__
+#  define __ARM_ARCH 6
+#  define __ARM_ARCH_ISA_THUMB 1
+#  define __ARM_ARCH_PROFILE 'M'
+# endif
+
+# if defined (__ARM_ARCH_6__) || defined (__ARM_ARCH_6J__) \
+  || defined (__ARM_ARCH_6K__) || defined (__ARM_ARCH_6Z__) \
+  || defined (__ARM_ARCH_6ZK__)
+#  define __ARM_ARCH 6
+#  define __ARM_ARCH_ISA_THUMB 1
+#  define __ARM_ARCH_ISA_ARM
+#  define __ARM_FEATURE_CLZ
+#  define __ARM_FEATURE_SIMD32
+#  define __ARM_FEATURE_DSP
+#  define __ARM_FEATURE_QBIT
+#  define __ARM_FEATURE_SAT
+#  define __ARM_FEATURE_UNALIGNED
+#  ifndef __thumb__
+#   if defined (__ARM_ARCH_6K__) || defined (__ARM_ARCH_6ZK__)
+#    define __ARM_FEATURE_LDREX 15
+#   else
+#    define __ARM_FEATURE_LDREX 4
+#   endif
+#  endif
+# endif
+
+# if defined (__ARM_ARCH_5TE__) || defined (__ARM_ARCH_5E__)
+#  define __ARM_ARCH 5
+#  define __ARM_ARCH_ISA_ARM
+#  ifdef __ARM_ARCH_5TE__
+#   define __ARM_ARCH_ISA_THUMB 1
+#  endif
+#  define __ARM_FEATURE_CLZ
+#  define __ARM_FEATURE_DSP
+# endif
+
+# if defined (__ARM_ARCH_5T__) || defined (__ARM_ARCH_5__)
+#  define __ARM_ARCH 5
+#  define __ARM_ARCH_ISA_ARM
+#  ifdef __ARM_ARCH_5TE__
+#   define __ARM_ARCH_ISA_THUMB 1
+#  endif
+#  define __ARM_FEATURE_CLZ
+# endif
+
+# ifdef __ARM_ARCH_4T__
+#  define __ARM_ARCH 4
+#  define __ARM_ARCH_ISA_ARM
+#  define __ARM_ARCH_ISA_THUMB 1
+# endif
+
+# ifdef __ARM_ARCH_4__
+#  define __ARM_ARCH 4
+#  define __ARM_ARCH_ISA_ARM
+# endif
+
+# if defined (__ARM_ARCH_3__) || defined (__ARM_ARCH_3M__)
+#  define __ARM_ARCH 3
+#  define __ARM_ARCH_ISA_ARM
+# endif
+
+# ifdef __ARM_ARCH_2__
+#  define __ARM_ARCH 2
+#  define __ARM_ARCH_ISA_ARM
+# endif
+
+# ifdef __ARMEB__
+#  define __ARM_BIG_ENDIAN
+# endif
+
+/* If we still don't know what the target architecture is, then we're
+   probably not using GCC.  */
+# ifndef __ARM_ARCH
+#  error Unable to determine architecture version.
+# endif
+
+#endif /* __ARM_ARCH  */

+ 30 - 3
src/cdefs-compat.h → include/openlibm_compat.h

@@ -1,5 +1,9 @@
-#ifndef _CDEFS_COMPAT_H_
-#define	_CDEFS_COMPAT_H_
+#ifndef _OPENLIBM_COMPAT_H_
+#define	_OPENLIBM_COMPAT_H_
+
+#define DLLEXPORT
+
+#define __FBSDID(s)
 
 #ifdef __MINIOS__
 /* No stdio.h on Mini-OS. */
@@ -80,4 +84,27 @@
 #endif	/* __GNUC__ */
 
 
-#endif /* _CDEFS_COMPAT_H_ */
+#include <stdint.h>
+#include <limits.h>
+#include <stdint.h>
+
+#ifdef __GLIBC__
+/* Not sure what to do about __pure2 on linux */
+#define __pure2
+#endif
+
+#ifdef _WIN32
+/* Not sure what to do about __pure2 on windows */
+#define __pure2
+#endif
+
+typedef uint8_t               u_int8_t;
+typedef uint16_t              u_int16_t;
+typedef uint32_t              u_int32_t;
+typedef uint64_t              u_int64_t;
+
+typedef float float_t;
+
+#define __always_inline
+
+#endif

+ 4 - 2
include/openlibm_fenv_amd64.h

@@ -35,7 +35,9 @@
 #include "math_private.h"
 
 #ifndef	__fenv_static
-#define	__fenv_static	static
+//VBS
+//#define	__fenv_static	static
+#define	__fenv_static
 #endif
 
 typedef struct {
@@ -204,7 +206,7 @@ DLLEXPORT int feenableexcept(int __mask);
 DLLEXPORT int fedisableexcept(int __mask);
 
 /* We currently provide no external definition of fegetexcept(). */
-static inline DLLEXPORT int
+DLLEXPORT int
 fegetexcept(void)
 {
 	uint16_t __control;

+ 85 - 41
include/openlibm_fenv_arm.h

@@ -23,7 +23,7 @@
  * 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 $
+ * $FreeBSD$
  */
 
 #ifndef	_FENV_H_
@@ -44,14 +44,32 @@ typedef	uint32_t	fexcept_t;
 #define	FE_OVERFLOW	0x0004
 #define	FE_UNDERFLOW	0x0008
 #define	FE_INEXACT	0x0010
+#ifdef __ARM_PCS_VFP
+#define	FE_DENORMAL	0x0080
+#define	FE_ALL_EXCEPT	(FE_DIVBYZERO | FE_INEXACT | \
+			 FE_INVALID | FE_OVERFLOW | FE_UNDERFLOW | FE_DENORMAL)
+#else
 #define	FE_ALL_EXCEPT	(FE_DIVBYZERO | FE_INEXACT | \
 			 FE_INVALID | FE_OVERFLOW | FE_UNDERFLOW)
+#endif
 
 /* Rounding modes */
+#define	VFP_FE_TONEAREST	0x00000000
+#define	VFP_FE_UPWARD		0x00400000
+#define	VFP_FE_DOWNWARD		0x00800000
+#define	VFP_FE_TOWARDZERO	0x00c00000
+
+#ifdef __ARM_PCS_VFP
+#define	FE_TONEAREST	VFP_FE_TONEAREST
+#define	FE_UPWARD	VFP_FE_UPWARD
+#define	FE_DOWNWARD	VFP_FE_DOWNWARD
+#define	FE_TOWARDZERO	VFP_FE_TOWARDZERO
+#else
 #define	FE_TONEAREST	0x0000
 #define	FE_TOWARDZERO	0x0001
 #define	FE_UPWARD	0x0002
 #define	FE_DOWNWARD	0x0003
+#endif
 #define	_ROUND_MASK	(FE_TONEAREST | FE_DOWNWARD | \
 			 FE_UPWARD | FE_TOWARDZERO)
 __BEGIN_DECLS
@@ -61,25 +79,45 @@ 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
+#ifndef __ARM_PCS_VFP
+#define	_FPUSW_SHIFT	16
 #define	_ENABLE_MASK	(FE_ALL_EXCEPT << _FPUSW_SHIFT)
+#endif
 
-#ifdef	ARM_HARD_FLOAT
-#define	__rfs(__fpsr)	__asm __volatile("rfs %0" : "=r" (*(__fpsr)))
-#define	__wfs(__fpsr)	__asm __volatile("wfs %0" : : "r" (__fpsr))
-#else
-#define __rfs(__fpsr)
-#define __wfs(__fpsr)
+#ifndef __ARM_PCS_VFP
+
+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);
+#if __BSD_VISIBLE
+int feenableexcept(int __mask);
+int fedisableexcept(int __mask);
+int fegetexcept(void);
 #endif
 
+#else	/* __ARM_PCS_VFP */
+
+#define	vmrs_fpscr(__r)	__asm __volatile("vmrs %0, fpscr" : "=&r"(__r))
+#define	vmsr_fpscr(__r)	__asm __volatile("vmsr fpscr, %0" : : "r"(__r))
+
+#define _FPU_MASK_SHIFT	8
+
 __fenv_static inline int
 feclearexcept(int __excepts)
 {
 	fexcept_t __fpsr;
 
-	__rfs(&__fpsr);
+	vmrs_fpscr(__fpsr);
 	__fpsr &= ~__excepts;
-	__wfs(__fpsr);
+	vmsr_fpscr(__fpsr);
 	return (0);
 }
 
@@ -88,7 +126,7 @@ fegetexceptflag(fexcept_t *__flagp, int __excepts)
 {
 	fexcept_t __fpsr;
 
-	__rfs(&__fpsr);
+	vmrs_fpscr(__fpsr);
 	*__flagp = __fpsr & __excepts;
 	return (0);
 }
@@ -98,10 +136,10 @@ fesetexceptflag(const fexcept_t *__flagp, int __excepts)
 {
 	fexcept_t __fpsr;
 
-	__rfs(&__fpsr);
+	vmrs_fpscr(__fpsr);
 	__fpsr &= ~__excepts;
 	__fpsr |= *__flagp & __excepts;
-	__wfs(__fpsr);
+	vmsr_fpscr(__fpsr);
 	return (0);
 }
 
@@ -119,34 +157,36 @@ fetestexcept(int __excepts)
 {
 	fexcept_t __fpsr;
 
-	__rfs(&__fpsr);
+	vmrs_fpscr(__fpsr);
 	return (__fpsr & __excepts);
 }
 
 __fenv_static inline int
 fegetround(void)
 {
+	fenv_t __fpsr;
 
-	/*
-	 * 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);
+	vmrs_fpscr(__fpsr);
+	return (__fpsr & _ROUND_MASK);
 }
 
 __fenv_static inline int
 fesetround(int __round)
 {
+	fenv_t __fpsr;
 
-	return (-1);
+	vmrs_fpscr(__fpsr);
+	__fpsr &= ~(_ROUND_MASK);
+	__fpsr |= __round;
+	vmsr_fpscr(__fpsr);
+	return (0);
 }
 
 __fenv_static inline int
 fegetenv(fenv_t *__envp)
 {
 
-	__rfs(__envp);
+	vmrs_fpscr(*__envp);
 	return (0);
 }
 
@@ -155,10 +195,10 @@ feholdexcept(fenv_t *__envp)
 {
 	fenv_t __env;
 
-	__rfs(&__env);
+	vmrs_fpscr(__env);
 	*__envp = __env;
-	__env &= ~(FE_ALL_EXCEPT | _ENABLE_MASK);
-	__wfs(__env);
+	__env &= ~(FE_ALL_EXCEPT);
+	vmsr_fpscr(__env);
 	return (0);
 }
 
@@ -166,7 +206,7 @@ __fenv_static inline int
 fesetenv(const fenv_t *__envp)
 {
 
-	__wfs(*__envp);
+	vmsr_fpscr(*__envp);
 	return (0);
 }
 
@@ -175,8 +215,8 @@ feupdateenv(const fenv_t *__envp)
 {
 	fexcept_t __fpsr;
 
-	__rfs(&__fpsr);
-	__wfs(*__envp);
+	vmrs_fpscr(__fpsr);
+	vmsr_fpscr(*__envp);
 	feraiseexcept(__fpsr & FE_ALL_EXCEPT);
 	return (0);
 }
@@ -185,39 +225,43 @@ feupdateenv(const fenv_t *__envp)
 
 /* We currently provide no external definitions of the functions below. */
 
-static inline int
+__fenv_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);
+	vmrs_fpscr(__old_fpsr);
+	__new_fpsr = __old_fpsr |
+	    ((__mask & FE_ALL_EXCEPT) << _FPU_MASK_SHIFT);
+	vmsr_fpscr(__new_fpsr);
+	return ((__old_fpsr >> _FPU_MASK_SHIFT) & FE_ALL_EXCEPT);
 }
 
-static inline int
+__fenv_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);
+	vmrs_fpscr(__old_fpsr);
+	__new_fpsr = __old_fpsr &
+	    ~((__mask & FE_ALL_EXCEPT) << _FPU_MASK_SHIFT);
+	vmsr_fpscr(__new_fpsr);
+	return ((__old_fpsr >> _FPU_MASK_SHIFT) & FE_ALL_EXCEPT);
 }
 
-static inline int
+__fenv_static inline int
 fegetexcept(void)
 {
 	fenv_t __fpsr;
 
-	__rfs(&__fpsr);
-	return ((__fpsr & _ENABLE_MASK) >> _FPUSW_SHIFT);
+	vmrs_fpscr(__fpsr);
+	return (__fpsr & FE_ALL_EXCEPT);
 }
 
 #endif /* __BSD_VISIBLE */
 
+#endif	/* __ARM_PCS_VFP */
+
 __END_DECLS
 
 #endif	/* !_FENV_H_ */

+ 54 - 0
include/openlibm_fenv_mangle_arm.h

@@ -0,0 +1,54 @@
+/*-
+ * Copyright (c) 2013 Andrew Turner <andrew@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$
+ */
+
+#ifdef _FENV_MANGLE_H_
+#error Only include fenv-mangle.h once
+#endif
+
+#define	_FENV_MANGLE_H_
+
+#ifndef FENV_MANGLE
+#error FENV_MANGLE is undefined
+#endif
+
+/*
+#define	feclearexcept	FENV_MANGLE(feclearexcept)
+#define	fegetexceptflag	FENV_MANGLE(fegetexceptflag)
+#define	fesetexceptflag	FENV_MANGLE(fesetexceptflag)
+#define	feraiseexcept	FENV_MANGLE(feraiseexcept)
+#define	fetestexcept	FENV_MANGLE(fetestexcept)
+#define	fegetround	FENV_MANGLE(fegetround)
+#define	fesetround	FENV_MANGLE(fesetround)
+#define	fegetenv	FENV_MANGLE(fegetenv)
+#define	feholdexcept	FENV_MANGLE(feholdexcept)
+#define	fesetenv	FENV_MANGLE(fesetenv)
+#define	feupdateenv	FENV_MANGLE(feupdateenv)
+#define	feenableexcept	FENV_MANGLE(feenableexcept)
+#define	fedisableexcept	FENV_MANGLE(fedisableexcept)
+#define	fegetexcept	FENV_MANGLE(fegetexcept)
+*/

+ 184 - 0
include/openlibm_fenv_softfloat.h

@@ -0,0 +1,184 @@
+/*-
+ * 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 */

+ 115 - 94
include/openlibm_math.h

@@ -11,27 +11,15 @@
 
 /*
  * 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 $
+ * $FreeBSD$
  */
 
-#ifdef OPENLIBM_USE_HOST_MATH_H
-#include <math.h>
-#else /* !OPENLIBM_USE_HOST_MATH_H */
+#ifndef _MATH_H_
+#define	_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
+#include <sys/cdefs.h>
+#include <sys/_types.h>
+#include <machine/_limits.h>
 
 /*
  * ANSI/POSIX
@@ -47,6 +35,7 @@ extern const union __nan_un {
 } __nan;
 
 /* VBS
+
 #if __GNUC_PREREQ__(3, 3) || (defined(__INTEL_COMPILER) && __INTEL_COMPILER >= 800)
 #define	__MATH_BUILTIN_CONSTANTS
 #endif
@@ -54,15 +43,8 @@ extern const union __nan_un {
 #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()
@@ -71,8 +53,8 @@ extern const union __nan_un {
 #endif
 
 #if __ISO_C_VISIBLE >= 1999
-#define	FP_ILOGB0	(-INT_MAX)
-#define	FP_ILOGBNAN	INT_MAX
+#define	FP_ILOGB0	(-__INT_MAX)
+#define	FP_ILOGBNAN	__INT_MAX
 
 #ifdef __MATH_BUILTIN_CONSTANTS
 #define	HUGE_VALF	__builtin_huge_valf()
@@ -91,10 +73,6 @@ extern const union __nan_un {
 #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
@@ -102,27 +80,43 @@ extern const union __nan_un {
 #define	FP_NORMAL	0x04
 #define	FP_SUBNORMAL	0x08
 #define	FP_ZERO		0x10
+
+#if (__STDC_VERSION__ >= 201112L && defined(__clang__)) || \
+    __has_extension(c_generic_selections)
+#define	__fp_type_select(x, f, d, ld) _Generic((x),			\
+    float: f(x),							\
+    double: d(x),							\
+    long double: ld(x),							\
+    volatile float: f(x),						\
+    volatile double: d(x),						\
+    volatile long double: ld(x),					\
+    volatile const float: f(x),						\
+    volatile const double: d(x),					\
+    volatile const long double: ld(x),					\
+    const float: f(x),							\
+    const double: d(x),							\
+    const long double: ld(x))
+#elif __GNUC_PREREQ__(3, 1) && !defined(__cplusplus)
+#define	__fp_type_select(x, f, d, ld) __builtin_choose_expr(		\
+    __builtin_types_compatible_p(__typeof(x), long double), ld(x),	\
+    __builtin_choose_expr(						\
+    __builtin_types_compatible_p(__typeof(x), double), d(x),		\
+    __builtin_choose_expr(						\
+    __builtin_types_compatible_p(__typeof(x), float), f(x), (void)0)))
+#else
+#define	 __fp_type_select(x, f, d, ld)					\
+    ((sizeof(x) == sizeof(float)) ? f(x)				\
+    : (sizeof(x) == sizeof(double)) ? d(x)				\
+    : ld(x))
+#endif
+
 #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))
+	__fp_type_select(x, __fpclassifyf, __fpclassifyd, __fpclassifyl)
+#define	isfinite(x) __fp_type_select(x, __isfinitef, __isfinite, __isfinitel)
+#define	isinf(x) __fp_type_select(x, __isinff, __isinf, __isinfl)
+#define	isnan(x) \
+	__fp_type_select(x, __inline_isnanf, __inline_isnan, __inline_isnanl)
+#define	isnormal(x) __fp_type_select(x, __isnormalf, __isnormal, __isnormall)
 
 #ifdef __MATH_BUILTIN_RELOPS
 #define	isgreater(x, y)		__builtin_isgreater((x), (y))
@@ -141,14 +135,10 @@ extern const union __nan_un {
 #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))
+#define	signbit(x) __fp_type_select(x, __signbitf, __signbit, __signbitl)
 
-//VBS
-//typedef	__double_t	double_t;
-//typedef	__float_t	float_t;
+typedef	__double_t	double_t;
+typedef	__float_t	float_t;
 #endif /* __ISO_C_VISIBLE >= 1999 */
 
 /*
@@ -170,15 +160,12 @@ extern const union __nan_un {
 #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. */
+/* Old value from 4.4BSD-Lite math.h; this is probably better. */
 #define	HUGE		HUGE_VAL
 #else
 #define	HUGE		MAXFLOAT
@@ -190,13 +177,7 @@ extern int signgam;
  * 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);
-
+__BEGIN_DECLS
 /*
  * ANSI/POSIX
  */
@@ -207,9 +188,8 @@ int	__isfinitef(float) __pure2;
 int	__isfinite(double) __pure2;
 int	__isfinitel(long double) __pure2;
 int	__isinff(float) __pure2;
+int	__isinf(double) __pure2;
 int	__isinfl(long double) __pure2;
-int	__isnanf(float) __pure2;
-int	__isnanl(long double) __pure2;
 int	__isnormalf(float) __pure2;
 int	__isnormal(double) __pure2;
 int	__isnormall(long double) __pure2;
@@ -217,6 +197,42 @@ int	__signbit(double) __pure2;
 int	__signbitf(float) __pure2;
 int	__signbitl(long double) __pure2;
 
+static __inline int
+__inline_isnan(__const double __x)
+{
+
+	return (__x != __x);
+}
+
+static __inline int
+__inline_isnanf(__const float __x)
+{
+
+	return (__x != __x);
+}
+
+static __inline int
+__inline_isnanl(__const long double __x)
+{
+
+	return (__x != __x);
+}
+
+/*
+ * Version 2 of the Single UNIX Specification (UNIX98) defined isnan() and
+ * isinf() as functions taking double.  C99, and the subsequent POSIX revisions
+ * (SUSv3, POSIX.1-2001, define it as a macro that accepts any real floating
+ * point type.  If we are targeting SUSv2 and C99 or C11 (or C++11) then we
+ * expose the newer definition, assuming that the language spec takes
+ * precedence over the operating system interface spec.
+ */
+#if	__XSI_VISIBLE > 0 && __XSI_VISIBLE < 600 && __ISO_C_VISIBLE < 1999
+#undef isinf
+#undef isnan
+int	isinf(double);
+int	isnan(double);
+#endif
+
 double	acos(double);
 double	asin(double);
 double	atan(double);
@@ -259,8 +275,6 @@ double	expm1(double);
 double	fma(double, double, double);
 double	hypot(double, double);
 int	ilogb(double) __pure2;
-int	(isinf)(double) __pure2;
-int	(isnan)(double) __pure2;
 double	lgamma(double);
 long long llrint(double);
 long long llround(double);
@@ -283,6 +297,14 @@ double	jn(int, double);
 double	y0(double);
 double	y1(double);
 double	yn(int, double);
+
+#if __XSI_VISIBLE <= 500 || __BSD_VISIBLE
+double	gamma(double);
+#endif
+
+#if __XSI_VISIBLE <= 600 || __BSD_VISIBLE
+double	scalb(double, double);
+#endif
 #endif /* __BSD_VISIBLE || __XSI_VISIBLE */
 
 #if __BSD_VISIBLE || __ISO_C_VISIBLE >= 1999
@@ -302,18 +324,21 @@ double	trunc(double);
  * BSD math library entry points
  */
 #if __BSD_VISIBLE
+double	drem(double, double);
+int	finite(double) __pure2;
 int	isnanf(float) __pure2;
 
 /*
- * Reentrant version of lgamma; passes signgam back by reference as the
- * second argument; user must allocate space for signgam.
+ * Reentrant version of gamma & lgamma; passes signgam back by reference
+ * as the second argument; user must allocate space for signgam.
  */
+double	gamma_r(double, int *);
 double	lgamma_r(double, int *);
 
 /*
- * Single sine/cosine function.
+ * IEEE Test Vector
  */
-void	sincos(double, double *, double *);
+double	significand(double);
 #endif /* __BSD_VISIBLE */
 
 /* float versions of ANSI/POSIX functions */
@@ -388,23 +413,28 @@ float	fminf(float, float) __pure2;
  */
 #if __BSD_VISIBLE
 float	dremf(float, float);
+int	finitef(float) __pure2;
+float	gammaf(float);
 float	j0f(float);
 float	j1f(float);
 float	jnf(int, float);
+float	scalbf(float, float);
 float	y0f(float);
 float	y1f(float);
 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.
+ * Float versions of reentrant version of gamma & lgamma; passes
+ * signgam back by reference as the second argument; user must
+ * allocate space for signgam.
  */
+float	gammaf_r(float, int *);
 float	lgammaf_r(float, int *);
 
 /*
- * Single sine/cosine function.
+ * float version of IEEE Test Vector
  */
-void	sincosf(float, float *, float *);
+float	significandf(float);
 #endif	/* __BSD_VISIBLE */
 
 /*
@@ -472,19 +502,10 @@ long double	tgammal(long double);
 long double	truncl(long double);
 #endif /* __ISO_C_VISIBLE >= 1999 */
 
-/* Reentrant version of lgammal. */
 #if __BSD_VISIBLE
 long double	lgammal_r(long double, int *);
-
-/*
- * Single sine/cosine function.
- */
-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 */
+__END_DECLS
+
+#endif /* !_MATH_H_ */

+ 2 - 3
ld80/Make.files

@@ -4,9 +4,8 @@ $(CUR_SRCS) += 	invtrig.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
+#            s_remquol.c    e_fmodl.c      s_truncl.c     s_logl.c       s_expl.c \
+#            e_hypotl.c     s_floorl.c     s_nextafterl.c s_ceill.c      s_modfl.c
 
 ifneq ($(OS), WINNT)
 $(CUR_SRCS) += s_nanl.c

+ 322 - 389
ld80/e_lgammal_r.c

@@ -1,425 +1,358 @@
+/* @(#)e_lgamma_r.c 1.3 95/01/18 */
 /*
  * ====================================================
  * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
  *
- * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * 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.
  * ====================================================
  */
 
-/*
- * 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.
- */
+#include <cdefs-compat.h>
+__FBSDID("$FreeBSD$");
 
-/* 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
+/*
+ * See e_lgamma_r.c for complete comments.
  *
+ * Converted to long double by Steven G. Kargl.
  */
 
-#include <openlibm_math.h>
+#ifdef __i386__
+#include <ieeefp.h>
+#endif
 
+#include "fpmath.h"
+#include "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 */
+static const volatile double vzero = 0;
 
+static const double
+zero=  0,
+half=  0.5,
+one =  1;
 
-  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 const union IEEEl2bits
+piu = LD80C(0xc90fdaa22168c235, 1,  3.14159265358979323851e+00L);
+#define	pi	(piu.e)
+/*
+ * Domain y in [0x1p-70, 0.27], range ~[-4.5264e-22, 4.5264e-22]:
+ * |(lgamma(2 - y) + y / 2) / y - a(y)| < 2**-70.9
+ */
+static const union IEEEl2bits
+a0u = LD80C(0x9e233f1bed863d26, -4,  7.72156649015328606028e-02L),
+a1u = LD80C(0xa51a6625307d3249, -2,  3.22467033424113218889e-01L),
+a2u = LD80C(0x89f000d2abafda8c, -4,  6.73523010531979398946e-02L),
+a3u = LD80C(0xa8991563eca75f26, -6,  2.05808084277991211934e-02L),
+a4u = LD80C(0xf2027e10634ce6b6, -8,  7.38555102796070454026e-03L),
+a5u = LD80C(0xbd6eb76dd22187f4, -9,  2.89051035162703932972e-03L),
+a6u = LD80C(0x9c562ab05e0458ed, -10,  1.19275351624639999297e-03L),
+a7u = LD80C(0x859baed93ee48e46, -11,  5.09674593842117925320e-04L),
+a8u = LD80C(0xe9f28a4432949af2, -13,  2.23109648015769155122e-04L),
+a9u = LD80C(0xd12ad0d9b93c6bb0, -14,  9.97387167479808509830e-05L),
+a10u= LD80C(0xb7522643c78a219b, -15,  4.37071076331030136818e-05L),
+a11u= LD80C(0xca024dcdece2cb79, -16,  2.40813493372040143061e-05L),
+a12u= LD80C(0xbb90fb6968ebdbf9, -19,  2.79495621083634031729e-06L),
+a13u= LD80C(0xba1c9ffeeae07b37, -17,  1.10931287015513924136e-05L);
+#define	a0	(a0u.e)
+#define	a1	(a1u.e)
+#define	a2	(a2u.e)
+#define	a3	(a3u.e)
+#define	a4	(a4u.e)
+#define	a5	(a5u.e)
+#define	a6	(a6u.e)
+#define	a7	(a7u.e)
+#define	a8	(a8u.e)
+#define	a9	(a9u.e)
+#define	a10	(a10u.e)
+#define	a11	(a11u.e)
+#define	a12	(a12u.e)
+#define	a13	(a13u.e)
+/*
+ * Domain x in [tc-0.24, tc+0.28], range ~[-6.1205e-22, 6.1205e-22]:
+ * |(lgamma(x) - tf) -  t(x - tc)| < 2**-70.5
+ */
+static const union IEEEl2bits
+tcu  = LD80C(0xbb16c31ab5f1fb71, 0,  1.46163214496836234128e+00L),
+tfu  = LD80C(0xf8cdcde61c520e0f, -4, -1.21486290535849608093e-01L),
+ttu  = LD80C(0xd46ee54b27d4de99, -69, -2.81152980996018785880e-21L),
+t0u  = LD80C(0x80b9406556a62a6b, -68,  3.40728634996055147231e-21L),
+t1u  = LD80C(0xc7e9c6f6df3f8c39, -67, -1.05833162742737073665e-20L),
+t2u  = LD80C(0xf7b95e4771c55d51, -2,  4.83836122723810583532e-01L),
+t3u  = LD80C(0x97213c6e35e119ff, -3, -1.47587722994530691476e-01L),
+t4u  = LD80C(0x845a14a6a81dc94b, -4,  6.46249402389135358063e-02L),
+t5u  = LD80C(0x864d46fa89997796, -5, -3.27885410884846056084e-02L),
+t6u  = LD80C(0x93373cbd00297438, -6,  1.79706751150707171293e-02L),
+t7u  = LD80C(0xa8fcfca7eddc8d1d, -7, -1.03142230361450732547e-02L),
+t8u  = LD80C(0xc7e7015ff4bc45af, -8,  6.10053603296546099193e-03L),
+t9u  = LD80C(0xf178d2247adc5093, -9, -3.68456964904901200152e-03L),
+t10u = LD80C(0x94188d58f12e5e9f, -9,  2.25976420273774583089e-03L),
+t11u = LD80C(0xb7cbaef14e1406f1, -10, -1.40224943666225639823e-03L),
+t12u = LD80C(0xe63a671e6704ea4d, -11,  8.78250640744776944887e-04L),
+t13u = LD80C(0x914b6c9cae61783e, -11, -5.54255012657716808811e-04L),
+t14u = LD80C(0xb858f5bdb79276fe, -12,  3.51614951536825927370e-04L),
+t15u = LD80C(0xea73e744c34b9591, -13, -2.23591563824520112236e-04L),
+t16u = LD80C(0x99aeabb0d67ba835, -13,  1.46562869351659194136e-04L),
+t17u = LD80C(0xd7c6938325db2024, -14, -1.02889866046435680588e-04L),
+t18u = LD80C(0xe24cb1e3b0474775, -15,  5.39540265505221957652e-05L);
+#define	tc	(tcu.e)
+#define	tf	(tfu.e)
+#define	tt	(ttu.e)
+#define	t0	(t0u.e)
+#define	t1	(t1u.e)
+#define	t2	(t2u.e)
+#define	t3	(t3u.e)
+#define	t4	(t4u.e)
+#define	t5	(t5u.e)
+#define	t6	(t6u.e)
+#define	t7	(t7u.e)
+#define	t8	(t8u.e)
+#define	t9	(t9u.e)
+#define	t10	(t10u.e)
+#define	t11	(t11u.e)
+#define	t12	(t12u.e)
+#define	t13	(t13u.e)
+#define	t14	(t14u.e)
+#define	t15	(t15u.e)
+#define	t16	(t16u.e)
+#define	t17	(t17u.e)
+#define	t18	(t18u.e)
+/*
+ * Domain y in [-0.1, 0.232], range ~[-8.1938e-22, 8.3815e-22]:
+ * |(lgamma(1 + y) + 0.5 * y) / y - u(y) / v(y)| < 2**-71.2
+ */
+static const union IEEEl2bits
+u0u = LD80C(0x9e233f1bed863d27, -4, -7.72156649015328606095e-02L),
+u1u = LD80C(0x98280ee45e4ddd3d, -1,  5.94361239198682739769e-01L),
+u2u = LD80C(0xe330c8ead4130733, 0,  1.77492629495841234275e+00L),
+u3u = LD80C(0xd4a213f1a002ec52, 0,  1.66119622514818078064e+00L),
+u4u = LD80C(0xa5a9ca6f5bc62163, -1,  6.47122051417476492989e-01L),
+u5u = LD80C(0xc980e49cd5b019e6, -4,  9.83903751718671509455e-02L),
+u6u = LD80C(0xff636a8bdce7025b, -9,  3.89691687802305743450e-03L),
+v1u = LD80C(0xbd109c533a19fbf5, 1,  2.95413883330948556544e+00L),
+v2u = LD80C(0xd295cbf96f31f099, 1,  3.29039286955665403176e+00L),
+v3u = LD80C(0xdab8bcfee40496cb, 0,  1.70876276441416471410e+00L),
+v4u = LD80C(0xd2f2dc3638567e9f, -2,  4.12009126299534668571e-01L),
+v5u = LD80C(0xa07d9b0851070f41, -5,  3.91822868305682491442e-02L),
+v6u = LD80C(0xe3cd8318f7adb2c4, -11,  8.68998648222144351114e-04L);
+#define	u0	(u0u.e)
+#define	u1	(u1u.e)
+#define	u2	(u2u.e)
+#define	u3	(u3u.e)
+#define	u4	(u4u.e)
+#define	u5	(u5u.e)
+#define	u6	(u6u.e)
+#define	v1	(v1u.e)
+#define	v2	(v2u.e)
+#define	v3	(v3u.e)
+#define	v4	(v4u.e)
+#define	v5	(v5u.e)
+#define	v6	(v6u.e)
+/*
+ * Domain x in (2, 3], range ~[-3.3648e-22, 3.4416e-22]:
+ * |(lgamma(y+2) - 0.5 * y) / y - s(y)/r(y)| < 2**-72.3
+ * with y = x - 2.
+ */
+static const union IEEEl2bits
+s0u = LD80C(0x9e233f1bed863d27, -4, -7.72156649015328606095e-02L),
+s1u = LD80C(0xd3ff0dcc7fa91f94, -3,  2.07027640921219389860e-01L),
+s2u = LD80C(0xb2bb62782478ef31, -2,  3.49085881391362090549e-01L),
+s3u = LD80C(0xb49f7438c4611a74, -3,  1.76389518704213357954e-01L),
+s4u = LD80C(0x9a957008fa27ecf9, -5,  3.77401710862930008071e-02L),
+s5u = LD80C(0xda9b389a6ca7a7ac, -9,  3.33566791452943399399e-03L),
+s6u = LD80C(0xbc7a2263faf59c14, -14,  8.98728786745638844395e-05L),
+r1u = LD80C(0xbf5cff5b11477d4d, 0,  1.49502555796294337722e+00L),
+r2u = LD80C(0xd9aec89de08e3da6, -1,  8.50323236984473285866e-01L),
+r3u = LD80C(0xeab7ae5057c443f9, -3,  2.29216312078225806131e-01L),
+r4u = LD80C(0xf29707d9bd2b1e37, -6,  2.96130326586640089145e-02L),
+r5u = LD80C(0xd376c2f09736c5a3, -10,  1.61334161411590662495e-03L),
+r6u = LD80C(0xc985983d0cd34e3d, -16,  2.40232770710953450636e-05L),
+r7u = LD80C(0xe5c7a4f7fc2ef13d, -25, -5.34997929289167573510e-08L);
+#define	s0	(s0u.e)
+#define	s1	(s1u.e)
+#define	s2	(s2u.e)
+#define	s3	(s3u.e)
+#define	s4	(s4u.e)
+#define	s5	(s5u.e)
+#define	s6	(s6u.e)
+#define	r1	(r1u.e)
+#define	r2	(r2u.e)
+#define	r3	(r3u.e)
+#define	r4	(r4u.e)
+#define	r5	(r5u.e)
+#define	r6	(r6u.e)
+#define	r7	(r7u.e)
+/*
+ * Domain z in [8, 0x1p70], range ~[-3.0235e-22, 3.0563e-22]:
+ * |lgamma(x) - (x - 0.5) * (log(x) - 1) - w(1/x)| < 2**-71.7
+ */
+static const union IEEEl2bits
+w0u = LD80C(0xd67f1c864beb4a69, -2,  4.18938533204672741776e-01L),
+w1u = LD80C(0xaaaaaaaaaaaaaaa1, -4,  8.33333333333333332678e-02L),
+w2u = LD80C(0xb60b60b60b5491c9, -9, -2.77777777777760927870e-03L),
+w3u = LD80C(0xd00d00cf58aede4c, -11,  7.93650793490637233668e-04L),
+w4u = LD80C(0x9c09bf626783d4a5, -11, -5.95238023926039051268e-04L),
+w5u = LD80C(0xdca7cadc5baa517b, -11,  8.41733700408000822962e-04L),
+w6u = LD80C(0xfb060e361e1ffd07, -10, -1.91515849570245136604e-03L),
+w7u = LD80C(0xcbd5101bb58d1f2b, -8,  6.22046743903262649294e-03L),
+w8u = LD80C(0xad27a668d32c821b, -6, -2.11370706734662081843e-02L);
+#define	w0	(w0u.e)
+#define	w1	(w1u.e)
+#define	w2	(w2u.e)
+#define	w3	(w3u.e)
+#define	w4	(w4u.e)
+#define	w5	(w5u.e)
+#define	w6	(w6u.e)
+#define	w7	(w7u.e)
+#define	w8	(w8u.e)
 
 static long double
-sin_pi(long double x)
+sin_pil(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 */
+	volatile long double vz;
+	long double y,z;
+	uint64_t n;
+	uint16_t hx;
+
+	y = -x;
+
+	vz = y+0x1p63;
+	z = vz-0x1p63;
+	if (z == y)
+	    return zero;
+
+	vz = y+0x1p61;
+	EXTRACT_LDBL80_WORDS(hx,n,vz);
+	z = vz-0x1p61;
+	if (z > y) {
+	    z -= 0.25;			/* adjust to round down */
+	    n--;
 	}
-      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;
+	n &= 7;				/* octant of y mod 2 */
+	y = y - z + n * 0.25;		/* y mod 2 */
+
+	switch (n) {
+	    case 0:   y =  __kernel_sinl(pi*y,zero,0); break;
+	    case 1:
+	    case 2:   y =  __kernel_cosl(pi*(0.5-y),zero); break;
+	    case 3:
+	    case 4:   y =  __kernel_sinl(pi*(one-y),zero,0); break;
+	    case 5:
+	    case 6:   y = -__kernel_cosl(pi*(y-1.5),zero); break;
+	    default:  y =  __kernel_sinl(pi*(y-2.0),zero,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;
+	long double nadj,p,p1,p2,p3,q,r,t,w,y,z;
+	uint64_t lx;
+	int i;
+	uint16_t hx,ix;
+
+	EXTRACT_LDBL80_WORDS(hx,lx,x);
+
+    /* purge +-Inf and NaNs */
+	*signgamp = 1;
+	ix = hx&0x7fff;
+	if(ix==0x7fff) return x*x;
+
+	ENTERI();
+
+    /* purge +-0 and tiny arguments */
+	*signgamp = 1-2*(hx>>15);
+	if(ix<0x3fff-67) {		/* |x|<2**-(p+3), return -log(|x|) */
+	    if((ix|lx)==0)
+		RETURNI(one/vzero);
+	    RETURNI(-logl(fabsl(x)));
+	}
 
-  if (ix < 0x3fc08000) /* 2^-63 */
-    {				/* |x|<2**-63, return -log(|x|) */
-      if (se & 0x8000)
-	{
-	  *signgamp = -1;
-	  return -logl (-x);
+    /* purge negative integers and start evaluation for other x < 0 */
+	if(hx&0x8000) {
+	    *signgamp = 1;
+	    if(ix>=0x3fff+63) 		/* |x|>=2**(p-1), must be -integer */
+		RETURNI(one/vzero);
+	    t = sin_pil(x);
+	    if(t==zero) RETURNI(one/vzero); /* -integer */
+	    nadj = logl(pi/fabsl(t*x));
+	    if(t<zero) *signgamp = -1;
+	    x = -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;
+    /* purge 1 and 2 */
+	if((ix==0x3fff || ix==0x4000) && lx==0x8000000000000000ULL) r = 0;
+    /* for x < 2.0 */
+	else if(ix<0x4000) {
+    /*
+     * XXX Supposedly, one can use the following information to replace the
+     * XXX FP rational expressions.  A similar approach is appropriate
+     * XXX for ld128, but one (may need?) needs to consider llx, too.
+     *
+     * 8.9999961853027344e-01 3ffe e666600000000000
+     * 7.3159980773925781e-01 3ffe bb4a200000000000
+     * 2.3163998126983643e-01 3ffc ed33080000000000
+     * 1.7316312789916992e+00 3fff dda6180000000000
+     * 1.2316322326660156e+00 3fff 9da6200000000000
+     */
+	    if(x<8.9999961853027344e-01) {
+		r = -logl(x);
+		if(x>=7.3159980773925781e-01) {y = 1-x; i= 0;}
+		else if(x>=2.3163998126983643e-01) {y= x-(tc-1); i=1;}
+		else {y = x; i=2;}
+	    } else {
+		r = 0;
+		if(x>=1.7316312789916992e+00) {y=2-x;i=0;}
+		else if(x>=1.2316322326660156e+00) {y=x-tc;i=1;}
+		else {y=x-1;i=2;}
 	    }
-	  else if (ix >= 0x3ffced33)/* 2.31639862060546875e-1 */
-	    {
-	      y = x - (tc - one);
-	      i = 1;
-	    }
-	  else
-	    {
-	      /* x < 0.23 */
-	      y = x;
-	      i = 2;
+	    switch(i) {
+	      case 0:
+		z = y*y;
+		p1 = a0+z*(a2+z*(a4+z*(a6+z*(a8+z*(a10+z*a12)))));
+		p2 = z*(a1+z*(a3+z*(a5+z*(a7+z*(a9+z*(a11+z*a13))))));
+		p  = y*p1+p2;
+		r  += p-y/2; break;
+	      case 1:
+		p = t0+y*t1+tt+y*y*(t2+y*(t3+y*(t4+y*(t5+y*(t6+y*(t7+y*(t8+
+		    y*(t9+y*(t10+y*(t11+y*(t12+y*(t13+y*(t14+y*(t15+y*(t16+
+		    y*(t17+y*t18))))))))))))))));
+		r += tf + p; break;
+	      case 2:
+		p1 = y*(u0+y*(u1+y*(u2+y*(u3+y*(u4+y*(u5+y*u6))))));
+		p2 = 1+y*(v1+y*(v2+y*(v3+y*(v4+y*(v5+y*v6)))));
+		r += p1/p2-y/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;
+    /* x < 8.0 */
+	else if(ix<0x4002) {
+	    i = x;
+	    y = x-i;
+	    p = y*(s0+y*(s1+y*(s2+y*(s3+y*(s4+y*(s5+y*s6))))));
+	    q = 1+y*(r1+y*(r2+y*(r3+y*(r4+y*(r5+y*(r6+y*r7))))));
+	    r = y/2+p/q;
+	    z = 1;	/* lgamma(1+s) = log(s) + lgamma(s) */
+	    switch(i) {
+	    case 7: z *= (y+6);		/* FALLTHRU */
+	    case 6: z *= (y+5);		/* FALLTHRU */
+	    case 5: z *= (y+4);		/* FALLTHRU */
+	    case 4: z *= (y+3);		/* FALLTHRU */
+	    case 3: z *= (y+2);		/* FALLTHRU */
+		    r += logl(z); break;
 	    }
-	}
-      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;
+    /* 8.0 <= x < 2**(p+3) */
+	} else if (ix<0x3fff+67) {
+	    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+y*w8)))))));
+	    r = (x-half)*(t-one)+w;
+    /* 2**(p+3) <= x <= inf */
+	} else 
+	    r =  x*(logl(x)-1);
+	if(hx&0x8000) r = nadj - r;
+	RETURNI(r);
 }

+ 3 - 3
ld80/invtrig.c

@@ -24,10 +24,10 @@
  * 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 <cdefs-compat.h>
+__FBSDID("$FreeBSD$");
 
-#include "ld80/invtrig.h"
+#include "invtrig.h"
 
 /*
  * asinl() and acosl()

+ 3 - 3
ld80/k_cosl.c

@@ -11,8 +11,8 @@
  * ====================================================
  */
 
-#include "cdefs-compat.h"
-//__FBSDID("$FreeBSD: src/lib/msun/ld80/k_cosl.c,v 1.1 2008/02/17 07:32:14 das Exp $");
+#include <cdefs-compat.h>
+__FBSDID("$FreeBSD$");
 
 /*
  * ld80 version of k_cos.c.  See ../src/k_cos.c for most comments.
@@ -65,7 +65,7 @@ C5 =  0.0000000020876754400407278,	/*  0x11eed8caaeccf1.0p-81 */
 C6 = -1.1470297442401303e-11,		/* -0x19393412bd1529.0p-89 */
 C7 =  4.7383039476436467e-14;		/*  0x1aac9d9af5c43e.0p-97 */
 
-DLLEXPORT long double
+long double
 __kernel_cosl(long double x, long double y)
 {
 	long double hz,z,r,w;

+ 3 - 3
ld80/k_sinl.c

@@ -11,8 +11,8 @@
  * ====================================================
  */
 
-#include "cdefs-compat.h"
-//__FBSDID("$FreeBSD: src/lib/msun/ld80/k_sinl.c,v 1.1 2008/02/17 07:32:14 das Exp $");
+#include <cdefs-compat.h>
+__FBSDID("$FreeBSD$");
 
 /*
  * ld80 version of k_sin.c.  See ../src/k_sin.c for most comments.
@@ -49,7 +49,7 @@ S6 =  1.6059006598854211e-10,		/*  0x161242b90243b5.0p-85 */
 S7 = -7.6429779983024564e-13,		/* -0x1ae42ebd1b2e00.0p-93 */
 S8 =  2.6174587166648325e-15;		/*  0x179372ea0b3f64.0p-101 */
 
-DLLEXPORT long double
+long double
 __kernel_sinl(long double x, long double y, int iy)
 {
 	long double z,r,v;

+ 4 - 5
ld80/k_tanl.c

@@ -11,15 +11,14 @@
  * ====================================================
  */
 
-#include "cdefs-compat.h"
-//__FBSDID("$FreeBSD: src/lib/msun/ld80/k_tanl.c,v 1.3 2008/02/18 15:39:52 bde Exp $");
+#include <cdefs-compat.h>
+__FBSDID("$FreeBSD$");
 
 /*
  * ld80 version of k_tan.c.  See ../src/k_tan.c for most comments.
  */
 
-#include <openlibm_math.h>
-
+#include "math.h"
 #include "math_private.h"
 
 /*
@@ -70,7 +69,7 @@ T29 =  0.0000078293456938132840,	/*  0x106b59141a6cb3.0p-69 */
 T31 = -0.0000032609076735050182,	/* -0x1b5abef3ba4b59.0p-71 */
 T33 =  0.0000023261313142559411;	/*  0x13835436c0c87f.0p-71 */
 
-DLLEXPORT long double
+long double
 __kernel_tanl(long double x, long double y, int iy) {
 	long double z, r, v, w, s;
 	long double osign;

+ 291 - 384
ld80/s_erfl.c

@@ -1,3 +1,4 @@
+/* @(#)s_erf.c 5.1 93/09/24 */
 /*
  * ====================================================
  * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
@@ -9,422 +10,328 @@
  * ====================================================
  */
 
-/*
- * 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.
- */
+#include <cdefs-compat.h>
+__FBSDID("$FreeBSD$");
 
-/* 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
+/*
+ * See s_erf.c for complete comments.
  *
- *      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
+ * Converted to long double by Steven G. Kargl.
  */
+#include <float.h>
+#ifdef __i386__
+#include <ieeefp.h>
+#endif
 
-
-#include <openlibm_math.h>
-
+#include "fpmath.h"
+#include "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,
+/* XXX Prevent compilers from erroneously constant folding: */
+static const volatile long double tiny = 0x1p-10000L;
+
+static const double
+half= 0.5,
+one = 1,
+two = 2;
 /*
- * Coefficients for approximation to  erf on [0,0.84375]
+ * In the domain [0, 2**-34], only the first term in the power series
+ * expansion of erf(x) is used.  The magnitude of the first neglected
+ * terms is less than 2**-102.
  */
-  /* 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 */
-  },
-
+static const union IEEEl2bits
+efxu  = LD80C(0x8375d410a6db446c, -3,  1.28379167095512573902e-1L),
+efx8u = LD80C(0x8375d410a6db446c,  0,  1.02703333676410059122e+0L),
 /*
- * Coefficients for approximation to  erf  in [0.84375,1.25]
+ * Domain [0, 0.84375], range ~[-1.423e-22, 1.423e-22]:
+ * |(erf(x) - x)/x - pp(x)/qq(x)| < 2**-72.573
  */
-/* 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 */
-  },
-
+pp0u  = LD80C(0x8375d410a6db446c, -3,   1.28379167095512573902e-1L),
+pp1u  = LD80C(0xa46c7d09ec3d0cec, -2,  -3.21140201054840180596e-1L),
+pp2u  = LD80C(0x9b31e66325576f86, -5,  -3.78893851760347812082e-2L),
+pp3u  = LD80C(0x804ac72c9a0b97dd, -7,  -7.83032847030604679616e-3L),
+pp4u  = LD80C(0x9f42bcbc3d5a601d, -12, -3.03765663857082048459e-4L),
+pp5u  = LD80C(0x9ec4ad6193470693, -16, -1.89266527398167917502e-5L),
+qq1u  = LD80C(0xdb4b8eb713188d6b, -2,   4.28310832832310510579e-1L),
+qq2u  = LD80C(0xa5750835b2459bd1, -4,   8.07896272074540216658e-2L),
+qq3u  = LD80C(0x8b85d6bd6a90b51c, -7,   8.51579638189385354266e-3L),
+qq4u  = LD80C(0x87332f82cff4ff96, -11,  5.15746855583604912827e-4L),
+qq5u  = LD80C(0x83466cb6bf9dca00, -16,  1.56492109706256700009e-5L),
+qq6u  = LD80C(0xf5bf98c2f996bf63, -24,  1.14435527803073879724e-7L);
+#define	efx	(efxu.e)
+#define	efx8	(efx8u.e)
+#define	pp0	(pp0u.e)
+#define	pp1	(pp1u.e)
+#define	pp2	(pp2u.e)
+#define	pp3	(pp3u.e)
+#define	pp4	(pp4u.e)
+#define	pp5	(pp5u.e)
+#define	qq1	(qq1u.e)
+#define	qq2	(qq2u.e)
+#define	qq3	(qq3u.e)
+#define	qq4	(qq4u.e)
+#define	qq5	(qq5u.e)
+#define	qq6	(qq6u.e)
+static const union IEEEl2bits
+erxu  = LD80C(0xd7bb3d0000000000, -1,  8.42700779438018798828e-1L),
 /*
- * Coefficients for approximation to  erfc in [1.25,1/0.35]
+ * Domain [0.84375, 1.25], range ~[-8.132e-22, 8.113e-22]:
+ * |(erf(x) - erx) - pa(x)/qa(x)| < 2**-71.762
  */
-/* 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 */
-    },
+pa0u  = LD80C(0xe8211158da02c692, -27,  1.35116960705131296711e-8L),
+pa1u  = LD80C(0xd488f89f36988618, -2,   4.15107507167065612570e-1L),
+pa2u  = LD80C(0xece74f8c63fa3942, -4,  -1.15675565215949226989e-1L),
+pa3u  = LD80C(0xc8d31e020727c006, -4,   9.80589241379624665791e-2L),
+pa4u  = LD80C(0x985d5d5fafb0551f, -5,   3.71984145558422368847e-2L),
+pa5u  = LD80C(0xa5b6c4854d2f5452, -8,  -5.05718799340957673661e-3L),
+pa6u  = LD80C(0x85c8d58fe3993a47, -8,   4.08277919612202243721e-3L),
+pa7u  = LD80C(0xddbfbc23677b35cf, -13,  2.11476292145347530794e-4L),
+qa1u  = LD80C(0xb8a977896f5eff3f, -1,   7.21335860303380361298e-1L),
+qa2u  = LD80C(0x9fcd662c3d4eac86, -1,   6.24227891731886593333e-1L),
+qa3u  = LD80C(0x9d0b618eac67ba07, -2,   3.06727455774491855801e-1L),
+qa4u  = LD80C(0x881a4293f6d6c92d, -3,   1.32912674218195890535e-1L),
+qa5u  = LD80C(0xbab144f07dea45bf, -5,   4.55792134233613027584e-2L),
+qa6u  = LD80C(0xa6c34ba438bdc900, -7,   1.01783980070527682680e-2L),
+qa7u  = LD80C(0x8fa866dc20717a91, -9,   2.19204436518951438183e-3L);
+#define erx	(erxu.e)
+#define pa0	(pa0u.e)
+#define pa1	(pa1u.e)
+#define pa2	(pa2u.e)
+#define pa3	(pa3u.e)
+#define pa4	(pa4u.e)
+#define pa5	(pa5u.e)
+#define pa6	(pa6u.e)
+#define pa7	(pa7u.e)
+#define qa1	(qa1u.e)
+#define qa2	(qa2u.e)
+#define qa3	(qa3u.e)
+#define qa4	(qa4u.e)
+#define qa5	(qa5u.e)
+#define qa6	(qa6u.e)
+#define qa7	(qa7u.e)
+static const union IEEEl2bits
 /*
- * Coefficients for approximation to  erfc in [1/.35,107]
+ * Domain [1.25,2.85715], range ~[-2.334e-22,2.334e-22]:
+ * |log(x*erfc(x)) + x**2 + 0.5625 - ra(x)/sa(x)| < 2**-71.860
  */
-/* 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 */
-    };
+ra0u  = LD80C(0xa1a091e0fb4f335a, -7, -9.86494298915814308249e-3L),
+ra1u  = LD80C(0xc2b0d045ae37df6b, -1, -7.60510460864878271275e-1L),
+ra2u  = LD80C(0xf2cec3ee7da636c5, 3,  -1.51754798236892278250e+1L),
+ra3u  = LD80C(0x813cc205395adc7d, 7,  -1.29237335516455333420e+2L),
+ra4u  = LD80C(0x8737c8b7b4062c2f, 9,  -5.40871625829510494776e+2L),
+ra5u  = LD80C(0x8ffe5383c08d4943, 10, -1.15194769466026108551e+3L),
+ra6u  = LD80C(0x983573e64d5015a9, 10, -1.21767039790249025544e+3L),
+ra7u  = LD80C(0x92a794e763a6d4db, 9,  -5.86618463370624636688e+2L),
+ra8u  = LD80C(0xd5ad1fae77c3d9a3, 6,  -1.06838132335777049840e+2L),
+ra9u  = LD80C(0x934c1a247807bb9c, 2,  -4.60303980944467334806e+0L),
+sa1u  = LD80C(0xd342f90012bb1189, 4,   2.64077014928547064865e+1L),
+sa2u  = LD80C(0x839be13d9d5da883, 8,   2.63217811300123973067e+2L),
+sa3u  = LD80C(0x9f8cba6d1ae1b24b, 10,  1.27639775710344617587e+3L),
+sa4u  = LD80C(0xcaa83f403713e33e, 11,  3.24251544209971162003e+3L),
+sa5u  = LD80C(0x8796aff2f3c47968, 12,  4.33883591261332837874e+3L),
+sa6u  = LD80C(0xb6ef97f9c753157b, 11,  2.92697460344182158454e+3L),
+sa7u  = LD80C(0xe02aee5f83773d1c, 9,   8.96670799139389559818e+2L),
+sa8u  = LD80C(0xc82b83855b88e07e, 6,   1.00084987800048510018e+2L),
+sa9u  = LD80C(0x92f030aefadf28ad, 1,   2.29591004455459083843e+0L);
+#define ra0	(ra0u.e)
+#define ra1	(ra1u.e)
+#define ra2	(ra2u.e)
+#define ra3	(ra3u.e)
+#define ra4	(ra4u.e)
+#define ra5	(ra5u.e)
+#define ra6	(ra6u.e)
+#define ra7	(ra7u.e)
+#define ra8	(ra8u.e)
+#define ra9	(ra9u.e)
+#define sa1	(sa1u.e)
+#define sa2	(sa2u.e)
+#define sa3	(sa3u.e)
+#define sa4	(sa4u.e)
+#define sa5	(sa5u.e)
+#define sa6	(sa6u.e)
+#define sa7	(sa7u.e)
+#define sa8	(sa8u.e)
+#define sa9	(sa9u.e)
+/*
+ * Domain [2.85715,7], range ~[-8.323e-22,8.390e-22]:
+ * |log(x*erfc(x)) + x**2 + 0.5625 - rb(x)/sb(x)| < 2**-70.326
+ */
+static const union IEEEl2bits
+rb0u = LD80C(0xa1a091cf43abcd26, -7, -9.86494292470284646962e-3L),
+rb1u = LD80C(0xd19d2df1cbb8da0a, -1, -8.18804618389296662837e-1L),
+rb2u = LD80C(0x9a4dd1383e5daf5b, 4,  -1.92879967111618594779e+1L),
+rb3u = LD80C(0xbff0ae9fc0751de6, 7,  -1.91940164551245394969e+2L),
+rb4u = LD80C(0xdde08465310b472b, 9,  -8.87508080766577324539e+2L),
+rb5u = LD80C(0xe796e1d38c8c70a9, 10, -1.85271506669474503781e+3L),
+rb6u = LD80C(0xbaf655a76e0ab3b5, 10, -1.49569795581333675349e+3L),
+rb7u = LD80C(0x95d21e3e75503c21, 8,  -2.99641547972948019157e+2L),
+sb1u = LD80C(0x814487ed823c8cbd, 5,   3.23169247732868256569e+1L),
+sb2u = LD80C(0xbe4bfbb1301304be, 8,   3.80593618534539961773e+2L),
+sb3u = LD80C(0x809c4ade46b927c7, 11,  2.05776827838541292848e+3L),
+sb4u = LD80C(0xa55284359f3395a8, 12,  5.29031455540062116327e+3L),
+sb5u = LD80C(0xbcfa72da9b820874, 12,  6.04730608102312640462e+3L),
+sb6u = LD80C(0x9d09a35988934631, 11,  2.51260238030767176221e+3L),
+sb7u = LD80C(0xd675bbe542c159fa, 7,   2.14459898308561015684e+2L);
+#define rb0	(rb0u.e)
+#define rb1	(rb1u.e)
+#define rb2	(rb2u.e)
+#define rb3	(rb3u.e)
+#define rb4	(rb4u.e)
+#define rb5	(rb5u.e)
+#define rb6	(rb6u.e)
+#define rb7	(rb7u.e)
+#define sb1	(sb1u.e)
+#define sb2	(sb2u.e)
+#define sb3	(sb3u.e)
+#define sb4	(sb4u.e)
+#define sb5	(sb5u.e)
+#define sb6	(sb6u.e)
+#define sb7	(sb7u.e)
+/*
+ * Domain [7,108], range ~[-4.422e-22,4.422e-22]:
+ * |log(x*erfc(x)) + x**2 + 0.5625 - rc(x)/sc(x)| < 2**-70.938
+ */
+static const union IEEEl2bits
+/* err = -4.422092275318925082e-22 -70.937689 */
+rc0u = LD80C(0xa1a091cf437a17ad, -7, -9.86494292470008707260e-3L),
+rc1u = LD80C(0xbe79c5a978122b00, -1, -7.44045595049165939261e-1L),
+rc2u = LD80C(0xdb26f9bbe31a2794, 3,  -1.36970155085888424425e+1L),
+rc3u = LD80C(0xb5f69a38f5747ac8, 6,  -9.09816453742625888546e+1L),
+rc4u = LD80C(0xd79676d970d0a21a, 7,  -2.15587750997584074147e+2L),
+rc5u = LD80C(0xfe528153c45ec97c, 6,  -1.27161142938347796666e+2L),
+sc1u = LD80C(0xc5e8cd46d5604a96, 4,   2.47386727842204312937e+1L),
+sc2u = LD80C(0xc5f0f5a5484520eb, 7,   1.97941248254913378865e+2L),
+sc3u = LD80C(0x964e3c7b34db9170, 9,   6.01222441484087787522e+2L),
+sc4u = LD80C(0x99be1b89faa0596a, 9,   6.14970430845978077827e+2L),
+sc5u = LD80C(0xf80dfcbf37ffc5ea, 6,   1.24027318931184605891e+2L);
+#define rc0	(rc0u.e)
+#define rc1	(rc1u.e)
+#define rc2	(rc2u.e)
+#define rc3	(rc3u.e)
+#define rc4	(rc4u.e)
+#define rc5	(rc5u.e)
+#define sc1	(sc1u.e)
+#define sc2	(sc2u.e)
+#define sc3	(sc3u.e)
+#define sc4	(sc4u.e)
+#define sc5	(sc5u.e)
 
 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;
+	long double ax,R,S,P,Q,s,y,z,r;
+	uint64_t lx;
+	int32_t i;
+	uint16_t hx;
 
-  GET_LDOUBLE_WORDS (se, i0, i1, x);
-  ix = se & 0x7fff;
+	EXTRACT_LDBL80_WORDS(hx, lx, x);
 
-  if (ix >= 0x7fff)
-    {				/* erf(nan)=nan */
-      i = ((se & 0xffff) >> 15) << 1;
-      return (long double) (1 - i) + one / x;	/* erf(+-inf)=+-1 */
-    }
+	if((hx & 0x7fff) == 0x7fff) {	/* erfl(nan)=nan */
+		i = (hx>>15)<<1;
+		return (1-i)+one/x;	/* erfl(+-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;
+	ENTERI();
+
+	ax = fabsl(x);
+	if(ax < 0.84375) {
+	    if(ax < 0x1p-34L) {
+	        if(ax < 0x1p-16373L)	
+		    RETURNI((8*x+efx8*x)/8);	/* avoid spurious underflow */
+		RETURNI(x + efx*x);
+	    }
+	    z = x*x;
+	    r = pp0+z*(pp1+z*(pp2+z*(pp3+z*(pp4+z*pp5))));
+	    s = one+z*(qq1+z*(qq2+z*(qq3+z*(qq4+z*(qq5+z*qq6)))));
+	    y = r/s;
+	    RETURNI(x + x*y);
+	}
+	if(ax < 1.25) {
+	    s = ax-one;
+	    P = pa0+s*(pa1+s*(pa2+s*(pa3+s*(pa4+s*(pa5+s*(pa6+s*pa7))))));
+	    Q = one+s*(qa1+s*(qa2+s*(qa3+s*(qa4+s*(qa5+s*(qa6+s*qa7))))));
+	    if(x>=0) RETURNI(erx + P/Q); else RETURNI(-erx - P/Q);
+	}
+	if(ax >= 7) {			/* inf>|x|>= 7 */
+	    if(x>=0) RETURNI(one-tiny); else RETURNI(tiny-one);
 	}
-      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;
+	s = one/(ax*ax);
+	if(ax < 2.85715) {	/* |x| < 2.85715 */
+	    R=ra0+s*(ra1+s*(ra2+s*(ra3+s*(ra4+s*(ra5+s*(ra6+s*(ra7+
+		s*(ra8+s*ra9))))))));
+	    S=one+s*(sa1+s*(sa2+s*(sa3+s*(sa4+s*(sa5+s*(sa6+s*(sa7+
+		s*(sa8+s*sa9))))))));
+	} else {	/* |x| >= 2.85715 */
+	    R=rb0+s*(rb1+s*(rb2+s*(rb3+s*(rb4+s*(rb5+s*(rb6+s*rb7))))));
+	    S=one+s*(sb1+s*(sb2+s*(sb3+s*(sb4+s*(sb5+s*(sb6+s*sb7))))));
+	}
+	z=(float)ax;
+	r=expl(-z*z-0.5625)*expl((z-ax)*(z+ax)+R/S);
+	if(x>=0) RETURNI(one-r/ax); else RETURNI(r/ax-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;
+	long double ax,R,S,P,Q,s,y,z,r;
+	uint64_t lx;
+	uint16_t hx;
 
-  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;
-    }
+	EXTRACT_LDBL80_WORDS(hx, lx, 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((hx & 0x7fff) == 0x7fff) {	/* erfcl(nan)=nan */
+					/* erfcl(+-inf)=0,2 */
+	    return ((hx>>15)<<1)+one/x;
 	}
-    }
-  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))))))));
+
+	ENTERI();
+
+	ax = fabsl(x);
+	if(ax < 0.84375L) {
+	    if(ax < 0x1p-34L)
+		RETURNI(one-x);
+	    z = x*x;
+	    r = pp0+z*(pp1+z*(pp2+z*(pp3+z*(pp4+z*pp5))));
+	    s = one+z*(qq1+z*(qq2+z*(qq3+z*(qq4+z*(qq5+z*qq6)))));
+	    y = r/s;
+	    if(ax < 0.25L) {  	/* x<1/4 */
+		RETURNI(one-(x+x*y));
+	    } else {
+		r = x*y;
+		r += (x-half);
+	       RETURNI(half - r);
+	    }
 	}
-      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))))));
+	if(ax < 1.25L) {
+	    s = ax-one;
+	    P = pa0+s*(pa1+s*(pa2+s*(pa3+s*(pa4+s*(pa5+s*(pa6+s*pa7))))));
+	    Q = one+s*(qa1+s*(qa2+s*(qa3+s*(qa4+s*(qa5+s*(qa6+s*qa7))))));
+	    if(x>=0) {
+	        z  = one-erx; RETURNI(z - P/Q);
+	    } else {
+		z = (erx+P/Q); RETURNI(one+z);
+	    }
 	}
-      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))));
+	if(ax < 108) {			/* |x| < 108 */
+ 	    s = one/(ax*ax);
+	    if(ax < 2.85715) {		/* |x| < 2.85715 */
+		R=ra0+s*(ra1+s*(ra2+s*(ra3+s*(ra4+s*(ra5+s*(ra6+s*(ra7+
+		    s*(ra8+s*ra9))))))));
+		S=one+s*(sa1+s*(sa2+s*(sa3+s*(sa4+s*(sa5+s*(sa6+s*(sa7+
+		    s*(sa8+s*sa9))))))));
+	    } else if(ax < 7) {		/* | |x| < 7 */
+		R=rb0+s*(rb1+s*(rb2+s*(rb3+s*(rb4+s*(rb5+s*(rb6+s*rb7))))));
+		S=one+s*(sb1+s*(sb2+s*(sb3+s*(sb4+s*(sb5+s*(sb6+s*sb7))))));
+	    } else {
+		if(x < -7) RETURNI(two-tiny);/* x < -7 */
+		R=rc0+s*(rc1+s*(rc2+s*(rc3+s*(rc4+s*rc5))));
+		S=one+s*(sc1+s*(sc2+s*(sc3+s*(sc4+s*sc5))));
+	    }
+	    z = (float)ax;
+	    r = expl(-z*z-0.5625)*expl((z-ax)*(z+ax)+R/S);
+	    if(x>0) RETURNI(r/ax); else RETURNI(two-r/ax);
+	} else {
+	    if(x>0) RETURNI(tiny*tiny); else RETURNI(two-tiny);
 	}
-      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;
-    }
 }

+ 40 - 47
ld80/s_exp2l.c

@@ -24,40 +24,43 @@
  * 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 <cdefs-compat.h>
+__FBSDID("$FreeBSD$");
 
 #include <float.h>
 #include <stdint.h>
 
-#include "amd64/bsd_cdefs.h"
-#include "amd64/bsd_ieeefp.h"
-
-#include <openlibm_math.h>
+#ifdef __i386__
+#include <ieeefp.h>
+#endif
 
+#include "fpmath.h"
+#include "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 volatile long double
+    huge = 0x1p10000L,
+    twom10000 = 0x1p-10000L;
+
+static const union IEEEl2bits
+P1 = LD80C(0xb17217f7d1cf79ac, -1, 6.93147180559945309429e-1L);
 
 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;
+redux = 0x1.8p63 / TBLSIZE,
+/*
+ * Domain [-0.00390625, 0.00390625], range ~[-1.7079e-23, 1.7079e-23]
+ * |exp(x) - p(x)| < 2**-75.6
+ */
+P2 = 2.4022650695910072e-1,		/*  0x1ebfbdff82c58f.0p-55 */
+P3 = 5.5504108664816879e-2,		/*  0x1c6b08d7049e1a.0p-57 */
+P4 = 9.6181291055695180e-3,		/*  0x13b2ab6fa8321a.0p-59 */
+P5 = 1.3333563089183052e-3,		/*  0x15d8806f67f251.0p-62 */
+P6 = 1.5413361552277414e-4;		/*  0x1433ddacff3441.0p-65 */
 
 static const double tbl[TBLSIZE * 2] = {
 	0x1.6a09e667f3bcdp-1,	-0x1.bdd3413b2648p-55,
@@ -190,8 +193,8 @@ static const double tbl[TBLSIZE * 2] = {
 	0x1.68155d44ca973p+0,	 0x1.038ae44f74p-57,
 };
 
-/*
- * exp2l(x): compute the base 2 exponential of x
+/**
+ * Compute the base 2 exponential of x for Intel 80-bit format.
  *
  * Accuracy: Peak error < 0.511 ulp.
  *
@@ -207,11 +210,11 @@ static const double tbl[TBLSIZE * 2] = {
  *     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.
+ *   degree-6 minimax polynomial with maximum error under 2**-75.6.
  *   The table entries each have 104 bits of accuracy, encoded as
  *   a pair of double precision values.
  */
-DLLEXPORT long double
+long double
 exp2l(long double x)
 {
 	union IEEEl2bits u, v;
@@ -222,31 +225,22 @@ exp2l(long double x)
 	/* Filter out exceptional cases. */
 	u.e = x;
 	hx = u.xbits.expsign;
-	ix = hx & EXPMASK;
+	ix = hx & 0x7fff;
 	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 (hx & 0x8000 && u.xbits.man == 1ULL << 63)
+				return (0.0L);	/* x is -Inf */
+			return (x + x); /* x is +Inf, NaN or unsupported */
 		}
 		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);
+	} else if (ix <= BIAS - 66) {	/* |x| < 0x1p-65 (includes pseudos) */
+		return (1.0L + x);	/* 1 with inexact */
 	}
 
-#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
-
+	ENTERI();
 
 	/*
 	 * Reduce x, computing z, i0, and k. The low bits of x + redux
@@ -270,26 +264,25 @@ exp2l(long double x)
 	z = x - u.e;
 	v.xbits.man = 1ULL << 63;
 	if (k >= LDBL_MIN_EXP) {
-		v.xbits.expsign = LDBL_MAX_EXP - 1 + k;
+		v.xbits.expsign = BIAS + k;
 		twopk = v.e;
 	} else {
-		v.xbits.expsign = LDBL_MAX_EXP - 1 + k + 10000;
+		v.xbits.expsign = BIAS + 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
+	r = t_lo + (t_hi + t_lo) * z * (P1.e + 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);
+			RETURNI(r * 2.0 * 0x1p16383L);
+		RETURNI(r * twopk);
 	} else {
-		return (r * twopkp10000 * twom10000);
+		RETURNI(r * twopkp10000 * twom10000);
 	}
 }

+ 284 - 0
ld80/s_expl.c

@@ -0,0 +1,284 @@
+/*-
+ * Copyright (c) 2009-2013 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.
+ *
+ * Optimized by Bruce D. Evans.
+ */
+
+#include <cdefs-compat.h>
+__FBSDID("$FreeBSD$");
+
+/**
+ * Compute the exponential of x for Intel 80-bit format.  This is based on:
+ *
+ *   PTP Tang, "Table-driven implementation of the exponential function
+ *   in IEEE floating-point arithmetic," ACM Trans. Math. Soft., 15,
+ *   144-157 (1989).
+ *
+ * where the 32 table entries have been expanded to INTERVALS (see below).
+ */
+
+#include <float.h>
+
+#ifdef __i386__
+#include <ieeefp.h>
+#endif
+
+#include "fpmath.h"
+#include "math.h"
+#include "math_private.h"
+#include "k_expl.h"
+
+/* XXX Prevent compilers from erroneously constant folding these: */
+static const volatile long double
+huge = 0x1p10000L,
+tiny = 0x1p-10000L;
+
+static const long double
+twom10000 = 0x1p-10000L;
+
+static const union IEEEl2bits
+/* log(2**16384 - 0.5) rounded towards zero: */
+/* log(2**16384 - 0.5 + 1) rounded towards zero for expm1l() is the same: */
+o_thresholdu = LD80C(0xb17217f7d1cf79ab, 13,  11356.5234062941439488L),
+#define o_threshold	 (o_thresholdu.e)
+/* log(2**(-16381-64-1)) rounded towards zero: */
+u_thresholdu = LD80C(0xb21dfe7f09e2baa9, 13, -11399.4985314888605581L);
+#define u_threshold	 (u_thresholdu.e)
+
+long double
+expl(long double x)
+{
+	union IEEEl2bits u;
+	long double hi, lo, t, twopk;
+	int k;
+	uint16_t hx, ix;
+
+	DOPRINT_START(&x);
+
+	/* Filter out exceptional cases. */
+	u.e = x;
+	hx = u.xbits.expsign;
+	ix = hx & 0x7fff;
+	if (ix >= BIAS + 13) {		/* |x| >= 8192 or x is NaN */
+		if (ix == BIAS + LDBL_MAX_EXP) {
+			if (hx & 0x8000)  /* x is -Inf, -NaN or unsupported */
+				RETURNP(-1 / x);
+			RETURNP(x + x);	/* x is +Inf, +NaN or unsupported */
+		}
+		if (x > o_threshold)
+			RETURNP(huge * huge);
+		if (x < u_threshold)
+			RETURNP(tiny * tiny);
+	} else if (ix < BIAS - 75) {	/* |x| < 0x1p-75 (includes pseudos) */
+		RETURN2P(1, x);		/* 1 with inexact iff x != 0 */
+	}
+
+	ENTERI();
+
+	twopk = 1;
+	__k_expl(x, &hi, &lo, &k);
+	t = SUM2P(hi, lo);
+
+	/* Scale by 2**k. */
+	if (k >= LDBL_MIN_EXP) {
+		if (k == LDBL_MAX_EXP)
+			RETURNI(t * 2 * 0x1p16383L);
+		SET_LDBL_EXPSIGN(twopk, BIAS + k);
+		RETURNI(t * twopk);
+	} else {
+		SET_LDBL_EXPSIGN(twopk, BIAS + k + 10000);
+		RETURNI(t * twopk * twom10000);
+	}
+}
+
+/**
+ * Compute expm1l(x) for Intel 80-bit format.  This is based on:
+ *
+ *   PTP Tang, "Table-driven implementation of the Expm1 function
+ *   in IEEE floating-point arithmetic," ACM Trans. Math. Soft., 18,
+ *   211-222 (1992).
+ */
+
+/*
+ * Our T1 and T2 are chosen to be approximately the points where method
+ * A and method B have the same accuracy.  Tang's T1 and T2 are the
+ * points where method A's accuracy changes by a full bit.  For Tang,
+ * this drop in accuracy makes method A immediately less accurate than
+ * method B, but our larger INTERVALS makes method A 2 bits more
+ * accurate so it remains the most accurate method significantly
+ * closer to the origin despite losing the full bit in our extended
+ * range for it.
+ */
+static const double
+T1 = -0.1659,				/* ~-30.625/128 * log(2) */
+T2 =  0.1659;				/* ~30.625/128 * log(2) */
+
+/*
+ * Domain [-0.1659, 0.1659], range ~[-2.6155e-22, 2.5507e-23]:
+ * |(exp(x)-1-x-x**2/2)/x - p(x)| < 2**-71.6
+ *
+ * XXX the coeffs aren't very carefully rounded, and I get 2.8 more bits,
+ * but unlike for ld128 we can't drop any terms.
+ */
+static const union IEEEl2bits
+B3 = LD80C(0xaaaaaaaaaaaaaaab, -3,  1.66666666666666666671e-1L),
+B4 = LD80C(0xaaaaaaaaaaaaaaac, -5,  4.16666666666666666712e-2L);
+
+static const double
+B5  =  8.3333333333333245e-3,		/*  0x1.111111111110cp-7 */
+B6  =  1.3888888888888861e-3,		/*  0x1.6c16c16c16c0ap-10 */
+B7  =  1.9841269841532042e-4,		/*  0x1.a01a01a0319f9p-13 */
+B8  =  2.4801587302069236e-5,		/*  0x1.a01a01a03cbbcp-16 */
+B9  =  2.7557316558468562e-6,		/*  0x1.71de37fd33d67p-19 */
+B10 =  2.7557315829785151e-7,		/*  0x1.27e4f91418144p-22 */
+B11 =  2.5063168199779829e-8,		/*  0x1.ae94fabdc6b27p-26 */
+B12 =  2.0887164654459567e-9;		/*  0x1.1f122d6413fe1p-29 */
+
+long double
+expm1l(long double x)
+{
+	union IEEEl2bits u, v;
+	long double fn, hx2_hi, hx2_lo, q, r, r1, r2, t, twomk, twopk, x_hi;
+	long double x_lo, x2, z;
+	long double x4;
+	int k, n, n2;
+	uint16_t hx, ix;
+
+	DOPRINT_START(&x);
+
+	/* Filter out exceptional cases. */
+	u.e = x;
+	hx = u.xbits.expsign;
+	ix = hx & 0x7fff;
+	if (ix >= BIAS + 6) {		/* |x| >= 64 or x is NaN */
+		if (ix == BIAS + LDBL_MAX_EXP) {
+			if (hx & 0x8000)  /* x is -Inf, -NaN or unsupported */
+				RETURNP(-1 / x - 1);
+			RETURNP(x + x);	/* x is +Inf, +NaN or unsupported */
+		}
+		if (x > o_threshold)
+			RETURNP(huge * huge);
+		/*
+		 * expm1l() never underflows, but it must avoid
+		 * unrepresentable large negative exponents.  We used a
+		 * much smaller threshold for large |x| above than in
+		 * expl() so as to handle not so large negative exponents
+		 * in the same way as large ones here.
+		 */
+		if (hx & 0x8000)	/* x <= -64 */
+			RETURN2P(tiny, -1);	/* good for x < -65ln2 - eps */
+	}
+
+	ENTERI();
+
+	if (T1 < x && x < T2) {
+		if (ix < BIAS - 74) {	/* |x| < 0x1p-74 (includes pseudos) */
+			/* x (rounded) with inexact if x != 0: */
+			RETURNPI(x == 0 ? x :
+			    (0x1p100 * x + fabsl(x)) * 0x1p-100);
+		}
+
+		x2 = x * x;
+		x4 = x2 * x2;
+		q = x4 * (x2 * (x4 *
+		    /*
+		     * XXX the number of terms is no longer good for
+		     * pairwise grouping of all except B3, and the
+		     * grouping is no longer from highest down.
+		     */
+		    (x2 *            B12  + (x * B11 + B10)) +
+		    (x2 * (x * B9 +  B8) +  (x * B7 +  B6))) +
+			  (x * B5 +  B4.e)) + x2 * x * B3.e;
+
+		x_hi = (float)x;
+		x_lo = x - x_hi;
+		hx2_hi = x_hi * x_hi / 2;
+		hx2_lo = x_lo * (x + x_hi) / 2;
+		if (ix >= BIAS - 7)
+			RETURN2PI(hx2_hi + x_hi, hx2_lo + x_lo + q);
+		else
+			RETURN2PI(x, hx2_lo + q + hx2_hi);
+	}
+
+	/* Reduce x to (k*ln2 + endpoint[n2] + r1 + r2). */
+	/* Use a specialized rint() to get fn.  Assume round-to-nearest. */
+	fn = x * INV_L + 0x1.8p63 - 0x1.8p63;
+#if defined(HAVE_EFFICIENT_IRINTL)
+	n = irintl(fn);
+#elif defined(HAVE_EFFICIENT_IRINT)
+	n = irint(fn);
+#else
+	n = (int)fn;
+#endif
+	n2 = (unsigned)n % INTERVALS;
+	k = n >> LOG2_INTERVALS;
+	r1 = x - fn * L1;
+	r2 = fn * -L2;
+	r = r1 + r2;
+
+	/* Prepare scale factor. */
+	v.e = 1;
+	v.xbits.expsign = BIAS + k;
+	twopk = v.e;
+
+	/*
+	 * Evaluate lower terms of
+	 * expl(endpoint[n2] + r1 + r2) = tbl[n2] * expl(r1 + r2).
+	 */
+	z = r * r;
+	q = r2 + z * (A2 + r * A3) + z * z * (A4 + r * A5) + z * z * z * A6;
+
+	t = (long double)tbl[n2].lo + tbl[n2].hi;
+
+	if (k == 0) {
+		t = SUM2P(tbl[n2].hi - 1, tbl[n2].lo * (r1 + 1) + t * q +
+		    tbl[n2].hi * r1);
+		RETURNI(t);
+	}
+	if (k == -1) {
+		t = SUM2P(tbl[n2].hi - 2, tbl[n2].lo * (r1 + 1) + t * q +
+		    tbl[n2].hi * r1);
+		RETURNI(t / 2);
+	}
+	if (k < -7) {
+		t = SUM2P(tbl[n2].hi, tbl[n2].lo + t * (q + r1));
+		RETURNI(t * twopk - 1);
+	}
+	if (k > 2 * LDBL_MANT_DIG - 1) {
+		t = SUM2P(tbl[n2].hi, tbl[n2].lo + t * (q + r1));
+		if (k == LDBL_MAX_EXP)
+			RETURNI(t * 2 * 0x1p16383L - 1);
+		RETURNI(t * twopk - 1);
+	}
+
+	v.xbits.expsign = BIAS - k;
+	twomk = v.e;
+
+	if (k > LDBL_MANT_DIG - 1)
+		t = SUM2P(tbl[n2].hi, tbl[n2].lo - twomk + t * (q + r1));
+	else
+		t = SUM2P(tbl[n2].hi - twomk, tbl[n2].lo + t * (q + r1));
+	RETURNI(t * twopk);
+}

+ 717 - 0
ld80/s_logl.c

@@ -0,0 +1,717 @@
+/*-
+ * Copyright (c) 2007-2013 Bruce D. Evans
+ * 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$");
+
+/**
+ * Implementation of the natural logarithm of x for Intel 80-bit format.
+ *
+ * First decompose x into its base 2 representation:
+ *
+ *    log(x) = log(X * 2**k), where X is in [1, 2)
+ *           = log(X) + k * log(2).
+ *
+ * Let X = X_i + e, where X_i is the center of one of the intervals
+ * [-1.0/256, 1.0/256), [1.0/256, 3.0/256), .... [2.0-1.0/256, 2.0+1.0/256)
+ * and X is in this interval.  Then
+ *
+ *    log(X) = log(X_i + e)
+ *           = log(X_i * (1 + e / X_i))
+ *           = log(X_i) + log(1 + e / X_i).
+ *
+ * The values log(X_i) are tabulated below.  Let d = e / X_i and use
+ *
+ *    log(1 + d) = p(d)
+ *
+ * where p(d) = d - 0.5*d*d + ... is a special minimax polynomial of
+ * suitably high degree.
+ *
+ * To get sufficiently small roundoff errors, k * log(2), log(X_i), and
+ * sometimes (if |k| is not large) the first term in p(d) must be evaluated
+ * and added up in extra precision.  Extra precision is not needed for the
+ * rest of p(d).  In the worst case when k = 0 and log(X_i) is 0, the final
+ * error is controlled mainly by the error in the second term in p(d).  The
+ * error in this term itself is at most 0.5 ulps from the d*d operation in
+ * it.  The error in this term relative to the first term is thus at most
+ * 0.5 * |-0.5| * |d| < 1.0/1024 ulps.  We aim for an accumulated error of
+ * at most twice this at the point of the final rounding step.  Thus the
+ * final error should be at most 0.5 + 1.0/512 = 0.5020 ulps.  Exhaustive
+ * testing of a float variant of this function showed a maximum final error
+ * of 0.5008 ulps.  Non-exhaustive testing of a double variant of this
+ * function showed a maximum final error of 0.5078 ulps (near 1+1.0/256).
+ *
+ * We made the maximum of |d| (and thus the total relative error and the
+ * degree of p(d)) small by using a large number of intervals.  Using
+ * centers of intervals instead of endpoints reduces this maximum by a
+ * factor of 2 for a given number of intervals.  p(d) is special only
+ * in beginning with the Taylor coefficients 0 + 1*d, which tends to happen
+ * naturally.  The most accurate minimax polynomial of a given degree might
+ * be different, but then we wouldn't want it since we would have to do
+ * extra work to avoid roundoff error (especially for P0*d instead of d).
+ */
+
+#ifdef DEBUG
+#include <assert.h>
+#include <fenv.h>
+#endif
+
+#ifdef __i386__
+#include <ieeefp.h>
+#endif
+
+#include "fpmath.h"
+#include "math.h"
+#define	i386_SSE_GOOD
+#ifndef NO_STRUCT_RETURN
+#define	STRUCT_RETURN
+#endif
+#include "math_private.h"
+
+#if !defined(NO_UTAB) && !defined(NO_UTABL)
+#define	USE_UTAB
+#endif
+
+/*
+ * Domain [-0.005280, 0.004838], range ~[-5.1736e-22, 5.1738e-22]:
+ * |log(1 + d)/d - p(d)| < 2**-70.7
+ */
+static const double
+P2 = -0.5,
+P3 =  3.3333333333333359e-1,		/*  0x1555555555555a.0p-54 */
+P4 = -2.5000000000004424e-1,		/* -0x1000000000031d.0p-54 */
+P5 =  1.9999999992970016e-1,		/*  0x1999999972f3c7.0p-55 */
+P6 = -1.6666666072191585e-1,		/* -0x15555548912c09.0p-55 */
+P7 =  1.4286227413310518e-1,		/*  0x12494f9d9def91.0p-55 */
+P8 = -1.2518388626763144e-1;		/* -0x1006068cc0b97c.0p-55 */
+
+static volatile const double zero = 0;
+
+#define	INTERVALS	128
+#define	LOG2_INTERVALS	7
+#define	TSIZE		(INTERVALS + 1)
+#define	G(i)		(T[(i)].G)
+#define	F_hi(i)		(T[(i)].F_hi)
+#define	F_lo(i)		(T[(i)].F_lo)
+#define	ln2_hi		F_hi(TSIZE - 1)
+#define	ln2_lo		F_lo(TSIZE - 1)
+#define	E(i)		(U[(i)].E)
+#define	H(i)		(U[(i)].H)
+
+static const struct {
+	float	G;			/* 1/(1 + i/128) rounded to 8/9 bits */
+	float	F_hi;			/* log(1 / G_i) rounded (see below) */
+	double	F_lo;			/* next 53 bits for log(1 / G_i) */
+} T[TSIZE] = {
+	/*
+	 * ln2_hi and each F_hi(i) are rounded to a number of bits that
+	 * makes F_hi(i) + dk*ln2_hi exact for all i and all dk.
+	 *
+	 * The last entry (for X just below 2) is used to define ln2_hi
+	 * and ln2_lo, to ensure that F_hi(i) and F_lo(i) cancel exactly
+	 * with dk*ln2_hi and dk*ln2_lo, respectively, when dk = -1.
+	 * This is needed for accuracy when x is just below 1.  (To avoid
+	 * special cases, such x are "reduced" strangely to X just below
+	 * 2 and dk = -1, and then the exact cancellation is needed
+	 * because any the error from any non-exactness would be too
+	 * large).
+	 *
+	 * We want to share this table between double precision and ld80,
+	 * so the relevant range of dk is the larger one of ld80
+	 * ([-16445, 16383]) and the relevant exactness requirement is
+	 * the stricter one of double precision.  The maximum number of
+	 * bits in F_hi(i) that works is very dependent on i but has
+	 * a minimum of 33.  We only need about 12 bits in F_hi(i) for
+	 * it to provide enough extra precision in double precision (11
+	 * more than that are required for ld80).
+	 *
+	 * We round F_hi(i) to 24 bits so that it can have type float,
+	 * mainly to minimize the size of the table.  Using all 24 bits
+	 * in a float for it automatically satisfies the above constraints.
+	 */
+	 0x800000.0p-23,  0,               0,
+	 0xfe0000.0p-24,  0x8080ac.0p-30, -0x14ee431dae6675.0p-84,
+	 0xfc0000.0p-24,  0x8102b3.0p-29, -0x1db29ee2d83718.0p-84,
+	 0xfa0000.0p-24,  0xc24929.0p-29,  0x1191957d173698.0p-83,
+	 0xf80000.0p-24,  0x820aec.0p-28,  0x13ce8888e02e79.0p-82,
+	 0xf60000.0p-24,  0xa33577.0p-28, -0x17a4382ce6eb7c.0p-82,
+	 0xf48000.0p-24,  0xbc42cb.0p-28, -0x172a21161a1076.0p-83,
+	 0xf30000.0p-24,  0xd57797.0p-28, -0x1e09de07cb9589.0p-82,
+	 0xf10000.0p-24,  0xf7518e.0p-28,  0x1ae1eec1b036c5.0p-91,
+	 0xef0000.0p-24,  0x8cb9df.0p-27, -0x1d7355325d560e.0p-81,
+	 0xed8000.0p-24,  0x999ec0.0p-27, -0x1f9f02d256d503.0p-82,
+	 0xec0000.0p-24,  0xa6988b.0p-27, -0x16fc0a9d12c17a.0p-83,
+	 0xea0000.0p-24,  0xb80698.0p-27,  0x15d581c1e8da9a.0p-81,
+	 0xe80000.0p-24,  0xc99af3.0p-27, -0x1535b3ba8f150b.0p-83,
+	 0xe70000.0p-24,  0xd273b2.0p-27,  0x163786f5251af0.0p-85,
+	 0xe50000.0p-24,  0xe442c0.0p-27,  0x1bc4b2368e32d5.0p-84,
+	 0xe38000.0p-24,  0xf1b83f.0p-27,  0x1c6090f684e676.0p-81,
+	 0xe20000.0p-24,  0xff448a.0p-27, -0x1890aa69ac9f42.0p-82,
+	 0xe08000.0p-24,  0x8673f6.0p-26,  0x1b9985194b6b00.0p-80,
+	 0xdf0000.0p-24,  0x8d515c.0p-26, -0x1dc08d61c6ef1e.0p-83,
+	 0xdd8000.0p-24,  0x943a9e.0p-26, -0x1f72a2dac729b4.0p-82,
+	 0xdc0000.0p-24,  0x9b2fe6.0p-26, -0x1fd4dfd3a0afb9.0p-80,
+	 0xda8000.0p-24,  0xa2315d.0p-26, -0x11b26121629c47.0p-82,
+	 0xd90000.0p-24,  0xa93f2f.0p-26,  0x1286d633e8e569.0p-81,
+	 0xd78000.0p-24,  0xb05988.0p-26,  0x16128eba936770.0p-84,
+	 0xd60000.0p-24,  0xb78094.0p-26,  0x16ead577390d32.0p-80,
+	 0xd50000.0p-24,  0xbc4c6c.0p-26,  0x151131ccf7c7b7.0p-81,
+	 0xd38000.0p-24,  0xc3890a.0p-26, -0x115e2cd714bd06.0p-80,
+	 0xd20000.0p-24,  0xcad2d7.0p-26, -0x1847f406ebd3b0.0p-82,
+	 0xd10000.0p-24,  0xcfb620.0p-26,  0x1c2259904d6866.0p-81,
+	 0xcf8000.0p-24,  0xd71653.0p-26,  0x1ece57a8d5ae55.0p-80,
+	 0xce0000.0p-24,  0xde843a.0p-26, -0x1f109d4bc45954.0p-81,
+	 0xcd0000.0p-24,  0xe37fde.0p-26,  0x1bc03dc271a74d.0p-81,
+	 0xcb8000.0p-24,  0xeb050c.0p-26, -0x1bf2badc0df842.0p-85,
+	 0xca0000.0p-24,  0xf29878.0p-26, -0x18efededd89fbe.0p-87,
+	 0xc90000.0p-24,  0xf7ad6f.0p-26,  0x1373ff977baa69.0p-81,
+	 0xc80000.0p-24,  0xfcc8e3.0p-26,  0x196766f2fb3283.0p-80,
+	 0xc68000.0p-24,  0x823f30.0p-25,  0x19bd076f7c434e.0p-79,
+	 0xc58000.0p-24,  0x84d52c.0p-25, -0x1a327257af0f46.0p-79,
+	 0xc40000.0p-24,  0x88bc74.0p-25,  0x113f23def19c5a.0p-81,
+	 0xc30000.0p-24,  0x8b5ae6.0p-25,  0x1759f6e6b37de9.0p-79,
+	 0xc20000.0p-24,  0x8dfccb.0p-25,  0x1ad35ca6ed5148.0p-81,
+	 0xc10000.0p-24,  0x90a22b.0p-25,  0x1a1d71a87deba4.0p-79,
+	 0xbf8000.0p-24,  0x94a0d8.0p-25, -0x139e5210c2b731.0p-80,
+	 0xbe8000.0p-24,  0x974f16.0p-25, -0x18f6ebcff3ed73.0p-81,
+	 0xbd8000.0p-24,  0x9a00f1.0p-25, -0x1aa268be39aab7.0p-79,
+	 0xbc8000.0p-24,  0x9cb672.0p-25, -0x14c8815839c566.0p-79,
+	 0xbb0000.0p-24,  0xa0cda1.0p-25,  0x1eaf46390dbb24.0p-81,
+	 0xba0000.0p-24,  0xa38c6e.0p-25,  0x138e20d831f698.0p-81,
+	 0xb90000.0p-24,  0xa64f05.0p-25, -0x1e8d3c41123616.0p-82,
+	 0xb80000.0p-24,  0xa91570.0p-25,  0x1ce28f5f3840b2.0p-80,
+	 0xb70000.0p-24,  0xabdfbb.0p-25, -0x186e5c0a424234.0p-79,
+	 0xb60000.0p-24,  0xaeadef.0p-25, -0x14d41a0b2a08a4.0p-83,
+	 0xb50000.0p-24,  0xb18018.0p-25,  0x16755892770634.0p-79,
+	 0xb40000.0p-24,  0xb45642.0p-25, -0x16395ebe59b152.0p-82,
+	 0xb30000.0p-24,  0xb73077.0p-25,  0x1abc65c8595f09.0p-80,
+	 0xb20000.0p-24,  0xba0ec4.0p-25, -0x1273089d3dad89.0p-79,
+	 0xb10000.0p-24,  0xbcf133.0p-25,  0x10f9f67b1f4bbf.0p-79,
+	 0xb00000.0p-24,  0xbfd7d2.0p-25, -0x109fab90486409.0p-80,
+	 0xaf0000.0p-24,  0xc2c2ac.0p-25, -0x1124680aa43333.0p-79,
+	 0xae8000.0p-24,  0xc439b3.0p-25, -0x1f360cc4710fc0.0p-80,
+	 0xad8000.0p-24,  0xc72afd.0p-25, -0x132d91f21d89c9.0p-80,
+	 0xac8000.0p-24,  0xca20a2.0p-25, -0x16bf9b4d1f8da8.0p-79,
+	 0xab8000.0p-24,  0xcd1aae.0p-25,  0x19deb5ce6a6a87.0p-81,
+	 0xaa8000.0p-24,  0xd0192f.0p-25,  0x1a29fb48f7d3cb.0p-79,
+	 0xaa0000.0p-24,  0xd19a20.0p-25,  0x1127d3c6457f9d.0p-81,
+	 0xa90000.0p-24,  0xd49f6a.0p-25, -0x1ba930e486a0ac.0p-81,
+	 0xa80000.0p-24,  0xd7a94b.0p-25, -0x1b6e645f31549e.0p-79,
+	 0xa70000.0p-24,  0xdab7d0.0p-25,  0x1118a425494b61.0p-80,
+	 0xa68000.0p-24,  0xdc40d5.0p-25,  0x1966f24d29d3a3.0p-80,
+	 0xa58000.0p-24,  0xdf566d.0p-25, -0x1d8e52eb2248f1.0p-82,
+	 0xa48000.0p-24,  0xe270ce.0p-25, -0x1ee370f96e6b68.0p-80,
+	 0xa40000.0p-24,  0xe3ffce.0p-25,  0x1d155324911f57.0p-80,
+	 0xa30000.0p-24,  0xe72179.0p-25, -0x1fe6e2f2f867d9.0p-80,
+	 0xa20000.0p-24,  0xea4812.0p-25,  0x1b7be9add7f4d4.0p-80,
+	 0xa18000.0p-24,  0xebdd3d.0p-25,  0x1b3cfb3f7511dd.0p-79,
+	 0xa08000.0p-24,  0xef0b5b.0p-25, -0x1220de1f730190.0p-79,
+	 0xa00000.0p-24,  0xf0a451.0p-25, -0x176364c9ac81cd.0p-80,
+	 0x9f0000.0p-24,  0xf3da16.0p-25,  0x1eed6b9aafac8d.0p-81,
+	 0x9e8000.0p-24,  0xf576e9.0p-25,  0x1d593218675af2.0p-79,
+	 0x9d8000.0p-24,  0xf8b47c.0p-25, -0x13e8eb7da053e0.0p-84,
+	 0x9d0000.0p-24,  0xfa553f.0p-25,  0x1c063259bcade0.0p-79,
+	 0x9c0000.0p-24,  0xfd9ac5.0p-25,  0x1ef491085fa3c1.0p-79,
+	 0x9b8000.0p-24,  0xff3f8c.0p-25,  0x1d607a7c2b8c53.0p-79,
+	 0x9a8000.0p-24,  0x814697.0p-24, -0x12ad3817004f3f.0p-78,
+	 0x9a0000.0p-24,  0x821b06.0p-24, -0x189fc53117f9e5.0p-81,
+	 0x990000.0p-24,  0x83c5f8.0p-24,  0x14cf15a048907b.0p-79,
+	 0x988000.0p-24,  0x849c7d.0p-24,  0x1cbb1d35fb8287.0p-78,
+	 0x978000.0p-24,  0x864ba6.0p-24,  0x1128639b814f9c.0p-78,
+	 0x970000.0p-24,  0x87244c.0p-24,  0x184733853300f0.0p-79,
+	 0x968000.0p-24,  0x87fdaa.0p-24,  0x109d23aef77dd6.0p-80,
+	 0x958000.0p-24,  0x89b293.0p-24, -0x1a81ef367a59de.0p-78,
+	 0x950000.0p-24,  0x8a8e20.0p-24, -0x121ad3dbb2f452.0p-78,
+	 0x948000.0p-24,  0x8b6a6a.0p-24, -0x1cfb981628af72.0p-79,
+	 0x938000.0p-24,  0x8d253a.0p-24, -0x1d21730ea76cfe.0p-79,
+	 0x930000.0p-24,  0x8e03c2.0p-24,  0x135cc00e566f77.0p-78,
+	 0x928000.0p-24,  0x8ee30d.0p-24, -0x10fcb5df257a26.0p-80,
+	 0x918000.0p-24,  0x90a3ee.0p-24, -0x16e171b15433d7.0p-79,
+	 0x910000.0p-24,  0x918587.0p-24, -0x1d050da07f3237.0p-79,
+	 0x908000.0p-24,  0x9267e7.0p-24,  0x1be03669a5268d.0p-79,
+	 0x8f8000.0p-24,  0x942f04.0p-24,  0x10b28e0e26c337.0p-79,
+	 0x8f0000.0p-24,  0x9513c3.0p-24,  0x1a1d820da57cf3.0p-78,
+	 0x8e8000.0p-24,  0x95f950.0p-24, -0x19ef8f13ae3cf1.0p-79,
+	 0x8e0000.0p-24,  0x96dfab.0p-24, -0x109e417a6e507c.0p-78,
+	 0x8d0000.0p-24,  0x98aed2.0p-24,  0x10d01a2c5b0e98.0p-79,
+	 0x8c8000.0p-24,  0x9997a2.0p-24, -0x1d6a50d4b61ea7.0p-78,
+	 0x8c0000.0p-24,  0x9a8145.0p-24,  0x1b3b190b83f952.0p-78,
+	 0x8b8000.0p-24,  0x9b6bbf.0p-24,  0x13a69fad7e7abe.0p-78,
+	 0x8b0000.0p-24,  0x9c5711.0p-24, -0x11cd12316f576b.0p-78,
+	 0x8a8000.0p-24,  0x9d433b.0p-24,  0x1c95c444b807a2.0p-79,
+	 0x898000.0p-24,  0x9f1e22.0p-24, -0x1b9c224ea698c3.0p-79,
+	 0x890000.0p-24,  0xa00ce1.0p-24,  0x125ca93186cf0f.0p-81,
+	 0x888000.0p-24,  0xa0fc80.0p-24, -0x1ee38a7bc228b3.0p-79,
+	 0x880000.0p-24,  0xa1ed00.0p-24, -0x1a0db876613d20.0p-78,
+	 0x878000.0p-24,  0xa2de62.0p-24,  0x193224e8516c01.0p-79,
+	 0x870000.0p-24,  0xa3d0a9.0p-24,  0x1fa28b4d2541ad.0p-79,
+	 0x868000.0p-24,  0xa4c3d6.0p-24,  0x1c1b5760fb4572.0p-78,
+	 0x858000.0p-24,  0xa6acea.0p-24,  0x1fed5d0f65949c.0p-80,
+	 0x850000.0p-24,  0xa7a2d4.0p-24,  0x1ad270c9d74936.0p-80,
+	 0x848000.0p-24,  0xa899ab.0p-24,  0x199ff15ce53266.0p-79,
+	 0x840000.0p-24,  0xa99171.0p-24,  0x1a19e15ccc45d2.0p-79,
+	 0x838000.0p-24,  0xaa8a28.0p-24, -0x121a14ec532b36.0p-80,
+	 0x830000.0p-24,  0xab83d1.0p-24,  0x1aee319980bff3.0p-79,
+	 0x828000.0p-24,  0xac7e6f.0p-24, -0x18ffd9e3900346.0p-80,
+	 0x820000.0p-24,  0xad7a03.0p-24, -0x1e4db102ce29f8.0p-80,
+	 0x818000.0p-24,  0xae768f.0p-24,  0x17c35c55a04a83.0p-81,
+	 0x810000.0p-24,  0xaf7415.0p-24,  0x1448324047019b.0p-78,
+	 0x808000.0p-24,  0xb07298.0p-24, -0x1750ee3915a198.0p-78,
+	 0x800000.0p-24,  0xb17218.0p-24, -0x105c610ca86c39.0p-81,
+};
+
+#ifdef USE_UTAB
+static const struct {
+	float	H;			/* 1 + i/INTERVALS (exact) */
+	float	E;			/* H(i) * G(i) - 1 (exact) */
+} U[TSIZE] = {
+	 0x800000.0p-23,  0,
+	 0x810000.0p-23, -0x800000.0p-37,
+	 0x820000.0p-23, -0x800000.0p-35,
+	 0x830000.0p-23, -0x900000.0p-34,
+	 0x840000.0p-23, -0x800000.0p-33,
+	 0x850000.0p-23, -0xc80000.0p-33,
+	 0x860000.0p-23, -0xa00000.0p-36,
+	 0x870000.0p-23,  0x940000.0p-33,
+	 0x880000.0p-23,  0x800000.0p-35,
+	 0x890000.0p-23, -0xc80000.0p-34,
+	 0x8a0000.0p-23,  0xe00000.0p-36,
+	 0x8b0000.0p-23,  0x900000.0p-33,
+	 0x8c0000.0p-23, -0x800000.0p-35,
+	 0x8d0000.0p-23, -0xe00000.0p-33,
+	 0x8e0000.0p-23,  0x880000.0p-33,
+	 0x8f0000.0p-23, -0xa80000.0p-34,
+	 0x900000.0p-23, -0x800000.0p-35,
+	 0x910000.0p-23,  0x800000.0p-37,
+	 0x920000.0p-23,  0x900000.0p-35,
+	 0x930000.0p-23,  0xd00000.0p-35,
+	 0x940000.0p-23,  0xe00000.0p-35,
+	 0x950000.0p-23,  0xc00000.0p-35,
+	 0x960000.0p-23,  0xe00000.0p-36,
+	 0x970000.0p-23, -0x800000.0p-38,
+	 0x980000.0p-23, -0xc00000.0p-35,
+	 0x990000.0p-23, -0xd00000.0p-34,
+	 0x9a0000.0p-23,  0x880000.0p-33,
+	 0x9b0000.0p-23,  0xe80000.0p-35,
+	 0x9c0000.0p-23, -0x800000.0p-35,
+	 0x9d0000.0p-23,  0xb40000.0p-33,
+	 0x9e0000.0p-23,  0x880000.0p-34,
+	 0x9f0000.0p-23, -0xe00000.0p-35,
+	 0xa00000.0p-23,  0x800000.0p-33,
+	 0xa10000.0p-23, -0x900000.0p-36,
+	 0xa20000.0p-23, -0xb00000.0p-33,
+	 0xa30000.0p-23, -0xa00000.0p-36,
+	 0xa40000.0p-23,  0x800000.0p-33,
+	 0xa50000.0p-23, -0xf80000.0p-35,
+	 0xa60000.0p-23,  0x880000.0p-34,
+	 0xa70000.0p-23, -0x900000.0p-33,
+	 0xa80000.0p-23, -0x800000.0p-35,
+	 0xa90000.0p-23,  0x900000.0p-34,
+	 0xaa0000.0p-23,  0xa80000.0p-33,
+	 0xab0000.0p-23, -0xac0000.0p-34,
+	 0xac0000.0p-23, -0x800000.0p-37,
+	 0xad0000.0p-23,  0xf80000.0p-35,
+	 0xae0000.0p-23,  0xf80000.0p-34,
+	 0xaf0000.0p-23, -0xac0000.0p-33,
+	 0xb00000.0p-23, -0x800000.0p-33,
+	 0xb10000.0p-23, -0xb80000.0p-34,
+	 0xb20000.0p-23, -0x800000.0p-34,
+	 0xb30000.0p-23, -0xb00000.0p-35,
+	 0xb40000.0p-23, -0x800000.0p-35,
+	 0xb50000.0p-23, -0xe00000.0p-36,
+	 0xb60000.0p-23, -0x800000.0p-35,
+	 0xb70000.0p-23, -0xb00000.0p-35,
+	 0xb80000.0p-23, -0x800000.0p-34,
+	 0xb90000.0p-23, -0xb80000.0p-34,
+	 0xba0000.0p-23, -0x800000.0p-33,
+	 0xbb0000.0p-23, -0xac0000.0p-33,
+	 0xbc0000.0p-23,  0x980000.0p-33,
+	 0xbd0000.0p-23,  0xbc0000.0p-34,
+	 0xbe0000.0p-23,  0xe00000.0p-36,
+	 0xbf0000.0p-23, -0xb80000.0p-35,
+	 0xc00000.0p-23, -0x800000.0p-33,
+	 0xc10000.0p-23,  0xa80000.0p-33,
+	 0xc20000.0p-23,  0x900000.0p-34,
+	 0xc30000.0p-23, -0x800000.0p-35,
+	 0xc40000.0p-23, -0x900000.0p-33,
+	 0xc50000.0p-23,  0x820000.0p-33,
+	 0xc60000.0p-23,  0x800000.0p-38,
+	 0xc70000.0p-23, -0x820000.0p-33,
+	 0xc80000.0p-23,  0x800000.0p-33,
+	 0xc90000.0p-23, -0xa00000.0p-36,
+	 0xca0000.0p-23, -0xb00000.0p-33,
+	 0xcb0000.0p-23,  0x840000.0p-34,
+	 0xcc0000.0p-23, -0xd00000.0p-34,
+	 0xcd0000.0p-23,  0x800000.0p-33,
+	 0xce0000.0p-23, -0xe00000.0p-35,
+	 0xcf0000.0p-23,  0xa60000.0p-33,
+	 0xd00000.0p-23, -0x800000.0p-35,
+	 0xd10000.0p-23,  0xb40000.0p-33,
+	 0xd20000.0p-23, -0x800000.0p-35,
+	 0xd30000.0p-23,  0xaa0000.0p-33,
+	 0xd40000.0p-23, -0xe00000.0p-35,
+	 0xd50000.0p-23,  0x880000.0p-33,
+	 0xd60000.0p-23, -0xd00000.0p-34,
+	 0xd70000.0p-23,  0x9c0000.0p-34,
+	 0xd80000.0p-23, -0xb00000.0p-33,
+	 0xd90000.0p-23, -0x800000.0p-38,
+	 0xda0000.0p-23,  0xa40000.0p-33,
+	 0xdb0000.0p-23, -0xdc0000.0p-34,
+	 0xdc0000.0p-23,  0xc00000.0p-35,
+	 0xdd0000.0p-23,  0xca0000.0p-33,
+	 0xde0000.0p-23, -0xb80000.0p-34,
+	 0xdf0000.0p-23,  0xd00000.0p-35,
+	 0xe00000.0p-23,  0xc00000.0p-33,
+	 0xe10000.0p-23, -0xf40000.0p-34,
+	 0xe20000.0p-23,  0x800000.0p-37,
+	 0xe30000.0p-23,  0x860000.0p-33,
+	 0xe40000.0p-23, -0xc80000.0p-33,
+	 0xe50000.0p-23, -0xa80000.0p-34,
+	 0xe60000.0p-23,  0xe00000.0p-36,
+	 0xe70000.0p-23,  0x880000.0p-33,
+	 0xe80000.0p-23, -0xe00000.0p-33,
+	 0xe90000.0p-23, -0xfc0000.0p-34,
+	 0xea0000.0p-23, -0x800000.0p-35,
+	 0xeb0000.0p-23,  0xe80000.0p-35,
+	 0xec0000.0p-23,  0x900000.0p-33,
+	 0xed0000.0p-23,  0xe20000.0p-33,
+	 0xee0000.0p-23, -0xac0000.0p-33,
+	 0xef0000.0p-23, -0xc80000.0p-34,
+	 0xf00000.0p-23, -0x800000.0p-35,
+	 0xf10000.0p-23,  0x800000.0p-35,
+	 0xf20000.0p-23,  0xb80000.0p-34,
+	 0xf30000.0p-23,  0x940000.0p-33,
+	 0xf40000.0p-23,  0xc80000.0p-33,
+	 0xf50000.0p-23, -0xf20000.0p-33,
+	 0xf60000.0p-23, -0xc80000.0p-33,
+	 0xf70000.0p-23, -0xa20000.0p-33,
+	 0xf80000.0p-23, -0x800000.0p-33,
+	 0xf90000.0p-23, -0xc40000.0p-34,
+	 0xfa0000.0p-23, -0x900000.0p-34,
+	 0xfb0000.0p-23, -0xc80000.0p-35,
+	 0xfc0000.0p-23, -0x800000.0p-35,
+	 0xfd0000.0p-23, -0x900000.0p-36,
+	 0xfe0000.0p-23, -0x800000.0p-37,
+	 0xff0000.0p-23, -0x800000.0p-39,
+	 0x800000.0p-22,  0,
+};
+#endif /* USE_UTAB */
+
+#ifdef STRUCT_RETURN
+#define	RETURN1(rp, v) do {	\
+	(rp)->hi = (v);		\
+	(rp)->lo_set = 0;	\
+	return;			\
+} while (0)
+
+#define	RETURN2(rp, h, l) do {	\
+	(rp)->hi = (h);		\
+	(rp)->lo = (l);		\
+	(rp)->lo_set = 1;	\
+	return;			\
+} while (0)
+
+struct ld {
+	long double hi;
+	long double lo;
+	int	lo_set;
+};
+#else
+#define	RETURN1(rp, v)	RETURNF(v)
+#define	RETURN2(rp, h, l)	RETURNI((h) + (l))
+#endif
+
+#ifdef STRUCT_RETURN
+static inline __always_inline void
+k_logl(long double x, struct ld *rp)
+#else
+long double
+logl(long double x)
+#endif
+{
+	long double d, dk, val_hi, val_lo, z;
+	uint64_t ix, lx;
+	int i, k;
+	uint16_t hx;
+
+	EXTRACT_LDBL80_WORDS(hx, lx, x);
+	k = -16383;
+#if 0 /* Hard to do efficiently.  Don't do it until we support all modes. */
+	if (x == 1)
+		RETURN1(rp, 0);		/* log(1) = +0 in all rounding modes */
+#endif
+	if (hx == 0 || hx >= 0x8000) {	/* zero, negative or subnormal? */
+		if (((hx & 0x7fff) | lx) == 0)
+			RETURN1(rp, -1 / zero);	/* log(+-0) = -Inf */
+		if (hx != 0)
+			/* log(neg or [pseudo-]NaN) = qNaN: */
+			RETURN1(rp, (x - x) / zero);
+		x *= 0x1.0p65;		/* subnormal; scale up x */
+					/* including pseudo-subnormals */
+		EXTRACT_LDBL80_WORDS(hx, lx, x);
+		k = -16383 - 65;
+	} else if (hx >= 0x7fff || (lx & 0x8000000000000000ULL) == 0)
+		RETURN1(rp, x + x);	/* log(Inf or NaN) = Inf or qNaN */
+					/* log(pseudo-Inf) = qNaN */
+					/* log(pseudo-NaN) = qNaN */
+					/* log(unnormal) = qNaN */
+#ifndef STRUCT_RETURN
+	ENTERI();
+#endif
+	k += hx;
+	ix = lx & 0x7fffffffffffffffULL;
+	dk = k;
+
+	/* Scale x to be in [1, 2). */
+	SET_LDBL_EXPSIGN(x, 0x3fff);
+
+	/* 0 <= i <= INTERVALS: */
+#define	L2I	(64 - LOG2_INTERVALS)
+	i = (ix + (1LL << (L2I - 2))) >> (L2I - 1);
+
+	/*
+	 * -0.005280 < d < 0.004838.  In particular, the infinite-
+	 * precision |d| is <= 2**-7.  Rounding of G(i) to 8 bits
+	 * ensures that d is representable without extra precision for
+	 * this bound on |d| (since when this calculation is expressed
+	 * as x*G(i)-1, the multiplication needs as many extra bits as
+	 * G(i) has and the subtraction cancels 8 bits).  But for
+	 * most i (107 cases out of 129), the infinite-precision |d|
+	 * is <= 2**-8.  G(i) is rounded to 9 bits for such i to give
+	 * better accuracy (this works by improving the bound on |d|,
+	 * which in turn allows rounding to 9 bits in more cases).
+	 * This is only important when the original x is near 1 -- it
+	 * lets us avoid using a special method to give the desired
+	 * accuracy for such x.
+	 */
+	if (0)
+		d = x * G(i) - 1;
+	else {
+#ifdef USE_UTAB
+		d = (x - H(i)) * G(i) + E(i);
+#else
+		long double x_hi, x_lo;
+		float fx_hi;
+
+		/*
+		 * Split x into x_hi + x_lo to calculate x*G(i)-1 exactly.
+		 * G(i) has at most 9 bits, so the splitting point is not
+		 * critical.
+		 */
+		SET_FLOAT_WORD(fx_hi, (lx >> 40) | 0x3f800000);
+		x_hi = fx_hi;
+		x_lo = x - x_hi;
+		d = x_hi * G(i) - 1 + x_lo * G(i);
+#endif
+	}
+
+	/*
+	 * Our algorithm depends on exact cancellation of F_lo(i) and
+	 * F_hi(i) with dk*ln_2_lo and dk*ln2_hi when k is -1 and i is
+	 * at the end of the table.  This and other technical complications
+	 * make it difficult to avoid the double scaling in (dk*ln2) *
+	 * log(base) for base != e without losing more accuracy and/or
+	 * efficiency than is gained.
+	 */
+	z = d * d;
+	val_lo = z * d * z * (z * (d * P8 + P7) + (d * P6 + P5)) +
+	    (F_lo(i) + dk * ln2_lo + z * d * (d * P4 + P3)) + z * P2;
+	val_hi = d;
+#ifdef DEBUG
+	if (fetestexcept(FE_UNDERFLOW))
+		breakpoint();
+#endif
+
+	_3sumF(val_hi, val_lo, F_hi(i) + dk * ln2_hi);
+	RETURN2(rp, val_hi, val_lo);
+}
+
+long double
+log1pl(long double x)
+{
+	long double d, d_hi, d_lo, dk, f_lo, val_hi, val_lo, z;
+	long double f_hi, twopminusk;
+	uint64_t ix, lx;
+	int i, k;
+	int16_t ax, hx;
+
+	DOPRINT_START(&x);
+	EXTRACT_LDBL80_WORDS(hx, lx, x);
+	if (hx < 0x3fff) {		/* x < 1, or x neg NaN */
+		ax = hx & 0x7fff;
+		if (ax >= 0x3fff) {	/* x <= -1, or x neg NaN */
+			if (ax == 0x3fff && lx == 0x8000000000000000ULL)
+				RETURNP(-1 / zero);	/* log1p(-1) = -Inf */
+			/* log1p(x < 1, or x [pseudo-]NaN) = qNaN: */
+			RETURNP((x - x) / (x - x));
+		}
+		if (ax <= 0x3fbe) {	/* |x| < 2**-64 */
+			if ((int)x == 0)
+				RETURNP(x);	/* x with inexact if x != 0 */
+		}
+		f_hi = 1;
+		f_lo = x;
+	} else if (hx >= 0x7fff) {	/* x +Inf or non-neg NaN */
+		RETURNP(x + x);		/* log1p(Inf or NaN) = Inf or qNaN */
+					/* log1p(pseudo-Inf) = qNaN */
+					/* log1p(pseudo-NaN) = qNaN */
+					/* log1p(unnormal) = qNaN */
+	} else if (hx < 0x407f) {	/* 1 <= x < 2**128 */
+		f_hi = x;
+		f_lo = 1;
+	} else {			/* 2**128 <= x < +Inf */
+		f_hi = x;
+		f_lo = 0;		/* avoid underflow of the P5 term */
+	}
+	ENTERI();
+	x = f_hi + f_lo;
+	f_lo = (f_hi - x) + f_lo;
+
+	EXTRACT_LDBL80_WORDS(hx, lx, x);
+	k = -16383;
+
+	k += hx;
+	ix = lx & 0x7fffffffffffffffULL;
+	dk = k;
+
+	SET_LDBL_EXPSIGN(x, 0x3fff);
+	twopminusk = 1;
+	SET_LDBL_EXPSIGN(twopminusk, 0x7ffe - (hx & 0x7fff));
+	f_lo *= twopminusk;
+
+	i = (ix + (1LL << (L2I - 2))) >> (L2I - 1);
+
+	/*
+	 * x*G(i)-1 (with a reduced x) can be represented exactly, as
+	 * above, but now we need to evaluate the polynomial on d =
+	 * (x+f_lo)*G(i)-1 and extra precision is needed for that.
+	 * Since x+x_lo is a hi+lo decomposition and subtracting 1
+	 * doesn't lose too many bits, an inexact calculation for
+	 * f_lo*G(i) is good enough.
+	 */
+	if (0)
+		d_hi = x * G(i) - 1;
+	else {
+#ifdef USE_UTAB
+		d_hi = (x - H(i)) * G(i) + E(i);
+#else
+		long double x_hi, x_lo;
+		float fx_hi;
+
+		SET_FLOAT_WORD(fx_hi, (lx >> 40) | 0x3f800000);
+		x_hi = fx_hi;
+		x_lo = x - x_hi;
+		d_hi = x_hi * G(i) - 1 + x_lo * G(i);
+#endif
+	}
+	d_lo = f_lo * G(i);
+
+	/*
+	 * This is _2sumF(d_hi, d_lo) inlined.  The condition
+	 * (d_hi == 0 || |d_hi| >= |d_lo|) for using _2sumF() is not
+	 * always satisifed, so it is not clear that this works, but
+	 * it works in practice.  It works even if it gives a wrong
+	 * normalized d_lo, since |d_lo| > |d_hi| implies that i is
+	 * nonzero and d is tiny, so the F(i) term dominates d_lo.
+	 * In float precision:
+	 * (By exhaustive testing, the worst case is d_hi = 0x1.bp-25.
+	 * And if d is only a little tinier than that, we would have
+	 * another underflow problem for the P3 term; this is also ruled
+	 * out by exhaustive testing.)
+	 */
+	d = d_hi + d_lo;
+	d_lo = d_hi - d + d_lo;
+	d_hi = d;
+
+	z = d * d;
+	val_lo = z * d * z * (z * (d * P8 + P7) + (d * P6 + P5)) +
+	    (F_lo(i) + dk * ln2_lo + d_lo + z * d * (d * P4 + P3)) + z * P2;
+	val_hi = d_hi;
+#ifdef DEBUG
+	if (fetestexcept(FE_UNDERFLOW))
+		breakpoint();
+#endif
+
+	_3sumF(val_hi, val_lo, F_hi(i) + dk * ln2_hi);
+	RETURN2PI(val_hi, val_lo);
+}
+
+#ifdef STRUCT_RETURN
+
+long double
+logl(long double x)
+{
+	struct ld r;
+
+	ENTERI();
+	DOPRINT_START(&x);
+	k_logl(x, &r);
+	RETURNSPI(&r);
+}
+
+static const double
+invln10_hi =  4.3429448190317999e-1,		/*  0x1bcb7b1526e000.0p-54 */
+invln10_lo =  7.1842412889749798e-14,		/*  0x1438ca9aadd558.0p-96 */
+invln2_hi =  1.4426950408887933e0,		/*  0x171547652b8000.0p-52 */
+invln2_lo =  1.7010652264631490e-13;		/*  0x17f0bbbe87fed0.0p-95 */
+
+long double
+log10l(long double x)
+{
+	struct ld r;
+	long double hi, lo;
+
+	ENTERI();
+	DOPRINT_START(&x);
+	k_logl(x, &r);
+	if (!r.lo_set)
+		RETURNPI(r.hi);
+	_2sumF(r.hi, r.lo);
+	hi = (float)r.hi;
+	lo = r.lo + (r.hi - hi);
+	RETURN2PI(invln10_hi * hi,
+	    (invln10_lo + invln10_hi) * lo + invln10_lo * hi);
+}
+
+long double
+log2l(long double x)
+{
+	struct ld r;
+	long double hi, lo;
+
+	ENTERI();
+	DOPRINT_START(&x);
+	k_logl(x, &r);
+	if (!r.lo_set)
+		RETURNPI(r.hi);
+	_2sumF(r.hi, r.lo);
+	hi = (float)r.hi;
+	lo = r.lo + (r.hi - hi);
+	RETURN2PI(invln2_hi * hi,
+	    (invln2_lo + invln2_hi) * lo + invln2_lo * hi);
+}
+
+#endif /* STRUCT_RETURN */

+ 5 - 4
ld80/s_nanl.c

@@ -23,14 +23,15 @@
  * 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 $
+ * $FreeBSD$
  */
 
-#include <openlibm_math.h>
+#include <math.h>
 
-#include "math_private.h"
+#include "fpmath.h"
+#include "../src/math_private.h"
 
-DLLEXPORT long double
+long double
 nanl(const char *s)
 {
 	union {

+ 2 - 2
src/Make.files

@@ -30,7 +30,7 @@ $(CUR_SRCS) = common.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
+	w_cabs.c w_cabsf.c digittoint.c
 
 ifneq ($(OS), WINNT)
 $(CUR_SRCS) += s_nan.c
@@ -39,7 +39,7 @@ endif
 ifneq ($(ARCH), arm)
 ifneq ($(ARCH), powerpc)
 # C99 long double functions
-$(CUR_SRCS) +=	s_copysignl.c s_fabsl.c s_llrintl.c s_lrintl.c s_modfl.c
+$(CUR_SRCS) +=	s_copysignl.c s_fabsl.c s_llrintl.c s_lrintl.c s_modfl.c s_roundl.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 \

+ 67 - 0
src/arm_fpmath.h

@@ -0,0 +1,67 @@
+/*-
+ * 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$
+ */
+
+#if defined(__VFP_FP__) || defined(__ARM_EABI__)
+#define	_IEEE_WORD_ORDER	_BYTE_ORDER
+#else
+#define	_IEEE_WORD_ORDER	_BIG_ENDIAN
+#endif
+
+union IEEEl2bits {
+	long double	e;
+	struct {
+#if _BYTE_ORDER == _LITTLE_ENDIAN
+#if _IEEE_WORD_ORDER == _LITTLE_ENDIAN
+		unsigned int	manl	:32;
+#endif
+		unsigned int	manh	:20;
+		unsigned int	exp	:11;
+		unsigned int	sign	:1;
+#if _IEEE_WORD_ORDER == _BIG_ENDIAN
+		unsigned int	manl	:32;
+#endif
+#else	/* _BYTE_ORDER == _LITTLE_ENDIAN */
+		unsigned int		sign	:1;
+		unsigned int		exp	:11;
+		unsigned int		manh	:20;
+		unsigned int		manl	:32;
+#endif
+	} bits;
+};
+
+#define	LDBL_NBIT	0
+#define	LDBL_IMPLICIT_NBIT
+#define	mask_nbit_l(u)	((void)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)

+ 639 - 0
src/catrig.c

@@ -0,0 +1,639 @@
+/*-
+ * Copyright (c) 2012 Stephen Montgomery-Smith <stephen@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$");
+
+#include <complex.h>
+#include <float.h>
+
+#include "math.h"
+#include "math_private.h"
+
+#undef isinf
+#define isinf(x)	(fabs(x) == INFINITY)
+#undef isnan
+#define isnan(x)	((x) != (x))
+#define	raise_inexact()	do { volatile float junk = 1 + tiny; } while(0)
+#undef signbit
+#define signbit(x)	(__builtin_signbit(x))
+
+/* We need that DBL_EPSILON^2/128 is larger than FOUR_SQRT_MIN. */
+static const double
+A_crossover =		10, /* Hull et al suggest 1.5, but 10 works better */
+B_crossover =		0.6417,			/* suggested by Hull et al */
+FOUR_SQRT_MIN =		0x1p-509,		/* >= 4 * sqrt(DBL_MIN) */
+QUARTER_SQRT_MAX =	0x1p509,		/* <= sqrt(DBL_MAX) / 4 */
+m_e =			2.7182818284590452e0,	/*  0x15bf0a8b145769.0p-51 */
+m_ln2 =			6.9314718055994531e-1,	/*  0x162e42fefa39ef.0p-53 */
+pio2_hi =		1.5707963267948966e0,	/*  0x1921fb54442d18.0p-52 */
+RECIP_EPSILON =		1 / DBL_EPSILON,
+SQRT_3_EPSILON =	2.5809568279517849e-8,	/*  0x1bb67ae8584caa.0p-78 */
+SQRT_6_EPSILON =	3.6500241499888571e-8,	/*  0x13988e1409212e.0p-77 */
+SQRT_MIN =		0x1p-511;		/* >= sqrt(DBL_MIN) */
+
+static const volatile double
+pio2_lo =		6.1232339957367659e-17;	/*  0x11a62633145c07.0p-106 */
+static const volatile float
+tiny =			0x1p-100; 
+
+static double complex clog_for_large_values(double complex z);
+
+/*
+ * Testing indicates that all these functions are accurate up to 4 ULP.
+ * The functions casin(h) and cacos(h) are about 2.5 times slower than asinh.
+ * The functions catan(h) are a little under 2 times slower than atanh.
+ *
+ * The code for casinh, casin, cacos, and cacosh comes first.  The code is
+ * rather complicated, and the four functions are highly interdependent.
+ *
+ * The code for catanh and catan comes at the end.  It is much simpler than
+ * the other functions, and the code for these can be disconnected from the
+ * rest of the code.
+ */
+
+/*
+ *			================================
+ *			| casinh, casin, cacos, cacosh |
+ *			================================
+ */
+
+/*
+ * The algorithm is very close to that in "Implementing the complex arcsine
+ * and arccosine functions using exception handling" by T. E. Hull, Thomas F.
+ * Fairgrieve, and Ping Tak Peter Tang, published in ACM Transactions on
+ * Mathematical Software, Volume 23 Issue 3, 1997, Pages 299-335,
+ * http://dl.acm.org/citation.cfm?id=275324.
+ *
+ * Throughout we use the convention z = x + I*y.
+ *
+ * casinh(z) = sign(x)*log(A+sqrt(A*A-1)) + I*asin(B)
+ * where
+ * A = (|z+I| + |z-I|) / 2
+ * B = (|z+I| - |z-I|) / 2 = y/A
+ *
+ * These formulas become numerically unstable:
+ *   (a) for Re(casinh(z)) when z is close to the line segment [-I, I] (that
+ *       is, Re(casinh(z)) is close to 0);
+ *   (b) for Im(casinh(z)) when z is close to either of the intervals
+ *       [I, I*infinity) or (-I*infinity, -I] (that is, |Im(casinh(z))| is
+ *       close to PI/2).
+ *
+ * These numerical problems are overcome by defining
+ * f(a, b) = (hypot(a, b) - b) / 2 = a*a / (hypot(a, b) + b) / 2
+ * Then if A < A_crossover, we use
+ *   log(A + sqrt(A*A-1)) = log1p((A-1) + sqrt((A-1)*(A+1)))
+ *   A-1 = f(x, 1+y) + f(x, 1-y)
+ * and if B > B_crossover, we use
+ *   asin(B) = atan2(y, sqrt(A*A - y*y)) = atan2(y, sqrt((A+y)*(A-y)))
+ *   A-y = f(x, y+1) + f(x, y-1)
+ * where without loss of generality we have assumed that x and y are
+ * non-negative.
+ *
+ * Much of the difficulty comes because the intermediate computations may
+ * produce overflows or underflows.  This is dealt with in the paper by Hull
+ * et al by using exception handling.  We do this by detecting when
+ * computations risk underflow or overflow.  The hardest part is handling the
+ * underflows when computing f(a, b).
+ *
+ * Note that the function f(a, b) does not appear explicitly in the paper by
+ * Hull et al, but the idea may be found on pages 308 and 309.  Introducing the
+ * function f(a, b) allows us to concentrate many of the clever tricks in this
+ * paper into one function.
+ */
+
+/*
+ * Function f(a, b, hypot_a_b) = (hypot(a, b) - b) / 2.
+ * Pass hypot(a, b) as the third argument.
+ */
+static inline double
+f(double a, double b, double hypot_a_b)
+{
+	if (b < 0)
+		return ((hypot_a_b - b) / 2);
+	if (b == 0)
+		return (a / 2);
+	return (a * a / (hypot_a_b + b) / 2);
+}
+
+/*
+ * All the hard work is contained in this function.
+ * x and y are assumed positive or zero, and less than RECIP_EPSILON.
+ * Upon return:
+ * rx = Re(casinh(z)) = -Im(cacos(y + I*x)).
+ * B_is_usable is set to 1 if the value of B is usable.
+ * If B_is_usable is set to 0, sqrt_A2my2 = sqrt(A*A - y*y), and new_y = y.
+ * If returning sqrt_A2my2 has potential to result in an underflow, it is
+ * rescaled, and new_y is similarly rescaled.
+ */
+static inline void
+do_hard_work(double x, double y, double *rx, int *B_is_usable, double *B,
+    double *sqrt_A2my2, double *new_y)
+{
+	double R, S, A; /* A, B, R, and S are as in Hull et al. */
+	double Am1, Amy; /* A-1, A-y. */
+
+	R = hypot(x, y + 1);		/* |z+I| */
+	S = hypot(x, y - 1);		/* |z-I| */
+
+	/* A = (|z+I| + |z-I|) / 2 */
+	A = (R + S) / 2;
+	/*
+	 * Mathematically A >= 1.  There is a small chance that this will not
+	 * be so because of rounding errors.  So we will make certain it is
+	 * so.
+	 */
+	if (A < 1)
+		A = 1;
+
+	if (A < A_crossover) {
+		/*
+		 * Am1 = fp + fm, where fp = f(x, 1+y), and fm = f(x, 1-y).
+		 * rx = log1p(Am1 + sqrt(Am1*(A+1)))
+		 */
+		if (y == 1 && x < DBL_EPSILON * DBL_EPSILON / 128) {
+			/*
+			 * fp is of order x^2, and fm = x/2.
+			 * A = 1 (inexactly).
+			 */
+			*rx = sqrt(x);
+		} else if (x >= DBL_EPSILON * fabs(y - 1)) {
+			/*
+			 * Underflow will not occur because
+			 * x >= DBL_EPSILON^2/128 >= FOUR_SQRT_MIN
+			 */
+			Am1 = f(x, 1 + y, R) + f(x, 1 - y, S);
+			*rx = log1p(Am1 + sqrt(Am1 * (A + 1)));
+		} else if (y < 1) {
+			/*
+			 * fp = x*x/(1+y)/4, fm = x*x/(1-y)/4, and
+			 * A = 1 (inexactly).
+			 */
+			*rx = x / sqrt((1 - y) * (1 + y));
+		} else {		/* if (y > 1) */
+			/*
+			 * A-1 = y-1 (inexactly).
+			 */
+			*rx = log1p((y - 1) + sqrt((y - 1) * (y + 1)));
+		}
+	} else {
+		*rx = log(A + sqrt(A * A - 1));
+	}
+
+	*new_y = y;
+
+	if (y < FOUR_SQRT_MIN) {
+		/*
+		 * Avoid a possible underflow caused by y/A.  For casinh this
+		 * would be legitimate, but will be picked up by invoking atan2
+		 * later on.  For cacos this would not be legitimate.
+		 */
+		*B_is_usable = 0;
+		*sqrt_A2my2 = A * (2 / DBL_EPSILON);
+		*new_y = y * (2 / DBL_EPSILON);
+		return;
+	}
+
+	/* B = (|z+I| - |z-I|) / 2 = y/A */
+	*B = y / A;
+	*B_is_usable = 1;
+
+	if (*B > B_crossover) {
+		*B_is_usable = 0;
+		/*
+		 * Amy = fp + fm, where fp = f(x, y+1), and fm = f(x, y-1).
+		 * sqrt_A2my2 = sqrt(Amy*(A+y))
+		 */
+		if (y == 1 && x < DBL_EPSILON / 128) {
+			/*
+			 * fp is of order x^2, and fm = x/2.
+			 * A = 1 (inexactly).
+			 */
+			*sqrt_A2my2 = sqrt(x) * sqrt((A + y) / 2);
+		} else if (x >= DBL_EPSILON * fabs(y - 1)) {
+			/*
+			 * Underflow will not occur because
+			 * x >= DBL_EPSILON/128 >= FOUR_SQRT_MIN
+			 * and
+			 * x >= DBL_EPSILON^2 >= FOUR_SQRT_MIN
+			 */
+			Amy = f(x, y + 1, R) + f(x, y - 1, S);
+			*sqrt_A2my2 = sqrt(Amy * (A + y));
+		} else if (y > 1) {
+			/*
+			 * fp = x*x/(y+1)/4, fm = x*x/(y-1)/4, and
+			 * A = y (inexactly).
+			 *
+			 * y < RECIP_EPSILON.  So the following
+			 * scaling should avoid any underflow problems.
+			 */
+			*sqrt_A2my2 = x * (4 / DBL_EPSILON / DBL_EPSILON) * y /
+			    sqrt((y + 1) * (y - 1));
+			*new_y = y * (4 / DBL_EPSILON / DBL_EPSILON);
+		} else {		/* if (y < 1) */
+			/*
+			 * fm = 1-y >= DBL_EPSILON, fp is of order x^2, and
+			 * A = 1 (inexactly).
+			 */
+			*sqrt_A2my2 = sqrt((1 - y) * (1 + y));
+		}
+	}
+}
+
+/*
+ * casinh(z) = z + O(z^3)   as z -> 0
+ *
+ * casinh(z) = sign(x)*clog(sign(x)*z) + O(1/z^2)   as z -> infinity
+ * The above formula works for the imaginary part as well, because
+ * Im(casinh(z)) = sign(x)*atan2(sign(x)*y, fabs(x)) + O(y/z^3)
+ *    as z -> infinity, uniformly in y
+ */
+double complex
+casinh(double complex z)
+{
+	double x, y, ax, ay, rx, ry, B, sqrt_A2my2, new_y;
+	int B_is_usable;
+	double complex w;
+
+	x = creal(z);
+	y = cimag(z);
+	ax = fabs(x);
+	ay = fabs(y);
+
+	if (isnan(x) || isnan(y)) {
+		/* casinh(+-Inf + I*NaN) = +-Inf + I*NaN */
+		if (isinf(x))
+			return (CMPLX(x, y + y));
+		/* casinh(NaN + I*+-Inf) = opt(+-)Inf + I*NaN */
+		if (isinf(y))
+			return (CMPLX(y, x + x));
+		/* casinh(NaN + I*0) = NaN + I*0 */
+		if (y == 0)
+			return (CMPLX(x + x, y));
+		/*
+		 * All other cases involving NaN return NaN + I*NaN.
+		 * C99 leaves it optional whether to raise invalid if one of
+		 * the arguments is not NaN, so we opt not to raise it.
+		 */
+		return (CMPLX(x + 0.0L + (y + 0), x + 0.0L + (y + 0)));
+	}
+
+	if (ax > RECIP_EPSILON || ay > RECIP_EPSILON) {
+		/* clog...() will raise inexact unless x or y is infinite. */
+		if (signbit(x) == 0)
+			w = clog_for_large_values(z) + m_ln2;
+		else
+			w = clog_for_large_values(-z) + m_ln2;
+		return (CMPLX(copysign(creal(w), x), copysign(cimag(w), y)));
+	}
+
+	/* Avoid spuriously raising inexact for z = 0. */
+	if (x == 0 && y == 0)
+		return (z);
+
+	/* All remaining cases are inexact. */
+	raise_inexact();
+
+	if (ax < SQRT_6_EPSILON / 4 && ay < SQRT_6_EPSILON / 4)
+		return (z);
+
+	do_hard_work(ax, ay, &rx, &B_is_usable, &B, &sqrt_A2my2, &new_y);
+	if (B_is_usable)
+		ry = asin(B);
+	else
+		ry = atan2(new_y, sqrt_A2my2);
+	return (CMPLX(copysign(rx, x), copysign(ry, y)));
+}
+
+/*
+ * casin(z) = reverse(casinh(reverse(z)))
+ * where reverse(x + I*y) = y + I*x = I*conj(z).
+ */
+double complex
+casin(double complex z)
+{
+	double complex w = casinh(CMPLX(cimag(z), creal(z)));
+
+	return (CMPLX(cimag(w), creal(w)));
+}
+
+/*
+ * cacos(z) = PI/2 - casin(z)
+ * but do the computation carefully so cacos(z) is accurate when z is
+ * close to 1.
+ *
+ * cacos(z) = PI/2 - z + O(z^3)   as z -> 0
+ *
+ * cacos(z) = -sign(y)*I*clog(z) + O(1/z^2)   as z -> infinity
+ * The above formula works for the real part as well, because
+ * Re(cacos(z)) = atan2(fabs(y), x) + O(y/z^3)
+ *    as z -> infinity, uniformly in y
+ */
+double complex
+cacos(double complex z)
+{
+	double x, y, ax, ay, rx, ry, B, sqrt_A2mx2, new_x;
+	int sx, sy;
+	int B_is_usable;
+	double complex w;
+
+	x = creal(z);
+	y = cimag(z);
+	sx = signbit(x);
+	sy = signbit(y);
+	ax = fabs(x);
+	ay = fabs(y);
+
+	if (isnan(x) || isnan(y)) {
+		/* cacos(+-Inf + I*NaN) = NaN + I*opt(-)Inf */
+		if (isinf(x))
+			return (CMPLX(y + y, -INFINITY));
+		/* cacos(NaN + I*+-Inf) = NaN + I*-+Inf */
+		if (isinf(y))
+			return (CMPLX(x + x, -y));
+		/* cacos(0 + I*NaN) = PI/2 + I*NaN with inexact */
+		if (x == 0)
+			return (CMPLX(pio2_hi + pio2_lo, y + y));
+		/*
+		 * All other cases involving NaN return NaN + I*NaN.
+		 * C99 leaves it optional whether to raise invalid if one of
+		 * the arguments is not NaN, so we opt not to raise it.
+		 */
+		return (CMPLX(x + 0.0L + (y + 0), x + 0.0L + (y + 0)));
+	}
+
+	if (ax > RECIP_EPSILON || ay > RECIP_EPSILON) {
+		/* clog...() will raise inexact unless x or y is infinite. */
+		w = clog_for_large_values(z);
+		rx = fabs(cimag(w));
+		ry = creal(w) + m_ln2;
+		if (sy == 0)
+			ry = -ry;
+		return (CMPLX(rx, ry));
+	}
+
+	/* Avoid spuriously raising inexact for z = 1. */
+	if (x == 1 && y == 0)
+		return (CMPLX(0, -y));
+
+	/* All remaining cases are inexact. */
+	raise_inexact();
+
+	if (ax < SQRT_6_EPSILON / 4 && ay < SQRT_6_EPSILON / 4)
+		return (CMPLX(pio2_hi - (x - pio2_lo), -y));
+
+	do_hard_work(ay, ax, &ry, &B_is_usable, &B, &sqrt_A2mx2, &new_x);
+	if (B_is_usable) {
+		if (sx == 0)
+			rx = acos(B);
+		else
+			rx = acos(-B);
+	} else {
+		if (sx == 0)
+			rx = atan2(sqrt_A2mx2, new_x);
+		else
+			rx = atan2(sqrt_A2mx2, -new_x);
+	}
+	if (sy == 0)
+		ry = -ry;
+	return (CMPLX(rx, ry));
+}
+
+/*
+ * cacosh(z) = I*cacos(z) or -I*cacos(z)
+ * where the sign is chosen so Re(cacosh(z)) >= 0.
+ */
+double complex
+cacosh(double complex z)
+{
+	double complex w;
+	double rx, ry;
+
+	w = cacos(z);
+	rx = creal(w);
+	ry = cimag(w);
+	/* cacosh(NaN + I*NaN) = NaN + I*NaN */
+	if (isnan(rx) && isnan(ry))
+		return (CMPLX(ry, rx));
+	/* cacosh(NaN + I*+-Inf) = +Inf + I*NaN */
+	/* cacosh(+-Inf + I*NaN) = +Inf + I*NaN */
+	if (isnan(rx))
+		return (CMPLX(fabs(ry), rx));
+	/* cacosh(0 + I*NaN) = NaN + I*NaN */
+	if (isnan(ry))
+		return (CMPLX(ry, ry));
+	return (CMPLX(fabs(ry), copysign(rx, cimag(z))));
+}
+
+/*
+ * Optimized version of clog() for |z| finite and larger than ~RECIP_EPSILON.
+ */
+static double complex
+clog_for_large_values(double complex z)
+{
+	double x, y;
+	double ax, ay, t;
+
+	x = creal(z);
+	y = cimag(z);
+	ax = fabs(x);
+	ay = fabs(y);
+	if (ax < ay) {
+		t = ax;
+		ax = ay;
+		ay = t;
+	}
+
+	/*
+	 * Avoid overflow in hypot() when x and y are both very large.
+	 * Divide x and y by E, and then add 1 to the logarithm.  This depends
+	 * on E being larger than sqrt(2).
+	 * Dividing by E causes an insignificant loss of accuracy; however
+	 * this method is still poor since it is uneccessarily slow.
+	 */
+	if (ax > DBL_MAX / 2)
+		return (CMPLX(log(hypot(x / m_e, y / m_e)) + 1, atan2(y, x)));
+
+	/*
+	 * Avoid overflow when x or y is large.  Avoid underflow when x or
+	 * y is small.
+	 */
+	if (ax > QUARTER_SQRT_MAX || ay < SQRT_MIN)
+		return (CMPLX(log(hypot(x, y)), atan2(y, x)));
+
+	return (CMPLX(log(ax * ax + ay * ay) / 2, atan2(y, x)));
+}
+
+/*
+ *				=================
+ *				| catanh, catan |
+ *				=================
+ */
+
+/*
+ * sum_squares(x,y) = x*x + y*y (or just x*x if y*y would underflow).
+ * Assumes x*x and y*y will not overflow.
+ * Assumes x and y are finite.
+ * Assumes y is non-negative.
+ * Assumes fabs(x) >= DBL_EPSILON.
+ */
+static inline double
+sum_squares(double x, double y)
+{
+
+	/* Avoid underflow when y is small. */
+	if (y < SQRT_MIN)
+		return (x * x);
+
+	return (x * x + y * y);
+}
+
+/*
+ * real_part_reciprocal(x, y) = Re(1/(x+I*y)) = x/(x*x + y*y).
+ * Assumes x and y are not NaN, and one of x and y is larger than
+ * RECIP_EPSILON.  We avoid unwarranted underflow.  It is important to not use
+ * the code creal(1/z), because the imaginary part may produce an unwanted
+ * underflow.
+ * This is only called in a context where inexact is always raised before
+ * the call, so no effort is made to avoid or force inexact.
+ */
+static inline double
+real_part_reciprocal(double x, double y)
+{
+	double scale;
+	uint32_t hx, hy;
+	int32_t ix, iy;
+
+	/*
+	 * This code is inspired by the C99 document n1124.pdf, Section G.5.1,
+	 * example 2.
+	 */
+	GET_HIGH_WORD(hx, x);
+	ix = hx & 0x7ff00000;
+	GET_HIGH_WORD(hy, y);
+	iy = hy & 0x7ff00000;
+#define	BIAS	(DBL_MAX_EXP - 1)
+/* XXX more guard digits are useful iff there is extra precision. */
+#define	CUTOFF	(DBL_MANT_DIG / 2 + 1)	/* just half or 1 guard digit */
+	if (ix - iy >= CUTOFF << 20 || isinf(x))
+		return (1 / x);		/* +-Inf -> +-0 is special */
+	if (iy - ix >= CUTOFF << 20)
+		return (x / y / y);	/* should avoid double div, but hard */
+	if (ix <= (BIAS + DBL_MAX_EXP / 2 - CUTOFF) << 20)
+		return (x / (x * x + y * y));
+	scale = 1;
+	SET_HIGH_WORD(scale, 0x7ff00000 - ix);	/* 2**(1-ilogb(x)) */
+	x *= scale;
+	y *= scale;
+	return (x / (x * x + y * y) * scale);
+}
+
+/*
+ * catanh(z) = log((1+z)/(1-z)) / 2
+ *           = log1p(4*x / |z-1|^2) / 4
+ *             + I * atan2(2*y, (1-x)*(1+x)-y*y) / 2
+ *
+ * catanh(z) = z + O(z^3)   as z -> 0
+ *
+ * catanh(z) = 1/z + sign(y)*I*PI/2 + O(1/z^3)   as z -> infinity
+ * The above formula works for the real part as well, because
+ * Re(catanh(z)) = x/|z|^2 + O(x/z^4)
+ *    as z -> infinity, uniformly in x
+ */
+double complex
+catanh(double complex z)
+{
+	double x, y, ax, ay, rx, ry;
+
+	x = creal(z);
+	y = cimag(z);
+	ax = fabs(x);
+	ay = fabs(y);
+
+	/* This helps handle many cases. */
+	if (y == 0 && ax <= 1)
+		return (CMPLX(atanh(x), y));
+
+	/* To ensure the same accuracy as atan(), and to filter out z = 0. */
+	if (x == 0)
+		return (CMPLX(x, atan(y)));
+
+	if (isnan(x) || isnan(y)) {
+		/* catanh(+-Inf + I*NaN) = +-0 + I*NaN */
+		if (isinf(x))
+			return (CMPLX(copysign(0, x), y + y));
+		/* catanh(NaN + I*+-Inf) = sign(NaN)0 + I*+-PI/2 */
+		if (isinf(y))
+			return (CMPLX(copysign(0, x),
+			    copysign(pio2_hi + pio2_lo, y)));
+		/*
+		 * All other cases involving NaN return NaN + I*NaN.
+		 * C99 leaves it optional whether to raise invalid if one of
+		 * the arguments is not NaN, so we opt not to raise it.
+		 */
+		return (CMPLX(x + 0.0L + (y + 0), x + 0.0L + (y + 0)));
+	}
+
+	if (ax > RECIP_EPSILON || ay > RECIP_EPSILON)
+		return (CMPLX(real_part_reciprocal(x, y),
+		    copysign(pio2_hi + pio2_lo, y)));
+
+	if (ax < SQRT_3_EPSILON / 2 && ay < SQRT_3_EPSILON / 2) {
+		/*
+		 * z = 0 was filtered out above.  All other cases must raise
+		 * inexact, but this is the only only that needs to do it
+		 * explicitly.
+		 */
+		raise_inexact();
+		return (z);
+	}
+
+	if (ax == 1 && ay < DBL_EPSILON)
+		rx = (m_ln2 - log(ay)) / 2;
+	else
+		rx = log1p(4 * ax / sum_squares(ax - 1, ay)) / 4;
+
+	if (ax == 1)
+		ry = atan2(2, -ay) / 2;
+	else if (ay < DBL_EPSILON)
+		ry = atan2(2 * ay, (1 - ax) * (1 + ax)) / 2;
+	else
+		ry = atan2(2 * ay, (1 - ax) * (1 + ax) - ay * ay) / 2;
+
+	return (CMPLX(copysign(rx, x), copysign(ry, y)));
+}
+
+/*
+ * catan(z) = reverse(catanh(reverse(z)))
+ * where reverse(x + I*y) = y + I*x = I*conj(z).
+ */
+double complex
+catan(double complex z)
+{
+	double complex w = catanh(CMPLX(cimag(z), creal(z)));
+
+	return (CMPLX(cimag(w), creal(w)));
+}

+ 393 - 0
src/catrigf.c

@@ -0,0 +1,393 @@
+/*-
+ * Copyright (c) 2012 Stephen Montgomery-Smith <stephen@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.
+ */
+
+/*
+ * The algorithm is very close to that in "Implementing the complex arcsine
+ * and arccosine functions using exception handling" by T. E. Hull, Thomas F.
+ * Fairgrieve, and Ping Tak Peter Tang, published in ACM Transactions on
+ * Mathematical Software, Volume 23 Issue 3, 1997, Pages 299-335,
+ * http://dl.acm.org/citation.cfm?id=275324.
+ *
+ * See catrig.c for complete comments.
+ *
+ * XXX comments were removed automatically, and even short ones on the right
+ * of statements were removed (all of them), contrary to normal style.  Only
+ * a few comments on the right of declarations remain.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <complex.h>
+#include <float.h>
+
+#include "math.h"
+#include "math_private.h"
+
+#undef isinf
+#define isinf(x)	(fabsf(x) == INFINITY)
+#undef isnan
+#define isnan(x)	((x) != (x))
+#define	raise_inexact()	do { volatile float junk = 1 + tiny; } while(0)
+#undef signbit
+#define signbit(x)	(__builtin_signbitf(x))
+
+static const float
+A_crossover =		10,
+B_crossover =		0.6417,
+FOUR_SQRT_MIN =		0x1p-61,
+QUARTER_SQRT_MAX =	0x1p61,
+m_e =			2.7182818285e0,		/*  0xadf854.0p-22 */
+m_ln2 =			6.9314718056e-1,	/*  0xb17218.0p-24 */
+pio2_hi =		1.5707962513e0,		/*  0xc90fda.0p-23 */
+RECIP_EPSILON =		1 / FLT_EPSILON,
+SQRT_3_EPSILON =	5.9801995673e-4,	/*  0x9cc471.0p-34 */
+SQRT_6_EPSILON =	8.4572793338e-4,	/*  0xddb3d7.0p-34 */
+SQRT_MIN =		0x1p-63;
+
+static const volatile float
+pio2_lo =		7.5497899549e-8,	/*  0xa22169.0p-47 */
+tiny =			0x1p-100;
+
+static float complex clog_for_large_values(float complex z);
+
+static inline float
+f(float a, float b, float hypot_a_b)
+{
+	if (b < 0)
+		return ((hypot_a_b - b) / 2);
+	if (b == 0)
+		return (a / 2);
+	return (a * a / (hypot_a_b + b) / 2);
+}
+
+static inline void
+do_hard_work(float x, float y, float *rx, int *B_is_usable, float *B,
+    float *sqrt_A2my2, float *new_y)
+{
+	float R, S, A;
+	float Am1, Amy;
+
+	R = hypotf(x, y + 1);
+	S = hypotf(x, y - 1);
+
+	A = (R + S) / 2;
+	if (A < 1)
+		A = 1;
+
+	if (A < A_crossover) {
+		if (y == 1 && x < FLT_EPSILON * FLT_EPSILON / 128) {
+			*rx = sqrtf(x);
+		} else if (x >= FLT_EPSILON * fabsf(y - 1)) {
+			Am1 = f(x, 1 + y, R) + f(x, 1 - y, S);
+			*rx = log1pf(Am1 + sqrtf(Am1 * (A + 1)));
+		} else if (y < 1) {
+			*rx = x / sqrtf((1 - y) * (1 + y));
+		} else {
+			*rx = log1pf((y - 1) + sqrtf((y - 1) * (y + 1)));
+		}
+	} else {
+		*rx = logf(A + sqrtf(A * A - 1));
+	}
+
+	*new_y = y;
+
+	if (y < FOUR_SQRT_MIN) {
+		*B_is_usable = 0;
+		*sqrt_A2my2 = A * (2 / FLT_EPSILON);
+		*new_y = y * (2 / FLT_EPSILON);
+		return;
+	}
+
+	*B = y / A;
+	*B_is_usable = 1;
+
+	if (*B > B_crossover) {
+		*B_is_usable = 0;
+		if (y == 1 && x < FLT_EPSILON / 128) {
+			*sqrt_A2my2 = sqrtf(x) * sqrtf((A + y) / 2);
+		} else if (x >= FLT_EPSILON * fabsf(y - 1)) {
+			Amy = f(x, y + 1, R) + f(x, y - 1, S);
+			*sqrt_A2my2 = sqrtf(Amy * (A + y));
+		} else if (y > 1) {
+			*sqrt_A2my2 = x * (4 / FLT_EPSILON / FLT_EPSILON) * y /
+			    sqrtf((y + 1) * (y - 1));
+			*new_y = y * (4 / FLT_EPSILON / FLT_EPSILON);
+		} else {
+			*sqrt_A2my2 = sqrtf((1 - y) * (1 + y));
+		}
+	}
+}
+
+float complex
+casinhf(float complex z)
+{
+	float x, y, ax, ay, rx, ry, B, sqrt_A2my2, new_y;
+	int B_is_usable;
+	float complex w;
+
+	x = crealf(z);
+	y = cimagf(z);
+	ax = fabsf(x);
+	ay = fabsf(y);
+
+	if (isnan(x) || isnan(y)) {
+		if (isinf(x))
+			return (CMPLXF(x, y + y));
+		if (isinf(y))
+			return (CMPLXF(y, x + x));
+		if (y == 0)
+			return (CMPLXF(x + x, y));
+		return (CMPLXF(x + 0.0L + (y + 0), x + 0.0L + (y + 0)));
+	}
+
+	if (ax > RECIP_EPSILON || ay > RECIP_EPSILON) {
+		if (signbit(x) == 0)
+			w = clog_for_large_values(z) + m_ln2;
+		else
+			w = clog_for_large_values(-z) + m_ln2;
+		return (CMPLXF(copysignf(crealf(w), x),
+		    copysignf(cimagf(w), y)));
+	}
+
+	if (x == 0 && y == 0)
+		return (z);
+
+	raise_inexact();
+
+	if (ax < SQRT_6_EPSILON / 4 && ay < SQRT_6_EPSILON / 4)
+		return (z);
+
+	do_hard_work(ax, ay, &rx, &B_is_usable, &B, &sqrt_A2my2, &new_y);
+	if (B_is_usable)
+		ry = asinf(B);
+	else
+		ry = atan2f(new_y, sqrt_A2my2);
+	return (CMPLXF(copysignf(rx, x), copysignf(ry, y)));
+}
+
+float complex
+casinf(float complex z)
+{
+	float complex w = casinhf(CMPLXF(cimagf(z), crealf(z)));
+
+	return (CMPLXF(cimagf(w), crealf(w)));
+}
+
+float complex
+cacosf(float complex z)
+{
+	float x, y, ax, ay, rx, ry, B, sqrt_A2mx2, new_x;
+	int sx, sy;
+	int B_is_usable;
+	float complex w;
+
+	x = crealf(z);
+	y = cimagf(z);
+	sx = signbit(x);
+	sy = signbit(y);
+	ax = fabsf(x);
+	ay = fabsf(y);
+
+	if (isnan(x) || isnan(y)) {
+		if (isinf(x))
+			return (CMPLXF(y + y, -INFINITY));
+		if (isinf(y))
+			return (CMPLXF(x + x, -y));
+		if (x == 0)
+			return (CMPLXF(pio2_hi + pio2_lo, y + y));
+		return (CMPLXF(x + 0.0L + (y + 0), x + 0.0L + (y + 0)));
+	}
+
+	if (ax > RECIP_EPSILON || ay > RECIP_EPSILON) {
+		w = clog_for_large_values(z);
+		rx = fabsf(cimagf(w));
+		ry = crealf(w) + m_ln2;
+		if (sy == 0)
+			ry = -ry;
+		return (CMPLXF(rx, ry));
+	}
+
+	if (x == 1 && y == 0)
+		return (CMPLXF(0, -y));
+
+	raise_inexact();
+
+	if (ax < SQRT_6_EPSILON / 4 && ay < SQRT_6_EPSILON / 4)
+		return (CMPLXF(pio2_hi - (x - pio2_lo), -y));
+
+	do_hard_work(ay, ax, &ry, &B_is_usable, &B, &sqrt_A2mx2, &new_x);
+	if (B_is_usable) {
+		if (sx == 0)
+			rx = acosf(B);
+		else
+			rx = acosf(-B);
+	} else {
+		if (sx == 0)
+			rx = atan2f(sqrt_A2mx2, new_x);
+		else
+			rx = atan2f(sqrt_A2mx2, -new_x);
+	}
+	if (sy == 0)
+		ry = -ry;
+	return (CMPLXF(rx, ry));
+}
+
+float complex
+cacoshf(float complex z)
+{
+	float complex w;
+	float rx, ry;
+
+	w = cacosf(z);
+	rx = crealf(w);
+	ry = cimagf(w);
+	if (isnan(rx) && isnan(ry))
+		return (CMPLXF(ry, rx));
+	if (isnan(rx))
+		return (CMPLXF(fabsf(ry), rx));
+	if (isnan(ry))
+		return (CMPLXF(ry, ry));
+	return (CMPLXF(fabsf(ry), copysignf(rx, cimagf(z))));
+}
+
+static float complex
+clog_for_large_values(float complex z)
+{
+	float x, y;
+	float ax, ay, t;
+
+	x = crealf(z);
+	y = cimagf(z);
+	ax = fabsf(x);
+	ay = fabsf(y);
+	if (ax < ay) {
+		t = ax;
+		ax = ay;
+		ay = t;
+	}
+
+	if (ax > FLT_MAX / 2)
+		return (CMPLXF(logf(hypotf(x / m_e, y / m_e)) + 1,
+		    atan2f(y, x)));
+
+	if (ax > QUARTER_SQRT_MAX || ay < SQRT_MIN)
+		return (CMPLXF(logf(hypotf(x, y)), atan2f(y, x)));
+
+	return (CMPLXF(logf(ax * ax + ay * ay) / 2, atan2f(y, x)));
+}
+
+static inline float
+sum_squares(float x, float y)
+{
+
+	if (y < SQRT_MIN)
+		return (x * x);
+
+	return (x * x + y * y);
+}
+
+static inline float
+real_part_reciprocal(float x, float y)
+{
+	float scale;
+	uint32_t hx, hy;
+	int32_t ix, iy;
+
+	GET_FLOAT_WORD(hx, x);
+	ix = hx & 0x7f800000;
+	GET_FLOAT_WORD(hy, y);
+	iy = hy & 0x7f800000;
+#define	BIAS	(FLT_MAX_EXP - 1)
+#define	CUTOFF	(FLT_MANT_DIG / 2 + 1)
+	if (ix - iy >= CUTOFF << 23 || isinf(x))
+		return (1 / x);
+	if (iy - ix >= CUTOFF << 23)
+		return (x / y / y);
+	if (ix <= (BIAS + FLT_MAX_EXP / 2 - CUTOFF) << 23)
+		return (x / (x * x + y * y));
+	SET_FLOAT_WORD(scale, 0x7f800000 - ix);
+	x *= scale;
+	y *= scale;
+	return (x / (x * x + y * y) * scale);
+}
+
+float complex
+catanhf(float complex z)
+{
+	float x, y, ax, ay, rx, ry;
+
+	x = crealf(z);
+	y = cimagf(z);
+	ax = fabsf(x);
+	ay = fabsf(y);
+
+	if (y == 0 && ax <= 1)
+		return (CMPLXF(atanhf(x), y));
+
+	if (x == 0)
+		return (CMPLXF(x, atanf(y)));
+
+	if (isnan(x) || isnan(y)) {
+		if (isinf(x))
+			return (CMPLXF(copysignf(0, x), y + y));
+		if (isinf(y))
+			return (CMPLXF(copysignf(0, x),
+			    copysignf(pio2_hi + pio2_lo, y)));
+		return (CMPLXF(x + 0.0L + (y + 0), x + 0.0L + (y + 0)));
+	}
+
+	if (ax > RECIP_EPSILON || ay > RECIP_EPSILON)
+		return (CMPLXF(real_part_reciprocal(x, y),
+		    copysignf(pio2_hi + pio2_lo, y)));
+
+	if (ax < SQRT_3_EPSILON / 2 && ay < SQRT_3_EPSILON / 2) {
+		raise_inexact();
+		return (z);
+	}
+
+	if (ax == 1 && ay < FLT_EPSILON)
+		rx = (m_ln2 - logf(ay)) / 2;
+	else
+		rx = log1pf(4 * ax / sum_squares(ax - 1, ay)) / 4;
+
+	if (ax == 1)
+		ry = atan2f(2, -ay) / 2;
+	else if (ay < FLT_EPSILON)
+		ry = atan2f(2 * ay, (1 - ax) * (1 + ax)) / 2;
+	else
+		ry = atan2f(2 * ay, (1 - ax) * (1 + ax) - ay * ay) / 2;
+
+	return (CMPLXF(copysignf(rx, x), copysignf(ry, y)));
+}
+
+float complex
+catanf(float complex z)
+{
+	float complex w = catanhf(CMPLXF(cimagf(z), crealf(z)));
+
+	return (CMPLXF(cimagf(w), crealf(w)));
+}

+ 46 - 0
src/digittoint.c

@@ -0,0 +1,46 @@
+/*-
+ * 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$
+ */
+
+#include <sys/cdefs.h>
+
+/* digittoint is in the FreeBSD C library, but implemented in terms of locale stuff. */
+int digittoint(char ch) {
+  int d = ch - '0';
+  if ((unsigned) d < 10) {
+    return d;
+  }
+  d = ch - 'a';
+  if ((unsigned) d < 6) {
+    return d + 10;
+  }
+  d = ch - 'A';
+  if ((unsigned) d < 6) {
+    return d + 10;
+  }
+  return -1;
+}

+ 4 - 4
src/e_acos.c

@@ -11,8 +11,8 @@
  * ====================================================
  */
 
-#include "cdefs-compat.h"
-//__FBSDID("$FreeBSD: src/lib/msun/src/e_acos.c,v 1.13 2008/07/31 22:41:26 das Exp $");
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
 
 /* __ieee754_acos(x)
  * Method :                  
@@ -39,8 +39,8 @@
  */
 
 #include <float.h>
-#include <openlibm_math.h>
 
+#include "math.h"
 #include "math_private.h"
 
 static const double
@@ -61,7 +61,7 @@ qS2 =  2.02094576023350569471e+00, /* 0x40002AE5, 0x9C598AC8 */
 qS3 = -6.88283971605453293030e-01, /* 0xBFE6066C, 0x1B8D0159 */
 qS4 =  7.70381505559019352791e-02; /* 0x3FB3B8C5, 0xB12E9282 */
 
-DLLEXPORT double
+double
 __ieee754_acos(double x)
 {
 	double z,p,q,r,w,s,c,df;

+ 4 - 5
src/e_acosf.c

@@ -13,11 +13,10 @@
  * ====================================================
  */
 
-#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 <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
 
+#include "math.h"
 #include "math_private.h"
 
 static const float
@@ -32,7 +31,7 @@ pS1 = -4.2743422091e-02,
 pS2 = -8.6563630030e-03,
 qS1 = -7.0662963390e-01;
 
-DLLEXPORT float
+float
 __ieee754_acosf(float x)
 {
 	float z,p,q,r,w,s,c,df;

+ 9 - 4
src/e_acosh.c

@@ -12,8 +12,8 @@
  *
  */
 
-#include "cdefs-compat.h"
-//__FBSDID("$FreeBSD: src/lib/msun/src/e_acosh.c,v 1.9 2008/02/22 02:30:34 das Exp $");
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
 
 /* __ieee754_acosh(x)
  * Method :
@@ -29,15 +29,16 @@
  *	acosh(NaN) is NaN without signal.
  */
 
-#include <openlibm_math.h>
+#include <float.h>
 
+#include "math.h"
 #include "math_private.h"
 
 static const double
 one	= 1.0,
 ln2	= 6.93147180559945286227e-01;  /* 0x3FE62E42, 0xFEFA39EF */
 
-DLLEXPORT double
+double
 __ieee754_acosh(double x)
 {
 	double t;
@@ -61,3 +62,7 @@ __ieee754_acosh(double x)
 	    return log1p(t+sqrt(2.0*t+t*t));
 	}
 }
+
+#if LDBL_MANT_DIG == 53
+__weak_reference(acosh, acoshl);
+#endif

+ 4 - 5
src/e_acoshf.c

@@ -13,18 +13,17 @@
  * ====================================================
  */
 
-#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 <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
 
+#include "math.h"
 #include "math_private.h"
 
 static const float
 one	= 1.0,
 ln2	= 6.9314718246e-01;  /* 0x3f317218 */
 
-DLLEXPORT float
+float
 __ieee754_acoshf(float x)
 {
 	float t;

+ 89 - 0
src/e_acoshl.c

@@ -0,0 +1,89 @@
+/* from: FreeBSD: head/lib/msun/src/e_acosh.c 176451 2008-02-22 02:30:36Z das */
+
+/* @(#)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 <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * See e_acosh.c for complete comments.
+ *
+ * Converted to long double by David Schultz <das@FreeBSD.ORG> and
+ * Bruce D. Evans.
+ */
+
+#include <float.h>
+#ifdef __i386__
+#include <ieeefp.h>
+#endif
+
+#include "fpmath.h"
+#include "math.h"
+#include "math_private.h"
+
+/* EXP_LARGE is the threshold above which we use acosh(x) ~= log(2x). */
+#if LDBL_MANT_DIG == 64
+#define	EXP_LARGE	34
+#elif LDBL_MANT_DIG == 113
+#define	EXP_LARGE	58
+#else
+#error "Unsupported long double format"
+#endif
+
+#if LDBL_MAX_EXP != 0x4000
+/* We also require the usual expsign encoding. */
+#error "Unsupported long double format"
+#endif
+
+#define	BIAS	(LDBL_MAX_EXP - 1)
+
+static const double
+one	= 1.0;
+
+#if LDBL_MANT_DIG == 64
+static const union IEEEl2bits
+u_ln2 =  LD80C(0xb17217f7d1cf79ac, -1, 6.93147180559945309417e-1L);
+#define	ln2	u_ln2.e
+#elif LDBL_MANT_DIG == 113
+static const long double
+ln2 =  6.93147180559945309417232121458176568e-1L;	/* 0x162e42fefa39ef35793c7673007e6.0p-113 */
+#else
+#error "Unsupported long double format"
+#endif
+
+long double
+acoshl(long double x)
+{
+	long double t;
+	int16_t hx;
+
+	ENTERI();
+	GET_LDBL_EXPSIGN(hx, x);
+	if (hx < 0x3fff) {		/* x < 1, or misnormal */
+	    RETURNI((x-x)/(x-x));
+	} else if (hx >= BIAS + EXP_LARGE) { /* x >= LARGE */
+	    if (hx >= 0x7fff) {		/* x is inf, NaN or misnormal */
+	        RETURNI(x+x);
+	    } else 
+		RETURNI(logl(x)+ln2);	/* acosh(huge)=log(2x), or misnormal */
+	} else if (hx == 0x3fff && x == 1) {
+	    RETURNI(0.0);		/* acosh(1) = 0 */
+	} else if (hx >= 0x4000) {	/* LARGE > x >= 2, or misnormal */
+	    t=x*x;
+	    RETURNI(logl(2.0*x-one/(x+sqrtl(t-one))));
+	} else {			/* 1<x<2 */
+	    t = x-one;
+	    RETURNI(log1pl(t+sqrtl(2.0*t+t*t)));
+	}
+}

+ 4 - 4
src/e_acosl.c

@@ -12,8 +12,8 @@
  * ====================================================
  */
 
-#include "cdefs-compat.h"
-//__FBSDID("$FreeBSD: src/lib/msun/src/e_acosl.c,v 1.2 2008/08/02 03:56:22 das Exp $");
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
 
 /*
  * See comments in e_acos.c.
@@ -21,9 +21,9 @@
  */
 
 #include <float.h>
-#include <openlibm_math.h>
 
 #include "invtrig.h"
+#include "math.h"
 #include "math_private.h"
 
 static const long double
@@ -40,7 +40,7 @@ static const long double
 pi =  3.14159265358979323846264338327950280e+00L;
 #endif
 
-DLLEXPORT long double
+long double
 acosl(long double x)
 {
 	union IEEEl2bits u;

+ 4 - 4
src/e_asin.c

@@ -11,8 +11,8 @@
  * ====================================================
  */
 
-#include "cdefs-compat.h"
-//__FBSDID("$FreeBSD: src/lib/msun/src/e_asin.c,v 1.15 2011/02/10 07:37:50 das Exp $");
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
 
 /* __ieee754_asin(x)
  * Method :                  
@@ -45,8 +45,8 @@
  */
 
 #include <float.h>
-#include <openlibm_math.h>
 
+#include "math.h"
 #include "math_private.h"
 
 static const double
@@ -67,7 +67,7 @@ qS2 =  2.02094576023350569471e+00, /* 0x40002AE5, 0x9C598AC8 */
 qS3 = -6.88283971605453293030e-01, /* 0xBFE6066C, 0x1B8D0159 */
 qS4 =  7.70381505559019352791e-02; /* 0x3FB3B8C5, 0xB12E9282 */
 
-DLLEXPORT double
+double
 __ieee754_asin(double x)
 {
 	double t=0.0,w,p,q,c,r,s;

+ 4 - 5
src/e_asinf.c

@@ -13,11 +13,10 @@
  * ====================================================
  */
 
-#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 <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
 
+#include "math.h"
 #include "math_private.h"
 
 static const float
@@ -32,7 +31,7 @@ qS1 = -7.0662963390e-01;
 static const double
 pio2 =  1.570796326794896558e+00;
 
-DLLEXPORT float
+float
 __ieee754_asinf(float x)
 {
 	double s;

+ 4 - 4
src/e_asinl.c

@@ -12,8 +12,8 @@
  * ====================================================
  */
 
-#include "cdefs-compat.h"
-//__FBSDID("$FreeBSD: src/lib/msun/src/e_asinl.c,v 1.2 2008/08/03 17:49:05 das Exp $");
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
 
 /*
  * See comments in e_asin.c.
@@ -21,16 +21,16 @@
  */
 
 #include <float.h>
-#include <openlibm_math.h>
 
 #include "invtrig.h"
+#include "math.h"
 #include "math_private.h"
 
 static const long double
 one =  1.00000000000000000000e+00,
 huge = 1.000e+300;
 
-DLLEXPORT long double
+long double
 asinl(long double x)
 {
 	union IEEEl2bits u;

+ 5 - 5
src/e_atan2.c

@@ -12,8 +12,8 @@
  *
  */
 
-#include "cdefs-compat.h"
-//__FBSDID("$FreeBSD: src/lib/msun/src/e_atan2.c,v 1.14 2008/08/02 19:17:00 das Exp $");
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
 
 /* __ieee754_atan2(y,x)
  * Method :
@@ -43,8 +43,8 @@
  */
 
 #include <float.h>
-#include <openlibm_math.h>
 
+#include "math.h"
 #include "math_private.h"
 
 static volatile double
@@ -57,7 +57,7 @@ pi      = 3.1415926535897931160E+00; /* 0x400921FB, 0x54442D18 */
 static volatile double
 pi_lo   = 1.2246467991473531772E-16; /* 0x3CA1A626, 0x33145C07 */
 
-DLLEXPORT double
+double
 __ieee754_atan2(double y, double x)
 {
 	double z;
@@ -71,7 +71,7 @@ __ieee754_atan2(double y, double x)
 	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 */
+	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 */

+ 4 - 5
src/e_atan2f.c

@@ -13,11 +13,10 @@
  * ====================================================
  */
 
-#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 <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
 
+#include "math.h"
 #include "math_private.h"
 
 static volatile float
@@ -30,7 +29,7 @@ pi      = 3.1415927410e+00; /* 0x40490fdb */
 static volatile float
 pi_lo   = -8.7422776573e-08; /* 0xb3bbbd2e */
 
-DLLEXPORT float
+float
 __ieee754_atan2f(float y, float x)
 {
 	float z;

+ 4 - 4
src/e_atan2l.c

@@ -13,8 +13,8 @@
  *
  */
 
-#include "cdefs-compat.h"
-//__FBSDID("$FreeBSD: src/lib/msun/src/e_atan2l.c,v 1.3 2008/08/02 19:17:00 das Exp $");
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
 
 /*
  * See comments in e_atan2.c.
@@ -22,9 +22,9 @@
  */
 
 #include <float.h>
-#include <openlibm_math.h>
 
 #include "invtrig.h"
+#include "math.h"
 #include "math_private.h"
 
 static volatile long double
@@ -43,7 +43,7 @@ static const long double
 pi =  3.14159265358979323846264338327950280e+00L;
 #endif
 
-DLLEXPORT long double
+long double
 atan2l(long double y, long double x)
 {
 	union IEEEl2bits ux, uy;

+ 9 - 4
src/e_atanh.c

@@ -12,8 +12,8 @@
  *
  */
 
-#include "cdefs-compat.h"
-//__FBSDID("$FreeBSD: src/lib/msun/src/e_atanh.c,v 1.8 2008/02/22 02:30:34 das Exp $");
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
 
 /* __ieee754_atanh(x)
  * Method :
@@ -33,14 +33,15 @@
  *
  */
 
-#include <openlibm_math.h>
+#include <float.h>
 
+#include "math.h"
 #include "math_private.h"
 
 static const double one = 1.0, huge = 1e300;
 static const double zero = 0.0;
 
-DLLEXPORT double
+double
 __ieee754_atanh(double x)
 {
 	double t;
@@ -61,3 +62,7 @@ __ieee754_atanh(double x)
 	    t = 0.5*log1p((x+x)/(one-x));
 	if(hx>=0) return t; else return -t;
 }
+
+#if LDBL_MANT_DIG == 53
+__weak_reference(atanh, atanhl);
+#endif

+ 4 - 5
src/e_atanhf.c

@@ -13,18 +13,17 @@
  * ====================================================
  */
 
-#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 <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
 
+#include "math.h"
 #include "math_private.h"
 
 static const float one = 1.0, huge = 1e30;
 
 static const float zero = 0.0;
 
-DLLEXPORT float
+float
 __ieee754_atanhf(float x)
 {
 	float t;

+ 74 - 0
src/e_atanhl.c

@@ -0,0 +1,74 @@
+/* from: FreeBSD: head/lib/msun/src/e_atanh.c 176451 2008-02-22 02:30:36Z das */
+
+/* @(#)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 <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * See e_atanh.c for complete comments.
+ *
+ * Converted to long double by David Schultz <das@FreeBSD.ORG> and
+ * Bruce D. Evans.
+ */
+
+#include <float.h>
+#ifdef __i386__
+#include <ieeefp.h>
+#endif
+
+#include "fpmath.h"
+#include "math.h"
+#include "math_private.h"
+
+/* EXP_TINY is the threshold below which we use atanh(x) ~= x. */
+#if LDBL_MANT_DIG == 64
+#define	EXP_TINY	-34
+#elif LDBL_MANT_DIG == 113
+#define	EXP_TINY	-58
+#else
+#error "Unsupported long double format"
+#endif
+
+#if LDBL_MAX_EXP != 0x4000
+/* We also require the usual expsign encoding. */
+#error "Unsupported long double format"
+#endif
+
+#define	BIAS	(LDBL_MAX_EXP - 1)
+
+static const double one = 1.0, huge = 1e300;
+static const double zero = 0.0;
+
+long double
+atanhl(long double x)
+{
+	long double t;
+	uint16_t hx, ix;
+
+	ENTERI();
+	GET_LDBL_EXPSIGN(hx, x);
+	ix = hx & 0x7fff;
+	if (ix >= 0x3fff)		/* |x| >= 1, or NaN or misnormal */
+	    RETURNI(fabsl(x) == 1 ? x / zero : (x - x) / (x - x));
+	if (ix < BIAS + EXP_TINY && (huge + x) > zero)
+	    RETURNI(x);			/* x is tiny */
+	SET_LDBL_EXPSIGN(x, ix);
+	if (ix < 0x3ffe) {		/* |x| < 0.5, or misnormal */
+	    t = x+x;
+	    t = 0.5*log1pl(t+t*x/(one-x));
+	} else 
+	    t = 0.5*log1pl((x+x)/(one-x));
+	RETURNI((hx & 0x8000) == 0 ? t : -t);
+}

+ 9 - 4
src/e_cosh.c

@@ -11,8 +11,8 @@
  * ====================================================
  */
 
-#include "cdefs-compat.h"
-//__FBSDID("$FreeBSD: src/lib/msun/src/e_cosh.c,v 1.10 2011/10/21 06:28:47 das Exp $");
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
 
 /* __ieee754_cosh(x)
  * Method : 
@@ -35,13 +35,14 @@
  *	only cosh(0)=1 is exact for finite x.
  */
 
-#include <openlibm_math.h>
+#include <float.h>
 
+#include "math.h"
 #include "math_private.h"
 
 static const double one = 1.0, half=0.5, huge = 1.0e300;
 
-DLLEXPORT double
+double
 __ieee754_cosh(double x)
 {
 	double t,w;
@@ -78,3 +79,7 @@ __ieee754_cosh(double x)
     /* |x| > overflowthresold, cosh(x) overflow */
 	return huge*huge;
 }
+
+#if (LDBL_MANT_DIG == 53)
+__weak_reference(cosh, coshl);
+#endif

+ 4 - 5
src/e_coshf.c

@@ -13,16 +13,15 @@
  * ====================================================
  */
 
-#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 <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
 
+#include "math.h"
 #include "math_private.h"
 
 static const float one = 1.0, half=0.5, huge = 1.0e30;
 
-DLLEXPORT float
+float
 __ieee754_coshf(float x)
 {
 	float t,w;

+ 130 - 0
src/e_coshl.c

@@ -0,0 +1,130 @@
+/* from: FreeBSD: head/lib/msun/src/e_coshl.c XXX */
+
+/*
+ * ====================================================
+ * 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 <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * See e_cosh.c for complete comments.
+ *
+ * Converted to long double by Bruce D. Evans.
+ */
+
+#include <float.h>
+#ifdef __i386__
+#include <ieeefp.h>
+#endif
+
+#include "fpmath.h"
+#include "math.h"
+#include "math_private.h"
+#include "k_expl.h"
+
+#if LDBL_MAX_EXP != 0x4000
+/* We also require the usual expsign encoding. */
+#error "Unsupported long double format"
+#endif
+
+#define	BIAS	(LDBL_MAX_EXP - 1)
+
+static const volatile long double huge = 0x1p10000L, tiny = 0x1p-10000L;
+#if LDBL_MANT_DIG == 64
+/*
+ * Domain [-1, 1], range ~[-1.8211e-21, 1.8211e-21]:
+ * |cosh(x) - c(x)| < 2**-68.8
+ */
+static const union IEEEl2bits
+C4u = LD80C(0xaaaaaaaaaaaaac78, -5,  4.16666666666666682297e-2L);
+#define	C4	C4u.e
+static const double
+C2  =  0.5,
+C6  =  1.3888888888888616e-3,		/*  0x16c16c16c16b99.0p-62 */
+C8  =  2.4801587301767953e-5,		/*  0x1a01a01a027061.0p-68 */
+C10 =  2.7557319163300398e-7,		/*  0x127e4fb6c9b55f.0p-74 */
+C12 =  2.0876768371393075e-9,		/*  0x11eed99406a3f4.0p-81 */
+C14 =  1.1469537039374480e-11,		/*  0x1938c67cd18c48.0p-89 */
+C16 =  4.8473490896852041e-14;		/*  0x1b49c429701e45.0p-97 */
+#elif LDBL_MANT_DIG == 113
+/*
+ * Domain [-1, 1], range ~[-2.3194e-37, 2.3194e-37]:
+ * |cosh(x) - c(x)| < 2**-121.69
+ */
+static const long double
+C4  =  4.16666666666666666666666666666666225e-2L,	/*  0x1555555555555555555555555554e.0p-117L */
+C6  =  1.38888888888888888888888888889434831e-3L,	/*  0x16c16c16c16c16c16c16c16c1dd7a.0p-122L */
+C8  =  2.48015873015873015873015871870962089e-5L,	/*  0x1a01a01a01a01a01a01a017af2756.0p-128L */
+C10 =  2.75573192239858906525574318600800201e-7L,	/*  0x127e4fb7789f5c72ef01c8a040640.0p-134L */
+C12 =  2.08767569878680989791444691755468269e-9L,	/*  0x11eed8eff8d897b543d0679607399.0p-141L */
+C14=  1.14707455977297247387801189650495351e-11L,	/*  0x193974a8c07c9d24ae169a7fa9b54.0p-149L */
+C16 =  4.77947733238737883626416876486279985e-14L;	/*  0x1ae7f3e733b814d4e1b90f5727fe4.0p-157L */
+static const double
+C2  =  0.5,
+C18 =  1.5619206968597871e-16,		/*  0x16827863b9900b.0p-105 */
+C20 =  4.1103176218528049e-19,		/*  0x1e542ba3d3c269.0p-114 */
+C22 =  8.8967926401641701e-22,		/*  0x10ce399542a014.0p-122 */
+C24 =  1.6116681626523904e-24,		/*  0x1f2c981d1f0cb7.0p-132 */
+C26 =  2.5022374732804632e-27;		/*  0x18c7ecf8b2c4a0.0p-141 */
+#else
+#error "Unsupported long double format"
+#endif /* LDBL_MANT_DIG == 64 */
+
+/* log(2**16385 - 0.5) rounded up: */
+static const float
+o_threshold =  1.13572168e4;		/*  0xb174de.0p-10 */
+
+long double
+coshl(long double x)
+{
+	long double hi,lo,x2,x4;
+	double dx2;
+	uint16_t ix;
+
+	GET_LDBL_EXPSIGN(ix,x);
+	ix &= 0x7fff;
+
+    /* x is INF or NaN */
+	if(ix>=0x7fff) return x*x;
+
+	ENTERI();
+
+    /* |x| < 1, return 1 or c(x) */
+	if(ix<0x3fff) {
+	    if (ix<BIAS-(LDBL_MANT_DIG+1)/2) 	/* |x| < TINY */
+		RETURNI(1+tiny);	/* cosh(tiny) = 1(+) with inexact */
+	    x2 = x*x;
+#if LDBL_MANT_DIG == 64
+	    x4 = x2*x2;
+	    RETURNI(((C16*x2 + C14)*x4 + (C12*x2 + C10))*(x4*x4*x2) +
+		((C8*x2 + C6)*x2 + C4)*x4 + C2*x2 + 1);
+#elif LDBL_MANT_DIG == 113
+	    dx2 = x2;
+	    RETURNI((((((((((((C26*dx2 + C24)*dx2 + C22)*dx2 +
+		C20)*x2 + C18)*x2 +
+		C16)*x2 + C14)*x2 + C12)*x2 + C10)*x2 + C8)*x2 + C6)*x2 +
+		C4)*(x2*x2) + C2*x2 + 1);
+#endif
+	}
+
+    /* |x| in [1, 64), return accurate exp(|x|)/2+1/exp(|x|)/2 */
+	if (ix < 0x4005) {
+	    k_hexpl(fabsl(x), &hi, &lo);
+	    RETURNI(lo + 0.25/(hi + lo) + hi);
+	}
+
+    /* |x| in [64, o_threshold], return correctly-overflowing exp(|x|)/2 */
+	if (fabsl(x) <= o_threshold)
+	    RETURNI(hexpl(fabsl(x)));
+
+    /* |x| > o_threshold, cosh(x) overflow */
+	RETURNI(huge*huge);
+}

+ 9 - 12
src/e_exp.c

@@ -10,8 +10,8 @@
  * ====================================================
  */
 
-#include "cdefs-compat.h"
-//__FBSDID("$FreeBSD: src/lib/msun/src/e_exp.c,v 1.14 2011/10/21 06:26:38 das Exp $");
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
 
 /* __ieee754_exp(x)
  * Returns the exponential of x.
@@ -77,14 +77,13 @@
  */
 
 #include <float.h>
-#include <openlibm_math.h>
 
+#include "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 */
@@ -99,9 +98,10 @@ P4   = -1.65339022054652515390e-06, /* 0xBEBBBD41, 0xC5D26BF1 */
 P5   =  4.13813679705723846039e-08; /* 0x3E663769, 0x72BEA4D0 */
 
 static volatile double
+huge	= 1.0e+300,
 twom1000= 9.33263618503218878990e-302;     /* 2**-1000=0x01700000,0*/
 
-DLLEXPORT double
+double
 __ieee754_exp(double x)	/* default IEEE double exp */
 {
 	double y,hi=0.0,lo=0.0,c,t,twopk;
@@ -125,13 +125,6 @@ __ieee754_exp(double x)	/* default IEEE double exp */
 	    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 */
@@ -165,3 +158,7 @@ __ieee754_exp(double x)	/* default IEEE double exp */
 	    return y*twopk*twom1000;
 	}
 }
+
+#if (LDBL_MANT_DIG == 53)
+__weak_reference(exp, expl);
+#endif

+ 7 - 6
src/e_expf.c

@@ -13,18 +13,17 @@
  * ====================================================
  */
 
-#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 <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
 
 #include <float.h>
-#include <openlibm_math.h>
 
+#include "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 */
@@ -39,9 +38,11 @@ invln2 =  1.4426950216e+00, 		/* 0x3fb8aa3b */
 P1 =  1.6666625440e-1,		/*  0xaaaa8f.0p-26 */
 P2 = -2.7667332906e-3;		/* -0xb55215.0p-32 */
 
-static volatile float twom100 = 7.8886090522e-31;      /* 2**-100=0x0d800000 */
+static volatile float
+huge	= 1.0e+30,
+twom100 = 7.8886090522e-31;      /* 2**-100=0x0d800000 */
 
-DLLEXPORT float
+float
 __ieee754_expf(float x)
 {
 	float y,hi=0.0,lo=0.0,c,t,twopk;

+ 4 - 5
src/e_fmod.c

@@ -11,8 +11,8 @@
  * ====================================================
  */
 
-#include "cdefs-compat.h"
-//__FBSDID("$FreeBSD: src/lib/msun/src/e_fmod.c,v 1.10 2008/02/22 02:30:34 das Exp $");
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
 
 /* 
  * __ieee754_fmod(x,y)
@@ -20,13 +20,12 @@
  * Method: shift and subtract
  */
 
-#include <openlibm_math.h>
-
+#include "math.h"
 #include "math_private.h"
 
 static const double one = 1.0, Zero[] = {0.0, -0.0,};
 
-DLLEXPORT double
+double
 __ieee754_fmod(double x, double y)
 {
 	int32_t n,hx,hy,hz,ix,iy,sx,i;

+ 4 - 5
src/e_fmodf.c

@@ -13,8 +13,8 @@
  * ====================================================
  */
 
-#include "cdefs-compat.h"
-//__FBSDID("$FreeBSD: src/lib/msun/src/e_fmodf.c,v 1.7 2008/02/22 02:30:34 das Exp $");
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
 
 /*
  * __ieee754_fmodf(x,y)
@@ -22,13 +22,12 @@
  * Method: shift and subtract
  */
 
-#include <openlibm_math.h>
-
+#include "math.h"
 #include "math_private.h"
 
 static const float one = 1.0, Zero[] = {0.0, -0.0,};
 
-DLLEXPORT float
+float
 __ieee754_fmodf(float x, float y)
 {
 	int32_t n,hx,hy,hz,ix,iy,sx,i;

+ 8 - 9
src/e_fmodl.c

@@ -10,29 +10,28 @@
  * ====================================================
  */
 
-#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 <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
 
 #include <float.h>
-#include <openlibm_math.h>
 #include <stdint.h>
 
 #include "fpmath.h"
-
+#include "math.h"
 #include "math_private.h"
 
 #define	BIAS (LDBL_MAX_EXP - 1)
 
 #if LDBL_MANL_SIZE > 32
-typedef	u_int64_t manl_t;
+typedef	uint64_t manl_t;
 #else
-typedef	u_int32_t manl_t;
+typedef	uint32_t manl_t;
 #endif
 
 #if LDBL_MANH_SIZE > 32
-typedef	u_int64_t manh_t;
+typedef	uint64_t manh_t;
 #else
-typedef	u_int32_t manh_t;
+typedef	uint32_t manh_t;
 #endif
 
 /*
@@ -62,7 +61,7 @@ static const long double one = 1.0, Zero[] = {0.0, -0.0,};
  * - 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.
  */
-DLLEXPORT long double
+long double
 fmodl(long double x, long double y)
 {
 	union IEEEl2bits ux, uy;

+ 33 - 0
src/e_gamma.c

@@ -0,0 +1,33 @@
+
+/* @(#)e_gamma.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/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/* __ieee754_gamma(x)
+ * Return the logarithm of the Gamma function of x.
+ *
+ * Method: call __ieee754_gamma_r
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+extern int signgam;
+
+double
+__ieee754_gamma(double x)
+{
+	return __ieee754_gamma_r(x,&signgam);
+}

+ 32 - 0
src/e_gamma_r.c

@@ -0,0 +1,32 @@
+
+/* @(#)e_gamma_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 <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/* __ieee754_gamma_r(x, signgamp)
+ * Reentrant version of the logarithm of the Gamma function 
+ * with user provide pointer for the sign of Gamma(x). 
+ *
+ * Method: See __ieee754_lgamma_r
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+double
+__ieee754_gamma_r(double x, int *signgamp)
+{
+	return __ieee754_lgamma_r(x,signgamp);
+}

+ 34 - 0
src/e_gammaf.c

@@ -0,0 +1,34 @@
+/* e_gammaf.c -- float version of e_gamma.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 <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/* __ieee754_gammaf(x)
+ * Return the logarithm of the Gamma function of x.
+ *
+ * Method: call __ieee754_gammaf_r
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+extern int signgam;
+
+float
+__ieee754_gammaf(float x)
+{
+	return __ieee754_gammaf_r(x,&signgam);
+}

+ 33 - 0
src/e_gammaf_r.c

@@ -0,0 +1,33 @@
+/* e_gammaf_r.c -- float version of e_gamma_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 <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/* __ieee754_gammaf_r(x, signgamp)
+ * Reentrant version of the logarithm of the Gamma function
+ * with user provide pointer for the sign of Gamma(x).
+ *
+ * Method: See __ieee754_lgammaf_r
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+float
+__ieee754_gammaf_r(float x, int *signgamp)
+{
+	return __ieee754_lgammaf_r(x,signgamp);
+}

+ 4 - 4
src/e_hypot.c

@@ -11,8 +11,8 @@
  * ====================================================
  */
 
-#include "cdefs-compat.h"
-//__FBSDID("$FreeBSD: src/lib/msun/src/e_hypot.c,v 1.14 2011/10/15 07:00:28 das Exp $");
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
 
 /* __ieee754_hypot(x,y)
  *
@@ -47,11 +47,11 @@
  */
 
 #include <float.h>
-#include <openlibm_math.h>
 
+#include "math.h"
 #include "math_private.h"
 
-DLLEXPORT double
+double
 __ieee754_hypot(double x, double y)
 {
 	double a,b,t1,t2,y1,y2,w;

+ 4 - 5
src/e_hypotf.c

@@ -13,14 +13,13 @@
  * ====================================================
  */
 
-#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 <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
 
+#include "math.h"
 #include "math_private.h"
 
-DLLEXPORT float
+float
 __ieee754_hypotf(float x, float y)
 {
 	float a,b,t1,t2,y1,y2,w;

+ 6 - 6
src/e_hypotl.c

@@ -10,15 +10,15 @@
  * ====================================================
  */
 
-#include "cdefs-compat.h"
-//__FBSDID("$FreeBSD: src/lib/msun/src/e_hypotl.c,v 1.3 2011/10/16 05:36:39 das Exp $");
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
 
 /* long double version of hypot().  See e_hypot.c for most comments. */
 
 #include <float.h>
-#include <openlibm_math.h>
 
 #include "fpmath.h"
+#include "math.h"
 #include "math_private.h"
 
 #define	GET_LDBL_MAN(h, l, v) do {	\
@@ -40,12 +40,12 @@
 #define	MAX_EXP		LDBL_MAX_EXP
 
 #if LDBL_MANL_SIZE > 32
-typedef	u_int64_t man_t;
+typedef	uint64_t man_t;
 #else
-typedef	u_int32_t man_t;
+typedef	uint32_t man_t;
 #endif
 
-DLLEXPORT long double
+long double
 hypotl(long double x, long double y)
 {
 	long double a=x,b=y,t1,t2,y1,y2,w;

+ 25 - 22
src/e_j0.c

@@ -11,10 +11,8 @@
  * ====================================================
  */
 
-#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 $");
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
 
 /* __ieee754_j0(x), __ieee754_y0(x)
  * Bessel function of the first and second kinds of order zero.
@@ -61,11 +59,12 @@
  *	3. Special cases: y0(0)=-inf, y0(x<0)=NaN, y0(inf)=0.
  */
 
-#include <openlibm_math.h>
-
+#include "math.h"
 #include "math_private.h"
 
-static double pzero(double), qzero(double);
+static __inline double pzero(double), qzero(double);
+
+static const volatile double vone = 1, vzero = 0;
 
 static const double
 huge 	= 1e300,
@@ -84,7 +83,7 @@ S04  =  1.16614003333790000205e-09; /* 0x3E1408BC, 0xF4745D8F */
 
 static const double zero = 0.0;
 
-DLLEXPORT double
+double
 __ieee754_j0(double x)
 {
 	double z, s,c,ss,cc,r,u,v;
@@ -118,7 +117,7 @@ __ieee754_j0(double x)
 	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;
+	        else 	      return one - x*x/4;
 	    }
 	}
 	z = x*x;
@@ -145,7 +144,7 @@ v02  =  7.60068627350353253702e-05, /* 0x3F13ECBB, 0xF578C6C1 */
 v03  =  2.59150851840457805467e-07, /* 0x3E91642D, 0x7FF202FD */
 v04  =  4.41110311332675467403e-10; /* 0x3DFE5018, 0x3BD6D9EF */
 
-DLLEXPORT double
+double
 __ieee754_y0(double x)
 {
 	double z, s,c,ss,cc,u,v;
@@ -153,10 +152,16 @@ __ieee754_y0(double x)
 
 	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;
+	/*
+	 * y0(NaN) = NaN.
+	 * y0(Inf) = 0.
+	 * y0(-Inf) = NaN and raise invalid exception.
+	 */
+	if(ix>=0x7ff00000) return vone/(x+x*x); 
+	/* y0(+-0) = -inf and raise divide-by-zero exception. */
+	if((ix|lx)==0) return -one/vzero;
+	/* y0(x<0) = NaN and raise invalid exception. */
+	if(hx<0) return vzero/vzero;
         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
@@ -271,19 +276,18 @@ static const double pS2[5] = {
   1.46576176948256193810e+01, /* 0x402D50B3, 0x44391809 */
 };
 
-	/* Note: This function is only called for ix>=0x40000000 (see above) */
-	static double pzero(double x)
+static __inline 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;}
+	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]))));
@@ -368,19 +372,18 @@ static const double qS2[6] = {
  -5.31095493882666946917e+00, /* 0xC0153E6A, 0xF8B32931 */
 };
 
-	/* Note: This function is only called for ix>=0x40000000 (see above) */
-	static double qzero(double x)
+static __inline 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;}
+	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])))));

+ 19 - 12
src/e_j0f.c

@@ -13,13 +13,19 @@
  * ====================================================
  */
 
-#include <assert.h>
-#include "cdefs-compat.h"
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
 
-#include <openlibm_math.h>
+/*
+ * See e_j0.c for complete comments.
+ */
+
+#include "math.h"
 #include "math_private.h"
 
-static float pzerof(float), qzerof(float);
+static __inline float pzerof(float), qzerof(float);
+
+static const volatile float vone = 1,  vzero = 0;
 
 static const float
 huge 	= 1e30,
@@ -38,7 +44,7 @@ S04  =  1.1661400734e-09; /* 0x30a045e8 */
 
 static const float zero = 0.0;
 
-DLLEXPORT float
+float
 __ieee754_j0f(float x)
 {
 	float z, s,c,ss,cc,r,u,v;
@@ -99,7 +105,7 @@ v02  =  7.6006865129e-05, /* 0x389f65e0 */
 v03  =  2.5915085189e-07, /* 0x348b216c */
 v04  =  4.4111031494e-10; /* 0x2ff280c2 */
 
-DLLEXPORT float
+float
 __ieee754_y0f(float x)
 {
 	float z, s,c,ss,cc,u,v;
@@ -107,10 +113,9 @@ __ieee754_y0f(float x)
 
 	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>=0x7f800000) return  vone/(x+x*x);
+	if(ix==0) return -one/vzero;
+	if(hx<0) return vzero/vzero;
         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
@@ -224,7 +229,8 @@ static const float pS2[5] = {
   1.4657617569e+01, /* 0x416a859a */
 };
 
-	static float pzerof(float x)
+static __inline float
+pzerof(float x)
 {
 	const float *p,*q;
 	float z,r,s;
@@ -319,7 +325,8 @@ static const float qS2[6] = {
  -5.3109550476e+00, /* 0xc0a9f358 */
 };
 
-	static float qzerof(float x)
+static __inline float
+qzerof(float x)
 {
 	const float *p,*q;
 	float s,r,z;

+ 24 - 21
src/e_j1.c

@@ -11,10 +11,8 @@
  * ====================================================
  */
 
-#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 $");
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
 
 /* __ieee754_j1(x), __ieee754_y1(x)
  * Bessel function of the first and second kinds of order zero.
@@ -61,11 +59,12 @@
  *	   by method mentioned above.
  */
 
-#include <openlibm_math.h>
-
+#include "math.h"
 #include "math_private.h"
 
-static double pone(double), qone(double);
+static __inline double pone(double), qone(double);
+
+static const volatile double vone = 1, vzero = 0;
 
 static const double
 huge    = 1e300,
@@ -85,7 +84,7 @@ s05  =  1.23542274426137913908e-11; /* 0x3DAB2ACF, 0xCFB97ED8 */
 
 static const double zero    = 0.0;
 
-DLLEXPORT double
+double
 __ieee754_j1(double x)
 {
 	double z, s,c,ss,cc,r,u,v,y;
@@ -142,7 +141,7 @@ static const double V0[5] = {
   1.66559246207992079114e-11, /* 0x3DB25039, 0xDACA772A */
 };
 
-DLLEXPORT double
+double
 __ieee754_y1(double x)
 {
 	double z, s,c,ss,cc,u,v;
@@ -150,10 +149,16 @@ __ieee754_y1(double x)
 
 	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;
+	/*
+	 * y1(NaN) = NaN.
+	 * y1(Inf) = 0.
+	 * y1(-Inf) = NaN and raise invalid exception.
+	 */
+	if(ix>=0x7ff00000) return  vone/(x+x*x); 
+	/* y1(+-0) = -inf and raise divide-by-zero exception. */
+        if((ix|lx)==0) return -one/vzero;
+	/* y1(x<0) = NaN and raise invalid exception. */
+        if(hx<0) return vzero/vzero;
         if(ix >= 0x40000000) {  /* |x| >= 2.0 */
                 s = sin(x);
                 c = cos(x);
@@ -265,19 +270,18 @@ static const double ps2[5] = {
   8.36463893371618283368e+00, /* 0x4020BAB1, 0xF44E5192 */
 };
 
-	/* Note: This function is only called for ix>=0x40000000 (see above) */
-	static double pone(double x)
+static __inline 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;}
+	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]))));
@@ -363,19 +367,18 @@ static const double qs2[6] = {
  -4.95949898822628210127e+00, /* 0xC013D686, 0xE71BE86B */
 };
 
-	/* Note: This function is only called for ix>=0x40000000 (see above) */
-	static double qone(double x)
+static __inline 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;}
+	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])))));

+ 20 - 12
src/e_j1f.c

@@ -13,12 +13,19 @@
  * ====================================================
  */
 
-#include <assert.h>
-#include "cdefs-compat.h"
-#include <openlibm_math.h>
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * See e_j1.c for complete comments.
+ */
+
+#include "math.h"
 #include "math_private.h"
 
-static float ponef(float), qonef(float);
+static __inline float ponef(float), qonef(float);
+
+static const volatile float vone = 1, vzero = 0;
 
 static const float
 huge    = 1e30,
@@ -38,7 +45,7 @@ s05  =  1.2354227016e-11; /* 0x2d59567e */
 
 static const float zero    = 0.0;
 
-DLLEXPORT float
+float
 __ieee754_j1f(float x)
 {
 	float z, s,c,ss,cc,r,u,v,y;
@@ -95,7 +102,7 @@ static const float V0[5] = {
   1.6655924903e-11, /* 0x2d9281cf */
 };
 
-DLLEXPORT float
+float
 __ieee754_y1f(float x)
 {
 	float z, s,c,ss,cc,u,v;
@@ -103,10 +110,9 @@ __ieee754_y1f(float x)
 
 	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>=0x7f800000) return  vone/(x+x*x);
+	if(ix==0) return -one/vzero;
+	if(hx<0) return vzero/vzero;
         if(ix >= 0x40000000) {  /* |x| >= 2.0 */
                 s = sinf(x);
                 c = cosf(x);
@@ -218,7 +224,8 @@ static const float ps2[5] = {
   8.3646392822e+00, /* 0x4105d590 */
 };
 
-	static float ponef(float x)
+static __inline float
+ponef(float x)
 {
 	const float *p,*q;
 	float z,r,s;
@@ -314,7 +321,8 @@ static const float qs2[6] = {
  -4.9594988823e+00, /* 0xc09eb437 */
 };
 
-	static float qonef(float x)
+static __inline float
+qonef(float x)
 {
 	const float *p,*q;
 	float  s,r,z;

+ 12 - 9
src/e_jn.c

@@ -11,8 +11,8 @@
  * ====================================================
  */
 
-#include "cdefs-compat.h"
-//__FBSDID("$FreeBSD: src/lib/msun/src/e_jn.c,v 1.11 2010/11/13 10:54:10 uqs Exp $");
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
 
 /*
  * __ieee754_jn(n, x), __ieee754_yn(n, x)
@@ -40,10 +40,11 @@
  *	
  */
 
-#include <openlibm_math.h>
-
+#include "math.h"
 #include "math_private.h"
 
+static const volatile double vone = 1, vzero = 0;
+
 static const double
 invsqrtpi=  5.64189583547756279280e-01, /* 0x3FE20DD7, 0x50429B6D */
 two   =  2.00000000000000000000e+00, /* 0x40000000, 0x00000000 */
@@ -51,7 +52,7 @@ one   =  1.00000000000000000000e+00; /* 0x3FF00000, 0x00000000 */
 
 static const double zero  =  0.00000000000000000000e+00;
 
-DLLEXPORT double
+double
 __ieee754_jn(int n, double x)
 {
 	int32_t i,hx,ix,lx, sgn;
@@ -212,7 +213,7 @@ __ieee754_jn(int n, double x)
 	if(sgn==1) return -b; else return b;
 }
 
-DLLEXPORT double
+double
 __ieee754_yn(int n, double x)
 {
 	int32_t i,hx,ix,lx;
@@ -221,10 +222,12 @@ __ieee754_yn(int n, double x)
 
 	EXTRACT_WORDS(hx,lx,x);
 	ix = 0x7fffffff&hx;
-    /* if Y(n,NaN) is NaN */
+	/* yn(n,NaN) = 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;
+	/* yn(n,+-0) = -inf and raise divide-by-zero exception. */
+	if((ix|lx)==0) return -one/vzero;
+	/* yn(n,x<0) = NaN and raise invalid exception. */
+	if(hx<0) return vzero/vzero;
 	sign = 1;
 	if(n<0){
 		n = -n;

+ 12 - 8
src/e_jnf.c

@@ -13,20 +13,25 @@
  * ====================================================
  */
 
-#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 <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
 
-#include <openlibm_math.h>
+/*
+ * See e_jn.c for complete comments.
+ */
 
+#include "math.h"
 #include "math_private.h"
 
+static const volatile float vone = 1, vzero = 0;
+
 static const float
 two   =  2.0000000000e+00, /* 0x40000000 */
 one   =  1.0000000000e+00; /* 0x3F800000 */
 
 static const float zero  =  0.0000000000e+00;
 
-DLLEXPORT float
+float
 __ieee754_jnf(int n, float x)
 {
 	int32_t i,hx,ix, sgn;
@@ -164,7 +169,7 @@ __ieee754_jnf(int n, float x)
 	if(sgn==1) return -b; else return b;
 }
 
-DLLEXPORT float
+float
 __ieee754_ynf(int n, float x)
 {
 	int32_t i,hx,ix,ib;
@@ -173,10 +178,9 @@ __ieee754_ynf(int n, float x)
 
 	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;
+	if(ix==0) return -one/vzero;
+	if(hx<0) return vzero/vzero;
 	sign = 1;
 	if(n<0){
 		n = -n;

+ 11 - 8
src/e_lgamma.c

@@ -12,8 +12,8 @@
  *
  */
 
-#include "cdefs-compat.h"
-//__FBSDID("$FreeBSD: src/lib/msun/src/e_lgamma.c,v 1.9 2008/02/22 02:30:35 das Exp $");
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
 
 /* __ieee754_lgamma(x)
  * Return the logarithm of the Gamma function of x.
@@ -21,16 +21,19 @@
  * Method: call __ieee754_lgamma_r
  */
 
-#include <openlibm_math.h>
+#include <float.h>
 
+#include "math.h"
 #include "math_private.h"
 
-DLLEXPORT double
+extern int signgam;
+
+double
 __ieee754_lgamma(double x)
 {
-#ifdef OPENLIBM_ONLY_THREAD_SAFE
-	int signgam;
-#endif
-
 	return __ieee754_lgamma_r(x,&signgam);
 }
+
+#if (LDBL_MANT_DIG == 53)
+__weak_reference(lgamma, lgammal);
+#endif

+ 81 - 76
src/e_lgamma_r.c

@@ -1,4 +1,3 @@
-
 /* @(#)e_lgamma_r.c 1.3 95/01/18 */
 /*
  * ====================================================
@@ -6,22 +5,21 @@
  *
  * Developed at SunSoft, a Sun Microsystems, Inc. business.
  * Permission to use, copy, modify, and distribute this
- * software is freely granted, provided that this notice 
+ * 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 $");
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
 
 /* __ieee754_lgamma_r(x, signgamp)
- * Reentrant version of the logarithm of the Gamma function 
- * with user provide pointer for the sign of Gamma(x). 
+ * 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 
+ * 	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,
@@ -59,20 +57,20 @@
  *	by
  *	  			    3       5             11
  *		w = w0 + w1*z + w2*z  + w3*z  + ... + w6*z
- *	where 
+ *	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 
+ *	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 
+ *	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
@@ -80,15 +78,17 @@
  *		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 <float.h>
 
+#include "math.h"
 #include "math_private.h"
 
+static const volatile double vzero = 0;
+
 static const double
-two52=  4.50359962737049600000e+15, /* 0x43300000, 0x00000000 */
+zero=  0.00000000000000000000e+00,
 half=  5.00000000000000000000e-01, /* 0x3FE00000, 0x00000000 */
 one =  1.00000000000000000000e+00, /* 0x3FF00000, 0x00000000 */
 pi  =  3.14159265358979311600e+00, /* 0x400921FB, 0x54442D18 */
@@ -155,44 +155,40 @@ 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)
+/*
+ * Compute sin(pi*x) without actually doing the pi*x multiplication.
+ * sin_pi(x) is only called for x < 0 and |x| < 2**(p-1) where p is
+ * the precision of x.
+ */
+static double
+sin_pi(double x)
 {
+	volatile double vz;
 	double y,z;
-	int n,ix;
+	int n;
 
-	GET_HIGH_WORD(ix,x);
-	ix &= 0x7fffffff;
+	y = -x;
 
-	if(ix<0x3fd00000) return __kernel_sin(pi*x,zero,0);
-	y = -x;		/* x is assume negative */
+	vz = y+0x1p52;			/* depend on 0 <= y < 0x1p52 */
+	z = vz-0x1p52;			/* rint(y) for the above range */
+	if (z == y)
+	    return zero;
+
+	vz = y+0x1p50;
+	GET_LOW_WORD(n,vz);		/* bits for rounded y (units 0.25) */
+	z = vz-0x1p50;			/* y rounded to a multiple of 0.25 */
+	if (z > y) {
+	    z -= 0.25;			/* adjust to round down */
+	    n--;
+	}
+	n &= 7;				/* octant of y mod 2 */
+	y = y - z + n * 0.25;		/* y mod 2 */
 
-    /*
-     * 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 1:
 	    case 2:   y =  __kernel_cos(pi*(0.5-y),zero); break;
-	    case 3:  
+	    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;
@@ -202,37 +198,41 @@ static const double zero=  0.00000000000000000000e+00;
 }
 
 
-DLLEXPORT double
+double
 __ieee754_lgamma_r(double x, int *signgamp)
 {
-	double t,y,z,nadj,p,p1,p2,p3,q,r,w;
+	double nadj,p,p1,p2,p3,q,r,t,w,y,z;
 	int32_t hx;
-	int i,lx,ix;
+	int i,ix,lx;
 
 	EXTRACT_WORDS(hx,lx,x);
 
-    /* purge off +-inf, NaN, +-0, tiny and negative arguments */
+    /* purge +-Inf and NaNs */
 	*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);
+
+    /* purge +-0 and tiny arguments */
+	*signgamp = 1-2*((uint32_t)hx>>31);
+	if(ix<0x3c700000) {	/* |x|<2**-56, return -log(|x|) */
+	    if((ix|lx)==0)
+	        return one/vzero;
+	    return -__ieee754_log(fabs(x));
 	}
+
+    /* purge negative integers and start evaluation for other x < 0 */
 	if(hx<0) {
+	    *signgamp = 1;
 	    if(ix>=0x43300000) 	/* |x|>=2**52, must be -integer */
-		return one/zero;
+		return one/vzero;
 	    t = sin_pi(x);
-	    if(t==zero) return one/zero; /* -integer */
+	    if(t==zero) return one/vzero; /* -integer */
 	    nadj = __ieee754_log(pi/fabs(t*x));
 	    if(t<zero) *signgamp = -1;
 	    x = -x;
 	}
 
-    /* purge off 1 and 2 */
+    /* purge 1 and 2 */
 	if((((ix-0x3ff00000)|lx)==0)||(((ix-0x40000000)|lx)==0)) r = 0;
     /* for x < 2.0 */
 	else if(ix<0x40000000) {
@@ -253,7 +253,7 @@ __ieee754_lgamma_r(double x, int *signgamp)
 		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;
+		r  += p-y/2; break;
 	      case 1:
 		z = y*y;
 		w = z*y;
@@ -261,38 +261,43 @@ __ieee754_lgamma_r(double x, int *signgamp)
 		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:	
+		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);
+		r += p1/p2-y/2;
 	    }
 	}
-	else if(ix<0x40200000) { 			/* x < 8.0 */
-	    i = (int)x;
-	    y = x-(double)i;
+    /* x < 8.0 */
+	else if(ix<0x40200000) {
+	    i = x;
+	    y = x-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;
+	    r = y/2+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 */
+	    case 7: z *= (y+6);		/* FALLTHRU */
+	    case 6: z *= (y+5);		/* FALLTHRU */
+	    case 5: z *= (y+4);		/* FALLTHRU */
+	    case 4: z *= (y+3);		/* FALLTHRU */
+	    case 3: z *= (y+2);		/* FALLTHRU */
 		    r += __ieee754_log(z); break;
 	    }
-    /* 8.0 <= x < 2**58 */
-	} else if (ix < 0x43900000) {
+    /* 8.0 <= x < 2**56 */
+	} else if (ix < 0x43700000) {
 	    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 */
+	} else
+    /* 2**56 <= x <= inf */
 	    r =  x*(__ieee754_log(x)-one);
 	if(hx<0) r = nadj - r;
 	return r;
 }
+
+#if (LDBL_MANT_DIG == 53)
+__weak_reference(lgamma_r, lgammal_r);
+#endif

+ 6 - 9
src/e_lgammaf.c

@@ -13,8 +13,8 @@
  * ====================================================
  */
 
-#include "cdefs-compat.h"
-//__FBSDID("$FreeBSD: src/lib/msun/src/e_lgammaf.c,v 1.8 2008/02/22 02:30:35 das Exp $");
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
 
 /* __ieee754_lgammaf(x)
  * Return the logarithm of the Gamma function of x.
@@ -22,16 +22,13 @@
  * Method: call __ieee754_lgammaf_r
  */
 
-#include <openlibm_math.h>
-
+#include "math.h"
 #include "math_private.h"
 
-DLLEXPORT float
+extern int signgam;
+
+float
 __ieee754_lgammaf(float x)
 {
-#ifdef OPENLIBM_ONLY_THREAD_SAFE
-	int signgam;
-#endif
-
 	return __ieee754_lgammaf_r(x,&signgam);
 }

+ 127 - 143
src/e_lgammaf_r.c

@@ -1,5 +1,6 @@
 /* e_lgammaf_r.c -- float version of e_lgamma_r.c.
  * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ * Conversion to float fixed By Steven G. Kargl.
  */
 
 /*
@@ -13,114 +14,97 @@
  * ====================================================
  */
 
-#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 <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
 
+#include "math.h"
 #include "math_private.h"
 
+static const volatile float vzero = 0;
+
 static const float
-two23=  8.3886080000e+06, /* 0x4b000000 */
-half=  5.0000000000e-01, /* 0x3f000000 */
-one =  1.0000000000e+00, /* 0x3f800000 */
+zero=  0,
+half=  0.5,
+one =  1,
 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)
+/*
+ * Domain y in [0x1p-27, 0.27], range ~[-3.4599e-10, 3.4590e-10]:
+ * |(lgamma(2 - y) + 0.5 * y) / y - a(y)| < 2**-31.4
+ */
+a0  =  7.72156641e-02, /* 0x3d9e233f */
+a1  =  3.22467119e-01, /* 0x3ea51a69 */
+a2  =  6.73484802e-02, /* 0x3d89ee00 */
+a3  =  2.06395667e-02, /* 0x3ca9144f */
+a4  =  6.98275631e-03, /* 0x3be4cf9b */
+a5  =  4.11768444e-03, /* 0x3b86eda4 */
+/*
+ * Domain x in [tc-0.24, tc+0.28], range ~[-5.6577e-10, 5.5677e-10]:
+ * |(lgamma(x) - tf) - t(x - tc)| < 2**-30.8.
+ */
+tc  =  1.46163213e+00, /* 0x3fbb16c3 */
+tf  = -1.21486291e-01, /* 0xbdf8cdce */
+t0  = -2.94064460e-11, /* 0xae0154b7 */
+t1  = -2.35939837e-08, /* 0xb2caabb8 */
+t2  =  4.83836412e-01, /* 0x3ef7b968 */
+t3  = -1.47586212e-01, /* 0xbe1720d7 */
+t4  =  6.46013096e-02, /* 0x3d844db1 */
+t5  = -3.28450352e-02, /* 0xbd068884 */
+t6  =  1.86483748e-02, /* 0x3c98c47a */
+t7  = -9.89206228e-03, /* 0xbc221251 */
+/*
+ * Domain y in [-0.1, 0.232], range ~[-8.4931e-10, 8.7794e-10]:
+ * |(lgamma(1 + y) + 0.5 * y) / y - u(y) / v(y)| < 2**-31.2
+ */
+u0  = -7.72156641e-02, /* 0xbd9e233f */
+u1  =  7.36789703e-01, /* 0x3f3c9e40 */
+u2  =  4.95649040e-01, /* 0x3efdc5b6 */
+v1  =  1.10958421e+00, /* 0x3f8e06db */
+v2  =  2.10598111e-01, /* 0x3e57a708 */
+v3  = -1.02995494e-02, /* 0xbc28bf71 */
+/*
+ * Domain x in (2, 3], range ~[-5.5189e-11, 5.2317e-11]:
+ * |(lgamma(y+2) - 0.5 * y) / y - s(y)/r(y)| < 2**-35.0
+ * with y = x - 2.
+ */
+s0 = -7.72156641e-02, /* 0xbd9e233f */
+s1 =  2.69987404e-01, /* 0x3e8a3bca */
+s2 =  1.42851010e-01, /* 0x3e124789 */
+s3 =  1.19389519e-02, /* 0x3c439b98 */
+r1 =  6.79650068e-01, /* 0x3f2dfd8c */
+r2 =  1.16058730e-01, /* 0x3dedb033 */
+r3 =  3.75673687e-03, /* 0x3b763396 */
+/*
+ * Domain z in [8, 0x1p24], range ~[-1.2640e-09, 1.2640e-09]:
+ * |lgamma(x) - (x - 0.5) * (log(x) - 1) - w(1/x)| < 2**-29.6.
+ */
+w0 =  4.18938547e-01, /* 0x3ed67f1d */
+w1 =  8.33332464e-02, /* 0x3daaaa9f */
+w2 = -2.76129087e-03; /* 0xbb34f6c6 */
+
+static float
+sin_pif(float x)
 {
+	volatile float vz;
 	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;
-            }
-        }
+	int n;
+
+	y = -x;
+
+	vz = y+0x1p23F;			/* depend on 0 <= y < 0x1p23 */
+	z = vz-0x1p23F;			/* rintf(y) for the above range */
+	if (z == y)
+	    return zero;
+
+	vz = y+0x1p21F;
+	GET_FLOAT_WORD(n,vz);		/* bits for rounded y (units 0.25) */
+	z = vz-0x1p21F;			/* y rounded to a multiple of 0.25 */
+	if (z > y) {
+	    z -= 0.25F;			/* adjust to round down */
+	    n--;
+	}
+	n &= 7;				/* octant of y mod 2 */
+	y = y - z + n * 0.25F;		/* y mod 2 */
+
 	switch (n) {
 	    case 0:   y =  __kernel_sindf(pi*y); break;
 	    case 1:
@@ -135,37 +119,41 @@ static const float zero=  0.0000000000e+00;
 }
 
 
-DLLEXPORT float
+float
 __ieee754_lgammaf_r(float x, int *signgamp)
 {
-	float t,y,z,nadj,p,p1,p2,p3,q,r,w;
+	float nadj,p,p1,p2,p3,q,r,t,w,y,z;
 	int32_t hx;
 	int i,ix;
 
 	GET_FLOAT_WORD(hx,x);
 
-    /* purge off +-inf, NaN, +-0, tiny and negative arguments */
+    /* purge +-Inf and NaNs */
 	*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);
+
+    /* purge +-0 and tiny arguments */
+	*signgamp = 1-2*((uint32_t)hx>>31);
+	if(ix<0x32000000) {		/* |x|<2**-27, return -log(|x|) */
+	    if(ix==0)
+	        return one/vzero;
+	    return -__ieee754_logf(fabsf(x));
 	}
+
+    /* purge negative integers and start evaluation for other x < 0 */
 	if(hx<0) {
-	    if(ix>=0x4b000000) 	/* |x|>=2**23, must be -integer */
-		return one/zero;
+	    *signgamp = 1;
+	    if(ix>=0x4b000000) 		/* |x|>=2**23, must be -integer */
+		return one/vzero;
 	    t = sin_pif(x);
-	    if(t==zero) return one/zero; /* -integer */
+	    if(t==zero) return one/vzero; /* -integer */
 	    nadj = __ieee754_logf(pi/fabsf(t*x));
 	    if(t<zero) *signgamp = -1;
 	    x = -x;
 	}
 
-    /* purge off 1 and 2 */
+    /* purge 1 and 2 */
 	if (ix==0x3f800000||ix==0x40000000) r = 0;
     /* for x < 2.0 */
 	else if(ix<0x40000000) {
@@ -176,55 +164,51 @@ __ieee754_lgammaf_r(float x, int *signgamp)
 	  	else {y = x; i=2;}
 	    } else {
 	  	r = zero;
-	        if(ix>=0x3fdda618) {y=(float)2.0-x;i=0;} /* [1.7316,2] */
+	        if(ix>=0x3fdda618) {y=2-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)))));
+		p1 = a0+z*(a2+z*a4);
+		p2 = z*(a1+z*(a3+z*a5));
 		p  = y*p1+p2;
-		r  += (p-(float)0.5*y); break;
+		r  += p-y/2; 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;
+		p = t0+y*t1+y*y*(t2+y*(t3+y*(t4+y*(t5+y*(t6+y*t7)))));
+		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);
+		p1 = y*(u0+y*(u1+y*u2));
+		p2 = one+y*(v1+y*(v2+y*v3));
+		r += p1/p2-y/2;
 	    }
 	}
-	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;
+    /* x < 8.0 */
+	else if(ix<0x41000000) {
+	    i = x;
+	    y = x-i;
+	    p = y*(s0+y*(s1+y*(s2+y*s3)));
+	    q = one+y*(r1+y*(r2+y*r3));
+	    r = y/2+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 */
+	    case 7: z *= (y+6);		/* FALLTHRU */
+	    case 6: z *= (y+5);		/* FALLTHRU */
+	    case 5: z *= (y+4);		/* FALLTHRU */
+	    case 4: z *= (y+3);		/* FALLTHRU */
+	    case 3: z *= (y+2);		/* FALLTHRU */
 		    r += __ieee754_logf(z); break;
 	    }
-    /* 8.0 <= x < 2**58 */
-	} else if (ix < 0x5c800000) {
+    /* 8.0 <= x < 2**27 */
+	} else if (ix < 0x4d000000) {
 	    t = __ieee754_logf(x);
 	    z = one/x;
 	    y = z*z;
-	    w = w0+z*(w1+y*(w2+y*(w3+y*(w4+y*(w5+y*w6)))));
+	    w = w0+z*(w1+y*w2);
 	    r = (x-half)*(t-one)+w;
 	} else
-    /* 2**58 <= x <= inf */
+    /* 2**27 <= x <= inf */
 	    r =  x*(__ieee754_logf(x)-one);
 	if(hx<0) r = nadj - r;
 	return r;

+ 18 - 8
src/e_lgammal.c

@@ -1,15 +1,25 @@
-#include "cdefs-compat.h"
+/* @(#)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 <openlibm_math.h>
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
 
+#include "math.h"
 #include "math_private.h"
 
-DLLEXPORT long double
+extern int signgam;
+
+long double
 lgammal(long double x)
 {
-#ifdef OPENLIBM_ONLY_THREAD_SAFE
-	int signgam;
-#endif
-
-	return (lgammal_r(x, &signgam));
+	return lgammal_r(x,&signgam);
 }

+ 11 - 5
src/e_log.c

@@ -11,8 +11,8 @@
  * ====================================================
  */
 
-#include "cdefs-compat.h"
-//__FBSDID("$FreeBSD: src/lib/msun/src/e_log.c,v 1.15 2008/03/29 16:37:59 das Exp $");
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
 
 /* __ieee754_log(x)
  * Return the logrithm of x
@@ -65,8 +65,9 @@
  * to produce the hexadecimal values shown.
  */
 
-#include <openlibm_math.h>
+#include <float.h>
 
+#include "math.h"
 #include "math_private.h"
 
 static const double
@@ -82,8 +83,9 @@ Lg6 = 1.531383769920937332e-01,  /* 3FC39A09 D078C69F */
 Lg7 = 1.479819860511658591e-01;  /* 3FC2F112 DF3E5244 */
 
 static const double zero   =  0.0;
+static volatile double vzero = 0.0;
 
-DLLEXPORT double
+double
 __ieee754_log(double x)
 {
 	double hfsq,f,s,z,R,w,t1,t2,dk;
@@ -95,7 +97,7 @@ __ieee754_log(double x)
 	k=0;
 	if (hx < 0x00100000) {			/* x < 2**-1022  */
 	    if (((hx&0x7fffffff)|lx)==0) 
-		return -two54/zero;		/* log(+-0)=-inf */
+		return -two54/vzero;		/* 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);
@@ -139,3 +141,7 @@ __ieee754_log(double x)
 		     return dk*ln2_hi-((s*(f-R)-dk*ln2_lo)-f);
 	}
 }
+
+#if (LDBL_MANT_DIG == 53)
+__weak_reference(log, logl);
+#endif

+ 11 - 5
src/e_log10.c

@@ -11,8 +11,8 @@
  * ====================================================
  */
 
-#include "cdefs-compat.h"
-//__FBSDID("$FreeBSD: src/lib/msun/src/e_log10.c,v 1.15 2011/10/15 05:23:28 das Exp $");
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
 
 /*
  * Return the base 10 logarithm of x.  See e_log.c and k_log.h for most
@@ -22,8 +22,9 @@
  * in not-quite-routine extra precision.
  */
 
-#include <openlibm_math.h>
+#include <float.h>
 
+#include "math.h"
 #include "math_private.h"
 #include "k_log.h"
 
@@ -35,8 +36,9 @@ log10_2hi  =  3.01029995663611771306e-01, /* 0x3FD34413, 0x509F6000 */
 log10_2lo  =  3.69423907715893078616e-13; /* 0x3D59FEF3, 0x11F12B36 */
 
 static const double zero   =  0.0;
+static volatile double vzero = 0.0;
 
-DLLEXPORT double
+double
 __ieee754_log10(double x)
 {
 	double f,hfsq,hi,lo,r,val_hi,val_lo,w,y,y2;
@@ -48,7 +50,7 @@ __ieee754_log10(double x)
 	k=0;
 	if (hx < 0x00100000) {			/* x < 2**-1022  */
 	    if (((hx&0x7fffffff)|lx)==0)
-		return -two54/zero;		/* log(+-0)=-inf */
+		return -two54/vzero;		/* 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);
@@ -86,3 +88,7 @@ __ieee754_log10(double x)
 
 	return val_lo + val_hi;
 }
+
+#if (LDBL_MANT_DIG == 53)
+__weak_reference(log10, log10l);
+#endif

+ 6 - 9
src/e_log10f.c

@@ -9,21 +9,17 @@
  * ====================================================
  */
 
-#include "cdefs-compat.h"
-//__FBSDID("$FreeBSD: src/lib/msun/src/e_log10f.c,v 1.13 2011/10/16 05:36:23 das Exp $");
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
 
 /*
  * Float version of e_log10.c.  See the latter for most comments.
  */
 
-#include <openlibm_math.h>
-
+#include "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 */
@@ -32,8 +28,9 @@ log10_2hi  =  3.0102920532e-01, /* 0x3e9a2080 */
 log10_2lo  =  7.9034151668e-07; /* 0x355427db */
 
 static const float zero   =  0.0;
+static volatile float vzero = 0.0;
 
-DLLEXPORT float
+float
 __ieee754_log10f(float x)
 {
 	float f,hfsq,hi,lo,r,y;
@@ -44,7 +41,7 @@ __ieee754_log10f(float x)
 	k=0;
 	if (hx < 0x00800000) {			/* x < 2**-126  */
 	    if ((hx&0x7fffffff)==0)
-		return -two25/zero;		/* log(+-0)=-inf */
+		return -two25/vzero;		/* 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);

+ 11 - 5
src/e_log2.c

@@ -11,8 +11,8 @@
  * ====================================================
  */
 
-#include "cdefs-compat.h"
-//__FBSDID("$FreeBSD: src/lib/msun/src/e_log2.c,v 1.4 2011/10/15 05:23:28 das Exp $");
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
 
 /*
  * Return the base 2 logarithm of x.  See e_log.c and k_log.h for most
@@ -24,8 +24,9 @@
  * in not-quite-routine extra precision.
  */
 
-#include <openlibm_math.h>
+#include <float.h>
 
+#include "math.h"
 #include "math_private.h"
 #include "k_log.h"
 
@@ -35,8 +36,9 @@ ivln2hi    =  1.44269504072144627571e+00, /* 0x3ff71547, 0x65200000 */
 ivln2lo    =  1.67517131648865118353e-10; /* 0x3de705fc, 0x2eefa200 */
 
 static const double zero   =  0.0;
+static volatile double vzero = 0.0;
 
-DLLEXPORT double
+double
 __ieee754_log2(double x)
 {
 	double f,hfsq,hi,lo,r,val_hi,val_lo,w,y;
@@ -48,7 +50,7 @@ __ieee754_log2(double x)
 	k=0;
 	if (hx < 0x00100000) {			/* x < 2**-1022  */
 	    if (((hx&0x7fffffff)|lx)==0)
-		return -two54/zero;		/* log(+-0)=-inf */
+		return -two54/vzero;		/* 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);
@@ -109,3 +111,7 @@ __ieee754_log2(double x)
 
 	return val_lo + val_hi;
 }
+
+#if (LDBL_MANT_DIG == 53)
+__weak_reference(log2, log2l);
+#endif

+ 6 - 9
src/e_log2f.c

@@ -9,29 +9,26 @@
  * ====================================================
  */
 
-#include "cdefs-compat.h"
-//__FBSDID("$FreeBSD: src/lib/msun/src/e_log2f.c,v 1.5 2011/10/15 05:23:28 das Exp $");
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
 
 /*
  * Float version of e_log2.c.  See the latter for most comments.
  */
 
-#include <openlibm_math.h>
-
+#include "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;
+static volatile float vzero = 0.0;
 
-DLLEXPORT float
+float
 __ieee754_log2f(float x)
 {
 	float f,hfsq,hi,lo,r,y;
@@ -42,7 +39,7 @@ __ieee754_log2f(float x)
 	k=0;
 	if (hx < 0x00800000) {			/* x < 2**-126  */
 	    if ((hx&0x7fffffff)==0)
-		return -two25/zero;		/* log(+-0)=-inf */
+		return -two25/vzero;		/* 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);

+ 6 - 6
src/e_logf.c

@@ -13,11 +13,10 @@
  * ====================================================
  */
 
-#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 <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
 
+#include "math.h"
 #include "math_private.h"
 
 static const float
@@ -31,8 +30,9 @@ Lg3 =      0x91e9ee.0p-25,	/* 0.28498786688 */
 Lg4 =      0xf89e26.0p-26;	/* 0.24279078841 */
 
 static const float zero   =  0.0;
+static volatile float vzero = 0.0;
 
-DLLEXPORT float
+float
 __ieee754_logf(float x)
 {
 	float hfsq,f,s,z,R,w,t1,t2,dk;
@@ -43,7 +43,7 @@ __ieee754_logf(float x)
 	k=0;
 	if (ix < 0x00800000) {			/* x < 2**-126  */
 	    if ((ix&0x7fffffff)==0)
-		return -two25/zero;		/* log(+-0)=-inf */
+		return -two25/vzero;		/* 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);

+ 11 - 17
src/e_pow.c

@@ -9,8 +9,8 @@
  * ====================================================
  */
 
-#include "cdefs-compat.h"
-//__FBSDID("$FreeBSD: src/lib/msun/src/e_pow.c,v 1.14 2011/10/21 06:26:07 das Exp $");
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
 
 /* __ieee754_pow(x,y) return x**y
  *
@@ -19,20 +19,20 @@
  *	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 
+ *	2. Perform y*log2(x) = n+y' by simulating multi-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
+ *	3.  (anything) ** NAN is NAN except 1 ** NAN = 1
  *	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
+ *	9.  +-1         ** +-INF is 1
  *	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
@@ -57,8 +57,7 @@
  * to produce the hexadecimal values shown.
  */
 
-#include <openlibm_math.h>
-
+#include "math.h"
 #include "math_private.h"
 
 static const double
@@ -94,7 +93,7 @@ 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*/
 
-DLLEXPORT double
+double
 __ieee754_pow(double x, double y)
 {
 	double z,ax,z_h,z_l,p_h,p_l;
@@ -142,7 +141,7 @@ __ieee754_pow(double x, double y)
 	if(ly==0) { 	
 	    if (iy==0x7ff00000) {	/* y is +-inf */
 	        if(((ix-0x3ff00000)|lx)==0)
-		    return  one;	/* (-1)**+-inf is NaN */
+		    return  one;	/* (-1)**+-inf is 1 */
 	        else if (ix >= 0x3ff00000)/* (|x|>1)**+-inf = inf,0 */
 		    return (hy>=0)? y: zero;
 	        else			/* (|x|<1)**-,+inf = inf,0 */
@@ -151,15 +150,10 @@ __ieee754_pow(double x, double y)
 	    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(hy==0x40000000) return x*x; /* y is  2 */
+	    if(hy==0x3fe00000) {	/* y is  0.5 */
 		if(hx>=0)	/* x >= +0 */
-                    return sqrt(x);
+		return sqrt(x);	
 	    }
 	}
 

+ 7 - 13
src/e_powf.c

@@ -13,11 +13,10 @@
  * ====================================================
  */
 
-#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 <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
 
+#include "math.h"
 #include "math_private.h"
 
 static const float
@@ -53,7 +52,7 @@ 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*/
 
-DLLEXPORT float
+float
 __ieee754_powf(float x, float y)
 {
 	float z,ax,z_h,z_l,p_h,p_l;
@@ -103,15 +102,10 @@ __ieee754_powf(float x, float y)
 	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(hy==0x40000000) return x*x; /* y is  2 */
+	if(hy==0x3f000000) {	/* y is  0.5 */
 	    if(hx>=0)	/* x >= +0 */
-                return __ieee754_sqrtf(x);
+	    return __ieee754_sqrtf(x);
 	}
 
 	ax   = fabsf(x);

+ 7 - 4
src/e_rem_pio2.c

@@ -13,8 +13,8 @@
  * 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 $");
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
 
 /* __ieee754_rem_pio2(x,y)
  * 
@@ -23,8 +23,8 @@
  */
 
 #include <float.h>
-#include <openlibm_math.h>
 
+#include "math.h"
 #include "math_private.h"
 
 /*
@@ -48,7 +48,10 @@ pio2_2t =  2.02226624879595063154e-21, /* 0x3BA3198A, 0x2E037073 */
 pio2_3  =  2.02226624871116645580e-21, /* 0x3BA3198A, 0x2E000000 */
 pio2_3t =  8.47842766036889956997e-32; /* 0x397B839A, 0x252049C1 */
 
-__inline int
+#ifdef INLINE_REM_PIO2
+static __inline __always_inline
+#endif
+int
 __ieee754_rem_pio2(double x, double *y)
 {
 	double z,w,t,r,fn;

+ 8 - 5
src/e_rem_pio2f.c

@@ -14,8 +14,8 @@
  * ====================================================
  */
 
-#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 $");
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
 
 /* __ieee754_rem_pio2f(x,y)
  *
@@ -25,13 +25,13 @@
  */
 
 #include <float.h>
-#include <openlibm_math.h>
 
+#include "math.h"
 #include "math_private.h"
 
 /*
  * invpio2:  53 bits of 2/pi
- * pio2_1:   first  33 bit of pi/2
+ * pio2_1:   first 25 bits of pi/2
  * pio2_1t:  pi/2 - pio2_1
  */
 
@@ -40,7 +40,10 @@ invpio2 =  6.36619772367581382433e-01, /* 0x3FE45F30, 0x6DC9C883 */
 pio2_1  =  1.57079631090164184570e+00, /* 0x3FF921FB, 0x50000000 */
 pio2_1t =  1.58932547735281966916e-08; /* 0x3E5110b4, 0x611A6263 */
 
-__inline int
+#ifdef INLINE_REM_PIO2F
+static __inline __always_inline
+#endif
+int
 __ieee754_rem_pio2f(float x, double *y)
 {
 	double w,r,fn;

+ 4 - 4
src/e_remainder.c

@@ -11,8 +11,8 @@
  * ====================================================
  */
 
-#include "cdefs-compat.h"
-//__FBSDID("$FreeBSD: src/lib/msun/src/e_remainder.c,v 1.12 2008/03/30 20:47:42 das Exp $");
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
 
 /* __ieee754_remainder(x,p)
  * Return :                  
@@ -24,14 +24,14 @@
  */
 
 #include <float.h>
-#include <openlibm_math.h>
 
+#include "math.h"
 #include "math_private.h"
 
 static const double zero = 0.0;
 
 
-DLLEXPORT double
+double
 __ieee754_remainder(double x, double p)
 {
 	int32_t hx,hp;

+ 4 - 5
src/e_remainderf.c

@@ -13,17 +13,16 @@
  * ====================================================
  */
 
-#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 <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
 
+#include "math.h"
 #include "math_private.h"
 
 static const float zero = 0.0;
 
 
-DLLEXPORT float
+float
 __ieee754_remainderf(float x, float p)
 {
 	int32_t hx,hp;

+ 4 - 5
src/e_remainderl.c

@@ -24,13 +24,12 @@
  * 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 <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
 
-#include <openlibm_math.h>
-#include "math_private.h"
+#include <math.h>
 
-DLLEXPORT long double
+long double
 remainderl(long double x, long double y)
 {
 	int quo;

+ 47 - 0
src/e_scalb.c

@@ -0,0 +1,47 @@
+
+/* @(#)e_scalb.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/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * __ieee754_scalb(x, fn) is provide for
+ * passing various standard test suite. One 
+ * should use scalbn() instead.
+ */
+
+#include "math.h"
+#include "math_private.h"
+
+#ifdef _SCALB_INT
+double
+__ieee754_scalb(double x, int fn)
+#else
+double
+__ieee754_scalb(double x, double fn)
+#endif
+{
+#ifdef _SCALB_INT
+	return scalbn(x,fn);
+#else
+	if (isnan(x)||isnan(fn)) return x*fn;
+	if (!finite(fn)) {
+	    if(fn>0.0) return x*fn;
+	    else       return x/(-fn);
+	}
+	if (rint(fn)!=fn) return (fn-fn)/(fn-fn);
+	if ( fn > 65000.0) return scalbn(x, 65000);
+	if (-fn > 65000.0) return scalbn(x,-65000);
+	return scalbn(x,(int)fn);
+#endif
+}

+ 43 - 0
src/e_scalbf.c

@@ -0,0 +1,43 @@
+/* e_scalbf.c -- float version of e_scalb.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 <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "math.h"
+#include "math_private.h"
+
+#ifdef _SCALB_INT
+float
+__ieee754_scalbf(float x, int fn)
+#else
+float
+__ieee754_scalbf(float x, float fn)
+#endif
+{
+#ifdef _SCALB_INT
+	return scalbnf(x,fn);
+#else
+	if ((isnanf)(x)||(isnanf)(fn)) return x*fn;
+	if (!finitef(fn)) {
+	    if(fn>(float)0.0) return x*fn;
+	    else       return x/(-fn);
+	}
+	if (rintf(fn)!=fn) return (fn-fn)/(fn-fn);
+	if ( fn > (float)65000.0) return scalbnf(x, 65000);
+	if (-fn > (float)65000.0) return scalbnf(x,-65000);
+	return scalbnf(x,(int)fn);
+#endif
+}

+ 9 - 4
src/e_sinh.c

@@ -11,8 +11,8 @@
  * ====================================================
  */
 
-#include "cdefs-compat.h"
-//__FBSDID("$FreeBSD: src/lib/msun/src/e_sinh.c,v 1.11 2011/10/21 06:28:47 das Exp $");
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
 
 /* __ieee754_sinh(x)
  * Method : 
@@ -32,13 +32,14 @@
  *	only sinh(0)=0 is exact for finite x.
  */
 
-#include <openlibm_math.h>
+#include <float.h>
 
+#include "math.h"
 #include "math_private.h"
 
 static const double one = 1.0, shuge = 1.0e307;
 
-DLLEXPORT double
+double
 __ieee754_sinh(double x)
 {
 	double t,h;
@@ -72,3 +73,7 @@ __ieee754_sinh(double x)
     /* |x| > overflowthresold, sinh(x) overflow */
 	return x*shuge;
 }
+
+#if (LDBL_MANT_DIG == 53)
+__weak_reference(sinh, sinhl);
+#endif

+ 4 - 5
src/e_sinhf.c

@@ -13,16 +13,15 @@
  * ====================================================
  */
 
-#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 <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
 
+#include "math.h"
 #include "math_private.h"
 
 static const float one = 1.0, shuge = 1.0e37;
 
-DLLEXPORT float
+float
 __ieee754_sinhf(float x)
 {
 	float t,h;

+ 131 - 0
src/e_sinhl.c

@@ -0,0 +1,131 @@
+/* from: FreeBSD: head/lib/msun/src/e_sinhl.c XXX */
+
+/*
+ * ====================================================
+ * 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 <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * See e_sinh.c for complete comments.
+ *
+ * Converted to long double by Bruce D. Evans.
+ */
+
+#include <float.h>
+#ifdef __i386__
+#include <ieeefp.h>
+#endif
+
+#include "fpmath.h"
+#include "math.h"
+#include "math_private.h"
+#include "k_expl.h"
+
+#if LDBL_MAX_EXP != 0x4000
+/* We also require the usual expsign encoding. */
+#error "Unsupported long double format"
+#endif
+
+#define	BIAS	(LDBL_MAX_EXP - 1)
+
+static const long double shuge = 0x1p16383L;
+#if LDBL_MANT_DIG == 64
+/*
+ * Domain [-1, 1], range ~[-6.6749e-22, 6.6749e-22]:
+ * |sinh(x)/x - s(x)| < 2**-70.3
+ */
+static const union IEEEl2bits
+S3u = LD80C(0xaaaaaaaaaaaaaaaa, -3,  1.66666666666666666658e-1L);
+#define	S3	S3u.e
+static const double
+S5  =  8.3333333333333332e-3,		/*  0x11111111111111.0p-59 */
+S7  =  1.9841269841270074e-4,		/*  0x1a01a01a01a070.0p-65 */
+S9  =  2.7557319223873889e-6,		/*  0x171de3a5565fe6.0p-71 */
+S11 =  2.5052108406704084e-8,		/*  0x1ae6456857530f.0p-78 */
+S13 =  1.6059042748655297e-10,		/*  0x161245fa910697.0p-85 */
+S15 =  7.6470006914396920e-13,		/*  0x1ae7ce4eff2792.0p-93 */
+S17 =  2.8346142308424267e-15;		/*  0x19882ce789ffc6.0p-101 */
+#elif LDBL_MANT_DIG == 113
+/*
+ * Domain [-1, 1], range ~[-2.9673e-36, 2.9673e-36]:
+ * |sinh(x)/x - s(x)| < 2**-118.0
+ */
+static const long double
+S3  =  1.66666666666666666666666666666666033e-1L,	/*  0x1555555555555555555555555553b.0p-115L */
+S5  =  8.33333333333333333333333333337643193e-3L,	/*  0x111111111111111111111111180f5.0p-119L */
+S7  =  1.98412698412698412698412697391263199e-4L,	/*  0x1a01a01a01a01a01a01a0176aad11.0p-125L */
+S9  =  2.75573192239858906525574406205464218e-6L,	/*  0x171de3a556c7338faac243aaa9592.0p-131L */
+S11 =  2.50521083854417187749675637460977997e-8L,	/*  0x1ae64567f544e38fe59b3380d7413.0p-138L */
+S13 =  1.60590438368216146368737762431552702e-10L,	/*  0x16124613a86d098059c7620850fc2.0p-145L */
+S15 =  7.64716373181980539786802470969096440e-13L,	/*  0x1ae7f3e733b814193af09ce723043.0p-153L */
+S17 =  2.81145725434775409870584280722701574e-15L;	/*  0x1952c77030c36898c3fd0b6dfc562.0p-161L */
+static const double
+S19=  8.2206352435411005e-18,		/*  0x12f49b4662b86d.0p-109 */
+S21=  1.9572943931418891e-20,		/*  0x171b8f2fab9628.0p-118 */
+S23 =  3.8679983530666939e-23,		/*  0x17617002b73afc.0p-127 */
+S25 =  6.5067867911512749e-26;		/*  0x1423352626048a.0p-136 */
+#else
+#error "Unsupported long double format"
+#endif /* LDBL_MANT_DIG == 64 */
+
+/* log(2**16385 - 0.5) rounded up: */
+static const float
+o_threshold =  1.13572168e4;		/*  0xb174de.0p-10 */
+
+long double
+sinhl(long double x)
+{
+	long double hi,lo,x2,x4;
+	double dx2,s;
+	int16_t ix,jx;
+
+	GET_LDBL_EXPSIGN(jx,x);
+	ix = jx&0x7fff;
+
+    /* x is INF or NaN */
+	if(ix>=0x7fff) return x+x;
+
+	ENTERI();
+
+	s = 1;
+	if (jx<0) s = -1;
+
+    /* |x| < 64, return x, s(x), or accurate s*(exp(|x|)/2-1/exp(|x|)/2) */
+	if (ix<0x4005) {		/* |x|<64 */
+	    if (ix<BIAS-(LDBL_MANT_DIG+1)/2) 	/* |x|<TINY */
+		if(shuge+x>1) RETURNI(x);  /* sinh(tiny) = tiny with inexact */
+	    if (ix<0x3fff) {		/* |x|<1 */
+		x2 = x*x;
+#if LDBL_MANT_DIG == 64
+		x4 = x2*x2;
+		RETURNI(((S17*x2 + S15)*x4 + (S13*x2 + S11))*(x2*x*x4*x4) +
+		    ((S9*x2 + S7)*x2 + S5)*(x2*x*x2) + S3*(x2*x) + x);
+#elif LDBL_MANT_DIG == 113
+		dx2 = x2;
+		RETURNI(((((((((((S25*dx2 + S23)*dx2 +
+		    S21)*x2 + S19)*x2 +
+		    S17)*x2 + S15)*x2 + S13)*x2 + S11)*x2 + S9)*x2 + S7)*x2 +
+		    S5)* (x2*x*x2) +
+		    S3*(x2*x) + x);
+#endif
+	    }
+	    k_hexpl(fabsl(x), &hi, &lo);
+	    RETURNI(s*(lo - 0.25/(hi + lo) + hi));
+	}
+
+    /* |x| in [64, o_threshold], return correctly-overflowing s*exp(|x|)/2 */
+	if (fabsl(x) <= o_threshold)
+	    RETURNI(s*hexpl(fabsl(x)));
+
+    /* |x| > o_threshold, sinh(x) overflow */
+	return x*shuge;
+}

+ 4 - 4
src/e_sqrt.c

@@ -11,8 +11,8 @@
  * ====================================================
  */
 
-#include "cdefs-compat.h"
-//__FBSDID("$FreeBSD: src/lib/msun/src/e_sqrt.c,v 1.11 2008/03/02 01:47:58 das Exp $");
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
 
 /* __ieee754_sqrt(x)
  * Return correctly rounded sqrt.
@@ -85,13 +85,13 @@
  */
 
 #include <float.h>
-#include <openlibm_math.h>
 
+#include "math.h"
 #include "math_private.h"
 
 static	const double	one	= 1.0, tiny=1.0e-300;
 
-DLLEXPORT double
+double
 __ieee754_sqrt(double x)
 {
 	double z;

+ 5 - 2
src/e_sqrtf.c

@@ -13,13 +13,16 @@
  * ====================================================
  */
 
-#include <openlibm_math.h>
+#ifndef lint
+static char rcsid[] = "$FreeBSD$";
+#endif
 
+#include "math.h"
 #include "math_private.h"
 
 static	const float	one	= 1.0, tiny=1.0e-30;
 
-DLLEXPORT float
+float
 __ieee754_sqrtf(float x)
 {
 	float z;

+ 5 - 8
src/e_sqrtl.c

@@ -24,15 +24,14 @@
  * 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 <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
 
+#include <fenv.h>
 #include <float.h>
-#include <openlibm_fenv.h>
-#include <openlibm_math.h>
 
 #include "fpmath.h"
-#include "math_private.h"
+#include "math.h"
 
 /* Return (x + ulp) for normal positive x. Assumes no overflow. */
 static inline long double
@@ -66,16 +65,14 @@ dec(long double x)
 	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.
  */
 
-DLLEXPORT long double
+long double
 sqrtl(long double x)
 {
 	union IEEEl2bits u;

+ 184 - 0
src/fenv-softfloat.h

@@ -0,0 +1,184 @@
+/*-
+ * 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 */

+ 13 - 1
src/fpmath.h

@@ -34,7 +34,7 @@
 #elif defined(__i386__) || defined(__x86_64__)
 #ifdef __LP64__
 #include "amd64_fpmath.h"
-#else 
+#else
 #include "i386_fpmath.h"
 #endif
 #elif defined(__powerpc__)
@@ -128,4 +128,16 @@ union IEEEd2bits {
 	} bits;
 };
 
+#if defined(__aarch64__)
+#include "aarch64_fpmath.h"
+#elif defined(__arm__)
+#include "arm_fpmath.h"
+#elif defined(__i386__) || defined(__x86_64__)
+#ifdef __LP64__
+#include "amd64_fpmath.h"
+#else
+#include "i386_fpmath.h"
+#endif
+#endif
+
 #endif

+ 63 - 0
src/imprecise.c

@@ -0,0 +1,63 @@
+/*-
+ * Copyright (c) 2013 David Chisnall
+ * 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$
+ */
+
+#include <float.h>
+#include <math.h>
+
+/*
+ * If long double is not the same size as double, then these will lose
+ * precision and we should emit a warning whenever something links against
+ * them.
+ */
+#if (LDBL_MANT_DIG > 53)
+#define WARN_IMPRECISE(x) \
+	__warn_references(x, # x " has lower than advertised precision");
+#else
+#define WARN_IMPRECISE(x)
+#endif
+/*
+ * Declare the functions as weak variants so that other libraries providing
+ * real versions can override them.
+ */
+#define	DECLARE_WEAK(x)\
+	__weak_reference(imprecise_## x, x);\
+	WARN_IMPRECISE(x)
+
+long double
+imprecise_powl(long double x, long double y)
+{
+
+	return pow(x, y);
+}
+DECLARE_WEAK(powl);
+
+#define DECLARE_IMPRECISE(f) \
+	long double imprecise_ ## f ## l(long double v) { return f(v); }\
+	DECLARE_WEAK(f ## l)
+
+DECLARE_IMPRECISE(tgamma);

+ 4 - 5
src/k_cos.c

@@ -11,8 +11,8 @@
  * ====================================================
  */
 
-#include "cdefs-compat.h"
-//__FBSDID("$FreeBSD: src/lib/msun/src/k_cos.c,v 1.12 2008/02/19 12:54:14 bde Exp $");
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
 
 /*
  * __kernel_cos( x,  y )
@@ -53,8 +53,7 @@
  *	   any extra precision in w.
  */
 
-#include <openlibm_math.h>
-
+#include "math.h"
 #include "math_private.h"
 
 static const double
@@ -66,7 +65,7 @@ C4  = -2.75573143513906633035e-07, /* 0xBE927E4F, 0x809C52AD */
 C5  =  2.08757232129817482790e-09, /* 0x3E21EE9E, 0xBDB4B1C4 */
 C6  = -1.13596475577881948265e-11; /* 0xBDA8FAE9, 0xBE8838D4 */
 
-DLLEXPORT double
+double
 __kernel_cos(double x, double y)
 {
 	double hz,z,r,w;

+ 6 - 8
src/k_cosf.c

@@ -15,12 +15,11 @@
  */
 
 #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 $");
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
 #endif
 
-#include <openlibm_math.h>
-
+#include "math.h"
 #include "math_private.h"
 
 /* |cos(x) - c(x)| < 2**-34.1 (~[-5.37e-11, 5.295e-11]). */
@@ -31,11 +30,10 @@ C1  =  0x155553e1053a42.0p-57,	/*  0.0416666233237390631894 */
 C2  = -0x16c087e80f1e27.0p-62,	/* -0.00138867637746099294692 */
 C3  =  0x199342e0ee5069.0p-68;	/*  0.0000243904487962774090654 */
 
-#ifndef INLINE_KERNEL_COSDF
-extern
+#ifdef INLINE_KERNEL_COSDF
+static __inline
 #endif
-//__inline float
-DLLEXPORT float
+float
 __kernel_cosdf(double x)
 {
 	double r, w, z;

+ 8 - 8
src/k_exp.c

@@ -24,15 +24,15 @@
  * 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 <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
 
-#include <openlibm_complex.h>
-#include <openlibm_math.h>
+#include <complex.h>
 
+#include "math.h"
 #include "math_private.h"
 
-static const u_int32_t k = 1799;		/* constant for reduction */
+static const uint32_t k = 1799;		/* constant for reduction */
 static const double kln2 =  1246.97177782734161156;	/* k * ln2 */
 
 /*
@@ -46,7 +46,7 @@ static double
 __frexp_exp(double x, int *expt)
 {
 	double exp_x;
-	u_int32_t hx;
+	uint32_t hx;
 
 	/*
 	 * We use exp(x) = exp(x - kln2) * 2**k, carefully chosen to
@@ -71,7 +71,7 @@ __frexp_exp(double x, int *expt)
  * has filtered out very large x, for which overflow would be inevitable.
  */
 
-DLLEXPORT double
+double
 __ldexp_exp(double x, int expt)
 {
 	double exp_x, scale;
@@ -83,7 +83,7 @@ __ldexp_exp(double x, int expt)
 	return (exp_x * scale);
 }
 
-DLLEXPORT double complex
+double complex
 __ldexp_cexp(double complex z, int expt)
 {
 	double x, y, exp_x, scale1, scale2;

+ 9 - 9
src/k_expf.c

@@ -24,15 +24,15 @@
  * 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 <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
 
-#include <openlibm_complex.h>
-#include <openlibm_math.h>
+#include <complex.h>
 
+#include "math.h"
 #include "math_private.h"
 
-static const u_int32_t k = 235;			/* constant for reduction */
+static const uint32_t k = 235;			/* constant for reduction */
 static const float kln2 =  162.88958740F;	/* k * ln2 */
 
 /*
@@ -44,8 +44,8 @@ static const float kln2 =  162.88958740F;	/* k * ln2 */
 static float
 __frexp_expf(float x, int *expt)
 {
-	double exp_x;
-	u_int32_t hx;
+	float exp_x;
+	uint32_t hx;
 
 	exp_x = expf(x - kln2);
 	GET_FLOAT_WORD(hx, exp_x);
@@ -54,7 +54,7 @@ __frexp_expf(float x, int *expt)
 	return (exp_x);
 }
 
-DLLEXPORT float
+float
 __ldexp_expf(float x, int expt)
 {
 	float exp_x, scale;
@@ -66,7 +66,7 @@ __ldexp_expf(float x, int expt)
 	return (exp_x * scale);
 }
 
-DLLEXPORT float complex
+float complex
 __ldexp_cexpf(float complex z, int expt)
 {
 	float x, y, exp_x, scale1, scale2;

+ 2 - 2
src/k_log.h

@@ -11,8 +11,8 @@
  * ====================================================
  */
 
-#include "cdefs-compat.h"
-//__FBSDID("$FreeBSD: src/lib/msun/src/k_log.h,v 1.2 2011/10/15 05:23:28 das Exp $");
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
 
 /*
  * k_log1p(f):

+ 2 - 2
src/k_logf.h

@@ -9,8 +9,8 @@
  * ====================================================
  */
 
-#include "cdefs-compat.h"
-//__FBSDID("$FreeBSD: src/lib/msun/src/k_logf.h,v 1.3 2011/10/15 05:23:28 das Exp $");
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
 
 /*
  * Float version of k_log.h.  See the latter for most comments.

+ 5 - 5
src/k_rem_pio2.c

@@ -11,8 +11,8 @@
  * ====================================================
  */
 
-#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 $");
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
 
 /*
  * __kernel_rem_pio2(x,y,e0,nx,prec)
@@ -45,7 +45,7 @@
  *			z    = (z-x[i])*2**24
  *
  *
- *	y[]	ouput result in an array of double precision numbers.
+ *	y[]	output result in an array of double precision numbers.
  *		The dimension of y[] is:
  *			24-bit  precision	1
  *			53-bit  precision	2
@@ -130,8 +130,8 @@
  */
 
 #include <float.h>
-#include <openlibm_math.h>
 
+#include "math.h"
 #include "math_private.h"
 
 static const int init_jk[] = {3,4,4,6}; /* initial value for jk */
@@ -290,7 +290,7 @@ one    = 1.0,
 two24   =  1.67772160000000000000e+07, /* 0x41700000, 0x00000000 */
 twon24  =  5.96046447753906250000e-08; /* 0x3E700000, 0x00000000 */
 
-DLLEXPORT int
+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;

部分文件因为文件数量过多而无法显示