Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

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., 59 Temple Place - Suite 330,
00018   Boston, MA 02111-1307, USA.
00019 */
00020 
00021 #include <qlist.h>
00022 #include <string.h>
00023 
00024 #include "kapplication.h"
00025 #include "krandomsequence.h"
00026 
00027 const int    KRandomSequence::m_nShuffleTableSize = 32;
00028 
00030 //      Construction / Destruction
00032 
00033 KRandomSequence::KRandomSequence( long lngSeed1 )
00034 {
00035   // Seed the generator
00036   setSeed( lngSeed1 );
00037 
00038 
00039   // Set the size of the shuffle table
00040   m_ShuffleArray = new long [m_nShuffleTableSize];
00041 }
00042 
00043 KRandomSequence::~KRandomSequence()
00044 {
00045   delete [] m_ShuffleArray;
00046 }
00047 
00048 KRandomSequence::KRandomSequence(const KRandomSequence &a)
00049 {
00050   // Set the size of the shuffle table
00051   m_ShuffleArray = new long [m_nShuffleTableSize];
00052   *this = a;
00053 }
00054 
00055 KRandomSequence &
00056 KRandomSequence::operator=(const KRandomSequence &a)
00057 {
00058   m_lngSeed1 = a.m_lngSeed1;
00059   m_lngSeed2 = a.m_lngSeed2;
00060   m_lngShufflePos = a.m_lngShufflePos;
00061   memcpy(m_ShuffleArray, a.m_ShuffleArray, sizeof(long)*m_nShuffleTableSize);
00062   return *this;
00063 }
00064 
00065 
00067 //      Member Functions
00069 
00070 void KRandomSequence::setSeed( long lngSeed1 )
00071 {
00072   // Convert the positive seed number to a negative one so that the Draw()
00073   // function can intialise itself the first time it is called. We just have
00074   // to make sure that the seed used != 0 as zero perpetuates itself in a
00075   // sequence of random numbers.
00076   if ( lngSeed1 < 0 )
00077   {
00078     m_lngSeed1 = -1;
00079   }
00080   else if (lngSeed1 == 0)
00081   {
00082     m_lngSeed1 = -((_random() & ~1)+1);
00083   }
00084   else
00085   {
00086     m_lngSeed1 = -lngSeed1;
00087   }
00088 }
00089 
00090 static const long sMod1           = 2147483563;
00091 static const long sMod2           = 2147483399;
00092 
00093 void KRandomSequence::Draw()
00094 {
00095   static const long sMM1            = sMod1 - 1;
00096   static const long sA1             = 40014;
00097   static const long sA2             = 40692;
00098   static const long sQ1             = 53668;
00099   static const long sQ2             = 52774;
00100   static const long sR1             = 12211;
00101   static const long sR2             = 3791;
00102   static const long sDiv            = 1 + sMM1 / m_nShuffleTableSize;
00103 
00104   // Long period (>2 * 10^18) random number generator of L'Ecuyer with
00105   // Bayes-Durham shuffle and added safeguards. Returns a uniform random
00106   // deviate between 0.0 and 1.0 (exclusive of the endpoint values). Call
00107   // with a negative number to initialize; thereafter, do not alter idum
00108   // between successive deviates in a sequence. RNMX should approximate
00109   // the largest floating point value that is less than 1.
00110 
00111   int j; // Index for the shuffle table
00112   long k;
00113 
00114   // Initialise
00115   if ( m_lngSeed1 <= 0 )
00116   {
00117     m_lngSeed2 = m_lngSeed1;
00118 
00119     // Load the shuffle table after 8 warm-ups
00120     for ( j = m_nShuffleTableSize + 7; j >= 0; j-- )
00121     {
00122       k = m_lngSeed1 / sQ1;
00123       m_lngSeed1 = sA1 * ( m_lngSeed1 - k*sQ1) - k*sR1;
00124       if ( m_lngSeed1 < 0 )
00125       {
00126         m_lngSeed1 += sMod1;
00127       }
00128 
00129       if ( j < m_nShuffleTableSize )
00130       {
00131         m_ShuffleArray[j] = m_lngSeed1;
00132       }
00133     }
00134 
00135     m_lngShufflePos = m_ShuffleArray[0];
00136   }
00137 
00138   // Start here when not initializing
00139 
00140   // Compute m_lngSeed1 = ( lngIA1*m_lngSeed1 ) % lngIM1 without overflows
00141   // by Schrage's method
00142   k = m_lngSeed1 / sQ1;
00143   m_lngSeed1 = sA1 * ( m_lngSeed1 - k*sQ1 ) - k*sR1;
00144   if ( m_lngSeed1 < 0 )
00145   {
00146     m_lngSeed1 += sMod1;
00147   }
00148 
00149   // Compute m_lngSeed2 = ( lngIA2*m_lngSeed2 ) % lngIM2 without overflows
00150   // by Schrage's method
00151   k = m_lngSeed2 / sQ2;
00152   m_lngSeed2 = sA2 * ( m_lngSeed2 - k*sQ2 ) - k*sR2;
00153   if ( m_lngSeed2 < 0 )
00154   {
00155     m_lngSeed2 += sMod2;
00156   }
00157 
00158   j = m_lngShufflePos / sDiv;
00159   m_lngShufflePos = m_ShuffleArray[j] - m_lngSeed2;
00160   m_ShuffleArray[j] = m_lngSeed1;
00161 
00162   if ( m_lngShufflePos < 1 )
00163   {
00164     m_lngShufflePos += sMM1;
00165   }
00166 }
00167 
00168 void
00169 KRandomSequence::modulate(int i)
00170 {
00171   m_lngSeed2 -= i;
00172   if ( m_lngSeed2 < 0 )
00173   {
00174     m_lngShufflePos += sMod2;
00175   }
00176   Draw();
00177   m_lngSeed1 -= i;
00178   if ( m_lngSeed1 < 0 )
00179   {
00180     m_lngSeed1 += sMod1;
00181   }
00182   Draw();
00183 }
00184 
00185 double
00186 KRandomSequence::getDouble()
00187 {
00188   static const double finalAmp         = 1.0 / double( sMod1 );
00189   static const double epsilon          = 1.2E-7;
00190   static const double maxRand          = 1.0 - epsilon;
00191   double temp;
00192   Draw();
00193   // Return a value that is not one of the endpoints
00194   if ( ( temp = finalAmp * m_lngShufflePos ) > maxRand )
00195   {
00196     // We don't want to return 1.0
00197     return maxRand;
00198   }
00199   else
00200   {
00201     return temp;
00202   }
00203 }
00204 
00205 unsigned long
00206 KRandomSequence::getLong(unsigned long max)
00207 {
00208   Draw();
00209 
00210   return max ? (((unsigned long) m_lngShufflePos) % max) : 0;
00211 }
00212 
00213 bool
00214 KRandomSequence::getBool()
00215 {
00216   Draw();
00217 
00218   return (((unsigned long) m_lngShufflePos) & 1);
00219 }
00220 
00221 class KRandomSequenceList : public QGList
00222 {
00223   friend class KRandomSequence;
00224 public:
00225   KRandomSequenceList() : QGList() { }
00226   virtual void deleteItem( QCollection::Item ) {}
00227 };
00228 
00229 void
00230 KRandomSequence::randomize(QGList *_list)
00231 {
00232   KRandomSequenceList *list = (KRandomSequenceList *)_list;
00233   KRandomSequenceList l;
00234   while(list->count())
00235      l.append(list->takeFirst());
00236 
00237   list->append(l.takeFirst()); // Start with 1
00238   while(l.count())
00239      list->insertAt(getLong(list->count()+1), l.takeFirst());
00240 }

Generated on Sat Nov 5 16:17:28 2005 for OPIE by  doxygen 1.4.2