GNU Octave  4.2.1
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-2017 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 #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 
83  if (nargin < 2 || nargin > 3)
84  print_usage ();
85 
86  bool lower = true;
87  if (nargin == 3)
88  {
89  std::string s = args(2).xstring_value ("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 ("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:52
bool is_scalar_type(void) const
Definition: ov.h:673
#define DEFUN(name, args_name, nargout_name, doc)
Definition: defun.h:46
void error(const char *fmt,...)
Definition: error.cc:570
float float_value(bool frc_str_conv=false) const
Definition: ov.h:778
s
Definition: file-io.cc:2682
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:398
JNIEnv void * args
Definition: ov-java.cc:67
FloatNDArray float_array_value(bool frc_str_conv=false) const
Definition: ov.h:796
int nargin
Definition: graphics.cc:10115
octave_value retval
Definition: data.cc:6294
NDArray array_value(bool frc_str_conv=false) const
Definition: ov.h:793
ColumnVector transform(const Matrix &m, double x, double y, double z)
Definition: graphics.cc:5118
double gammainc(double x, double a, bool &err)
Definition: lo-specfun.cc:2547
bool is_single_type(void) const
Definition: ov.h:627
double double_value(bool frc_str_conv=false) const
Definition: ov.h:775
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:854
F77_RET_T F77_REAL &F77_RET_T F77_DBLE &F77_RET_T F77_REAL &F77_RET_T F77_DBLE &F77_RET_T F77_REAL &F77_RET_T F77_DBLE &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 F77_REAL &F77_RET_T F77_DBLE &F77_RET_T F77_DBLE &F77_RET_T F77_REAL &F77_RET_T F77_REAL &F77_RET_T F77_DBLE &F77_RET_T const F77_DBLE F77_DBLE &F77_RET_T const F77_REAL F77_REAL &F77_RET_T F77_REAL F77_REAL &F77_RET_T F77_DBLE F77_DBLE &F77_RET_T const F77_DBLE * x