GNU Octave  4.4.1
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
randgamma.cc
Go to the documentation of this file.
1 /*
2 
3 Copyright (C) 2006-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 /* Original version written by Paul Kienzle distributed as free
24  software in the in the public domain. */
25 
26 /*
27 
28 double randg (a)
29 void fill_randg (a,n,x)
30 
31 Generate a series of standard gamma distributions.
32 
33 See: Marsaglia G and Tsang W (2000), "A simple method for generating
34 gamma variables", ACM Transactions on Mathematical Software 26(3) 363-372
35 
36 Needs the following defines:
37 * NAN: value to return for Not-A-Number
38 * RUNI: uniform generator on (0,1)
39 * RNOR: normal generator
40 * REXP: exponential generator, or -log(RUNI) if one isn't available
41 * INFINITE: function to test whether a value is infinite
42 
43 Test using:
44  mean = a
45  variance = a
46  skewness = 2/sqrt(a)
47  kurtosis = 3 + 6/sqrt(a)
48 
49 Note that randg can be used to generate many distributions:
50 
51 gamma(a,b) for a>0, b>0 (from R)
52  r = b*randg(a)
53 beta(a,b) for a>0, b>0
54  r1 = randg(a,1)
55  r = r1 / (r1 + randg(b,1))
56 Erlang(a,n)
57  r = a*randg(n)
58 chisq(df) for df>0
59  r = 2*randg(df/2)
60 t(df) for 0<df<inf (use randn if df is infinite)
61  r = randn () / sqrt(2*randg(df/2)/df)
62 F(n1,n2) for 0<n1, 0<n2
63  r1 = 2*randg(n1/2)/n1 or 1 if n1 is infinite
64  r2 = 2*randg(n2/2)/n2 or 1 if n2 is infinite
65  r = r1 / r2
66 negative binonial (n, p) for n>0, 0<p<=1
67  r = randp((1-p)/p * randg(n))
68  (from R, citing Devroye(1986), Non-Uniform Random Variate Generation)
69 non-central chisq(df,L), for df>=0 and L>0 (use chisq if L=0)
70  r = randp(L/2)
71  r(r>0) = 2*randg(r(r>0))
72  r(df>0) += 2*randg(df(df>0)/2)
73  (from R, citing formula 29.5b-c in Johnson, Kotz, Balkrishnan(1995))
74 Dirichlet(a1,...,ak) for ai > 0
75  r = (randg(a1),...,randg(ak))
76  r = r / sum(r)
77  (from GSL, citing Law & Kelton(1991), Simulation Modeling and Analysis)
78 */
79 
80 #if defined (HAVE_CONFIG_H)
81 # include "config.h"
82 #endif
83 
84 #include <cmath>
85 
86 #include "lo-ieee.h"
87 #include "randgamma.h"
88 #include "randmtzig.h"
89 
90 #define INFINITE lo_ieee_isinf
91 #define RUNI oct_randu()
92 #define RNOR oct_randn()
93 #define REXP oct_rande()
94 
95 void
96 oct_fill_randg (double a, octave_idx_type n, double *r)
97 {
99  /* If a < 1, start by generating gamma (1+a) */
100  const double d = (a < 1. ? 1.+a : a) - 1./3.;
101  const double c = 1./std::sqrt (9.*d);
102 
103  /* Handle invalid cases */
104  if (a <= 0 || INFINITE(a))
105  {
106  for (i=0; i < n; i++)
108  return;
109  }
110 
111  for (i=0; i < n; i++)
112  {
113  double x, xsq, v, u;
114  restart:
115  x = RNOR;
116  v = (1+c*x);
117  v *= v*v;
118  if (v <= 0)
119  goto restart; /* rare, so don't bother moving up */
120  u = RUNI;
121  xsq = x*x;
122  if (u >= 1.-0.0331*xsq*xsq && std::log (u) >= 0.5*xsq + d*(1-v+std::log (v)))
123  goto restart;
124  r[i] = d*v;
125  }
126  if (a < 1)
127  {
128  /* Use gamma(a) = gamma(1+a)*U^(1/a) */
129  /* Given REXP = -log(U) then U^(1/a) = exp(-REXP/a) */
130  for (i = 0; i < n; i++)
131  r[i] *= exp (-REXP/a);
132  }
133 }
134 
135 double
136 oct_randg (double a)
137 {
138  double ret;
139  oct_fill_randg (a,1,&ret);
140  return ret;
141 }
142 
143 #undef RUNI
144 #undef RNOR
145 #undef REXP
146 #define RUNI oct_float_randu()
147 #define RNOR oct_float_randn()
148 #define REXP oct_float_rande()
149 
150 void
152 {
154  /* If a < 1, start by generating gamma(1+a) */
155  const float d = (a < 1. ? 1.+a : a) - 1./3.;
156  const float c = 1./std::sqrt (9.*d);
157 
158  /* Handle invalid cases */
159  if (a <= 0 || INFINITE(a))
160  {
161  for (i=0; i < n; i++)
163  return;
164  }
165 
166  for (i=0; i < n; i++)
167  {
168  float x, xsq, v, u;
169  frestart:
170  x = RNOR;
171  v = (1+c*x);
172  v *= v*v;
173  if (v <= 0)
174  goto frestart; /* rare, so don't bother moving up */
175  u = RUNI;
176  xsq = x*x;
177  if (u >= 1.-0.0331*xsq*xsq && std::log (u) >= 0.5*xsq + d*(1-v+std::log (v)))
178  goto frestart;
179  r[i] = d*v;
180  }
181  if (a < 1)
182  {
183  /* Use gamma(a) = gamma(1+a)*U^(1/a) */
184  /* Given REXP = -log(U) then U^(1/a) = exp(-REXP/a) */
185  for (i = 0; i < n; i++)
186  r[i] *= exp (-REXP/a);
187  }
188 }
189 
190 float
192 {
193  float ret;
194  oct_fill_float_randg (a,1,&ret);
195  return ret;
196 }
#define RNOR
Definition: randgamma.cc:147
OCTAVE_EXPORT octave_value_list or N dimensional array whose elements are all equal to the base of natural logarithms The constant ex $e satisfies the equation log(e)
void oct_fill_randg(double a, octave_idx_type n, double *r)
Definition: randgamma.cc:96
u
Definition: lu.cc:138
nd example oindent opens the file binary numeric values will be read assuming they are stored in IEEE format with the least significant bit and then converted to the native representation Opening a file that is already open simply opens it again and returns a separate file id It is not an error to open a file several though writing to the same file through several different file ids may produce unexpected results The possible values of text mode reading and writing automatically converts linefeeds to the appropriate line end character for the you may append a you must also open the file in binary mode The parameter conversions are currently only supported for and permissions will be set to and then everything is written in a single operation This is very efficient and improves performance c
Definition: file-io.cc:587
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 const F77_DBLE F77_DBLE * d
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
#define REXP
Definition: randgamma.cc:148
float oct_float_randg(float a)
Definition: randgamma.cc:191
double oct_randg(double a)
Definition: randgamma.cc:136
void oct_fill_float_randg(float a, octave_idx_type n, float *r)
Definition: randgamma.cc:151
#define INFINITE
Definition: randgamma.cc:90
OCTAVE_EXPORT octave_value_list or N dimensional array whose elements are all equal to the IEEE symbol NaN(Not a Number). NaN is the result of operations which do not produce a well defined 0 result. Common operations which produce a NaN are arithmetic with infinity ex($\infty - \infty$)
for i
Definition: data.cc:5264
#define RUNI
Definition: randgamma.cc:146
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