# Copyright (C) 1995 John W. Eaton
# 
# This file is part of Octave.
# 
# Octave 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, or (at your option) any
# later version.
# 
# Octave 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 Octave; see the file COPYING.  If not, write to the Free
# Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.

function y = betai(a, b, x)
  
# usage: betai(a, b, x)
#
# Returns the incomplete beta function
#   betai (a, b, x) = BETA(a,b)^(-1) INT_0^x t^(a-1) (1-t)^(b-1) dt.
# If x has more than one component, both a and b must be scalars.
# If x is a scalar, a and b must be of compatible dimensions.
  
# Written by KH (Kurt.Hornik@ci.tuwien.ac.at) on Aug 2, 1994.

# Computation is based on the series expansion
#   betai(a, b, x) 
#     = \frac{1}{B(a, b)} x^a 
#         \sum_{k=0}^\infty \frac{(1-b)\cdots(k-b)}{a+k} \frac{x^k}{k!}
# for x <= 1/2.  For x > 1/2, betai(a, b, x) = 1 - betai(b, a, 1-x).

  if (nargin <> 3)
    usage (" betai (a, b, x)");
  endif

  if !((a > 0) && (b > 0))
    error("betai:  a and b must both be positive.");
  endif
  [nr, nc] = size(x);
  if (min ([nr, nc]) == 0)
    error ("betai:  x must not be empty.");
  endif
  if (any (x < 0) || any (x > 1))
    error ("betai: all entries of x must be in [0,1].");
  endif

  if ((nr > 1) || (nc > 1))
    
    if (! (is_scalar (a) && is_scalar (b)))
      error ("betai: if x is not a scalar, a and b must be scalars");
    endif

    n = nr * nc;
    x = reshape (x, 1, n);
    y = zeros (1, n);
    c = exp (lgamma (a+b) - lgamma (a) - lgamma (b));

    y (find (x == 1)) = ones (1, sum (x == 1));

# Now do the series computation.  The error when truncating at term K
# is always less than 2^(-K), hence the following choice of K.

    K = ceil (-log (eps) / log (2));
    k = (1:K)';

    ind = find ((x > 0) & (x <= 1/2));
    len = length (ind);
    if (len > 0)
      tmp    = cumprod((1 - b./k) * x(ind)) ./ ((a + k) * ones(1, len));
      y(ind) = c * exp(a * log(x(ind))) .* (1/a + sum(tmp));
    endif
    
    ind = find ((x > 1/2) & (x < 1));
    len = length(ind);
    if (len > 0)
      tmp    = cumprod ((1 - a./k) * (1 - x(ind))) ./ ((b + k) * ones(1, len));
      y(ind) = 1 - c * exp (b * log (1-x(ind))) .* (1/b + sum (tmp));
    endif
  
    y = reshape (y, nr, nc);
    
  else
    
    [ra, ca] = size (a);
    [rb, cb] = size (b);
    if (! (ra == rb && ca == cb))
      error ("betai: a and b must have the same size");
    endif

    n = ra * ca;
    a = reshape (a, 1, n);
    b = reshape (b, 1, n);
    c = exp (lgamma (a+b) - lgamma (a) - lgamma (b));
    
    if (x == 0)
      y   = zeros (1, n);
    elseif (x == 1)
      y   = ones (1, n);
    else
      K = ceil (-log (eps) / log (2));
      k = (1:K)' * ones (1, n);
      h = ones (K, 1);
      if (x > 0 && x <= 1/2)
	tmp = cumprod ((1 - (h * b) ./ k) * x) ./ ((h * a) + k);
	y   = c .* exp (a * log(x)) .* (1 ./ a + sum (tmp));
      else
	tmp = cumprod ((1 - (h * a) ./ k) * (1-x)) ./ ((h * b) + k);
	y   = 1 - c .* exp (b * log (1-x)) .* (1 ./ b + sum (tmp));
      endif
    endif
  
    y = reshape (y, ra, ca);
    
  endif

endfunction





