/* dgamit.f -- translated by f2c (version 20041007).
   You must link the resulting object file with libf2c:
        on Microsoft Windows system, link with libf2c.lib;
        on Linux or Unix systems, link with .../path/to/libf2c.a -lm
        or, if you install libf2c.a in a standard place, with -lf2c -lm
        -- in that order, at the end of the command line, as in
                cc *.o -lf2c -lm
        Source for libf2c is in /netlib/f2c/libf2c.zip, e.g.,

                http://www.netlib.org/f2c/libf2c.zip
*/

/** This routine has been editted to be thread safe **/

#include "f2c.h"

/* Table of constant values */

static integer c__3 = 3;
static integer c__4 = 4;
static integer c__1 = 1;
static integer c__2 = 2;
static doublereal c_b10 = 1.;

/* DECK DGAMIT */
doublereal dgamit_(doublereal *a, doublereal *x)
{
    /* Initialized data */

    // static logical first = TRUE_;

    /* System generated locals */
    doublereal ret_val, d__1, d__2;

    /* Builtin functions */
    double log(doublereal), sqrt(doublereal), d_sign(doublereal *, doublereal 
            *), d_int(doublereal *), exp(doublereal);

    /* Local variables */
    doublereal h__, t, sga, alx;
    /* static */ doublereal bot;
    doublereal alng, aeps;
    extern doublereal dgamr_(doublereal *);
    doublereal ainta;
    /* static */ doublereal sqeps;
    extern doublereal d1mach_(integer *);
    doublereal algap1;
    extern doublereal d9lgic_(doublereal *, doublereal *, doublereal *), 
            d9lgit_(doublereal *, doublereal *, doublereal *), d9gmit_(
            doublereal *, doublereal *, doublereal *, doublereal *, 
            doublereal *), dlngam_(doublereal *);
    extern /* Subroutine */ int dlgams_(doublereal *, doublereal *, 
            doublereal *);
    doublereal sgngam;
    /* static */ doublereal alneps;
//    extern /* Subroutine */ int xerclr_(void);
    extern /* Subroutine */ xermsg_(char *, char *, char *,
             integer *, integer *, ftnlen, ftnlen, ftnlen);

/* ***BEGIN PROLOGUE  DGAMIT */
/* ***PURPOSE  Calculate Tricomi's form of the incomplete Gamma function. */
/* ***LIBRARY   SLATEC (FNLIB) */
/* ***CATEGORY  C7E */
/* ***TYPE      DOUBLE PRECISION (GAMIT-S, DGAMIT-D) */
/* ***KEYWORDS  COMPLEMENTARY INCOMPLETE GAMMA FUNCTION, FNLIB, */
/*             SPECIAL FUNCTIONS, TRICOMI */
/* ***AUTHOR  Fullerton, W., (LANL) */
/* ***DESCRIPTION */

/*   Evaluate Tricomi's incomplete Gamma function defined by */

/*   DGAMIT = X**(-A)/GAMMA(A) * integral from 0 to X of EXP(-T) * */
/*              T**(A-1.) */

/*   for A .GT. 0.0 and by analytic continuation for A .LE. 0.0. */
/*   GAMMA(X) is the complete gamma function of X. */

/*   DGAMIT is evaluated for arbitrary real values of A and for non- */
/*   negative values of X (even though DGAMIT is defined for X .LT. */
/*   0.0), except that for X = 0 and A .LE. 0.0, DGAMIT is infinite, */
/*   which is a fatal error. */

/*   The function and both arguments are DOUBLE PRECISION. */

/*   A slight deterioration of 2 or 3 digits accuracy will occur when */
/*   DGAMIT is very large or very small in absolute value, because log- */
/*   arithmic variables are used.  Also, if the parameter  A  is very */
/*   close to a negative integer (but not a negative integer), there is */
/*   a loss of accuracy, which is reported if the result is less than */
/*   half machine precision. */

/* ***REFERENCES  W. Gautschi, A computational procedure for incomplete */
/*                 gamma functions, ACM Transactions on Mathematical */
/*                 Software 5, 4 (December 1979), pp. 466-481. */
/*               W. Gautschi, Incomplete gamma functions, Algorithm 542, */
/*                 ACM Transactions on Mathematical Software 5, 4 */
/*                 (December 1979), pp. 482-489. */
/* ***ROUTINES CALLED  D1MACH, D9GMIT, D9LGIC, D9LGIT, DGAMR, DLGAMS, */
/*                    DLNGAM, XERCLR, XERMSG */
/* ***REVISION HISTORY  (YYMMDD) */
/*   770701  DATE WRITTEN */
/*   890531  Changed all specific intrinsics to generic.  (WRB) */
/*   890531  REVISION DATE from Version 3.2 */
/*   891214  Prologue converted to Version 4.0 format.  (BAB) */
/*   900315  CALLs to XERROR changed to CALLs to XERMSG.  (THJ) */
/*   920528  DESCRIPTION and REFERENCES sections revised.  (WRB) */
/* ***END PROLOGUE  DGAMIT */
/* ***FIRST EXECUTABLE STATEMENT  DGAMIT */

    // d1mach has been made thread safe, so there is no need for the
    // statics in determining these values
//     if (first) {
//      alneps = -log(d1mach_(&c__3));
//      sqeps = sqrt(d1mach_(&c__4));
//      bot = log(d1mach_(&c__1));
//     }
//     first = FALSE_;
    alneps = -log(d1mach_(&c__3));
    sqeps = sqrt(d1mach_(&c__4));
    bot = log(d1mach_(&c__1));

    if (*x < 0.) {
        xermsg_("SLATEC", "DGAMIT", "X IS NEGATIVE", &c__2, &c__2, (ftnlen)6, 
                (ftnlen)6, (ftnlen)13);
    }

    if (*x != 0.) {
        alx = log(*x);
    }
    sga = 1.;
    if (*a != 0.) {
        sga = d_sign(&c_b10, a);
    }
    d__1 = *a + sga * .5;
    ainta = d_int(&d__1);
    aeps = *a - ainta;

    if (*x > 0.) {
        goto L20;
    }
    ret_val = 0.;
    if (ainta > 0. || aeps != 0.) {
        d__1 = *a + 1.;
        ret_val = dgamr_(&d__1);
    }
    return ret_val;

L20:
    if (*x > 1.) {
        goto L30;
    }
    if (*a >= -.5 || aeps != 0.) {
        d__1 = *a + 1.;
        dlgams_(&d__1, &algap1, &sgngam);
    }
    ret_val = d9gmit_(a, x, &algap1, &sgngam, &alx);
    return ret_val;

L30:
    if (*a < *x) {
        goto L40;
    }
    d__2 = *a + 1.;
    d__1 = dlngam_(&d__2);
    t = d9lgit_(a, x, &d__1);
    if (t < bot) {
//      xerclr_();
    }
    ret_val = exp(t);
    return ret_val;

L40:
    alng = d9lgic_(a, x, &alx);

/* EVALUATE DGAMIT IN TERMS OF LOG (DGAMIC (A, X)) */

    h__ = 1.;
    if (aeps == 0. && ainta <= 0.) {
        goto L50;
    }

    d__1 = *a + 1.;
    dlgams_(&d__1, &algap1, &sgngam);
    t = log((abs(*a))) + alng - algap1;
    if (t > alneps) {
        goto L60;
    }

    if (t > -alneps) {
        h__ = 1. - sga * sgngam * exp(t);
    }
    if (abs(h__) > sqeps) {
        goto L50;
    }

//    xerclr_();
    xermsg_("SLATEC", "DGAMIT", "RESULT LT HALF PRECISION", &c__1, &c__1, (
            ftnlen)6, (ftnlen)6, (ftnlen)24);

L50:
    t = -(*a) * alx + log((abs(h__)));
    if (t < bot) {
//      xerclr_();
    }
    d__1 = exp(t);
    ret_val = d_sign(&d__1, &h__);
    return ret_val;

L60:
    t -= *a * alx;
    if (t < bot) {
//      xerclr_();
    }
    ret_val = -sga * sgngam * exp(t);
    return ret_val;

} /* dgamit_ */

