KDECore
krandomsequence.cpp
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
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
00031
00032 KRandomSequence::KRandomSequence( long lngSeed1 )
00033 {
00034
00035 setSeed( lngSeed1 );
00036
00037
00038
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
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
00068
00069 void KRandomSequence::setSeed( long lngSeed1 )
00070 {
00071
00072
00073
00074
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
00104
00105
00106
00107
00108
00109
00110 int j;
00111 long k;
00112
00113
00114 if ( m_lngSeed1 <= 0 )
00115 {
00116 m_lngSeed2 = m_lngSeed1;
00117
00118
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
00138
00139
00140
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
00149
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
00193 if ( ( temp = finalAmp * m_lngShufflePos ) > maxRand )
00194 {
00195
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());
00237 while(l.count())
00238 list->insertAt(getLong(list->count()+1), l.takeFirst());
00239 }