root/win32/itpp-4.0.1/itpp/base/random.h @ 109

Revision 35, 27.2 kB (checked in by mido, 16 years ago)

zasadni zmeny ve /win32

Line 
1/*!
2 * \file
3 * \brief Definition of classes for random number generators
4 * \author Tony Ottosson and Adam Piatyszek
5 *
6 * -------------------------------------------------------------------------
7 *
8 * IT++ - C++ library of mathematical, signal processing, speech processing,
9 *        and communications classes and functions
10 *
11 * Copyright (C) 1995-2007  (see AUTHORS file for a list of contributors)
12 *
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
17 *
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21 * GNU General Public License for more details.
22 *
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
26 *
27 * -------------------------------------------------------------------------
28 */
29
30#ifndef RANDOM_H
31#define RANDOM_H
32
33#include <itpp/base/operators.h>
34#include <ctime>
35
36
37namespace itpp {
38
39  //! \addtogroup randgen
40
41  /*!
42   * \brief Base class for random (stochastic) sources.
43   * \ingroup randgen
44   *
45   * The Random_Generator class is based on the MersenneTwister MTRand
46   * class code in version 1.0 (15 May 2003) by Richard J. Wagner. See
47   * http://www-personal.engin.umich.edu/~wagnerr/MersenneTwister.html
48   * for details.
49   *
50   * Here are the original release notes copied from the
51   * \c MersenneTwister.h file:
52   *
53   * \verbatim
54   * Mersenne Twister random number generator -- a C++ class MTRand Based on
55   * code by Makoto Matsumoto, Takuji Nishimura, and Shawn Cokus Richard J.
56   * Wagner v1.0 15 May 2003 rjwagner@writeme.com
57   *
58   * The Mersenne Twister is an algorithm for generating random numbers. It
59   * was designed with consideration of the flaws in various other generators.
60   * The period, 2^19937-1, and the order of equidistribution, 623 dimensions,
61   * are far greater. The generator is also fast; it avoids multiplication and
62   * division, and it benefits from caches and pipelines. For more information
63   * see the inventors' web page at
64   * http://www.math.keio.ac.jp/~matumoto/emt.html
65
66   * Reference:
67   * M. Matsumoto and T. Nishimura, "Mersenne Twister: A 623-Dimensionally
68   * Equidistributed Uniform Pseudo-Random Number Generator", ACM Transactions
69   * on Modeling and Computer Simulation, Vol. 8, No. 1, January 1998, pp.
70   * 3-30.
71   *
72   * Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura,
73   * Copyright (C) 2000 - 2003, Richard J. Wagner
74   * All rights reserved.
75   *
76   * Redistribution and use in source and binary forms, with or without
77   * modification, are permitted provided that the following conditions
78   * are met:
79   *
80   *   1. Redistributions of source code must retain the above copyright
81   *      notice, this list of conditions and the following disclaimer.
82   *
83   *   2. Redistributions in binary form must reproduce the above copyright
84   *      notice, this list of conditions and the following disclaimer in the
85   *      documentation and/or other materials provided with the distribution.
86   *
87   *   3. The names of its contributors may not be used to endorse or promote
88   *      products derived from this software without specific prior written
89   *      permission.
90   *
91   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
92   * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
93   * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
94   * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
95   * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
96   * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
97   * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
98   * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
99   * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
100   * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
101   * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
102   *
103   * The original code included the following notice:
104   *
105   *     When you use this, send an email to: matumoto@math.keio.ac.jp with an
106   *     appropriate reference to your work.
107   *
108   * It would be nice to CC: rjwagner@writeme.com and
109   * Cokus@math.washington.edu when you write.
110   * \endverbatim
111   */
112  class Random_Generator {
113  public:
114    //! Construct a new Random_Generator.
115    Random_Generator() { if (!initialized) reset(4357U); }
116    //! Construct Random_Generator object using \c seed
117    Random_Generator(unsigned int seed) { reset(seed); }
118    //! Set the seed to a semi-random value (based on hashed time and clock).
119    void randomize() { reset(hash(time(0), clock())); }
120    //! Reset the source. The same sequance will be generated as the last time.
121    void reset() { initialize(last_seed); reload(); initialized = true; }
122    //! Reset the source after setting the seed to seed.
123    void reset(unsigned int seed) { last_seed = seed; reset(); }
124
125    //! Return a uniformly distributed [0,2^32-1] integer.
126    unsigned int random_int()
127    {
128      if( left == 0 ) reload();
129      --left;
130
131      register unsigned int s1;
132      s1 = *pNext++;
133      s1 ^= (s1 >> 11);
134      s1 ^= (s1 <<  7) & 0x9d2c5680U;
135      s1 ^= (s1 << 15) & 0xefc60000U;
136      return ( s1 ^ (s1 >> 18) );
137    }
138
139    //! Return a uniformly distributed (0,1) value.
140    double random_01() { return (random_int() + 0.5) * (1.0/4294967296.0); }
141    //! Return a uniformly distributed [0,1) value.
142    double random_01_lclosed() { return random_int() * (1.0/4294967296.0); }
143    //! Return a uniformly distributed [0,1] value.
144    double random_01_closed() { return random_int() * (1.0/4294967295.0); }
145    //! Return a uniformly distributed [0,1) value in 53-bit resolution.
146    double random53_01_lclosed()
147    {
148      return ((random_int() >> 5) * 67108864.0 + (random_int() >> 6))
149        * (1.0/9007199254740992.0); // by Isaku Wada
150    }
151
152    //! Save current full state of generator in memory
153    void get_state(ivec &out_state);
154    //! Resume the state saved in memory. Clears memory.
155    void set_state(ivec &new_state);
156
157  private:
158    //! initialization flag
159    static bool initialized;
160    //! seed used for initialisation
161    unsigned int last_seed;
162    //! internal state
163    static unsigned int state[624];
164    //! next value to get from state
165    static unsigned int *pNext;
166    //! number of values left before reload needed
167    static int left;
168
169    /*!
170     * \brief Initialize generator state with seed.
171     * See Knuth TAOCP Vol 2, 3rd Ed, p.106 for multiplier.
172     * \note In previous versions, most significant bits (MSBs) of the seed
173     * affect only MSBs of the state array. Modified 9 Jan 2002 by Makoto
174     * Matsumoto.
175     */
176    void initialize( unsigned int seed )
177    {
178      register unsigned int *s = state;
179      register unsigned int *r = state;
180      register int i = 1;
181      *s++ = seed & 0xffffffffU;
182      for( ; i < 624; ++i )
183        {
184          *s++ = ( 1812433253U * ( *r ^ (*r >> 30) ) + i ) & 0xffffffffU;
185          r++;
186        }
187    }
188
189    /*!
190     * \brief Generate N new values in state.
191     * Made clearer and faster by Matthew Bellew (matthew.bellew@home.com)
192     */
193    void reload()
194    {
195      register unsigned int *p = state;
196      register int i;
197      for( i = 624 - 397; i--; ++p )
198        *p = twist( p[397], p[0], p[1] );
199      for( i = 397; --i; ++p )
200        *p = twist( p[397-624], p[0], p[1] );
201      *p = twist( p[397-624], p[0], state[0] );
202
203      left = 624, pNext = state;
204    }
205    //!
206    unsigned int hiBit( const unsigned int& u ) const { return u & 0x80000000U; }
207    //!
208    unsigned int loBit( const unsigned int& u ) const { return u & 0x00000001U; }
209    //!
210    unsigned int loBits( const unsigned int& u ) const { return u & 0x7fffffffU; }
211    //!
212    unsigned int mixBits( const unsigned int& u, const unsigned int& v ) const
213    { return hiBit(u) | loBits(v); }
214
215    /*
216     * ----------------------------------------------------------------------
217     * --- ediap - 2007/01/17 ---
218     * ----------------------------------------------------------------------
219     * Wagners's implementation of the twist() function was as follows:
220     *  { return m ^ (mixBits(s0,s1)>>1) ^ (-loBit(s1) & 0x9908b0dfU); }
221     * However, this code caused a warning/error under MSVC++, because
222     * unsigned value loBit(s1) is being negated with `-' (c.f. bug report
223     * [1635988]). I changed this to the same implementation as is used in
224     * original C sources of Mersenne Twister RNG:
225     *  #define MATRIX_A 0x9908b0dfUL
226     *  #define UMASK 0x80000000UL
227     *  #define LMASK 0x7fffffffUL
228     *  #define MIXBITS(u,v) ( ((u) & UMASK) | ((v) & LMASK) )
229     *  #define TWIST(u,v) ((MIXBITS(u,v) >> 1) ^ ((v)&1UL ? MATRIX_A : 0UL))
230     * ----------------------------------------------------------------------
231     */
232    //!
233    unsigned int twist( const unsigned int& m, const unsigned int& s0,
234                        const unsigned int& s1 ) const
235    { return m ^ (mixBits(s0,s1)>>1) ^ (loBit(s1) ? 0x9908b0dfU : 0U); }
236    //!
237    unsigned int hash( time_t t, clock_t c );
238  };
239
240
241  //! \addtogroup randgen
242  //!@{
243
244  //! Set the seed of the Global Random Number Generator
245  void RNG_reset(unsigned int seed);
246  //! Set the seed of the Global Random Number Generator to the same as last reset/init
247  void RNG_reset();
248  //! Set a random seed for the Global Random Number Generator.
249  void RNG_randomize();
250  //! Save current full state of generator in memory
251  void RNG_get_state(ivec &state);
252  //! Resume the state saved in memory
253  void RNG_set_state(ivec &state);
254  //!@}
255
256  /*!
257    \brief Bernoulli distribution
258    \ingroup randgen
259  */
260  class Bernoulli_RNG {
261  public:
262    //! Binary source with probability prob for a 1
263    Bernoulli_RNG(double prob) { setup(prob); }
264    //! Binary source with probability prob for a 1
265    Bernoulli_RNG() { p=0.5; }
266    //! set the probability
267    void setup(double prob)
268    {
269      it_assert(prob>=0.0 && prob<=1.0, "The bernoulli source probability must be between 0 and 1");
270      p = prob;
271    }
272    //! return the probability
273    double get_setup() const { return p; }
274    //! Get one sample.
275    bin operator()() { return sample(); }
276    //! Get a sample vector.
277    bvec operator()(int n) { bvec temp(n); sample_vector(n, temp); return temp; }
278    //! Get a sample matrix.
279    bmat operator()(int h, int w) { bmat temp(h, w); sample_matrix(h, w, temp); return temp; }
280    //! Get a sample
281    bin sample() { return bin( RNG.random_01() < p ? 1 : 0 ); }
282    //! Get a sample vector.
283    void sample_vector(int size, bvec &out)
284    {
285      out.set_size(size, false);
286      for (int i=0; i<size; i++) out(i) = sample();
287    }
288    //! Get a sample matrix.
289    void sample_matrix(int rows, int cols, bmat &out)
290    {
291      out.set_size(rows, cols, false);
292      for (int i=0; i<rows*cols; i++) out(i) = sample();
293    }
294  protected:
295  private:
296    //!
297    double p;
298    //!
299    Random_Generator RNG;
300  };
301
302  /*!
303    \brief Integer uniform distribution
304    \ingroup randgen
305
306    Example: Generation of random uniformly distributed integers in the interval [0,10].
307    \code
308    #include "itpp/sigproc.h"
309
310    int main() {
311
312    I_Uniform_RNG gen(0, 10);
313
314    cout << gen() << endl; // prints a random integer
315    cout << gen(10) << endl; // prints 10 random integers
316    }
317    \endcode
318  */
319  class I_Uniform_RNG {
320  public:
321    //! constructor. Sets min and max values.
322    I_Uniform_RNG(int min=0, int max=1);
323    //! set min and max values
324    void setup(int min, int max);
325    //! get the parameters
326    void get_setup(int &min, int &max) const;
327    //! Get one sample.
328    int operator()() { return sample(); }
329    //! Get a sample vector.
330    ivec operator()(int n);
331    //! Get a sample matrix.
332    imat operator()(int h, int w);
333    //! Return a single value from this random generator
334    int sample() { return ( floor_i(RNG.random_01() * (hi - lo + 1)) + lo ); }
335  protected:
336  private:
337    //!
338    int lo;
339    //!
340    int hi;
341    //!
342    Random_Generator RNG;
343  };
344
345  /*!
346    \brief Uniform distribution
347    \ingroup randgen
348  */
349  class Uniform_RNG {
350  public:
351    //! Constructor. Set min, max and seed.
352    Uniform_RNG(double min=0, double max=1.0);
353    //! set min and max
354    void setup(double min, double max);
355    //! get parameters
356    void get_setup(double &min, double &max) const;
357    //! Get one sample.
358    double operator()() { return (sample() * (hi_bound - lo_bound) + lo_bound); }
359    //! Get a sample vector.
360    vec operator()(int n)
361    {
362      vec temp(n);
363      sample_vector(n, temp);
364      temp *= hi_bound - lo_bound;
365      temp += lo_bound;
366      return temp;
367    }
368    //! Get a sample matrix.
369    mat operator()(int h, int w)
370    {
371      mat temp(h, w);
372      sample_matrix(h, w, temp);
373      temp *= hi_bound - lo_bound;
374      temp += lo_bound;
375      return temp;
376    }
377    //! Get a Uniformly distributed (0,1) sample
378    double sample() {  return RNG.random_01(); }
379    //! Get a Uniformly distributed (0,1) vector
380    void sample_vector(int size, vec &out)
381    {
382      out.set_size(size, false);
383      for (int i=0; i<size; i++) out(i) = sample();
384    }
385    //! Get a Uniformly distributed (0,1) matrix
386    void sample_matrix(int rows, int cols, mat &out)
387    {
388      out.set_size(rows, cols, false);
389      for (int i=0; i<rows*cols; i++) out(i) = sample();
390    }
391  protected:
392  private:
393    //!
394    double lo_bound, hi_bound;
395    //!
396    Random_Generator RNG;
397  };
398
399  /*!
400    \brief Exponential distribution
401    \ingroup randgen
402  */
403  class Exponential_RNG {
404  public:
405    //! constructor. Set lambda.
406    Exponential_RNG(double lambda=1.0);
407    //! Set lambda
408    void setup(double lambda) { l=lambda; }
409    //! get lambda
410    double get_setup() const;
411    //! Get one sample.
412    double operator()() { return sample(); }
413    //! Get a sample vector.
414    vec operator()(int n);
415    //! Get a sample matrix.
416    mat operator()(int h, int w);
417  protected:
418  private:
419    //!
420    double sample() {  return ( -std::log(RNG.random_01()) / l ); }
421    //!
422    double l;
423    //!
424    Random_Generator RNG;
425  };
426
427  /*!
428   * \brief Normal distribution
429   * \ingroup randgen
430   *
431   * Normal (Gaussian) random variables, using a simplified Ziggurat method.
432   *
433   * For details see the following arcticle: George Marsaglia, Wai Wan
434   * Tsang, "The Ziggurat Method for Generating Random Variables", Journal
435   * of Statistical Software, vol. 5 (2000), no. 8
436   *
437   * This implementation is based on the generator written by Jochen Voss
438   * found at http://seehuhn.de/comp/ziggurat/, which is also included in
439   * the GSL library (randlist/gauss.c).
440   */
441  class Normal_RNG {
442  public:
443    //! Constructor. Set mean and variance.
444    Normal_RNG(double meanval, double variance):
445      mean(meanval), sigma(std::sqrt(variance)) {}
446    //! Constructor. Set mean and variance.
447    Normal_RNG(): mean(0.0), sigma(1.0) {}
448    //! Set mean, and variance
449    void setup(double meanval, double variance)
450    { mean = meanval; sigma = std::sqrt(variance); }
451    //! Get mean and variance
452    void get_setup(double &meanval, double &variance) const;
453    //! Get one sample.
454    double operator()() { return (sigma*sample()+mean); }
455    //! Get a sample vector.
456    vec operator()(int n)
457    {
458      vec temp(n);
459      sample_vector(n, temp);
460      temp *= sigma;
461      temp += mean;
462      return temp;
463    }
464    //! Get a sample matrix.
465    mat operator()(int h, int w)
466    {
467      mat temp(h, w);
468      sample_matrix(h, w, temp);
469      temp *= sigma;
470      temp += mean;
471      return temp;
472    }
473    //! Get a Normal distributed (0,1) sample
474    double sample()
475    {
476      unsigned int u, sign, i, j;
477      double x, y;
478
479      while(true) {
480        u = RNG.random_int();
481        sign = u & 0x80; // 1 bit for the sign
482        i = u & 0x7f; // 7 bits to choose the step
483        j = u >> 8; // 24 bits for the x-value
484
485        x = j * wtab[i];
486
487        if (j < ktab[i])
488          break;
489
490        if (i < 127) {
491          y = ytab[i+1] + (ytab[i] - ytab[i+1]) * RNG.random_01();
492        }
493        else {
494          x = PARAM_R - std::log(1.0 - RNG.random_01()) / PARAM_R;
495          y = std::exp(-PARAM_R * (x - 0.5 * PARAM_R)) * RNG.random_01();
496        }
497
498        if (y < std::exp(-0.5 * x * x))
499          break;
500      }
501      return sign ? x : -x;
502    }
503
504    //! Get a Normal distributed (0,1) vector
505    void sample_vector(int size, vec &out)
506    {
507      out.set_size(size, false);
508      for (int i=0; i<size; i++) out(i) = sample();
509    }
510
511    //! Get a Normal distributed (0,1) matrix
512    void sample_matrix(int rows, int cols, mat &out)
513    {
514      out.set_size(rows, cols, false);
515      for (int i=0; i<rows*cols; i++) out(i) = sample();
516    }
517  private:
518    double mean, sigma;
519    static const double ytab[128];
520    static const unsigned int ktab[128];
521    static const double wtab[128];
522    static const double PARAM_R;
523    Random_Generator RNG;
524  };
525
526  /*!
527    \brief Laplacian distribution
528    \ingroup randgen
529  */
530  class Laplace_RNG {
531  public:
532    //! Constructor. Set mean and variance.
533    Laplace_RNG(double meanval = 0.0, double variance = 1.0);
534    //! Set mean and variance
535    void setup(double meanval, double variance);
536    //! Get mean and variance
537    void get_setup(double &meanval, double &variance) const;
538    //! Get one sample.
539    double operator()() { return sample(); }
540    //! Get a sample vector.
541    vec operator()(int n);
542    //! Get a sample matrix.
543    mat operator()(int h, int w);
544    //! Returns a single sample
545    double sample()
546    {
547      double u = RNG.random_01();
548      double l = sqrt_12var;
549      if (u < 0.5)
550        l *= std::log(2.0 * u);
551      else
552        l *= -std::log(2.0 * (1-u));
553      return (l + mean);
554    }
555  private:
556    double mean, var, sqrt_12var;
557    Random_Generator RNG;
558  };
559
560  /*!
561    \brief A Complex Normal Source
562    \ingroup randgen
563  */
564  class Complex_Normal_RNG {
565  public:
566    //! Constructor. Set mean and variance.
567    Complex_Normal_RNG(std::complex<double> mean, double variance):
568      norm_factor(1.0/std::sqrt(2.0))
569    {
570      setup(mean, variance);
571    }
572    //! Default constructor
573    Complex_Normal_RNG(): m(0.0), sigma(1.0), norm_factor(1.0/std::sqrt(2.0)) {}
574    //! Set mean and variance
575    void setup(std::complex<double> mean, double variance)
576    {
577      m = mean; sigma = std::sqrt(variance);
578    }
579    //! Get mean and variance
580    void get_setup(std::complex<double> &mean, double &variance)
581    {
582      mean = m; variance = sigma*sigma;
583    }
584    //! Get one sample.
585    std::complex<double> operator()() { return sigma*sample()+m; }
586    //! Get a sample vector.
587    cvec operator()(int n)
588    {
589      cvec temp(n);
590      sample_vector(n, temp);
591      temp *= sigma;
592      temp += m;
593      return temp;
594    }
595    //! Get a sample matrix.
596    cmat operator()(int h, int w)
597    {
598      cmat temp(h, w);
599      sample_matrix(h, w, temp);
600      temp *= sigma;
601      temp += m;
602      return temp;
603    }
604    //! Get a Complex Normal (0,1) distributed sample
605    std::complex<double> sample()
606    {
607      double a = nRNG.sample() * norm_factor;
608      double b = nRNG.sample() * norm_factor;
609      return std::complex<double>(a, b);
610    }
611
612    //! Get a Complex Normal (0,1) distributed vector
613    void sample_vector(int size, cvec &out)
614    {
615      out.set_size(size, false);
616      for (int i=0; i<size; i++) out(i) = sample();
617    }
618
619    //! Get a Complex Normal (0,1) distributed matrix
620    void sample_matrix(int rows, int cols, cmat &out)
621    {
622      out.set_size(rows, cols, false);
623      for (int i=0; i<rows*cols; i++) out(i) = sample();
624    }
625  private:
626    std::complex<double> m;
627    double sigma;
628    const double norm_factor;
629    Normal_RNG nRNG;
630  };
631
632  /*!
633    \brief Filtered normal distribution
634    \ingroup randgen
635  */
636  class AR1_Normal_RNG {
637  public:
638    //! Constructor. Set mean, variance, and correlation.
639    AR1_Normal_RNG(double meanval = 0.0, double variance = 1.0,
640                   double rho = 0.0);
641    //! Set mean, variance, and correlation
642    void setup(double meanval, double variance, double rho);
643    //! Get mean, variance and correlation
644    void get_setup(double &meanval, double &variance, double &rho) const;
645    //! Set memory contents to zero
646    void reset();
647    //! Get a single random sample
648    double operator()() { return sample(); }
649    //! Get a sample vector.
650    vec operator()(int n);
651    //! Get a sample matrix.
652    mat operator()(int h, int w);
653  private:
654    double sample()
655    {
656      mem *= r;
657      if (odd) {
658        r1 = m_2pi * RNG.random_01();
659        r2 = std::sqrt(factr * std::log(RNG.random_01()));
660        mem += r2 * std::cos(r1);
661      }
662      else {
663        mem += r2 * std::sin(r1);
664      }
665      odd = !odd;
666      return (mem + mean);
667    }
668    double mem, r, factr, mean, var, r1, r2;
669    bool odd;
670    Random_Generator RNG;
671  };
672
673  /*!
674    \brief Gauss_RNG is the same as Normal Source
675    \ingroup randgen
676  */
677  typedef Normal_RNG Gauss_RNG;
678
679  /*!
680    \brief AR1_Gauss_RNG is the same as AR1_Normal_RNG
681    \ingroup randgen
682  */
683  typedef AR1_Normal_RNG AR1_Gauss_RNG;
684
685  /*!
686    \brief Weibull distribution
687    \ingroup randgen
688  */
689  class Weibull_RNG {
690  public:
691    //! Constructor. Set lambda and beta.
692    Weibull_RNG(double lambda = 1.0, double beta = 1.0);
693    //! Set lambda, and beta
694    void setup(double lambda, double beta);
695    //! Get lambda and beta
696    void get_setup(double &lambda, double &beta) { lambda = l; beta = b; }
697    //! Get one sample.
698    double operator()() { return sample(); }
699    //! Get a sample vector.
700    vec operator()(int n);
701    //! Get a sample matrix.
702    mat operator()(int h, int w);
703  private:
704    double sample()
705    {
706      return (std::pow(-std::log(RNG.random_01()), 1.0/b) / l);
707    }
708    double l, b;
709    double mean, var;
710    Random_Generator RNG;
711  };
712
713  /*!
714    \brief Rayleigh distribution
715    \ingroup randgen
716  */
717  class Rayleigh_RNG {
718  public:
719    //! Constructor. Set sigma.
720    Rayleigh_RNG(double sigma = 1.0);
721    //! Set sigma
722    void setup(double sigma) { sig = sigma; }
723    //! Get sigma
724    double get_setup() { return sig; }
725    //! Get one sample.
726    double operator()() { return sample(); }
727    //! Get a sample vector.
728    vec operator()(int n);
729    //! Get a sample matrix.
730    mat operator()(int h, int w);
731  private:
732    double sample()
733    {
734      double s1 = nRNG.sample();
735      double s2 = nRNG.sample();
736      // s1 and s2 are N(0,1) and independent
737      return (sig * std::sqrt(s1*s1 + s2*s2));
738    }
739    double sig;
740    Normal_RNG nRNG;
741  };
742
743  /*!
744    \brief Rice distribution
745    \ingroup randgen
746  */
747  class Rice_RNG {
748  public:
749    //! Constructor. Set sigma, and v (if v = 0, Rice -> Rayleigh).
750    Rice_RNG(double sigma = 1.0, double v = 1.0);
751    //! Set sigma, and v (if v = 0, Rice -> Rayleigh).
752    void setup(double sigma, double v) { sig = sigma; s = v; }
753    //! Get parameters
754    void get_setup(double &sigma, double &v) { sigma = sig; v = s; }
755    //! Get one sample
756    double operator()() { return sample(); }
757    //! Get a sample vector
758    vec operator()(int n);
759    //! Get a sample matrix
760    mat operator()(int h, int w);
761  private:
762    double sample()
763    {
764      double s1 = nRNG.sample() + s;
765      double s2 = nRNG.sample();
766      // s1 and s2 are N(0,1) and independent
767      return (sig * std::sqrt(s1*s1 + s2*s2));
768    }
769    double sig, s;
770    Normal_RNG nRNG;
771  };
772
773  //! \addtogroup randgen
774  //!@{
775
776  //! Generates a random bit (equally likely 0s and 1s)
777  inline bin randb(void) { Bernoulli_RNG src; return src.sample(); }
778  //! Generates a random bit vector (equally likely 0s and 1s)
779  inline void randb(int size, bvec &out) { Bernoulli_RNG src; src.sample_vector(size, out); }
780  //! Generates a random bit vector (equally likely 0s and 1s)
781  inline bvec randb(int size) { bvec temp; randb(size, temp); return temp; }
782  //! Generates a random bit matrix (equally likely 0s and 1s)
783  inline void randb(int rows, int cols, bmat &out) { Bernoulli_RNG src; src.sample_matrix(rows, cols, out); }
784  //! Generates a random bit matrix (equally likely 0s and 1s)
785  inline bmat randb(int rows, int cols){ bmat temp; randb(rows, cols, temp); return temp; }
786
787  //! Generates a random uniform (0,1) number
788  inline double randu(void) { Uniform_RNG src; return src.sample(); }
789  //! Generates a random uniform (0,1) vector
790  inline void randu(int size, vec &out) { Uniform_RNG src; src.sample_vector(size, out); }
791  //! Generates a random uniform (0,1) vector
792  inline vec randu(int size){ vec temp; randu(size, temp); return temp; }
793  //! Generates a random uniform (0,1) matrix
794  inline void randu(int rows, int cols, mat &out) { Uniform_RNG src; src.sample_matrix(rows, cols, out); }
795  //! Generates a random uniform (0,1) matrix
796  inline mat randu(int rows, int cols) { mat temp; randu(rows, cols, temp); return temp; }
797
798  //! Generates a random integer in the interval [low,high]
799  inline int randi(int low, int high) { I_Uniform_RNG src; src.setup(low, high); return src(); }
800  //! Generates a random ivec with elements in the interval [low,high]
801  inline ivec randi(int size, int low, int high) { I_Uniform_RNG src; src.setup(low, high); return src(size); }
802  //! Generates a random imat with elements in the interval [low,high]
803  inline imat randi(int rows, int cols, int low, int high) { I_Uniform_RNG src; src.setup(low, high); return src(rows, cols); }
804
805  //! Generates a random Rayleigh vector
806  inline vec randray(int size, double sigma = 1.0) { Rayleigh_RNG src; src.setup(sigma); return src(size); }
807
808  //! Generates a random Rice vector (See J.G. Poakis, "Digital Communications, 3rd ed." p.47)
809  inline vec randrice(int size, double sigma = 1.0, double s = 1.0) { Rice_RNG src; src.setup(sigma, s); return src(size); }
810
811  //! Generates a random complex Gaussian vector
812  inline vec randexp(int size, double lambda = 1.0) { Exponential_RNG src; src.setup(lambda); return src(size); }
813
814  //! Generates a random Gaussian (0,1) variable
815  inline double randn(void) { Normal_RNG src; return src.sample(); }
816  //! Generates a random Gaussian (0,1) vector
817  inline void randn(int size, vec &out) { Normal_RNG src; src.sample_vector(size, out); }
818  //! Generates a random Gaussian (0,1) vector
819  inline vec randn(int size) { vec temp; randn(size, temp); return temp; }
820  //! Generates a random Gaussian (0,1) matrix
821  inline void randn(int rows, int cols, mat &out)  { Normal_RNG src; src.sample_matrix(rows, cols, out); }
822  //! Generates a random Gaussian (0,1) matrix
823  inline mat randn(int rows, int cols){ mat temp; randn(rows, cols, temp); return temp; }
824
825  /*! \brief Generates a random complex Gaussian (0,1) variable
826
827  The real and imaginary parts are independent and have variances equal to 0.5
828  */
829  inline std::complex<double> randn_c(void) { Complex_Normal_RNG src; return src.sample(); }
830  //! Generates a random complex Gaussian (0,1) vector
831  inline void randn_c(int size, cvec &out)  { Complex_Normal_RNG src; src.sample_vector(size, out); }
832  //! Generates a random complex Gaussian (0,1) vector
833  inline cvec randn_c(int size){ cvec temp; randn_c(size, temp); return temp; }
834  //! Generates a random complex Gaussian (0,1) matrix
835  inline void randn_c(int rows, int cols, cmat &out) { Complex_Normal_RNG src; src.sample_matrix(rows, cols, out); }
836  //! Generates a random complex Gaussian (0,1) matrix
837  inline cmat randn_c(int rows, int cols) { cmat temp; randn_c(rows, cols, temp); return temp; }
838
839  //!@}
840
841} // namespace itpp
842
843#endif // #ifndef RANDOM_H
Note: See TracBrowser for help on using the browser.