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 "krandomsequence.h"
00022 #include "krandom.h"
00023 #include <string.h>
00024 #include <config.h>
00025
00026 static const int s_nShuffleTableSize = 32;
00027
00028 class KRandomSequence::Private
00029 {
00030 public:
00031
00032 void draw();
00033
00034 long lngSeed1;
00035 long lngSeed2;
00036 long lngShufflePos;
00037 long shuffleArray[s_nShuffleTableSize];
00038 };
00039
00041
00043
00044 KRandomSequence::KRandomSequence( long lngSeed1 ) : d(new Private)
00045 {
00046
00047 setSeed( lngSeed1 );
00048 }
00049
00050 KRandomSequence::~KRandomSequence()
00051 {
00052 delete d;
00053 }
00054
00055 KRandomSequence::KRandomSequence(const KRandomSequence &a) : d(new Private)
00056 {
00057 *d = *a.d;
00058 }
00059
00060 KRandomSequence & KRandomSequence::operator=(const KRandomSequence &a)
00061 {
00062 if ( this != &a ) {
00063 *d = *a.d;
00064 }
00065 return *this;
00066 }
00067
00068
00070
00072
00073 void KRandomSequence::setSeed( long lngSeed1 )
00074 {
00075
00076
00077
00078
00079 if ( lngSeed1 < 0 )
00080 {
00081 d->lngSeed1 = -1;
00082 }
00083 else if (lngSeed1 == 0)
00084 {
00085 d->lngSeed1 = -((KRandom::random() & ~1)+1);
00086 }
00087 else
00088 {
00089 d->lngSeed1 = -lngSeed1;
00090 }
00091 }
00092
00093 static const long sMod1 = 2147483563;
00094 static const long sMod2 = 2147483399;
00095
00096 void KRandomSequence::Private::draw()
00097 {
00098 static const long sMM1 = sMod1 - 1;
00099 static const long sA1 = 40014;
00100 static const long sA2 = 40692;
00101 static const long sQ1 = 53668;
00102 static const long sQ2 = 52774;
00103 static const long sR1 = 12211;
00104 static const long sR2 = 3791;
00105 static const long sDiv = 1 + sMM1 / s_nShuffleTableSize;
00106
00107
00108
00109
00110
00111
00112
00113
00114 int j;
00115 long k;
00116
00117
00118 if ( lngSeed1 <= 0 )
00119 {
00120 lngSeed2 = lngSeed1;
00121
00122
00123 for ( j = s_nShuffleTableSize + 7; j >= 0; j-- )
00124 {
00125 k = lngSeed1 / sQ1;
00126 lngSeed1 = sA1 * ( lngSeed1 - k*sQ1) - k*sR1;
00127 if ( lngSeed1 < 0 )
00128 {
00129 lngSeed1 += sMod1;
00130 }
00131
00132 if ( j < s_nShuffleTableSize )
00133 {
00134 shuffleArray[j] = lngSeed1;
00135 }
00136 }
00137
00138 lngShufflePos = shuffleArray[0];
00139 }
00140
00141
00142
00143
00144
00145 k = lngSeed1 / sQ1;
00146 lngSeed1 = sA1 * ( lngSeed1 - k*sQ1 ) - k*sR1;
00147 if ( lngSeed1 < 0 )
00148 {
00149 lngSeed1 += sMod1;
00150 }
00151
00152
00153
00154 k = lngSeed2 / sQ2;
00155 lngSeed2 = sA2 * ( lngSeed2 - k*sQ2 ) - k*sR2;
00156 if ( lngSeed2 < 0 )
00157 {
00158 lngSeed2 += sMod2;
00159 }
00160
00161 j = lngShufflePos / sDiv;
00162 lngShufflePos = shuffleArray[j] - lngSeed2;
00163 shuffleArray[j] = lngSeed1;
00164
00165 if ( lngShufflePos < 1 )
00166 {
00167 lngShufflePos += sMM1;
00168 }
00169 }
00170
00171 void
00172 KRandomSequence::modulate(int i)
00173 {
00174 d->lngSeed2 -= i;
00175 if ( d->lngSeed2 < 0 )
00176 {
00177 d->lngShufflePos += sMod2;
00178 }
00179 d->draw();
00180 d->lngSeed1 -= i;
00181 if ( d->lngSeed1 < 0 )
00182 {
00183 d->lngSeed1 += sMod1;
00184 }
00185 d->draw();
00186 }
00187
00188 double
00189 KRandomSequence::getDouble()
00190 {
00191 static const double finalAmp = 1.0 / double( sMod1 );
00192 static const double epsilon = 1.2E-7;
00193 static const double maxRand = 1.0 - epsilon;
00194 double temp;
00195 d->draw();
00196
00197 if ( ( temp = finalAmp * d->lngShufflePos ) > maxRand )
00198 {
00199
00200 return maxRand;
00201 }
00202 else
00203 {
00204 return temp;
00205 }
00206 }
00207
00208 unsigned long
00209 KRandomSequence::getLong(unsigned long max)
00210 {
00211 d->draw();
00212
00213 return max ? (((unsigned long) d->lngShufflePos) % max) : 0;
00214 }
00215
00216 bool
00217 KRandomSequence::getBool()
00218 {
00219 d->draw();
00220
00221 return (((unsigned long) d->lngShufflePos) & 1);
00222 }