Mercurial > hg > octave-nkf
view liboctave/numeric/randgamma.c @ 20685:7fa1970a655d
pkg.m: drop check of nargout value, the interpreter already does that.
* scripts/pkg/pkg.m: the interpreter already checks if there was any variable
that got no value assigned, there's no need to make the code more
complicated to cover that. Also, there's no point in calling describe()
with different nargout since it doesn't check nargout.
author | Carnë Draug <carandraug@octave.org> |
---|---|
date | Thu, 03 Sep 2015 16:21:08 +0100 |
parents | 4197fc428c7d |
children |
line wrap: on
line source
/* Copyright (C) 2006-2015 John W. Eaton This file is part of Octave. Octave is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. Octave is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Octave; see the file COPYING. If not, see <http://www.gnu.org/licenses/>. */ /* Original version written by Paul Kienzle distributed as free software in the in the public domain. */ /* double randg (a) void fill_randg (a,n,x) Generate a series of standard gamma distributions. See: Marsaglia G and Tsang W (2000), "A simple method for generating gamma variables", ACM Transactions on Mathematical Software 26(3) 363-372 Needs the following defines: * NAN: value to return for Not-A-Number * RUNI: uniform generator on (0,1) * RNOR: normal generator * REXP: exponential generator, or -log(RUNI) if one isn't available * INFINITE: function to test whether a value is infinite Test using: mean = a variance = a skewness = 2/sqrt(a) kurtosis = 3 + 6/sqrt(a) Note that randg can be used to generate many distributions: gamma(a,b) for a>0, b>0 (from R) r = b*randg(a) beta(a,b) for a>0, b>0 r1 = randg(a,1) r = r1 / (r1 + randg(b,1)) Erlang(a,n) r = a*randg(n) chisq(df) for df>0 r = 2*randg(df/2) t(df) for 0<df<inf (use randn if df is infinite) r = randn () / sqrt(2*randg(df/2)/df) F(n1,n2) for 0<n1, 0<n2 r1 = 2*randg(n1/2)/n1 or 1 if n1 is infinite r2 = 2*randg(n2/2)/n2 or 1 if n2 is infinite r = r1 / r2 negative binonial (n, p) for n>0, 0<p<=1 r = randp((1-p)/p * randg(n)) (from R, citing Devroye(1986), Non-Uniform Random Variate Generation) non-central chisq(df,L), for df>=0 and L>0 (use chisq if L=0) r = randp(L/2) r(r>0) = 2*randg(r(r>0)) r(df>0) += 2*randg(df(df>0)/2) (from R, citing formula 29.5b-c in Johnson, Kotz, Balkrishnan(1995)) Dirichlet(a1,...,ak) for ai > 0 r = (randg(a1),...,randg(ak)) r = r / sum(r) (from GSL, citing Law & Kelton(1991), Simulation Modeling and Analysis) */ #if defined (HAVE_CONFIG_H) #include <config.h> #endif #include <stdio.h> #include "lo-ieee.h" #include "lo-math.h" #include "randmtzig.h" #include "randgamma.h" #undef NAN #define NAN octave_NaN #define INFINITE lo_ieee_isinf #define RUNI oct_randu() #define RNOR oct_randn() #define REXP oct_rande() void oct_fill_randg (double a, octave_idx_type n, double *r) { octave_idx_type i; /* If a < 1, start by generating gamma (1+a) */ const double d = (a < 1. ? 1.+a : a) - 1./3.; const double c = 1./sqrt (9.*d); /* Handle invalid cases */ if (a <= 0 || INFINITE(a)) { for (i=0; i < n; i++) r[i] = NAN; return; } for (i=0; i < n; i++) { double x, xsq, v, u; restart: x = RNOR; v = (1+c*x); v *= v*v; if (v <= 0) goto restart; /* rare, so don't bother moving up */ u = RUNI; xsq = x*x; if (u >= 1.-0.0331*xsq*xsq && log (u) >= 0.5*xsq + d*(1-v+log (v))) goto restart; r[i] = d*v; } if (a < 1) { /* Use gamma(a) = gamma(1+a)*U^(1/a) */ /* Given REXP = -log(U) then U^(1/a) = exp(-REXP/a) */ for (i = 0; i < n; i++) r[i] *= exp (-REXP/a); } } double oct_randg (double a) { double ret; oct_fill_randg (a,1,&ret); return ret; } #undef NAN #undef RUNI #undef RNOR #undef REXP #define NAN octave_Float_NaN #define RUNI oct_float_randu() #define RNOR oct_float_randn() #define REXP oct_float_rande() void oct_fill_float_randg (float a, octave_idx_type n, float *r) { octave_idx_type i; /* If a < 1, start by generating gamma(1+a) */ const float d = (a < 1. ? 1.+a : a) - 1./3.; const float c = 1./sqrt (9.*d); /* Handle invalid cases */ if (a <= 0 || INFINITE(a)) { for (i=0; i < n; i++) r[i] = NAN; return; } for (i=0; i < n; i++) { float x, xsq, v, u; frestart: x = RNOR; v = (1+c*x); v *= v*v; if (v <= 0) goto frestart; /* rare, so don't bother moving up */ u = RUNI; xsq = x*x; if (u >= 1.-0.0331*xsq*xsq && log (u) >= 0.5*xsq + d*(1-v+log (v))) goto frestart; r[i] = d*v; } if (a < 1) { /* Use gamma(a) = gamma(1+a)*U^(1/a) */ /* Given REXP = -log(U) then U^(1/a) = exp(-REXP/a) */ for (i = 0; i < n; i++) r[i] *= exp (-REXP/a); } } float oct_float_randg (float a) { float ret; oct_fill_float_randg (a,1,&ret); return ret; }