GNU Octave  3.8.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
gammainc.cc
Go to the documentation of this file.
1 /*
2 
3 Copyright (C) 1997-2013 John W. Eaton
4 
5 This file is part of Octave.
6 
7 Octave is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by the
9 Free Software Foundation; either version 3 of the License, or (at your
10 option) any later version.
11 
12 Octave is distributed in the hope that it will be useful, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 for more details.
16 
17 You should have received a copy of the GNU General Public License
18 along with Octave; see the file COPYING. If not, see
19 <http://www.gnu.org/licenses/>.
20 
21 */
22 
23 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
26 
27 #include "lo-specfun.h"
28 
29 #include "defun.h"
30 #include "error.h"
31 #include "gripes.h"
32 #include "oct-obj.h"
33 #include "utils.h"
34 
35 DEFUN (gammainc, args, ,
36  "-*- texinfo -*-\n\
37 @deftypefn {Mapping Function} {} gammainc (@var{x}, @var{a})\n\
38 @deftypefnx {Mapping Function} {} gammainc (@var{x}, @var{a}, \"lower\")\n\
39 @deftypefnx {Mapping Function} {} gammainc (@var{x}, @var{a}, \"upper\")\n\
40 Compute the normalized incomplete gamma function,\n\
41 @tex\n\
42 $$\n\
43  \\gamma (x, a) = {1 \\over {\\Gamma (a)}}\\displaystyle{\\int_0^x t^{a-1} e^{-t} dt}\n\
44 $$\n\
45 @end tex\n\
46 @ifnottex\n\
47 \n\
48 @example\n\
49 @group\n\
50  x\n\
51  1 /\n\
52 gammainc (x, a) = --------- | exp (-t) t^(a-1) dt\n\
53  gamma (a) /\n\
54  t=0\n\
55 @end group\n\
56 @end example\n\
57 \n\
58 @end ifnottex\n\
59 with the limiting value of 1 as @var{x} approaches infinity.\n\
60 The standard notation is @math{P(a,x)}, e.g., Abramowitz and Stegun (6.5.1).\n\
61 \n\
62 If @var{a} is scalar, then @code{gammainc (@var{x}, @var{a})} is returned\n\
63 for each element of @var{x} and vice versa.\n\
64 \n\
65 If neither @var{x} nor @var{a} is scalar, the sizes of @var{x} and\n\
66 @var{a} must agree, and @code{gammainc} is applied element-by-element.\n\
67 \n\
68 By default the incomplete gamma function integrated from 0 to @var{x} is\n\
69 computed. If @qcode{\"upper\"} is given then the complementary function\n\
70 integrated from @var{x} to infinity is calculated. It should be noted that\n\
71 \n\
72 @example\n\
73 gammainc (@var{x}, @var{a}) @equiv{} 1 - gammainc (@var{x}, @var{a}, \"upper\")\n\
74 @end example\n\
75 @seealso{gamma, lgamma}\n\
76 @end deftypefn")
77 {
78  octave_value retval;
79  bool lower = true;
80 
81  int nargin = args.length ();
82 
83  if (nargin == 3)
84  {
85  if (args(2).is_string ())
86  {
87  std::string s = args(2).string_value ();
88  std::transform (s.begin (), s.end (), s.begin (), tolower);
89  if (s == "upper")
90  lower = false;
91  else if (s != "lower")
92  error ("gammainc: third argument must be \"lower\" or \"upper\"");
93  }
94  else
95  error ("gammainc: third argument must be \"lower\" or \"upper\"");
96 
97  }
98 
99  if (!error_state && nargin >= 2 && nargin <= 3)
100  {
101  octave_value x_arg = args(0);
102  octave_value a_arg = args(1);
103 
104  // FIXME: Can we make a template version of the duplicated code below
105  if (x_arg.is_single_type () || a_arg.is_single_type ())
106  {
107  if (x_arg.is_scalar_type ())
108  {
109  float x = x_arg.float_value ();
110 
111  if (! error_state)
112  {
113  if (a_arg.is_scalar_type ())
114  {
115  float a = a_arg.float_value ();
116 
117  if (! error_state)
118  retval = lower ? gammainc (x, a)
119  : static_cast<float>(1)
120  - gammainc (x, a);
121  }
122  else
123  {
124  FloatNDArray a = a_arg.float_array_value ();
125 
126  if (! error_state)
127  retval = lower ? gammainc (x, a)
128  : static_cast<float>(1)
129  - gammainc (x, a);
130  }
131  }
132  }
133  else
134  {
135  FloatNDArray x = x_arg.float_array_value ();
136 
137  if (! error_state)
138  {
139  if (a_arg.is_scalar_type ())
140  {
141  float a = a_arg.float_value ();
142 
143  if (! error_state)
144  retval = lower ? gammainc (x, a)
145  : static_cast<float>(1)
146  - gammainc (x, a);
147  }
148  else
149  {
150  FloatNDArray a = a_arg.float_array_value ();
151 
152  if (! error_state)
153  retval = lower ? gammainc (x, a)
154  : static_cast<float>(1)
155  - gammainc (x, a);
156  }
157  }
158  }
159  }
160  else
161  {
162  if (x_arg.is_scalar_type ())
163  {
164  double x = x_arg.double_value ();
165 
166  if (! error_state)
167  {
168  if (a_arg.is_scalar_type ())
169  {
170  double a = a_arg.double_value ();
171 
172  if (! error_state)
173  retval = lower ? gammainc (x, a) : 1. - gammainc (x, a);
174  }
175  else
176  {
177  NDArray a = a_arg.array_value ();
178 
179  if (! error_state)
180  retval = lower ? gammainc (x, a) : 1. - gammainc (x, a);
181  }
182  }
183  }
184  else
185  {
186  NDArray x = x_arg.array_value ();
187 
188  if (! error_state)
189  {
190  if (a_arg.is_scalar_type ())
191  {
192  double a = a_arg.double_value ();
193 
194  if (! error_state)
195  retval = lower ? gammainc (x, a) : 1. - gammainc (x, a);
196  }
197  else
198  {
199  NDArray a = a_arg.array_value ();
200 
201  if (! error_state)
202  retval = lower ? gammainc (x, a) : 1. - gammainc (x, a);
203  }
204  }
205  }
206  }
207  }
208  else
209  print_usage ();
210 
211  return retval;
212 }
213 
214 /*
215 %!test
216 %! a = [.5 .5 .5 .5 .5];
217 %! x = [0 1 2 3 4];
218 %! v1 = sqrt (pi)*erf (x)./gamma (a);
219 %! v3 = gammainc (x.*x, a);
220 %! assert (v1, v3, sqrt (eps));
221 
222 %!assert (gammainc (0:4,0.5, "upper"), 1-gammainc (0:4,0.5), 1e-10)
223 
224 %!test
225 %! a = single ([.5 .5 .5 .5 .5]);
226 %! x = single ([0 1 2 3 4]);
227 %! v1 = sqrt (pi ("single"))*erf (x)./gamma (a);
228 %! v3 = gammainc (x.*x, a);
229 %! assert (v1, v3, sqrt (eps ("single")));
230 
231 %!assert (gammainc (single (0:4), single (0.5), "upper"),
232 %! single (1)-gammainc (single (0:4), single (0.5)),
233 %! single (1e-7))
234 */