function [ value, ifault ] = gamain ( x, p )

%*****************************************************************************80
%
%% GAMAIN computes the incomplete gamma ratio.
%
%  Discussion:
%
%    A series expansion is used if P > X or X <= 1.  Otherwise, a
%    continued fraction approximation is used.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    17 January 2008
%
%  Author:
%
%    Original FORTRAN77 version by G Bhattacharjee.
%    MATLAB version by John Burkardt.
%
%  Reference:
%
%    G Bhattacharjee,
%    Algorithm AS 32:
%    The Incomplete Gamma Integral,
%    Applied Statistics,
%    Volume 19, Number 3, 1970, pages 285-287.
%
%  Parameters:
%
%    Input, real X, P, the parameters of the incomplete 
%    gamma ratio.  0 <= X, and 0 < P.
%
%    Output, integer IFAULT, error flag.
%    0, no errors.
%    1, P <= 0.
%    2, X < 0.
%    3, underflow.
%    4, error return from the Log Gamma routine.
%
%    Output, real VALUE, the value of the incomplete
%    gamma ratio.
%
  acu = 1.0E-08;
  oflo = 1.0E+37;
  uflo = 1.0E-37;
%
%  Check the input.
%
  if ( p <= 0.0 )
    ifault = 1;
    value = 0.0;
    return
  end

  if ( x < 0.0 )
    ifault = 2;
    value = 0.0;
    return
  end

  if ( x == 0.0 )
    ifault = 0;
    value = 0.0;
    return
  end

  [ g, ifault ] = alngam ( p );

  if ( ifault ~= 0 )
    ifault = 4;
    value = 0.0;
    return
  end

  arg = p * log ( x ) - x - g;

  if ( arg < log ( uflo ) )
    ifault = 3;
    value = 0.0;
    return
  end

  ifault = 0;
  factor = exp ( arg );
%
%  Calculation by series expansion.
%
  if ( x <= 1.0 || x < p )

    gin = 1.0;
    term = 1.0;
    rn = p;

    while ( true )

      rn = rn + 1.0;
      term = term * x / rn;
      gin = gin + term;

      if ( term <= acu )
        break
      end

    end

    value = gin * factor / p;
    return

  end
%
%  Calculation by continued fraction.
%
  a = 1.0 - p;
  b = a + x + 1.0;
  term = 0.0;

  pn(1) = 1.0;
  pn(2) = x;
  pn(3) = x + 1.0;
  pn(4) = x * b;

  gin = pn(3) / pn(4);

  while ( 1 )

    a = a + 1.0;
    b = b + 2.0;
    term = term + 1.0;
    an = a * term;
    for i = 1 : 2
      pn(i+4) = b * pn(i+2) - an * pn(i);
    end

    if ( pn(6) ~= 0.0 )

      rn = pn(5) / pn(6);
      dif = abs ( gin - rn );
%
%  Absolute error tolerance satisfied?
%
      if ( dif <= acu )
%
%  Relative error tolerance satisfied?
%
        if ( dif <= acu * rn )
          value = 1.0 - factor * gin;
          break
        end

      end

      gin = rn;

    end

    for i = 1 : 4
      pn(i) = pn(i+2);
    end

    if ( oflo <= abs ( pn(5) ) )

      for i = 1 : 4
        pn(i) = pn(i) / oflo;
      end

    end

  end
 
  return
end
