STK++ 1.0
STK_RandBase.cpp
Go to the documentation of this file.
00001 /*--------------------------------------------------------------------*/
00002 /*     Copyright (C) 2004  Serge Iovleff
00003 
00004     This program is free software; you can redistribute it and/or modify
00005     it under the terms of the GNU Lesser General Public License as
00006     published by the Free Software Foundation; either version 2 of the
00007     License, or (at your option) any later version.
00008 
00009     This program is distributed in the hope that it will be useful,
00010     but WITHOUT ANY WARRANTY; without even the implied warranty of
00011     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012     GNU Lesser General Public License for more details.
00013 
00014     You should have received a copy of the GNU Lesser General Public
00015     License along with this program; if not, write to the
00016     Free Software Foundation, Inc.,
00017     59 Temple Place,
00018     Suite 330,
00019     Boston, MA 02111-1307
00020     USA
00021 
00022     Contact : Serge.Iovleff@stkpp.org                                   */
00023 
00024 /*
00025  * Project:  Analysis
00026  * Purpose:  implementation of the class RandBase
00027  * Author:   Serge Iovleff, serge.iovleff@stkpp.org
00028  **/
00029 
00035 #include "../include/STK_RandBase.h"
00036 
00037 namespace STK
00038 {
00039 
00040 /* Initialize with a simple Integer seed.                             */
00041 RandBase::RandBase( Integer const& oneSeed
00042                   , Real const&    glimit
00043                   , Real const&    gvol
00044                   , Integer const& gsize
00045                   )
00046                   : MTRand( (uint32)oneSeed )
00047                   , gsize_(gsize)
00048                   , glimit_(glimit)
00049                   , gvol_(gvol)
00050 {
00051   gaussInit();
00052 }
00053 
00054 /* auto-initialize with /dev/urandom or time() and clock() */
00055 RandBase::RandBase( Real const&    glimit
00056                   , Real const&    gvol
00057                   , Integer const& gsize
00058                   )
00059                   : MTRand()
00060                   , gsize_(gsize)
00061                   , glimit_(glimit)
00062                   , gvol_(gvol)
00063 {
00064   gaussInit();
00065 }
00066 
00067 /* destructor.                                                            */
00068 RandBase::~RandBase()
00069 {
00070   delete [] kn;
00071   delete [] wn;
00072   delete [] fn;
00073 }
00074 
00075 /* Pseudo-random gaussian generator.
00076  * \f[     f(x) = \frac{1}{\sqrt{2\pi}}
00077  *         \exp\left\{-\frac{x^2}{2}\right\}
00078  * \f]
00079  *  Return a real number from a normal (Gaussian) normalized
00080  *  distribution.
00081 **/
00082 Real RandBase::randGauss(Real const& mu, Real const& sigma)
00083 {
00084   while(1)
00085   {
00086     // uniforms number
00087     Real u = 2.0 * randUnif() - 1.0;
00088     // random box
00089     uint32 i = randInt() & 0x7F; //
00090     // squeeze step : try the rectangular boxes
00091     if (abs(u) < wn[i]) return mu + sigma * u * kn[i];
00092     // bottom box: we have to sample from the tail
00093     if (i == 0)
00094     {
00095       // result
00096       Real x;
00097       // loop
00098       do { x = randExp() / glimit_;}
00099       while ( 2.0 * randExp() < x * x);
00100       // result sign(u) * (x+dr)
00101       return mu + sigma * sign(u, x+glimit_);
00102     }
00103     else // other box
00104     { // x : result, f1 : intermediary result
00105       Real x = u * kn[i], f1 = fn[i+1];
00106       // reject step : is this a sample from the wedges ?
00107       if ( f1 + randUnif()*( fn[i]*exp(x*x/2.)-f1) < 1.0)
00108       { return mu + sigma * x;}
00109     }
00110   }
00111   // avoid warning at compilation
00112   return 0.;
00113 }
00114 
00115 /* Pseudo-random exponential generator.
00116  * \f[ 
00117  *      f(x) = \exp\left\{ -x \right\}
00118  * \f]
00119  *  Return a real number from an exponential normalized
00120  *  distribution.
00121 **/
00122 Real RandBase::randExp()
00123 {
00124   return -log(1.-randUnif());
00125 }
00126 
00127 /* Initialization (Zigourrat method).  */
00128 void RandBase::gaussInit()
00129 {
00130   kn = new Real[gsize_+1];
00131   wn = new Real[gsize_];
00132   fn = new Real[gsize_+1];
00133 
00134   Real f = exp(-0.5 * glimit_ * glimit_);
00135   kn[0]  = gvol_ / f; // [0] is bottom block: gvol/f(gbound)
00136 
00137   kn[gsize_] = 0;
00138   fn[gsize_] = 1;
00139 
00140   kn[1]  = glimit_;
00141   fn[1]  = f;
00142 
00143   for (Integer i = 2; i < gsize_; ++i)
00144   {
00145     kn[i] = sqrt(-2 * log(gvol_ / kn[i-1] + f));
00146     fn[i] = (f = exp(-0.5 * kn[i] * kn[i]));
00147   }
00148   for (Integer i = 0; i < gsize_; ++i)
00149     wn[i] = kn[i + 1] / kn[i];
00150 }
00151 
00152 } // namespace STK