home *** CD-ROM | disk | FTP | other *** search
/ Geek Gadgets 1 / ADE-1.bin / ade-dist / octave-1.1.1p1-src.tgz / tar.out / fsf / octave / scripts / specfun / gammai.m < prev    next >
Text File  |  1996-09-28  |  4KB  |  124 lines

  1. # Copyright (C) 1995 John W. Eaton
  2. # This file is part of Octave.
  3. # Octave is free software; you can redistribute it and/or modify it
  4. # under the terms of the GNU General Public License as published by the
  5. # Free Software Foundation; either version 2, or (at your option) any
  6. # later version.
  7. # Octave is distributed in the hope that it will be useful, but WITHOUT
  8. # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  9. # FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  10. # for more details.
  11. # You should have received a copy of the GNU General Public License
  12. # along with Octave; see the file COPYING.  If not, write to the Free
  13. # Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  14.  
  15. function y = gammai (a, x)
  16.   
  17. # usage: gammai (a, x)
  18. #
  19. # Computes the incomplete gamma function
  20. #
  21. #   gammai (a, x) 
  22. #     = (integral from 0 to x of exp(-t) t^(a-1) dt) / gamma(a).
  23. #
  24. # If a is scalar, then gammai(a, x) is returned for each element of x
  25. # and vice versa.
  26. #
  27. # If neither a nor x is scalar, the sizes of a and x must agree, and
  28. # gammai is applied pointwise.
  29.   
  30. # Written by KH (Kurt.Hornik@ci.tuwien.ac.at) on Aug 13, 1994
  31.  
  32.   if (nargin != 2)
  33.     usage ("gammai (a, x)");
  34.   endif
  35.   
  36.   [r_a, c_a] = size (a);
  37.   [r_x, c_x] = size (x);
  38.   e_a = r_a * c_a;
  39.   e_x = r_x * c_x;
  40.   
  41.   # The following code is rather ugly.  We want the function to work
  42.   # whenever a and x have the same size or a or x is scalar.  
  43.   # We do this by reducing the latter cases to the former.
  44.   
  45.   if (e_a == 0 || e_x == 0)
  46.     error ("gammai: both a and x must be nonempty");
  47.   endif
  48.   if (r_a == r_x && c_a == c_x)
  49.     n   = e_a;
  50.     a   = reshape (a, 1, n);
  51.     x   = reshape (x, 1, n);
  52.     r_y = r_a;
  53.     c_y = c_a;
  54.   elseif (e_a == 1)
  55.     n   = e_x;
  56.     a   = a * ones (1, n);
  57.     x   = reshape (x, 1, n);
  58.     r_y = r_x;
  59.     c_y = c_x;
  60.   elseif (e_x == 1)
  61.     n   = e_a;
  62.     a   = reshape (a, 1, n);
  63.     x   = x * ones (1, n);
  64.     r_y = r_a;
  65.     c_y = c_a;
  66.   else
  67.     error ("gammai: a and x must have the same size if neither is scalar"); 
  68.   endif
  69.  
  70. # Now we can do sanity checking ...
  71.   
  72.   if (any (a <= 0) || any (a == Inf))
  73.     error ("gammai: all entries of a must be positive anf finite");
  74.   endif
  75.   if (any (x < 0))
  76.     error ("gammai: all entries of x must be nonnegative");
  77.   endif
  78.   
  79.   y = zeros(1, n);
  80.  
  81. # For x < a + 1, use summation.  The below choice of k should ensure
  82. # that the overall error is less than eps ... 
  83.  
  84.   S = find ((x > 0) & (x < a + 1));
  85.   s = length (S);
  86.   if (s > 0)
  87.     k   = ceil (- max ([a(S), x(S)]) * log (eps));
  88.     K   = (1:k)';
  89.     M   = ones(k, 1);
  90.     A   = cumprod((M * x(S)) ./ (M * a(S) + K * ones(1, s)));
  91.     y(S) = exp (-x(S) + a(S) .* log (x(S))) .* (1 + sum (A)) ./ gamma (a(S)+1);
  92.   endif
  93.  
  94. # For x >= a + 1, use the continued fraction.
  95. # Note, however, that this converges MUCH slower than the series
  96. # expansion for small a and x not too large!
  97.  
  98.   S = find((x >= a + 1) & (x < Inf));
  99.   s = length(S);
  100.   if (s > 0)
  101.     u   = [zeros(1, s); ones(1, s)];
  102.     v   = [ones(1, s); x(S)];
  103.     c_old = 0;
  104.     c_new = v(1,:) ./ v(2,:);
  105.     n   = 1;
  106.     while (max (abs (c_old ./ c_new - 1)) > 10 * eps)
  107.       c_old = c_new;
  108.       u = v + u .* (ones (2, 1) * (n - a(S)));
  109.       v = u .* (ones (2, 1) * x(S)) + n * v;
  110.       c_new = v(1,:) ./ v(2,:);
  111.       n = n + 1;
  112.     endwhile
  113.     y(S) = 1 - exp (-x(S) + a(S) .* log (x(S))) .* c_new ./ gamma (a(S));
  114.   endif
  115.   
  116.   y (find (x == Inf)) = ones (1, sum (x == Inf));
  117.   
  118.   y = reshape (y, r_y, c_y);
  119.  
  120. endfunction