• Skip to content
  • Skip to link menu
KDE 4.1 API Reference
  • KDE API Reference
  • kdelibs
  • Sitemap
  • Contact Us
 

KDECore

krandomsequence.cpp

Go to the documentation of this file.
00001 /*
00002   This file is part of the KDE libraries
00003   Copyright (c) 1999 Sean Harmer <sh@astro.keele.ac.uk>
00004 
00005   This library is free software; you can redistribute it and/or
00006   modify it under the terms of the GNU Library General Public
00007   License as published by the Free Software Foundation; either
00008   version 2 of the License, or (at your option) any later version.
00009 
00010   This library is distributed in the hope that it will be useful,
00011   but WITHOUT ANY WARRANTY; without even the implied warranty of
00012   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013   Library General Public License for more details.
00014 
00015   You should have received a copy of the GNU Library General Public License
00016   along with this library; see the file COPYING.LIB.  If not, write to
00017   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00018   Boston, MA 02110-1301, USA.
00019 */
00020 
00021 #include "krandomsequence.h"
00022 #include "krandom.h"
00023 #include <string.h>
00024 #include <config.h>
00025 
00026 static const int s_nShuffleTableSize = 32;
00027 
00028 class KRandomSequence::Private
00029 {
00030 public:
00031   // Generate the random number
00032   void draw();
00033 
00034   long lngSeed1;
00035   long lngSeed2;
00036   long lngShufflePos;
00037   long shuffleArray[s_nShuffleTableSize];
00038 };
00039 
00041 //  Construction / Destruction
00043 
00044 KRandomSequence::KRandomSequence( long lngSeed1 ) : d(new Private)
00045 {
00046   // Seed the generator
00047   setSeed( lngSeed1 );
00048 }
00049 
00050 KRandomSequence::~KRandomSequence()
00051 {
00052    delete d;
00053 }
00054 
00055 KRandomSequence::KRandomSequence(const KRandomSequence &a) : d(new Private)
00056 {
00057     *d = *a.d;
00058 }
00059 
00060 KRandomSequence & KRandomSequence::operator=(const KRandomSequence &a)
00061 {
00062     if ( this != &a ) {
00063         *d = *a.d;
00064     }
00065     return *this;
00066 }
00067 
00068 
00070 //  Member Functions
00072 
00073 void KRandomSequence::setSeed( long lngSeed1 )
00074 {
00075   // Convert the positive seed number to a negative one so that the draw()
00076   // function can intialise itself the first time it is called. We just have
00077   // to make sure that the seed used != 0 as zero perpetuates itself in a
00078   // sequence of random numbers.
00079   if ( lngSeed1 < 0 )
00080   {
00081     d->lngSeed1 = -1;
00082   }
00083   else if (lngSeed1 == 0)
00084   {
00085     d->lngSeed1 = -((KRandom::random() & ~1)+1);
00086   }
00087   else
00088   {
00089     d->lngSeed1 = -lngSeed1;
00090   }
00091 }
00092 
00093 static const long sMod1           = 2147483563;
00094 static const long sMod2           = 2147483399;
00095 
00096 void KRandomSequence::Private::draw()
00097 {
00098   static const long sMM1            = sMod1 - 1;
00099   static const long sA1             = 40014;
00100   static const long sA2             = 40692;
00101   static const long sQ1             = 53668;
00102   static const long sQ2             = 52774;
00103   static const long sR1             = 12211;
00104   static const long sR2             = 3791;
00105   static const long sDiv            = 1 + sMM1 / s_nShuffleTableSize;
00106 
00107   // Long period (>2 * 10^18) random number generator of L'Ecuyer with
00108   // Bayes-Durham shuffle and added safeguards. Returns a uniform random
00109   // deviate between 0.0 and 1.0 (exclusive of the endpoint values). Call
00110   // with a negative number to initialize; thereafter, do not alter idum
00111   // between successive deviates in a sequence. RNMX should approximate
00112   // the largest floating point value that is less than 1.
00113 
00114   int j; // Index for the shuffle table
00115   long k;
00116 
00117   // Initialise
00118   if ( lngSeed1 <= 0 )
00119   {
00120     lngSeed2 = lngSeed1;
00121 
00122     // Load the shuffle table after 8 warm-ups
00123     for ( j = s_nShuffleTableSize + 7; j >= 0; j-- )
00124     {
00125       k = lngSeed1 / sQ1;
00126       lngSeed1 = sA1 * ( lngSeed1 - k*sQ1) - k*sR1;
00127       if ( lngSeed1 < 0 )
00128       {
00129         lngSeed1 += sMod1;
00130       }
00131 
00132       if ( j < s_nShuffleTableSize )
00133       {
00134     shuffleArray[j] = lngSeed1;
00135       }
00136     }
00137 
00138     lngShufflePos = shuffleArray[0];
00139   }
00140 
00141   // Start here when not initializing
00142 
00143   // Compute lngSeed1 = ( lngIA1*lngSeed1 ) % lngIM1 without overflows
00144   // by Schrage's method
00145   k = lngSeed1 / sQ1;
00146   lngSeed1 = sA1 * ( lngSeed1 - k*sQ1 ) - k*sR1;
00147   if ( lngSeed1 < 0 )
00148   {
00149     lngSeed1 += sMod1;
00150   }
00151 
00152   // Compute lngSeed2 = ( lngIA2*lngSeed2 ) % lngIM2 without overflows
00153   // by Schrage's method
00154   k = lngSeed2 / sQ2;
00155   lngSeed2 = sA2 * ( lngSeed2 - k*sQ2 ) - k*sR2;
00156   if ( lngSeed2 < 0 )
00157   {
00158     lngSeed2 += sMod2;
00159   }
00160 
00161   j = lngShufflePos / sDiv;
00162   lngShufflePos = shuffleArray[j] - lngSeed2;
00163   shuffleArray[j] = lngSeed1;
00164 
00165   if ( lngShufflePos < 1 )
00166   {
00167     lngShufflePos += sMM1;
00168   }
00169 }
00170 
00171 void
00172 KRandomSequence::modulate(int i)
00173 {
00174   d->lngSeed2 -= i;
00175   if ( d->lngSeed2 < 0 )
00176   {
00177     d->lngShufflePos += sMod2;
00178   }
00179   d->draw();
00180   d->lngSeed1 -= i;
00181   if ( d->lngSeed1 < 0 )
00182   {
00183     d->lngSeed1 += sMod1;
00184   }
00185   d->draw();
00186 }
00187 
00188 double
00189 KRandomSequence::getDouble()
00190 {
00191   static const double finalAmp         = 1.0 / double( sMod1 );
00192   static const double epsilon          = 1.2E-7;
00193   static const double maxRand          = 1.0 - epsilon;
00194   double temp;
00195   d->draw();
00196   // Return a value that is not one of the endpoints
00197   if ( ( temp = finalAmp * d->lngShufflePos ) > maxRand )
00198   {
00199     // We don't want to return 1.0
00200     return maxRand;
00201   }
00202   else
00203   {
00204     return temp;
00205   }
00206 }
00207 
00208 unsigned long
00209 KRandomSequence::getLong(unsigned long max)
00210 {
00211   d->draw();
00212 
00213   return max ? (((unsigned long) d->lngShufflePos) % max) : 0;
00214 }
00215 
00216 bool
00217 KRandomSequence::getBool()
00218 {
00219   d->draw();
00220 
00221   return (((unsigned long) d->lngShufflePos) & 1);
00222 }

KDECore

Skip menu "KDECore"
  • Main Page
  • Modules
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

kdelibs

Skip menu "kdelibs"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • Kate
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • KIO
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • Kross
  • KUtils
  • Nepomuk
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.5.4
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal