/**
 * This file has no copyright assigned and is placed in the Public Domain.
 * This file is part of the w64 mingw-runtime package.
 * No warranty is given; refer to the file DISCLAIMER.PD within this package.
 */
/* log gamma(x+2), -.5 < x < .5 */
static const float B[] = {
   6.055172732649237E-004,
  -1.311620815545743E-003,
   2.863437556468661E-003,
  -7.366775108654962E-003,
   2.058355474821512E-002,
  -6.735323259371034E-002,
   3.224669577325661E-001,
   4.227843421859038E-001
};

/* log gamma(x+1), -.25 < x < .25 */
static const float C[] = {
   1.369488127325832E-001,
  -1.590086327657347E-001,
   1.692415923504637E-001,
  -2.067882815621965E-001,
   2.705806208275915E-001,
  -4.006931650563372E-001,
   8.224670749082976E-001,
  -5.772156501719101E-001
};

/* log( sqrt( 2*pi ) ) */
static const float LS2PI  =  0.91893853320467274178;
#define MAXLGM 2.035093e36
static const float PIINV =  0.318309886183790671538;

#include "cephes_mconf.h"

/* Reentrant version */ 
/* Logarithm of gamma function */
float __lgammaf_r(float x, int* sgngamf);

float __lgammaf_r(float x, int* sgngamf)
{
	float p, q, w, z;
	float nx, tx;
	int i, direction;

	*sgngamf = 1;
#ifdef NANS
	if (isnan(x))
		return (x);
#endif

#ifdef INFINITIES
	if (!isfinite(x))
		return (x);
#endif

	if (x < 0.0)
	{
		q = -x;
		w = __lgammaf_r(q, sgngamf); /* note this modifies sgngam! */
		p = floorf(q);
		if (p == q)
		{
lgsing:
			_SET_ERRNO(EDOM);
			mtherr("lgamf", SING);
#ifdef INFINITIES
			return (INFINITYF);
#else
			return( *sgngamf * MAXNUMF );
#endif
		}
		i = p;
		if ((i & 1) == 0)
			*sgngamf = -1;
		else
			*sgngamf = 1;
		z = q - p;
		if (z > 0.5)
		{
			p += 1.0;
			z = p - q;
		}
		z = q * sinf(PIF * z);
		if (z == 0.0)
			goto lgsing;
		z = -logf(PIINV * z) - w;
		return (z);
	}

	if (x < 6.5)
	{
		direction = 0;
		z = 1.0;
		tx = x;
		nx = 0.0;
		if (x >= 1.5)
		{
			while (tx > 2.5)
			{
				nx -= 1.0;
				tx = x + nx;
				z *=tx;
			}
			x += nx - 2.0;
iv1r5:
			p = x * polevlf( x, B, 7 );
			goto cont;
		}
		if (x >= 1.25)
		{
			z *= x;
			x -= 1.0; /* x + 1 - 2 */
			direction = 1;
			goto iv1r5;
		}
		if (x >= 0.75)
		{
			x -= 1.0;
			p = x * polevlf( x, C, 7 );
			q = 0.0;
			goto contz;
		}
		while (tx < 1.5)
		{
			if (tx == 0.0)
				goto lgsing;
			z *=tx;
			nx += 1.0;
			tx = x + nx;
		}
		direction = 1;
		x += nx - 2.0;
		p = x * polevlf(x, B, 7);

cont:
		if (z < 0.0)
		{
			*sgngamf = -1;
			z = -z;
		}
		else
		{
			*sgngamf = 1;
		}
		q = logf(z);
		if (direction)
			q = -q;
contz:
		return( p + q );
	}

	if (x > MAXLGM)
	{
		_SET_ERRNO(ERANGE);
		mtherr("lgamf", OVERFLOW);
#ifdef INFINITIES
		return (*sgngamf * INFINITYF);
#else
		return (*sgngamf * MAXNUMF);
#endif

	}

/* Note, though an asymptotic formula could be used for x >= 3,
 * there is cancellation error in the following if x < 6.5.  */
	q = LS2PI - x;
	q += (x - 0.5) * logf(x);

	if (x <= 1.0e4)
	{
		z = 1.0/x;
		p = z * z;
		q += ((    6.789774945028216E-004 * p
			 - 2.769887652139868E-003 ) * p
			+  8.333316229807355E-002 ) * z;
	}
	return (q);
}

/* This is the C99 version */
float lgammaf(float x)
{
	int local_sgngamf = 0;
	return (__lgammaf_r(x, &local_sgngamf));
}

