GNU Octave  4.4.1
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
gammainc.cc
Go to the documentation of this file.
1 /*
2 
3 Copyright (C) 1997-2018 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
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
11 
12 Octave is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License 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 <https://www.gnu.org/licenses/>.
20 
21 */
22 
23 #if defined (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 "errwarn.h"
32 #include "ovl.h"
33 #include "utils.h"
34 
35 DEFUN (gammainc, args, ,
36  doc: /* -*- texinfo -*-
37 @deftypefn {} {} gammainc (@var{x}, @var{a})
38 @deftypefnx {} {} gammainc (@var{x}, @var{a}, "lower")
39 @deftypefnx {} {} gammainc (@var{x}, @var{a}, "upper")
40 Compute the normalized incomplete gamma function.
41 
42 This is defined as
43 @tex
44 $$
45  \gamma (x, a) = {1 \over {\Gamma (a)}}\displaystyle{\int_0^x t^{a-1} e^{-t} dt}
46 $$
47 @end tex
48 @ifnottex
49 
50 @example
51 @group
52  x
53  1 /
54 gammainc (x, a) = --------- | exp (-t) t^(a-1) dt
55  gamma (a) /
56  t=0
57 @end group
58 @end example
59 
60 @end ifnottex
61 with the limiting value of 1 as @var{x} approaches infinity.
62 The standard notation is @math{P(a,x)}, e.g., @nospell{Abramowitz} and
63 @nospell{Stegun} (6.5.1).
64 
65 If @var{a} is scalar, then @code{gammainc (@var{x}, @var{a})} is returned
66 for each element of @var{x} and vice versa.
67 
68 If neither @var{x} nor @var{a} is scalar, the sizes of @var{x} and
69 @var{a} must agree, and @code{gammainc} is applied element-by-element.
70 
71 By default the incomplete gamma function integrated from 0 to @var{x} is
72 computed. If @qcode{"upper"} is given then the complementary function
73 integrated from @var{x} to infinity is calculated. It should be noted that
74 
75 @example
76 gammainc (@var{x}, @var{a}) @equiv{} 1 - gammainc (@var{x}, @var{a}, "upper")
77 @end example
78 @seealso{gamma, gammaln}
79 @end deftypefn */)
80 {
81  int nargin = args.length ();
82 
84  print_usage ();
85 
86  bool lower = true;
87  if (nargin == 3)
88  {
89  std::string s = args(2).xstring_value (R"(gammainc: third argument must be "lower" or "upper")");
90 
91  std::transform (s.begin (), s.end (), s.begin (), tolower);
92 
93  if (s == "upper")
94  lower = false;
95  else if (s == "lower")
96  lower = true;
97  else
98  error (R"(gammainc: third argument must be "lower" or "upper")");
99  }
100 
102 
103  octave_value x_arg = args(0);
104  octave_value a_arg = args(1);
105 
106  // FIXME: Can we make a template version of the duplicated code below
107  if (x_arg.is_single_type () || a_arg.is_single_type ())
108  {
109  if (x_arg.is_scalar_type ())
110  {
111  float x = x_arg.float_value ();
112 
113  if (a_arg.is_scalar_type ())
114  {
115  float a = a_arg.float_value ();
116 
117  retval = (lower ? octave::math::gammainc (x, a)
118  : 1.0f - octave::math::gammainc (x, a));
119  }
120  else
121  {
122  FloatNDArray a = a_arg.float_array_value ();
123 
124  retval = (lower ? octave::math::gammainc (x, a)
125  : 1.0f - octave::math::gammainc (x, a));
126  }
127  }
128  else
129  {
130  FloatNDArray x = x_arg.float_array_value ();
131 
132  if (a_arg.is_scalar_type ())
133  {
134  float a = a_arg.float_value ();
135 
136  retval = (lower ? octave::math::gammainc (x, a)
137  : 1.0f - octave::math::gammainc (x, a));
138  }
139  else
140  {
141  FloatNDArray a = a_arg.float_array_value ();
142 
143  retval = (lower ? octave::math::gammainc (x, a)
144  : 1.0f - octave::math::gammainc (x, a));
145  }
146  }
147  }
148  else
149  {
150  if (x_arg.is_scalar_type ())
151  {
152  double x = x_arg.double_value ();
153 
154  if (a_arg.is_scalar_type ())
155  {
156  double a = a_arg.double_value ();
157 
158  retval = (lower ? octave::math::gammainc (x, a)
159  : 1.0 - octave::math::gammainc (x, a));
160  }
161  else
162  {
163  NDArray a = a_arg.array_value ();
164 
165  retval = (lower ? octave::math::gammainc (x, a)
166  : 1.0 - octave::math::gammainc (x, a));
167  }
168  }
169  else
170  {
171  NDArray x = x_arg.array_value ();
172 
173  if (a_arg.is_scalar_type ())
174  {
175  double a = a_arg.double_value ();
176 
177  retval = (lower ? octave::math::gammainc (x, a)
178  : 1.0 - octave::math::gammainc (x, a));
179  }
180  else
181  {
182  NDArray a = a_arg.array_value ();
183 
184  retval = (lower ? octave::math::gammainc (x, a)
185  : 1.0 - octave::math::gammainc (x, a));
186  }
187  }
188  }
189 
190  return retval;
191 }
192 
193 /*
194 %!test
195 %! a = [.5 .5 .5 .5 .5];
196 %! x = [0 1 2 3 4];
197 %! v1 = sqrt (pi)*erf (x)./gamma (a);
198 %! v3 = gammainc (x.*x, a);
199 %! assert (v1, v3, sqrt (eps));
200 
201 %!assert (gammainc (0:4,0.5, "upper"), 1-gammainc (0:4,0.5), 1e-10)
202 
203 %!test
204 %! a = single ([.5 .5 .5 .5 .5]);
205 %! x = single ([0 1 2 3 4]);
206 %! v1 = sqrt (pi ("single"))*erf (x)./gamma (a);
207 %! v3 = gammainc (x.*x, a);
208 %! assert (v1, v3, sqrt (eps ("single")));
209 
210 %!assert (gammainc (single (0:4), single (0.5), "upper"),
211 %! single (1)-gammainc (single (0:4), single (0.5)),
212 %! single (1e-7))
213 */
OCTINTERP_API void print_usage(void)
Definition: defun.cc:54
#define DEFUN(name, args_name, nargout_name, doc)
Macro to define a builtin function.
Definition: defun.h:53
void error(const char *fmt,...)
Definition: error.cc:578
s
Definition: file-io.cc:2729
FloatNDArray float_array_value(bool frc_str_conv=false) const
Definition: ov.h:843
float float_value(bool frc_str_conv=false) const
Definition: ov.h:825
calling an anonymous function involves an overhead quite comparable to the overhead of an m file function Passing a handle to a built in function is because the interpreter is not involved in the internal loop For a
Definition: cellfun.cc:400
bool is_single_type(void) const
Definition: ov.h:651
octave_value retval
Definition: data.cc:6246
double double_value(bool frc_str_conv=false) const
Definition: ov.h:822
args.length() nargin
Definition: file-io.cc:589
ColumnVector transform(const Matrix &m, double x, double y, double z)
Definition: graphics.cc:5410
OCTAVE_API double gammainc(double x, double a, bool &err)
If this string is the system will ring the terminal sometimes it is useful to be able to print the original representation of the string
Definition: utils.cc:888
bool is_scalar_type(void) const
Definition: ov.h:717
NDArray array_value(bool frc_str_conv=false) const
Definition: ov.h:840
F77_RET_T const F77_REAL const F77_REAL F77_REAL &F77_RET_T const F77_DBLE const F77_DBLE F77_DBLE &F77_RET_T const F77_DBLE F77_DBLE &F77_RET_T const F77_REAL F77_REAL &F77_RET_T const F77_DBLE * x