summaryrefslogtreecommitdiff
path: root/winsup/mingw/mingwex/math/tgammaf.c
diff options
context:
space:
mode:
Diffstat (limited to 'winsup/mingw/mingwex/math/tgammaf.c')
-rw-r--r--winsup/mingw/mingwex/math/tgammaf.c265
1 files changed, 265 insertions, 0 deletions
diff --git a/winsup/mingw/mingwex/math/tgammaf.c b/winsup/mingw/mingwex/math/tgammaf.c
new file mode 100644
index 00000000000..38e7d75a10a
--- /dev/null
+++ b/winsup/mingw/mingwex/math/tgammaf.c
@@ -0,0 +1,265 @@
+/* gammaf.c
+ *
+ * Gamma function
+ *
+ *
+ *
+ * SYNOPSIS:
+ *
+ * float x, y, __tgammaf_r();
+ * int* sgngamf;
+ * y = __tgammaf_r( x, sgngamf );
+ *
+ * float x, y, tgammaf();
+ * y = tgammaf( x);
+ *
+ *
+ * DESCRIPTION:
+ *
+ * Returns gamma function of the argument. The result is
+ * correctly signed. In the reentrant version the sign (+1 or -1)
+ * is returned in the variable referenced by sgngamf.
+ *
+ * Arguments between 0 and 10 are reduced by recurrence and the
+ * function is approximated by a polynomial function covering
+ * the interval (2,3). Large arguments are handled by Stirling's
+ * formula. Negative arguments are made positive using
+ * a reflection formula.
+ *
+ *
+ * ACCURACY:
+ *
+ * Relative error:
+ * arithmetic domain # trials peak rms
+ * IEEE 0,-33 100,000 5.7e-7 1.0e-7
+ * IEEE -33,0 100,000 6.1e-7 1.2e-7
+ *
+ *
+ */
+
+/*
+Cephes Math Library Release 2.7: July, 1998
+Copyright 1984, 1987, 1989, 1992, 1998 by Stephen L. Moshier
+*/
+
+
+/*
+ * 26-11-2002 Modified for mingw.
+ * Danny Smith <dannysmith@users.sourceforge.net>
+ */
+
+
+#ifndef __MINGW32__
+#include "mconf.h"
+#else
+#include "cephes_mconf.h"
+#endif
+
+/* define MAXGAM 34.84425627277176174 */
+
+/* Stirling's formula for the gamma function
+ * gamma(x) = sqrt(2 pi) x^(x-.5) exp(-x) ( 1 + 1/x P(1/x) )
+ * .028 < 1/x < .1
+ * relative error < 1.9e-11
+ */
+static const float STIR[] = {
+-2.705194986674176E-003,
+ 3.473255786154910E-003,
+ 8.333331788340907E-002,
+};
+static const float MAXSTIR = 26.77;
+static const float SQTPIF = 2.50662827463100050242; /* sqrt( 2 pi ) */
+
+#ifndef __MINGW32__
+
+extern float MAXLOGF, MAXNUMF, PIF;
+
+#ifdef ANSIC
+float expf(float);
+float logf(float);
+float powf( float, float );
+float sinf(float);
+float gammaf(float);
+float floorf(float);
+static float stirf(float);
+float polevlf( float, float *, int );
+float p1evlf( float, float *, int );
+#else
+float expf(), logf(), powf(), sinf(), floorf();
+float polevlf(), p1evlf();
+static float stirf();
+#endif
+
+#else /* __MINGW32__ */
+static float stirf(float);
+#endif
+
+/* Gamma function computed by Stirling's formula,
+ * sqrt(2 pi) x^(x-.5) exp(-x) (1 + 1/x P(1/x))
+ * The polynomial STIR is valid for 33 <= x <= 172.
+ */
+static float stirf( float x )
+{
+float y, w, v;
+
+w = 1.0/x;
+w = 1.0 + w * polevlf( w, STIR, 2 );
+y = expf( -x );
+if( x > MAXSTIR )
+ { /* Avoid overflow in pow() */
+ v = powf( x, 0.5 * x - 0.25 );
+ y *= v;
+ y *= v;
+ }
+else
+ {
+ y = powf( x, x - 0.5 ) * y;
+ }
+y = SQTPIF * y * w;
+return( y );
+}
+
+
+/* gamma(x+2), 0 < x < 1 */
+static const float P[] = {
+ 1.536830450601906E-003,
+ 5.397581592950993E-003,
+ 4.130370201859976E-003,
+ 7.232307985516519E-002,
+ 8.203960091619193E-002,
+ 4.117857447645796E-001,
+ 4.227867745131584E-001,
+ 9.999999822945073E-001,
+};
+
+float __tgammaf_r( float x, int* sgngamf)
+{
+float p, q, z, nz;
+int i, direction, negative;
+
+#ifdef NANS
+if( isnan(x) )
+ return(x);
+#endif
+#ifdef INFINITIES
+#ifdef NANS
+if( x == INFINITYF )
+ return(x);
+if( x == -INFINITYF )
+ return(NANF);
+#else
+if( !isfinite(x) )
+ return(x);
+#endif
+#endif
+
+*sgngamf = 1;
+negative = 0;
+nz = 0.0;
+if( x < 0.0 )
+ {
+ negative = 1;
+ q = -x;
+ p = floorf(q);
+ if( p == q )
+ {
+gsing:
+ _SET_ERRNO(EDOM);
+ mtherr( "tgammaf", SING );
+#ifdef INFINITIES
+ return (INFINITYF);
+#else
+ return (MAXNUMF);
+#endif
+ }
+ i = p;
+ if( (i & 1) == 0 )
+ *sgngamf = -1;
+ nz = q - p;
+ if( nz > 0.5 )
+ {
+ p += 1.0;
+ nz = q - p;
+ }
+ nz = q * sinf( PIF * nz );
+ if( nz == 0.0 )
+ {
+ _SET_ERRNO(ERANGE);
+ mtherr( "tgamma", OVERFLOW );
+#ifdef INFINITIES
+ return( *sgngamf * INFINITYF);
+#else
+ return( *sgngamf * MAXNUMF);
+#endif
+ }
+ if( nz < 0 )
+ nz = -nz;
+ x = q;
+ }
+if( x >= 10.0 )
+ {
+ z = stirf(x);
+ }
+if( x < 2.0 )
+ direction = 1;
+else
+ direction = 0;
+z = 1.0;
+while( x >= 3.0 )
+ {
+ x -= 1.0;
+ z *= x;
+ }
+/*
+while( x < 0.0 )
+ {
+ if( x > -1.E-4 )
+ goto small;
+ z *=x;
+ x += 1.0;
+ }
+*/
+while( x < 2.0 )
+ {
+ if( x < 1.e-4 )
+ goto small;
+ z *=x;
+ x += 1.0;
+ }
+
+if( direction )
+ z = 1.0/z;
+
+if( x == 2.0 )
+ return(z);
+
+x -= 2.0;
+p = z * polevlf( x, P, 7 );
+
+gdone:
+
+if( negative )
+ {
+ p = *sgngamf * PIF/(nz * p );
+ }
+return(p);
+
+small:
+if( x == 0.0 )
+ {
+ goto gsing;
+ }
+else
+ {
+ p = z / ((1.0 + 0.5772156649015329 * x) * x);
+ goto gdone;
+ }
+}
+
+/* This is the C99 version */
+
+float tgammaf(float x)
+{
+ int local_sgngamf=0;
+ return (__tgammaf_r(x, &local_sgngamf));
+}