krandomsequence.cpp Source File (kdecore Library)

| # kdecore Library API Documentation
Overview | Class Hierarchy | Classes | Classes (annotated) | Members | Source Files

# krandomsequence.cpp

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

This file is part of the documentation for kdelibs Version 3.1.5.
Documentation copyright © 1996-2002 the KDE developers.
Generated on Wed Jan 28 12:46:47 2004 by doxygen 1.3.4 written by Dimitri van Heesch, © 1997-2001