OSDN Git Service

PR libfortran/47970
[pf3gnuchains/gcc-fork.git] / libgfortran / intrinsics / c99_functions.c
index 13d5503..a95f09a 100644 (file)
@@ -1,31 +1,26 @@
 /* Implementation of various C99 functions 
-   Copyright (C) 2004 Free Software Foundation, Inc.
+   Copyright (C) 2004, 2009, 2010 Free Software Foundation, Inc.
 
 This file is part of the GNU Fortran 95 runtime library (libgfortran).
 
 Libgfortran is free software; you can redistribute it and/or
 modify it under the terms of the GNU General Public
 License as published by the Free Software Foundation; either
-version 2 of the License, or (at your option) any later version.
-
-In addition to the permissions in the GNU General Public License, the
-Free Software Foundation gives you unlimited permission to link the
-compiled version of this file into combinations with other programs,
-and to distribute those combinations without any restriction coming
-from the use of this file.  (The General Public License restrictions
-do apply in other respects; for example, they cover modification of
-the file, and distribution when not linked into a combine
-executable.)
+version 3 of the License, or (at your option) any later version.
 
 Libgfortran is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.
 
-You should have received a copy of the GNU General Public
-License along with libgfortran; see the file COPYING.  If not,
-write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
-Boston, MA 02110-1301, USA.  */
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+<http://www.gnu.org/licenses/>.  */
 
 #include "config.h"
 
@@ -59,19 +54,20 @@ Boston, MA 02110-1301, USA.  */
 #define cabsl __gfc_cabsl
 #endif
 
-/* Prototypes to silence -Wstrict-prototypes -Wmissing-prototypes.  */
-
-float cabsf(float complex);
-double cabs(double complex);
-long double cabsl(long double complex);
-
-float cargf(float complex);
-double carg(double complex);
-long double cargl(long double complex);
+/* On a C99 system "I" (with I*I = -1) should be defined in complex.h;
+   if not, we define a fallback version here.  */
+#ifndef I
+# if defined(_Imaginary_I)
+#   define I _Imaginary_I
+# elif defined(_Complex_I)
+#   define I _Complex_I
+# else
+#   define I (1.0fi)
+# endif
+#endif
 
-float complex clog10f(float complex);
-double complex clog10(double complex);
-long double complex clog10l(long double complex);
+/* Prototypes are included to silence -Wstrict-prototypes
+   -Wmissing-prototypes.  */
 
 
 /* Wrappers for systems without the various C99 single precision Bessel
@@ -79,7 +75,7 @@ long double complex clog10l(long double complex);
 
 #if defined(HAVE_J0) && ! defined(HAVE_J0F)
 #define HAVE_J0F 1
-extern float j0f (float);
+float j0f (float);
 
 float
 j0f (float x)
@@ -90,7 +86,7 @@ j0f (float x)
 
 #if defined(HAVE_J1) && !defined(HAVE_J1F)
 #define HAVE_J1F 1
-extern float j1f (float);
+float j1f (float);
 
 float j1f (float x)
 {
@@ -100,7 +96,7 @@ float j1f (float x)
 
 #if defined(HAVE_JN) && !defined(HAVE_JNF)
 #define HAVE_JNF 1
-extern float jnf (int, float);
+float jnf (int, float);
 
 float
 jnf (int n, float x)
@@ -111,7 +107,7 @@ jnf (int n, float x)
 
 #if defined(HAVE_Y0) && !defined(HAVE_Y0F)
 #define HAVE_Y0F 1
-extern float y0f (float);
+float y0f (float);
 
 float
 y0f (float x)
@@ -122,7 +118,7 @@ y0f (float x)
 
 #if defined(HAVE_Y1) && !defined(HAVE_Y1F)
 #define HAVE_Y1F 1
-extern float y1f (float);
+float y1f (float);
 
 float
 y1f (float x)
@@ -133,7 +129,7 @@ y1f (float x)
 
 #if defined(HAVE_YN) && !defined(HAVE_YNF)
 #define HAVE_YNF 1
-extern float ynf (int, float);
+float ynf (int, float);
 
 float
 ynf (int n, float x)
@@ -147,7 +143,7 @@ ynf (int n, float x)
 
 #if defined(HAVE_ERF) && !defined(HAVE_ERFF)
 #define HAVE_ERFF 1
-extern float erff (float);
+float erff (float);
 
 float
 erff (float x)
@@ -158,7 +154,7 @@ erff (float x)
 
 #if defined(HAVE_ERFC) && !defined(HAVE_ERFCF)
 #define HAVE_ERFCF 1
-extern float erfcf (float);
+float erfcf (float);
 
 float
 erfcf (float x)
@@ -170,14 +166,18 @@ erfcf (float x)
 
 #ifndef HAVE_ACOSF
 #define HAVE_ACOSF 1
+float acosf (float x);
+
 float
-acosf(float x)
+acosf (float x)
 {
-  return (float) acos(x);
+  return (float) acos (x);
 }
 #endif
 
 #if HAVE_ACOSH && !HAVE_ACOSHF
+float acoshf (float x);
+
 float
 acoshf (float x)
 {
@@ -187,14 +187,18 @@ acoshf (float x)
 
 #ifndef HAVE_ASINF
 #define HAVE_ASINF 1
+float asinf (float x);
+
 float
-asinf(float x)
+asinf (float x)
 {
-  return (float) asin(x);
+  return (float) asin (x);
 }
 #endif
 
 #if HAVE_ASINH && !HAVE_ASINHF
+float asinhf (float x);
+
 float
 asinhf (float x)
 {
@@ -204,23 +208,29 @@ asinhf (float x)
 
 #ifndef HAVE_ATAN2F
 #define HAVE_ATAN2F 1
+float atan2f (float y, float x);
+
 float
-atan2f(float y, float x)
+atan2f (float y, float x)
 {
-  return (float) atan2(y, x);
+  return (float) atan2 (y, x);
 }
 #endif
 
 #ifndef HAVE_ATANF
 #define HAVE_ATANF 1
+float atanf (float x);
+
 float
-atanf(float x)
+atanf (float x)
 {
-  return (float) atan(x);
+  return (float) atan (x);
 }
 #endif
 
 #if HAVE_ATANH && !HAVE_ATANHF
+float atanhf (float x);
+
 float
 atanhf (float x)
 {
@@ -230,69 +240,85 @@ atanhf (float x)
 
 #ifndef HAVE_CEILF
 #define HAVE_CEILF 1
+float ceilf (float x);
+
 float
-ceilf(float x)
+ceilf (float x)
 {
-  return (float) ceil(x);
+  return (float) ceil (x);
 }
 #endif
 
 #ifndef HAVE_COPYSIGNF
 #define HAVE_COPYSIGNF 1
+float copysignf (float x, float y);
+
 float
-copysignf(float x, float y)
+copysignf (float x, float y)
 {
-  return (float) copysign(x, y);
+  return (float) copysign (x, y);
 }
 #endif
 
 #ifndef HAVE_COSF
 #define HAVE_COSF 1
+float cosf (float x);
+
 float
-cosf(float x)
+cosf (float x)
 {
-  return (float) cos(x);
+  return (float) cos (x);
 }
 #endif
 
 #ifndef HAVE_COSHF
 #define HAVE_COSHF 1
+float coshf (float x);
+
 float
-coshf(float x)
+coshf (float x)
 {
-  return (float) cosh(x);
+  return (float) cosh (x);
 }
 #endif
 
 #ifndef HAVE_EXPF
 #define HAVE_EXPF 1
+float expf (float x);
+
 float
-expf(float x)
+expf (float x)
 {
-  return (float) exp(x);
+  return (float) exp (x);
 }
 #endif
 
 #ifndef HAVE_FABSF
 #define HAVE_FABSF 1
+float fabsf (float x);
+
 float
-fabsf(float x)
+fabsf (float x)
 {
-  return (float) fabs(x);
+  return (float) fabs (x);
 }
 #endif
 
 #ifndef HAVE_FLOORF
 #define HAVE_FLOORF 1
+float floorf (float x);
+
 float
-floorf(float x)
+floorf (float x)
 {
-  return (float) floor(x);
+  return (float) floor (x);
 }
 #endif
 
 #ifndef HAVE_FMODF
 #define HAVE_FMODF 1
+float fmodf (float x, float y);
+
 float
 fmodf (float x, float y)
 {
@@ -302,111 +328,135 @@ fmodf (float x, float y)
 
 #ifndef HAVE_FREXPF
 #define HAVE_FREXPF 1
+float frexpf (float x, int *exp);
+
 float
-frexpf(float x, int *exp)
+frexpf (float x, int *exp)
 {
-  return (float) frexp(x, exp);
+  return (float) frexp (x, exp);
 }
 #endif
 
 #ifndef HAVE_HYPOTF
 #define HAVE_HYPOTF 1
+float hypotf (float x, float y);
+
 float
-hypotf(float x, float y)
+hypotf (float x, float y)
 {
-  return (float) hypot(x, y);
+  return (float) hypot (x, y);
 }
 #endif
 
 #ifndef HAVE_LOGF
 #define HAVE_LOGF 1
+float logf (float x);
+
 float
-logf(float x)
+logf (float x)
 {
-  return (float) log(x);
+  return (float) log (x);
 }
 #endif
 
 #ifndef HAVE_LOG10F
 #define HAVE_LOG10F 1
+float log10f (float x);
+
 float
-log10f(float x)
+log10f (float x)
 {
-  return (float) log10(x);
+  return (float) log10 (x);
 }
 #endif
 
 #ifndef HAVE_SCALBN
 #define HAVE_SCALBN 1
+double scalbn (double x, int y);
+
 double
-scalbn(double x, int y)
+scalbn (double x, int y)
 {
 #if (FLT_RADIX == 2) && defined(HAVE_LDEXP)
   return ldexp (x, y);
 #else
-  return x * pow(FLT_RADIX, y);
+  return x * pow (FLT_RADIX, y);
 #endif
 }
 #endif
 
 #ifndef HAVE_SCALBNF
 #define HAVE_SCALBNF 1
+float scalbnf (float x, int y);
+
 float
-scalbnf(float x, int y)
+scalbnf (float x, int y)
 {
-  return (float) scalbn(x, y);
+  return (float) scalbn (x, y);
 }
 #endif
 
 #ifndef HAVE_SINF
 #define HAVE_SINF 1
+float sinf (float x);
+
 float
-sinf(float x)
+sinf (float x)
 {
-  return (float) sin(x);
+  return (float) sin (x);
 }
 #endif
 
 #ifndef HAVE_SINHF
 #define HAVE_SINHF 1
+float sinhf (float x);
+
 float
-sinhf(float x)
+sinhf (float x)
 {
-  return (float) sinh(x);
+  return (float) sinh (x);
 }
 #endif
 
 #ifndef HAVE_SQRTF
 #define HAVE_SQRTF 1
+float sqrtf (float x);
+
 float
-sqrtf(float x)
+sqrtf (float x)
 {
-  return (float) sqrt(x);
+  return (float) sqrt (x);
 }
 #endif
 
 #ifndef HAVE_TANF
 #define HAVE_TANF 1
+float tanf (float x);
+
 float
-tanf(float x)
+tanf (float x)
 {
-  return (float) tan(x);
+  return (float) tan (x);
 }
 #endif
 
 #ifndef HAVE_TANHF
 #define HAVE_TANHF 1
+float tanhf (float x);
+
 float
-tanhf(float x)
+tanhf (float x)
 {
-  return (float) tanh(x);
+  return (float) tanh (x);
 }
 #endif
 
 #ifndef HAVE_TRUNC
 #define HAVE_TRUNC 1
+double trunc (double x);
+
 double
-trunc(double x)
+trunc (double x)
 {
   if (!isfinite (x))
     return x;
@@ -420,8 +470,10 @@ trunc(double x)
 
 #ifndef HAVE_TRUNCF
 #define HAVE_TRUNCF 1
+float truncf (float x);
+
 float
-truncf(float x)
+truncf (float x)
 {
   return (float) trunc (x);
 }
@@ -432,15 +484,17 @@ truncf(float x)
 /* This is a portable implementation of nextafterf that is intended to be
    independent of the floating point format or its in memory representation.
    This implementation works correctly with denormalized values.  */
+float nextafterf (float x, float y);
+
 float
-nextafterf(float x, float y)
+nextafterf (float x, float y)
 {
   /* This variable is marked volatile to avoid excess precision problems
      on some platforms, including IA-32.  */
   volatile float delta;
   float absx, denorm_min;
 
-  if (isnan(x) || isnan(y))
+  if (isnan (x) || isnan (y))
     return x + y;
   if (x == y)
     return x;
@@ -491,27 +545,63 @@ nextafterf(float x, float y)
 #endif
 
 
+#if !defined(HAVE_POWF) || defined(HAVE_BROKEN_POWF)
 #ifndef HAVE_POWF
 #define HAVE_POWF 1
+#endif
+float powf (float x, float y);
+
 float
-powf(float x, float y)
+powf (float x, float y)
+{
+  return (float) pow (x, y);
+}
+#endif
+
+
+#ifndef HAVE_ROUND
+#define HAVE_ROUND 1
+/* Round to nearest integral value.  If the argument is halfway between two
+   integral values then round away from zero.  */
+double round (double x);
+
+double
+round (double x)
 {
-  return (float) pow(x, y);
+   double t;
+   if (!isfinite (x))
+     return (x);
+
+   if (x >= 0.0) 
+    {
+      t = floor (x);
+      if (t - x <= -0.5)
+       t += 1.0;
+      return (t);
+    } 
+   else 
+    {
+      t = floor (-x);
+      if (t + x <= -0.5)
+       t += 1.0;
+      return (-t);
+    }
 }
 #endif
 
-/* Note that if fpclassify is not defined, then NaN is not handled */
 
 /* Algorithm by Steven G. Kargl.  */
 
 #if !defined(HAVE_ROUNDL)
 #define HAVE_ROUNDL 1
+long double roundl (long double x);
+
 #if defined(HAVE_CEILL)
 /* Round to nearest integral value.  If the argument is halfway between two
    integral values then round away from zero.  */
 
 long double
-roundl(long double x)
+roundl (long double x)
 {
    long double t;
    if (!isfinite (x))
@@ -519,14 +609,14 @@ roundl(long double x)
 
    if (x >= 0.0)
     {
-      t = ceill(x);
+      t = ceill (x);
       if (t - x > 0.5)
        t -= 1.0;
       return (t);
     } 
    else 
     {
-      t = ceill(-x);
+      t = ceill (-x);
       if (t + x > 0.5)
        t -= 1.0;
       return (-t);
@@ -536,12 +626,12 @@ roundl(long double x)
 
 /* Poor version of roundl for system that don't have ceill.  */
 long double
-roundl(long double x)
+roundl (long double x)
 {
   if (x > DBL_MAX || x < -DBL_MAX)
     {
 #ifdef HAVE_NEXTAFTERL
-      static long double prechalf = nexafterl (0.5L, LDBL_MAX);
+      long double prechalf = nextafterl (0.5L, LDBL_MAX);
 #else
       static long double prechalf = 0.5L;
 #endif
@@ -549,48 +639,20 @@ roundl(long double x)
     }
   else
     /* Use round().  */
-    return round((double) x);
+    return round ((double) x);
 }
 
 #endif
 #endif
 
-#ifndef HAVE_ROUND
-#define HAVE_ROUND 1
-/* Round to nearest integral value.  If the argument is halfway between two
-   integral values then round away from zero.  */
-
-double
-round(double x)
-{
-   double t;
-   if (!isfinite (x))
-     return (x);
-
-   if (x >= 0.0) 
-    {
-      t = ceil(x);
-      if (t - x > 0.5)
-       t -= 1.0;
-      return (t);
-    } 
-   else 
-    {
-      t = ceil(-x);
-      if (t + x > 0.5)
-       t -= 1.0;
-      return (-t);
-    }
-}
-#endif
-
 #ifndef HAVE_ROUNDF
 #define HAVE_ROUNDF 1
 /* Round to nearest integral value.  If the argument is halfway between two
    integral values then round away from zero.  */
+float roundf (float x);
 
 float
-roundf(float x)
+roundf (float x)
 {
    float t;
    if (!isfinite (x))
@@ -598,16 +660,16 @@ roundf(float x)
 
    if (x >= 0.0) 
     {
-      t = ceilf(x);
-      if (t - x 0.5)
-       t -= 1.0;
+      t = floorf (x);
+      if (t - x <= -0.5)
+       t += 1.0;
       return (t);
     } 
    else 
     {
-      t = ceilf(-x);
-      if (t + x 0.5)
-       t -= 1.0;
+      t = floorf (-x);
+      if (t + x <= -0.5)
+       t += 1.0;
       return (-t);
     }
 }
@@ -618,6 +680,8 @@ roundf(float x)
 
 #if !defined(HAVE_LROUNDF) && defined(HAVE_ROUNDF)
 #define HAVE_LROUNDF 1
+long int lroundf (float x);
+
 long int
 lroundf (float x)
 {
@@ -627,6 +691,8 @@ lroundf (float x)
 
 #if !defined(HAVE_LROUND) && defined(HAVE_ROUND)
 #define HAVE_LROUND 1
+long int lround (double x);
+
 long int
 lround (double x)
 {
@@ -636,6 +702,8 @@ lround (double x)
 
 #if !defined(HAVE_LROUNDL) && defined(HAVE_ROUNDL)
 #define HAVE_LROUNDL 1
+long int lroundl (long double x);
+
 long int
 lroundl (long double x)
 {
@@ -645,6 +713,8 @@ lroundl (long double x)
 
 #if !defined(HAVE_LLROUNDF) && defined(HAVE_ROUNDF)
 #define HAVE_LLROUNDF 1
+long long int llroundf (float x);
+
 long long int
 llroundf (float x)
 {
@@ -654,6 +724,8 @@ llroundf (float x)
 
 #if !defined(HAVE_LLROUND) && defined(HAVE_ROUND)
 #define HAVE_LLROUND 1
+long long int llround (double x);
+
 long long int
 llround (double x)
 {
@@ -663,6 +735,8 @@ llround (double x)
 
 #if !defined(HAVE_LLROUNDL) && defined(HAVE_ROUNDL)
 #define HAVE_LLROUNDL 1
+long long int llroundl (long double x);
+
 long long int
 llroundl (long double x)
 {
@@ -675,8 +749,10 @@ llroundl (long double x)
 #define HAVE_LOG10L 1
 /* log10 function for long double variables. The version provided here
    reduces the argument until it fits into a double, then use log10.  */
+long double log10l (long double x);
+
 long double
-log10l(long double x)
+log10l (long double x)
 {
 #if LDBL_MAX_EXP > DBL_MAX_EXP
   if (x > DBL_MAX)
@@ -702,7 +778,7 @@ log10l(long double x)
       if (x < 0x1p-4093L) { p2_result += 4093; x /= 0x1p-4093L; }
       if (x < 0x1p-2045L) { p2_result += 2045; x /= 0x1p-2045L; }
       if (x < 0x1p-1021L) { p2_result += 1021; x /= 0x1p-1021L; }
-      val = fabs(log10 ((double) x));
+      val = fabs (log10 ((double) x));
       return (- val - p2_result * .30102999566398119521373889472449302L);
     }
 #endif
@@ -713,6 +789,8 @@ log10l(long double x)
 
 #ifndef HAVE_FLOORL
 #define HAVE_FLOORL 1
+long double floorl (long double x);
+
 long double
 floorl (long double x)
 {
@@ -739,6 +817,8 @@ floorl (long double x)
 
 #ifndef HAVE_FMODL
 #define HAVE_FMODL 1
+long double fmodl (long double x, long double y);
+
 long double
 fmodl (long double x, long double y)
 {
@@ -754,6 +834,8 @@ fmodl (long double x, long double y)
 
 #if !defined(HAVE_CABSF)
 #define HAVE_CABSF 1
+float cabsf (float complex z);
+
 float
 cabsf (float complex z)
 {
@@ -763,6 +845,8 @@ cabsf (float complex z)
 
 #if !defined(HAVE_CABS)
 #define HAVE_CABS 1
+double cabs (double complex z);
+
 double
 cabs (double complex z)
 {
@@ -772,6 +856,8 @@ cabs (double complex z)
 
 #if !defined(HAVE_CABSL) && defined(HAVE_HYPOTL)
 #define HAVE_CABSL 1
+long double cabsl (long double complex z);
+
 long double
 cabsl (long double complex z)
 {
@@ -782,6 +868,8 @@ cabsl (long double complex z)
 
 #if !defined(HAVE_CARGF)
 #define HAVE_CARGF 1
+float cargf (float complex z);
+
 float
 cargf (float complex z)
 {
@@ -791,6 +879,8 @@ cargf (float complex z)
 
 #if !defined(HAVE_CARG)
 #define HAVE_CARG 1
+double carg (double complex z);
+
 double
 carg (double complex z)
 {
@@ -800,6 +890,8 @@ carg (double complex z)
 
 #if !defined(HAVE_CARGL) && defined(HAVE_ATAN2L)
 #define HAVE_CARGL 1
+long double cargl (long double complex z);
+
 long double
 cargl (long double complex z)
 {
@@ -811,6 +903,8 @@ cargl (long double complex z)
 /* exp(z) = exp(a)*(cos(b) + i sin(b))  */
 #if !defined(HAVE_CEXPF)
 #define HAVE_CEXPF 1
+float complex cexpf (float complex z);
+
 float complex
 cexpf (float complex z)
 {
@@ -826,6 +920,8 @@ cexpf (float complex z)
 
 #if !defined(HAVE_CEXP)
 #define HAVE_CEXP 1
+double complex cexp (double complex z);
+
 double complex
 cexp (double complex z)
 {
@@ -841,6 +937,8 @@ cexp (double complex z)
 
 #if !defined(HAVE_CEXPL) && defined(HAVE_COSL) && defined(HAVE_SINL) && defined(EXPL)
 #define HAVE_CEXPL 1
+long double complex cexpl (long double complex z);
+
 long double complex
 cexpl (long double complex z)
 {
@@ -858,6 +956,8 @@ cexpl (long double complex z)
 /* log(z) = log (cabs(z)) + i*carg(z)  */
 #if !defined(HAVE_CLOGF)
 #define HAVE_CLOGF 1
+float complex clogf (float complex z);
+
 float complex
 clogf (float complex z)
 {
@@ -870,6 +970,8 @@ clogf (float complex z)
 
 #if !defined(HAVE_CLOG)
 #define HAVE_CLOG 1
+double complex clog (double complex z);
+
 double complex
 clog (double complex z)
 {
@@ -882,6 +984,8 @@ clog (double complex z)
 
 #if !defined(HAVE_CLOGL) && defined(HAVE_LOGL) && defined(HAVE_CABSL) && defined(HAVE_CARGL)
 #define HAVE_CLOGL 1
+long double complex clogl (long double complex z);
+
 long double complex
 clogl (long double complex z)
 {
@@ -896,6 +1000,8 @@ clogl (long double complex z)
 /* log10(z) = log10 (cabs(z)) + i*carg(z)  */
 #if !defined(HAVE_CLOG10F)
 #define HAVE_CLOG10F 1
+float complex clog10f (float complex z);
+
 float complex
 clog10f (float complex z)
 {
@@ -908,6 +1014,8 @@ clog10f (float complex z)
 
 #if !defined(HAVE_CLOG10)
 #define HAVE_CLOG10 1
+double complex clog10 (double complex z);
+
 double complex
 clog10 (double complex z)
 {
@@ -920,6 +1028,8 @@ clog10 (double complex z)
 
 #if !defined(HAVE_CLOG10L) && defined(HAVE_LOG10L) && defined(HAVE_CABSL) && defined(HAVE_CARGL)
 #define HAVE_CLOG10L 1
+long double complex clog10l (long double complex z);
+
 long double complex
 clog10l (long double complex z)
 {
@@ -934,6 +1044,8 @@ clog10l (long double complex z)
 /* pow(base, power) = cexp (power * clog (base))  */
 #if !defined(HAVE_CPOWF)
 #define HAVE_CPOWF 1
+float complex cpowf (float complex base, float complex power);
+
 float complex
 cpowf (float complex base, float complex power)
 {
@@ -943,6 +1055,8 @@ cpowf (float complex base, float complex power)
 
 #if !defined(HAVE_CPOW)
 #define HAVE_CPOW 1
+double complex cpow (double complex base, double complex power);
+
 double complex
 cpow (double complex base, double complex power)
 {
@@ -952,6 +1066,8 @@ cpow (double complex base, double complex power)
 
 #if !defined(HAVE_CPOWL) && defined(HAVE_CEXPL) && defined(HAVE_CLOGL)
 #define HAVE_CPOWL 1
+long double complex cpowl (long double complex base, long double complex power);
+
 long double complex
 cpowl (long double complex base, long double complex power)
 {
@@ -963,6 +1079,8 @@ cpowl (long double complex base, long double complex power)
 /* sqrt(z).  Algorithm pulled from glibc.  */
 #if !defined(HAVE_CSQRTF)
 #define HAVE_CSQRTF 1
+float complex csqrtf (float complex z);
+
 float complex
 csqrtf (float complex z)
 {
@@ -1016,6 +1134,8 @@ csqrtf (float complex z)
 
 #if !defined(HAVE_CSQRT)
 #define HAVE_CSQRT 1
+double complex csqrt (double complex z);
+
 double complex
 csqrt (double complex z)
 {
@@ -1069,6 +1189,8 @@ csqrt (double complex z)
 
 #if !defined(HAVE_CSQRTL) && defined(HAVE_COPYSIGNL) && defined(HAVE_SQRTL) && defined(HAVE_FABSL) && defined(HAVE_HYPOTL)
 #define HAVE_CSQRTL 1
+long double complex csqrtl (long double complex z);
+
 long double complex
 csqrtl (long double complex z)
 {
@@ -1124,6 +1246,8 @@ csqrtl (long double complex z)
 /* sinh(a + i b) = sinh(a) cos(b) + i cosh(a) sin(b)  */
 #if !defined(HAVE_CSINHF)
 #define HAVE_CSINHF 1
+float complex csinhf (float complex a);
+
 float complex
 csinhf (float complex a)
 {
@@ -1139,6 +1263,8 @@ csinhf (float complex a)
 
 #if !defined(HAVE_CSINH)
 #define HAVE_CSINH 1
+double complex csinh (double complex a);
+
 double complex
 csinh (double complex a)
 {
@@ -1154,6 +1280,8 @@ csinh (double complex a)
 
 #if !defined(HAVE_CSINHL) && defined(HAVE_COSL) && defined(HAVE_COSHL) && defined(HAVE_SINL) && defined(HAVE_SINHL)
 #define HAVE_CSINHL 1
+long double complex csinhl (long double complex a);
+
 long double complex
 csinhl (long double complex a)
 {
@@ -1168,9 +1296,11 @@ csinhl (long double complex a)
 #endif
 
 
-/* cosh(a + i b) = cosh(a) cos(b) - i sinh(a) sin(b)  */
+/* cosh(a + i b) = cosh(a) cos(b) + i sinh(a) sin(b)  */
 #if !defined(HAVE_CCOSHF)
 #define HAVE_CCOSHF 1
+float complex ccoshf (float complex a);
+
 float complex
 ccoshf (float complex a)
 {
@@ -1179,13 +1309,15 @@ ccoshf (float complex a)
 
   r = REALPART (a);
   i = IMAGPART (a);
-  COMPLEX_ASSIGN (v, coshf (r) * cosf (i), - (sinhf (r) * sinf (i)));
+  COMPLEX_ASSIGN (v, coshf (r) * cosf (i), sinhf (r) * sinf (i));
   return v;
 }
 #endif
 
 #if !defined(HAVE_CCOSH)
 #define HAVE_CCOSH 1
+double complex ccosh (double complex a);
+
 double complex
 ccosh (double complex a)
 {
@@ -1194,13 +1326,15 @@ ccosh (double complex a)
 
   r = REALPART (a);
   i = IMAGPART (a);
-  COMPLEX_ASSIGN (v, cosh (r) * cos (i), - (sinh (r) * sin (i)));
+  COMPLEX_ASSIGN (v, cosh (r) * cos (i),  sinh (r) * sin (i));
   return v;
 }
 #endif
 
 #if !defined(HAVE_CCOSHL) && defined(HAVE_COSL) && defined(HAVE_COSHL) && defined(HAVE_SINL) && defined(HAVE_SINHL)
 #define HAVE_CCOSHL 1
+long double complex ccoshl (long double complex a);
+
 long double complex
 ccoshl (long double complex a)
 {
@@ -1209,15 +1343,17 @@ ccoshl (long double complex a)
 
   r = REALPART (a);
   i = IMAGPART (a);
-  COMPLEX_ASSIGN (v, coshl (r) * cosl (i), - (sinhl (r) * sinl (i)));
+  COMPLEX_ASSIGN (v, coshl (r) * cosl (i), sinhl (r) * sinl (i));
   return v;
 }
 #endif
 
 
-/* tanh(a + i b) = (tanh(a) + i tan(b)) / (1 - i tanh(a) tan(b))  */
+/* tanh(a + i b) = (tanh(a) + i tan(b)) / (1 + i tanh(a) tan(b))  */
 #if !defined(HAVE_CTANHF)
 #define HAVE_CTANHF 1
+float complex ctanhf (float complex a);
+
 float complex
 ctanhf (float complex a)
 {
@@ -1227,7 +1363,7 @@ ctanhf (float complex a)
   rt = tanhf (REALPART (a));
   it = tanf (IMAGPART (a));
   COMPLEX_ASSIGN (n, rt, it);
-  COMPLEX_ASSIGN (d, 1, - (rt * it));
+  COMPLEX_ASSIGN (d, 1, rt * it);
 
   return n / d;
 }
@@ -1235,6 +1371,7 @@ ctanhf (float complex a)
 
 #if !defined(HAVE_CTANH)
 #define HAVE_CTANH 1
+double complex ctanh (double complex a);
 double complex
 ctanh (double complex a)
 {
@@ -1244,7 +1381,7 @@ ctanh (double complex a)
   rt = tanh (REALPART (a));
   it = tan (IMAGPART (a));
   COMPLEX_ASSIGN (n, rt, it);
-  COMPLEX_ASSIGN (d, 1, - (rt * it));
+  COMPLEX_ASSIGN (d, 1, rt * it);
 
   return n / d;
 }
@@ -1252,6 +1389,8 @@ ctanh (double complex a)
 
 #if !defined(HAVE_CTANHL) && defined(HAVE_TANL) && defined(HAVE_TANHL)
 #define HAVE_CTANHL 1
+long double complex ctanhl (long double complex a);
+
 long double complex
 ctanhl (long double complex a)
 {
@@ -1261,7 +1400,7 @@ ctanhl (long double complex a)
   rt = tanhl (REALPART (a));
   it = tanl (IMAGPART (a));
   COMPLEX_ASSIGN (n, rt, it);
-  COMPLEX_ASSIGN (d, 1, - (rt * it));
+  COMPLEX_ASSIGN (d, 1, rt * it);
 
   return n / d;
 }
@@ -1271,6 +1410,8 @@ ctanhl (long double complex a)
 /* sin(a + i b) = sin(a) cosh(b) + i cos(a) sinh(b)  */
 #if !defined(HAVE_CSINF)
 #define HAVE_CSINF 1
+float complex csinf (float complex a);
+
 float complex
 csinf (float complex a)
 {
@@ -1286,6 +1427,8 @@ csinf (float complex a)
 
 #if !defined(HAVE_CSIN)
 #define HAVE_CSIN 1
+double complex csin (double complex a);
+
 double complex
 csin (double complex a)
 {
@@ -1301,6 +1444,8 @@ csin (double complex a)
 
 #if !defined(HAVE_CSINL) && defined(HAVE_COSL) && defined(HAVE_COSHL) && defined(HAVE_SINL) && defined(HAVE_SINHL)
 #define HAVE_CSINL 1
+long double complex csinl (long double complex a);
+
 long double complex
 csinl (long double complex a)
 {
@@ -1318,6 +1463,8 @@ csinl (long double complex a)
 /* cos(a + i b) = cos(a) cosh(b) - i sin(a) sinh(b)  */
 #if !defined(HAVE_CCOSF)
 #define HAVE_CCOSF 1
+float complex ccosf (float complex a);
+
 float complex
 ccosf (float complex a)
 {
@@ -1333,6 +1480,8 @@ ccosf (float complex a)
 
 #if !defined(HAVE_CCOS)
 #define HAVE_CCOS 1
+double complex ccos (double complex a);
+
 double complex
 ccos (double complex a)
 {
@@ -1348,6 +1497,8 @@ ccos (double complex a)
 
 #if !defined(HAVE_CCOSL) && defined(HAVE_COSL) && defined(HAVE_COSHL) && defined(HAVE_SINL) && defined(HAVE_SINHL)
 #define HAVE_CCOSL 1
+long double complex ccosl (long double complex a);
+
 long double complex
 ccosl (long double complex a)
 {
@@ -1365,6 +1516,8 @@ ccosl (long double complex a)
 /* tan(a + i b) = (tan(a) + i tanh(b)) / (1 - i tan(a) tanh(b))  */
 #if !defined(HAVE_CTANF)
 #define HAVE_CTANF 1
+float complex ctanf (float complex a);
+
 float complex
 ctanf (float complex a)
 {
@@ -1382,6 +1535,8 @@ ctanf (float complex a)
 
 #if !defined(HAVE_CTAN)
 #define HAVE_CTAN 1
+double complex ctan (double complex a);
+
 double complex
 ctan (double complex a)
 {
@@ -1399,6 +1554,8 @@ ctan (double complex a)
 
 #if !defined(HAVE_CTANL) && defined(HAVE_TANL) && defined(HAVE_TANHL)
 #define HAVE_CTANL 1
+long double complex ctanl (long double complex a);
+
 long double complex
 ctanl (long double complex a)
 {
@@ -1415,10 +1572,242 @@ ctanl (long double complex a)
 #endif
 
 
+/* Complex ASIN.  Returns wrongly NaN for infinite arguments.
+   Algorithm taken from Abramowitz & Stegun.  */
+
+#if !defined(HAVE_CASINF) && defined(HAVE_CLOGF) && defined(HAVE_CSQRTF)
+#define HAVE_CASINF 1
+complex float casinf (complex float z);
+
+complex float
+casinf (complex float z)
+{
+  return -I*clogf (I*z + csqrtf (1.0f-z*z));
+}
+#endif
+
+
+#if !defined(HAVE_CASIN) && defined(HAVE_CLOG) && defined(HAVE_CSQRT)
+#define HAVE_CASIN 1
+complex double casin (complex double z);
+
+complex double
+casin (complex double z)
+{
+  return -I*clog (I*z + csqrt (1.0-z*z));
+}
+#endif
+
+
+#if !defined(HAVE_CASINL) && defined(HAVE_CLOGL) && defined(HAVE_CSQRTL)
+#define HAVE_CASINL 1
+complex long double casinl (complex long double z);
+
+complex long double
+casinl (complex long double z)
+{
+  return -I*clogl (I*z + csqrtl (1.0L-z*z));
+}
+#endif
+
+
+/* Complex ACOS.  Returns wrongly NaN for infinite arguments.
+   Algorithm taken from Abramowitz & Stegun.  */
+
+#if !defined(HAVE_CACOSF) && defined(HAVE_CLOGF) && defined(HAVE_CSQRTF)
+#define HAVE_CACOSF 1
+complex float cacosf (complex float z);
+
+complex float
+cacosf (complex float z)
+{
+  return -I*clogf (z + I*csqrtf (1.0f-z*z));
+}
+#endif
+
+
+#if !defined(HAVE_CACOS) && defined(HAVE_CLOG) && defined(HAVE_CSQRT)
+#define HAVE_CACOS 1
+complex double cacos (complex double z);
+
+complex double
+cacos (complex double z)
+{
+  return -I*clog (z + I*csqrt (1.0-z*z));
+}
+#endif
+
+
+#if !defined(HAVE_CACOSL) && defined(HAVE_CLOGL) && defined(HAVE_CSQRTL)
+#define HAVE_CACOSL 1
+complex long double cacosl (complex long double z);
+
+complex long double
+cacosl (complex long double z)
+{
+  return -I*clogl (z + I*csqrtl (1.0L-z*z));
+}
+#endif
+
+
+/* Complex ATAN.  Returns wrongly NaN for infinite arguments.
+   Algorithm taken from Abramowitz & Stegun.  */
+
+#if !defined(HAVE_CATANF) && defined(HAVE_CLOGF)
+#define HAVE_CACOSF 1
+complex float catanf (complex float z);
+
+complex float
+catanf (complex float z)
+{
+  return I*clogf ((I+z)/(I-z))/2.0f;
+}
+#endif
+
+
+#if !defined(HAVE_CATAN) && defined(HAVE_CLOG)
+#define HAVE_CACOS 1
+complex double catan (complex double z);
+
+complex double
+catan (complex double z)
+{
+  return I*clog ((I+z)/(I-z))/2.0;
+}
+#endif
+
+
+#if !defined(HAVE_CATANL) && defined(HAVE_CLOGL)
+#define HAVE_CACOSL 1
+complex long double catanl (complex long double z);
+
+complex long double
+catanl (complex long double z)
+{
+  return I*clogl ((I+z)/(I-z))/2.0L;
+}
+#endif
+
+
+/* Complex ASINH.  Returns wrongly NaN for infinite arguments.
+   Algorithm taken from Abramowitz & Stegun.  */
+
+#if !defined(HAVE_CASINHF) && defined(HAVE_CLOGF) && defined(HAVE_CSQRTF)
+#define HAVE_CASINHF 1
+complex float casinhf (complex float z);
+
+complex float
+casinhf (complex float z)
+{
+  return clogf (z + csqrtf (z*z+1.0f));
+}
+#endif
+
+
+#if !defined(HAVE_CASINH) && defined(HAVE_CLOG) && defined(HAVE_CSQRT)
+#define HAVE_CASINH 1
+complex double casinh (complex double z);
+
+complex double
+casinh (complex double z)
+{
+  return clog (z + csqrt (z*z+1.0));
+}
+#endif
+
+
+#if !defined(HAVE_CASINHL) && defined(HAVE_CLOGL) && defined(HAVE_CSQRTL)
+#define HAVE_CASINHL 1
+complex long double casinhl (complex long double z);
+
+complex long double
+casinhl (complex long double z)
+{
+  return clogl (z + csqrtl (z*z+1.0L));
+}
+#endif
+
+
+/* Complex ACOSH.  Returns wrongly NaN for infinite arguments.
+   Algorithm taken from Abramowitz & Stegun.  */
+
+#if !defined(HAVE_CACOSHF) && defined(HAVE_CLOGF) && defined(HAVE_CSQRTF)
+#define HAVE_CACOSHF 1
+complex float cacoshf (complex float z);
+
+complex float
+cacoshf (complex float z)
+{
+  return clogf (z + csqrtf (z-1.0f) * csqrtf (z+1.0f));
+}
+#endif
+
+
+#if !defined(HAVE_CACOSH) && defined(HAVE_CLOG) && defined(HAVE_CSQRT)
+#define HAVE_CACOSH 1
+complex double cacosh (complex double z);
+
+complex double
+cacosh (complex double z)
+{
+  return clog (z + csqrt (z-1.0) * csqrt (z+1.0));
+}
+#endif
+
+
+#if !defined(HAVE_CACOSHL) && defined(HAVE_CLOGL) && defined(HAVE_CSQRTL)
+#define HAVE_CACOSHL 1
+complex long double cacoshl (complex long double z);
+
+complex long double
+cacoshl (complex long double z)
+{
+  return clogl (z + csqrtl (z-1.0L) * csqrtl (z+1.0L));
+}
+#endif
+
+
+/* Complex ATANH.  Returns wrongly NaN for infinite arguments.
+   Algorithm taken from Abramowitz & Stegun.  */
+
+#if !defined(HAVE_CATANHF) && defined(HAVE_CLOGF)
+#define HAVE_CATANHF 1
+complex float catanhf (complex float z);
+
+complex float
+catanhf (complex float z)
+{
+  return clogf ((1.0f+z)/(1.0f-z))/2.0f;
+}
+#endif
+
+
+#if !defined(HAVE_CATANH) && defined(HAVE_CLOG)
+#define HAVE_CATANH 1
+complex double catanh (complex double z);
+
+complex double
+catanh (complex double z)
+{
+  return clog ((1.0+z)/(1.0-z))/2.0;
+}
+#endif
+
+#if !defined(HAVE_CATANHL) && defined(HAVE_CLOGL)
+#define HAVE_CATANHL 1
+complex long double catanhl (complex long double z);
+
+complex long double
+catanhl (complex long double z)
+{
+  return clogl ((1.0L+z)/(1.0L-z))/2.0L;
+}
+#endif
+
+
 #if !defined(HAVE_TGAMMA)
 #define HAVE_TGAMMA 1
-
-extern double tgamma (double); 
+double tgamma (double); 
 
 /* Fallback tgamma() function. Uses the algorithm from
    http://www.netlib.org/specfun/gamma and references therein.  */
@@ -1458,27 +1847,27 @@ tgamma (double x)
   static double eps = 0;
   
   if (eps == 0)
-    eps = nextafter(1., 2.) - 1.;
+    eps = nextafter (1., 2.) - 1.;
 
   parity = 0;
   fact = 1;
   n = 0;
   y = x;
 
-  if (__builtin_isnan (x))
+  if (isnan (x))
     return x;
 
   if (y <= 0)
     {
       y = -x;
-      y1 = trunc(y);
+      y1 = trunc (y);
       res = y - y1;
 
       if (res != 0)
        {
-         if (y1 != trunc(y1*0.5l)*2)
+         if (y1 != trunc (y1*0.5l)*2)
            parity = 1;
-         fact = -PI / sin(PI*res);
+         fact = -PI / sin (PI*res);
          y = y + 1;
        }
       else
@@ -1536,8 +1925,8 @@ tgamma (double x)
            sum = sum / ysq + c[i];
 
          sum = sum/y - y + SQRTPI;
-         sum = sum + (y - 0.5) * log(y);
-         res = exp(sum);
+         sum = sum + (y - 0.5) * log (y);
+         res = exp (sum);
        }
       else
        return x < 0 ? xnan : xinf;
@@ -1556,8 +1945,7 @@ tgamma (double x)
 
 #if !defined(HAVE_LGAMMA)
 #define HAVE_LGAMMA 1
-
-extern double lgamma (double); 
+double lgamma (double); 
 
 /* Fallback lgamma() function. Uses the algorithm from
    http://www.netlib.org/specfun/algama and references therein, 
@@ -1624,17 +2012,17 @@ lgamma (double y)
   double corr, res, xden, xm1, xm2, xm4, xnum, ysq;
 
   if (eps == 0)
-    eps = __builtin_nextafter(1., 2.) - 1.;
+    eps = __builtin_nextafter (1., 2.) - 1.;
 
   if ((y > 0) && (y <= xbig))
     {
       if (y <= eps)
-       res = -log(y);
+       res = -log (y);
       else if (y <= 1.5)
        {
          if (y < PNT68)
            {
-             corr = -log(y);
+             corr = -log (y);
              xm1 = y;
            }
          else
@@ -1702,7 +2090,7 @@ lgamma (double y)
                res = res / ysq + c[i];
            }
          res = res/y;
-         corr = log(y);
+         corr = log (y);
          res = res + SQRTPI - 0.5*corr;
          res = res + y*(corr-1);
        }
@@ -1727,7 +2115,7 @@ lgamma (double y)
 
 #if defined(HAVE_TGAMMA) && !defined(HAVE_TGAMMAF)
 #define HAVE_TGAMMAF 1
-extern float tgammaf (float);
+float tgammaf (float);
 
 float
 tgammaf (float x)
@@ -1738,7 +2126,7 @@ tgammaf (float x)
 
 #if defined(HAVE_LGAMMA) && !defined(HAVE_LGAMMAF)
 #define HAVE_LGAMMAF 1
-extern float lgammaf (float);
+float lgammaf (float);
 
 float
 lgammaf (float x)