|
STK++ 1.0
|
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