~ubuntu-branches/ubuntu/lucid/igraph/lucid

« back to all changes in this revision

Viewing changes to src/random.c

  • Committer: Bazaar Package Importer
  • Author(s): Mathieu Malaterre
  • Date: 2009-11-16 18:12:42 UTC
  • Revision ID: james.westby@ubuntu.com-20091116181242-mzv9p5fz9uj57xd1
Tags: upstream-0.5.3
ImportĀ upstreamĀ versionĀ 0.5.3

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* -*- mode: C -*-  */
 
2
/* 
 
3
   IGraph library.
 
4
   Copyright (C) 2005  Gabor Csardi <csardi@rmki.kfki.hu>
 
5
   MTA RMKI, Konkoly-Thege Miklos st. 29-33, Budapest 1121, Hungary
 
6
   
 
7
   This program is free software; you can redistribute it and/or modify
 
8
   it under the terms of the GNU General Public License as published by
 
9
   the Free Software Foundation; either version 2 of the License, or
 
10
   (at your option) any later version.
 
11
   
 
12
   This program is distributed in the hope that it will be useful,
 
13
   but 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 this program; if not, write to the Free Software
 
19
   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 
 
20
   02110-1301 USA
 
21
 
 
22
*/
 
23
 
 
24
#include "random.h"
 
25
#include "error.h"
 
26
#include "config.h"
 
27
 
 
28
#include <math.h>
 
29
#include "igraph_math.h"
 
30
 
 
31
int igraph_rng_inited = 0;
 
32
 
 
33
#ifndef HAVE_EXPM1
 
34
#ifndef USING_R                 /* R provides a replacement */
 
35
/* expm1 replacement */
 
36
static double expm1 (double x)
 
37
{
 
38
    if (fabs(x) < M_LN2)
 
39
    {
 
40
        /* Compute the taylor series S = x + (1/2!) x^2 + (1/3!) x^3 + ... */
 
41
 
 
42
        double i = 1.0;
 
43
        double sum = x;
 
44
        double term = x / 1.0;
 
45
 
 
46
        do
 
47
        {
 
48
            term *= x / ++i;
 
49
            sum += term;
 
50
        }
 
51
        while (fabs(term) > fabs(sum) * 2.22e-16);
 
52
      
 
53
        return sum;
 
54
    }
 
55
 
 
56
    return expl(x) - 1.0L;
 
57
}
 
58
#endif
 
59
#endif
 
60
 
 
61
#ifndef HAVE_RINT
 
62
#ifndef USING_R                 /* R provides a replacement */
 
63
/* rint replacement */
 
64
static double rint (double x)
 
65
{
 
66
   return ( (x<0.) ? -floor(-x+.5) : floor(x+.5) );
 
67
}
 
68
#endif
 
69
#endif
 
70
 
 
71
#if HAVE_RINTF != 1
 
72
static float rintf (float x)
 
73
{
 
74
   return ( (x<(float)0.) ? -(float)floor(-x+.5) : (float)floor(x+.5) );
 
75
}
 
76
#endif
 
77
 
 
78
/*
 
79
 * \ingroup internal
 
80
 * 
 
81
 * This function appends the rest of the needed random number to the 
 
82
 * result vector.
 
83
 */
 
84
 
 
85
int igraph_random_sample_alga(igraph_vector_t *res, igraph_integer_t l, igraph_integer_t h, 
 
86
                              igraph_integer_t length) {
 
87
  igraph_real_t N=h-l+1;
 
88
  igraph_real_t n=length;
 
89
  
 
90
  igraph_real_t top=N-n;
 
91
  igraph_real_t Nreal=N;
 
92
  igraph_real_t S=0;
 
93
  igraph_real_t V, quot;
 
94
  
 
95
  l=l-1;
 
96
 
 
97
  while (n>=2) {
 
98
    V=RNG_UNIF01();
 
99
    S=1;
 
100
    quot=top/Nreal;
 
101
    while (quot>V) {
 
102
      S+=1;
 
103
      top=-1.0+top;
 
104
      Nreal=-1.0+Nreal;
 
105
      quot=(quot*top)/Nreal;
 
106
    }
 
107
    l+=S;
 
108
    igraph_vector_push_back(res, l);    /* allocated */
 
109
    Nreal=-1.0+Nreal; n=-1+n;
 
110
  }
 
111
  
 
112
  S=floor(round(Nreal)*RNG_UNIF01());
 
113
  l+=S+1;
 
114
  igraph_vector_push_back(res, l);      /* allocated */
 
115
  
 
116
  return 0;
 
117
}
 
118
 
 
119
/**
 
120
 * \ingroup nongraph
 
121
 * \function igraph_random_sample
 
122
 * \brief Generates an increasing random sequence of integers.
 
123
 * 
 
124
 * </para><para>
 
125
 * This function generates an incresing sequence of random integer
 
126
 * numbers from a given interval. The algorithm is taken literally
 
127
 * from Jeffrey Scott Vitter: 'An Efficient Algorithm for Sequential
 
128
 * Random Sampling', ACM Transactions on Mathematical Software, 13/1,
 
129
 * 58--67. This method can be used for generating numbers from a
 
130
 * \em very large interval, it is primilarly created for randomly
 
131
 * selecting some edges from the sometimes huge set of possible edges
 
132
 * in a large graph.
 
133
 * \param res Pointer to an initialized vector, this will hold the
 
134
 *        result. It will be resized to the proper size.
 
135
 * \param l The lower limit of the generation interval (inclusive).
 
136
 * \param h The upper limit of the generation interval (inclusive).
 
137
 * \param length The number of random integers to generate.
 
138
 * \return Error code.
 
139
 *
 
140
 * Time complexity: according to the referenced paper, the expected
 
141
 * running time is O(length).
 
142
 */
 
143
 
 
144
int igraph_random_sample(igraph_vector_t *res, igraph_integer_t l, igraph_integer_t h, 
 
145
                         igraph_integer_t length) {
 
146
  igraph_real_t N=h-l+1;
 
147
  igraph_real_t n=length;
 
148
  int retval;
 
149
 
 
150
  igraph_real_t nreal=length;
 
151
  igraph_real_t ninv=1.0/nreal;
 
152
  igraph_real_t Nreal=N;
 
153
  igraph_real_t Vprime;
 
154
  igraph_real_t qu1=-n+1+N;
 
155
  igraph_real_t qu1real=-nreal+1.0+Nreal;
 
156
  igraph_real_t negalphainv=-13;
 
157
  igraph_real_t threshold=-negalphainv*n;
 
158
  igraph_real_t S;
 
159
  
 
160
  igraph_vector_clear(res);
 
161
  IGRAPH_CHECK(igraph_vector_reserve(res, length));  
 
162
 
 
163
  RNG_BEGIN();
 
164
  
 
165
  Vprime=exp(log(RNG_UNIF01())*ninv);
 
166
 
 
167
  while (n>1 && threshold < N) {
 
168
    igraph_real_t X, U;
 
169
    igraph_real_t limit, t;
 
170
    igraph_real_t negSreal, y1, y2, top, bottom;
 
171
    igraph_real_t nmin1inv=1.0/(-1.0+nreal);
 
172
    while (1) {
 
173
      while(1) {
 
174
        X=Nreal*(-Vprime+1.0);
 
175
        S=floor(X);
 
176
        if (S==0) { S=1; }
 
177
        if (S <qu1) { break; }
 
178
        Vprime = exp(log(RNG_UNIF01())*ninv);
 
179
      }
 
180
      U=RNG_UNIF01();
 
181
      negSreal=-S;
 
182
      
 
183
      y1=exp(log(U*Nreal/qu1real)*nmin1inv);
 
184
      Vprime=y1*(-X/Nreal+1.0)*(qu1real/(negSreal+qu1real));
 
185
      if (Vprime <= 1.0) { break; }
 
186
      
 
187
      y2=1.0;
 
188
      top=-1.0+Nreal;
 
189
      if (-1+n > S) {
 
190
        bottom=-nreal+Nreal; 
 
191
        limit=-S+N;
 
192
      } else {
 
193
        bottom=-1.0+negSreal+Nreal;
 
194
        limit=qu1;
 
195
      }
 
196
      for (t=-1+N; t>=limit; t--) {
 
197
        y2=(y2*top)/bottom;
 
198
        top=-1.0+top;
 
199
        bottom=-1.0+bottom;
 
200
      }
 
201
      if (Nreal/(-X+Nreal) >= y1*exp(log(y2)*nmin1inv)) {
 
202
        Vprime=exp(log(RNG_UNIF01())*nmin1inv);
 
203
        break;
 
204
      }
 
205
      Vprime=exp(log(RNG_UNIF01())*ninv);
 
206
    }
 
207
        
 
208
    l+=S;
 
209
    igraph_vector_push_back(res, l);    /* allocated */
 
210
    N=-S+(-1+N);   Nreal=negSreal+(-1.0+Nreal);
 
211
    n=-1+n;   nreal=-1.0+nreal; ninv=nmin1inv;
 
212
    qu1=-S+qu1; qu1real=negSreal+qu1real;
 
213
    threshold=threshold+negalphainv;
 
214
  }
 
215
  
 
216
  if (n>1) {
 
217
    retval=igraph_random_sample_alga(res, l, h, n);
 
218
  } else {
 
219
    retval=0;
 
220
    S=floor(N*Vprime);
 
221
    l+=S;
 
222
    igraph_vector_push_back(res, l);    /* allocated */
 
223
  }
 
224
 
 
225
  RNG_END();
 
226
  
 
227
  return retval;
 
228
}
 
229
  
 
230
#ifdef USING_R
 
231
 
 
232
#else
 
233
 
 
234
/*
 
235
 *  Mathlib : A C Library of Special Functions
 
236
 *  Copyright (C) 1998 Ross Ihaka
 
237
 *  Copyright (C) 2000 The R Development Core Team
 
238
 *  based on AS 111 (C) 1977 Royal Statistical Society
 
239
 *  and   on AS 241 (C) 1988 Royal Statistical Society
 
240
 *
 
241
 *  This program is free software; you can redistribute it and/or modify
 
242
 *  it under the terms of the GNU General Public License as published by
 
243
 *  the Free Software Foundation; either version 2 of the License, or
 
244
 *  (at your option) any later version.
 
245
 *
 
246
 *  This program is distributed in the hope that it will be useful,
 
247
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
248
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
249
 *  GNU General Public License for more details.
 
250
 *
 
251
 *  You should have received a copy of the GNU General Public License
 
252
 *  along with this program; if not, write to the Free Software
 
253
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA.
 
254
 *
 
255
 *  SYNOPSIS
 
256
 *
 
257
 *      double qnorm5(double p, double mu, double sigma,
 
258
 *                    int lower_tail, int log_p)
 
259
 *            {qnorm (..) is synonymous and preferred inside R}
 
260
 *
 
261
 *  DESCRIPTION
 
262
 *
 
263
 *      Compute the quantile function for the normal distribution.
 
264
 *
 
265
 *      For small to moderate probabilities, algorithm referenced
 
266
 *      below is used to obtain an initial approximation which is
 
267
 *      polished with a final Newton step.
 
268
 *
 
269
 *      For very large arguments, an algorithm of Wichura is used.
 
270
 *
 
271
 *  REFERENCE
 
272
 *
 
273
 *      Beasley, J. D. and S. G. Springer (1977).
 
274
 *      Algorithm AS 111: The percentage points of the normal distribution,
 
275
 *      Applied Statistics, 26, 118-121.
 
276
 *
 
277
 *      Wichura, M.J. (1988).
 
278
 *      Algorithm AS 241: The Percentage Points of the Normal Distribution.
 
279
 *      Applied Statistics, 37, 477-484.
 
280
 */
 
281
 
 
282
/*
 
283
 *  Mathlib : A C Library of Special Functions
 
284
 *  Copyright (C) 1998-2004  The R Development Core Team
 
285
 *
 
286
 *  This program is free software; you can redistribute it and/or modify
 
287
 *  it under the terms of the GNU General Public License as published by
 
288
 *  the Free Software Foundation; either version 2 of the License, or
 
289
 *  (at your option) any later version.
 
290
 *
 
291
 *  This program is distributed in the hope that it will be useful,
 
292
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
293
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
294
 *  GNU General Public License for more details.
 
295
 *
 
296
 *  You should have received a copy of the GNU General Public License
 
297
 *  along with this program; if not, write to the Free Software
 
298
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
299
 *
 
300
 */
 
301
 
 
302
/* Private header file for use during compilation of Mathlib */
 
303
#ifndef MATHLIB_PRIVATE_H
 
304
#define MATHLIB_PRIVATE_H
 
305
 
 
306
#ifdef _MSC_VER
 
307
#  define ML_POSINF IGRAPH_INFINITY
 
308
#  define ML_NEGINF -IGRAPH_INFINITY
 
309
#  define ML_NAN    IGRAPH_NAN
 
310
#else
 
311
#  define ML_POSINF     (1.0 / 0.0)
 
312
#  define ML_NEGINF     ((-1.0) / 0.0)
 
313
#  define ML_NAN                (0.0 / 0.0)
 
314
#endif
 
315
 
 
316
#define ML_ERROR(x)     /* nothing */
 
317
#define ML_UNDERFLOW    (DBL_MIN * DBL_MIN)
 
318
#define ML_VALID(x)     (!ISNAN(x))
 
319
 
 
320
#define ME_NONE         0
 
321
/*      no error */
 
322
#define ME_DOMAIN       1
 
323
/*      argument out of domain */
 
324
#define ME_RANGE        2
 
325
/*      value out of range */
 
326
#define ME_NOCONV       4
 
327
/*      process did not converge */
 
328
#define ME_PRECISION    8
 
329
/*      does not have "full" precision */
 
330
#define ME_UNDERFLOW    16
 
331
/*      and underflow occured (important for IEEE)*/
 
332
 
 
333
#define ML_ERR_return_NAN { ML_ERROR(ME_DOMAIN); return ML_NAN; }
 
334
 
 
335
/* Wilcoxon Rank Sum Distribution */
 
336
 
 
337
#define WILCOX_MAX 50
 
338
 
 
339
/* Wilcoxon Signed Rank Distribution */
 
340
 
 
341
#define SIGNRANK_MAX 50
 
342
 
 
343
/* Formerly private part of Mathlib.h */
 
344
 
 
345
/* always remap internal functions */
 
346
#define bd0             Rf_bd0
 
347
#define chebyshev_eval  Rf_chebyshev_eval
 
348
#define chebyshev_init  Rf_chebyshev_init
 
349
#define i1mach          Rf_i1mach
 
350
#define gammalims       Rf_gammalims
 
351
#define lfastchoose     Rf_lfastchoose
 
352
#define lgammacor       Rf_lgammacor
 
353
#define stirlerr        Rf_stirlerr
 
354
 
 
355
        /* Chebyshev Series */
 
356
 
 
357
int     chebyshev_init(double*, int, double);
 
358
double  chebyshev_eval(double, const double *, const int);
 
359
 
 
360
        /* Gamma and Related Functions */
 
361
 
 
362
void    gammalims(double*, double*);
 
363
double  lgammacor(double); /* log(gamma) correction */
 
364
double  stirlerr(double);  /* Stirling expansion "error" */
 
365
 
 
366
double  lfastchoose(double, double);
 
367
 
 
368
double  bd0(double, double);
 
369
 
 
370
/* Consider adding these two to the API (Rmath.h): */
 
371
double  dbinom_raw(double, double, double, double, int);
 
372
double  dpois_raw (double, double, int);
 
373
double  pnchisq_raw(double, double, double, double, double, int);
 
374
 
 
375
int     i1mach(int);
 
376
 
 
377
/* From toms708.c */
 
378
void bratio(double a, double b, double x, double y, 
 
379
            double *w, double *w1, int *ierr);
 
380
 
 
381
 
 
382
#endif /* MATHLIB_PRIVATE_H */
 
383
 
 
384
 
 
385
        /* Utilities for `dpq' handling (density/probability/quantile) */
 
386
 
 
387
/* give_log in "d";  log_p in "p" & "q" : */
 
388
#define give_log log_p
 
389
                                                        /* "DEFAULT" */
 
390
                                                        /* --------- */
 
391
#define R_D__0  (log_p ? ML_NEGINF : 0.)                /* 0 */
 
392
#define R_D__1  (log_p ? 0. : 1.)                       /* 1 */
 
393
#define R_DT_0  (lower_tail ? R_D__0 : R_D__1)          /* 0 */
 
394
#define R_DT_1  (lower_tail ? R_D__1 : R_D__0)          /* 1 */
 
395
 
 
396
#define R_D_Lval(p)     (lower_tail ? (p) : (1 - (p)))  /*  p  */
 
397
#define R_D_Cval(p)     (lower_tail ? (1 - (p)) : (p))  /*  1 - p */
 
398
 
 
399
#define R_D_val(x)      (log_p  ? log(x) : (x))         /*  x  in pF(x,..) */
 
400
#define R_D_qIv(p)      (log_p  ? exp(p) : (p))         /*  p  in qF(p,..) */
 
401
#define R_D_exp(x)      (log_p  ?  (x)   : exp(x))      /* exp(x) */
 
402
#define R_D_log(p)      (log_p  ?  (p)   : log(p))      /* log(p) */
 
403
#define R_D_Clog(p)     (log_p  ? log1p(-(p)) : (1 - (p)))/* [log](1-p) */
 
404
 
 
405
/* log(1-exp(x)):  R_D_LExp(x) == (log1p(- R_D_qIv(x))) but even more stable:*/
 
406
#define R_D_LExp(x)     (log_p ? R_Log1_Exp(x) : log1p(-x))
 
407
 
 
408
/*till 1.8.x:
 
409
 * #define R_DT_val(x)  R_D_val(R_D_Lval(x))
 
410
 * #define R_DT_Cval(x) R_D_val(R_D_Cval(x)) */
 
411
#define R_DT_val(x)     (lower_tail ? R_D_val(x)  : R_D_Clog(x))
 
412
#define R_DT_Cval(x)    (lower_tail ? R_D_Clog(x) : R_D_val(x))
 
413
 
 
414
/*#define R_DT_qIv(p)   R_D_Lval(R_D_qIv(p))             *  p  in qF ! */
 
415
#define R_DT_qIv(p)     (log_p ? (lower_tail ? exp(p) : - expm1(p)) \
 
416
                               : R_D_Lval(p))
 
417
 
 
418
/*#define R_DT_CIv(p)   R_D_Cval(R_D_qIv(p))             *  1 - p in qF */
 
419
#define R_DT_CIv(p)     (log_p ? (lower_tail ? -expm1(p) : exp(p)) \
 
420
                               : R_D_Cval(p))
 
421
 
 
422
#define R_DT_exp(x)     R_D_exp(R_D_Lval(x))            /* exp(x) */
 
423
#define R_DT_Cexp(x)    R_D_exp(R_D_Cval(x))            /* exp(1 - x) */
 
424
 
 
425
#define R_DT_log(p)     (lower_tail? R_D_log(p) : R_D_LExp(p))/* log(p) in qF */
 
426
#define R_DT_Clog(p)    (lower_tail? R_D_LExp(p): R_D_log(p))/* log(1-p) in qF*/
 
427
#define R_DT_Log(p)     (lower_tail? (p) : R_Log1_Exp(p))
 
428
/* ==   R_DT_log when we already "know" log_p == TRUE :*/
 
429
 
 
430
#define R_Q_P01_check(p)                        \
 
431
    if ((log_p  && p > 0) ||                    \
 
432
        (!log_p && (p < 0 || p > 1)) )          \
 
433
        ML_ERR_return_NAN
 
434
 
 
435
/* additions for density functions (C.Loader) */
 
436
#define R_D_fexp(f,x)     (give_log ? -0.5*log(f)+(x) : exp(x)/sqrt(f))
 
437
#define R_D_forceint(x)   floor((x) + 0.5)
 
438
#define R_D_nonint(x)     (fabs((x) - floor((x)+0.5)) > 1e-7)
 
439
/* [neg]ative or [non int]eger : */
 
440
#define R_D_negInonint(x) (x < 0. || R_D_nonint(x))
 
441
 
 
442
#define R_D_nonint_check(x)                             \
 
443
   if(R_D_nonint(x)) {                                  \
 
444
        MATHLIB_WARNING("non-integer x = %f", x);       \
 
445
        return R_D__0;                                  \
 
446
   }
 
447
 
 
448
double igraph_qnorm5(double p, double mu, double sigma, int lower_tail, int log_p)
 
449
{
 
450
    double p_, q, r, val;
 
451
 
 
452
#ifdef IEEE_754
 
453
    if (ISNAN(p) || ISNAN(mu) || ISNAN(sigma))
 
454
        return p + mu + sigma;
 
455
#endif
 
456
    if (p == R_DT_0)    return ML_NEGINF;
 
457
    if (p == R_DT_1)    return ML_POSINF;
 
458
    R_Q_P01_check(p);
 
459
 
 
460
    if(sigma  < 0)      ML_ERR_return_NAN;
 
461
    if(sigma == 0)      return mu;
 
462
 
 
463
    p_ = R_DT_qIv(p);/* real lower_tail prob. p */
 
464
    q = p_ - 0.5;
 
465
 
 
466
/*-- use AS 241 --- */
 
467
/* double ppnd16_(double *p, long *ifault)*/
 
468
/*      ALGORITHM AS241  APPL. STATIST. (1988) VOL. 37, NO. 3
 
469
 
 
470
        Produces the normal deviate Z corresponding to a given lower
 
471
        tail area of P; Z is accurate to about 1 part in 10**16.
 
472
 
 
473
        (original fortran code used PARAMETER(..) for the coefficients
 
474
         and provided hash codes for checking them...)
 
475
*/
 
476
    if (fabs(q) <= .425) {/* 0.075 <= p <= 0.925 */
 
477
        r = .180625 - q * q;
 
478
        val =
 
479
            q * (((((((r * 2509.0809287301226727 +
 
480
                       33430.575583588128105) * r + 67265.770927008700853) * r +
 
481
                     45921.953931549871457) * r + 13731.693765509461125) * r +
 
482
                   1971.5909503065514427) * r + 133.14166789178437745) * r +
 
483
                 3.387132872796366608)
 
484
            / (((((((r * 5226.495278852854561 +
 
485
                     28729.085735721942674) * r + 39307.89580009271061) * r +
 
486
                   21213.794301586595867) * r + 5394.1960214247511077) * r +
 
487
                 687.1870074920579083) * r + 42.313330701600911252) * r + 1.);
 
488
    }
 
489
    else { /* closer than 0.075 from {0,1} boundary */
 
490
 
 
491
        /* r = min(p, 1-p) < 0.075 */
 
492
        if (q > 0)
 
493
            r = R_DT_CIv(p);/* 1-p */
 
494
        else
 
495
            r = p_;/* = R_DT_Iv(p) ^=  p */
 
496
 
 
497
        r = sqrt(- ((log_p &&
 
498
                     ((lower_tail && q <= 0) || (!lower_tail && q > 0))) ?
 
499
                    p : /* else */ log(r)));
 
500
        /* r = sqrt(-log(r))  <==>  min(p, 1-p) = exp( - r^2 ) */
 
501
 
 
502
        if (r <= 5.) { /* <==> min(p,1-p) >= exp(-25) ~= 1.3888e-11 */
 
503
            r += -1.6;
 
504
            val = (((((((r * 7.7454501427834140764e-4 +
 
505
                       .0227238449892691845833) * r + .24178072517745061177) *
 
506
                     r + 1.27045825245236838258) * r +
 
507
                    3.64784832476320460504) * r + 5.7694972214606914055) *
 
508
                  r + 4.6303378461565452959) * r +
 
509
                 1.42343711074968357734)
 
510
                / (((((((r *
 
511
                         1.05075007164441684324e-9 + 5.475938084995344946e-4) *
 
512
                        r + .0151986665636164571966) * r +
 
513
                       .14810397642748007459) * r + .68976733498510000455) *
 
514
                     r + 1.6763848301838038494) * r +
 
515
                    2.05319162663775882187) * r + 1.);
 
516
        }
 
517
        else { /* very close to  0 or 1 */
 
518
            r += -5.;
 
519
            val = (((((((r * 2.01033439929228813265e-7 +
 
520
                       2.71155556874348757815e-5) * r +
 
521
                      .0012426609473880784386) * r + .026532189526576123093) *
 
522
                    r + .29656057182850489123) * r +
 
523
                   1.7848265399172913358) * r + 5.4637849111641143699) *
 
524
                 r + 6.6579046435011037772)
 
525
                / (((((((r *
 
526
                         2.04426310338993978564e-15 + 1.4215117583164458887e-7)*
 
527
                        r + 1.8463183175100546818e-5) * r +
 
528
                       7.868691311456132591e-4) * r + .0148753612908506148525)
 
529
                     * r + .13692988092273580531) * r +
 
530
                    .59983220655588793769) * r + 1.);
 
531
        }
 
532
 
 
533
        if(q < 0.0)
 
534
            val = -val;
 
535
        /* return (q >= 0.)? r : -r ;*/
 
536
    }
 
537
    return mu + sigma * val;
 
538
}
 
539
 
 
540
double fsign(double x, double y)
 
541
{
 
542
#ifdef IEEE_754
 
543
    if (ISNAN(x) || ISNAN(y))
 
544
        return x + y;
 
545
#endif
 
546
    return ((y >= 0) ? fabs(x) : -fabs(x));
 
547
}
 
548
 
 
549
int imax2(int x, int y)
 
550
{
 
551
    return (x < y) ? y : x;
 
552
}
 
553
 
 
554
int imin2(int x, int y)
 
555
{
 
556
    return (x < y) ? x : y;
 
557
}
 
558
 
 
559
#ifdef HAVE_WORKING_ISFINITE
 
560
/* isfinite is defined in <math.h> according to C99 */
 
561
# define R_FINITE(x)    isfinite(x)
 
562
#elif HAVE_WORKING_FINITE
 
563
/* include header needed to define finite() */
 
564
#  ifdef HAVE_IEEE754_H
 
565
#   include <ieee754.h>         /* newer Linuxen */
 
566
#  else
 
567
#   ifdef HAVE_IEEEFP_H
 
568
#    include <ieeefp.h>         /* others [Solaris], .. */
 
569
#   endif
 
570
#  endif
 
571
# define R_FINITE(x)    finite(x)
 
572
#else
 
573
# define R_FINITE(x)    R_finite(x)
 
574
#endif
 
575
 
 
576
int R_finite(double x)
 
577
{
 
578
#ifdef HAVE_WORKING_ISFINITE
 
579
    return isfinite(x);
 
580
#elif HAVE_WORKING_FINITE
 
581
    return finite(x);
 
582
#else
 
583
/* neither finite nor isfinite work. Do we really need the AIX exception? */
 
584
# ifdef _AIX
 
585
#  include <fp.h>
 
586
     return FINITE(x);
 
587
# elif defined(_MSC_VER)
 
588
     return _finite(x);
 
589
#else
 
590
    return (!isnan(x) & (x != 1/0.0) & (x != -1.0/0.0));
 
591
# endif
 
592
#endif
 
593
}
 
594
 
 
595
int R_isnancpp(double x)
 
596
{
 
597
   return (isnan(x)!=0);
 
598
}
 
599
 
 
600
#ifdef __cplusplus
 
601
  int R_isnancpp(double); /* in arithmetic.c */
 
602
#  define ISNAN(x)     R_isnancpp(x)
 
603
#else
 
604
#  define ISNAN(x)     (isnan(x)!=0)
 
605
#endif
 
606
 
 
607
double igraph_norm_rand(void) {
 
608
  
 
609
  double u1;
 
610
 
 
611
#define BIG 134217728 /* 2^27 */
 
612
  /* unif_rand() alone is not of high enough precision */
 
613
  u1 = RNG_UNIF(0,1);
 
614
  u1 = (int)(BIG*u1) + RNG_UNIF(0,1);
 
615
  return igraph_qnorm5(u1/BIG, 0.0, 1.0, 1, 0);
 
616
}
 
617
 
 
618
/*
 
619
 *  Mathlib : A C Library of Special Functions
 
620
 *  Copyright (C) 1998 Ross Ihaka
 
621
 *  Copyright (C) 2000-2002 the R Development Core Team
 
622
 *
 
623
 *  This program is free software; you can redistribute it and/or modify
 
624
 *  it under the terms of the GNU General Public License as published by
 
625
 *  the Free Software Foundation; either version 2 of the License, or
 
626
 *  (at your option) any later version.
 
627
 *
 
628
 *  This program is distributed in the hope that it will be useful,
 
629
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
630
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
631
 *  GNU General Public License for more details.
 
632
 *
 
633
 *  You should have received a copy of the GNU General Public License
 
634
 *  along with this program; if not, write to the Free Software
 
635
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA.
 
636
 *
 
637
 *  SYNOPSIS
 
638
 *
 
639
 *    #include <Rmath.h>
 
640
 *    double exp_rand(void);
 
641
 *
 
642
 *  DESCRIPTION
 
643
 *
 
644
 *    Random variates from the standard exponential distribution.
 
645
 *
 
646
 *  REFERENCE
 
647
 *
 
648
 *    Ahrens, J.H. and Dieter, U. (1972).
 
649
 *    Computer methods for sampling from the exponential and
 
650
 *    normal distributions.
 
651
 *    Comm. ACM, 15, 873-882.
 
652
 */
 
653
 
 
654
double igraph_exp_rand(void)
 
655
{
 
656
    /* q[k-1] = sum(log(2)^k / k!)  k=1,..,n, */
 
657
    /* The highest n (here 8) is determined by q[n-1] = 1.0 */
 
658
    /* within standard precision */
 
659
    const double q[] =
 
660
    {
 
661
        0.6931471805599453,
 
662
        0.9333736875190459,
 
663
        0.9888777961838675,
 
664
        0.9984959252914960,
 
665
        0.9998292811061389,
 
666
        0.9999833164100727,
 
667
        0.9999985691438767,
 
668
        0.9999998906925558,
 
669
        0.9999999924734159,
 
670
        0.9999999995283275,
 
671
        0.9999999999728814,
 
672
        0.9999999999985598,
 
673
        0.9999999999999289,
 
674
        0.9999999999999968,
 
675
        0.9999999999999999,
 
676
        1.0000000000000000
 
677
    };
 
678
    double a, u, ustar, umin;
 
679
    int i;
 
680
 
 
681
    a = 0.;
 
682
    /* precaution if u = 0 is ever returned */
 
683
    u = RNG_UNIF01();
 
684
    while(u <= 0.0 || u >= 1.0) u = RNG_UNIF01();
 
685
    for (;;) {
 
686
        u += u;
 
687
        if (u > 1.0)
 
688
            break;
 
689
        a += q[0];
 
690
    }
 
691
    u -= 1.;
 
692
 
 
693
    if (u <= q[0])
 
694
        return a + u;
 
695
 
 
696
    i = 0;
 
697
    ustar = RNG_UNIF01();
 
698
    umin = ustar;
 
699
    do {
 
700
        ustar = RNG_UNIF01();
 
701
        if (ustar < umin)
 
702
            umin = ustar;
 
703
        i++;
 
704
    } while (u > q[i]);
 
705
    return a + umin * q[0];
 
706
}
 
707
 
 
708
/*
 
709
 *  Mathlib : A C Library of Special Functions
 
710
 *  Copyright (C) 1998 Ross Ihaka
 
711
 *  Copyright (C) 2000-2001 The R Development Core Team
 
712
 *
 
713
 *  This program is free software; you can redistribute it and/or modify
 
714
 *  it under the terms of the GNU General Public License as published by
 
715
 *  the Free Software Foundation; either version 2 of the License, or
 
716
 *  (at your option) any later version.
 
717
 *
 
718
 *  This program is distributed in the hope that it will be useful,
 
719
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
720
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
721
 *  GNU General Public License for more details.
 
722
 *
 
723
 *  You should have received a copy of the GNU General Public License
 
724
 *  along with this program; if not, write to the Free Software
 
725
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA.
 
726
 *
 
727
 *  SYNOPSIS
 
728
 *
 
729
 *    #include <Rmath.h>
 
730
 *    double rpois(double lambda)
 
731
 *
 
732
 *  DESCRIPTION
 
733
 *
 
734
 *    Random variates from the Poisson distribution.
 
735
 *
 
736
 *  REFERENCE
 
737
 *
 
738
 *    Ahrens, J.H. and Dieter, U. (1982).
 
739
 *    Computer generation of Poisson deviates
 
740
 *    from modified normal distributions.
 
741
 *    ACM Trans. Math. Software 8, 163-179.
 
742
 */
 
743
 
 
744
#define a0      -0.5
 
745
#define a1       0.3333333
 
746
#define a2      -0.2500068
 
747
#define a3       0.2000118
 
748
#define a4      -0.1661269
 
749
#define a5       0.1421878
 
750
#define a6      -0.1384794
 
751
#define a7       0.1250060
 
752
 
 
753
#define one_7   0.1428571428571428571
 
754
#define one_12  0.0833333333333333333
 
755
#define one_24  0.0416666666666666667
 
756
 
 
757
#define repeat for(;;)
 
758
 
 
759
#define FALSE 0
 
760
#define TRUE  1
 
761
#define M_1_SQRT_2PI    0.398942280401432677939946059934     /* 1/sqrt(2pi) */
 
762
 
 
763
double igraph_rpois(double mu)
 
764
{
 
765
    /* Factorial Table (0:9)! */
 
766
    const double fact[10] =
 
767
    {
 
768
        1., 1., 2., 6., 24., 120., 720., 5040., 40320., 362880.
 
769
    };
 
770
 
 
771
    /* These are static --- persistent between calls for same mu : */
 
772
    static int l, m;
 
773
 
 
774
    static double b1, b2, c, c0, c1, c2, c3;
 
775
    static double pp[36], p0, p, q, s, d, omega;
 
776
    static double big_l;/* integer "w/o overflow" */
 
777
    static double muprev = 0., muprev2 = 0.;/*, muold    = 0.*/
 
778
 
 
779
    /* Local Vars  [initialize some for -Wall]: */
 
780
    double del, difmuk= 0., E= 0., fk= 0., fx, fy, g, px, py, t, u= 0., v, x;
 
781
    double pois = -1.;
 
782
    int k, kflag, big_mu, new_big_mu = FALSE;
 
783
 
 
784
    if (!R_FINITE(mu))
 
785
        ML_ERR_return_NAN;
 
786
 
 
787
    if (mu <= 0.)
 
788
        return 0.;
 
789
 
 
790
    big_mu = mu >= 10.;
 
791
    if(big_mu)
 
792
        new_big_mu = FALSE;
 
793
 
 
794
    if (!(big_mu && mu == muprev)) {/* maybe compute new persistent par.s */
 
795
 
 
796
        if (big_mu) {
 
797
            new_big_mu = TRUE;
 
798
            /* Case A. (recalculation of s,d,l  because mu has changed):
 
799
             * The poisson probabilities pk exceed the discrete normal
 
800
             * probabilities fk whenever k >= m(mu).
 
801
             */
 
802
            muprev = mu;
 
803
            s = sqrt(mu);
 
804
            d = 6. * mu * mu;
 
805
            big_l = floor(mu - 1.1484);
 
806
            /* = an upper bound to m(mu) for all mu >= 10.*/
 
807
        }
 
808
        else { /* Small mu ( < 10) -- not using normal approx. */
 
809
 
 
810
            /* Case B. (start new table and calculate p0 if necessary) */
 
811
 
 
812
            /*muprev = 0.;-* such that next time, mu != muprev ..*/
 
813
            if (mu != muprev) {
 
814
                muprev = mu;
 
815
                m = imax2(1, (int) mu);
 
816
                l = 0; /* pp[] is already ok up to pp[l] */
 
817
                q = p0 = p = exp(-mu);
 
818
            }
 
819
 
 
820
            repeat {
 
821
                /* Step U. uniform sample for inversion method */
 
822
                u = RNG_UNIF01();
 
823
                if (u <= p0)
 
824
                    return 0.;
 
825
 
 
826
                /* Step T. table comparison until the end pp[l] of the
 
827
                   pp-table of cumulative poisson probabilities
 
828
                   (0.458 > ~= pp[9](= 0.45792971447) for mu=10 ) */
 
829
                if (l != 0) {
 
830
                    for (k = (u <= 0.458) ? 1 : imin2(l, m);  k <= l; k++)
 
831
                        if (u <= pp[k])
 
832
                            return (double)k;
 
833
                    if (l == 35) /* u > pp[35] */
 
834
                        continue;
 
835
                }
 
836
                /* Step C. creation of new poisson
 
837
                   probabilities p[l..] and their cumulatives q =: pp[k] */
 
838
                l++;
 
839
                for (k = l; k <= 35; k++) {
 
840
                    p *= mu / k;
 
841
                    q += p;
 
842
                    pp[k] = q;
 
843
                    if (u <= q) {
 
844
                        l = k;
 
845
                        return (double)k;
 
846
                    }
 
847
                }
 
848
                l = 35;
 
849
            } /* end(repeat) */
 
850
        }/* mu < 10 */
 
851
 
 
852
    } /* end {initialize persistent vars} */
 
853
 
 
854
/* Only if mu >= 10 : ----------------------- */
 
855
 
 
856
    /* Step N. normal sample */
 
857
    g = mu + s * igraph_norm_rand();/* norm_rand() ~ N(0,1), standard normal */
 
858
 
 
859
    if (g >= 0.) {
 
860
        pois = floor(g);
 
861
        /* Step I. immediate acceptance if pois is large enough */
 
862
        if (pois >= big_l)
 
863
            return pois;
 
864
        /* Step S. squeeze acceptance */
 
865
        fk = pois;
 
866
        difmuk = mu - fk;
 
867
        u = RNG_UNIF01(); /* ~ U(0,1) - sample */
 
868
        if (d * u >= difmuk * difmuk * difmuk)
 
869
            return pois;
 
870
    }
 
871
 
 
872
    /* Step P. preparations for steps Q and H.
 
873
       (recalculations of parameters if necessary) */
 
874
 
 
875
    if (new_big_mu || mu != muprev2) {
 
876
        /* Careful! muprev2 is not always == muprev
 
877
           because one might have exited in step I or S
 
878
           */
 
879
        muprev2 = mu;
 
880
        omega = M_1_SQRT_2PI / s;
 
881
        /* The quantities b1, b2, c3, c2, c1, c0 are for the Hermite
 
882
         * approximations to the discrete normal probabilities fk. */
 
883
 
 
884
        b1 = one_24 / mu;
 
885
        b2 = 0.3 * b1 * b1;
 
886
        c3 = one_7 * b1 * b2;
 
887
        c2 = b2 - 15. * c3;
 
888
        c1 = b1 - 6. * b2 + 45. * c3;
 
889
        c0 = 1. - b1 + 3. * b2 - 15. * c3;
 
890
        c = 0.1069 / mu; /* guarantees majorization by the 'hat'-function. */
 
891
    }
 
892
 
 
893
    if (g >= 0.) {
 
894
        /* 'Subroutine' F is called (kflag=0 for correct return) */
 
895
        kflag = 0;
 
896
        goto Step_F;
 
897
    }
 
898
 
 
899
 
 
900
    repeat {
 
901
        /* Step E. Exponential Sample */
 
902
 
 
903
        E = igraph_exp_rand();  /* ~ Exp(1) (standard exponential) */
 
904
 
 
905
        /*  sample t from the laplace 'hat'
 
906
            (if t <= -0.6744 then pk < fk for all mu >= 10.) */
 
907
        u = 2 * RNG_UNIF01() - 1.;
 
908
        t = 1.8 + fsign(E, u);
 
909
        if (t > -0.6744) {
 
910
            pois = floor(mu + s * t);
 
911
            fk = pois;
 
912
            difmuk = mu - fk;
 
913
 
 
914
            /* 'subroutine' F is called (kflag=1 for correct return) */
 
915
            kflag = 1;
 
916
 
 
917
          Step_F: /* 'subroutine' F : calculation of px,py,fx,fy. */
 
918
 
 
919
            if (pois < 10) { /* use factorials from table fact[] */
 
920
                px = -mu;
 
921
                py = pow(mu, pois) / fact[(int)pois];
 
922
            }
 
923
            else {
 
924
                /* Case pois >= 10 uses polynomial approximation
 
925
                   a0-a7 for accuracy when advisable */
 
926
                del = one_12 / fk;
 
927
                del = del * (1. - 4.8 * del * del);
 
928
                v = difmuk / fk;
 
929
                if (fabs(v) <= 0.25)
 
930
                    px = fk * v * v * (((((((a7 * v + a6) * v + a5) * v + a4) *
 
931
                                          v + a3) * v + a2) * v + a1) * v + a0)
 
932
                        - del;
 
933
                else /* |v| > 1/4 */
 
934
                    px = fk * log(1. + v) - difmuk - del;
 
935
                py = M_1_SQRT_2PI / sqrt(fk);
 
936
            }
 
937
            x = (0.5 - difmuk) / s;
 
938
            x *= x;/* x^2 */
 
939
            fx = -0.5 * x;
 
940
            fy = omega * (((c3 * x + c2) * x + c1) * x + c0);
 
941
            if (kflag > 0) {
 
942
                /* Step H. Hat acceptance (E is repeated on rejection) */
 
943
                if (c * fabs(u) <= py * exp(px + E) - fy * exp(fx + E))
 
944
                    break;
 
945
            } else
 
946
                /* Step Q. Quotient acceptance (rare case) */
 
947
                if (fy - u * fy <= py * exp(px - fx))
 
948
                    break;
 
949
        }/* t > -.67.. */
 
950
    }
 
951
    return pois;
 
952
}
 
953
 
 
954
double igraph_rgeom(double p) {
 
955
    if (ISNAN(p) || p <= 0 || p > 1) ML_ERR_return_NAN;
 
956
 
 
957
    return igraph_rpois(igraph_exp_rand() * ((1 - p) / p));
 
958
}
 
959
 
 
960
/* This is from nmath/rbinom.c */
 
961
 
 
962
#define repeat for(;;)
 
963
 
 
964
double igraph_rbinom(double nin, double pp)
 
965
{
 
966
    /* FIXME: These should become THREAD_specific globals : */
 
967
 
 
968
    static double c, fm, npq, p1, p2, p3, p4, qn;
 
969
    static double xl, xll, xlr, xm, xr;
 
970
 
 
971
    static double psave = -1.0;
 
972
    static int nsave = -1;
 
973
    static int m;
 
974
 
 
975
    double f, f1, f2, u, v, w, w2, x, x1, x2, z, z2;
 
976
    double p, q, np, g, r, al, alv, amaxp, ffm, ynorm;
 
977
    int i,ix,k, n;
 
978
 
 
979
    if (!R_FINITE(nin)) ML_ERR_return_NAN;
 
980
    n = floor(nin + 0.5);
 
981
    if (n != nin) ML_ERR_return_NAN;
 
982
 
 
983
    if (!R_FINITE(pp) ||
 
984
        /* n=0, p=0, p=1 are not errors <TSL>*/
 
985
        n < 0 || pp < 0. || pp > 1.)    ML_ERR_return_NAN;
 
986
 
 
987
    if (n == 0 || pp == 0.) return 0;
 
988
    if (pp == 1.) return n;
 
989
 
 
990
    p = fmin(pp, 1. - pp);
 
991
    q = 1. - p;
 
992
    np = n * p;
 
993
    r = p / q;
 
994
    g = r * (n + 1);
 
995
 
 
996
    /* Setup, perform only when parameters change [using static (globals): */
 
997
 
 
998
    /* FIXING: Want this thread safe
 
999
       -- use as little (thread globals) as possible
 
1000
    */
 
1001
    if (pp != psave || n != nsave) {
 
1002
        psave = pp;
 
1003
        nsave = n;
 
1004
        if (np < 30.0) {
 
1005
            /* inverse cdf logic for mean less than 30 */
 
1006
            qn = pow(q, (double) n);
 
1007
            goto L_np_small;
 
1008
        } else {
 
1009
            ffm = np + p;
 
1010
            m = ffm;
 
1011
            fm = m;
 
1012
            npq = np * q;
 
1013
            p1 = (int)(2.195 * sqrt(npq) - 4.6 * q) + 0.5;
 
1014
            xm = fm + 0.5;
 
1015
            xl = xm - p1;
 
1016
            xr = xm + p1;
 
1017
            c = 0.134 + 20.5 / (15.3 + fm);
 
1018
            al = (ffm - xl) / (ffm - xl * p);
 
1019
            xll = al * (1.0 + 0.5 * al);
 
1020
            al = (xr - ffm) / (xr * q);
 
1021
            xlr = al * (1.0 + 0.5 * al);
 
1022
            p2 = p1 * (1.0 + c + c);
 
1023
            p3 = p2 + c / xll;
 
1024
            p4 = p3 + c / xlr;
 
1025
        }
 
1026
    } else if (n == nsave) {
 
1027
        if (np < 30.0)
 
1028
            goto L_np_small;
 
1029
    }
 
1030
 
 
1031
    /*-------------------------- np = n*p >= 30 : ------------------- */
 
1032
    repeat {
 
1033
      u = RNG_UNIF01() * p4;
 
1034
      v = RNG_UNIF01();
 
1035
      /* triangular region */
 
1036
      if (u <= p1) {
 
1037
          ix = xm - p1 * v + u;
 
1038
          goto finis;
 
1039
      }
 
1040
      /* parallelogram region */
 
1041
      if (u <= p2) {
 
1042
          x = xl + (u - p1) / c;
 
1043
          v = v * c + 1.0 - fabs(xm - x) / p1;
 
1044
          if (v > 1.0 || v <= 0.)
 
1045
              continue;
 
1046
          ix = x;
 
1047
      } else {
 
1048
          if (u > p3) { /* right tail */
 
1049
              ix = xr - log(v) / xlr;
 
1050
              if (ix > n)
 
1051
                  continue;
 
1052
              v = v * (u - p3) * xlr;
 
1053
          } else {/* left tail */
 
1054
              ix = xl + log(v) / xll;
 
1055
              if (ix < 0)
 
1056
                  continue;
 
1057
              v = v * (u - p2) * xll;
 
1058
          }
 
1059
      }
 
1060
      /* determine appropriate way to perform accept/reject test */
 
1061
      k = abs(ix - m);
 
1062
      if (k <= 20 || k >= npq / 2 - 1) {
 
1063
          /* explicit evaluation */
 
1064
          f = 1.0;
 
1065
          if (m < ix) {
 
1066
              for (i = m + 1; i <= ix; i++)
 
1067
                  f *= (g / i - r);
 
1068
          } else if (m != ix) {
 
1069
              for (i = ix + 1; i <= m; i++)
 
1070
                  f /= (g / i - r);
 
1071
          }
 
1072
          if (v <= f)
 
1073
              goto finis;
 
1074
      } else {
 
1075
          /* squeezing using upper and lower bounds on log(f(x)) */
 
1076
          amaxp = (k / npq) * ((k * (k / 3. + 0.625) + 0.1666666666666) / npq + 0.5);
 
1077
          ynorm = -k * k / (2.0 * npq);
 
1078
          alv = log(v);
 
1079
          if (alv < ynorm - amaxp)
 
1080
              goto finis;
 
1081
          if (alv <= ynorm + amaxp) {
 
1082
              /* stirling's formula to machine accuracy */
 
1083
              /* for the final acceptance/rejection test */
 
1084
              x1 = ix + 1;
 
1085
              f1 = fm + 1.0;
 
1086
              z = n + 1 - fm;
 
1087
              w = n - ix + 1.0;
 
1088
              z2 = z * z;
 
1089
              x2 = x1 * x1;
 
1090
              f2 = f1 * f1;
 
1091
              w2 = w * w;
 
1092
              if (alv <= xm * log(f1 / x1) + (n - m + 0.5) * log(z / w) + (ix - m) * log(w * p / (x1 * q)) + (13860.0 - (462.0 - (132.0 - (99.0 - 140.0 / f2) / f2) / f2) / f2) / f1 / 166320.0 + (13860.0 - (462.0 - (132.0 - (99.0 - 140.0 / z2) / z2) / z2) / z2) / z / 166320.0 + (13860.0 - (462.0 - (132.0 - (99.0 - 140.0 / x2) / x2) / x2) / x2) / x1 / 166320.0 + (13860.0 - (462.0 - (132.0 - (99.0 - 140.0 / w2) / w2) / w2) / w2) / w / 166320.)
 
1093
                  goto finis;
 
1094
          }
 
1095
      }
 
1096
  }
 
1097
 
 
1098
 L_np_small:
 
1099
    /*---------------------- np = n*p < 30 : ------------------------- */
 
1100
 
 
1101
  repeat {
 
1102
     ix = 0;
 
1103
     f = qn;
 
1104
     u = RNG_UNIF01();
 
1105
     repeat {
 
1106
         if (u < f)
 
1107
             goto finis;
 
1108
         if (ix > 110)
 
1109
             break;
 
1110
         u -= f;
 
1111
         ix++;
 
1112
         f *= (g / ix - r);
 
1113
     }
 
1114
  }
 
1115
 finis:
 
1116
    if (psave > 0.5)
 
1117
         ix = n - ix;
 
1118
  return (double)ix;
 
1119
}
 
1120
 
 
1121
#endif
 
1122
 
 
1123
/**********************************************************
 
1124
 * Testing purposes                                       *
 
1125
 *********************************************************/
 
1126
 
 
1127
/* int main() { */
 
1128
 
 
1129
/*   int i; */
 
1130
 
 
1131
/*   for (i=0; i<100; i++) { */
 
1132
/*     printf("%i ", RNG_INTEGER(0,10)); */
 
1133
/*   } */
 
1134
/*   printf("\n"); */
 
1135
 
 
1136
/*   for (i=0; i<100; i++) { */
 
1137
/*     printf("%f ", RNG_UNIF(0,1)); */
 
1138
/*   } */
 
1139
/*   printf("\n"); */
 
1140
 
 
1141
/*   for (i=0; i<100; i++) { */
 
1142
/*     printf("%f ", RNG_NORMAL(0,5)); */
 
1143
/*   } */
 
1144
/*   printf("\n"); */
 
1145
 
 
1146
/* } */
 
1147
 
 
1148