kdecore Library API Documentation

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 }
KDE Logo
This file is part of the documentation for kdecore Library Version 3.2.3.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Fri Aug 20 09:48:26 2004 by doxygen 1.3.7 written by Dimitri van Heesch, © 1997-2003