• Skip to content
  • Skip to link menu
KDE 3.5 API Reference
  • KDE API Reference
  • API Reference
  • 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 <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 }

KDECore

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

API Reference

Skip menu "API Reference"
  • dcop
  • DNSSD
  • interfaces
  • Kate
  • kconf_update
  • KDECore
  • KDED
  • kdefx
  • KDEsu
  • kdeui
  • KDocTools
  • KHTML
  • KImgIO
  • KInit
  • kio
  • kioslave
  • KJS
  • KNewStuff
  • KParts
  • KUtils
Generated for API Reference by doxygen 1.5.9
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