libm: Sync with FreeBSD (~50 math functions added)
authorJohn Marino <draco@marino.st>
Wed, 21 Dec 2011 17:10:04 +0000 (18:10 +0100)
committerJohn Marino <draco@marino.st>
Thu, 22 Dec 2011 07:21:23 +0000 (08:21 +0100)
The main purpose of syncing with FreeBSD is to obtain numerous "long double"
functions which are required for C99 compliance.  There are still many
functions missing.  According to g++ testsuite, the following 10 functions
still must be implemented at least:
        coshl           logl            expl
        sinhl           log2l           expm1l
        acoshl          log10l
        asinhl          log1pl

Also known missing are nexttowardl, tgammal, and the long double version of
most of several complex functions.

A few years ago the freebsd-based math library was thrown out in favor of
the NetBSD version.  It may be time to reverse that and sync the entire
libm with FreeBSD.  Right now the DragonFly libm is a mixture between the
two and it doesn't divide nicely.  All the rounding and rint functions from
NetBSD had to be thrown out as well as the "kernel" functions.  For the
short term this is okay, but in the long term it would be a good idea to
start tracking FreeBSD again.  They are maintaining this library more
frequently and adding more functions more rapidly than NetBSD, so it would
be good to piggy-back on that effort.

The man page will be committed separately.

95 files changed:
include/complex.h
include/math.h
lib/libm/arch/i386/Makefile.inc
lib/libm/arch/i386/e_remainderl.S [copied from lib/libm/src/s_roundf.c with 57% similarity]
lib/libm/arch/i386/e_sqrtl.S [copied from lib/libm/src/s_roundf.c with 62% similarity]
lib/libm/arch/i386/lrint.S [deleted file]
lib/libm/arch/i386/s_lrint.S [copied from lib/libm/src/s_copysignl.c with 72% similarity]
lib/libm/arch/i386/s_lrintf.S [copied from lib/libm/src/s_copysignl.c with 72% similarity]
lib/libm/arch/i386/s_lrintl.S [copied from lib/libm/src/s_copysignl.c with 71% similarity]
lib/libm/arch/i386/s_remquol.S [new file with mode: 0644]
lib/libm/arch/i386/s_scalbnf.S
lib/libm/arch/i386/s_scalbnl.S
lib/libm/complex/Makefile.inc
lib/libm/complex/s_cargl.c [copied from lib/libm/src/s_copysignl.c with 77% similarity]
lib/libm/complex/s_csqrtl.c [new file with mode: 0644]
lib/libm/complex/w_cabsl.c [new file with mode: 0644]
lib/libm/src/Makefile.inc
lib/libm/src/b_exp.c [new file with mode: 0644]
lib/libm/src/b_log.c [new file with mode: 0644]
lib/libm/src/b_tgamma.c [new file with mode: 0644]
lib/libm/src/e_acosl.c [new file with mode: 0644]
lib/libm/src/e_asinl.c [new file with mode: 0644]
lib/libm/src/e_atan2l.c [new file with mode: 0644]
lib/libm/src/e_fmodl.c [new file with mode: 0644]
lib/libm/src/e_hypotl.c [new file with mode: 0644]
lib/libm/src/e_lgamma_r.c
lib/libm/src/e_lgammaf_r.c
lib/libm/src/e_log2.c
lib/libm/src/e_log2f.c
lib/libm/src/e_rem_pio2.c
lib/libm/src/e_rem_pio2f.c
lib/libm/src/e_rem_pio2l.h [new file with mode: 0644]
lib/libm/src/e_remainderl.c [copied from lib/libm/src/s_copysignl.c with 77% similarity]
lib/libm/src/e_sqrtl.c [new file with mode: 0644]
lib/libm/src/invtrig.c [new file with mode: 0644]
lib/libm/src/invtrig.h [new file with mode: 0644]
lib/libm/src/k_cosf.c
lib/libm/src/k_cosl.c [new file with mode: 0644]
lib/libm/src/k_rem_pio2.c
lib/libm/src/k_sinf.c
lib/libm/src/k_sinl.c [new file with mode: 0644]
lib/libm/src/k_tanf.c
lib/libm/src/k_tanl.c [new file with mode: 0644]
lib/libm/src/llrint.c [deleted file]
lib/libm/src/llrintf.c [deleted file]
lib/libm/src/llround.c [deleted file]
lib/libm/src/llroundf.c [deleted file]
lib/libm/src/lrint.c [deleted file]
lib/libm/src/lrintf.c [deleted file]
lib/libm/src/math_private.h
lib/libm/src/mathimpl.h [new file with mode: 0644]
lib/libm/src/s_atanl.c [new file with mode: 0644]
lib/libm/src/s_cbrtl.c [new file with mode: 0644]
lib/libm/src/s_ceill.c [new file with mode: 0644]
lib/libm/src/s_copysignl.c
lib/libm/src/s_cosf.c
lib/libm/src/s_cosl.c [copied from lib/libm/src/s_roundf.c with 57% similarity]
lib/libm/src/s_exp2.c
lib/libm/src/s_exp2f.c
lib/libm/src/s_exp2l.c [new file with mode: 0644]
lib/libm/src/s_fabs.c [moved from lib/libm/src/s_ldexpf.c with 52% similarity]
lib/libm/src/s_floorl.c [new file with mode: 0644]
lib/libm/src/s_fma.c [new file with mode: 0644]
lib/libm/src/s_fmaf.c [moved from lib/libm/src/lroundf.c with 52% similarity]
lib/libm/src/s_fmal.c [new file with mode: 0644]
lib/libm/src/s_llrint.c [new file with mode: 0644]
lib/libm/src/s_llrintf.c [new file with mode: 0644]
lib/libm/src/s_llrintl.c [new file with mode: 0644]
lib/libm/src/s_llround.c [new file with mode: 0644]
lib/libm/src/s_llroundf.c [new file with mode: 0644]
lib/libm/src/s_llroundl.c [new file with mode: 0644]
lib/libm/src/s_lrint.c [copied from lib/libm/src/s_nearbyint.c with 65% similarity]
lib/libm/src/s_lrintf.c [new file with mode: 0644]
lib/libm/src/s_lrintl.c [new file with mode: 0644]
lib/libm/src/s_lround.c [copied from lib/libm/src/s_nearbyint.c with 56% similarity]
lib/libm/src/s_lroundf.c [new file with mode: 0644]
lib/libm/src/s_lroundl.c [new file with mode: 0644]
lib/libm/src/s_modf.c [new file with mode: 0644]
lib/libm/src/s_modfl.c [new file with mode: 0644]
lib/libm/src/s_nearbyint.c
lib/libm/src/s_nexttowardf.c [new file with mode: 0644]
lib/libm/src/s_remquo.c
lib/libm/src/s_remquof.c
lib/libm/src/s_remquol.c [new file with mode: 0644]
lib/libm/src/s_rintl.c [moved from lib/libm/src/lround.c with 50% similarity]
lib/libm/src/s_round.c
lib/libm/src/s_roundf.c
lib/libm/src/s_roundl.c [copied from lib/libm/src/s_round.c with 85% similarity]
lib/libm/src/s_scalbln.c [copied from lib/libm/src/s_nearbyint.c with 69% similarity]
lib/libm/src/s_sinf.c
lib/libm/src/s_sinl.c [copied from lib/libm/src/s_roundf.c with 59% similarity]
lib/libm/src/s_tanf.c
lib/libm/src/s_tanl.c [copied from lib/libm/src/s_round.c with 56% similarity]
lib/libm/src/s_tgammaf.c [copied from lib/libm/src/s_copysignl.c with 69% similarity]
lib/libm/src/s_truncl.c [new file with mode: 0644]

index d73233f..cc842ee 100644 (file)
@@ -109,6 +109,7 @@ float complex clogf(float complex);
 /* 7.3.8.1 The cabs functions */
 double cabs(double complex);
 float cabsf(float complex);
+long double cabsl (long double complex);
 
 /* 7.3.8.2 The cpow functions */
 double complex cpow(double complex, double complex);
@@ -117,11 +118,13 @@ float complex cpowf(float complex, float complex);
 /* 7.3.8.3 The csqrt functions */
 double complex csqrt(double complex);
 float complex csqrtf(float complex);
+long double complex csqrtl(long double complex);
 
 /* 7.3.9 Manipulation functions */
 /* 7.3.9.1 The carg functions */
 double carg(double complex);
 float cargf(float complex);
+long double cargl(long double complex);
 
 /* 7.3.9.2 The cimag functions */
 double cimag(double complex);
index 125557e..2902294 100644 (file)
@@ -205,6 +205,7 @@ double      j0(double);
 double j1(double);
 double jn(int, double);
 double lgamma(double);
+double tgamma(double);
 double y0(double);
 double y1(double);
 double yn(int, double);
@@ -266,7 +267,6 @@ float       expf(float);
 float   exp2f(float);
 float  expm1f(float);
 float  frexpf(float, int *);
-long double    frexpl(long double, int *);
 int    ilogbf(float);
 float  ldexpf(float, int);
 float  logf(float);
@@ -275,13 +275,13 @@ float     log10f(float);
 float  log1pf(float);
 float  logbf(float);
 float  modff(float, float *);
+float  scalblnf(float, long);
 float  scalbnf(float, int);
 
 /* 7.12.7 power / absolute */
 
 float  cbrtf(float);
 float  fabsf(float);
-long double    fabsl(long double);
 float  hypotf(float, float);
 float  powf(float, float);
 float  sqrtf(float);
@@ -291,6 +291,7 @@ float       sqrtf(float);
 float  erff(float);
 float  erfcf(float);
 float  lgammaf(float);
+float  tgammaf(float);
 
 /* 7.12.9 nearest integer */
 
@@ -328,27 +329,27 @@ float  remquof(float, float, int *);
 /* 7.12.11 manipulation */
 
 float  copysignf(float, float);
-long double copysignl(long double, long double);
-
 double nan(const char *);
 float  nanf(const char *);
-long double    nanl(const char *);
 float  nextafterf(float, float);
-long double nextafterl(long double, long double);
-double nexttoward (double, long double);
 
 /* 7.12.12 maximum, minimum, positive difference */
 double fdim(double, double);
 float  fdimf(float, float);
-long double    fdiml(long double, long double);
 
 double fmax(double, double);
 float  fmaxf(float, float);
-long double    fmaxl(long double, long double);
 
 double  fmin(double, double);
 float   fminf(float, float);
-long double     fminl(long double, long double);
+
+
+/* isoC99 */
+double fma  (double, double, double);
+float  fmaf (float,  float,  float);
+
+
+
 
 #endif /* __ISO_C_VISIBLE >= 1999 */
 
@@ -397,6 +398,7 @@ double      significand(double);
  * Functions callable from C, intended to support IEEE arithmetic.
  */
 double copysign(double, double);
+double scalbln(double, long);
 double scalbn(double, int);
 
 /*
@@ -462,16 +464,52 @@ int       __signbitf(float);
 int    __signbitd(double);
 
 #ifdef __HAVE_LONG_DOUBLE
-int    __fpclassifyl(long double);
-int    __isfinitel(long double);
-int    __isinfl(long double);
-int    __isnanl(long double);
-int    __signbitl(long double);
+int    __fpclassifyl       (long double);
+int    __isfinitel         (long double);
+int    __isinfl            (long double);
+int    __isnanl            (long double);
+int    __signbitl          (long double);
+
+long double    acosl       (long double);
+long double    asinl       (long double);
+long double    atan2l      (long double, long double);
+long double    atanl       (long double);
+long double    ceill       (long double);
+long double    cosl        (long double);
+long double    cbrtl       (long double);
+long double    copysignl   (long double, long double);
+long double    fdiml       (long double, long double);
+long double    exp2l       (long double);
+long double    fabsl       (long double);
+long double    floorl      (long double);
+long double    fmal        (long double, long double, long double);
+long double    frexpl      (long double, int *);
+long double    fmaxl       (long double, long double);
+long double    fminl       (long double, long double);
+long double    fmodl       (long double, long double);
+long double    hypotl      (long double, long double);
+int            ilogbl      (long double);
+long double    ldexpl      (long double, int);
+long long              llroundl    (long double);
+long double    logbl       (long double);
+long           lrintl      (long double);
+long           lroundl     (long double);
+long double    modfl       (long double, long double *);
+long double    nanl        (const char *);
+long double    nextafterl  (long double, long double);
+double         nexttoward  (double,      long double);
+float          nexttowardf (float,       long double);
+long double    remainderl  (long double, long double);
+long double    remquol     (long double, long double, int *);
+long double    rintl       (long double);
+long double    roundl      (long double);
+long double    scalblnl    (long double, long);
+long double    scalbnl     (long double, int);
+long double    sinl        (long double);
+long double    sqrtl       (long double);
+long double    tanl        (long double);
+long double    truncl      (long double);
 #endif
-
-int            ilogbl(long double);
-long double    logbl(long double);
-long double    scalbnl(long double, int);
 __END_DECLS
 
 #endif /* _MATH_H_ */
index 258fc5c..12fe3c7 100644 (file)
@@ -3,14 +3,15 @@
 .PATH: ${.CURDIR}/arch/i386
 
 SRCS+= e_acos.S e_asin.S e_atan2.S e_atan2f.S e_exp.S e_expf.S e_fmod.S \
-       e_log.S e_log10.S e_log10f.S e_log2.S e_log2f.S e_logf.S e_remainder.S e_remainderf.S \
-       e_scalb.S e_scalbf.S e_sqrt.S e_sqrtf.S lrint.S s_atan.S s_atanf.S \
+       e_log.S e_log10.S e_log10f.S e_log2.S e_log2f.S e_logf.S \
+       e_scalb.S e_scalbf.S e_sqrt.S e_sqrtf.S s_lrint.S s_atan.S s_atanf.S \
        s_ceil.S s_ceilf.S s_copysign.S s_copysignf.S s_cos.S s_cosf.S \
        s_finite.S s_finitef.S s_floor.S s_floorf.S s_ilogb.S s_ilogbf.S \
        s_log1p.S s_log1pf.S s_logb.S s_logbf.S s_rint.S s_rintf.S \
        s_scalbn.S s_scalbnf.S s_significand.S s_significandf.S s_sin.S \
-       s_sinf.S s_tan.S s_tanf.S
-SRCS+= s_ilogbl.S s_logbl.S s_modf.S s_scalbnl.S
+       s_sinf.S s_tan.S s_tanf.S e_remainder.S e_remainderf.S
+SRCS+=  s_ilogbl.S s_logbl.S s_modf.S s_scalbnl.S
+SRCS+=  s_remquol.S e_remainderl.S s_lrintf.S s_lrintl.S
 
 # This file is included by arch/x86_64/Makefile.inc, so pull in the right
 # fenv.[ch].
similarity index 57%
copy from lib/libm/src/s_roundf.c
copy to lib/libm/arch/i386/e_remainderl.S
index 734a8d8..3781ba9 100644 (file)
@@ -1,16 +1,20 @@
-/*-
- * Copyright (c) 2003, Steven G. Kargl
+/*
+ * Copyright (c) 1993,94 Winning Strategies, Inc.
  * 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.
+ *    notice, this list of conditions and the following disclaimer.
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *      This product includes software developed by Winning Strategies, Inc.
+ * 4. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
  *
  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  * 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.
- *
- * $NetBSD: s_roundf.c,v 1.2 2007/08/21 20:10:27 drochner Exp $
  */
 
-#include <math.h>
+/*
+ * Written by:
+ *     J.T. Conklin (jtc@wimsey.com), Winning Strategies, Inc.
+ * FreeBSD SVN: 217108 (2011-01-07)
+ */
 
-float
-roundf(float x)
-{
-       float t;
-       int i;
+#include <machine/asm.h>
 
-       i = fpclassify(x);
-       if (i == FP_INFINITE || i == FP_NAN)
-               return (x);
+ENTRY(remainderl)
+#ifdef __i386__
+       fldt    16(%esp)
+       fldt    4(%esp)
+1:     fprem1
+       fstsw   %ax
+       sahf
+       jp      1b
+       fstp    %st(1)
+       ret
+#else
+       fldt    24(%rsp)
+       fldt    8(%rsp)
+1:     fprem1
+       fstsw   %ax
+       testw   $0x400,%ax
+       jne     1b
+       fstp    %st(1)
+       ret
+#endif
+END(remainderl)
 
-       if (x >= 0.0) {
-               t = floorf(x);
-               if (x - t >= 0.5)
-                       t += 1.0;
-               return (t);
-       } else {
-               x = -x;
-               t = floorf(x);
-               if (x - t >= 0.5)
-                       t += 1.0;
-               return (-t);
-       }
-}
+       .section .note.GNU-stack,"",%progbits
similarity index 62%
copy from lib/libm/src/s_roundf.c
copy to lib/libm/arch/i386/e_sqrtl.S
index 734a8d8..769e660 100644 (file)
@@ -1,16 +1,20 @@
-/*-
- * Copyright (c) 2003, Steven G. Kargl
+/*
+ * Copyright (c) 1993,94 Winning Strategies, Inc.
  * 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.
+ *    notice, this list of conditions and the following disclaimer.
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *      This product includes software developed by Winning Strategies, Inc.
+ * 4. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
  *
  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  * 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.
- *
- * $NetBSD: s_roundf.c,v 1.2 2007/08/21 20:10:27 drochner Exp $
  */
 
-#include <math.h>
+/*
+ * Written by:
+ *     J.T. Conklin (jtc@wimsey.com), Winning Strategies, Inc.
+ */
 
-float
-roundf(float x)
-{
-       float t;
-       int i;
+#include <machine/asm.h>
 
-       i = fpclassify(x);
-       if (i == FP_INFINITE || i == FP_NAN)
-               return (x);
+ENTRY(sqrtl)
+#ifdef __i386__
+       fldt    4(%esp)
+       fsqrt
+       ret
+#else
+       fldt    8(%rsp)
+       fsqrt
+       ret
+#endif
+END(sqrtl)
 
-       if (x >= 0.0) {
-               t = floorf(x);
-               if (x - t >= 0.5)
-                       t += 1.0;
-               return (t);
-       } else {
-               x = -x;
-               t = floorf(x);
-               if (x - t >= 0.5)
-                       t += 1.0;
-               return (-t);
-       }
-}
+       .section .note.GNU-stack,"",%progbits
diff --git a/lib/libm/arch/i386/lrint.S b/lib/libm/arch/i386/lrint.S
deleted file mode 100644 (file)
index 2759d39..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Written by Matthias Drochner <drochner@NetBSD.org>.
- * Public domain.
- *
- * $NetBSD: lrint.S,v 1.2 2004/10/13 15:18:32 drochner Exp $
- */
-
-#include <machine/asm.h>
-
-ENTRY(lrint)
-#ifdef __i386__
-       pushl   %ebp
-       movl    %esp,%ebp
-       subl    $4,%esp
-       fldl    8(%ebp)
-       fistpl  (%esp)
-       movl    (%esp),%eax
-       leave
-       ret
-#else
-       cvtsd2siq %xmm0,%rax
-       ret
-#endif
-END(lrint)
-
-       .section .note.GNU-stack,"",%progbits
similarity index 72%
copy from lib/libm/src/s_copysignl.c
copy to lib/libm/arch/i386/s_lrint.S
index 8d39f84..17cef89 100644 (file)
@@ -1,5 +1,5 @@
 /*-
- * Copyright (c) 2004 Stefan Farfeleder
+ * Copyright (c) 2005 David Schultz <das@FreeBSD.ORG>
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  *    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
+ * 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 AUTHOR OR CONTRIBUTORS BE LIABLE
+ * 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)
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $FreeBSD$
+ * FreeBSD SVN: 217108 (2011-01-07)
  */
 
-#include <math.h>
+#include <machine/asm.h>
 
-#include "fpmath.h"
+ENTRY(lrint)
+#ifdef __i386__
+       fldl    4(%esp)
+       subl    $4,%esp
+       fistpl  (%esp)
+       popl    %eax
+       ret
+#else
+       cvtsd2si %xmm0, %rax
+       ret
+#endif
+END(lrint)
 
-long double
-copysignl(long double x, long double y)
-{
-       union IEEEl2bits ux, uy;
-
-       ux.e = x;
-       uy.e = y;
-       ux.bits.sign = uy.bits.sign;
-       return (ux.e);
-}
+       .section .note.GNU-stack,"",%progbits
similarity index 72%
copy from lib/libm/src/s_copysignl.c
copy to lib/libm/arch/i386/s_lrintf.S
index 8d39f84..975d1b0 100644 (file)
@@ -1,5 +1,5 @@
 /*-
- * Copyright (c) 2004 Stefan Farfeleder
+ * Copyright (c) 2005 David Schultz <das@FreeBSD.ORG>
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  *    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
+ * 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 AUTHOR OR CONTRIBUTORS BE LIABLE
+ * 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)
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $FreeBSD$
+ * FreeBSD SVN: 217108 (2011-01-07)
  */
 
-#include <math.h>
+#include <machine/asm.h>
 
-#include "fpmath.h"
+ENTRY(lrintf)
+#ifdef __i386__
+       flds    4(%esp)
+       subl    $4,%esp
+       fistpl  (%esp)
+       popl    %eax
+       ret
+#else
+       cvtss2si %xmm0, %rax
+       ret
+#endif
+END(lrintf)
 
-long double
-copysignl(long double x, long double y)
-{
-       union IEEEl2bits ux, uy;
-
-       ux.e = x;
-       uy.e = y;
-       ux.bits.sign = uy.bits.sign;
-       return (ux.e);
-}
+       .section .note.GNU-stack,"",%progbits
similarity index 71%
copy from lib/libm/src/s_copysignl.c
copy to lib/libm/arch/i386/s_lrintl.S
index 8d39f84..6550d38 100644 (file)
@@ -1,5 +1,5 @@
 /*-
- * Copyright (c) 2004 Stefan Farfeleder
+ * Copyright (c) 2008 David Schultz <das@FreeBSD.ORG>
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  *    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
+ * 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 AUTHOR OR CONTRIBUTORS BE LIABLE
+ * 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)
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $FreeBSD$
+ * FreeBSD SVN: 217108 (2011-01-07)
  */
 
-#include <math.h>
+#include <machine/asm.h>
 
-#include "fpmath.h"
+ENTRY(lrintl)
+#ifdef __i386__
+       fldt    4(%esp)
+       subl    $4,%esp
+       fistpl  (%esp)
+       popl    %eax
+       ret
+#else
+       fldt    8(%rsp)
+       subq    $8,%rsp
+       fistpll (%rsp)
+       popq    %rax
+       ret
+#endif
+END(lrintl)
 
-long double
-copysignl(long double x, long double y)
-{
-       union IEEEl2bits ux, uy;
-
-       ux.e = x;
-       uy.e = y;
-       ux.bits.sign = uy.bits.sign;
-       return (ux.e);
-}
+       .section .note.GNU-stack,"",%progbits
diff --git a/lib/libm/arch/i386/s_remquol.S b/lib/libm/arch/i386/s_remquol.S
new file mode 100644 (file)
index 0000000..312d1dc
--- /dev/null
@@ -0,0 +1,97 @@
+/*-
+ * Copyright (c) 2005-2008 David Schultz <das@FreeBSD.ORG>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Based on public-domain remainder routine by J.T. Conklin <jtc@NetBSD.org>.
+ * FreeBSD SVN: 217108 (2011-01-07)
+ */
+
+#include <machine/asm.h>
+
+ENTRY(remquol)
+#ifdef __i386__
+       fldt    16(%esp)
+       fldt    4(%esp)
+1:     fprem1
+       fstsw   %ax
+       sahf
+       jp      1b
+       fstp    %st(1)
+/* Extract the three low-order bits of the quotient from C0,C3,C1. */
+       shrl    $6,%eax
+       movl    %eax,%ecx
+       andl    $0x108,%eax
+       rorl    $7,%eax
+       orl     %eax,%ecx
+       roll    $4,%eax
+       orl     %ecx,%eax
+       andl    $7,%eax
+/* Negate the quotient bits if x*y<0.  Avoid using an unpredictable branch. */
+       movl    24(%esp),%ecx
+       xorl    12(%esp),%ecx
+       movsx   %cx,%ecx
+       sarl    $16,%ecx
+       sarl    $16,%ecx
+       xorl    %ecx,%eax
+       andl    $1,%ecx
+       addl    %ecx,%eax
+/* Store the quotient and return. */
+       movl    28(%esp),%ecx
+       movl    %eax,(%ecx)
+       ret
+#else
+       fldt    24(%rsp)
+       fldt    8(%rsp)
+1:     fprem1
+       fstsw   %ax
+       btw     $10,%ax
+       jc      1b
+       fstp    %st(1)
+/* Extract the three low-order bits of the quotient from C0,C3,C1. */
+       shrl    $6,%eax
+       movl    %eax,%ecx
+       andl    $0x108,%eax
+       rorl    $7,%eax
+       orl     %eax,%ecx
+       roll    $4,%eax
+       orl     %ecx,%eax
+       andl    $7,%eax
+/* Negate the quotient bits if x*y<0.  Avoid using an unpredictable branch. */
+       movl    32(%rsp),%ecx
+       xorl    16(%rsp),%ecx
+       movsx   %cx,%ecx
+       sarl    $16,%ecx
+       sarl    $16,%ecx
+       xorl    %ecx,%eax
+       andl    $1,%ecx
+       addl    %ecx,%eax
+/* Store the quotient and return. */
+       movl    %eax,(%rdi)
+       ret
+#endif
+END(remquol)
+
+       .section .note.GNU-stack,"",%progbits
index e0b91f9..b32fda1 100644 (file)
@@ -26,4 +26,7 @@ ENTRY(scalbnf)
        ret
 END(scalbnf)
 
+.globl CNAME(ldexpf)
+.set   CNAME(ldexpf),CNAME(scalbnf)
+
        .section .note.GNU-stack,"",%progbits
index e1857a2..56a03b3 100644 (file)
@@ -23,4 +23,7 @@ ENTRY(scalbnl)
        ret
 END(scalbnl)
 
+.globl CNAME(ldexpl)
+.set   CNAME(ldexpl),CNAME(scalbnl)
+
        .section .note.GNU-stack,"",%progbits
index f51fe59..6027cdb 100644 (file)
@@ -2,17 +2,29 @@
 
 .PATH: ${.CURDIR}/complex
 
-SRCS+= cabs.c cabsf.c carg.c cargf.c
+SRCS+= cabs.c cabsf.c w_cabsl.c
+SRCS+= carg.c cargf.c s_cargl.c
 SRCS+= creal.c crealf.c creall.c
 SRCS+= cimag.c cimagf.c cimagl.c
 SRCS+= conj.c conjf.c conjl.c
 SRCS+= cproj.c cprojf.c cprojl.c
-SRCS+= csqrt.c cexp.c clog.c cpow.c
-SRCS+= cephes_subr.c csin.c ccos.c ctan.c csinh.c ccosh.c ctanh.c
-SRCS+= casin.c cacos.c catan.c casinh.c cacosh.c catanh.c
-SRCS+= csqrtf.c cexpf.c clogf.c cpowf.c
-SRCS+= cephes_subrf.c csinf.c ccosf.c ctanf.c csinhf.c ccoshf.c ctanhf.c
-SRCS+= casinf.c cacosf.c catanf.c casinhf.c cacoshf.c catanhf.c
+SRCS+= csqrt.c csqrtf.c s_csqrtl.c
+SRCS+= cexp.c cexpf.c
+SRCS+= clog.c clogf.c
+SRCS+= cpow.c cpowf.c
+SRCS+= cephes_subr.c cephes_subrf.c
+SRCS+= csin.c csinf.c
+SRCS+= ccos.c ccosf.c
+SRCS+= ctan.c ctanf.c
+SRCS+= csinh.c csinhf.c
+SRCS+= ccosh.c ccoshf.c
+SRCS+= ctanh.c ctanhf.c
+SRCS+= casin.c casinf.c
+SRCS+= cacos.c cacosf.c
+SRCS+= catan.c catanf.c
+SRCS+= casinh.c casinhf.c
+SRCS+= cacosh.c cacoshf.c
+SRCS+= catanh.c catanhf.c
 
 MAN+= cabs.3 cacos.3 cacosh.3 carg.3 casin.3 casinh.3 catan.3 catanh.3
 MAN+= ccos.3 ccosh.3 cexp.3 cimag.3 clog.3 conj.3 cpow.3 cproj.3 creal.3
similarity index 77%
copy from lib/libm/src/s_copysignl.c
copy to lib/libm/complex/s_cargl.c
index 8d39f84..e0cbd7a 100644 (file)
@@ -1,5 +1,5 @@
 /*-
- * Copyright (c) 2004 Stefan Farfeleder
+ * Copyright (c) 2005-2008 David Schultz <das@FreeBSD.ORG>
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  *    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
+ * 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 AUTHOR OR CONTRIBUTORS BE LIABLE
+ * 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)
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $FreeBSD$
+ * FreeBSD SVN: 181074 (2008-07-31)
  */
 
+#include <complex.h>
 #include <math.h>
 
-#include "fpmath.h"
-
 long double
-copysignl(long double x, long double y)
+cargl(long double complex z)
 {
-       union IEEEl2bits ux, uy;
 
-       ux.e = x;
-       uy.e = y;
-       ux.bits.sign = uy.bits.sign;
-       return (ux.e);
+       return (atan2l(cimagl(z), creall(z)));
 }
diff --git a/lib/libm/complex/s_csqrtl.c b/lib/libm/complex/s_csqrtl.c
new file mode 100644 (file)
index 0000000..6a56843
--- /dev/null
@@ -0,0 +1,109 @@
+/*-
+ * Copyright (c) 2007-2008 David Schultz <das@FreeBSD.ORG>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * FreeBSD SVN: 181402 (2008-08-08)
+ */
+
+#include <complex.h>
+#include <float.h>
+#include <math.h>
+
+#include "../src/math_private.h"
+
+/*
+ * gcc doesn't implement complex multiplication or division correctly,
+ * so we need to handle infinities specially. We turn on this pragma to
+ * notify conforming c99 compilers that the fast-but-incorrect code that
+ * gcc generates is acceptable, since the special cases have already been
+ * handled.
+ *
+ * IGNORED BY DRAGONFLY BASE COMPILER, MASK TO AVOID WARNING=ERROR
+ * #pragma     STDC CX_LIMITED_RANGE   ON
+ */
+
+/* We risk spurious overflow for components >= LDBL_MAX / (1 + sqrt(2)). */
+#define        THRESH  (LDBL_MAX / 2.414213562373095048801688724209698L)
+
+long double complex
+csqrtl(long double complex z)
+{
+       long double complex result;
+       long double a, b;
+       long double t;
+       int scale;
+
+       a = creall(z);
+       b = cimagl(z);
+
+       /* Handle special cases. */
+       if (z == 0)
+               return (cpackl(0, b));
+       if (isinf(b))
+               return (cpackl(INFINITY, b));
+       if (isnan(a)) {
+               t = (b - b) / (b - b);  /* raise invalid if b is not a NaN */
+               return (cpackl(a, t));  /* return NaN + NaN i */
+       }
+       if (isinf(a)) {
+               /*
+                * csqrt(inf + NaN i)  = inf +  NaN i
+                * csqrt(inf + y i)    = inf +  0 i
+                * csqrt(-inf + NaN i) = NaN +- inf i
+                * csqrt(-inf + y i)   = 0   +  inf i
+                */
+               if (signbit(a))
+                       return (cpackl(fabsl(b - b), copysignl(a, b)));
+               else
+                       return (cpackl(a, copysignl(b - b, b)));
+       }
+       /*
+        * The remaining special case (b is NaN) is handled just fine by
+        * the normal code path below.
+        */
+
+       /* Scale to avoid overflow. */
+       if (fabsl(a) >= THRESH || fabsl(b) >= THRESH) {
+               a *= 0.25;
+               b *= 0.25;
+               scale = 1;
+       } else {
+               scale = 0;
+       }
+
+       /* Algorithm 312, CACM vol 10, Oct 1967. */
+       if (a >= 0) {
+               t = sqrtl((a + hypotl(a, b)) * 0.5);
+               result = cpackl(t, b / (2 * t));
+       } else {
+               t = sqrtl((-a + hypotl(a, b)) * 0.5);
+               result = cpackl(fabsl(b) / (2 * t), copysignl(t, b));
+       }
+
+       /* Rescale. */
+       if (scale)
+               return (result * 2);
+       else
+               return (result);
+}
diff --git a/lib/libm/complex/w_cabsl.c b/lib/libm/complex/w_cabsl.c
new file mode 100644 (file)
index 0000000..aebed20
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ * cabs() wrapper for hypot().
+ *
+ * Written by J.T. Conklin, <jtc@wimsey.com>
+ * Placed into the Public Domain, 1994.
+ *
+ * Modified by Steven G. Kargl for the long double type.
+ *
+ * FreeBSD SVN: 177757 (2008-03-30)
+ */
+
+#include <complex.h>
+#include <math.h>
+
+long double
+cabsl(long double complex z)
+{
+       return hypotl(creall(z), cimagl(z));
+}
index 0c77da0..2128bc9 100644 (file)
@@ -7,11 +7,20 @@ CFLAGS+=-I${LIBCDIR}/include -I${LIBCDIR}/${MACHINE_ARCH}
 
 # These files are always used.
 SRCS+= k_cos.c k_cosf.c k_rem_pio2.c k_rem_pio2f.c k_sin.c k_sinf.c \
-       k_tan.c k_tanf.c llrint.c llrintf.c llround.c \
-       llroundf.c lrint.c lrintf.c lround.c lroundf.c s_trunc.c s_truncf.c \
+       k_tan.c k_tanf.c s_llrint.c s_llrintf.c s_llround.c s_llroundf.c \
+       s_lrintf.c s_lround.c s_lroundf.c s_trunc.c s_truncf.c \
        w_drem.c w_dremf.c w_gamma.c w_gamma_r.c w_gammaf.c w_gammaf_r.c \
        w_lgamma.c w_lgammaf.c
 
+# Origin: FreeBSD's msun library, always used source files
+# Long Double: 80-bit version used (LD80 on FreeBSD)
+
+SRCS+= invtrig.c e_acosl.c e_asinl.c e_atan2l.c e_fmodl.c e_hypotl.c \
+       k_sinl.c k_cosl.c k_tanl.c b_log.c b_exp.c \
+       s_atanl.c s_sinl.c s_cosl.c s_tanl.c s_exp2l.c s_cbrtl.c s_floorl.c \
+       s_roundl.c s_lroundl.c s_llroundl.c s_rintl.c s_lrintl.c s_modfl.c \
+       s_fabs.c s_fma.c s_fmaf.c s_fmal.c s_tgammaf.c b_tgamma.c s_scalbln.c
+
 # These files are only used if the MI Makefile didn't already provide
 # them as assembler version.
 
@@ -28,13 +37,15 @@ MI_FUNCS+=  \
        s_erff.c s_expm1.c s_expm1f.c s_fabsf.c s_fdim.c s_finite.c \
        s_finitef.c s_floor.c s_floorf.c s_fmax.c s_fmaxf.c s_fmaxl.c \
        s_fmin.c s_fminf.c s_fminl.c s_frexpf.c s_frexpl.c s_ilogb.c \
-       s_ilogbf.c s_ldexpf.c s_log1p.c s_log1pf.c s_logb.c s_logbf.c \
+       s_ilogbf.c s_log1p.c s_log1pf.c s_logb.c s_logbf.c \
        s_modff.c s_nearbyint.c s_nextafter.c s_nextafterf.c s_rint.c s_rintf.c \
        s_round.c s_roundf.c s_scalbn.c s_scalbnf.c \
        s_signgam.c s_significand.c s_significandf.c s_sin.c s_sinf.c \
-       s_tan.c s_tanf.c s_tanh.c s_tanhf.c
-MI_FUNCS+= s_exp2.c s_exp2f.c s_frexp.c s_ilogbl.c s_logbl.c s_nextafterl.c s_nexttoward.c \
-       s_remquo.c s_remquof.c s_scalbnl.c s_fabsl.c
+       s_tan.c s_tanf.c s_tanh.c s_tanhf.c s_lrint.c
+MI_FUNCS+= s_exp2.c s_exp2f.c s_frexp.c s_ilogbl.c s_logbl.c s_nextafterl.c \
+       s_nexttoward.c s_remquo.c s_remquof.c s_scalbnl.c s_fabsl.c
+MI_FUNCS+= e_sqrtl.c e_remainderl.c s_remquol.c s_ceill.c s_llrintl.c \
+       s_modf.c s_nexttowardf.c s_truncl.c
 
 .for f in ${MI_FUNCS}
 .if empty(SRCS:M${f:H:R})
diff --git a/lib/libm/src/b_exp.c b/lib/libm/src/b_exp.c
new file mode 100644 (file)
index 0000000..87d4bff
--- /dev/null
@@ -0,0 +1,130 @@
+/*
+ * Copyright (c) 1985, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * FreeBSD SVN: 226414 (2011-10-16)
+ */
+
+/* @(#)exp.c   8.1 (Berkeley) 6/4/93 */
+
+/* EXP(X)
+ * RETURN THE EXPONENTIAL OF X
+ * DOUBLE PRECISION (IEEE 53 bits, VAX D FORMAT 56 BITS)
+ * CODED IN C BY K.C. NG, 1/19/85;
+ * REVISED BY K.C. NG on 2/6/85, 2/15/85, 3/7/85, 3/24/85, 4/16/85, 6/14/86.
+ *
+ * Required system supported functions:
+ *     scalb(x,n)
+ *     copysign(x,y)
+ *     finite(x)
+ *
+ * Method:
+ *     1. Argument Reduction: given the input x, find r and integer k such
+ *        that
+ *                        x = k*ln2 + r,  |r| <= 0.5*ln2 .
+ *        r will be represented as r := z+c for better accuracy.
+ *
+ *     2. Compute exp(r) by
+ *
+ *             exp(r) = 1 + r + r*R1/(2-R1),
+ *        where
+ *             R1 = x - x^2*(p1+x^2*(p2+x^2*(p3+x^2*(p4+p5*x^2)))).
+ *
+ *     3. exp(x) = 2^k * exp(r) .
+ *
+ * Special cases:
+ *     exp(INF) is INF, exp(NaN) is NaN;
+ *     exp(-INF)=  0;
+ *     for finite argument, only exp(0)=1 is exact.
+ *
+ * Accuracy:
+ *     exp(x) returns the exponential of x nearly rounded. In a test run
+ *     with 1,156,000 random arguments on a VAX, the maximum observed
+ *     error was 0.869 ulps (units in the last place).
+ */
+
+#include "mathimpl.h"
+
+static const double p1 = 0x1.555555555553ep-3;
+static const double p2 = -0x1.6c16c16bebd93p-9;
+static const double p3 = 0x1.1566aaf25de2cp-14;
+static const double p4 = -0x1.bbd41c5d26bf1p-20;
+static const double p5 = 0x1.6376972bea4d0p-25;
+static const double ln2hi = 0x1.62e42fee00000p-1;
+static const double ln2lo = 0x1.a39ef35793c76p-33;
+static const double lnhuge = 0x1.6602b15b7ecf2p9;
+static const double lntiny = -0x1.77af8ebeae354p9;
+static const double invln2 = 0x1.71547652b82fep0;
+
+
+/* returns exp(r = x + c) for |c| < |x| with no overlap.  */
+
+double __exp__D(x, c)
+double x, c;
+{
+       double  z,hi,lo;
+       int k;
+
+       if (x != x)     /* x is NaN */
+               return(x);
+       if ( x <= lnhuge ) {
+               if ( x >= lntiny ) {
+
+                   /* argument reduction : x --> x - k*ln2 */
+                       z = invln2*x;
+                       k = z + copysign(.5, x);
+
+                   /* express (x+c)-k*ln2 as hi-lo and let x=hi-lo rounded */
+
+                       hi=(x-k*ln2hi);                 /* Exact. */
+                       x= hi - (lo = k*ln2lo-c);
+                   /* return 2^k*[1+x+x*c/(2+c)]  */
+                       z=x*x;
+                       c= x - z*(p1+z*(p2+z*(p3+z*(p4+z*p5))));
+                       c = (x*c)/(2.0-c);
+
+                       return  scalb(1.+(hi-(lo - c)), k);
+               }
+               /* end of x > lntiny */
+
+               else
+                    /* exp(-big#) underflows to zero */
+                    if(finite(x))  return(scalb(1.0,-5000));
+
+                    /* exp(-INF) is zero */
+                    else return(0.0);
+       }
+       /* end of x < lnhuge */
+
+       else
+       /* exp(INF) is INF, exp(+big#) overflows to INF */
+           return( finite(x) ?  scalb(1.0,5000)  : x);
+}
diff --git a/lib/libm/src/b_log.c b/lib/libm/src/b_log.c
new file mode 100644 (file)
index 0000000..343f545
--- /dev/null
@@ -0,0 +1,471 @@
+/*
+ * Copyright (c) 1992, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * FreeBSD SVN: 176449 (2008-02-22)
+ */
+
+/* @(#)log.c   8.2 (Berkeley) 11/30/93 */
+
+#include <math.h>
+#include <errno.h>
+
+#include "mathimpl.h"
+
+/* Table-driven natural logarithm.
+ *
+ * This code was derived, with minor modifications, from:
+ *     Peter Tang, "Table-Driven Implementation of the
+ *     Logarithm in IEEE Floating-Point arithmetic." ACM Trans.
+ *     Math Software, vol 16. no 4, pp 378-400, Dec 1990).
+ *
+ * Calculates log(2^m*F*(1+f/F)), |f/j| <= 1/256,
+ * where F = j/128 for j an integer in [0, 128].
+ *
+ * log(2^m) = log2_hi*m + log2_tail*m
+ * since m is an integer, the dominant term is exact.
+ * m has at most 10 digits (for subnormal numbers),
+ * and log2_hi has 11 trailing zero bits.
+ *
+ * log(F) = logF_hi[j] + logF_lo[j] is in tabular form in log_table.h
+ * logF_hi[] + 512 is exact.
+ *
+ * log(1+f/F) = 2*f/(2*F + f) + 1/12 * (2*f/(2*F + f))**3 + ...
+ * the leading term is calculated to extra precision in two
+ * parts, the larger of which adds exactly to the dominant
+ * m and F terms.
+ * There are two cases:
+ *     1. when m, j are non-zero (m | j), use absolute
+ *        precision for the leading term.
+ *     2. when m = j = 0, |1-x| < 1/256, and log(x) ~= (x-1).
+ *        In this case, use a relative precision of 24 bits.
+ * (This is done differently in the original paper)
+ *
+ * Special cases:
+ *     0       return signalling -Inf
+ *     neg     return signalling NaN
+ *     +Inf    return +Inf
+*/
+
+#define N 128
+
+/* Table of log(Fj) = logF_head[j] + logF_tail[j], for Fj = 1+j/128.
+ * Used for generation of extend precision logarithms.
+ * The constant 35184372088832 is 2^45, so the divide is exact.
+ * It ensures correct reading of logF_head, even for inaccurate
+ * decimal-to-binary conversion routines.  (Everybody gets the
+ * right answer for integers less than 2^53.)
+ * Values for log(F) were generated using error < 10^-57 absolute
+ * with the bc -l package.
+*/
+static double  A1 =      .08333333333333178827;
+static double  A2 =      .01250000000377174923;
+static double  A3 =     .002232139987919447809;
+static double  A4 =    .0004348877777076145742;
+
+static double logF_head[N+1] = {
+       0.,
+       .007782140442060381246,
+       .015504186535963526694,
+       .023167059281547608406,
+       .030771658666765233647,
+       .038318864302141264488,
+       .045809536031242714670,
+       .053244514518837604555,
+       .060624621816486978786,
+       .067950661908525944454,
+       .075223421237524235039,
+       .082443669210988446138,
+       .089612158689760690322,
+       .096729626458454731618,
+       .103796793681567578460,
+       .110814366340264314203,
+       .117783035656430001836,
+       .124703478501032805070,
+       .131576357788617315236,
+       .138402322859292326029,
+       .145182009844575077295,
+       .151916042025732167530,
+       .158605030176659056451,
+       .165249572895390883786,
+       .171850256926518341060,
+       .178407657472689606947,
+       .184922338493834104156,
+       .191394852999565046047,
+       .197825743329758552135,
+       .204215541428766300668,
+       .210564769107350002741,
+       .216873938300523150246,
+       .223143551314024080056,
+       .229374101064877322642,
+       .235566071312860003672,
+       .241719936886966024758,
+       .247836163904594286577,
+       .253915209980732470285,
+       .259957524436686071567,
+       .265963548496984003577,
+       .271933715484010463114,
+       .277868451003087102435,
+       .283768173130738432519,
+       .289633292582948342896,
+       .295464212893421063199,
+       .301261330578199704177,
+       .307025035294827830512,
+       .312755710004239517729,
+       .318453731118097493890,
+       .324119468654316733591,
+       .329753286372579168528,
+       .335355541920762334484,
+       .340926586970454081892,
+       .346466767346100823488,
+       .351976423156884266063,
+       .357455888922231679316,
+       .362905493689140712376,
+       .368325561158599157352,
+       .373716409793814818840,
+       .379078352934811846353,
+       .384411698910298582632,
+       .389716751140440464951,
+       .394993808240542421117,
+       .400243164127459749579,
+       .405465108107819105498,
+       .410659924985338875558,
+       .415827895143593195825,
+       .420969294644237379543,
+       .426084395310681429691,
+       .431173464818130014464,
+       .436236766774527495726,
+       .441274560805140936281,
+       .446287102628048160113,
+       .451274644139630254358,
+       .456237433481874177232,
+       .461175715122408291790,
+       .466089729924533457960,
+       .470979715219073113985,
+       .475845904869856894947,
+       .480688529345570714212,
+       .485507815781602403149,
+       .490303988045525329653,
+       .495077266798034543171,
+       .499827869556611403822,
+       .504556010751912253908,
+       .509261901790523552335,
+       .513945751101346104405,
+       .518607764208354637958,
+       .523248143765158602036,
+       .527867089620485785417,
+       .532464798869114019908,
+       .537041465897345915436,
+       .541597282432121573947,
+       .546132437597407260909,
+       .550647117952394182793,
+       .555141507540611200965,
+       .559615787935399566777,
+       .564070138285387656651,
+       .568504735352689749561,
+       .572919753562018740922,
+       .577315365035246941260,
+       .581691739635061821900,
+       .586049045003164792433,
+       .590387446602107957005,
+       .594707107746216934174,
+       .599008189645246602594,
+       .603290851438941899687,
+       .607555250224322662688,
+       .611801541106615331955,
+       .616029877215623855590,
+       .620240409751204424537,
+       .624433288012369303032,
+       .628608659422752680256,
+       .632766669570628437213,
+       .636907462236194987781,
+       .641031179420679109171,
+       .645137961373620782978,
+       .649227946625615004450,
+       .653301272011958644725,
+       .657358072709030238911,
+       .661398482245203922502,
+       .665422632544505177065,
+       .669430653942981734871,
+       .673422675212350441142,
+       .677398823590920073911,
+       .681359224807238206267,
+       .685304003098281100392,
+       .689233281238557538017,
+       .693147180560117703862
+};
+
+static double logF_tail[N+1] = {
+       0.,
+       -.00000000000000543229938420049,
+        .00000000000000172745674997061,
+       -.00000000000001323017818229233,
+       -.00000000000001154527628289872,
+       -.00000000000000466529469958300,
+        .00000000000005148849572685810,
+       -.00000000000002532168943117445,
+       -.00000000000005213620639136504,
+       -.00000000000001819506003016881,
+        .00000000000006329065958724544,
+        .00000000000008614512936087814,
+       -.00000000000007355770219435028,
+        .00000000000009638067658552277,
+        .00000000000007598636597194141,
+        .00000000000002579999128306990,
+       -.00000000000004654729747598444,
+       -.00000000000007556920687451336,
+        .00000000000010195735223708472,
+       -.00000000000017319034406422306,
+       -.00000000000007718001336828098,
+        .00000000000010980754099855238,
+       -.00000000000002047235780046195,
+       -.00000000000008372091099235912,
+        .00000000000014088127937111135,
+        .00000000000012869017157588257,
+        .00000000000017788850778198106,
+        .00000000000006440856150696891,
+        .00000000000016132822667240822,
+       -.00000000000007540916511956188,
+       -.00000000000000036507188831790,
+        .00000000000009120937249914984,
+        .00000000000018567570959796010,
+       -.00000000000003149265065191483,
+       -.00000000000009309459495196889,
+        .00000000000017914338601329117,
+       -.00000000000001302979717330866,
+        .00000000000023097385217586939,
+        .00000000000023999540484211737,
+        .00000000000015393776174455408,
+       -.00000000000036870428315837678,
+        .00000000000036920375082080089,
+       -.00000000000009383417223663699,
+        .00000000000009433398189512690,
+        .00000000000041481318704258568,
+       -.00000000000003792316480209314,
+        .00000000000008403156304792424,
+       -.00000000000034262934348285429,
+        .00000000000043712191957429145,
+       -.00000000000010475750058776541,
+       -.00000000000011118671389559323,
+        .00000000000037549577257259853,
+        .00000000000013912841212197565,
+        .00000000000010775743037572640,
+        .00000000000029391859187648000,
+       -.00000000000042790509060060774,
+        .00000000000022774076114039555,
+        .00000000000010849569622967912,
+       -.00000000000023073801945705758,
+        .00000000000015761203773969435,
+        .00000000000003345710269544082,
+       -.00000000000041525158063436123,
+        .00000000000032655698896907146,
+       -.00000000000044704265010452446,
+        .00000000000034527647952039772,
+       -.00000000000007048962392109746,
+        .00000000000011776978751369214,
+       -.00000000000010774341461609578,
+        .00000000000021863343293215910,
+        .00000000000024132639491333131,
+        .00000000000039057462209830700,
+       -.00000000000026570679203560751,
+        .00000000000037135141919592021,
+       -.00000000000017166921336082431,
+       -.00000000000028658285157914353,
+       -.00000000000023812542263446809,
+        .00000000000006576659768580062,
+       -.00000000000028210143846181267,
+        .00000000000010701931762114254,
+        .00000000000018119346366441110,
+        .00000000000009840465278232627,
+       -.00000000000033149150282752542,
+       -.00000000000018302857356041668,
+       -.00000000000016207400156744949,
+        .00000000000048303314949553201,
+       -.00000000000071560553172382115,
+        .00000000000088821239518571855,
+       -.00000000000030900580513238244,
+       -.00000000000061076551972851496,
+        .00000000000035659969663347830,
+        .00000000000035782396591276383,
+       -.00000000000046226087001544578,
+        .00000000000062279762917225156,
+        .00000000000072838947272065741,
+        .00000000000026809646615211673,
+       -.00000000000010960825046059278,
+        .00000000000002311949383800537,
+       -.00000000000058469058005299247,
+       -.00000000000002103748251144494,
+       -.00000000000023323182945587408,
+       -.00000000000042333694288141916,
+       -.00000000000043933937969737844,
+        .00000000000041341647073835565,
+        .00000000000006841763641591466,
+        .00000000000047585534004430641,
+        .00000000000083679678674757695,
+       -.00000000000085763734646658640,
+        .00000000000021913281229340092,
+       -.00000000000062242842536431148,
+       -.00000000000010983594325438430,
+        .00000000000065310431377633651,
+       -.00000000000047580199021710769,
+       -.00000000000037854251265457040,
+        .00000000000040939233218678664,
+        .00000000000087424383914858291,
+        .00000000000025218188456842882,
+       -.00000000000003608131360422557,
+       -.00000000000050518555924280902,
+        .00000000000078699403323355317,
+       -.00000000000067020876961949060,
+        .00000000000016108575753932458,
+        .00000000000058527188436251509,
+       -.00000000000035246757297904791,
+       -.00000000000018372084495629058,
+        .00000000000088606689813494916,
+        .00000000000066486268071468700,
+        .00000000000063831615170646519,
+        .00000000000025144230728376072,
+       -.00000000000017239444525614834
+};
+
+#if 0
+double
+#ifdef _ANSI_SOURCE
+log(double x)
+#else
+log(x) double x;
+#endif
+{
+       int m, j;
+       double F, f, g, q, u, u2, v, zero = 0.0, one = 1.0;
+       volatile double u1;
+
+       /* Catch special cases */
+       if (x <= 0)
+               if (x == zero)  /* log(0) = -Inf */
+                       return (-one/zero);
+               else            /* log(neg) = NaN */
+                       return (zero/zero);
+       else if (!finite(x))
+               return (x+x);           /* x = NaN, Inf */
+
+       /* Argument reduction: 1 <= g < 2; x/2^m = g;   */
+       /* y = F*(1 + f/F) for |f| <= 2^-8              */
+
+       m = logb(x);
+       g = ldexp(x, -m);
+       if (m == -1022) {
+               j = logb(g), m += j;
+               g = ldexp(g, -j);
+       }
+       j = N*(g-1) + .5;
+       F = (1.0/N) * j + 1;    /* F*128 is an integer in [128, 512] */
+       f = g - F;
+
+       /* Approximate expansion for log(1+f/F) ~= u + q */
+       g = 1/(2*F+f);
+       u = 2*f*g;
+       v = u*u;
+       q = u*v*(A1 + v*(A2 + v*(A3 + v*A4)));
+
+    /* case 1: u1 = u rounded to 2^-43 absolute.  Since u < 2^-8,
+     *                u1 has at most 35 bits, and F*u1 is exact, as F has < 8 bits.
+     *         It also adds exactly to |m*log2_hi + log_F_head[j] | < 750
+    */
+       if (m | j)
+               u1 = u + 513, u1 -= 513;
+
+    /* case 2: |1-x| < 1/256. The m- and j- dependent terms are zero;
+     *                 u1 = u to 24 bits.
+    */
+       else
+               u1 = u, TRUNC(u1);
+       u2 = (2.0*(f - F*u1) - u1*f) * g;
+                       /* u1 + u2 = 2f/(2F+f) to extra precision.      */
+
+       /* log(x) = log(2^m*F*(1+f/F)) =                                */
+       /* (m*log2_hi+logF_head[j]+u1) + (m*log2_lo+logF_tail[j]+q);    */
+       /* (exact) + (tiny)                                             */
+
+       u1 += m*logF_head[N] + logF_head[j];            /* exact */
+       u2 = (u2 + logF_tail[j]) + q;                   /* tiny */
+       u2 += logF_tail[N]*m;
+       return (u1 + u2);
+}
+#endif
+
+/*
+ * Extra precision variant, returning struct {double a, b;};
+ * log(x) = a+b to 63 bits, with a rounded to 26 bits.
+ */
+struct Double
+#ifdef _ANSI_SOURCE
+__log__D(double x)
+#else
+__log__D(x) double x;
+#endif
+{
+       int m, j;
+       double F, f, g, q, u, v, u2;
+       volatile double u1;
+       struct Double r;
+
+       /* Argument reduction: 1 <= g < 2; x/2^m = g;   */
+       /* y = F*(1 + f/F) for |f| <= 2^-8              */
+
+       m = logb(x);
+       g = ldexp(x, -m);
+       if (m == -1022) {
+               j = logb(g), m += j;
+               g = ldexp(g, -j);
+       }
+       j = N*(g-1) + .5;
+       F = (1.0/N) * j + 1;
+       f = g - F;
+
+       g = 1/(2*F+f);
+       u = 2*f*g;
+       v = u*u;
+       q = u*v*(A1 + v*(A2 + v*(A3 + v*A4)));
+       if (m | j)
+               u1 = u + 513, u1 -= 513;
+       else
+               u1 = u, TRUNC(u1);
+       u2 = (2.0*(f - F*u1) - u1*f) * g;
+
+       u1 += m*logF_head[N] + logF_head[j];
+
+       u2 +=  logF_tail[j]; u2 += q;
+       u2 += logF_tail[N]*m;
+       r.a = u1 + u2;                  /* Only difference is here */
+       TRUNC(r.a);
+       r.b = (u1 - r.a) + u2;
+       return (r);
+}
diff --git a/lib/libm/src/b_tgamma.c b/lib/libm/src/b_tgamma.c
new file mode 100644 (file)
index 0000000..8256b76
--- /dev/null
@@ -0,0 +1,316 @@
+/*-
+ * Copyright (c) 1992, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)gamma.c 8.1 (Berkeley) 6/4/93
+ * FreeBSD SVN: 176449 (2008-02-22)
+ */
+
+/*
+ * This code by P. McIlroy, Oct 1992;
+ *
+ * The financial support of UUNET Communications Services is greatfully
+ * acknowledged.
+ */
+
+#include <math.h>
+#include "mathimpl.h"
+
+/* METHOD:
+ * x < 0: Use reflection formula, G(x) = pi/(sin(pi*x)*x*G(x))
+ *     At negative integers, return NaN and raise invalid.
+ *
+ * x < 6.5:
+ *     Use argument reduction G(x+1) = xG(x) to reach the
+ *     range [1.066124,2.066124].  Use a rational
+ *     approximation centered at the minimum (x0+1) to
+ *     ensure monotonicity.
+ *
+ * x >= 6.5: Use the asymptotic approximation (Stirling's formula)
+ *     adjusted for equal-ripples:
+ *
+ *     log(G(x)) ~= (x-.5)*(log(x)-1) + .5(log(2*pi)-1) + 1/x*P(1/(x*x))
+ *
+ *     Keep extra precision in multiplying (x-.5)(log(x)-1), to
+ *     avoid premature round-off.
+ *
+ * Special values:
+ *     -Inf:                   return NaN and raise invalid;
+ *     negative integer:       return NaN and raise invalid;
+ *     other x ~< 177.79:      return +-0 and raise underflow;
+ *     +-0:                    return +-Inf and raise divide-by-zero;
+ *     finite x ~> 171.63:     return +Inf and raise overflow;
+ *     +Inf:                   return +Inf;
+ *     NaN:                    return NaN.
+ *
+ * Accuracy: tgamma(x) is accurate to within
+ *     x > 0:  error provably < 0.9ulp.
+ *     Maximum observed in 1,000,000 trials was .87ulp.
+ *     x < 0:
+ *     Maximum observed error < 4ulp in 1,000,000 trials.
+ */
+
+static double neg_gam(double);
+static double small_gam(double);
+static double smaller_gam(double);
+static struct Double large_gam(double);
+static struct Double ratfun_gam(double, double);
+
+/*
+ * Rational approximation, A0 + x*x*P(x)/Q(x), on the interval
+ * [1.066.., 2.066..] accurate to 4.25e-19.
+ */
+#define LEFT -.3955078125      /* left boundary for rat. approx */
+#define x0 .461632144968362356785      /* xmin - 1 */
+
+#define a0_hi 0.88560319441088874992
+#define a0_lo -.00000000000000004996427036469019695
+#define P0      6.21389571821820863029017800727e-01
+#define P1      2.65757198651533466104979197553e-01
+#define P2      5.53859446429917461063308081748e-03
+#define P3      1.38456698304096573887145282811e-03
+#define P4      2.40659950032711365819348969808e-03
+#define Q0      1.45019531250000000000000000000e+00
+#define Q1      1.06258521948016171343454061571e+00
+#define Q2     -2.07474561943859936441469926649e-01
+#define Q3     -1.46734131782005422506287573015e-01
+#define Q4      3.07878176156175520361557573779e-02
+#define Q5      5.12449347980666221336054633184e-03
+#define Q6     -1.76012741431666995019222898833e-03
+#define Q7      9.35021023573788935372153030556e-05
+#define Q8      6.13275507472443958924745652239e-06
+/*
+ * Constants for large x approximation (x in [6, Inf])
+ * (Accurate to 2.8*10^-19 absolute)
+ */
+#define lns2pi_hi 0.418945312500000
+#define lns2pi_lo -.000006779295327258219670263595
+#define Pa0     8.33333333333333148296162562474e-02
+#define Pa1    -2.77777777774548123579378966497e-03
+#define Pa2     7.93650778754435631476282786423e-04
+#define Pa3    -5.95235082566672847950717262222e-04
+#define Pa4     8.41428560346653702135821806252e-04
+#define Pa5    -1.89773526463879200348872089421e-03
+#define Pa6     5.69394463439411649408050664078e-03
+#define Pa7    -1.44705562421428915453880392761e-02
+
+static const double zero = 0., one = 1.0, tiny = 1e-300;
+
+double
+tgamma(x)
+       double x;
+{
+       struct Double u;
+
+       if (x >= 6) {
+               if(x > 171.63)
+                       return (x / zero);
+               u = large_gam(x);
+               return(__exp__D(u.a, u.b));
+       } else if (x >= 1.0 + LEFT + x0)
+               return (small_gam(x));
+       else if (x > 1.e-17)
+               return (smaller_gam(x));
+       else if (x > -1.e-17) {
+               if (x != 0.0)
+                       u.a = one - tiny;       /* raise inexact */
+               return (one/x);
+       } else if (!finite(x))
+               return (x - x);         /* x is NaN or -Inf */
+       else
+               return (neg_gam(x));
+}
+/*
+ * Accurate to max(ulp(1/128) absolute, 2^-66 relative) error.
+ */
+static struct Double
+large_gam(x)
+       double x;
+{
+       double z, p;
+       struct Double t, u, v;
+
+       z = one/(x*x);
+       p = Pa0+z*(Pa1+z*(Pa2+z*(Pa3+z*(Pa4+z*(Pa5+z*(Pa6+z*Pa7))))));
+       p = p/x;
+
+       u = __log__D(x);
+       u.a -= one;
+       v.a = (x -= .5);
+       TRUNC(v.a);
+       v.b = x - v.a;
+       t.a = v.a*u.a;                  /* t = (x-.5)*(log(x)-1) */
+       t.b = v.b*u.a + x*u.b;
+       /* return t.a + t.b + lns2pi_hi + lns2pi_lo + p */
+       t.b += lns2pi_lo; t.b += p;
+       u.a = lns2pi_hi + t.b; u.a += t.a;
+       u.b = t.a - u.a;
+       u.b += lns2pi_hi; u.b += t.b;
+       return (u);
+}
+/*
+ * Good to < 1 ulp.  (provably .90 ulp; .87 ulp on 1,000,000 runs.)
+ * It also has correct monotonicity.
+ */
+static double
+small_gam(x)
+       double x;
+{
+       double y, ym1, t;
+       struct Double yy, r;
+       y = x - one;
+       ym1 = y - one;
+       if (y <= 1.0 + (LEFT + x0)) {
+               yy = ratfun_gam(y - x0, 0);
+               return (yy.a + yy.b);
+       }
+       r.a = y;
+       TRUNC(r.a);
+       yy.a = r.a - one;
+       y = ym1;
+       yy.b = r.b = y - yy.a;
+       /* Argument reduction: G(x+1) = x*G(x) */
+       for (ym1 = y-one; ym1 > LEFT + x0; y = ym1--, yy.a--) {
+               t = r.a*yy.a;
+               r.b = r.a*yy.b + y*r.b;
+               r.a = t;
+               TRUNC(r.a);
+               r.b += (t - r.a);
+       }
+       /* Return r*tgamma(y). */
+       yy = ratfun_gam(y - x0, 0);
+       y = r.b*(yy.a + yy.b) + r.a*yy.b;
+       y += yy.a*r.a;
+       return (y);
+}
+/*
+ * Good on (0, 1+x0+LEFT].  Accurate to 1ulp.
+ */
+static double
+smaller_gam(x)
+       double x;
+{
+       double t, d;
+       struct Double r, xx;
+       if (x < x0 + LEFT) {
+               t = x, TRUNC(t);
+               d = (t+x)*(x-t);
+               t *= t;
+               xx.a = (t + x), TRUNC(xx.a);
+               xx.b = x - xx.a; xx.b += t; xx.b += d;
+               t = (one-x0); t += x;
+               d = (one-x0); d -= t; d += x;
+               x = xx.a + xx.b;
+       } else {
+               xx.a =  x, TRUNC(xx.a);
+               xx.b = x - xx.a;
+               t = x - x0;
+               d = (-x0 -t); d += x;
+       }
+       r = ratfun_gam(t, d);
+       d = r.a/x, TRUNC(d);
+       r.a -= d*xx.a; r.a -= d*xx.b; r.a += r.b;
+       return (d + r.a/x);
+}
+/*
+ * returns (z+c)^2 * P(z)/Q(z) + a0
+ */
+static struct Double
+ratfun_gam(z, c)
+       double z, c;
+{
+       double p, q;
+       struct Double r, t;
+
+       q = Q0 +z*(Q1+z*(Q2+z*(Q3+z*(Q4+z*(Q5+z*(Q6+z*(Q7+z*Q8)))))));
+       p = P0 + z*(P1 + z*(P2 + z*(P3 + z*P4)));
+
+       /* return r.a + r.b = a0 + (z+c)^2*p/q, with r.a truncated to 26 bits. */
+       p = p/q;
+       t.a = z, TRUNC(t.a);            /* t ~= z + c */
+       t.b = (z - t.a) + c;
+       t.b *= (t.a + z);
+       q = (t.a *= t.a);               /* t = (z+c)^2 */
+       TRUNC(t.a);
+       t.b += (q - t.a);
+       r.a = p, TRUNC(r.a);            /* r = P/Q */
+       r.b = p - r.a;
+       t.b = t.b*p + t.a*r.b + a0_lo;
+       t.a *= r.a;                     /* t = (z+c)^2*(P/Q) */
+       r.a = t.a + a0_hi, TRUNC(r.a);
+       r.b = ((a0_hi-r.a) + t.a) + t.b;
+       return (r);                     /* r = a0 + t */
+}
+
+static double
+neg_gam(x)
+       double x;
+{
+       int sgn = 1;
+       struct Double lg, lsine;
+       double y, z;
+
+       y = ceil(x);
+       if (y == x)             /* Negative integer. */
+               return ((x - x) / zero);
+       z = y - x;
+       if (z > 0.5)
+               z = one - z;
+       y = 0.5 * y;
+       if (y == ceil(y))
+               sgn = -1;
+       if (z < .25)
+               z = sin(M_PI*z);
+       else
+               z = cos(M_PI*(0.5-z));
+       /* Special case: G(1-x) = Inf; G(x) may be nonzero. */
+       if (x < -170) {
+               if (x < -190)
+                       return ((double)sgn*tiny*tiny);
+               y = one - x;            /* exact: 128 < |x| < 255 */
+               lg = large_gam(y);
+               lsine = __log__D(M_PI/z);       /* = TRUNC(log(u)) + small */
+               lg.a -= lsine.a;                /* exact (opposite signs) */
+               lg.b -= lsine.b;
+               y = -(lg.a + lg.b);
+               z = (y + lg.a) + lg.b;
+               y = __exp__D(y, z);
+               if (sgn < 0) y = -y;
+               return (y);
+       }
+       y = one-x;
+       if (one-y == x)
+               y = tgamma(y);
+       else            /* 1-x is inexact */
+               y = -x*tgamma(-x);
+       if (sgn < 0) y = -y;
+       return (M_PI / (y*z));
+}
diff --git a/lib/libm/src/e_acosl.c b/lib/libm/src/e_acosl.c
new file mode 100644 (file)
index 0000000..44f4254
--- /dev/null
@@ -0,0 +1,84 @@
+
+/* @(#)e_acos.c 1.3 95/01/18 */
+/* FreeBSD: head/lib/msun/src/e_acos.c 176451 2008-02-22 02:30:36Z das */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunSoft, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/*
+ * See comments in e_acos.c.
+ * Converted to long double by David Schultz <das@FreeBSD.ORG>.
+ */
+
+#include <float.h>
+
+#include "invtrig.h"
+#include "math.h"
+#include "math_private.h"
+
+static const long double
+one=  1.00000000000000000000e+00;
+
+#ifdef __i386__
+/* XXX Work around the fact that gcc truncates long double constants on i386 */
+static volatile double
+pi1 =  3.14159265358979311600e+00,     /*  0x1.921fb54442d18p+1  */
+pi2 =  1.22514845490862001043e-16;     /*  0x1.1a80000000000p-53 */
+#define        pi      ((long double)pi1 + pi2)
+#else
+static const long double
+pi =  3.14159265358979323846264338327950280e+00L;
+#endif
+
+long double
+acosl(long double x)
+{
+       union IEEEl2bits u;
+       long double z,p,q,r,w,s,c,df;
+       int16_t expsign, expt;
+       u.e = x;
+       expsign = u.xbits.expsign;
+       expt = expsign & 0x7fff;
+       if(expt >= BIAS) {      /* |x| >= 1 */
+           if(expt==BIAS && ((u.bits.manh&~LDBL_NBIT)|u.bits.manl)==0) {
+               if (expsign>0) return 0.0;      /* acos(1) = 0  */
+               else return pi+2.0*pio2_lo;     /* acos(-1)= pi */
+           }
+           return (x-x)/(x-x);         /* acos(|x|>1) is NaN */
+       }
+       if(expt<BIAS-1) {       /* |x| < 0.5 */
+           if(expt<ACOS_CONST) return pio2_hi+pio2_lo;/*x tiny: acosl=pi/2*/
+           z = x*x;
+           p = P(z);
+           q = Q(z);
+           r = p/q;
+           return pio2_hi - (x - (pio2_lo-x*r));
+       } else  if (expsign<0) {        /* x < -0.5 */
+           z = (one+x)*0.5;
+           p = P(z);
+           q = Q(z);
+           s = sqrtl(z);
+           r = p/q;
+           w = r*s-pio2_lo;
+           return pi - 2.0*(s+w);
+       } else {                        /* x > 0.5 */
+           z = (one-x)*0.5;
+           s = sqrtl(z);
+           u.e = s;
+           u.bits.manl = 0;
+           df = u.e;
+           c  = (z-df*df)/(s+df);
+           p = P(z);
+           q = Q(z);
+           r = p/q;
+           w = r*s+c;
+           return 2.0*(df+w);
+       }
+}
diff --git a/lib/libm/src/e_asinl.c b/lib/libm/src/e_asinl.c
new file mode 100644 (file)
index 0000000..f587ef6
--- /dev/null
@@ -0,0 +1,74 @@
+
+/* @(#)e_asin.c 1.3 95/01/18 */
+/* FreeBSD: head/lib/msun/src/e_asin.c 176451 2008-02-22 02:30:36Z das */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunSoft, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/*
+ * See comments in e_asin.c.
+ * Converted to long double by David Schultz <das@FreeBSD.ORG>.
+ */
+
+#include <float.h>
+
+#include "invtrig.h"
+#include "math.h"
+#include "math_private.h"
+
+static const long double
+one =  1.00000000000000000000e+00,
+huge = 1.000e+300;
+
+long double
+asinl(long double x)
+{
+       union IEEEl2bits u;
+       long double t=0.0,w,p,q,c,r,s;
+       int16_t expsign, expt;
+       u.e = x;
+       expsign = u.xbits.expsign;
+       expt = expsign & 0x7fff;
+       if(expt >= BIAS) {              /* |x|>= 1 */
+               if(expt==BIAS && ((u.bits.manh&~LDBL_NBIT)|u.bits.manl)==0)
+                   /* asin(1)=+-pi/2 with inexact */
+                   return x*pio2_hi+x*pio2_lo;
+           return (x-x)/(x-x);         /* asin(|x|>1) is NaN */
+       } else if (expt<BIAS-1) {       /* |x|<0.5 */
+           if(expt<ASIN_LINEAR) {      /* if |x| is small, asinl(x)=x */
+               if(huge+x>one) return x;/* return x with inexact if x!=0*/
+           }
+           t = x*x;
+           p = P(t);
+           q = Q(t);
+           w = p/q;
+           return x+x*w;
+       }
+       /* 1> |x|>= 0.5 */
+       w = one-fabsl(x);
+       t = w*0.5;
+       p = P(t);
+       q = Q(t);
+       s = sqrtl(t);
+       if(u.bits.manh>=THRESH) {       /* if |x| is close to 1 */
+           w = p/q;
+           t = pio2_hi-(2.0*(s+s*w)-pio2_lo);
+       } else {
+           u.e = s;
+           u.bits.manl = 0;
+           w = u.e;
+           c  = (t-w*w)/(s+w);
+           r  = p/q;
+           p  = 2.0*s*r-(pio2_lo-2.0*c);
+           q  = pio4_hi-2.0*w;
+           t  = pio4_hi-(p-q);
+       }
+       if(expsign>0) return t; else return -t;
+}
diff --git a/lib/libm/src/e_atan2l.c b/lib/libm/src/e_atan2l.c
new file mode 100644 (file)
index 0000000..0bb68ee
--- /dev/null
@@ -0,0 +1,117 @@
+
+/* @(#)e_atan2.c 1.3 95/01/18 */
+/* FreeBSD: head/lib/msun/src/e_atan2.c 176451 2008-02-22 02:30:36Z das */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunSoft, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ *
+ */
+
+/*
+ * See comments in e_atan2.c.
+ * Converted to long double by David Schultz <das@FreeBSD.ORG>.
+ */
+
+#include <float.h>
+
+#include "invtrig.h"
+#include "math.h"
+#include "math_private.h"
+
+static volatile long double
+tiny  = 1.0e-300;
+static const long double
+zero  = 0.0;
+
+#ifdef __i386__
+/* XXX Work around the fact that gcc truncates long double constants on i386 */
+static volatile double
+pi1 =  3.14159265358979311600e+00,     /*  0x1.921fb54442d18p+1  */
+pi2 =  1.22514845490862001043e-16;     /*  0x1.1a80000000000p-53 */
+#define        pi      ((long double)pi1 + pi2)
+#else
+static const long double
+pi =  3.14159265358979323846264338327950280e+00L;
+#endif
+
+long double
+atan2l(long double y, long double x)
+{
+       union IEEEl2bits ux, uy;
+       long double z;
+       int32_t k,m;
+       int16_t exptx, expsignx, expty, expsigny;
+
+       uy.e = y;
+       expsigny = uy.xbits.expsign;
+       expty = expsigny & 0x7fff;
+       ux.e = x;
+       expsignx = ux.xbits.expsign;
+       exptx = expsignx & 0x7fff;
+
+       if ((exptx==BIAS+LDBL_MAX_EXP &&
+            ((ux.bits.manh&~LDBL_NBIT)|ux.bits.manl)!=0) ||    /* x is NaN */
+           (expty==BIAS+LDBL_MAX_EXP &&
+            ((uy.bits.manh&~LDBL_NBIT)|uy.bits.manl)!=0))      /* y is NaN */
+           return x+y;
+       if (expsignx==BIAS && ((ux.bits.manh&~LDBL_NBIT)|ux.bits.manl)==0)
+           return atanl(y);                                    /* x=1.0 */
+       m = ((expsigny>>15)&1)|((expsignx>>14)&2);      /* 2*sign(x)+sign(y) */
+
+    /* when y = 0 */
+       if(expty==0 && ((uy.bits.manh&~LDBL_NBIT)|uy.bits.manl)==0) {
+           switch(m) {
+               case 0:
+               case 1: return y;       /* atan(+-0,+anything)=+-0 */
+               case 2: return  pi+tiny;/* atan(+0,-anything) = pi */
+               case 3: return -pi-tiny;/* atan(-0,-anything) =-pi */
+           }
+       }
+    /* when x = 0 */
+       if(exptx==0 && ((ux.bits.manh&~LDBL_NBIT)|ux.bits.manl)==0)
+           return (expsigny<0)?  -pio2_hi-tiny: pio2_hi+tiny;
+
+    /* when x is INF */
+       if(exptx==BIAS+LDBL_MAX_EXP) {
+           if(expty==BIAS+LDBL_MAX_EXP) {
+               switch(m) {
+                   case 0: return  pio2_hi*0.5+tiny;/* atan(+INF,+INF) */
+                   case 1: return -pio2_hi*0.5-tiny;/* atan(-INF,+INF) */
+                   case 2: return  1.5*pio2_hi+tiny;/*atan(+INF,-INF)*/
+                   case 3: return -1.5*pio2_hi-tiny;/*atan(-INF,-INF)*/
+               }
+           } else {
+               switch(m) {
+                   case 0: return  zero  ;     /* atan(+...,+INF) */
+                   case 1: return -zero  ;     /* atan(-...,+INF) */
+                   case 2: return  pi+tiny  ;  /* atan(+...,-INF) */
+                   case 3: return -pi-tiny  ;  /* atan(-...,-INF) */
+               }
+           }
+       }
+    /* when y is INF */
+       if(expty==BIAS+LDBL_MAX_EXP)
+           return (expsigny<0)? -pio2_hi-tiny: pio2_hi+tiny;
+
+    /* compute y/x */
+       k = expty-exptx;
+       if(k > LDBL_MANT_DIG+2) {                       /* |y/x| huge */
+           z=pio2_hi+pio2_lo;
+           m&=1;
+       }
+       else if(expsignx<0&&k<-LDBL_MANT_DIG-2) z=0.0;  /* |y/x| tiny, x<0 */
+       else z=atanl(fabsl(y/x));               /* safe to do y/x */
+       switch (m) {
+           case 0: return       z  ;   /* atan(+,+) */
+           case 1: return      -z  ;   /* atan(-,+) */
+           case 2: return  pi-(z-pi_lo);/* atan(+,-) */
+           default: /* case 3 */
+                   return  (z-pi_lo)-pi;/* atan(-,-) */
+       }
+}
diff --git a/lib/libm/src/e_fmodl.c b/lib/libm/src/e_fmodl.c
new file mode 100644 (file)
index 0000000..d71a281
--- /dev/null
@@ -0,0 +1,148 @@
+/* @(#)e_fmod.c 1.3 95/01/18 */
+/*-
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunSoft, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ *
+ * FreeBSD SVN: 181063 (2008-07-31)
+ */
+
+#include <float.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        uint64_t manl_t;
+#else
+typedef        uint32_t manl_t;
+#endif
+
+#if LDBL_MANH_SIZE > 32
+typedef        uint64_t manh_t;
+#else
+typedef        uint32_t manh_t;
+#endif
+
+/*
+ * These macros add and remove an explicit integer bit in front of the
+ * fractional mantissa, if the architecture doesn't have such a bit by
+ * default already.
+ */
+#ifdef LDBL_IMPLICIT_NBIT
+#define        SET_NBIT(hx)    ((hx) | (1ULL << LDBL_MANH_SIZE))
+#define        HFRAC_BITS      LDBL_MANH_SIZE
+#else
+#define        SET_NBIT(hx)    (hx)
+#define        HFRAC_BITS      (LDBL_MANH_SIZE - 1)
+#endif
+
+#define        MANL_SHIFT      (LDBL_MANL_SIZE - 1)
+
+static const long double one = 1.0, Zero[] = {0.0, -0.0,};
+
+/*
+ * fmodl(x,y)
+ * Return x mod y in exact arithmetic
+ * Method: shift and subtract
+ *
+ * Assumptions:
+ * - The low part of the mantissa fits in a manl_t exactly.
+ * - The high part of the mantissa fits in an int64_t with enough room
+ *   for an explicit integer bit in front of the fractional bits.
+ */
+long double
+fmodl(long double x, long double y)
+{
+       union IEEEl2bits ux, uy;
+       int64_t hx,hz;  /* We need a carry bit even if LDBL_MANH_SIZE is 32. */
+       manh_t hy;
+       manl_t lx,ly,lz;
+       int ix,iy,n,sx;
+
+       ux.e = x;
+       uy.e = y;
+       sx = ux.bits.sign;
+
+    /* purge off exception values */
+       if((uy.bits.exp|uy.bits.manh|uy.bits.manl)==0 || /* y=0 */
+          (ux.bits.exp == BIAS + LDBL_MAX_EXP) ||       /* or x not finite */
+          (uy.bits.exp == BIAS + LDBL_MAX_EXP &&
+           ((uy.bits.manh&~LDBL_NBIT)|uy.bits.manl)!=0)) /* or y is NaN */
+           return (x*y)/(x*y);
+       if(ux.bits.exp<=uy.bits.exp) {
+           if((ux.bits.exp<uy.bits.exp) ||
+              (ux.bits.manh<=uy.bits.manh &&
+               (ux.bits.manh<uy.bits.manh ||
+                ux.bits.manl<uy.bits.manl))) {
+               return x;               /* |x|<|y| return x or x-y */
+           }
+           if(ux.bits.manh==uy.bits.manh && ux.bits.manl==uy.bits.manl) {
+               return Zero[sx];        /* |x|=|y| return x*0*/
+           }
+       }
+
+    /* determine ix = ilogb(x) */
+       if(ux.bits.exp == 0) {  /* subnormal x */
+           ux.e *= 0x1.0p512;
+           ix = ux.bits.exp - (BIAS + 512);
+       } else {
+           ix = ux.bits.exp - BIAS;
+       }
+
+    /* determine iy = ilogb(y) */
+       if(uy.bits.exp == 0) {  /* subnormal y */
+           uy.e *= 0x1.0p512;
+           iy = uy.bits.exp - (BIAS + 512);
+       } else {
+           iy = uy.bits.exp - BIAS;
+       }
+
+    /* set up {hx,lx}, {hy,ly} and align y to x */
+       hx = SET_NBIT(ux.bits.manh);
+       hy = SET_NBIT(uy.bits.manh);
+       lx = ux.bits.manl;
+       ly = uy.bits.manl;
+
+    /* fix point fmod */
+       n = ix - iy;
+
+       while(n--) {
+           hz=hx-hy;lz=lx-ly; if(lx<ly) hz -= 1;
+           if(hz<0){hx = hx+hx+(lx>>MANL_SHIFT); lx = lx+lx;}
+           else {
+               if ((hz|lz)==0)         /* return sign(x)*0 */
+                   return Zero[sx];
+               hx = hz+hz+(lz>>MANL_SHIFT); lx = lz+lz;
+           }
+       }
+       hz=hx-hy;lz=lx-ly; if(lx<ly) hz -= 1;
+       if(hz>=0) {hx=hz;lx=lz;}
+
+    /* convert back to floating value and restore the sign */
+       if((hx|lx)==0)                  /* return sign(x)*0 */
+           return Zero[sx];
+       while(hx<(1ULL<<HFRAC_BITS)) {  /* normalize x */
+           hx = hx+hx+(lx>>MANL_SHIFT); lx = lx+lx;
+           iy -= 1;
+       }
+       ux.bits.manh = hx; /* The mantissa is truncated here if needed. */
+       ux.bits.manl = lx;
+       if (iy < LDBL_MIN_EXP) {
+           ux.bits.exp = iy + (BIAS + 512);
+           ux.e *= 0x1p-512;
+       } else {
+           ux.bits.exp = iy + BIAS;
+       }
+       x = ux.e * one;         /* create necessary signal */
+       return x;               /* exact output */
+}
diff --git a/lib/libm/src/e_hypotl.c b/lib/libm/src/e_hypotl.c
new file mode 100644 (file)
index 0000000..a469479
--- /dev/null
@@ -0,0 +1,123 @@
+/* From: @(#)e_hypot.c 1.3 95/01/18 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunSoft, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ *
+ * FreeBSD SVN: 226412 (2011-10-16)
+ */
+
+/* long double version of hypot().  See e_hypot.c for most comments. */
+
+#include <float.h>
+
+#include "fpmath.h"
+#include "math.h"
+#include "math_private.h"
+
+#define        GET_LDBL_MAN(h, l, v) do {      \
+       union IEEEl2bits uv;            \
+                                       \
+       uv.e = v;                       \
+       h = uv.bits.manh;               \
+       l = uv.bits.manl;               \
+} while (0)
+
+#undef GET_HIGH_WORD
+#define        GET_HIGH_WORD(i, v)     GET_LDBL_EXPSIGN(i, v)
+#undef SET_HIGH_WORD
+#define        SET_HIGH_WORD(v, i)     SET_LDBL_EXPSIGN(v, i)
+
+#define        DESW(exp)       (exp)           /* delta expsign word */
+#define        ESW(exp)        (MAX_EXP - 1 + (exp))   /* expsign word */
+#define        MANT_DIG        LDBL_MANT_DIG
+#define        MAX_EXP         LDBL_MAX_EXP
+
+#if LDBL_MANL_SIZE > 32
+typedef        uint64_t man_t;
+#else
+typedef        uint32_t man_t;
+#endif
+
+long double
+hypotl(long double x, long double y)
+{
+       long double a=x,b=y,t1,t2,y1,y2,w;
+       int32_t j,k,ha,hb;
+
+       GET_HIGH_WORD(ha,x);
+       ha &= 0x7fff;
+       GET_HIGH_WORD(hb,y);
+       hb &= 0x7fff;
+       if(hb > ha) {a=y;b=x;j=ha; ha=hb;hb=j;} else {a=x;b=y;}
+       a = fabsl(a);
+       b = fabsl(b);
+       if((ha-hb)>DESW(MANT_DIG+7)) {return a+b;} /* x/y > 2**(MANT_DIG+7) */
+       k=0;
+       if(ha > ESW(MAX_EXP/2-12)) {    /* a>2**(MAX_EXP/2-12) */
+          if(ha >= ESW(MAX_EXP)) {     /* Inf or NaN */
+              man_t manh, manl;
+              /* Use original arg order iff result is NaN; quieten sNaNs. */
+              w = fabsl(x+0.0)-fabsl(y+0.0);
+              GET_LDBL_MAN(manh,manl,a);
+              if (manh == LDBL_NBIT && manl == 0) w = a;
+              GET_LDBL_MAN(manh,manl,b);
+              if (hb >= ESW(MAX_EXP) && manh == LDBL_NBIT && manl == 0) w = b;
+              return w;
+          }
+          /* scale a and b by 2**-(MAX_EXP/2+88) */
+          ha -= DESW(MAX_EXP/2+88); hb -= DESW(MAX_EXP/2+88);
+          k += MAX_EXP/2+88;
+          SET_HIGH_WORD(a,ha);
+          SET_HIGH_WORD(b,hb);
+       }
+       if(hb < ESW(-(MAX_EXP/2-12))) { /* b < 2**-(MAX_EXP/2-12) */
+           if(hb <= 0) {               /* subnormal b or 0 */
+               man_t manh, manl;
+               GET_LDBL_MAN(manh,manl,b);
+               if((manh|manl)==0) return a;
+               t1=0;
+               SET_HIGH_WORD(t1,ESW(MAX_EXP-2));       /* t1=2^(MAX_EXP-2) */
+               b *= t1;
+               a *= t1;
+               k -= MAX_EXP-2;
+           } else {            /* scale a and b by 2^(MAX_EXP/2+88) */
+               ha += DESW(MAX_EXP/2+88);
+               hb += DESW(MAX_EXP/2+88);
+               k -= MAX_EXP/2+88;
+               SET_HIGH_WORD(a,ha);
+               SET_HIGH_WORD(b,hb);
+           }
+       }
+    /* medium size a and b */
+       w = a-b;
+       if (w>b) {
+           t1 = a;
+           union IEEEl2bits uv;
+           uv.e = t1; uv.bits.manl = 0; t1 = uv.e;
+           t2 = a-t1;
+           w  = sqrtl(t1*t1-(b*(-b)-t2*(a+t1)));
+       } else {
+           a  = a+a;
+           y1 = b;
+           union IEEEl2bits uv;
+           uv.e = y1; uv.bits.manl = 0; y1 = uv.e;
+           y2 = b - y1;
+           t1 = a;
+           uv.e = t1; uv.bits.manl = 0; t1 = uv.e;
+           t2 = a - t1;
+           w  = sqrtl(t1*y1-(w*(-w)-(t1*y2+t2*b)));
+       }
+       if(k!=0) {
+           u_int32_t high;
+           t1 = 1.0;
+           GET_HIGH_WORD(high,t1);
+           SET_HIGH_WORD(t1,high+DESW(k));
+           return t1*w;
+       } else return w;
+}
index 3b217d5..bd5904e 100644 (file)
@@ -1,16 +1,16 @@
-/* @(#)er_lgamma.c 5.1 93/09/24 */
+
+/* @(#)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.
  * ====================================================
  *
- * $NetBSD: e_lgamma_r.c,v 1.10 2002/05/26 22:01:51 wiz Exp $
- * $DragonFly: src/lib/libm/src/e_lgamma_r.c,v 1.1 2005/07/26 21:15:20 joerg Exp $
+ * FreeBSD SVN: 226380 (2011-10-15)
  */
 
 /* lgamma_r(x, signgamp)
  *
  *   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
+ *             lgamma(1) = lgamma(2) = 0
+ *             lgamma(x) ~ -log(|x|) for tiny x
+ *             lgamma(0) = lgamma(neg.integer) = inf and raise divide-by-zero
+ *             lgamma(inf) = inf
+ *             lgamma(-inf) = inf (bug for bug compatible with C99!?)
  *
  */
 
@@ -203,12 +204,12 @@ double
 lgamma_r(double x, int *signgamp)
 {
        double t,y,z,nadj,p,p1,p2,p3,q,r,w;
-       int i,hx,lx,ix;
+       int32_t hx;
+       int i,lx,ix;
 
-       nadj = 0;
        EXTRACT_WORDS(hx,lx,x);
 
-    /* purge off +-inf, NaN, +-0, and negative arguments */
+    /* purge off +-inf, NaN, +-0, tiny and negative arguments */
        *signgamp = 1;
        ix = hx&0x7fffffff;
        if(ix>=0x7ff00000) return x*x;
index 85283cd..f267c46 100644 (file)
@@ -12,8 +12,7 @@
  * is preserved.
  * ====================================================
  *
- * $NetBSD: e_lgammaf_r.c,v 1.6 2002/05/26 22:01:51 wiz Exp $
- * $DragonFly: src/lib/libm/src/e_lgammaf_r.c,v 1.2 2007/07/03 18:51:45 pavalos Exp $
+ * FreeBSD SVN: 226380 (2011-10-15)
  */
 
 #include <math.h>
@@ -98,7 +97,7 @@ sin_pif(float x)
        GET_FLOAT_WORD(ix,x);
        ix &= 0x7fffffff;
 
-       if(ix<0x3e800000) return __kernel_sinf(pi*x,zero,0);
+       if(ix<0x3e800000) return __kernel_sindf(pi*x);
        y = -x;         /* x is assume negative */
 
     /*
@@ -122,14 +121,14 @@ sin_pif(float x)
             }
         }
        switch (n) {
-           case 0:   y =  __kernel_sinf(pi*y,zero,0); break;
+           case 0:   y =  __kernel_sindf(pi*y); break;
            case 1:
-           case 2:   y =  __kernel_cosf(pi*((float)0.5-y),zero); break;
+           case 2:   y =  __kernel_cosdf(pi*((float)0.5-y)); break;
            case 3:
-           case 4:   y =  __kernel_sinf(pi*(one-y),zero,0); break;
+           case 4:   y =  __kernel_sindf(pi*(one-y)); break;
            case 5:
-           case 6:   y = -__kernel_cosf(pi*(y-(float)1.5),zero); break;
-           default:  y =  __kernel_sinf(pi*(y-(float)2.0),zero,0); break;
+           case 6:   y = -__kernel_cosdf(pi*(y-(float)1.5)); break;
+           default:  y =  __kernel_sindf(pi*(y-(float)2.0)); break;
            }
        return -y;
 }
@@ -139,12 +138,12 @@ float
 lgammaf_r(float x, int *signgamp)
 {
        float t,y,z,nadj,p,p1,p2,p3,q,r,w;
-       int i,hx,ix;
+       int32_t hx;
+       int i,ix;
 
-       nadj = 0;
        GET_FLOAT_WORD(hx,x);
 
-    /* purge off +-inf, NaN, +-0, and negative arguments */
+    /* purge off +-inf, NaN, +-0, tiny and negative arguments */
        *signgamp = 1;
        ix = hx&0x7fffffff;
        if(ix>=0x7f800000) return x*x;
index 45d3460..9656c8d 100644 (file)
@@ -6,7 +6,7 @@
  *
  * 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.
  * ====================================================
  *
@@ -41,12 +41,12 @@ log2(double x)
 
        k=0;
        if (hx < 0x00100000) {                  /* x < 2**-1022  */
-           if (((hx&0x7fffffff)|lx)==0) 
+           if (((hx&0x7fffffff)|lx)==0)
                return -two54/zero;             /* log(+-0)=-inf */
            if (hx<0) return (x-x)/zero;        /* log(-#) = NaN */
            k -= 54; x *= two54; /* subnormal number, scale up x */
            GET_HIGH_WORD(hx,x);
-       } 
+       }
        if (hx >= 0x7ff00000) return x+x;
        k += (hx>>20)-1023;
        hx &= 0x000fffff;
@@ -56,18 +56,18 @@ log2(double x)
        f = x-1.0;
        dk = (double)k;
        if((0x000fffff&(2+hx))<3) {     /* |f| < 2**-20 */
-           if (f==zero) 
+           if (f==zero)
                    return (dk);
            R = f*f*(0.5-0.33333333333333333*f);
            return (dk-(R-f)/ln2);
        }
-       s = f/(2.0+f); 
+       s = f/(2.0+f);
        z = s*s;
        i = hx-0x6147a;
        w = z*z;
        j = 0x6b851-hx;
-       t1= w*(Lg2+w*(Lg4+w*Lg6)); 
-       t2= z*(Lg1+w*(Lg3+w*(Lg5+w*Lg7))); 
+       t1= w*(Lg2+w*(Lg4+w*Lg6));
+       t2= z*(Lg1+w*(Lg3+w*(Lg5+w*Lg7)));
        i |= j;
        R = t2+t1;
        if(i>0) {
index 549db93..2a6b5a2 100644 (file)
@@ -20,7 +20,7 @@
 #include "math_private.h"
 
 static const float
-ln2 = 0.6931471805599452862268, 
+ln2 = 0.6931471805599452862268,
 two25 =    3.355443200e+07,    /* 0x4c000000 */
 Lg1 = 6.6666668653e-01,        /* 3F2AAAAB */
 Lg2 = 4.0000000596e-01,        /* 3ECCCCCD */
@@ -57,7 +57,7 @@ log2f(float x)
        dk = (float)k;
        f = x-(float)1.0;
        if((0x007fffff&(15+ix))<16) {   /* |f| < 2**-20 */
-           if (f==zero) 
+           if (f==zero)
                    return (dk);
            R = f*f*((float)0.5-(float)0.33333333333333333*f);
            return (dk-(R-f)/ln2);
index 369b7d5..866aaad 100644 (file)
@@ -1,16 +1,17 @@
-/* @(#)e_rem_pio2.c 5.1 93/09/24 */
+
+/* @(#)e_rem_pio2.c 1.4 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.
  * ====================================================
  *
- * $NetBSD: e_rem_pio2.c,v 1.11 2002/05/26 22:01:52 wiz Exp $
- * $DragonFly: src/lib/libm/src/e_rem_pio2.c,v 1.1 2005/07/26 21:15:20 joerg Exp $
+ * Optimized by Bruce D. Evans.
+ * FreeBSD SVN: 223302 (2011-06-19)
  */
 
 /* __libm_rem_pio2(x,y)
 #include "math_private.h"
 
 /*
- * Table of constants for 2/pi, 396 Hex digits (476 decimal) of 2/pi
- */
-static const int32_t two_over_pi[] = {
-0xA2F983, 0x6E4E44, 0x1529FC, 0x2757D1, 0xF534DD, 0xC0DB62,
-0x95993C, 0x439041, 0xFE5163, 0xABDEBB, 0xC561B7, 0x246E3A,
-0x424DD2, 0xE00649, 0x2EEA09, 0xD1921C, 0xFE1DEB, 0x1CB129,
-0xA73EE8, 0x8235F5, 0x2EBB44, 0x84E99C, 0x7026B4, 0x5F7E41,
-0x3991D6, 0x398353, 0x39F49C, 0x845F8B, 0xBDF928, 0x3B1FF8,
-0x97FFDE, 0x05980F, 0xEF2F11, 0x8B5A0A, 0x6D1F6D, 0x367ECF,
-0x27CB09, 0xB74F46, 0x3F669E, 0x5FEA2D, 0x7527BA, 0xC7EBE5,
-0xF17B3D, 0x0739F7, 0x8A5292, 0xEA6BFB, 0x5FB11F, 0x8D5D08,
-0x560330, 0x46FC7B, 0x6BABF0, 0xCFBC20, 0x9AF436, 0x1DA9E3,
-0x91615E, 0xE61B08, 0x659985, 0x5F14A0, 0x68408D, 0xFFD880,
-0x4D7327, 0x310606, 0x1556CA, 0x73A8C9, 0x60E27B, 0xC08C6B,
-};
-
-static const int32_t npio2_hw[] = {
-0x3FF921FB, 0x400921FB, 0x4012D97C, 0x401921FB, 0x401F6A7A, 0x4022D97C,
-0x4025FDBB, 0x402921FB, 0x402C463A, 0x402F6A7A, 0x4031475C, 0x4032D97C,
-0x40346B9C, 0x4035FDBB, 0x40378FDB, 0x403921FB, 0x403AB41B, 0x403C463A,
-0x403DD85A, 0x403F6A7A, 0x40407E4C, 0x4041475C, 0x4042106C, 0x4042D97C,
-0x4043A28C, 0x40446B9C, 0x404534AC, 0x4045FDBB, 0x4046C6CB, 0x40478FDB,
-0x404858EB, 0x404921FB,
-};
-
-/*
  * invpio2:  53 bits of 2/pi
  * pio2_1:   first  33 bit of pi/2
  * pio2_1t:  pi/2 - pio2_1
@@ -60,7 +35,6 @@ static const int32_t npio2_hw[] = {
 
 static const double
 zero =  0.00000000000000000000e+00, /* 0x00000000, 0x00000000 */
-half =  5.00000000000000000000e-01, /* 0x3FE00000, 0x00000000 */
 two24 =  1.67772160000000000000e+07, /* 0x41700000, 0x00000000 */
 invpio2 =  6.36619772367581382433e-01, /* 0x3FE45F30, 0x6DC9C883 */
 pio2_1  =  1.57079632673412561417e+00, /* 0x3FF921FB, 0x54400000 */
@@ -70,53 +44,93 @@ pio2_2t =  2.02226624879595063154e-21, /* 0x3BA3198A, 0x2E037073 */
 pio2_3  =  2.02226624871116645580e-21, /* 0x3BA3198A, 0x2E000000 */
 pio2_3t =  8.47842766036889956997e-32; /* 0x397B839A, 0x252049C1 */
 
-int32_t
+__inline int
 __libm_rem_pio2(double x, double *y)
 {
        double z,w,t,r,fn;
-       double tx[3];
+       double tx[3],ty[2];
        int32_t e0,i,j,nx,n,ix,hx;
        u_int32_t low;
 
-       z = 0;
        GET_HIGH_WORD(hx,x);            /* high word of x */
        ix = hx&0x7fffffff;
+#if 0 /* Must be handled in caller. */
        if(ix<=0x3fe921fb)   /* |x| ~<= pi/4 , no need for reduction */
            {y[0] = x; y[1] = 0; return 0;}
-       if(ix<0x4002d97c) {  /* |x| < 3pi/4, special case with n=+-1 */
-           if(hx>0) {
-               z = x - pio2_1;
-               if(ix!=0x3ff921fb) {    /* 33+53 bit pi is good enough */
+#endif
+       if (ix <= 0x400f6a7a) {         /* |x| ~<= 5pi/4 */
+           if ((ix & 0xfffff) == 0x921fb)  /* |x| ~= pi/2 or 2pi/2 */
+               goto medium;            /* cancellation -- use medium case */
+           if (ix <= 0x4002d97c) {     /* |x| ~<= 3pi/4 */
+               if (hx > 0) {
+                   z = x - pio2_1;     /* one round good to 85 bits */
                    y[0] = z - pio2_1t;
                    y[1] = (z-y[0])-pio2_1t;
-               } else {                /* near pi/2, use 33+33+53 bit pi */
-                   z -= pio2_2;
-                   y[0] = z - pio2_2t;
-                   y[1] = (z-y[0])-pio2_2t;
-               }
-               return 1;
-           } else {    /* negative x */
-               z = x + pio2_1;
-               if(ix!=0x3ff921fb) {    /* 33+53 bit pi is good enough */
+                   return 1;
+               } else {
+                   z = x + pio2_1;
                    y[0] = z + pio2_1t;
                    y[1] = (z-y[0])+pio2_1t;
-               } else {                /* near pi/2, use 33+33+53 bit pi */
-                   z += pio2_2;
-                   y[0] = z + pio2_2t;
-                   y[1] = (z-y[0])+pio2_2t;
+                   return -1;
+               }
+           } else {
+               if (hx > 0) {
+                   z = x - 2*pio2_1;
+                   y[0] = z - 2*pio2_1t;
+                   y[1] = (z-y[0])-2*pio2_1t;
+                   return 2;
+               } else {
+                   z = x + 2*pio2_1;
+                   y[0] = z + 2*pio2_1t;
+                   y[1] = (z-y[0])+2*pio2_1t;
+                   return -2;
                }
-               return -1;
            }
        }
-       if(ix<=0x413921fb) { /* |x| ~<= 2^19*(pi/2), medium size */
-           t  = fabs(x);
-           n  = (int32_t) (t*invpio2+half);
-           fn = (double)n;
-           r  = t-fn*pio2_1;
-           w  = fn*pio2_1t;    /* 1st round good to 85 bit */
-           if(n<32&&ix!=npio2_hw[n-1]) {
-               y[0] = r-w;     /* quick check no cancellation */
+       if (ix <= 0x401c463b) {         /* |x| ~<= 9pi/4 */
+           if (ix <= 0x4015fdbc) {     /* |x| ~<= 7pi/4 */
+               if (ix == 0x4012d97c)   /* |x| ~= 3pi/2 */
+                   goto medium;
+               if (hx > 0) {
+                   z = x - 3*pio2_1;
+                   y[0] = z - 3*pio2_1t;
+                   y[1] = (z-y[0])-3*pio2_1t;
+                   return 3;
+               } else {
+                   z = x + 3*pio2_1;
+                   y[0] = z + 3*pio2_1t;
+                   y[1] = (z-y[0])+3*pio2_1t;
+                   return -3;
+               }
            } else {
+               if (ix == 0x401921fb)   /* |x| ~= 4pi/2 */
+                   goto medium;
+               if (hx > 0) {
+                   z = x - 4*pio2_1;
+                   y[0] = z - 4*pio2_1t;
+                   y[1] = (z-y[0])-4*pio2_1t;
+                   return 4;
+               } else {
+                   z = x + 4*pio2_1;
+                   y[0] = z + 4*pio2_1t;
+                   y[1] = (z-y[0])+4*pio2_1t;
+                   return -4;
+               }
+           }
+       }
+       if(ix<0x413921fb) {     /* |x| ~< 2^20*(pi/2), medium size */
+medium:
+           /* Use a specialized rint() to get fn.  Assume round-to-nearest. */
+           STRICT_ASSIGN(double,fn,x*invpio2+0x1.8p52);
+           fn = fn-0x1.8p52;
+#ifdef HAVE_EFFICIENT_IRINT
+           n  = irint(fn);
+#else
+           n  = (int32_t)fn;
+#endif
+           r  = x-fn*pio2_1;
+           w  = fn*pio2_1t;    /* 1st round good to 85 bit */
+           {
                u_int32_t high;
                j  = ix>>20;
                y[0] = r-w;
@@ -140,8 +154,7 @@ __libm_rem_pio2(double x, double *y)
                }
            }
            y[1] = (r-y[0])-w;
-           if(hx<0)    {y[0] = -y[0]; y[1] = -y[1]; return -n;}
-           else         return n;
+           return n;
        }
     /*
      * all other (large) arguments
@@ -151,9 +164,8 @@ __libm_rem_pio2(double x, double *y)
        }
     /* set z = scalbn(|x|,ilogb(x)-23) */
        GET_LOW_WORD(low,x);
-       SET_LOW_WORD(z,low);
        e0      = (ix>>20)-1046;        /* e0 = ilogb(z)-23; */
-       SET_HIGH_WORD(z, ix - ((int32_t)(e0<<20)));
+       INSERT_WORDS(z, ix - ((int32_t)(e0<<20)), low);
        for(i=0;i<2;i++) {
                tx[i] = (double)((int32_t)(z));
                z     = (z-tx[i])*two24;
@@ -161,7 +173,7 @@ __libm_rem_pio2(double x, double *y)
        tx[2] = z;
        nx = 3;
        while(tx[nx-1]==zero) nx--;     /* skip zero term */
-       n  =  __kernel_rem_pio2(tx,y,e0,nx,2,two_over_pi);
-       if(hx<0) {y[0] = -y[0]; y[1] = -y[1]; return -n;}
-       return n;
+       n  =  __kernel_rem_pio2(tx,ty,e0,nx,1);
+       if(hx<0) {y[0] = -ty[0]; y[1] = -ty[1]; return -n;}
+       y[0] = ty[0]; y[1] = ty[1]; return n;
 }
index ba02f90..c653571 100644 (file)
@@ -1,5 +1,6 @@
 /* e_rem_pio2f.c -- float version of e_rem_pio2.c
  * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ * Debugged and optimized by Bruce D. Evans.
  */
 
 /*
  * software is freely granted, provided that this notice
  * is preserved.
  * ====================================================
- *
- * $NetBSD: e_rem_pio2f.c,v 1.9 2009/01/19 06:00:30 lukem Exp $
+ * FreeBSD SVN: 193368 (2009-06-03)
  */
 
 /* __libm_rem_pio2f(x,y)
  *
- * return the remainder of x rem pi/2 in y[0]+y[1]
- * use __kernel_rem_pio2f()
+ * return the remainder of x rem pi/2 in *y
+ * use double precision for everything except passing x
+ * use __kernel_rem_pio2() for large x
  */
 
 #include <math.h>
 #include "math_private.h"
 
 /*
- * Table of constants for 2/pi, 396 Hex digits (476 decimal) of 2/pi
- */
-static const int32_t two_over_pi[] = {
-0xA2, 0xF9, 0x83, 0x6E, 0x4E, 0x44, 0x15, 0x29, 0xFC,
-0x27, 0x57, 0xD1, 0xF5, 0x34, 0xDD, 0xC0, 0xDB, 0x62,
-0x95, 0x99, 0x3C, 0x43, 0x90, 0x41, 0xFE, 0x51, 0x63,
-0xAB, 0xDE, 0xBB, 0xC5, 0x61, 0xB7, 0x24, 0x6E, 0x3A,
-0x42, 0x4D, 0xD2, 0xE0, 0x06, 0x49, 0x2E, 0xEA, 0x09,
-0xD1, 0x92, 0x1C, 0xFE, 0x1D, 0xEB, 0x1C, 0xB1, 0x29,
-0xA7, 0x3E, 0xE8, 0x82, 0x35, 0xF5, 0x2E, 0xBB, 0x44,
-0x84, 0xE9, 0x9C, 0x70, 0x26, 0xB4, 0x5F, 0x7E, 0x41,
-0x39, 0x91, 0xD6, 0x39, 0x83, 0x53, 0x39, 0xF4, 0x9C,
-0x84, 0x5F, 0x8B, 0xBD, 0xF9, 0x28, 0x3B, 0x1F, 0xF8,
-0x97, 0xFF, 0xDE, 0x05, 0x98, 0x0F, 0xEF, 0x2F, 0x11,
-0x8B, 0x5A, 0x0A, 0x6D, 0x1F, 0x6D, 0x36, 0x7E, 0xCF,
-0x27, 0xCB, 0x09, 0xB7, 0x4F, 0x46, 0x3F, 0x66, 0x9E,
-0x5F, 0xEA, 0x2D, 0x75, 0x27, 0xBA, 0xC7, 0xEB, 0xE5,
-0xF1, 0x7B, 0x3D, 0x07, 0x39, 0xF7, 0x8A, 0x52, 0x92,
-0xEA, 0x6B, 0xFB, 0x5F, 0xB1, 0x1F, 0x8D, 0x5D, 0x08,
-0x56, 0x03, 0x30, 0x46, 0xFC, 0x7B, 0x6B, 0xAB, 0xF0,
-0xCF, 0xBC, 0x20, 0x9A, 0xF4, 0x36, 0x1D, 0xA9, 0xE3,
-0x91, 0x61, 0x5E, 0xE6, 0x1B, 0x08, 0x65, 0x99, 0x85,
-0x5F, 0x14, 0xA0, 0x68, 0x40, 0x8D, 0xFF, 0xD8, 0x80,
-0x4D, 0x73, 0x27, 0x31, 0x06, 0x06, 0x15, 0x56, 0xCA,
-0x73, 0xA8, 0xC9, 0x60, 0xE2, 0x7B, 0xC0, 0x8C, 0x6B,
-};
-
-/* This array is like the one in e_rem_pio2.c, but the numbers are
-   single precision and the last 8 bits are forced to 0.  */
-static const int32_t npio2_hw[] = {
-0x3fc90f00, 0x40490f00, 0x4096cb00, 0x40c90f00, 0x40fb5300, 0x4116cb00,
-0x412fed00, 0x41490f00, 0x41623100, 0x417b5300, 0x418a3a00, 0x4196cb00,
-0x41a35c00, 0x41afed00, 0x41bc7e00, 0x41c90f00, 0x41d5a000, 0x41e23100,
-0x41eec200, 0x41fb5300, 0x4203f200, 0x420a3a00, 0x42108300, 0x4216cb00,
-0x421d1400, 0x42235c00, 0x4229a500, 0x422fed00, 0x42363600, 0x423c7e00,
-0x4242c700, 0x42490f00
-};
-
-/*
- * invpio2:  24 bits of 2/pi
- * pio2_1:   first  17 bit of pi/2
+ * invpio2:  53 bits of 2/pi
+ * pio2_1:   first  33 bit of pi/2
  * pio2_1t:  pi/2 - pio2_1
- * pio2_2:   second 17 bit of pi/2
- * pio2_2t:  pi/2 - (pio2_1+pio2_2)
- * pio2_3:   third  17 bit of pi/2
- * pio2_3t:  pi/2 - (pio2_1+pio2_2+pio2_3)
  */
 
-static const float
-zero =  0.0000000000e+00, /* 0x00000000 */
-half =  5.0000000000e-01, /* 0x3f000000 */
-two8 =  2.5600000000e+02, /* 0x43800000 */
-invpio2 =  6.3661980629e-01, /* 0x3f22f984 */
-pio2_1  =  1.5707855225e+00, /* 0x3fc90f80 */
-pio2_1t =  1.0804334124e-05, /* 0x37354443 */
-pio2_2  =  1.0804273188e-05, /* 0x37354400 */
-pio2_2t =  6.0770999344e-11, /* 0x2e85a308 */
-pio2_3  =  6.0770943833e-11, /* 0x2e85a300 */
-pio2_3t =  6.1232342629e-17; /* 0x248d3132 */
+static const double
+invpio2 =  6.36619772367581382433e-01, /* 0x3FE45F30, 0x6DC9C883 */
+pio2_1  =  1.57079631090164184570e+00, /* 0x3FF921FB, 0x50000000 */
+pio2_1t =  1.58932547735281966916e-08; /* 0x3E5110b4, 0x611A6263 */
 
-int32_t
-__libm_rem_pio2f(float x, float *y)
+#ifndef INLINE_REM_PIO2F
+extern
+#endif
+__inline int
+__libm_rem_pio2f(float x, double *y)
 {
-       float z,w,t,r,fn;
-       float tx[3];
-       int32_t e0,i,j,nx,n,ix,hx;
+       double w,r,fn;
+       double tx[1],ty[1];
+       float z;
+       int32_t e0,n,ix,hx;
 
        GET_FLOAT_WORD(hx,x);
        ix = hx&0x7fffffff;
-       if(ix<=0x3f490fd8)   /* |x| ~<= pi/4 , no need for reduction */
-           {y[0] = x; y[1] = 0; return 0;}
-       if(ix<0x4016cbe4) {  /* |x| < 3pi/4, special case with n=+-1 */
-           if(hx>0) {
-               z = x - pio2_1;
-               if((ix&0xfffffff0)!=0x3fc90fd0) { /* 24+24 bit pi OK */
-                   y[0] = z - pio2_1t;
-                   y[1] = (z-y[0])-pio2_1t;
-               } else {                /* near pi/2, use 24+24+24 bit pi */
-                   z -= pio2_2;
-                   y[0] = z - pio2_2t;
-                   y[1] = (z-y[0])-pio2_2t;
-               }
-               return 1;
-           } else {    /* negative x */
-               z = x + pio2_1;
-               if((ix&0xfffffff0)!=0x3fc90fd0) { /* 24+24 bit pi OK */
-                   y[0] = z + pio2_1t;
-                   y[1] = (z-y[0])+pio2_1t;
-               } else {                /* near pi/2, use 24+24+24 bit pi */
-                   z += pio2_2;
-                   y[0] = z + pio2_2t;
-                   y[1] = (z-y[0])+pio2_2t;
-               }
-               return -1;
-           }
-       }
-       if(ix<=0x43490f80) { /* |x| ~<= 2^7*(pi/2), medium size */
-           t  = fabsf(x);
-           n  = (int32_t) (t*invpio2+half);
-           fn = (float)n;
-           r  = t-fn*pio2_1;
-           w  = fn*pio2_1t;    /* 1st round good to 40 bit */
-           if(n<32&&(int32_t)(ix&0xffffff00)!=npio2_hw[n-1]) {
-               y[0] = r-w;     /* quick check no cancellation */
-           } else {
-               u_int32_t high;
-               j  = ix>>23;
-               y[0] = r-w;
-               GET_FLOAT_WORD(high,y[0]);
-               i = j-((high>>23)&0xff);
-               if(i>8) {  /* 2nd iteration needed, good to 57 */
-                   t  = r;
-                   w  = fn*pio2_2;
-                   r  = t-w;
-                   w  = fn*pio2_2t-((t-r)-w);
-                   y[0] = r-w;
-                   GET_FLOAT_WORD(high,y[0]);
-                   i = j-((high>>23)&0xff);
-                   if(i>25)  { /* 3rd iteration need, 74 bits acc */
-                       t  = r; /* will cover all possible cases */
-                       w  = fn*pio2_3;
-                       r  = t-w;
-                       w  = fn*pio2_3t-((t-r)-w);
-                       y[0] = r-w;
-                   }
-               }
-           }
-           y[1] = (r-y[0])-w;
-           if(hx<0)    {y[0] = -y[0]; y[1] = -y[1]; return -n;}
-           else         return n;
+    /* 33+53 bit pi is good enough for medium size */
+       if(ix<0x4dc90fdb) {             /* |x| ~< 2^28*(pi/2), medium size */
+           /* Use a specialized rint() to get fn.  Assume round-to-nearest. */
+           STRICT_ASSIGN(double,fn,x*invpio2+0x1.8p52);
+           fn = fn-0x1.8p52;
+#ifdef HAVE_EFFICIENT_IRINT
+           n  = irint(fn);
+#else
+           n  = (int32_t)fn;
+#endif
+           r  = x-fn*pio2_1;
+           w  = fn*pio2_1t;
+           *y = r-w;
+           return n;
        }
     /*
      * all other (large) arguments
      */
        if(ix>=0x7f800000) {            /* x is inf or NaN */
-           y[0]=y[1]=x-x; return 0;
+           *y=x-x; return 0;
        }
-    /* set z = scalbn(|x|,ilogb(x)-7) */
-       e0      = (ix>>23)-134;         /* e0 = ilogb(z)-7; */
+    /* set z = scalbn(|x|,ilogb(|x|)-23) */
+       e0 = (ix>>23)-150;              /* e0 = ilogb(|x|)-23; */
        SET_FLOAT_WORD(z, ix - ((int32_t)(e0<<23)));
-       for(i=0;i<2;i++) {
-               tx[i] = (float)((int32_t)(z));
-               z     = (z-tx[i])*two8;
-       }
-       tx[2] = z;
-       nx = 3;
-       while(tx[nx-1]==zero) nx--;     /* skip zero term */
-       n  =  __kernel_rem_pio2f(tx,y,e0,nx,2,two_over_pi);
-       if(hx<0) {y[0] = -y[0]; y[1] = -y[1]; return -n;}
-       return n;
+       tx[0] = z;
+       n  =  __kernel_rem_pio2(tx,ty,e0,1,0);
+       if(hx<0) {*y = -ty[0]; return -n;}
+       *y = ty[0]; return n;
 }
diff --git a/lib/libm/src/e_rem_pio2l.h b/lib/libm/src/e_rem_pio2l.h
new file mode 100644 (file)
index 0000000..6f0cdd4
--- /dev/null
@@ -0,0 +1,147 @@
+/* From: @(#)e_rem_pio2.c 1.4 95/01/18 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ * Copyright (c) 2008 Steven G. Kargl, David Schultz, Bruce D. Evans.
+ *
+ * Developed at SunSoft, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ *
+ * Optimized by Bruce D. Evans.
+ * FreeBSD SVN: 223262 (2011-06-18)
+ */
+
+/* ld80 version of __ieee754_rem_pio2l(x,y)
+ *
+ * return the remainder of x rem pi/2 in y[0]+y[1]
+ * use __kernel_rem_pio2()
+ */
+
+#include <float.h>
+
+#include "math.h"
+#include "math_private.h"
+#include "fpmath.h"
+
+#define        BIAS    (LDBL_MAX_EXP - 1)
+
+/*
+ * invpio2:  64 bits of 2/pi
+ * pio2_1:   first  39 bits of pi/2
+ * pio2_1t:  pi/2 - pio2_1
+ * pio2_2:   second 39 bits of pi/2
+ * pio2_2t:  pi/2 - (pio2_1+pio2_2)
+ * pio2_3:   third  39 bits of pi/2
+ * pio2_3t:  pi/2 - (pio2_1+pio2_2+pio2_3)
+ */
+
+static const double
+zero =  0.00000000000000000000e+00, /* 0x00000000, 0x00000000 */
+two24 =  1.67772160000000000000e+07, /* 0x41700000, 0x00000000 */
+pio2_1  =  1.57079632679597125389e+00, /* 0x3FF921FB, 0x54444000 */
+pio2_2  = -1.07463465549783099519e-12, /* -0x12e7b967674000.0p-92 */
+pio2_3  =  6.36831716351370313614e-25; /*  0x18a2e037074000.0p-133 */
+
+#if defined(__amd64__) || defined(__i386__)
+/* Long double constants are slow on these arches, and broken on i386. */
+static const volatile double
+invpio2hi =  6.3661977236758138e-01,   /*  0x145f306dc9c883.0p-53 */
+invpio2lo = -3.9356538861223811e-17,   /* -0x16b00000000000.0p-107 */
+pio2_1thi = -1.0746346554971943e-12,   /* -0x12e7b9676733af.0p-92 */
+pio2_1tlo =  8.8451028997905949e-29,   /*  0x1c080000000000.0p-146 */
+pio2_2thi =  6.3683171635109499e-25,   /*  0x18a2e03707344a.0p-133 */
+pio2_2tlo =  2.3183081793789774e-41,   /*  0x10280000000000.0p-187 */
+pio2_3thi = -2.7529965190440717e-37,   /* -0x176b7ed8fbbacc.0p-174 */
+pio2_3tlo = -4.2006647512740502e-54;   /* -0x19c00000000000.0p-230 */
+#define        invpio2 ((long double)invpio2hi + invpio2lo)
+#define        pio2_1t ((long double)pio2_1thi + pio2_1tlo)
+#define        pio2_2t ((long double)pio2_2thi + pio2_2tlo)
+#define        pio2_3t ((long double)pio2_3thi + pio2_3tlo)
+#else
+static const long double
+invpio2 =  6.36619772367581343076e-01L,        /*  0xa2f9836e4e44152a.0p-64 */
+pio2_1t = -1.07463465549719416346e-12L,        /* -0x973dcb3b399d747f.0p-103 */
+pio2_2t =  6.36831716351095013979e-25L,        /*  0xc51701b839a25205.0p-144 */
+pio2_3t = -2.75299651904407171810e-37L;        /* -0xbb5bf6c7ddd660ce.0p-185 */
+#endif
+
+static inline __always_inline int
+__libm_rem_pio2l(long double x, long double *y)
+{
+       union IEEEl2bits u,u1;
+       long double z,w,t,r,fn;
+       double tx[3],ty[2];
+       int e0,ex,i,j,nx,n;
+       int16_t expsign;
+
+       u.e = x;
+       expsign = u.xbits.expsign;
+       ex = expsign & 0x7fff;
+       if (ex < BIAS + 25 || (ex == BIAS + 25 && u.bits.manh < 0xc90fdaa2)) {
+           /* |x| ~< 2^25*(pi/2), medium size */
+           /* Use a specialized rint() to get fn.  Assume round-to-nearest. */
+           fn = x*invpio2+0x1.8p63;
+           fn = fn-0x1.8p63;
+#ifdef HAVE_EFFICIENT_IRINT
+           n  = irint(fn);
+#else
+           n  = fn;
+#endif
+           r  = x-fn*pio2_1;
+           w  = fn*pio2_1t;    /* 1st round good to 102 bit */
+           {
+               union IEEEl2bits u2;
+               int ex1;
+               j  = ex;
+               y[0] = r-w;
+               u2.e = y[0];
+               ex1 = u2.xbits.expsign & 0x7fff;
+               i = j-ex1;
+               if(i>22) {  /* 2nd iteration needed, good to 141 */
+                   t  = r;
+                   w  = fn*pio2_2;
+                   r  = t-w;
+                   w  = fn*pio2_2t-((t-r)-w);
+                   y[0] = r-w;
+                   u2.e = y[0];
+                   ex1 = u2.xbits.expsign & 0x7fff;
+                   i = j-ex1;
+                   if(i>61) {  /* 3rd iteration need, 180 bits acc */
+                       t  = r; /* will cover all possible cases */
+                       w  = fn*pio2_3;
+                       r  = t-w;
+                       w  = fn*pio2_3t-((t-r)-w);
+                       y[0] = r-w;
+                   }
+               }
+           }
+           y[1] = (r-y[0])-w;
+           return n;
+       }
+    /*
+     * all other (large) arguments
+     */
+       if(ex==0x7fff) {                /* x is inf or NaN */
+           y[0]=y[1]=x-x; return 0;
+       }
+    /* set z = scalbn(|x|,ilogb(x)-23) */
+       u1.e = x;
+       e0 = ex - BIAS - 23;            /* e0 = ilogb(|x|)-23; */
+       u1.xbits.expsign = ex - e0;
+       z = u1.e;
+       for(i=0;i<2;i++) {
+               tx[i] = (double)((int32_t)(z));
+               z     = (z-tx[i])*two24;
+       }
+       tx[2] = z;
+       nx = 3;
+       while(tx[nx-1]==zero) nx--;     /* skip zero term */
+       n  =  __kernel_rem_pio2(tx,ty,e0,nx,2);
+       r = (long double)ty[0] + ty[1];
+       w = ty[1] - (r - ty[0]);
+       if(expsign<0) {y[0] = -r; y[1] = -w; return -n;}
+       y[0] = r; y[1] = w; return n;
+}
similarity index 77%
copy from lib/libm/src/s_copysignl.c
copy to lib/libm/src/e_remainderl.c
index 8d39f84..7d70e2e 100644 (file)
@@ -1,5 +1,5 @@
 /*-
- * Copyright (c) 2004 Stefan Farfeleder
+ * Copyright (c) 2008 David Schultz <das@FreeBSD.ORG>
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  *    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
+ * 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 AUTHOR OR CONTRIBUTORS BE LIABLE
+ * 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)
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $FreeBSD$
+ * FreeBSD SVN: 177765 (2008-03-30)
  */
 
 #include <math.h>
 
-#include "fpmath.h"
-
 long double
-copysignl(long double x, long double y)
+remainderl(long double x, long double y)
 {
-       union IEEEl2bits ux, uy;
+       int quo;
 
-       ux.e = x;
-       uy.e = y;
-       ux.bits.sign = uy.bits.sign;
-       return (ux.e);
+       return (remquol(x, y, &quo));
 }
diff --git a/lib/libm/src/e_sqrtl.c b/lib/libm/src/e_sqrtl.c
new file mode 100644 (file)
index 0000000..3bb0361
--- /dev/null
@@ -0,0 +1,160 @@
+/*-
+ * Copyright (c) 2007 Steven G. Kargl
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice unmodified, this list of conditions, and the following
+ *    disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * FreeBSD SVN: 176720 (2008-03-02)
+ */
+
+#include <fenv.h>
+#include <float.h>
+
+#include "fpmath.h"
+#include "math.h"
+
+/* Return (x + ulp) for normal positive x. Assumes no overflow. */
+static inline long double
+inc(long double x)
+{
+       union IEEEl2bits u;
+
+       u.e = x;
+       if (++u.bits.manl == 0) {
+               if (++u.bits.manh == 0) {
+                       u.bits.exp++;
+                       u.bits.manh |= LDBL_NBIT;
+               }
+       }
+       return (u.e);
+}
+
+/* Return (x - ulp) for normal positive x. Assumes no underflow. */
+static inline long double
+dec(long double x)
+{
+       union IEEEl2bits u;
+
+       u.e = x;
+       if (u.bits.manl-- == 0) {
+               if (u.bits.manh-- == LDBL_NBIT) {
+                       u.bits.exp--;
+                       u.bits.manh |= LDBL_NBIT;
+               }
+       }
+       return (u.e);
+}
+
+#if 0  /* Ignored by gcc, emits warning */
+#pragma STDC FENV_ACCESS ON
+#endif
+
+/*
+ * This is slow, but simple and portable. You should use hardware sqrt
+ * if possible.
+ */
+
+long double
+sqrtl(long double x)
+{
+       union IEEEl2bits u;
+       int k, r;
+       long double lo, xn;
+       fenv_t env;
+
+       u.e = x;
+
+       /* If x = NaN, then sqrt(x) = NaN. */
+       /* If x = Inf, then sqrt(x) = Inf. */
+       /* If x = -Inf, then sqrt(x) = NaN. */
+       if (u.bits.exp == LDBL_MAX_EXP * 2 - 1)
+               return (x * x + x);
+
+       /* If x = +-0, then sqrt(x) = +-0. */
+       if ((u.bits.manh | u.bits.manl | u.bits.exp) == 0)
+               return (x);
+
+       /* If x < 0, then raise invalid and return NaN */
+       if (u.bits.sign)
+               return ((x - x) / (x - x));
+
+       feholdexcept(&env);
+
+       if (u.bits.exp == 0) {
+               /* Adjust subnormal numbers. */
+               u.e *= 0x1.0p514;
+               k = -514;
+       } else {
+               k = 0;
+       }
+       /*
+        * u.e is a normal number, so break it into u.e = e*2^n where
+        * u.e = (2*e)*2^2k for odd n and u.e = (4*e)*2^2k for even n.
+        */
+       if ((u.bits.exp - 0x3ffe) & 1) {        /* n is odd.     */
+               k += u.bits.exp - 0x3fff;       /* 2k = n - 1.   */
+               u.bits.exp = 0x3fff;            /* u.e in [1,2). */
+       } else {
+               k += u.bits.exp - 0x4000;       /* 2k = n - 2.   */
+               u.bits.exp = 0x4000;            /* u.e in [2,4). */
+       }
+
+       /*
+        * Newton's iteration.
+        * Split u.e into a high and low part to achieve additional precision.
+        */
+       xn = sqrt(u.e);                 /* 53-bit estimate of sqrtl(x). */
+#if LDBL_MANT_DIG > 100
+       xn = (xn + (u.e / xn)) * 0.5;   /* 106-bit estimate. */
+#endif
+       lo = u.e;
+       u.bits.manl = 0;                /* Zero out lower bits. */
+       lo = (lo - u.e) / xn;           /* Low bits divided by xn. */
+       xn = xn + (u.e / xn);           /* High portion of estimate. */
+       u.e = xn + lo;                  /* Combine everything. */
+       u.bits.exp += (k >> 1) - 1;
+
+       feclearexcept(FE_INEXACT);
+       r = fegetround();
+       fesetround(FE_TOWARDZERO);      /* Set to round-toward-zero. */
+       xn = x / u.e;                   /* Chopped quotient (inexact?). */
+
+       if (!fetestexcept(FE_INEXACT)) { /* Quotient is exact. */
+               if (xn == u.e) {
+                       fesetenv(&env);
+                       return (u.e);
+               }
+               /* Round correctly for inputs like x = y**2 - ulp. */
+               xn = dec(xn);           /* xn = xn - ulp. */
+       }
+
+       if (r == FE_TONEAREST) {
+               xn = inc(xn);           /* xn = xn + ulp. */
+       } else if (r == FE_UPWARD) {
+               u.e = inc(u.e);         /* u.e = u.e + ulp. */
+               xn = inc(xn);           /* xn  = xn + ulp. */
+       }
+       u.e = u.e + xn;                         /* Chopped sum. */
+       feupdateenv(&env);      /* Restore env and raise inexact */
+       u.bits.exp--;
+       return (u.e);
+}
diff --git a/lib/libm/src/invtrig.c b/lib/libm/src/invtrig.c
new file mode 100644 (file)
index 0000000..57c9881
--- /dev/null
@@ -0,0 +1,79 @@
+/*-
+ * Copyright (c) 2008 David Schultz <das@FreeBSD.ORG>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "invtrig.h"
+
+/*
+ * asinl() and acosl()
+ */
+const long double
+pS0 =  1.66666666666666666631e-01L,
+pS1 = -4.16313987993683104320e-01L,
+pS2 =  3.69068046323246813704e-01L,
+pS3 = -1.36213932016738603108e-01L,
+pS4 =  1.78324189708471965733e-02L,
+pS5 = -2.19216428382605211588e-04L,
+pS6 = -7.10526623669075243183e-06L,
+qS1 = -2.94788392796209867269e+00L,
+qS2 =  3.27309890266528636716e+00L,
+qS3 = -1.68285799854822427013e+00L,
+qS4 =  3.90699412641738801874e-01L,
+qS5 = -3.14365703596053263322e-02L;
+
+/*
+ * atanl()
+ */
+const long double atanhi[] = {
+        4.63647609000806116202e-01L,
+        7.85398163397448309628e-01L,
+        9.82793723247329067960e-01L,
+        1.57079632679489661926e+00L,
+};
+
+const long double atanlo[] = {
+        1.18469937025062860669e-20L,
+       -1.25413940316708300586e-20L,
+        2.55232234165405176172e-20L,
+       -2.50827880633416601173e-20L,
+};
+
+const long double aT[] = {
+        3.33333333333333333017e-01L,
+       -1.99999999999999632011e-01L,
+        1.42857142857046531280e-01L,
+       -1.11111111100562372733e-01L,
+        9.09090902935647302252e-02L,
+       -7.69230552476207730353e-02L,
+        6.66661718042406260546e-02L,
+       -5.88158892835030888692e-02L,
+        5.25499891539726639379e-02L,
+       -4.70119845393155721494e-02L,
+        4.03539201366454414072e-02L,
+       -2.91303858419364158725e-02L,
+        1.24822046299269234080e-02L,
+};
+
+const long double pi_lo = -5.01655761266833202345e-20L;
diff --git a/lib/libm/src/invtrig.h b/lib/libm/src/invtrig.h
new file mode 100644 (file)
index 0000000..fe30c01
--- /dev/null
@@ -0,0 +1,114 @@
+/*-
+ * Copyright (c) 2008 David Schultz <das@FreeBSD.ORG>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <float.h>
+
+#include "fpmath.h"
+
+#define        BIAS            (LDBL_MAX_EXP - 1)
+#define        MANH_SIZE       LDBL_MANH_SIZE
+
+/* Approximation thresholds. */
+#define        ASIN_LINEAR     (BIAS - 32)     /* 2**-32 */
+#define        ACOS_CONST      (BIAS - 65)     /* 2**-65 */
+#define        ATAN_CONST      (BIAS + 65)     /* 2**65 */
+#define        ATAN_LINEAR     (BIAS - 32)     /* 2**-32 */
+
+/* 0.95 */
+#define        THRESH  ((0xe666666666666666ULL>>(64-(MANH_SIZE-1)))|LDBL_NBIT)
+
+/* Constants shared by the long double inverse trig functions. */
+#define        pS0     _ItL_pS0
+#define        pS1     _ItL_pS1
+#define        pS2     _ItL_pS2
+#define        pS3     _ItL_pS3
+#define        pS4     _ItL_pS4
+#define        pS5     _ItL_pS5
+#define        pS6     _ItL_pS6
+#define        qS1     _ItL_qS1
+#define        qS2     _ItL_qS2
+#define        qS3     _ItL_qS3
+#define        qS4     _ItL_qS4
+#define        qS5     _ItL_qS5
+#define        atanhi  _ItL_atanhi
+#define        atanlo  _ItL_atanlo
+#define        aT      _ItL_aT
+#define        pi_lo   _ItL_pi_lo
+
+#define        pio2_hi atanhi[3]
+#define        pio2_lo atanlo[3]
+#define        pio4_hi atanhi[1]
+
+#ifdef STRUCT_DECLS
+typedef struct longdouble {
+       uint64_t mant;
+       uint16_t expsign;
+} LONGDOUBLE;
+#else
+typedef long double LONGDOUBLE;
+#endif
+
+extern const LONGDOUBLE pS0, pS1, pS2, pS3, pS4, pS5, pS6;
+extern const LONGDOUBLE qS1, qS2, qS3, qS4, qS5;
+extern const LONGDOUBLE atanhi[], atanlo[], aT[];
+extern const LONGDOUBLE pi_lo;
+
+#ifndef STRUCT_DECLS
+
+static inline long double
+P(long double x)
+{
+
+       return (x * (pS0 + x * (pS1 + x * (pS2 + x * (pS3 + x * \
+               (pS4 + x * (pS5 + x * pS6)))))));
+}
+
+static inline long double
+Q(long double x)
+{
+
+       return (1.0 + x * (qS1 + x * (qS2 + x * (qS3 + x * (qS4 + x * qS5)))));
+}
+
+static inline long double
+T_even(long double x)
+{
+
+       return (aT[0] + x * (aT[2] + x * (aT[4] + x * (aT[6] + x * \
+               (aT[8] + x * (aT[10] + x * aT[12]))))));
+}
+
+static inline long double
+T_odd(long double x)
+{
+
+       return (aT[1] + x * (aT[3] + x * (aT[5] + x * (aT[7] + x * \
+               (aT[9] + x * aT[11])))));
+}
+
+#endif
index 3de1427..6beaa79 100644 (file)
@@ -1,5 +1,6 @@
 /* k_cosf.c -- float version of k_cos.c
  * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ * Debugged and optimized by Bruce D. Evans.
  */
 
 /*
  * software is freely granted, provided that this notice
  * is preserved.
  * ====================================================
- *
- * $NetBSD: k_cosf.c,v 1.7 2002/05/26 22:01:53 wiz Exp $
- * $DragonFly: src/lib/libm/src/k_cosf.c,v 1.1 2005/07/26 21:15:20 joerg Exp $
+ * FreeBSD SVN: 193368 (2009-06-03)
  */
 
 #include <math.h>
 #include "math_private.h"
 
-static const float
-one =  1.0000000000e+00, /* 0x3f800000 */
-C1  =  4.1666667908e-02, /* 0x3d2aaaab */
-C2  = -1.3888889225e-03, /* 0xbab60b61 */
-C3  =  2.4801587642e-05, /* 0x37d00d01 */
-C4  = -2.7557314297e-07, /* 0xb493f27c */
-C5  =  2.0875723372e-09, /* 0x310f74f6 */
-C6  = -1.1359647598e-11; /* 0xad47d74e */
+/* |cos(x) - c(x)| < 2**-34.1 (~[-5.37e-11, 5.295e-11]). */
+static const double
+one =  1.0,
+C0  = -0x1ffffffd0c5e81.0p-54, /* -0.499999997251031003120 */
+C1  =  0x155553e1053a42.0p-57, /*  0.0416666233237390631894 */
+C2  = -0x16c087e80f1e27.0p-62, /* -0.00138867637746099294692 */
+C3  =  0x199342e0ee5069.0p-68; /*  0.0000243904487962774090654 */
 
-float
-__kernel_cosf(float x, float y)
+__inline float
+__kernel_cosdf(double x)
 {
-       float a,hz,z,r,qx;
-       int32_t ix;
-       GET_FLOAT_WORD(ix,x);
-       ix &= 0x7fffffff;                       /* ix = |x|'s high word*/
-       if(ix<0x32000000) {                     /* if x < 2**27 */
-           if(((int)x)==0) return one;         /* generate inexact */
-       }
-       z  = x*x;
-       r  = z*(C1+z*(C2+z*(C3+z*(C4+z*(C5+z*C6)))));
-       if(ix < 0x3e99999a)                     /* if |x| < 0.3 */
-           return one - ((float)0.5*z - (z*r - x*y));
-       else {
-           if(ix > 0x3f480000) {               /* x > 0.78125 */
-               qx = (float)0.28125;
-           } else {
-               SET_FLOAT_WORD(qx,ix-0x01000000);       /* x/4 */
-           }
-           hz = (float)0.5*z-qx;
-           a  = one-qx;
-           return a - (hz - (z*r-x*y));
-       }
+       double r, w, z;
+
+       /* Try to optimize for parallel evaluation as in k_tanf.c. */
+       z = x*x;
+       w = z*z;
+       r = C2+z*C3;
+       return ((one+z*C0) + w*C1) + (w*z)*r;
 }
diff --git a/lib/libm/src/k_cosl.c b/lib/libm/src/k_cosl.c
new file mode 100644 (file)
index 0000000..c2fa4af
--- /dev/null
@@ -0,0 +1,76 @@
+/* From: @(#)k_cos.c 1.3 95/01/18 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ * Copyright (c) 2008 Steven G. Kargl, David Schultz, Bruce D. Evans.
+ *
+ * Developed at SunSoft, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ * FreeBSD SVN: 176357 (2008-02-17)
+ */
+
+/*
+ * ld80 version of k_cos.c.  See ../src/k_cos.c for most comments.
+ */
+
+#include "math_private.h"
+
+/*
+ * Domain [-0.7854, 0.7854], range ~[-2.43e-23, 2.425e-23]:
+ * |cos(x) - c(x)| < 2**-75.1
+ *
+ * The coefficients of c(x) were generated by a pari-gp script using
+ * a Remez algorithm that searches for the best higher coefficients
+ * after rounding leading coefficients to a specified precision.
+ *
+ * Simpler methods like Chebyshev or basic Remez barely suffice for
+ * cos() in 64-bit precision, because we want the coefficient of x^2
+ * to be precisely -0.5 so that multiplying by it is exact, and plain
+ * rounding of the coefficients of a good polynomial approximation only
+ * gives this up to about 64-bit precision.  Plain rounding also gives
+ * a mediocre approximation for the coefficient of x^4, but a rounding
+ * error of 0.5 ulps for this coefficient would only contribute ~0.01
+ * ulps to the final error, so this is unimportant.  Rounding errors in
+ * higher coefficients are even less important.
+ *
+ * In fact, coefficients above the x^4 one only need to have 53-bit
+ * precision, and this is more efficient.  We get this optimization
+ * almost for free from the complications needed to search for the best
+ * higher coefficients.
+ */
+static const double
+one = 1.0;
+
+#if defined(__amd64__) || defined(__i386__)
+/* Long double constants are slow on these arches, and broken on i386. */
+static const volatile double
+C1hi = 0.041666666666666664,           /*  0x15555555555555.0p-57 */
+C1lo = 2.2598839032744733e-18;         /*  0x14d80000000000.0p-111 */
+#define        C1      ((long double)C1hi + C1lo)
+#else
+static const long double
+C1 =  0.0416666666666666666136L;       /*  0xaaaaaaaaaaaaaa9b.0p-68 */
+#endif
+
+static const double
+C2 = -0.0013888888888888874,           /* -0x16c16c16c16c10.0p-62 */
+C3 =  0.000024801587301571716,         /*  0x1a01a01a018e22.0p-68 */
+C4 = -0.00000027557319215507120,       /* -0x127e4fb7602f22.0p-74 */
+C5 =  0.0000000020876754400407278,     /*  0x11eed8caaeccf1.0p-81 */
+C6 = -1.1470297442401303e-11,          /* -0x19393412bd1529.0p-89 */
+C7 =  4.7383039476436467e-14;          /*  0x1aac9d9af5c43e.0p-97 */
+
+long double
+__kernel_cosl(long double x, long double y)
+{
+       long double hz,z,r,w;
+
+       z  = x*x;
+       r  = z*(C1+z*(C2+z*(C3+z*(C4+z*(C5+z*(C6+z*C7))))));
+       hz = 0.5*z;
+       w  = one-hz;
+       return w + (((one-w)-hz) + (z*r-x*y));
+}
index fa9194d..6328f83 100644 (file)
@@ -1,20 +1,21 @@
-/* @(#)k_rem_pio2.c 5.1 93/09/24 */
+
+/* @(#)k_rem_pio2.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.
  * ====================================================
  *
- * $NetBSD: k_rem_pio2.c,v 1.12 2010/04/23 19:17:07 drochner Exp $
+ * FreeBSD SVN: 176550 (2008-02-25)
  */
 
 /*
- * __kernel_rem_pio2(x,y,e0,nx,prec,ipio2)
- * double x[],y[]; int e0,nx,prec; int ipio2[];
+ * __kernel_rem_pio2(x,y,e0,nx,prec)
+ * double x[],y[]; int e0,nx,prec;
  *
  * __kernel_rem_pio2 return the last three digits of N with
  *             y = x - N*pi/2
@@ -58,7 +59,8 @@
  *             r_head = t+w;
  *             r_tail = w - (r_head - t);
  *
- *     e0      The exponent of x[0]
+ *     e0      The exponent of x[0]. Must be <= 16360 or you need to
+ *              expand the ipio2 table.
  *
  *     nx      dimension of x[]
  *
  *                     2       64  bits (extended)
  *                     3       113 bits (quad)
  *
- *     ipio2[]
- *             integer array, contains the (24*i)-th to (24*i+23)-th
- *             bit of 2/pi after binary point. The corresponding
- *             floating value is
- *
- *                     ipio2[i] * 2^(-24(i+1)).
- *
  * External function:
  *     double scalbn(), floor();
  *
  * Here is the description of some local variables:
  *
  *     jk      jk+1 is the initial number of terms of ipio2[] needed
- *             in the computation. The recommended value is 2,3,4,
- *             6 for single, double, extended,and quad.
+ *             in the computation. The minimum and recommended value
+ *             for jk is 3,4,4,6 for single, double, extended, and quad.
+ *             jk+1 must be 2 larger than you might expect so that our
+ *             recomputation test works. (Up to 24 bits in the integer
+ *             part (the 24 bits of it that we compute) and 23 bits in
+ *             the fraction part may be lost to cancelation before we
+ *             recompute.)
  *
  *     jz      local integer variable indicating the number of
  *             terms of ipio2[] used.
 #include <math.h>
 #include "math_private.h"
 
-static const int init_jk[] = {2,3,4,6}; /* initial value for jk */
+static const int init_jk[] = {3,4,4,6}; /* initial value for jk */
+
+/*
+ * Table of constants for 2/pi, 396 Hex digits (476 decimal) of 2/pi
+ *
+ *             integer array, contains the (24*i)-th to (24*i+23)-th
+ *             bit of 2/pi after binary point. The corresponding
+ *             floating value is
+ *
+ *                     ipio2[i] * 2^(-24(i+1)).
+ *
+ * NB: This table must have at least (e0-3)/24 + jk terms.
+ *     For quad precision (e0 <= 16360, jk = 6), this is 686.
+ */
+static const int32_t ipio2[] = {
+0xA2F983, 0x6E4E44, 0x1529FC, 0x2757D1, 0xF534DD, 0xC0DB62,
+0x95993C, 0x439041, 0xFE5163, 0xABDEBB, 0xC561B7, 0x246E3A,
+0x424DD2, 0xE00649, 0x2EEA09, 0xD1921C, 0xFE1DEB, 0x1CB129,
+0xA73EE8, 0x8235F5, 0x2EBB44, 0x84E99C, 0x7026B4, 0x5F7E41,
+0x3991D6, 0x398353, 0x39F49C, 0x845F8B, 0xBDF928, 0x3B1FF8,
+0x97FFDE, 0x05980F, 0xEF2F11, 0x8B5A0A, 0x6D1F6D, 0x367ECF,
+0x27CB09, 0xB74F46, 0x3F669E, 0x5FEA2D, 0x7527BA, 0xC7EBE5,
+0xF17B3D, 0x0739F7, 0x8A5292, 0xEA6BFB, 0x5FB11F, 0x8D5D08,
+0x560330, 0x46FC7B, 0x6BABF0, 0xCFBC20, 0x9AF436, 0x1DA9E3,
+0x91615E, 0xE61B08, 0x659985, 0x5F14A0, 0x68408D, 0xFFD880,
+0x4D7327, 0x310606, 0x1556CA, 0x73A8C9, 0x60E27B, 0xC08C6B,
+
+#if LDBL_MAX_EXP > 1024
+#if LDBL_MAX_EXP > 16384
+#error "ipio2 table needs to be expanded"
+#endif
+0x47C419, 0xC367CD, 0xDCE809, 0x2A8359, 0xC4768B, 0x961CA6,
+0xDDAF44, 0xD15719, 0x053EA5, 0xFF0705, 0x3F7E33, 0xE832C2,
+0xDE4F98, 0x327DBB, 0xC33D26, 0xEF6B1E, 0x5EF89F, 0x3A1F35,
+0xCAF27F, 0x1D87F1, 0x21907C, 0x7C246A, 0xFA6ED5, 0x772D30,
+0x433B15, 0xC614B5, 0x9D19C3, 0xC2C4AD, 0x414D2C, 0x5D000C,
+0x467D86, 0x2D71E3, 0x9AC69B, 0x006233, 0x7CD2B4, 0x97A7B4,
+0xD55537, 0xF63ED7, 0x1810A3, 0xFC764D, 0x2A9D64, 0xABD770,
+0xF87C63, 0x57B07A, 0xE71517, 0x5649C0, 0xD9D63B, 0x3884A7,
+0xCB2324, 0x778AD6, 0x23545A, 0xB91F00, 0x1B0AF1, 0xDFCE19,
+0xFF319F, 0x6A1E66, 0x615799, 0x47FBAC, 0xD87F7E, 0xB76522,
+0x89E832, 0x60BFE6, 0xCDC4EF, 0x09366C, 0xD43F5D, 0xD7DE16,
+0xDE3B58, 0x929BDE, 0x2822D2, 0xE88628, 0x4D58E2, 0x32CAC6,
+0x16E308, 0xCB7DE0, 0x50C017, 0xA71DF3, 0x5BE018, 0x34132E,
+0x621283, 0x014883, 0x5B8EF5, 0x7FB0AD, 0xF2E91E, 0x434A48,
+0xD36710, 0xD8DDAA, 0x425FAE, 0xCE616A, 0xA4280A, 0xB499D3,
+0xF2A606, 0x7F775C, 0x83C2A3, 0x883C61, 0x78738A, 0x5A8CAF,
+0xBDD76F, 0x63A62D, 0xCBBFF4, 0xEF818D, 0x67C126, 0x45CA55,
+0x36D9CA, 0xD2A828, 0x8D61C2, 0x77C912, 0x142604, 0x9B4612,
+0xC459C4, 0x44C5C8, 0x91B24D, 0xF31700, 0xAD43D4, 0xE54929,
+0x10D5FD, 0xFCBE00, 0xCC941E, 0xEECE70, 0xF53E13, 0x80F1EC,
+0xC3E7B3, 0x28F8C7, 0x940593, 0x3E71C1, 0xB3092E, 0xF3450B,
+0x9C1288, 0x7B20AB, 0x9FB52E, 0xC29247, 0x2F327B, 0x6D550C,
+0x90A772, 0x1FE76B, 0x96CB31, 0x4A1679, 0xE27941, 0x89DFF4,
+0x9794E8, 0x84E6E2, 0x973199, 0x6BED88, 0x365F5F, 0x0EFDBB,
+0xB49A48, 0x6CA467, 0x427271, 0x325D8D, 0xB8159F, 0x09E5BC,
+0x25318D, 0x3974F7, 0x1C0530, 0x010C0D, 0x68084B, 0x58EE2C,
+0x90AA47, 0x02E774, 0x24D6BD, 0xA67DF7, 0x72486E, 0xEF169F,
+0xA6948E, 0xF691B4, 0x5153D1, 0xF20ACF, 0x339820, 0x7E4BF5,
+0x6863B2, 0x5F3EDD, 0x035D40, 0x7F8985, 0x295255, 0xC06437,
+0x10D86D, 0x324832, 0x754C5B, 0xD4714E, 0x6E5445, 0xC1090B,
+0x69F52A, 0xD56614, 0x9D0727, 0x50045D, 0xDB3BB4, 0xC576EA,
+0x17F987, 0x7D6B49, 0xBA271D, 0x296996, 0xACCCC6, 0x5414AD,
+0x6AE290, 0x89D988, 0x50722C, 0xBEA404, 0x940777, 0x7030F3,
+0x27FC00, 0xA871EA, 0x49C266, 0x3DE064, 0x83DD97, 0x973FA3,
+0xFD9443, 0x8C860D, 0xDE4131, 0x9D3992, 0x8C70DD, 0xE7B717,
+0x3BDF08, 0x2B3715, 0xA0805C, 0x93805A, 0x921110, 0xD8E80F,
+0xAF806C, 0x4BFFDB, 0x0F9038, 0x761859, 0x15A562, 0xBBCB61,
+0xB989C7, 0xBD4010, 0x04F2D2, 0x277549, 0xF6B6EB, 0xBB22DB,
+0xAA140A, 0x2F2689, 0x768364, 0x333B09, 0x1A940E, 0xAA3A51,
+0xC2A31D, 0xAEEDAF, 0x12265C, 0x4DC26D, 0x9C7A2D, 0x9756C0,
+0x833F03, 0xF6F009, 0x8C402B, 0x99316D, 0x07B439, 0x15200C,
+0x5BC3D8, 0xC492F5, 0x4BADC6, 0xA5CA4E, 0xCD37A7, 0x36A9E6,
+0x9492AB, 0x6842DD, 0xDE6319, 0xEF8C76, 0x528B68, 0x37DBFC,
+0xABA1AE, 0x3115DF, 0xA1AE00, 0xDAFB0C, 0x664D64, 0xB705ED,
+0x306529, 0xBF5657, 0x3AFF47, 0xB9F96A, 0xF3BE75, 0xDF9328,
+0x3080AB, 0xF68C66, 0x15CB04, 0x0622FA, 0x1DE4D9, 0xA4B33D,
+0x8F1B57, 0x09CD36, 0xE9424E, 0xA4BE13, 0xB52333, 0x1AAAF0,
+0xA8654F, 0xA5C1D2, 0x0F3F0B, 0xCD785B, 0x76F923, 0x048B7B,
+0x721789, 0x53A6C6, 0xE26E6F, 0x00EBEF, 0x584A9B, 0xB7DAC4,
+0xBA66AA, 0xCFCF76, 0x1D02D1, 0x2DF1B1, 0xC1998C, 0x77ADC3,
+0xDA4886, 0xA05DF7, 0xF480C6, 0x2FF0AC, 0x9AECDD, 0xBC5C3F,
+0x6DDED0, 0x1FC790, 0xB6DB2A, 0x3A25A3, 0x9AAF00, 0x9353AD,
+0x0457B6, 0xB42D29, 0x7E804B, 0xA707DA, 0x0EAA76, 0xA1597B,
+0x2A1216, 0x2DB7DC, 0xFDE5FA, 0xFEDB89, 0xFDBE89, 0x6C76E4,
+0xFCA906, 0x70803E, 0x156E85, 0xFF87FD, 0x073E28, 0x336761,
+0x86182A, 0xEABD4D, 0xAFE7B3, 0x6E6D8F, 0x396795, 0x5BBF31,
+0x48D784, 0x16DF30, 0x432DC7, 0x356125, 0xCE70C9, 0xB8CB30,
+0xFD6CBF, 0xA200A4, 0xE46C05, 0xA0DD5A, 0x476F21, 0xD21262,
+0x845CB9, 0x496170, 0xE0566B, 0x015299, 0x375550, 0xB7D51E,
+0xC4F133, 0x5F6E13, 0xE4305D, 0xA92E85, 0xC3B21D, 0x3632A1,
+0xA4B708, 0xD4B1EA, 0x21F716, 0xE4698F, 0x77FF27, 0x80030C,
+0x2D408D, 0xA0CD4F, 0x99A520, 0xD3A2B3, 0x0A5D2F, 0x42F9B4,
+0xCBDA11, 0xD0BE7D, 0xC1DB9B, 0xBD17AB, 0x81A2CA, 0x5C6A08,
+0x17552E, 0x550027, 0xF0147F, 0x8607E1, 0x640B14, 0x8D4196,
+0xDEBE87, 0x2AFDDA, 0xB6256B, 0x34897B, 0xFEF305, 0x9EBFB9,
+0x4F6A68, 0xA82A4A, 0x5AC44F, 0xBCF82D, 0x985AD7, 0x95C7F4,
+0x8D4D0D, 0xA63A20, 0x5F57A4, 0xB13F14, 0x953880, 0x0120CC,
+0x86DD71, 0xB6DEC9, 0xF560BF, 0x11654D, 0x6B0701, 0xACB08C,
+0xD0C0B2, 0x485551, 0x0EFB1E, 0xC37295, 0x3B06A3, 0x3540C0,
+0x7BDC06, 0xCC45E0, 0xFA294E, 0xC8CAD6, 0x41F3E8, 0xDE647C,
+0xD8649B, 0x31BED9, 0xC397A4, 0xD45877, 0xC5E369, 0x13DAF0,
+0x3C3ABA, 0x461846, 0x5F7555, 0xF5BDD2, 0xC6926E, 0x5D2EAC,
+0xED440E, 0x423E1C, 0x87C461, 0xE9FD29, 0xF3D6E7, 0xCA7C22,
+0x35916F, 0xC5E008, 0x8DD7FF, 0xE26A6E, 0xC6FDB0, 0xC10893,
+0x745D7C, 0xB2AD6B, 0x9D6ECD, 0x7B723E, 0x6A11C6, 0xA9CFF7,
+0xDF7329, 0xBAC9B5, 0x5100B7, 0x0DB2E2, 0x24BA74, 0x607DE5,
+0x8AD874, 0x2C150D, 0x0C1881, 0x94667E, 0x162901, 0x767A9F,
+0xBEFDFD, 0xEF4556, 0x367ED9, 0x13D9EC, 0xB9BA8B, 0xFC97C4,
+0x27A831, 0xC36EF1, 0x36C594, 0x56A8D8, 0xB5A8B4, 0x0ECCCF,
+0x2D8912, 0x34576F, 0x89562C, 0xE3CE99, 0xB920D6, 0xAA5E6B,
+0x9C2A3E, 0xCC5F11, 0x4A0BFD, 0xFBF4E1, 0x6D3B8E, 0x2C86E2,
+0x84D4E9, 0xA9B4FC, 0xD1EEEF, 0xC9352E, 0x61392F, 0x442138,
+0xC8D91B, 0x0AFC81, 0x6A4AFB, 0xD81C2F, 0x84B453, 0x8C994E,
+0xCC2254, 0xDC552A, 0xD6C6C0, 0x96190B, 0xB8701A, 0x649569,
+0x605A26, 0xEE523F, 0x0F117F, 0x11B5F4, 0xF5CBFC, 0x2DBC34,
+0xEEBC34, 0xCC5DE8, 0x605EDD, 0x9B8E67, 0xEF3392, 0xB817C9,
+0x9B5861, 0xBC57E1, 0xC68351, 0x103ED8, 0x4871DD, 0xDD1C2D,
+0xA118AF, 0x462C21, 0xD7F359, 0x987AD9, 0xC0549E, 0xFA864F,
+0xFC0656, 0xAE79E5, 0x362289, 0x22AD38, 0xDC9367, 0xAAE855,
+0x382682, 0x9BE7CA, 0xA40D51, 0xB13399, 0x0ED7A9, 0x480569,
+0xF0B265, 0xA7887F, 0x974C88, 0x36D1F9, 0xB39221, 0x4A827B,
+0x21CF98, 0xDC9F40, 0x5547DC, 0x3A74E1, 0x42EB67, 0xDF9DFE,
+0x5FD45E, 0xA4677B, 0x7AACBA, 0xA2F655, 0x23882B, 0x55BA41,
+0x086E59, 0x862A21, 0x834739, 0xE6E389, 0xD49EE5, 0x40FB49,
+0xE956FF, 0xCA0F1C, 0x8A59C5, 0x2BFA94, 0xC5C1D3, 0xCFC50F,
+0xAE5ADB, 0x86C547, 0x624385, 0x3B8621, 0x94792C, 0x876110,
+0x7B4C2A, 0x1A2C80, 0x12BF43, 0x902688, 0x893C78, 0xE4C4A8,
+0x7BDBE5, 0xC23AC4, 0xEAF426, 0x8A67F7, 0xBF920D, 0x2BA365,
+0xB1933D, 0x0B7CBD, 0xDC51A4, 0x63DD27, 0xDDE169, 0x19949A,
+0x9529A8, 0x28CE68, 0xB4ED09, 0x209F44, 0xCA984E, 0x638270,
+0x237C7E, 0x32B90F, 0x8EF5A7, 0xE75614, 0x08F121, 0x2A9DB5,
+0x4D7E6F, 0x5119A5, 0xABF9B5, 0xD6DF82, 0x61DD96, 0x023616,
+0x9F3AC4, 0xA1A283, 0x6DED72, 0x7A8D39, 0xA9B882, 0x5C326B,
+0x5B2746, 0xED3400, 0x7700D2, 0x55F4FC, 0x4D5901, 0x8071E0,
+#endif
+
+};
 
 static const double PIo2[] = {
   1.57079625129699707031e+00, /* 0x3FF921FB, 0x40000000 */
@@ -151,7 +288,7 @@ two24   =  1.67772160000000000000e+07, /* 0x41700000, 0x00000000 */
 twon24  =  5.96046447753906250000e-08; /* 0x3E700000, 0x00000000 */
 
 int
-__kernel_rem_pio2(double *x, double *y, int e0, int nx, int prec, const int32_t *ipio2)
+__kernel_rem_pio2(double *x, double *y, int e0, int nx, int prec)
 {
        int32_t jz,jx,jv,jp,jk,carry,n,iq[20],i,j,k,m,q0,ih;
        double z,fw,f[20],fq[20],q[20];
@@ -275,6 +412,7 @@ recompute:
            case 2:
                fw = 0.0;
                for (i=jz;i>=0;i--) fw += fq[i];
+               STRICT_ASSIGN(double,fw,fw);
                y[0] = (ih==0)? fw: -fw;
                fw = fq[0]-fw;
                for (i=1;i<=jz;i++) fw += fq[i];
index 671adca..af8f355 100644 (file)
@@ -1,5 +1,6 @@
 /* k_sinf.c -- float version of k_sin.c
  * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ * Optimized by Bruce D. Evans.
  */
 
 /*
  * software is freely granted, provided that this notice
  * is preserved.
  * ====================================================
- *
- * $NetBSD: k_sinf.c,v 1.7 2002/05/26 22:01:53 wiz Exp $
- * $DragonFly: src/lib/libm/src/k_sinf.c,v 1.1 2005/07/26 21:15:20 joerg Exp $
+ * FreeBSD SVN: 193368 (2009-06-03)
  */
 
+
 #include <math.h>
 #include "math_private.h"
 
-static const float
-half =  5.0000000000e-01,/* 0x3f000000 */
-S1  = -1.6666667163e-01, /* 0xbe2aaaab */
-S2  =  8.3333337680e-03, /* 0x3c088889 */
-S3  = -1.9841270114e-04, /* 0xb9500d01 */
-S4  =  2.7557314297e-06, /* 0x3638ef1b */
-S5  = -2.5050759689e-08, /* 0xb2d72f34 */
-S6  =  1.5896910177e-10; /* 0x2f2ec9d3 */
+/* |sin(x)/x - s(x)| < 2**-37.5 (~[-4.89e-12, 4.824e-12]). */
+static const double
+S1 = -0x15555554cbac77.0p-55,  /* -0.166666666416265235595 */
+S2 =  0x111110896efbb2.0p-59,  /*  0.0083333293858894631756 */
+S3 = -0x1a00f9e2cae774.0p-65,  /* -0.000198393348360966317347 */
+S4 =  0x16cd878c3b46a7.0p-71;  /*  0.0000027183114939898219064 */
 
-float
-__kernel_sinf(float x, float y, int iy)
+__inline float
+__kernel_sindf(double x)
 {
-       float z,r,v;
-       int32_t ix;
-       GET_FLOAT_WORD(ix,x);
-       ix &= 0x7fffffff;                       /* high word of x */
-       if(ix<0x32000000)                       /* |x| < 2**-27 */
-          {if((int)x==0) return x;}            /* generate inexact */
-       z       =  x*x;
-       v       =  z*x;
-       r       =  S2+z*(S3+z*(S4+z*(S5+z*S6)));
-       if(iy==0) return x+v*(S1+z*r);
-       else      return x-((z*(half*y-v*r)-y)-v*S1);
+       double r, s, w, z;
+
+       /* Try to optimize for parallel evaluation as in k_tanf.c. */
+       z = x*x;
+       w = z*z;
+       r = S3+z*S4;
+       s = z*x;
+       return (x + s*(S1+z*S2)) + s*w*r;
 }
diff --git a/lib/libm/src/k_sinl.c b/lib/libm/src/k_sinl.c
new file mode 100644 (file)
index 0000000..3cf9117
--- /dev/null
@@ -0,0 +1,60 @@
+/* From: @(#)k_sin.c 1.3 95/01/18 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ * Copyright (c) 2008 Steven G. Kargl, David Schultz, Bruce D. Evans.
+ *
+ * Developed at SunSoft, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ * FreeBSD SVN: 176357 (2008-02-17)
+ */
+
+/*
+ * ld80 version of k_sin.c.  See ../src/k_sin.c for most comments.
+ */
+
+#include "math_private.h"
+
+static const double
+half =  0.5;
+
+/*
+ * Domain [-0.7854, 0.7854], range ~[-1.89e-22, 1.915e-22]
+ * |sin(x)/x - s(x)| < 2**-72.1
+ *
+ * See ../ld80/k_cosl.c for more details about the polynomial.
+ */
+#if defined(__amd64__) || defined(__i386__)
+/* Long double constants are slow on these arches, and broken on i386. */
+static const volatile double
+S1hi = -0.16666666666666666,           /* -0x15555555555555.0p-55 */
+S1lo = -9.2563760475949941e-18;                /* -0x15580000000000.0p-109 */
+#define        S1      ((long double)S1hi + S1lo)
+#else
+static const long double
+S1 = -0.166666666666666666671L;                /* -0xaaaaaaaaaaaaaaab.0p-66 */
+#endif
+
+static const double
+S2 =  0.0083333333333333332,           /*  0x11111111111111.0p-59 */
+S3 = -0.00019841269841269427,          /* -0x1a01a01a019f81.0p-65 */
+S4 =  0.0000027557319223597490,                /*  0x171de3a55560f7.0p-71 */
+S5 = -0.000000025052108218074604,      /* -0x1ae64564f16cad.0p-78 */
+S6 =  1.6059006598854211e-10,          /*  0x161242b90243b5.0p-85 */
+S7 = -7.6429779983024564e-13,          /* -0x1ae42ebd1b2e00.0p-93 */
+S8 =  2.6174587166648325e-15;          /*  0x179372ea0b3f64.0p-101 */
+
+long double
+__kernel_sinl(long double x, long double y, int iy)
+{
+       long double z,r,v;
+
+       z       =  x*x;
+       v       =  z*x;
+       r       =  S2+z*(S3+z*(S4+z*(S5+z*(S6+z*(S7+z*S8)))));
+       if(iy==0) return x+v*(S1+z*r);
+       else      return x-((z*(half*y-v*r)-y)-v*S1);
+}
index d58336d..21e2d2f 100644 (file)
@@ -1,92 +1,59 @@
 /* k_tanf.c -- float version of k_tan.c
  * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ * Optimized by Bruce D. Evans.
  */
 
 /*
  * ====================================================
- * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2004 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.
  * ====================================================
- *
- * $NetBSD: k_tanf.c,v 1.7 2002/05/26 22:01:54 wiz Exp $
- * $DragonFly: src/lib/libm/src/k_tanf.c,v 1.1 2005/07/26 21:15:20 joerg Exp $
+ * FreeBSD SVN: 193368 (2009-06-03)
  */
 
 #include <math.h>
 #include "math_private.h"
-static const float
-one   =  1.0000000000e+00, /* 0x3f800000 */
-pio4  =  7.8539812565e-01, /* 0x3f490fda */
-pio4lo=  3.7748947079e-08, /* 0x33222168 */
+
+/* |tan(x)/x - t(x)| < 2**-25.5 (~[-2e-08, 2e-08]). */
+static const double
 T[] =  {
-  3.3333334327e-01, /* 0x3eaaaaab */
-  1.3333334029e-01, /* 0x3e088889 */
-  5.3968254477e-02, /* 0x3d5d0dd1 */
-  2.1869488060e-02, /* 0x3cb327a4 */
-  8.8632395491e-03, /* 0x3c11371f */
-  3.5920790397e-03, /* 0x3b6b6916 */
-  1.4562094584e-03, /* 0x3abede48 */
-  5.8804126456e-04, /* 0x3a1a26c8 */
-  2.4646313977e-04, /* 0x398137b9 */
-  7.8179444245e-05, /* 0x38a3f445 */
-  7.1407252108e-05, /* 0x3895c07a */
- -1.8558637748e-05, /* 0xb79bae5f */
-  2.5907305826e-05, /* 0x37d95384 */
+  0x15554d3418c99f.0p-54,      /* 0.333331395030791399758 */
+  0x1112fd38999f72.0p-55,      /* 0.133392002712976742718 */
+  0x1b54c91d865afe.0p-57,      /* 0.0533812378445670393523 */
+  0x191df3908c33ce.0p-58,      /* 0.0245283181166547278873 */
+  0x185dadfcecf44e.0p-61,      /* 0.00297435743359967304927 */
+  0x1362b9bf971bcd.0p-59,      /* 0.00946564784943673166728 */
 };
 
-float
-__kernel_tanf(float x, float y, int iy)
+__inline float
+__kernel_tandf(double x, int iy)
 {
-       float z,r,v,w,s;
-       int32_t ix,hx;
-       GET_FLOAT_WORD(hx,x);
-       ix = hx&0x7fffffff;     /* high word of |x| */
-       if(ix<0x31800000)                       /* x < 2**-28 */
-           {if((int)x==0) {                    /* generate inexact */
-               if((ix|(iy+1))==0) return one/fabsf(x);
-               else return (iy==1)? x: -one/x;
-           }
-           }
-       if(ix>=0x3f2ca140) {                    /* |x|>=0.6744 */
-           if(hx<0) {x = -x; y = -y;}
-           z = pio4-x;
-           w = pio4lo-y;
-           x = z+w; y = 0.0;
-       }
+       double z,r,w,s,t,u;
+
        z       =  x*x;
-       w       =  z*z;
-    /* Break x^5*(T[1]+x^2*T[2]+...) into
-     *   x^5(T[1]+x^4*T[3]+...+x^20*T[11]) +
-     *   x^5(x^2*(T[2]+x^4*T[4]+...+x^22*[T12]))
-     */
-       r = T[1]+w*(T[3]+w*(T[5]+w*(T[7]+w*(T[9]+w*T[11]))));
-       v = z*(T[2]+w*(T[4]+w*(T[6]+w*(T[8]+w*(T[10]+w*T[12])))));
+       /*
+        * Split up the polynomial into small independent terms to give
+        * opportunities for parallel evaluation.  The chosen splitting is
+        * micro-optimized for Athlons (XP, X64).  It costs 2 multiplications
+        * relative to Horner's method on sequential machines.
+        *
+        * We add the small terms from lowest degree up for efficiency on
+        * non-sequential machines (the lowest degree terms tend to be ready
+        * earlier).  Apart from this, we don't care about order of
+        * operations, and don't need to to care since we have precision to
+        * spare.  However, the chosen splitting is good for accuracy too,
+        * and would give results as accurate as Horner's method if the
+        * small terms were added from highest degree down.
+        */
+       r = T[4]+z*T[5];
+       t = T[2]+z*T[3];
+       w = z*z;
        s = z*x;
-       r = y + z*(s*(r+v)+y);
-       r += T[0]*s;
-       w = x+r;
-       if(ix>=0x3f2ca140) {
-           v = (float)iy;
-           return (float)(1-((hx>>30)&2))*(v-(float)2.0*(x-(w*w/(w+v)-r)));
-       }
-       if(iy==1) return w;
-       else {          /* if allow error up to 2 ulp,
-                          simply return -1.0/(x+r) here */
-     /*  compute -1.0/(x+r) accurately */
-           float a,t;
-           int32_t i;
-           z  = w;
-           GET_FLOAT_WORD(i,z);
-           SET_FLOAT_WORD(z,i&0xfffff000);
-           v  = r-(z - x);     /* z+v = r+x */
-           t = a  = -(float)1.0/w;     /* a = -1.0/w */
-           GET_FLOAT_WORD(i,t);
-           SET_FLOAT_WORD(t,i&0xfffff000);
-           s  = (float)1.0+t*z;
-           return t+a*(s+t*v);
-       }
+       u = T[0]+z*T[1];
+       r = (x+s*u)+(s*w)*(t+w*r);
+       if(iy==1) return r;
+       else return -1.0/r;
 }
diff --git a/lib/libm/src/k_tanl.c b/lib/libm/src/k_tanl.c
new file mode 100644 (file)
index 0000000..0aa28ed
--- /dev/null
@@ -0,0 +1,122 @@
+/* From: @(#)k_tan.c 1.5 04/04/22 SMI */
+
+/*
+ * ====================================================
+ * Copyright 2004 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright (c) 2008 Steven G. Kargl, David Schultz, Bruce D. Evans.
+ *
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ * FreeBSD SVN: 176357 (2008-02-17)
+ */
+
+/*
+ * ld80 version of k_tan.c.  See ../src/k_tan.c for most comments.
+ */
+
+#include <math.h>
+#include "math_private.h"
+
+/*
+ * Domain [-0.67434, 0.67434], range ~[-2.25e-22, 1.921e-22]
+ * |tan(x)/x - t(x)| < 2**-71.9
+ *
+ * See k_cosl.c for more details about the polynomial.
+ */
+#if defined(__amd64__) || defined(__i386__)
+/* Long double constants are slow on these arches, and broken on i386. */
+static const volatile double
+T3hi =  0.33333333333333331,           /*  0x15555555555555.0p-54 */
+T3lo =  1.8350121769317163e-17,                /*  0x15280000000000.0p-108 */
+T5hi =  0.13333333333333336,           /*  0x11111111111112.0p-55 */
+T5lo =  1.3051083651294260e-17,                /*  0x1e180000000000.0p-109 */
+T7hi =  0.053968253968250494,          /*  0x1ba1ba1ba1b827.0p-57 */
+T7lo =  3.1509625637859973e-18,                /*  0x1d100000000000.0p-111 */
+pio4_hi =  0.78539816339744828,                /*  0x1921fb54442d18.0p-53 */
+pio4_lo =  3.0628711372715500e-17,     /*  0x11a80000000000.0p-107 */
+pio4lo_hi = -1.2541394031670831e-20,   /* -0x1d9cceba3f91f2.0p-119 */
+pio4lo_lo =  6.1493048227390915e-37;   /*  0x1a280000000000.0p-173 */
+#define        T3      ((long double)T3hi + T3lo)
+#define        T5      ((long double)T5hi + T5lo)
+#define        T7      ((long double)T7hi + T7lo)
+#define        pio4    ((long double)pio4_hi + pio4_lo)
+#define        pio4lo  ((long double)pio4lo_hi + pio4lo_lo)
+#else
+static const long double
+T3 =   0.333333333333333333180L,       /*  0xaaaaaaaaaaaaaaa5.0p-65 */
+T5 =   0.133333333333333372290L,       /*  0x88888888888893c3.0p-66 */
+T7 =   0.0539682539682504975744L,      /*  0xdd0dd0dd0dc13ba2.0p-68 */
+pio4 = 0.785398163397448309628L,       /*  0xc90fdaa22168c235.0p-64 */
+pio4lo = -1.25413940316708300586e-20L; /* -0xece675d1fc8f8cbb.0p-130 */
+#endif
+
+static const double
+T9  =  0.021869488536312216,           /*  0x1664f4882cc1c2.0p-58 */
+T11 =  0.0088632355256619590,          /*  0x1226e355c17612.0p-59 */
+T13 =  0.0035921281113786528,          /*  0x1d6d3d185d7ff8.0p-61 */
+T15 =  0.0014558334756312418,          /*  0x17da354aa3f96b.0p-62 */
+T17 =  0.00059003538700862256,         /*  0x13559358685b83.0p-63 */
+T19 =  0.00023907843576635544,         /*  0x1f56242026b5be.0p-65 */
+T21 =  0.000097154625656538905,                /*  0x1977efc26806f4.0p-66 */
+T23 =  0.000038440165747303162,                /*  0x14275a09b3ceac.0p-67 */
+T25 =  0.000018082171885432524,                /*  0x12f5e563e5487e.0p-68 */
+T27 =  0.0000024196006108814377,       /*  0x144c0d80cc6896.0p-71 */
+T29 =  0.0000078293456938132840,       /*  0x106b59141a6cb3.0p-69 */
+T31 = -0.0000032609076735050182,       /* -0x1b5abef3ba4b59.0p-71 */
+T33 =  0.0000023261313142559411;       /*  0x13835436c0c87f.0p-71 */
+
+long double
+__kernel_tanl(long double x, long double y, int iy) {
+       long double z, r, v, w, s;
+       long double osign;
+       int i;
+
+       iy = (iy == 1 ? -1 : 1);        /* XXX recover original interface */
+       osign = (x >= 0 ? 1.0 : -1.0);  /* XXX slow, probably wrong for -0 */
+       if (fabsl(x) >= 0.67434) {
+               if (x < 0) {
+                       x = -x;
+                       y = -y;
+               }
+               z = pio4 - x;
+               w = pio4lo - y;
+               x = z + w;
+               y = 0.0;
+               i = 1;
+       } else
+               i = 0;
+       z = x * x;
+       w = z * z;
+       r = T5 + w * (T9 + w * (T13 + w * (T17 + w * (T21 +
+           w * (T25 + w * (T29 + w * T33))))));
+       v = z * (T7 + w * (T11 + w * (T15 + w * (T19 + w * (T23 +
+           w * (T27 + w * T31))))));
+       s = z * x;
+       r = y + z * (s * (r + v) + y);
+       r += T3 * s;
+       w = x + r;
+       if (i == 1) {
+               v = (long double) iy;
+               return osign *
+                       (v - 2.0 * (x - (w * w / (w + v) - r)));
+       }
+       if (iy == 1)
+               return w;
+       else {
+               /*
+                * if allow error up to 2 ulp, simply return
+                * -1.0 / (x+r) here
+                */
+               /* compute -1.0 / (x+r) accurately */
+               long double a, t;
+               z = w;
+               z = z + 0x1p32 - 0x1p32;
+               v = r - (z - x);        /* z+v = r+x */
+               t = a = -1.0 / w;       /* a = -1.0/w */
+               t = t + 0x1p32 - 0x1p32;
+               s = 1.0 + t * z;
+               return t + a * (s + t * v);
+       }
+}
diff --git a/lib/libm/src/llrint.c b/lib/libm/src/llrint.c
deleted file mode 100644 (file)
index 426f203..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-/*
- * Written by Matthias Drochner <drochner@NetBSD.org>.
- * Public domain.
- *
- * $NetBSD: llrint.c,v 1.2 2004/10/13 15:18:32 drochner Exp $
- * $DragonFly: src/lib/libm/src/llrint.c,v 1.1 2005/07/26 21:15:20 joerg Exp $
- */
-
-#define LRINTNAME llrint
-#define RESTYPE long long int
-#define RESTYPE_MIN LLONG_MIN
-#define RESTYPE_MAX LLONG_MAX
-
-#include "lrint.c"
diff --git a/lib/libm/src/llrintf.c b/lib/libm/src/llrintf.c
deleted file mode 100644 (file)
index 6ecb638..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-/*
- * Written by Matthias Drochner <drochner@NetBSD.org>.
- * Public domain.
- *
- * $NetBSD: llrintf.c,v 1.2 2004/10/13 15:18:32 drochner Exp $
- * $DragonFly: src/lib/libm/src/llrintf.c,v 1.1 2005/07/26 21:15:20 joerg Exp $
- */
-
-#define LRINTNAME llrintf
-#define RESTYPE long long int
-#define RESTYPE_MIN LLONG_MIN
-#define RESTYPE_MAX LLONG_MAX
-
-#include "lrintf.c"
diff --git a/lib/libm/src/llround.c b/lib/libm/src/llround.c
deleted file mode 100644 (file)
index 119d688..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-/*
- * Written by Matthias Drochner <drochner@NetBSD.org>.
- * Public domain.
- *
- * $NetBSD: llround.c,v 1.2 2004/10/13 15:18:32 drochner Exp $
- * $DragonFly: src/lib/libm/src/llround.c,v 1.1 2005/07/26 21:15:20 joerg Exp $
- */
-
-#define LROUNDNAME llround
-#define RESTYPE long long int
-#define RESTYPE_MIN LLONG_MIN
-#define RESTYPE_MAX LLONG_MAX
-
-#include "lround.c"
diff --git a/lib/libm/src/llroundf.c b/lib/libm/src/llroundf.c
deleted file mode 100644 (file)
index ed70bfb..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-/*
- * Written by Matthias Drochner <drochner@NetBSD.org>.
- * Public domain.
- *
- * $NetBSD: llroundf.c,v 1.2 2004/10/13 15:18:32 drochner Exp $
- * $DragonFly: src/lib/libm/src/llroundf.c,v 1.1 2005/07/26 21:15:20 joerg Exp $
- */
-
-#define LROUNDNAME llroundf
-#define RESTYPE long long int
-#define RESTYPE_MIN LLONG_MIN
-#define RESTYPE_MAX LLONG_MAX
-
-#include "lroundf.c"
diff --git a/lib/libm/src/lrint.c b/lib/libm/src/lrint.c
deleted file mode 100644 (file)
index 9b81132..0000000
+++ /dev/null
@@ -1,92 +0,0 @@
-/* $NetBSD: lrint.c,v 1.4 2008/04/26 23:49:50 christos Exp $ */
-
-/*-
- * Copyright (c) 2004
- *     Matthias Drochner. 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 <math.h>
-#include <sys/ieee754.h>
-#include <machine/limits.h>
-#include "math_private.h"
-
-#ifndef LRINTNAME
-#define LRINTNAME lrint
-#define RESTYPE long int
-#define RESTYPE_MIN LONG_MIN
-#define RESTYPE_MAX LONG_MAX
-#endif
-
-#define RESTYPE_BITS (sizeof(RESTYPE) * 8)
-
-static const double
-TWO52[2]={
-  4.50359962737049600000e+15, /* 0x43300000, 0x00000000 */
- -4.50359962737049600000e+15, /* 0xC3300000, 0x00000000 */
-};
-
-RESTYPE
-LRINTNAME(double x)
-{
-       u_int32_t i0, i1;
-       int e, s, shift;
-       RESTYPE res;
-
-       GET_HIGH_WORD(i0, x);
-       e = i0 >> 20;
-       s = (uint32_t)e >> DBL_EXPBITS;
-       e = (e & 0x7ff) - DBL_EXP_BIAS;
-
-       /* 1.0 x 2^-1 is the smallest number which can be rounded to 1 */
-       if (e < -1)
-               return (0);
-       /* 1.0 x 2^31 (or 2^63) is already too large */
-       if (e >= (int)RESTYPE_BITS - 1)
-               return (s ? RESTYPE_MIN : RESTYPE_MAX); /* ??? unspecified */
-
-       /* >= 2^52 is already an exact integer */
-       if (e < DBL_FRACBITS) {
-               /* round, using current direction */
-               x += TWO52[s];
-               x -= TWO52[s];
-       }
-
-       EXTRACT_WORDS(i0, i1, x);
-       e = ((i0 >> 20) & 0x7ff) - DBL_EXP_BIAS;
-       i0 &= 0xfffff;
-       i0 |= (1 << 20);
-
-       shift = e - DBL_FRACBITS;
-       if (shift >=0)
-               res = (shift < 32 ? (RESTYPE)i1 << shift : 0);
-       else
-               res = (shift > -32 ? i1 >> -shift : 0);
-       shift += 32;
-       if (shift >=0)
-               res |= (shift < 32 ? (RESTYPE)i0 << shift : 0);
-       else
-               res |= (shift > -32 ? i0 >> -shift : 0);
-
-       return (s ? -res : res);
-}
diff --git a/lib/libm/src/lrintf.c b/lib/libm/src/lrintf.c
deleted file mode 100644 (file)
index 929854c..0000000
+++ /dev/null
@@ -1,91 +0,0 @@
-/* $NetBSD: lrintf.c,v 1.5 2008/04/26 23:49:50 christos Exp $ */
-
-/*-
- * Copyright (c) 2004
- *     Matthias Drochner. 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 <math.h>
-#include <sys/ieee754.h>
-#include <machine/limits.h>
-#include "math_private.h"
-
-#ifndef LRINTNAME
-#define LRINTNAME lrintf
-#define RESTYPE long int
-#define RESTYPE_MIN LONG_MIN
-#define RESTYPE_MAX LONG_MAX
-#endif
-
-#define RESTYPE_BITS (sizeof(RESTYPE) * 8)
-
-static const float
-TWO23[2]={
-  8.3886080000e+06, /* 0x4b000000 */
- -8.3886080000e+06, /* 0xcb000000 */
-};
-
-RESTYPE
-LRINTNAME(float x)
-{
-       u_int32_t i0;
-       int e, s, shift;
-       RESTYPE res;
-#ifdef __i386__ /* XXX gcc4 will omit the rounding otherwise */
-       volatile
-#endif
-               float w;
-
-       GET_FLOAT_WORD(i0, x);
-       e = i0 >> SNG_FRACBITS;
-       s = (uint32_t)e >> SNG_EXPBITS;
-       e = (e & 0xff) - SNG_EXP_BIAS;
-
-       /* 1.0 x 2^-1 is the smallest number which can be rounded to 1 */
-       if (e < -1)
-               return (0);
-       /* 1.0 x 2^31 (or 2^63) is already too large */
-       if (e >= (int)RESTYPE_BITS - 1)
-               return (s ? RESTYPE_MIN : RESTYPE_MAX); /* ??? unspecified */
-
-       /* >= 2^23 is already an exact integer */
-       if (e < SNG_FRACBITS) {
-               /* round, using current direction */
-               w = TWO23[s] + x;
-               x = w - TWO23[s];
-       }
-
-       GET_FLOAT_WORD(i0, x);
-       e = ((i0 >> SNG_FRACBITS) & 0xff) - SNG_EXP_BIAS;
-       i0 &= 0x7fffff;
-       i0 |= (1 << SNG_FRACBITS);
-
-       shift = e - SNG_FRACBITS;
-       if (shift >=0)
-               res = (shift < 32 ? (RESTYPE)i0 << shift : 0);
-       else
-               res = (shift > -32 ? i0 >> -shift : 0);
-
-       return (s ? -res : res);
-}
index f043078..d1ee45b 100644 (file)
@@ -38,7 +38,7 @@
  * big endian.
  */
 
-#if (BYTE_ORDER == BIG_ENDIAN) || (defined(__arm__) && !defined(__VFP_FP__))
+#if BYTE_ORDER == BIG_ENDIAN
 
 typedef union
 {
@@ -48,12 +48,15 @@ typedef union
     u_int32_t msw;
     u_int32_t lsw;
   } parts;
+  struct
+  {
+    u_int64_t w;
+  } xparts;
 } ieee_double_shape_type;
 
 #endif
 
-#if (BYTE_ORDER == LITTLE_ENDIAN) && \
-    !(defined(__arm__) && !defined(__VFP_FP__))
+#if BYTE_ORDER == LITTLE_ENDIAN
 
 typedef union
 {
@@ -63,6 +66,10 @@ typedef union
     u_int32_t lsw;
     u_int32_t msw;
   } parts;
+  struct
+  {
+    u_int64_t w;
+  } xparts;
 } ieee_double_shape_type;
 
 #endif
@@ -77,6 +84,17 @@ do {                                                         \
   (ix1) = ew_u.parts.lsw;                                      \
 } while (/*CONSTCOND*/0)
 
+/*
+ * Get a 64-bit int from a double.
+ * Origin: FreeBSD msun/src/math_private.h
+ */
+#define EXTRACT_WORD64(ix,d)                                   \
+do {                                                           \
+  ieee_double_shape_type ew_u;                                 \
+  ew_u.value = (d);                                            \
+  (ix) = ew_u.xparts.w;                                                \
+} while (0)
+
 /* Get the more significant 32 bit int from a double.  */
 
 #define GET_HIGH_WORD(i,d)                                     \
@@ -105,6 +123,17 @@ do {                                                               \
   (d) = iw_u.value;                                            \
 } while (/*CONSTCOND*/0)
 
+/*
+ * Set a double from a 64-bit int.
+ * Origin: FreeBSD msun/src/math_private.h
+ */
+#define INSERT_WORD64(d,ix)                                    \
+do {                                                           \
+  ieee_double_shape_type iw_u;                                 \
+  iw_u.xparts.w = (ix);                                                \
+  (d) = iw_u.value;                                            \
+} while (0)
+
 /* Set the more significant 32 bits of a double from an int.  */
 
 #define SET_HIGH_WORD(d,v)                                     \
@@ -153,6 +182,30 @@ do {                                                               \
 } while (/*CONSTCOND*/0)
 
 /*
+ * Get expsign as a 16 bit int from a long double.
+ * Origin: FreeBSD msun/src/math_private.h
+ */
+
+#define        GET_LDBL_EXPSIGN(i,d)                                   \
+do {                                                           \
+  union IEEEl2bits ge_u;                                       \
+  ge_u.e = (d);                                                        \
+  (i) = ge_u.xbits.expsign;                                    \
+} while (/*CONSTCOND*/0)
+
+/*
+ * Set expsign of a long double from a 16 bit int.
+ */
+
+#define        SET_LDBL_EXPSIGN(d,v)                                   \
+do {                                                           \
+  union IEEEl2bits se_u;                                       \
+  se_u.e = (d);                                                        \
+  se_u.xbits.expsign = (v);                                    \
+  (d) = se_u.e;                                                        \
+} while (/*CONSTCOND*/0)
+
+/*
  * Attempt to get strict C99 semantics for assignment with non-C99 compilers.
  */
 #if FLT_EVAL_METHOD == 0 || __GNUC__ == 0
@@ -244,24 +297,25 @@ cpackl(long double x, long double y)
 __BEGIN_DECLS
 #pragma GCC visibility push(hidden)
 
-/* ieee style elementary functions */
-int    __libm_rem_pio2(double, double*);
-
 /* fdlibm kernel function */
+int    __kernel_rem_pio2(double*,double*,int,int,int);
+
+/* double precision kernel functions */
+int    __libm_rem_pio2(double, double*);
 double __kernel_sin(double, double, int);
 double __kernel_cos(double, double);
 double __kernel_tan(double, double, int);
-int    __kernel_rem_pio2(double*, double*, int, int, int, const int*);
-
 
-/* ieee style elementary float functions */
-int    __libm_rem_pio2f(float,float*);
+/* float precision kernel functions */
+int    __libm_rem_pio2f(float,double*);
+float  __kernel_sindf(double);
+float  __kernel_cosdf(double);
+float  __kernel_tandf(double, int);
 
-/* float versions of fdlibm kernel functions */
-float  __kernel_sinf(float, float, int);
-float  __kernel_cosf(float, float);
-float  __kernel_tanf(float, float, int);
-int    __kernel_rem_pio2f(float*, float*, int, int, int, const int*);
+/* long double precision kernel functions */
+long double __kernel_sinl(long double, long double, int);
+long double __kernel_cosl(long double, long double);
+long double __kernel_tanl(long double, long double, int);
 
 #pragma GCC visibility pop
 __END_DECLS
diff --git a/lib/libm/src/mathimpl.h b/lib/libm/src/mathimpl.h
new file mode 100644 (file)
index 0000000..dc719cd
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 1988, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)mathimpl.h  8.1 (Berkeley) 6/4/93
+ * FreeBSD SVN: 152566 (2005-11-18)
+ */
+
+#ifndef _MATHIMPL_H_
+#define        _MATHIMPL_H_
+
+#include <math.h>
+
+#include "math_private.h"
+
+/*
+ * TRUNC() is a macro that sets the trailing 27 bits in the mantissa of an
+ * IEEE double variable to zero.  It must be expression-like for syntactic
+ * reasons, and we implement this expression using an inline function
+ * instead of a pure macro to avoid depending on the gcc feature of
+ * statement-expressions.
+ */
+#define        TRUNC(d)        (_b_trunc(&(d)))
+
+static __inline void
+_b_trunc(volatile double *_dp)
+{
+       uint32_t _lw;
+
+       GET_LOW_WORD(_lw, *_dp);
+       SET_LOW_WORD(*_dp, _lw & 0xf8000000);
+}
+
+struct Double {
+       double  a;
+       double  b;
+};
+
+/*
+ * Functions internal to the math package, yet not static.
+ */
+double __exp__D(double, double);
+struct Double __log__D(double);
+
+#endif /* !_MATHIMPL_H_ */
diff --git a/lib/libm/src/s_atanl.c b/lib/libm/src/s_atanl.c
new file mode 100644 (file)
index 0000000..a030c21
--- /dev/null
@@ -0,0 +1,82 @@
+/* @(#)s_atan.c 5.1 93/09/24 */
+/* FreeBSD: head/lib/msun/src/s_atan.c 176451 2008-02-22 02:30:36Z das */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/*
+ * See comments in s_atan.c.
+ * Converted to long double by David Schultz <das@FreeBSD.ORG>.
+ */
+
+#include <float.h>
+
+#include "invtrig.h"
+#include "math.h"
+#include "math_private.h"
+
+static const long double
+one   = 1.0,
+huge   = 1.0e300;
+
+long double
+atanl(long double x)
+{
+       union IEEEl2bits u;
+       long double w,s1,s2,z;
+       int id;
+       int16_t expsign, expt;
+       int32_t expman;
+
+       u.e = x;
+       expsign = u.xbits.expsign;
+       expt = expsign & 0x7fff;
+       if(expt >= ATAN_CONST) {        /* if |x| is large, atan(x)~=pi/2 */
+           if(expt == BIAS + LDBL_MAX_EXP &&
+              ((u.bits.manh&~LDBL_NBIT)|u.bits.manl)!=0)
+               return x+x;             /* NaN */
+           if(expsign>0) return  atanhi[3]+atanlo[3];
+           else     return -atanhi[3]-atanlo[3];
+       }
+       /* Extract the exponent and the first few bits of the mantissa. */
+       /* XXX There should be a more convenient way to do this. */
+       expman = (expt << 8) | ((u.bits.manh >> (MANH_SIZE - 9)) & 0xff);
+       if (expman < ((BIAS - 2) << 8) + 0xc0) {        /* |x| < 0.4375 */
+           if (expt < ATAN_LINEAR) {   /* if |x| is small, atanl(x)~=x */
+               if(huge+x>one) return x;        /* raise inexact */
+           }
+           id = -1;
+       } else {
+       x = fabsl(x);
+       if (expman < (BIAS << 8) + 0x30) {              /* |x| < 1.1875 */
+           if (expman < ((BIAS - 1) << 8) + 0x60) {    /* 7/16 <=|x|<11/16 */
+               id = 0; x = (2.0*x-one)/(2.0+x);
+           } else {                    /* 11/16<=|x|< 19/16 */
+               id = 1; x  = (x-one)/(x+one);
+           }
+       } else {
+           if (expman < ((BIAS + 1) << 8) + 0x38) {    /* |x| < 2.4375 */
+               id = 2; x  = (x-1.5)/(one+1.5*x);
+           } else {                    /* 2.4375 <= |x| < 2^ATAN_CONST */
+               id = 3; x  = -1.0/x;
+           }
+       }}
+    /* end of argument reduction */
+       z = x*x;
+       w = z*z;
+    /* break sum aT[i]z**(i+1) into odd and even poly */
+       s1 = z*T_even(w);
+       s2 = w*T_odd(w);
+       if (id<0) return x - x*(s1+s2);
+       else {
+           z = atanhi[id] - ((x*(s1+s2) - atanlo[id]) - x);
+           return (expsign<0)? -z:z;
+       }
+}
diff --git a/lib/libm/src/s_cbrtl.c b/lib/libm/src/s_cbrtl.c
new file mode 100644 (file)
index 0000000..c9ae65b
--- /dev/null
@@ -0,0 +1,142 @@
+/*-
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ * Copyright (c) 2009-2011, Bruce D. Evans, Steven G. Kargl, David Schultz.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ *
+ * The argument reduction and testing for exceptional cases was
+ * written by Steven G. Kargl with input from Bruce D. Evans
+ * and David A. Schultz.
+ *
+ * FreeBSD SVN: 219576 (2011-03-12)
+ */
+
+#include <float.h>
+#include <math.h>
+#include <ieeefp.h>
+
+#include "fpmath.h"
+#include "math_private.h"
+
+#define        BIAS    (LDBL_MAX_EXP - 1)
+
+static const unsigned
+    B1 = 709958130;    /* B1 = (127-127.0/3-0.03306235651)*2**23 */
+
+long double
+cbrtl(long double x)
+{
+       union IEEEl2bits u, v;
+       long double r, s, t, w;
+       double dr, dt, dx;
+       float ft, fx;
+       uint32_t hx;
+       uint16_t expsign;
+       int k;
+
+       u.e = x;
+       expsign = u.xbits.expsign;
+       k = expsign & 0x7fff;
+
+       /*
+        * If x = +-Inf, then cbrt(x) = +-Inf.
+        * If x = NaN, then cbrt(x) = NaN.
+        */
+       if (k == BIAS + LDBL_MAX_EXP)
+               return (x + x);
+
+#ifdef __i386__
+       fp_prec_t oprec;
+
+       oprec = fpgetprec();
+       if (oprec != FP_PE)
+               fpsetprec(FP_PE);
+#endif
+
+       if (k == 0) {
+               /* If x = +-0, then cbrt(x) = +-0. */
+               if ((u.bits.manh | u.bits.manl) == 0) {
+#ifdef __i386__
+                       if (oprec != FP_PE)
+                               fpsetprec(oprec);
+#endif
+                       return (x);
+               }
+               /* Adjust subnormal numbers. */
+               u.e *= 0x1.0p514;
+               k = u.bits.exp;
+               k -= BIAS + 514;
+       } else
+               k -= BIAS;
+       u.xbits.expsign = BIAS;
+       v.e = 1;
+
+       x = u.e;
+       switch (k % 3) {
+       case 1:
+       case -2:
+               x = 2*x;
+               k--;
+               break;
+       case 2:
+       case -1:
+               x = 4*x;
+               k -= 2;
+               break;
+       }
+       v.xbits.expsign = (expsign & 0x8000) | (BIAS + k / 3);
+
+       /*
+        * The following is the guts of s_cbrtf, with the handling of
+        * special values removed and extra care for accuracy not taken,
+        * but with most of the extra accuracy not discarded.
+        */
+
+       /* ~5-bit estimate: */
+       fx = x;
+       GET_FLOAT_WORD(hx, fx);
+       SET_FLOAT_WORD(ft, ((hx & 0x7fffffff) / 3 + B1));
+
+       /* ~16-bit estimate: */
+       dx = x;
+       dt = ft;
+       dr = dt * dt * dt;
+       dt = dt * (dx + dx + dr) / (dx + dr + dr);
+
+       /* ~47-bit estimate: */
+       dr = dt * dt * dt;
+       dt = dt * (dx + dx + dr) / (dx + dr + dr);
+
+       /*
+        * dt is cbrtl(x) to ~47 bits (after x has been reduced to 1 <= x < 8).
+        * Round it away from zero to 32 bits (32 so that t*t is exact, and
+        * away from zero for technical reasons).
+        */
+       volatile double vd2 = 0x1.0p32;
+       volatile double vd1 = 0x1.0p-31;
+       #define vd ((long double)vd2 + vd1)
+
+       t = dt + vd - 0x1.0p32;
+
+       /*
+        * Final step Newton iteration to 64 or 113 bits with
+        * error < 0.667 ulps
+        */
+       s=t*t;                          /* t*t is exact */
+       r=x/s;                          /* error <= 0.5 ulps; |r| < |t| */
+       w=t+t;                          /* t+t is exact */
+       r=(r-t)/(w+r);                  /* r-t is exact; w+r ~= 3*t */
+       t=t+t*r;                        /* error <= 0.5 + 0.5/3 + epsilon */
+
+       t *= v.e;
+#ifdef __i386__
+       if (oprec != FP_PE)
+               fpsetprec(oprec);
+#endif
+       return (t);
+}
diff --git a/lib/libm/src/s_ceill.c b/lib/libm/src/s_ceill.c
new file mode 100644 (file)
index 0000000..6838e12
--- /dev/null
@@ -0,0 +1,99 @@
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ *
+ * From: @(#)s_ceil.c 5.1 93/09/24
+ * FreeBSD SVN: 176280 (2008-02-14)
+ */
+
+/*
+ * ceill(x)
+ * Return x rounded toward -inf to integral value
+ * Method:
+ *     Bit twiddling.
+ * Exception:
+ *     Inexact flag raised if x not equal to ceill(x).
+ */
+
+#include <float.h>
+#include <math.h>
+#include <stdint.h>
+
+#include "fpmath.h"
+
+#ifdef LDBL_IMPLICIT_NBIT
+#define        MANH_SIZE       (LDBL_MANH_SIZE + 1)
+#define        INC_MANH(u, c)  do {                                    \
+       uint64_t o = u.bits.manh;                               \
+       u.bits.manh += (c);                                     \
+       if (u.bits.manh < o)                                    \
+               u.bits.exp++;                                   \
+} while (0)
+#else
+#define        MANH_SIZE       LDBL_MANH_SIZE
+#define        INC_MANH(u, c)  do {                                    \
+       uint64_t o = u.bits.manh;                               \
+       u.bits.manh += (c);                                     \
+       if (u.bits.manh < o) {                                  \
+               u.bits.exp++;                                   \
+               u.bits.manh |= 1llu << (LDBL_MANH_SIZE - 1);    \
+       }                                                       \
+} while (0)
+#endif
+
+static const long double huge = 1.0e300;
+
+long double
+ceill(long double x)
+{
+       union IEEEl2bits u = { .e = x };
+       int e = u.bits.exp - LDBL_MAX_EXP + 1;
+
+       if (e < MANH_SIZE - 1) {
+               if (e < 0) {                    /* raise inexact if x != 0 */
+                       if (huge + x > 0.0)
+                               if (u.bits.exp > 0 ||
+                                   (u.bits.manh | u.bits.manl) != 0)
+                                       u.e = u.bits.sign ? -0.0 : 1.0;
+               } else {
+                       uint64_t m = ((1llu << MANH_SIZE) - 1) >> (e + 1);
+                       if (((u.bits.manh & m) | u.bits.manl) == 0)
+                               return (x);     /* x is integral */
+                       if (!u.bits.sign) {
+#ifdef LDBL_IMPLICIT_NBIT
+                               if (e == 0)
+                                       u.bits.exp++;
+                               else
+#endif
+                               INC_MANH(u, 1llu << (MANH_SIZE - e - 1));
+                       }
+                       if (huge + x > 0.0) {   /* raise inexact flag */
+                               u.bits.manh &= ~m;
+                               u.bits.manl = 0;
+                       }
+               }
+       } else if (e < LDBL_MANT_DIG - 1) {
+               uint64_t m = (uint64_t)-1 >> (64 - LDBL_MANT_DIG + e + 1);
+               if ((u.bits.manl & m) == 0)
+                       return (x);     /* x is integral */
+               if (!u.bits.sign) {
+                       if (e == MANH_SIZE - 1)
+                               INC_MANH(u, 1);
+                       else {
+                               uint64_t o = u.bits.manl;
+                               u.bits.manl += 1llu << (LDBL_MANT_DIG - e - 1);
+                               if (u.bits.manl < o)    /* got a carry */
+                                       INC_MANH(u, 1);
+                       }
+               }
+               if (huge + x > 0.0)             /* raise inexact flag */
+                       u.bits.manl &= ~m;
+       }
+       return (u.e);
+}
index 8d39f84..a209a1e 100644 (file)
@@ -23,7 +23,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $FreeBSD$
+ * FreeBSD SVN: 129040 (2004-05-07)
  */
 
 #include <math.h>
index 7dc8e38..1c8e329 100644 (file)
@@ -1,5 +1,6 @@
 /* s_cosf.c -- float version of s_cos.c.
  * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ * Optimized by Bruce D. Evans.
  */
 
 /*
  * software is freely granted, provided that this notice
  * is preserved.
  * ====================================================
- *
- * $NetBSD: s_cosf.c,v 1.9 2007/08/20 16:01:39 drochner Exp $
+ * FreeBSD SVN: 176569 (2008-02-25)
  */
 
 #include <math.h>
+#define        INLINE_KERNEL_COSDF
+#define        INLINE_KERNEL_SINDF
+#define INLINE_REM_PIO2F
 #include "math_private.h"
+#include "e_rem_pio2f.c"
+#include "k_cosf.c"
+#include "k_sinf.c"
+
+/* Small multiples of pi/2 rounded to double precision. */
+static const double
+c1pio2 = 1*M_PI_2,                     /* 0x3FF921FB, 0x54442D18 */
+c2pio2 = 2*M_PI_2,                     /* 0x400921FB, 0x54442D18 */
+c3pio2 = 3*M_PI_2,                     /* 0x4012D97C, 0x7F3321D2 */
+c4pio2 = 4*M_PI_2;                     /* 0x401921FB, 0x54442D18 */
 
 float
 cosf(float x)
 {
-       float y[2],z=0.0;
-       int32_t n,ix;
+       double y;
+       int32_t n, hx, ix;
 
-       GET_FLOAT_WORD(ix,x);
+       GET_FLOAT_WORD(hx,x);
+       ix = hx & 0x7fffffff;
 
-    /* |x| ~< pi/4 */
-       ix &= 0x7fffffff;
-       if(ix <= 0x3f490fd8) return __kernel_cosf(x,z);
+       if(ix <= 0x3f490fda) {          /* |x| ~<= pi/4 */
+           if(ix<0x39800000)           /* |x| < 2**-12 */
+               if(((int)x)==0) return 1.0;     /* 1 with inexact if x != 0 */
+           return __kernel_cosdf(x);
+       }
+       if(ix<=0x407b53d1) {            /* |x| ~<= 5*pi/4 */
+           if(ix>0x4016cbe3)           /* |x|  ~> 3*pi/4 */
+               return -__kernel_cosdf(x + (hx > 0 ? -c2pio2 : c2pio2));
+           else {
+               if(hx>0)
+                   return __kernel_sindf(c1pio2 - x);
+               else
+                   return __kernel_sindf(x + c1pio2);
+           }
+       }
+       if(ix<=0x40e231d5) {            /* |x| ~<= 9*pi/4 */
+           if(ix>0x40afeddf)           /* |x|  ~> 7*pi/4 */
+               return __kernel_cosdf(x + (hx > 0 ? -c4pio2 : c4pio2));
+           else {
+               if(hx>0)
+                   return __kernel_sindf(x - c3pio2);
+               else
+                   return __kernel_sindf(-c3pio2 - x);
+           }
+       }
 
     /* cos(Inf or NaN) is NaN */
        else if (ix>=0x7f800000) return x-x;
 
-    /* argument reduction needed */
+    /* general argument reduction needed */
        else {
-           n = __libm_rem_pio2f(x,y);
+           n = __libm_rem_pio2f(x,&y);
            switch(n&3) {
-               case 0: return  __kernel_cosf(y[0],y[1]);
-               case 1: return -__kernel_sinf(y[0],y[1],1);
-               case 2: return -__kernel_cosf(y[0],y[1]);
+               case 0: return  __kernel_cosdf(y);
+               case 1: return  __kernel_sindf(-y);
+               case 2: return -__kernel_cosdf(y);
                default:
-                       return  __kernel_sinf(y[0],y[1],1);
+                       return  __kernel_sindf(y);
            }
        }
 }
similarity index 57%
copy from lib/libm/src/s_roundf.c
copy to lib/libm/src/s_cosl.c
index 734a8d8..345feb1 100644 (file)
@@ -1,5 +1,5 @@
 /*-
- * Copyright (c) 2003, Steven G. Kargl
+ * Copyright (c) 2007 Steven G. Kargl
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
- * $NetBSD: s_roundf.c,v 1.2 2007/08/21 20:10:27 drochner Exp $
+ * FreeBSD SVN: 222508 (2011-05-30)
+ */
+
+/*
+ * Limited testing on pseudorandom numbers drawn within [-2e8:4e8] shows
+ * an accuracy of <= 0.7412 ULP.
  */
 
 #include <math.h>
+#include "math_private.h"
+#include "e_rem_pio2l.h"
 
-float
-roundf(float x)
+long double
+cosl(long double x)
 {
-       float t;
-       int i;
-
-       i = fpclassify(x);
-       if (i == FP_INFINITE || i == FP_NAN)
-               return (x);
-
-       if (x >= 0.0) {
-               t = floorf(x);
-               if (x - t >= 0.5)
-                       t += 1.0;
-               return (t);
-       } else {
-               x = -x;
-               t = floorf(x);
-               if (x - t >= 0.5)
-                       t += 1.0;
-               return (-t);
+       union IEEEl2bits z;
+       int e0;
+       long double y[2];
+       long double hi, lo;
+
+       z.e = x;
+       z.bits.sign = 0;
+
+       /* If x = +-0 or x is a subnormal number, then cos(x) = 1 */
+       if (z.bits.exp == 0)
+               return (1.0);
+
+       /* If x = NaN or Inf, then cos(x) = NaN. */
+       if (z.bits.exp == 32767)
+               return ((x - x) / (x - x));
+
+       /* Optimize the case where x is already within range. */
+       if (z.e < M_PI_4)
+               return (__kernel_cosl(z.e, 0));
+
+       e0 = __libm_rem_pio2l(x, y);
+       hi = y[0];
+       lo = y[1];
+
+       switch (e0 & 3) {
+       case 0:
+           hi = __kernel_cosl(hi, lo);
+           break;
+       case 1:
+           hi = - __kernel_sinl(hi, lo, 1);
+           break;
+       case 2:
+           hi = - __kernel_cosl(hi, lo);
+           break;
+       case 3:
+           hi = __kernel_sinl(hi, lo, 1);
+           break;
        }
+
+       return (hi);
 }
index c35d2ba..833e44f 100644 (file)
@@ -351,7 +351,7 @@ exp2(double x)
                        GET_LOW_WORD(lx,x);
                        if(((ix & 0xfffff) | lx) != 0 || (hx & 0x80000000) == 0)
                                return (x + x); /* x is NaN or +Inf */
-                       else 
+                       else
                                return (0.0);   /* x is -Inf */
                }
                if(x >= 0x1.0p10)
index 761559d..ab3e3c1 100644 (file)
@@ -62,7 +62,7 @@ static const double exp2ft[TBLSIZE] = {
        0x1.4bfdad5362a27p+0,
        0x1.5ab07dd485429p+0,
 };
-       
+
 /*
  * exp2f(x): compute the base 2 exponential of x
  *
@@ -104,7 +104,7 @@ exp2f(float x)
                if(ix >= 0x7f800000) {
                        if ((ix & 0x7fffff) != 0 || (hx & 0x80000000) == 0)
                                return (x + x); /* x is NaN or +Inf */
-                       else 
+                       else
                                return (0.0);   /* x is -Inf */
                }
                if(x >= 0x1.0p7f)
diff --git a/lib/libm/src/s_exp2l.c b/lib/libm/src/s_exp2l.c
new file mode 100644 (file)
index 0000000..4abf91b
--- /dev/null
@@ -0,0 +1,293 @@
+/*-
+ * Copyright (c) 2005-2008 David Schultz <das@FreeBSD.ORG>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * FreeBSD SVN: 176231 (2008-02-13)
+ */
+
+#include <math.h>
+#include <float.h>
+#include <stdint.h>
+
+#ifdef __i386__
+#include <ieeefp.h>
+#endif
+
+#include "fpmath.h"
+
+#define        TBLBITS 7
+#define        TBLSIZE (1 << TBLBITS)
+
+#define        BIAS    (LDBL_MAX_EXP - 1)
+#define        EXPMASK (BIAS + LDBL_MAX_EXP)
+
+static const long double huge = 0x1p10000L;
+#if 0 /* XXX Prevent gcc from erroneously constant folding this. */
+static const long double twom10000 = 0x1p-10000L;
+#else
+static volatile long double twom10000 = 0x1p-10000L;
+#endif
+
+static const double
+    redux     = 0x1.8p63 / TBLSIZE,
+    P1        = 0x1.62e42fefa39efp-1,
+    P2        = 0x1.ebfbdff82c58fp-3,
+    P3        = 0x1.c6b08d7049fap-5,
+    P4        = 0x1.3b2ab6fba4da5p-7,
+    P5        = 0x1.5d8804780a736p-10,
+    P6        = 0x1.430918835e33dp-13;
+
+static const double tbl[TBLSIZE * 2] = {
+       0x1.6a09e667f3bcdp-1,   -0x1.bdd3413b2648p-55,
+       0x1.6c012750bdabfp-1,   -0x1.2895667ff0cp-57,
+       0x1.6dfb23c651a2fp-1,   -0x1.bbe3a683c88p-58,
+       0x1.6ff7df9519484p-1,   -0x1.83c0f25860fp-56,
+       0x1.71f75e8ec5f74p-1,   -0x1.16e4786887bp-56,
+       0x1.73f9a48a58174p-1,   -0x1.0a8d96c65d5p-55,
+       0x1.75feb564267c9p-1,   -0x1.0245957316ep-55,
+       0x1.780694fde5d3fp-1,    0x1.866b80a0216p-55,
+       0x1.7a11473eb0187p-1,   -0x1.41577ee0499p-56,
+       0x1.7c1ed0130c132p-1,    0x1.f124cd1164ep-55,
+       0x1.7e2f336cf4e62p-1,    0x1.05d02ba157ap-57,
+       0x1.80427543e1a12p-1,   -0x1.27c86626d97p-55,
+       0x1.82589994cce13p-1,   -0x1.d4c1dd41533p-55,
+       0x1.8471a4623c7adp-1,   -0x1.8d684a341cep-56,
+       0x1.868d99b4492edp-1,   -0x1.fc6f89bd4f68p-55,
+       0x1.88ac7d98a6699p-1,    0x1.994c2f37cb5p-55,
+       0x1.8ace5422aa0dbp-1,    0x1.6e9f156864bp-55,
+       0x1.8cf3216b5448cp-1,   -0x1.0d55e32e9e4p-57,
+       0x1.8f1ae99157736p-1,    0x1.5cc13a2e397p-56,
+       0x1.9145b0b91ffc6p-1,   -0x1.dd6792e5825p-55,
+       0x1.93737b0cdc5e5p-1,   -0x1.75fc781b58p-58,
+       0x1.95a44cbc8520fp-1,   -0x1.64b7c96a5fp-57,
+       0x1.97d829fde4e5p-1,    -0x1.d185b7c1b86p-55,
+       0x1.9a0f170ca07bap-1,   -0x1.173bd91cee6p-55,
+       0x1.9c49182a3f09p-1,     0x1.c7c46b071f2p-57,
+       0x1.9e86319e32323p-1,    0x1.824ca78e64cp-57,
+       0x1.a0c667b5de565p-1,   -0x1.359495d1cd5p-55,
+       0x1.a309bec4a2d33p-1,    0x1.6305c7ddc368p-55,
+       0x1.a5503b23e255dp-1,   -0x1.d2f6edb8d42p-55,
+       0x1.a799e1330b358p-1,    0x1.bcb7ecac564p-55,
+       0x1.a9e6b5579fdbfp-1,    0x1.0fac90ef7fdp-55,
+       0x1.ac36bbfd3f37ap-1,   -0x1.f9234cae76dp-56,
+       0x1.ae89f995ad3adp-1,    0x1.7a1cd345dcc8p-55,
+       0x1.b0e07298db666p-1,   -0x1.bdef54c80e4p-55,
+       0x1.b33a2b84f15fbp-1,   -0x1.2805e3084d8p-58,
+       0x1.b59728de5593ap-1,   -0x1.c71dfbbba6ep-55,
+       0x1.b7f76f2fb5e47p-1,   -0x1.5584f7e54acp-57,
+       0x1.ba5b030a1064ap-1,   -0x1.efcd30e5429p-55,
+       0x1.bcc1e904bc1d2p-1,    0x1.23dd07a2d9fp-56,
+       0x1.bf2c25bd71e09p-1,   -0x1.efdca3f6b9c8p-55,
+       0x1.c199bdd85529cp-1,    0x1.11065895049p-56,
+       0x1.c40ab5fffd07ap-1,    0x1.b4537e083c6p-55,
+       0x1.c67f12e57d14bp-1,    0x1.2884dff483c8p-55,
+       0x1.c8f6d9406e7b5p-1,    0x1.1acbc48805cp-57,
+       0x1.cb720dcef9069p-1,    0x1.503cbd1e94ap-57,
+       0x1.cdf0b555dc3fap-1,   -0x1.dd83b53829dp-56,
+       0x1.d072d4a07897cp-1,   -0x1.cbc3743797a8p-55,
+       0x1.d2f87080d89f2p-1,   -0x1.d487b719d858p-55,
+       0x1.d5818dcfba487p-1,    0x1.2ed02d75b37p-56,
+       0x1.d80e316c98398p-1,   -0x1.11ec18bedep-55,
+       0x1.da9e603db3285p-1,    0x1.c2300696db5p-55,
+       0x1.dd321f301b46p-1,     0x1.2da5778f019p-55,
+       0x1.dfc97337b9b5fp-1,   -0x1.1a5cd4f184b8p-55,
+       0x1.e264614f5a129p-1,   -0x1.7b627817a148p-55,
+       0x1.e502ee78b3ff6p-1,    0x1.39e8980a9cdp-56,
+       0x1.e7a51fbc74c83p-1,    0x1.2d522ca0c8ep-55,
+       0x1.ea4afa2a490dap-1,   -0x1.e9c23179c288p-55,
+       0x1.ecf482d8e67f1p-1,   -0x1.c93f3b411ad8p-55,
+       0x1.efa1bee615a27p-1,    0x1.dc7f486a4b68p-55,
+       0x1.f252b376bba97p-1,    0x1.3a1a5bf0d8e8p-55,
+       0x1.f50765b6e454p-1,     0x1.9d3e12dd8a18p-55,
+       0x1.f7bfdad9cbe14p-1,   -0x1.dbb12d00635p-55,
+       0x1.fa7c1819e90d8p-1,    0x1.74853f3a593p-56,
+       0x1.fd3c22b8f71f1p-1,    0x1.2eb74966578p-58,
+       0x1p+0,  0x0p+0,
+       0x1.0163da9fb3335p+0,    0x1.b61299ab8cd8p-54,
+       0x1.02c9a3e778061p+0,   -0x1.19083535b08p-56,
+       0x1.04315e86e7f85p+0,   -0x1.0a31c1977c98p-54,
+       0x1.059b0d3158574p+0,    0x1.d73e2a475b4p-55,
+       0x1.0706b29ddf6dep+0,   -0x1.c91dfe2b13cp-55,
+       0x1.0874518759bc8p+0,    0x1.186be4bb284p-57,
+       0x1.09e3ecac6f383p+0,    0x1.14878183161p-54,
+       0x1.0b5586cf9890fp+0,    0x1.8a62e4adc61p-54,
+       0x1.0cc922b7247f7p+0,    0x1.01edc16e24f8p-54,
+       0x1.0e3ec32d3d1a2p+0,    0x1.03a1727c58p-59,
+       0x1.0fb66affed31bp+0,   -0x1.b9bedc44ebcp-57,
+       0x1.11301d0125b51p+0,   -0x1.6c51039449bp-54,
+       0x1.12abdc06c31ccp+0,   -0x1.1b514b36ca8p-58,
+       0x1.1429aaea92dep+0,    -0x1.32fbf9af1368p-54,
+       0x1.15a98c8a58e51p+0,    0x1.2406ab9eeabp-55,
+       0x1.172b83c7d517bp+0,   -0x1.19041b9d78ap-55,
+       0x1.18af9388c8deap+0,   -0x1.11023d1970f8p-54,
+       0x1.1a35beb6fcb75p+0,    0x1.e5b4c7b4969p-55,
+       0x1.1bbe084045cd4p+0,   -0x1.95386352ef6p-54,
+       0x1.1d4873168b9aap+0,    0x1.e016e00a264p-54,
+       0x1.1ed5022fcd91dp+0,   -0x1.1df98027bb78p-54,
+       0x1.2063b88628cd6p+0,    0x1.dc775814a85p-55,
+       0x1.21f49917ddc96p+0,    0x1.2a97e9494a6p-55,
+       0x1.2387a6e756238p+0,    0x1.9b07eb6c7058p-54,
+       0x1.251ce4fb2a63fp+0,    0x1.ac155bef4f5p-55,
+       0x1.26b4565e27cddp+0,    0x1.2bd339940eap-55,
+       0x1.284dfe1f56381p+0,   -0x1.a4c3a8c3f0d8p-54,
+       0x1.29e9df51fdee1p+0,    0x1.612e8afad12p-55,
+       0x1.2b87fd0dad99p+0,    -0x1.10adcd6382p-59,
+       0x1.2d285a6e4030bp+0,    0x1.0024754db42p-54,
+       0x1.2ecafa93e2f56p+0,    0x1.1ca0f45d524p-56,
+       0x1.306fe0a31b715p+0,    0x1.6f46ad23183p-55,
+       0x1.32170fc4cd831p+0,    0x1.a9ce78e1804p-55,
+       0x1.33c08b26416ffp+0,    0x1.327218436598p-54,
+       0x1.356c55f929ff1p+0,   -0x1.b5cee5c4e46p-55,
+       0x1.371a7373aa9cbp+0,   -0x1.63aeabf42ebp-54,
+       0x1.38cae6d05d866p+0,   -0x1.e958d3c99048p-54,
+       0x1.3a7db34e59ff7p+0,   -0x1.5e436d661f6p-56,
+       0x1.3c32dc313a8e5p+0,   -0x1.efff8375d2ap-54,
+       0x1.3dea64c123422p+0,    0x1.ada0911f09fp-55,
+       0x1.3fa4504ac801cp+0,   -0x1.7d023f956fap-54,
+       0x1.4160a21f72e2ap+0,   -0x1.ef3691c309p-58,
+       0x1.431f5d950a897p+0,   -0x1.1c7dde35f7ap-55,
+       0x1.44e086061892dp+0,    0x1.89b7a04ef8p-59,
+       0x1.46a41ed1d0057p+0,    0x1.c944bd1648a8p-54,
+       0x1.486a2b5c13cdp+0,     0x1.3c1a3b69062p-56,
+       0x1.4a32af0d7d3dep+0,    0x1.9cb62f3d1be8p-54,
+       0x1.4bfdad5362a27p+0,    0x1.d4397afec42p-56,
+       0x1.4dcb299fddd0dp+0,    0x1.8ecdbbc6a78p-54,
+       0x1.4f9b2769d2ca7p+0,   -0x1.4b309d25958p-54,
+       0x1.516daa2cf6642p+0,   -0x1.f768569bd94p-55,
+       0x1.5342b569d4f82p+0,   -0x1.07abe1db13dp-55,
+       0x1.551a4ca5d920fp+0,   -0x1.d689cefede6p-55,
+       0x1.56f4736b527dap+0,    0x1.9bb2c011d938p-54,
+       0x1.58d12d497c7fdp+0,    0x1.295e15b9a1ep-55,
+       0x1.5ab07dd485429p+0,    0x1.6324c0546478p-54,
+       0x1.5c9268a5946b7p+0,    0x1.c4b1b81698p-60,
+       0x1.5e76f15ad2148p+0,    0x1.ba6f93080e68p-54,
+       0x1.605e1b976dc09p+0,   -0x1.3e2429b56de8p-54,
+       0x1.6247eb03a5585p+0,   -0x1.383c17e40b48p-54,
+       0x1.6434634ccc32p+0,    -0x1.c483c759d89p-55,
+       0x1.6623882552225p+0,   -0x1.bb60987591cp-54,
+       0x1.68155d44ca973p+0,    0x1.038ae44f74p-57,
+};
+
+/*
+ * exp2l(x): compute the base 2 exponential of x
+ *
+ * Accuracy: Peak error < 0.511 ulp.
+ *
+ * Method: (equally-spaced tables)
+ *
+ *   Reduce x:
+ *     x = 2**k + y, for integer k and |y| <= 1/2.
+ *     Thus we have exp2l(x) = 2**k * exp2(y).
+ *
+ *   Reduce y:
+ *     y = i/TBLSIZE + z for integer i near y * TBLSIZE.
+ *     Thus we have exp2(y) = exp2(i/TBLSIZE) * exp2(z),
+ *     with |z| <= 2**-(TBLBITS+1).
+ *
+ *   We compute exp2(i/TBLSIZE) via table lookup and exp2(z) via a
+ *   degree-6 minimax polynomial with maximum error under 2**-69.
+ *   The table entries each have 104 bits of accuracy, encoded as
+ *   a pair of double precision values.
+ */
+long double
+exp2l(long double x)
+{
+       union IEEEl2bits u, v;
+       long double r, twopk, twopkp10000, z;
+       uint32_t hx, ix, i0;
+       int k;
+
+       /* Filter out exceptional cases. */
+       u.e = x;
+       hx = u.xbits.expsign;
+       ix = hx & EXPMASK;
+       if (ix >= BIAS + 14) {          /* |x| >= 16384 or x is NaN */
+               if (ix == BIAS + LDBL_MAX_EXP) {
+                       if (u.xbits.man != 1ULL << 63 || (hx & 0x8000) == 0)
+                               return (x + x); /* x is +Inf or NaN */
+                       else
+                               return (0.0);   /* x is -Inf */
+               }
+               if (x >= 16384)
+                       return (huge * huge);   /* overflow */
+               if (x <= -16446)
+                       return (twom10000 * twom10000); /* underflow */
+       } else if (ix <= BIAS - 66) {           /* |x| < 0x1p-66 */
+               return (1.0 + x);
+       }
+
+#ifdef __i386__
+       /*
+        * The default precision on i386 is 53 bits, so long doubles are
+        * broken. Call exp2() to get an accurate (double precision) result.
+        */
+       if (fpgetprec() != FP_PE)
+               return (exp2(x));
+#endif
+
+       /*
+        * Reduce x, computing z, i0, and k. The low bits of x + redux
+        * contain the 16-bit integer part of the exponent (k) followed by
+        * TBLBITS fractional bits (i0). We use bit tricks to extract these
+        * as integers, then set z to the remainder.
+        *
+        * Example: Suppose x is 0xabc.123456p0 and TBLBITS is 8.
+        * Then the low-order word of x + redux is 0x000abc12,
+        * We split this into k = 0xabc and i0 = 0x12 (adjusted to
+        * index into the table), then we compute z = 0x0.003456p0.
+        *
+        * XXX If the exponent is negative, the computation of k depends on
+        *     '>>' doing sign extension.
+        */
+       u.e = x + redux;
+       i0 = u.bits.manl + TBLSIZE / 2;
+       k = (int)i0 >> TBLBITS;
+       i0 = (i0 & (TBLSIZE - 1)) << 1;
+       u.e -= redux;
+       z = x - u.e;
+       v.xbits.man = 1ULL << 63;
+       if (k >= LDBL_MIN_EXP) {
+               v.xbits.expsign = LDBL_MAX_EXP - 1 + k;
+               twopk = v.e;
+       } else {
+               v.xbits.expsign = LDBL_MAX_EXP - 1 + k + 10000;
+               twopkp10000 = v.e;
+       }
+
+       /* Compute r = exp2l(y) = exp2lt[i0] * p(z). */
+       long double t_hi = tbl[i0];
+       long double t_lo = tbl[i0 + 1];
+       /* XXX This gives > 1 ulp errors outside of FE_TONEAREST mode */
+       r = t_lo + (t_hi + t_lo) * z * (P1 + z * (P2 + z * (P3 + z * (P4
+           + z * (P5 + z * P6))))) + t_hi;
+
+       /* Scale by 2**k. */
+       if (k >= LDBL_MIN_EXP) {
+               if (k == LDBL_MAX_EXP)
+                       return (r * 2.0 * 0x1p16383L);
+               return (r * twopk);
+       } else {
+               return (r * twopkp10000 * twom10000);
+       }
+}
similarity index 52%
rename from lib/libm/src/s_ldexpf.c
rename to lib/libm/src/s_fabs.c
index 4a2c9f9..4d54bb2 100644 (file)
@@ -1,7 +1,4 @@
-/* s_ldexp0f.c -- float version of s_ldexp0.c.
- * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
- */
-
+/* @(#)s_fabs.c 5.1 93/09/24 */
 /*
  * ====================================================
  * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
  * is preserved.
  * ====================================================
  *
- * $NetBSD: s_ldexpf.c,v 1.8 2010/04/23 19:17:07 drochner Exp $
+ * FreeBSD SVN: 97413 (2002-05-28)
+ */
+
+/*
+ * fabs(x) returns the absolute value of x.
  */
 
 #include <math.h>
 #include "math_private.h"
-#include <errno.h>
 
-float
-ldexpf(float value, int exp0)
+double
+fabs(double x)
 {
-       if(!finitef(value)||value==(float)0.0) return value;
-       value = scalbnf(value,exp0);
-       if(!finitef(value)||value==(float)0.0) errno = ERANGE;
-       return value;
+       u_int32_t high;
+       GET_HIGH_WORD(high,x);
+       SET_HIGH_WORD(x,high&0x7fffffff);
+        return x;
 }
diff --git a/lib/libm/src/s_floorl.c b/lib/libm/src/s_floorl.c
new file mode 100644 (file)
index 0000000..c9fd28b
--- /dev/null
@@ -0,0 +1,99 @@
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ *
+ * From: @(#)s_floor.c 5.1 93/09/24
+ * FreeBSD SVN: 176280 (2008-02-14)
+ */
+
+/*
+ * floorl(x)
+ * Return x rounded toward -inf to integral value
+ * Method:
+ *     Bit twiddling.
+ * Exception:
+ *     Inexact flag raised if x not equal to floorl(x).
+ */
+
+#include <float.h>
+#include <math.h>
+#include <stdint.h>
+
+#include "fpmath.h"
+
+#ifdef LDBL_IMPLICIT_NBIT
+#define        MANH_SIZE       (LDBL_MANH_SIZE + 1)
+#define        INC_MANH(u, c)  do {                                    \
+       uint64_t o = u.bits.manh;                               \
+       u.bits.manh += (c);                                     \
+       if (u.bits.manh < o)                                    \
+               u.bits.exp++;                                   \
+} while (0)
+#else
+#define        MANH_SIZE       LDBL_MANH_SIZE
+#define        INC_MANH(u, c)  do {                                    \
+       uint64_t o = u.bits.manh;                               \
+       u.bits.manh += (c);                                     \
+       if (u.bits.manh < o) {                                  \
+               u.bits.exp++;                                   \
+               u.bits.manh |= 1llu << (LDBL_MANH_SIZE - 1);    \
+       }                                                       \
+} while (0)
+#endif
+
+static const long double huge = 1.0e300;
+
+long double
+floorl(long double x)
+{
+       union IEEEl2bits u = { .e = x };
+       int e = u.bits.exp - LDBL_MAX_EXP + 1;
+
+       if (e < MANH_SIZE - 1) {
+               if (e < 0) {                    /* raise inexact if x != 0 */
+                       if (huge + x > 0.0)
+                               if (u.bits.exp > 0 ||
+                                   (u.bits.manh | u.bits.manl) != 0)
+                                       u.e = u.bits.sign ? -1.0 : 0.0;
+               } else {
+                       uint64_t m = ((1llu << MANH_SIZE) - 1) >> (e + 1);
+                       if (((u.bits.manh & m) | u.bits.manl) == 0)
+                               return (x);     /* x is integral */
+                       if (u.bits.sign) {
+#ifdef LDBL_IMPLICIT_NBIT
+                               if (e == 0)
+                                       u.bits.exp++;
+                               else
+#endif
+                               INC_MANH(u, 1llu << (MANH_SIZE - e - 1));
+                       }
+                       if (huge + x > 0.0) {   /* raise inexact flag */
+                               u.bits.manh &= ~m;
+                               u.bits.manl = 0;
+                       }
+               }
+       } else if (e < LDBL_MANT_DIG - 1) {
+               uint64_t m = (uint64_t)-1 >> (64 - LDBL_MANT_DIG + e + 1);
+               if ((u.bits.manl & m) == 0)
+                       return (x);     /* x is integral */
+               if (u.bits.sign) {
+                       if (e == MANH_SIZE - 1)
+                               INC_MANH(u, 1);
+                       else {
+                               uint64_t o = u.bits.manl;
+                               u.bits.manl += 1llu << (LDBL_MANT_DIG - e - 1);
+                               if (u.bits.manl < o)    /* got a carry */
+                                       INC_MANH(u, 1);
+                       }
+               }
+               if (huge + x > 0.0)             /* raise inexact flag */
+                       u.bits.manl &= ~m;
+       }
+       return (u.e);
+}
diff --git a/lib/libm/src/s_fma.c b/lib/libm/src/s_fma.c
new file mode 100644 (file)
index 0000000..043b9b3
--- /dev/null
@@ -0,0 +1,283 @@
+/*-
+ * Copyright (c) 2005-2011 David Schultz <das@FreeBSD.ORG>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * FreeBSD SVN: 226601 (2011-10-21)
+ */
+
+#include <fenv.h>
+#include <float.h>
+#include <math.h>
+
+#include "math_private.h"
+
+/*
+ * A struct dd represents a floating-point number with twice the precision
+ * of a double.  We maintain the invariant that "hi" stores the 53 high-order
+ * bits of the result.
+ */
+struct dd {
+       double hi;
+       double lo;
+};
+
+/*
+ * Compute a+b exactly, returning the exact result in a struct dd.  We assume
+ * that both a and b are finite, but make no assumptions about their relative
+ * magnitudes.
+ */
+static inline struct dd
+dd_add(double a, double b)
+{
+       struct dd ret;
+       double s;
+
+       ret.hi = a + b;
+       s = ret.hi - a;
+       ret.lo = (a - (ret.hi - s)) + (b - s);
+       return (ret);
+}
+
+/*
+ * Compute a+b, with a small tweak:  The least significant bit of the
+ * result is adjusted into a sticky bit summarizing all the bits that
+ * were lost to rounding.  This adjustment negates the effects of double
+ * rounding when the result is added to another number with a higher
+ * exponent.  For an explanation of round and sticky bits, see any reference
+ * on FPU design, e.g.,
+ *
+ *     J. Coonen.  An Implementation Guide to a Proposed Standard for
+ *     Floating-Point Arithmetic.  Computer, vol. 13, no. 1, Jan 1980.
+ */
+static inline double
+add_adjusted(double a, double b)
+{
+       struct dd sum;
+       uint64_t hibits, lobits;
+
+       sum = dd_add(a, b);
+       if (sum.lo != 0) {
+               EXTRACT_WORD64(hibits, sum.hi);
+               if ((hibits & 1) == 0) {
+                       /* hibits += (int)copysign(1.0, sum.hi * sum.lo) */
+                       EXTRACT_WORD64(lobits, sum.lo);
+                       hibits += 1 - ((hibits ^ lobits) >> 62);
+                       INSERT_WORD64(sum.hi, hibits);
+               }
+       }
+       return (sum.hi);
+}
+
+/*
+ * Compute ldexp(a+b, scale) with a single rounding error. It is assumed
+ * that the result will be subnormal, and care is taken to ensure that
+ * double rounding does not occur.
+ */
+static inline double
+add_and_denormalize(double a, double b, int scale)
+{
+       struct dd sum;
+       uint64_t hibits, lobits;
+       int bits_lost;
+
+       sum = dd_add(a, b);
+
+       /*
+        * If we are losing at least two bits of accuracy to denormalization,
+        * then the first lost bit becomes a round bit, and we adjust the
+        * lowest bit of sum.hi to make it a sticky bit summarizing all the
+        * bits in sum.lo. With the sticky bit adjusted, the hardware will
+        * break any ties in the correct direction.
+        *
+        * If we are losing only one bit to denormalization, however, we must
+        * break the ties manually.
+        */
+       if (sum.lo != 0) {
+               EXTRACT_WORD64(hibits, sum.hi);
+               bits_lost = -((int)(hibits >> 52) & 0x7ff) - scale + 1;
+               if ((bits_lost != 1) ^ (int)(hibits & 1)) {
+                       /* hibits += (int)copysign(1.0, sum.hi * sum.lo) */
+                       EXTRACT_WORD64(lobits, sum.lo);
+                       hibits += 1 - (((hibits ^ lobits) >> 62) & 2);
+                       INSERT_WORD64(sum.hi, hibits);
+               }
+       }
+       return (ldexp(sum.hi, scale));
+}
+
+/*
+ * Compute a*b exactly, returning the exact result in a struct dd.  We assume
+ * that both a and b are normalized, so no underflow or overflow will occur.
+ * The current rounding mode must be round-to-nearest.
+ */
+static inline struct dd
+dd_mul(double a, double b)
+{
+       static const double split = 0x1p27 + 1.0;
+       struct dd ret;
+       double ha, hb, la, lb, p, q;
+
+       p = a * split;
+       ha = a - p;
+       ha += p;
+       la = a - ha;
+
+       p = b * split;
+       hb = b - p;
+       hb += p;
+       lb = b - hb;
+
+       p = ha * hb;
+       q = ha * lb + la * hb;
+
+       ret.hi = p + q;
+       ret.lo = p - ret.hi + q + la * lb;
+       return (ret);
+}
+
+/*
+ * Fused multiply-add: Compute x * y + z with a single rounding error.
+ *
+ * We use scaling to avoid overflow/underflow, along with the
+ * canonical precision-doubling technique adapted from:
+ *
+ *     Dekker, T.  A Floating-Point Technique for Extending the
+ *     Available Precision.  Numer. Math. 18, 224-242 (1971).
+ *
+ * This algorithm is sensitive to the rounding precision.  FPUs such
+ * as the i387 must be set in double-precision mode if variables are
+ * to be stored in FP registers in order to avoid incorrect results.
+ * This is the default on FreeBSD, but not on many other systems.
+ *
+ * Hardware instructions should be used on architectures that support it,
+ * since this implementation will likely be several times slower.
+ */
+double
+fma(double x, double y, double z)
+{
+       double xs, ys, zs, adj;
+       struct dd xy, r;
+       int oround;
+       int ex, ey, ez;
+       int spread;
+
+       /*
+        * Handle special cases. The order of operations and the particular
+        * return values here are crucial in handling special cases involving
+        * infinities, NaNs, overflows, and signed zeroes correctly.
+        */
+       if (x == 0.0 || y == 0.0)
+               return (x * y + z);
+       if (z == 0.0)
+               return (x * y);
+       if (!isfinite(x) || !isfinite(y))
+               return (x * y + z);
+       if (!isfinite(z))
+               return (z);
+
+       xs = frexp(x, &ex);
+       ys = frexp(y, &ey);
+       zs = frexp(z, &ez);
+       oround = fegetround();
+       spread = ex + ey - ez;
+
+       /*
+        * If x * y and z are many orders of magnitude apart, the scaling
+        * will overflow, so we handle these cases specially.  Rounding
+        * modes other than FE_TONEAREST are painful.
+        */
+       if (spread < -DBL_MANT_DIG) {
+               feraiseexcept(FE_INEXACT);
+               if (!isnormal(z))
+                       feraiseexcept(FE_UNDERFLOW);
+               switch (oround) {
+               case FE_TONEAREST:
+                       return (z);
+               case FE_TOWARDZERO:
+                       if ((x > 0.0) ^ (y < 0.0) ^ (z < 0.0))
+                               return (z);
+                       else
+                               return (nextafter(z, 0));
+               case FE_DOWNWARD:
+                       if ((x > 0.0) ^ (y < 0.0))
+                               return (z);
+                       else
+                               return (nextafter(z, -INFINITY));
+               default:        /* FE_UPWARD */
+                       if ((x > 0.0) ^ (y < 0.0))
+                               return (nextafter(z, INFINITY));
+                       else
+                               return (z);
+               }
+       }
+       if (spread <= DBL_MANT_DIG * 2)
+               zs = ldexp(zs, -spread);
+       else
+               zs = copysign(DBL_MIN, zs);
+
+       fesetround(FE_TONEAREST);
+
+       /*
+        * Basic approach for round-to-nearest:
+        *
+        *     (xy.hi, xy.lo) = x * y           (exact)
+        *     (r.hi, r.lo)   = xy.hi + z       (exact)
+        *     adj = xy.lo + r.lo               (inexact; low bit is sticky)
+        *     result = r.hi + adj              (correctly rounded)
+        */
+       xy = dd_mul(xs, ys);
+       r = dd_add(xy.hi, zs);
+
+       spread = ex + ey;
+
+       if (r.hi == 0.0) {
+               /*
+                * When the addends cancel to 0, ensure that the result has
+                * the correct sign.
+                */
+               fesetround(oround);
+               volatile double vzs = zs; /* XXX gcc CSE bug workaround */
+               return (xy.hi + vzs + ldexp(xy.lo, spread));
+       }
+
+       if (oround != FE_TONEAREST) {
+               /*
+                * There is no need to worry about double rounding in directed
+                * rounding modes.
+                */
+               fesetround(oround);
+               adj = r.lo + xy.lo;
+               return (ldexp(r.hi + adj, spread));
+       }
+
+       adj = add_adjusted(r.lo, xy.lo);
+       if (spread + ilogb(r.hi) > -1023)
+               return (ldexp(r.hi + adj, spread));
+       else
+               return (add_and_denormalize(r.hi, adj, spread));
+}
+
+#if (LDBL_MANT_DIG == 53)
+__weak_reference(fma, fmal);
+#endif
similarity index 52%
rename from lib/libm/src/lroundf.c
rename to lib/libm/src/s_fmaf.c
index 75fb029..e589d51 100644 (file)
@@ -1,8 +1,6 @@
-/* $NetBSD: lroundf.c,v 1.3 2008/04/26 23:49:50 christos Exp $ */
-
 /*-
- * Copyright (c) 2004
- *     Matthias Drochner. All rights reserved.
+ * Copyright (c) 2005-2011 David Schultz <das@FreeBSD.ORG>
+ * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * 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 SVN: 226371 (2011-10-15)
  */
 
+#include <fenv.h>
 #include <math.h>
-#include <sys/ieee754.h>
-#include <machine/limits.h>
 #include "math_private.h"
 
-#ifndef LROUNDNAME
-#define LROUNDNAME lroundf
-#define RESTYPE long int
-#define RESTYPE_MIN LONG_MIN
-#define RESTYPE_MAX LONG_MAX
-#endif
-
-#define RESTYPE_BITS (sizeof(RESTYPE) * 8)
-
-RESTYPE
-LROUNDNAME(float x)
+/*
+ * Fused multiply-add: Compute x * y + z with a single rounding error.
+ *
+ * A double has more than twice as much precision than a float, so
+ * direct double-precision arithmetic suffices, except where double
+ * rounding occurs.
+ */
+float
+fmaf(float x, float y, float z)
 {
-       u_int32_t i0;
-       int e, s, shift;
-       RESTYPE res;
-
-       GET_FLOAT_WORD(i0, x);
-       e = i0 >> SNG_FRACBITS;
-       s = (uint32_t)e >> SNG_EXPBITS;
-       e = (e & 0xff) - SNG_EXP_BIAS;
-
-       /* 1.0 x 2^-1 is the smallest number which can be rounded to 1 */
-       if (e < -1)
-               return (0);
-       /* 1.0 x 2^31 (or 2^63) is already too large */
-       if (e >= (int)RESTYPE_BITS - 1)
-               return (s ? RESTYPE_MIN : RESTYPE_MAX); /* ??? unspecified */
-
-       /* >= 2^23 is already an exact integer */
-       if (e < SNG_FRACBITS) {
-               /* add 0.5, extraction below will truncate */
-               x += (s ? -0.5 : 0.5);
-       }
-
-       GET_FLOAT_WORD(i0, x);
-       e = ((i0 >> SNG_FRACBITS) & 0xff) - SNG_EXP_BIAS;
-       i0 &= 0x7fffff;
-       i0 |= (1 << SNG_FRACBITS);
+       double xy, result;
+       uint32_t hr, lr;
 
-       shift = e - SNG_FRACBITS;
-       if (shift >=0)
-               res = (shift < 32 ? (RESTYPE)i0 << shift : 0);
-       else
-               res = (shift > -32 ? i0 >> -shift : 0);
+       xy = (double)x * y;
+       result = xy + z;
+       EXTRACT_WORDS(hr, lr, result);
+       /* Common case: The double precision result is fine. */
+       if ((lr & 0x1fffffff) != 0x10000000 ||  /* not a halfway case */
+           (hr & 0x7ff00000) == 0x7ff00000 ||  /* NaN */
+           result - xy == z ||                 /* exact */
+           fegetround() != FE_TONEAREST)       /* not round-to-nearest */
+               return (result);
 
-       return (s ? -res : res);
+       /*
+        * If result is inexact, and exactly halfway between two float values,
+        * we need to adjust the low-order bit in the direction of the error.
+        */
+       fesetround(FE_TOWARDZERO);
+       volatile double vxy = xy;  /* XXX work around gcc CSE bug */
+       double adjusted_result = vxy + z;
+       fesetround(FE_TONEAREST);
+       if (result == adjusted_result)
+               SET_LOW_WORD(adjusted_result, lr + 1);
+       return (adjusted_result);
 }
diff --git a/lib/libm/src/s_fmal.c b/lib/libm/src/s_fmal.c
new file mode 100644 (file)
index 0000000..90c2cc8
--- /dev/null
@@ -0,0 +1,267 @@
+/*-
+ * Copyright (c) 2005-2011 David Schultz <das@FreeBSD.ORG>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * FreeBSD SVN: 226601 (2011-10-21)
+ */
+
+#include <fenv.h>
+#include <float.h>
+#include <math.h>
+
+#include "fpmath.h"
+
+/*
+ * A struct dd represents a floating-point number with twice the precision
+ * of a long double.  We maintain the invariant that "hi" stores the high-order
+ * bits of the result.
+ */
+struct dd {
+       long double hi;
+       long double lo;
+};
+
+/*
+ * Compute a+b exactly, returning the exact result in a struct dd.  We assume
+ * that both a and b are finite, but make no assumptions about their relative
+ * magnitudes.
+ */
+static inline struct dd
+dd_add(long double a, long double b)
+{
+       struct dd ret;
+       long double s;
+
+       ret.hi = a + b;
+       s = ret.hi - a;
+       ret.lo = (a - (ret.hi - s)) + (b - s);
+       return (ret);
+}
+
+/*
+ * Compute a+b, with a small tweak:  The least significant bit of the
+ * result is adjusted into a sticky bit summarizing all the bits that
+ * were lost to rounding.  This adjustment negates the effects of double
+ * rounding when the result is added to another number with a higher
+ * exponent.  For an explanation of round and sticky bits, see any reference
+ * on FPU design, e.g.,
+ *
+ *     J. Coonen.  An Implementation Guide to a Proposed Standard for
+ *     Floating-Point Arithmetic.  Computer, vol. 13, no. 1, Jan 1980.
+ */
+static inline long double
+add_adjusted(long double a, long double b)
+{
+       struct dd sum;
+       union IEEEl2bits u;
+
+       sum = dd_add(a, b);
+       if (sum.lo != 0) {
+               u.e = sum.hi;
+               if ((u.bits.manl & 1) == 0)
+                       sum.hi = nextafterl(sum.hi, INFINITY * sum.lo);
+       }
+       return (sum.hi);
+}
+
+/*
+ * Compute ldexp(a+b, scale) with a single rounding error. It is assumed
+ * that the result will be subnormal, and care is taken to ensure that
+ * double rounding does not occur.
+ */
+static inline long double
+add_and_denormalize(long double a, long double b, int scale)
+{
+       struct dd sum;
+       int bits_lost;
+       union IEEEl2bits u;
+
+       sum = dd_add(a, b);
+
+       /*
+        * If we are losing at least two bits of accuracy to denormalization,
+        * then the first lost bit becomes a round bit, and we adjust the
+        * lowest bit of sum.hi to make it a sticky bit summarizing all the
+        * bits in sum.lo. With the sticky bit adjusted, the hardware will
+        * break any ties in the correct direction.
+        *
+        * If we are losing only one bit to denormalization, however, we must
+        * break the ties manually.
+        */
+       if (sum.lo != 0) {
+               u.e = sum.hi;
+               bits_lost = -u.bits.exp - scale + 1;
+               if ((bits_lost != 1) ^ (int)(u.bits.manl & 1))
+                       sum.hi = nextafterl(sum.hi, INFINITY * sum.lo);
+       }
+       return (ldexp(sum.hi, scale));
+}
+
+/*
+ * Compute a*b exactly, returning the exact result in a struct dd.  We assume
+ * that both a and b are normalized, so no underflow or overflow will occur.
+ * The current rounding mode must be round-to-nearest.
+ */
+static inline struct dd
+dd_mul(long double a, long double b)
+{
+#if LDBL_MANT_DIG == 64
+       static const long double split = 0x1p32L + 1.0;
+#elif LDBL_MANT_DIG == 113
+       static const long double split = 0x1p57L + 1.0;
+#endif
+       struct dd ret;
+       long double ha, hb, la, lb, p, q;
+
+       p = a * split;
+       ha = a - p;
+       ha += p;
+       la = a - ha;
+
+       p = b * split;
+       hb = b - p;
+       hb += p;
+       lb = b - hb;
+
+       p = ha * hb;
+       q = ha * lb + la * hb;
+
+       ret.hi = p + q;
+       ret.lo = p - ret.hi + q + la * lb;
+       return (ret);
+}
+
+/*
+ * Fused multiply-add: Compute x * y + z with a single rounding error.
+ *
+ * We use scaling to avoid overflow/underflow, along with the
+ * canonical precision-doubling technique adapted from:
+ *
+ *     Dekker, T.  A Floating-Point Technique for Extending the
+ *     Available Precision.  Numer. Math. 18, 224-242 (1971).
+ */
+long double
+fmal(long double x, long double y, long double z)
+{
+       long double xs, ys, zs, adj;
+       struct dd xy, r;
+       int oround;
+       int ex, ey, ez;
+       int spread;
+
+       /*
+        * Handle special cases. The order of operations and the particular
+        * return values here are crucial in handling special cases involving
+        * infinities, NaNs, overflows, and signed zeroes correctly.
+        */
+       if (x == 0.0 || y == 0.0)
+               return (x * y + z);
+       if (z == 0.0)
+               return (x * y);
+       if (!isfinite(x) || !isfinite(y))
+               return (x * y + z);
+       if (!isfinite(z))
+               return (z);
+
+       xs = frexpl(x, &ex);
+       ys = frexpl(y, &ey);
+       zs = frexpl(z, &ez);
+       oround = fegetround();
+       spread = ex + ey - ez;
+
+       /*
+        * If x * y and z are many orders of magnitude apart, the scaling
+        * will overflow, so we handle these cases specially.  Rounding
+        * modes other than FE_TONEAREST are painful.
+        */
+       if (spread < -LDBL_MANT_DIG) {
+               feraiseexcept(FE_INEXACT);
+               if (!isnormal(z))
+                       feraiseexcept(FE_UNDERFLOW);
+               switch (oround) {
+               case FE_TONEAREST:
+                       return (z);
+               case FE_TOWARDZERO:
+                       if ((x > 0.0) ^ (y < 0.0) ^ (z < 0.0))
+                               return (z);
+                       else
+                               return (nextafterl(z, 0));
+               case FE_DOWNWARD:
+                       if ((x > 0.0) ^ (y < 0.0))
+                               return (z);
+                       else
+                               return (nextafterl(z, -INFINITY));
+               default:        /* FE_UPWARD */
+                       if ((x > 0.0) ^ (y < 0.0))
+                               return (nextafterl(z, INFINITY));
+                       else
+                               return (z);
+               }
+       }
+       if (spread <= LDBL_MANT_DIG * 2)
+               zs = ldexpl(zs, -spread);
+       else
+               zs = copysignl(LDBL_MIN, zs);
+
+       fesetround(FE_TONEAREST);
+
+       /*
+        * Basic approach for round-to-nearest:
+        *
+        *     (xy.hi, xy.lo) = x * y           (exact)
+        *     (r.hi, r.lo)   = xy.hi + z       (exact)
+        *     adj = xy.lo + r.lo               (inexact; low bit is sticky)
+        *     result = r.hi + adj              (correctly rounded)
+        */
+       xy = dd_mul(xs, ys);
+       r = dd_add(xy.hi, zs);
+
+       spread = ex + ey;
+
+       if (r.hi == 0.0) {
+               /*
+                * When the addends cancel to 0, ensure that the result has
+                * the correct sign.
+                */
+               fesetround(oround);
+               volatile long double vzs = zs; /* XXX gcc CSE bug workaround */
+               return (xy.hi + vzs + ldexpl(xy.lo, spread));
+       }
+
+       if (oround != FE_TONEAREST) {
+               /*
+                * There is no need to worry about double rounding in directed
+                * rounding modes.
+                */
+               fesetround(oround);
+               adj = r.lo + xy.lo;
+               return (ldexpl(r.hi + adj, spread));
+       }
+
+       adj = add_adjusted(r.lo, xy.lo);
+       if (spread + ilogbl(r.hi) > -16383)
+               return (ldexpl(r.hi + adj, spread));
+       else
+               return (add_and_denormalize(r.hi, adj, spread));
+}
diff --git a/lib/libm/src/s_llrint.c b/lib/libm/src/s_llrint.c
new file mode 100644 (file)
index 0000000..edc631a
--- /dev/null
@@ -0,0 +1,10 @@
+/*
+ * FreeBSD SVN: 140088 (2005-01-11)
+ */
+
+#define type           double
+#define        roundit         rint
+#define dtype          long long
+#define        fn              llrint
+
+#include "s_lrint.c"
diff --git a/lib/libm/src/s_llrintf.c b/lib/libm/src/s_llrintf.c
new file mode 100644 (file)
index 0000000..a684b7b
--- /dev/null
@@ -0,0 +1,10 @@
+/*
+ * FreeBSD SVN: 140088 (2005-01-11)
+ */
+
+#define type           float
+#define        roundit         rintf
+#define dtype          long long
+#define        fn              llrintf
+
+#include "s_lrint.c"
diff --git a/lib/libm/src/s_llrintl.c b/lib/libm/src/s_llrintl.c
new file mode 100644 (file)
index 0000000..0b01b3d
--- /dev/null
@@ -0,0 +1,10 @@
+/*
+ * FreeBSD SVN: 175309 (2008-01-14)
+ */
+
+#define type           long double
+#define        roundit         rintl
+#define dtype          long long
+#define        fn              llrintl
+
+#include "s_lrint.c"
diff --git a/lib/libm/src/s_llround.c b/lib/libm/src/s_llround.c
new file mode 100644 (file)
index 0000000..43507bf
--- /dev/null
@@ -0,0 +1,12 @@
+/*
+ * FreeBSD SVN: 144771 (2005-04-08)
+ */
+
+#define type           double
+#define        roundit         round
+#define dtype          long long
+#define        DTYPE_MIN       LLONG_MIN
+#define        DTYPE_MAX       LLONG_MAX
+#define        fn              llround
+
+#include "s_lround.c"
diff --git a/lib/libm/src/s_llroundf.c b/lib/libm/src/s_llroundf.c
new file mode 100644 (file)
index 0000000..ba4d4f9
--- /dev/null
@@ -0,0 +1,12 @@
+/*
+ * FreeBSD SVN: 144771 (2005-04-08)
+ */
+
+#define type           float
+#define        roundit         roundf
+#define dtype          long long
+#define        DTYPE_MIN       LLONG_MIN
+#define        DTYPE_MAX       LLONG_MAX
+#define        fn              llroundf
+
+#include "s_lround.c"
diff --git a/lib/libm/src/s_llroundl.c b/lib/libm/src/s_llroundl.c
new file mode 100644 (file)
index 0000000..2ab1255
--- /dev/null
@@ -0,0 +1,12 @@
+/*
+ * FreeBSD SVN: 144772 (2005-04-08)
+ */
+
+#define type           long double
+#define        roundit         roundl
+#define dtype          long long
+#define        DTYPE_MIN       LLONG_MIN
+#define        DTYPE_MAX       LLONG_MAX
+#define        fn              llroundl
+
+#include "s_lround.c"
similarity index 65%
copy from lib/libm/src/s_nearbyint.c
copy to lib/libm/src/s_lrint.c
index 58056e5..4242912 100644 (file)
@@ -1,5 +1,5 @@
 /*-
- * Copyright (c) 2004 David Schultz <das@FreeBSD.ORG>
+ * Copyright (c) 2005 David Schultz <das@FreeBSD.ORG>
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * 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 SVN: 140088 (2005-01-11)
  */
 
-#include <sys/cdefs.h>
-
 #include <fenv.h>
 #include <math.h>
 
+#ifndef type
+#define type           double
+#define        roundit         rint
+#define dtype          long
+#define        fn              lrint
+#endif
+
 /*
- * We save and restore the floating-point environment to avoid raising
- * an inexact exception.  We can get away with using fesetenv()
- * instead of feclearexcept()/feupdateenv() to restore the environment
- * because the only exception defined for rint() is overflow, and
- * rounding can't overflow as long as emax >= p.
+ * C99 says we should not raise a spurious inexact exception when an
+ * invalid exception is raised.  Unfortunately, the set of inputs
+ * that overflows depends on the rounding mode when 'dtype' has more
+ * significant bits than 'type'.  Hence, we bend over backwards for the
+ * sake of correctness; an MD implementation could be more efficient.
  */
-#define        DECL(type, fn, rint)    \
-type                           \
-fn(type x)                     \
-{                              \
-       type ret;               \
-       fenv_t env;             \
-                               \
-       fegetenv(&env);         \
-       ret = rint(x);          \
-       fesetenv(&env);         \
-       return (ret);           \
-}
+dtype
+fn(type x)
+{
+       fenv_t env;
+       dtype d;
 
-DECL(double, nearbyint, rint)
-DECL(float, nearbyintf, rintf)
+       feholdexcept(&env);
+       d = (dtype)roundit(x);
+       if (fetestexcept(FE_INVALID))
+               feclearexcept(FE_INEXACT);
+       feupdateenv(&env);
+       return (d);
+}
diff --git a/lib/libm/src/s_lrintf.c b/lib/libm/src/s_lrintf.c
new file mode 100644 (file)
index 0000000..e791538
--- /dev/null
@@ -0,0 +1,10 @@
+/*
+ * FreeBSD SVN: 153017 (2005-12-02)
+ */
+
+#define type           float
+#define        roundit         rintf
+#define dtype          long
+#define        fn              lrintf
+
+#include "s_lrint.c"
diff --git a/lib/libm/src/s_lrintl.c b/lib/libm/src/s_lrintl.c
new file mode 100644 (file)
index 0000000..aabdde8
--- /dev/null
@@ -0,0 +1,10 @@
+/*
+ * FreeBSD SVN: 175309 (2008-01-14)
+ */
+
+#define type           long double
+#define        roundit         rintl
+#define dtype          long
+#define        fn              lrintl
+
+#include "s_lrint.c"
similarity index 56%
copy from lib/libm/src/s_nearbyint.c
copy to lib/libm/src/s_lround.c
index 58056e5..2f9bc00 100644 (file)
@@ -1,5 +1,5 @@
 /*-
- * Copyright (c) 2004 David Schultz <das@FreeBSD.ORG>
+ * Copyright (c) 2005 David Schultz <das@FreeBSD.ORG>
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * 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 SVN: 144770 (2005-04-08)
  */
 
-#include <sys/cdefs.h>
-
+#include <sys/limits.h>
 #include <fenv.h>
 #include <math.h>
 
+#ifndef type
+#define type           double
+#define        roundit         round
+#define dtype          long
+#define        DTYPE_MIN       LONG_MIN
+#define        DTYPE_MAX       LONG_MAX
+#define        fn              lround
+#endif
+
 /*
- * We save and restore the floating-point environment to avoid raising
- * an inexact exception.  We can get away with using fesetenv()
- * instead of feclearexcept()/feupdateenv() to restore the environment
- * because the only exception defined for rint() is overflow, and
- * rounding can't overflow as long as emax >= p.
+ * If type has more precision than dtype, the endpoints dtype_(min|max) are
+ * of the form xxx.5; they are "out of range" because lround() rounds away
+ * from 0.  On the other hand, if type has less precision than dtype, then
+ * all values that are out of range are integral, so we might as well assume
+ * that everything is in range.  At compile time, INRANGE(x) should reduce to
+ * two floating-point comparisons in the former case, or TRUE otherwise.
  */
-#define        DECL(type, fn, rint)    \
-type                           \
-fn(type x)                     \
-{                              \
-       type ret;               \
-       fenv_t env;             \
-                               \
-       fegetenv(&env);         \
-       ret = rint(x);          \
-       fesetenv(&env);         \
-       return (ret);           \
-}
+static const type dtype_min = DTYPE_MIN - 0.5;
+static const type dtype_max = DTYPE_MAX + 0.5;
+#define        INRANGE(x)      (dtype_max - DTYPE_MAX != 0.5 || \
+                        ((x) > dtype_min && (x) < dtype_max))
+
+dtype
+fn(type x)
+{
 
-DECL(double, nearbyint, rint)
-DECL(float, nearbyintf, rintf)
+       if (INRANGE(x)) {
+               x = roundit(x);
+               return ((dtype)x);
+       } else {
+               feraiseexcept(FE_INVALID);
+               return (DTYPE_MAX);
+       }
+}
diff --git a/lib/libm/src/s_lroundf.c b/lib/libm/src/s_lroundf.c
new file mode 100644 (file)
index 0000000..00deeb5
--- /dev/null
@@ -0,0 +1,12 @@
+/*
+ * FreeBSD SVN: 144771 (2005-04-08)
+ */
+
+#define type           float
+#define        roundit         roundf
+#define dtype          long
+#define        DTYPE_MIN       LONG_MIN
+#define        DTYPE_MAX       LONG_MAX
+#define        fn              lroundf
+
+#include "s_lround.c"
diff --git a/lib/libm/src/s_lroundl.c b/lib/libm/src/s_lroundl.c
new file mode 100644 (file)
index 0000000..b68fbfc
--- /dev/null
@@ -0,0 +1,12 @@
+/*
+ * FreeBSD SVN: 144772 (2005-04-08)
+ */
+
+#define type           long double
+#define        roundit         roundl
+#define dtype          long
+#define        DTYPE_MIN       LONG_MIN
+#define        DTYPE_MAX       LONG_MAX
+#define        fn              lroundl
+
+#include "s_lround.c"
diff --git a/lib/libm/src/s_modf.c b/lib/libm/src/s_modf.c
new file mode 100644 (file)
index 0000000..aab8d0a
--- /dev/null
@@ -0,0 +1,77 @@
+/* @(#)s_modf.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ *
+ * FreeBSD SVN: 165838 (2007-01-06)
+ */
+
+/*
+ * modf(double x, double *iptr)
+ * return fraction part of x, and return x's integral part in *iptr.
+ * Method:
+ *     Bit twiddling.
+ *
+ * Exception:
+ *     No exception.
+ */
+
+#include <math.h>
+#include "math_private.h"
+
+static const double one = 1.0;
+
+double
+modf(double x, double *iptr)
+{
+       int32_t i0,i1,j0;
+       u_int32_t i;
+       EXTRACT_WORDS(i0,i1,x);
+       j0 = ((i0>>20)&0x7ff)-0x3ff;    /* exponent of x */
+       if(j0<20) {                     /* integer part in high x */
+           if(j0<0) {                  /* |x|<1 */
+               INSERT_WORDS(*iptr,i0&0x80000000,0);    /* *iptr = +-0 */
+               return x;
+           } else {
+               i = (0x000fffff)>>j0;
+               if(((i0&i)|i1)==0) {            /* x is integral */
+                   u_int32_t high;
+                   *iptr = x;
+                   GET_HIGH_WORD(high,x);
+                   INSERT_WORDS(x,high&0x80000000,0);  /* return +-0 */
+                   return x;
+               } else {
+                   INSERT_WORDS(*iptr,i0&(~i),0);
+                   return x - *iptr;
+               }
+           }
+       } else if (j0>51) {             /* no fraction part */
+           u_int32_t high;
+           if (j0 == 0x400) {          /* inf/NaN */
+               *iptr = x;
+               return 0.0 / x;
+           }
+           *iptr = x*one;
+           GET_HIGH_WORD(high,x);
+           INSERT_WORDS(x,high&0x80000000,0);  /* return +-0 */
+           return x;
+       } else {                        /* fraction part in low x */
+           i = ((u_int32_t)(0xffffffff))>>(j0-20);
+           if((i1&i)==0) {             /* x is integral */
+               u_int32_t high;
+               *iptr = x;
+               GET_HIGH_WORD(high,x);
+               INSERT_WORDS(x,high&0x80000000,0);      /* return +-0 */
+               return x;
+           } else {
+               INSERT_WORDS(*iptr,i0,i1&(~i));
+               return x - *iptr;
+           }
+       }
+}
diff --git a/lib/libm/src/s_modfl.c b/lib/libm/src/s_modfl.c
new file mode 100644 (file)
index 0000000..fb9f75d
--- /dev/null
@@ -0,0 +1,101 @@
+/*-
+ * Copyright (c) 2007 David Schultz <das@FreeBSD.ORG>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * Derived from s_modf.c, which has the following Copyright:
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ *
+ * FreeBSD SVN: 165855 (2007-01-06)
+ */
+
+#include <float.h>
+#include <math.h>
+#include <sys/types.h>
+
+#include "fpmath.h"
+
+#if LDBL_MANL_SIZE > 32
+#define        MASK    ((uint64_t)-1)
+#else
+#define        MASK    ((uint32_t)-1)
+#endif
+/* Return the last n bits of a word, representing the fractional part. */
+#define        GETFRAC(bits, n)        ((bits) & ~(MASK << (n)))
+/* The number of fraction bits in manh, not counting the integer bit */
+#define        HIBITS  (LDBL_MANT_DIG - LDBL_MANL_SIZE)
+
+static const long double zero[] = { 0.0L, -0.0L };
+
+long double
+modfl(long double x, long double *iptr)
+{
+       union IEEEl2bits ux;
+       int e;
+
+       ux.e = x;
+       e = ux.bits.exp - LDBL_MAX_EXP + 1;
+       if (e < HIBITS) {                       /* Integer part is in manh. */
+               if (e < 0) {                    /* |x|<1 */
+                       *iptr = zero[ux.bits.sign];
+                       return (x);
+               } else {
+                       if ((GETFRAC(ux.bits.manh, HIBITS - 1 - e) |
+                            ux.bits.manl) == 0) {      /* X is an integer. */
+                               *iptr = x;
+                               return (zero[ux.bits.sign]);
+                       } else {
+                               /* Clear all but the top e+1 bits. */
+                               ux.bits.manh >>= HIBITS - 1 - e;
+                               ux.bits.manh <<= HIBITS - 1 - e;
+                               ux.bits.manl = 0;
+                               *iptr = ux.e;
+                               return (x - ux.e);
+                       }
+               }
+       } else if (e >= LDBL_MANT_DIG - 1) {    /* x has no fraction part. */
+               *iptr = x;
+               if (x != x)                     /* Handle NaNs. */
+                       return (x);
+               return (zero[ux.bits.sign]);
+       } else {                                /* Fraction part is in manl. */
+               if (GETFRAC(ux.bits.manl, LDBL_MANT_DIG - 1 - e) == 0) {
+                       /* x is integral. */
+                       *iptr = x;
+                       return (zero[ux.bits.sign]);
+               } else {
+                       /* Clear all but the top e+1 bits. */
+                       ux.bits.manl >>= LDBL_MANT_DIG - 1 - e;
+                       ux.bits.manl <<= LDBL_MANT_DIG - 1 - e;
+                       *iptr = ux.e;
+                       return (x - ux.e);
+               }
+       }
+}
index 58056e5..1bd3ad1 100644 (file)
  * 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 SVN: 175309 (2008-01-14)
  */
 
-#include <sys/cdefs.h>
-
 #include <fenv.h>
 #include <math.h>
 
@@ -51,3 +51,4 @@ fn(type x)                    \
 
 DECL(double, nearbyint, rint)
 DECL(float, nearbyintf, rintf)
+DECL(long double, nearbyintl, rintl)
diff --git a/lib/libm/src/s_nexttowardf.c b/lib/libm/src/s_nexttowardf.c
new file mode 100644 (file)
index 0000000..025bcbc
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ *
+ * FreeBSD SVN: 218511 (2011-02-10)
+ */
+
+#include <float.h>
+#include <math.h>
+
+#include "fpmath.h"
+#include "math_private.h"
+
+#define        LDBL_INFNAN_EXP (LDBL_MAX_EXP * 2 - 1)
+
+float
+nexttowardf(float x, long double y)
+{
+       union IEEEl2bits uy;
+       volatile float t;
+       int32_t hx,ix;
+
+       GET_FLOAT_WORD(hx,x);
+       ix = hx&0x7fffffff;             /* |x| */
+       uy.e = y;
+
+       if((ix>0x7f800000) ||
+          (uy.bits.exp == LDBL_INFNAN_EXP &&
+           ((uy.bits.manh&~LDBL_NBIT)|uy.bits.manl) != 0))
+          return x+y;  /* x or y is nan */
+       if(x==y) return (float)y;               /* x=y, return y */
+       if(ix==0) {                             /* x == 0 */
+           SET_FLOAT_WORD(x,(uy.bits.sign<<31)|1);/* return +-minsubnormal */
+           t = x*x;
+           if(t==x) return t; else return x;   /* raise underflow flag */
+       }
+       if((hx>=0) ^ (x < y))                   /* x -= ulp */
+           hx -= 1;
+       else                                    /* x += ulp */
+           hx += 1;
+       ix = hx&0x7f800000;
+       if(ix>=0x7f800000) return x+x;  /* overflow  */
+       if(ix<0x00800000) {             /* underflow */
+           t = x*x;
+           if(t!=x) {          /* raise underflow flag */
+               SET_FLOAT_WORD(x,hx);
+               return x;
+           }
+       }
+       SET_FLOAT_WORD(x,hx);
+       return x;
+}
index bd3e0ad..6f23bae 100644 (file)
@@ -5,7 +5,7 @@
  *
  * 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.
  * ====================================================
  */
@@ -74,7 +74,7 @@ remquo(double x, double y, int *quo)
        } else iy = (hy>>20)-1023;
 
     /* set up {hx,lx}, {hy,ly} and align y to x */
-       if(ix >= -1022) 
+       if(ix >= -1022)
            hx = 0x00100000|(0x000fffff&hx);
        else {          /* subnormal x, shift x to normal */
            n = -1022-ix;
@@ -86,7 +86,7 @@ remquo(double x, double y, int *quo)
                lx = 0;
            }
        }
-       if(iy >= -1022) 
+       if(iy >= -1022)
            hy = 0x00100000|(0x000fffff&hy);
        else {          /* subnormal y, shift y to normal */
            n = -1022-iy;
index 2d1c994..37a6cbc 100644 (file)
@@ -5,7 +5,7 @@
  *
  * 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.
  * ====================================================
  */
diff --git a/lib/libm/src/s_remquol.c b/lib/libm/src/s_remquol.c
new file mode 100644 (file)
index 0000000..2515b85
--- /dev/null
@@ -0,0 +1,175 @@
+/* @(#)e_fmod.c 1.3 95/01/18 */
+/*-
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunSoft, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ * FreeBSD SVN: 177764 (2008-03-30)
+ */
+
+#include <float.h>
+#include <stdint.h>
+
+#include <math.h>
+#include "fpmath.h"
+#include "math_private.h"
+
+#define        BIAS (LDBL_MAX_EXP - 1)
+
+#if LDBL_MANL_SIZE > 32
+typedef        uint64_t manl_t;
+#else
+typedef        uint32_t manl_t;
+#endif
+
+#if LDBL_MANH_SIZE > 32
+typedef        uint64_t manh_t;
+#else
+typedef        uint32_t manh_t;
+#endif
+
+/*
+ * These macros add and remove an explicit integer bit in front of the
+ * fractional mantissa, if the architecture doesn't have such a bit by
+ * default already.
+ */
+#ifdef LDBL_IMPLICIT_NBIT
+#define        SET_NBIT(hx)    ((hx) | (1ULL << LDBL_MANH_SIZE))
+#define        HFRAC_BITS      LDBL_MANH_SIZE
+#else
+#define        SET_NBIT(hx)    (hx)
+#define        HFRAC_BITS      (LDBL_MANH_SIZE - 1)
+#endif
+
+#define        MANL_SHIFT      (LDBL_MANL_SIZE - 1)
+
+static const long double Zero[] = {0.0L, -0.0L};
+
+/*
+ * Return the IEEE remainder and set *quo to the last n bits of the
+ * quotient, rounded to the nearest integer.  We choose n=31 because
+ * we wind up computing all the integer bits of the quotient anyway as
+ * a side-effect of computing the remainder by the shift and subtract
+ * method.  In practice, this is far more bits than are needed to use
+ * remquo in reduction algorithms.
+ *
+ * Assumptions:
+ * - The low part of the mantissa fits in a manl_t exactly.
+ * - The high part of the mantissa fits in an int64_t with enough room
+ *   for an explicit integer bit in front of the fractional bits.
+ */
+long double
+remquol(long double x, long double y, int *quo)
+{
+       union IEEEl2bits ux, uy;
+       int64_t hx,hz;  /* We need a carry bit even if LDBL_MANH_SIZE is 32. */
+       manh_t hy;
+       manl_t lx,ly,lz;
+       int ix,iy,n,q,sx,sxy;
+
+       ux.e = x;
+       uy.e = y;
+       sx = ux.bits.sign;
+       sxy = sx ^ uy.bits.sign;
+       ux.bits.sign = 0;       /* |x| */
+       uy.bits.sign = 0;       /* |y| */
+       x = ux.e;
+
+    /* purge off exception values */
+       if((uy.bits.exp|uy.bits.manh|uy.bits.manl)==0 || /* y=0 */
+          (ux.bits.exp == BIAS + LDBL_MAX_EXP) ||       /* or x not finite */
+          (uy.bits.exp == BIAS + LDBL_MAX_EXP &&
+           ((uy.bits.manh&~LDBL_NBIT)|uy.bits.manl)!=0)) /* or y is NaN */
+           return (x*y)/(x*y);
+       if(ux.bits.exp<=uy.bits.exp) {
+           if((ux.bits.exp<uy.bits.exp) ||
+              (ux.bits.manh<=uy.bits.manh &&
+               (ux.bits.manh<uy.bits.manh ||
+                ux.bits.manl<uy.bits.manl))) {
+               q = 0;
+               goto fixup;     /* |x|<|y| return x or x-y */
+           }
+           if(ux.bits.manh==uy.bits.manh && ux.bits.manl==uy.bits.manl) {
+               *quo = 1;
+               return Zero[sx];        /* |x|=|y| return x*0*/
+           }
+       }
+
+    /* determine ix = ilogb(x) */
+       if(ux.bits.exp == 0) {  /* subnormal x */
+           ux.e *= 0x1.0p512;
+           ix = ux.bits.exp - (BIAS + 512);
+       } else {
+           ix = ux.bits.exp - BIAS;
+       }
+
+    /* determine iy = ilogb(y) */
+       if(uy.bits.exp == 0) {  /* subnormal y */
+           uy.e *= 0x1.0p512;
+           iy = uy.bits.exp - (BIAS + 512);
+       } else {
+           iy = uy.bits.exp - BIAS;
+       }
+
+    /* set up {hx,lx}, {hy,ly} and align y to x */
+       hx = SET_NBIT(ux.bits.manh);
+       hy = SET_NBIT(uy.bits.manh);
+       lx = ux.bits.manl;
+       ly = uy.bits.manl;
+
+    /* fix point fmod */
+       n = ix - iy;
+       q = 0;
+
+       while(n--) {
+           hz=hx-hy;lz=lx-ly; if(lx<ly) hz -= 1;
+           if(hz<0){hx = hx+hx+(lx>>MANL_SHIFT); lx = lx+lx;}
+           else {hx = hz+hz+(lz>>MANL_SHIFT); lx = lz+lz; q++;}
+           q <<= 1;
+       }
+       hz=hx-hy;lz=lx-ly; if(lx<ly) hz -= 1;
+       if(hz>=0) {hx=hz;lx=lz;q++;}
+
+    /* convert back to floating value and restore the sign */
+       if((hx|lx)==0) {                        /* return sign(x)*0 */
+           *quo = (sxy ? -q : q);
+           return Zero[sx];
+       }
+       while(hx<(1ULL<<HFRAC_BITS)) {  /* normalize x */
+           hx = hx+hx+(lx>>MANL_SHIFT); lx = lx+lx;
+           iy -= 1;
+       }
+       ux.bits.manh = hx; /* The integer bit is truncated here if needed. */
+       ux.bits.manl = lx;
+       if (iy < LDBL_MIN_EXP) {
+           ux.bits.exp = iy + (BIAS + 512);
+           ux.e *= 0x1p-512;
+       } else {
+           ux.bits.exp = iy + BIAS;
+       }
+       ux.bits.sign = 0;
+       x = ux.e;
+fixup:
+       y = fabsl(y);
+       if (y < LDBL_MIN * 2) {
+           if (x+x>y || (x+x==y && (q & 1))) {
+               q++;
+               x-=y;
+           }
+       } else if (x>0.5*y || (x==0.5*y && (q & 1))) {
+           q++;
+           x-=y;
+       }
+
+       ux.e = x;
+       ux.bits.sign ^= sx;
+       x = ux.e;
+
+       q &= 0x7fffffff;
+       *quo = (sxy ? -q : q);
+       return x;
+}
similarity index 50%
rename from lib/libm/src/lround.c
rename to lib/libm/src/s_rintl.c
index ab71944..e1ab92d 100644 (file)
@@ -1,8 +1,6 @@
-/* $NetBSD: lround.c,v 1.3 2008/04/26 23:49:50 christos Exp $ */
-
 /*-
- * Copyright (c) 2004
- *     Matthias Drochner. All rights reserved.
+ * Copyright (c) 2008 David Schultz <das@FreeBSD.ORG>
+ * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * 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 SVN: 176461 (2008-02-22)
  */
 
+#include <float.h>
 #include <math.h>
-#include <sys/ieee754.h>
-#include <machine/limits.h>
-#include "math_private.h"
 
-#ifndef LROUNDNAME
-#define LROUNDNAME lround
-#define RESTYPE long int
-#define RESTYPE_MIN LONG_MIN
-#define RESTYPE_MAX LONG_MAX
+#include "fpmath.h"
+
+#if LDBL_MAX_EXP != 0x4000
+/* We also require the usual bias, min exp and expsign packing. */
+#error "Unsupported long double format"
 #endif
 
-#define RESTYPE_BITS (sizeof(RESTYPE) * 8)
+#define        BIAS    (LDBL_MAX_EXP - 1)
 
-RESTYPE
-LROUNDNAME(double x)
-{
-       u_int32_t i0, i1;
-       int e, s, shift;
-       RESTYPE res;
+static const float
+shift[2] = {
+       0x1.0p63, -0x1.0p63
+};
+static const float zero[2] = { 0.0, -0.0 };
 
-       GET_HIGH_WORD(i0, x);
-       e = i0 >> 20;
-       s = (uint32_t)e >> DBL_EXPBITS;
-       e = (e & 0x7ff) - DBL_EXP_BIAS;
+long double
+rintl(long double x)
+{
+       union IEEEl2bits u;
+       uint32_t expsign;
+       int ex, sign;
 
-       /* 1.0 x 2^-1 is the smallest number which can be rounded to 1 */
-       if (e < -1)
-               return (0);
-       /* 1.0 x 2^31 (or 2^63) is already too large */
-       if (e >= (int)RESTYPE_BITS - 1)
-               return (s ? RESTYPE_MIN : RESTYPE_MAX); /* ??? unspecified */
+       u.e = x;
+       expsign = u.xbits.expsign;
+       ex = expsign & 0x7fff;
 
-       /* >= 2^52 is already an exact integer */
-       if (e < DBL_FRACBITS) {
-               /* add 0.5, extraction below will truncate */
-               x += (s ? -0.5 : 0.5);
+       if (ex >= BIAS + LDBL_MANT_DIG - 1) {
+               if (ex == BIAS + LDBL_MAX_EXP)
+                       return (x + x); /* Inf, NaN, or unsupported format */
+               return (x);             /* finite and already an integer */
        }
+       sign = expsign >> 15;
 
-       EXTRACT_WORDS(i0, i1, x);
-       e = ((i0 >> 20) & 0x7ff) - DBL_EXP_BIAS;
-       i0 &= 0xfffff;
-       i0 |= (1 << 20);
+       /*
+        * The following code assumes that intermediate results are
+        * evaluated in long double precision. If they are evaluated in
+        * greater precision, double rounding may occur, and if they are
+        * evaluated in less precision (as on i386), results will be
+        * wildly incorrect.
+        */
+       x += shift[sign];
+       x -= shift[sign];
 
-       shift = e - DBL_FRACBITS;
-       if (shift >=0)
-               res = (shift < 32 ? (RESTYPE)i1 << shift : 0);
-       else
-               res = (shift > -32 ? i1 >> -shift : 0);
-       shift += 32;
-       if (shift >=0)
-               res |= (shift < 32 ? (RESTYPE)i0 << shift : 0);
-       else
-               res |= (shift > -32 ? i0 >> -shift : 0);
+       /*
+        * If the result is +-0, then it must have the same sign as x, but
+        * the above calculation doesn't always give this.  Fix up the sign.
+        */
+       if (ex < BIAS && x == 0.0L)
+               return (zero[sign]);
 
-       return (s ? -res : res);
+       return (x);
 }
index 72a726c..5977e91 100644 (file)
@@ -23,7 +23,7 @@
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
- * $NetBSD: s_round.c,v 1.2 2007/08/21 20:10:27 drochner Exp $
+ * FreeBSD SVN: 153017 (2005-12-02)
  */
 
 #include <math.h>
@@ -32,21 +32,18 @@ double
 round(double x)
 {
        double t;
-       int i;
 
-       i = fpclassify(x);
-       if (i == FP_INFINITE || i == FP_NAN)
+       if (!isfinite(x))
                return (x);
 
        if (x >= 0.0) {
                t = floor(x);
-               if (x - t >= 0.5)
+               if (t - x <= -0.5)
                        t += 1.0;
                return (t);
        } else {
-               x = -x;
-               t = floor(x);
-               if (x - t >= 0.5)
+               t = floor(-x);
+               if (t + x <= -0.5)
                        t += 1.0;
                return (-t);
        }
index 734a8d8..2572872 100644 (file)
@@ -23,7 +23,7 @@
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
- * $NetBSD: s_roundf.c,v 1.2 2007/08/21 20:10:27 drochner Exp $
+ * FreeBSD SVN: 153017 (2005-12-02)
  */
 
 #include <math.h>
@@ -32,21 +32,18 @@ float
 roundf(float x)
 {
        float t;
-       int i;
 
-       i = fpclassify(x);
-       if (i == FP_INFINITE || i == FP_NAN)
+       if (!isfinite(x))
                return (x);
 
        if (x >= 0.0) {
                t = floorf(x);
-               if (x - t >= 0.5)
+               if (t - x <= -0.5)
                        t += 1.0;
                return (t);
        } else {
-               x = -x;
-               t = floorf(x);
-               if (x - t >= 0.5)
+               t = floorf(-x);
+               if (t + x <= -0.5)
                        t += 1.0;
                return (-t);
        }
similarity index 85%
copy from lib/libm/src/s_round.c
copy to lib/libm/src/s_roundl.c
index 72a726c..07383f5 100644 (file)
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
- * $NetBSD: s_round.c,v 1.2 2007/08/21 20:10:27 drochner Exp $
+  * FreeBSD SVN: 153017 (2005-12-02)
  */
 
 #include <math.h>
 
-double
-round(double x)
+long double
+roundl(long double x)
 {
-       double t;
-       int i;
+       long double t;
 
-       i = fpclassify(x);
-       if (i == FP_INFINITE || i == FP_NAN)
+       if (!isfinite(x))
                return (x);
 
        if (x >= 0.0) {
-               t = floor(x);
-               if (x - t >= 0.5)
+               t = floorl(x);
+               if (t - x <= -0.5)
                        t += 1.0;
                return (t);
        } else {
-               x = -x;
-               t = floor(x);
-               if (x - t >= 0.5)
+               t = floorl(-x);
+               if (t + x <= -0.5)
                        t += 1.0;
                return (-t);
        }
similarity index 69%
copy from lib/libm/src/s_nearbyint.c
copy to lib/libm/src/s_scalbln.c
index 58056e5..dcaa140 100644 (file)
  * 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 SVN: 143219 (2005-03-07)
  */
 
-#include <sys/cdefs.h>
-
-#include <fenv.h>
+#include <limits.h>
 #include <math.h>
 
-/*
- * We save and restore the floating-point environment to avoid raising
- * an inexact exception.  We can get away with using fesetenv()
- * instead of feclearexcept()/feupdateenv() to restore the environment
- * because the only exception defined for rint() is overflow, and
- * rounding can't overflow as long as emax >= p.
- */
-#define        DECL(type, fn, rint)    \
-type                           \
-fn(type x)                     \
-{                              \
-       type ret;               \
-       fenv_t env;             \
-                               \
-       fegetenv(&env);         \
-       ret = rint(x);          \
-       fesetenv(&env);         \
-       return (ret);           \
+double
+scalbln (double x, long n)
+{
+       int in;
+
+       in = (int)n;
+       if (in != n) {
+               if (n > 0)
+                       in = INT_MAX;
+               else
+                       in = INT_MIN;
+       }
+       return (scalbn(x, in));
 }
 
-DECL(double, nearbyint, rint)
-DECL(float, nearbyintf, rintf)
+float
+scalblnf (float x, long n)
+{
+       int in;
+
+       in = (int)n;
+       if (in != n) {
+               if (n > 0)
+                       in = INT_MAX;
+               else
+                       in = INT_MIN;
+       }
+       return (scalbnf(x, in));
+}
+
+long double
+scalblnl (long double x, long n)
+{
+       int in;
+
+       in = (int)n;
+       if (in != n) {
+               if (n > 0)
+                       in = INT_MAX;
+               else
+                       in = INT_MIN;
+       }
+       return (scalbnl(x, (int)n));
+}
index ed4d64a..fe530f4 100644 (file)
@@ -1,5 +1,6 @@
 /* s_sinf.c -- float version of s_sin.c.
  * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ * Optimized by Bruce D. Evans.
  */
 
 /*
  * software is freely granted, provided that this notice
  * is preserved.
  * ====================================================
- *
- * $NetBSD: s_sinf.c,v 1.8 2007/08/20 16:01:39 drochner Exp $
+ * FreeBSD SVN: 176569 (2008-02-25)
  */
 
 #include <math.h>
+#define        INLINE_KERNEL_COSDF
+#define        INLINE_KERNEL_SINDF
+#define INLINE_REM_PIO2F
 #include "math_private.h"
+#include "e_rem_pio2f.c"
+#include "k_cosf.c"
+#include "k_sinf.c"
+
+/* Small multiples of pi/2 rounded to double precision. */
+static const double
+s1pio2 = 1*M_PI_2,                     /* 0x3FF921FB, 0x54442D18 */
+s2pio2 = 2*M_PI_2,                     /* 0x400921FB, 0x54442D18 */
+s3pio2 = 3*M_PI_2,                     /* 0x4012D97C, 0x7F3321D2 */
+s4pio2 = 4*M_PI_2;                     /* 0x401921FB, 0x54442D18 */
 
 float
 sinf(float x)
 {
-       float y[2],z=0.0;
-       int32_t n, ix;
+       double y;
+       int32_t n, hx, ix;
 
-       GET_FLOAT_WORD(ix,x);
+       GET_FLOAT_WORD(hx,x);
+       ix = hx & 0x7fffffff;
 
-    /* |x| ~< pi/4 */
-       ix &= 0x7fffffff;
-       if(ix <= 0x3f490fd8) return __kernel_sinf(x,z,0);
+       if(ix <= 0x3f490fda) {          /* |x| ~<= pi/4 */
+           if(ix<0x39800000)           /* |x| < 2**-12 */
+               if(((int)x)==0) return x;       /* x with inexact if x != 0 */
+           return __kernel_sindf(x);
+       }
+       if(ix<=0x407b53d1) {            /* |x| ~<= 5*pi/4 */
+           if(ix<=0x4016cbe3) {        /* |x| ~<= 3pi/4 */
+               if(hx>0)
+                   return __kernel_cosdf(x - s1pio2);
+               else
+                   return -__kernel_cosdf(x + s1pio2);
+           } else
+               return __kernel_sindf((hx > 0 ? s2pio2 : -s2pio2) - x);
+       }
+       if(ix<=0x40e231d5) {            /* |x| ~<= 9*pi/4 */
+           if(ix<=0x40afeddf) {        /* |x| ~<= 7*pi/4 */
+               if(hx>0)
+                   return -__kernel_cosdf(x - s3pio2);
+               else
+                   return __kernel_cosdf(x + s3pio2);
+           } else
+               return __kernel_sindf(x + (hx > 0 ? -s4pio2 : s4pio2));
+       }
 
     /* sin(Inf or NaN) is NaN */
        else if (ix>=0x7f800000) return x-x;
 
-    /* argument reduction needed */
+    /* general argument reduction needed */
        else {
-           n = __libm_rem_pio2f(x,y);
+           n = __libm_rem_pio2f(x,&y);
            switch(n&3) {
-               case 0: return  __kernel_sinf(y[0],y[1],1);
-               case 1: return  __kernel_cosf(y[0],y[1]);
-               case 2: return -__kernel_sinf(y[0],y[1],1);
+               case 0: return  __kernel_sindf(y);
+               case 1: return  __kernel_cosdf(y);
+               case 2: return  __kernel_sindf(-y);
                default:
-                       return -__kernel_cosf(y[0],y[1]);
+                       return -__kernel_cosdf(y);
            }
        }
 }
similarity index 59%
copy from lib/libm/src/s_roundf.c
copy to lib/libm/src/s_sinl.c
index 734a8d8..9bbe6a7 100644 (file)
@@ -1,5 +1,5 @@
 /*-
- * Copyright (c) 2003, Steven G. Kargl
+ * Copyright (c) 2007 Steven G. Kargl
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
- * $NetBSD: s_roundf.c,v 1.2 2007/08/21 20:10:27 drochner Exp $
+ * FreeBSD SVN: 222508 (2011-05-30)
  */
 
 #include <math.h>
+#include "math_private.h"
+#include "e_rem_pio2l.h"
 
-float
-roundf(float x)
+long double
+sinl(long double x)
 {
-       float t;
-       int i;
+       union IEEEl2bits z;
+       int e0, s;
+       long double y[2];
+       long double hi, lo;
 
-       i = fpclassify(x);
-       if (i == FP_INFINITE || i == FP_NAN)
+       z.e = x;
+       s = z.bits.sign;
+       z.bits.sign = 0;
+
+       /* If x = +-0 or x is a subnormal number, then sin(x) = x */
+       if (z.bits.exp == 0)
                return (x);
 
-       if (x >= 0.0) {
-               t = floorf(x);
-               if (x - t >= 0.5)
-                       t += 1.0;
-               return (t);
-       } else {
-               x = -x;
-               t = floorf(x);
-               if (x - t >= 0.5)
-                       t += 1.0;
-               return (-t);
+       /* If x = NaN or Inf, then sin(x) = NaN. */
+       if (z.bits.exp == 32767)
+               return ((x - x) / (x - x));
+
+       /* Optimize the case where x is already within range. */
+       if (z.e < M_PI_4) {
+               hi = __kernel_sinl(z.e, 0, 0);
+               return  (s ? -hi : hi);
+       }
+
+       e0 = __libm_rem_pio2l(x, y);
+       hi = y[0];
+       lo = y[1];
+
+       switch (e0 & 3) {
+       case 0:
+           hi = __kernel_sinl(hi, lo, 1);
+           break;
+       case 1:
+           hi = __kernel_cosl(hi, lo);
+           break;
+       case 2:
+           hi = - __kernel_sinl(hi, lo, 1);
+           break;
+       case 3:
+           hi = - __kernel_cosl(hi, lo);
+           break;
        }
+
+       return (hi);
 }
index 00265ff..2531ba8 100644 (file)
@@ -1,5 +1,6 @@
 /* s_tanf.c -- float version of s_tan.c.
  * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ * Optimized by Bruce D. Evans.
  */
 
 /*
  * software is freely granted, provided that this notice
  * is preserved.
  * ====================================================
- *
- * $NetBSD: s_tanf.c,v 1.7 2002/05/26 22:01:58 wiz Exp $
- * $DragonFly: src/lib/libm/src/s_tanf.c,v 1.1 2005/07/26 21:15:20 joerg Exp $
+ * FreeBSD SVN: 176569 (2008-02-25)
  */
 
 #include <math.h>
+#define        INLINE_KERNEL_TANDF
+#define INLINE_REM_PIO2F
 #include "math_private.h"
+#include "e_rem_pio2f.c"
+#include "k_tanf.c"
+
+/* Small multiples of pi/2 rounded to double precision. */
+static const double
+t1pio2 = 1*M_PI_2,                     /* 0x3FF921FB, 0x54442D18 */
+t2pio2 = 2*M_PI_2,                     /* 0x400921FB, 0x54442D18 */
+t3pio2 = 3*M_PI_2,                     /* 0x4012D97C, 0x7F3321D2 */
+t4pio2 = 4*M_PI_2;                     /* 0x401921FB, 0x54442D18 */
 
 float
 tanf(float x)
 {
-       float y[2],z=0.0;
-       int32_t n, ix;
+       double y;
+       int32_t n, hx, ix;
 
-       GET_FLOAT_WORD(ix,x);
+       GET_FLOAT_WORD(hx,x);
+       ix = hx & 0x7fffffff;
 
-    /* |x| ~< pi/4 */
-       ix &= 0x7fffffff;
-       if(ix <= 0x3f490fda) return __kernel_tanf(x,z,1);
+       if(ix <= 0x3f490fda) {          /* |x| ~<= pi/4 */
+           if(ix<0x39800000)           /* |x| < 2**-12 */
+               if(((int)x)==0) return x;       /* x with inexact if x != 0 */
+           return __kernel_tandf(x,1);
+       }
+       if(ix<=0x407b53d1) {            /* |x| ~<= 5*pi/4 */
+           if(ix<=0x4016cbe3)          /* |x| ~<= 3pi/4 */
+               return __kernel_tandf(x + (hx>0 ? -t1pio2 : t1pio2), -1);
+           else
+               return __kernel_tandf(x + (hx>0 ? -t2pio2 : t2pio2), 1);
+       }
+       if(ix<=0x40e231d5) {            /* |x| ~<= 9*pi/4 */
+           if(ix<=0x40afeddf)          /* |x| ~<= 7*pi/4 */
+               return __kernel_tandf(x + (hx>0 ? -t3pio2 : t3pio2), -1);
+           else
+               return __kernel_tandf(x + (hx>0 ? -t4pio2 : t4pio2), 1);
+       }
 
     /* tan(Inf or NaN) is NaN */
-       else if (ix>=0x7f800000) return x-x;            /* NaN */
+       else if (ix>=0x7f800000) return x-x;
 
-    /* argument reduction needed */
+    /* general argument reduction needed */
        else {
-           n = __libm_rem_pio2f(x,y);
-           return __kernel_tanf(y[0],y[1],1-((n&1)<<1)); /*