summaryrefslogtreecommitdiffstats
path: root/tdecore/krandomsequence.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'tdecore/krandomsequence.cpp')
-rw-r--r--tdecore/krandomsequence.cpp239
1 files changed, 239 insertions, 0 deletions
diff --git a/tdecore/krandomsequence.cpp b/tdecore/krandomsequence.cpp
new file mode 100644
index 000000000..04240733f
--- /dev/null
+++ b/tdecore/krandomsequence.cpp
@@ -0,0 +1,239 @@
+/*
+ This file is part of the KDE libraries
+ Copyright (c) 1999 Sean Harmer <sh@astro.keele.ac.uk>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include <tqptrlist.h>
+
+#include "krandomsequence.h"
+#include "kapplication.h"
+
+const int KRandomSequence::m_nShuffleTableSize = 32;
+
+//////////////////////////////////////////////////////////////////////////////
+// Construction / Destruction
+//////////////////////////////////////////////////////////////////////////////
+
+KRandomSequence::KRandomSequence( long lngSeed1 )
+{
+ // Seed the generator
+ setSeed( lngSeed1 );
+
+
+ // Set the size of the shuffle table
+ m_ShuffleArray = new long [m_nShuffleTableSize];
+}
+
+KRandomSequence::~KRandomSequence()
+{
+ delete [] m_ShuffleArray;
+}
+
+KRandomSequence::KRandomSequence(const KRandomSequence &a)
+{
+ // Set the size of the shuffle table
+ m_ShuffleArray = new long [m_nShuffleTableSize];
+ *this = a;
+}
+
+KRandomSequence &
+KRandomSequence::operator=(const KRandomSequence &a)
+{
+ m_lngSeed1 = a.m_lngSeed1;
+ m_lngSeed2 = a.m_lngSeed2;
+ m_lngShufflePos = a.m_lngShufflePos;
+ memcpy(m_ShuffleArray, a.m_ShuffleArray, sizeof(long)*m_nShuffleTableSize);
+ return *this;
+}
+
+
+//////////////////////////////////////////////////////////////////////////////
+// Member Functions
+//////////////////////////////////////////////////////////////////////////////
+
+void KRandomSequence::setSeed( long lngSeed1 )
+{
+ // Convert the positive seed number to a negative one so that the Draw()
+ // function can intialise itself the first time it is called. We just have
+ // to make sure that the seed used != 0 as zero perpetuates itself in a
+ // sequence of random numbers.
+ if ( lngSeed1 < 0 )
+ {
+ m_lngSeed1 = -1;
+ }
+ else if (lngSeed1 == 0)
+ {
+ m_lngSeed1 = -((KApplication::random() & ~1)+1);
+ }
+ else
+ {
+ m_lngSeed1 = -lngSeed1;
+ }
+}
+
+static const long sMod1 = 2147483563;
+static const long sMod2 = 2147483399;
+
+void KRandomSequence::Draw()
+{
+ static const long sMM1 = sMod1 - 1;
+ static const long sA1 = 40014;
+ static const long sA2 = 40692;
+ static const long sQ1 = 53668;
+ static const long sQ2 = 52774;
+ static const long sR1 = 12211;
+ static const long sR2 = 3791;
+ static const long sDiv = 1 + sMM1 / m_nShuffleTableSize;
+
+ // Long period (>2 * 10^18) random number generator of L'Ecuyer with
+ // Bayes-Durham shuffle and added safeguards. Returns a uniform random
+ // deviate between 0.0 and 1.0 (exclusive of the endpoint values). Call
+ // with a negative number to initialize; thereafter, do not alter idum
+ // between successive deviates in a sequence. RNMX should approximate
+ // the largest floating point value that is less than 1.
+
+ int j; // Index for the shuffle table
+ long k;
+
+ // Initialise
+ if ( m_lngSeed1 <= 0 )
+ {
+ m_lngSeed2 = m_lngSeed1;
+
+ // Load the shuffle table after 8 warm-ups
+ for ( j = m_nShuffleTableSize + 7; j >= 0; j-- )
+ {
+ k = m_lngSeed1 / sQ1;
+ m_lngSeed1 = sA1 * ( m_lngSeed1 - k*sQ1) - k*sR1;
+ if ( m_lngSeed1 < 0 )
+ {
+ m_lngSeed1 += sMod1;
+ }
+
+ if ( j < m_nShuffleTableSize )
+ {
+ m_ShuffleArray[j] = m_lngSeed1;
+ }
+ }
+
+ m_lngShufflePos = m_ShuffleArray[0];
+ }
+
+ // Start here when not initializing
+
+ // Compute m_lngSeed1 = ( lngIA1*m_lngSeed1 ) % lngIM1 without overflows
+ // by Schrage's method
+ k = m_lngSeed1 / sQ1;
+ m_lngSeed1 = sA1 * ( m_lngSeed1 - k*sQ1 ) - k*sR1;
+ if ( m_lngSeed1 < 0 )
+ {
+ m_lngSeed1 += sMod1;
+ }
+
+ // Compute m_lngSeed2 = ( lngIA2*m_lngSeed2 ) % lngIM2 without overflows
+ // by Schrage's method
+ k = m_lngSeed2 / sQ2;
+ m_lngSeed2 = sA2 * ( m_lngSeed2 - k*sQ2 ) - k*sR2;
+ if ( m_lngSeed2 < 0 )
+ {
+ m_lngSeed2 += sMod2;
+ }
+
+ j = m_lngShufflePos / sDiv;
+ m_lngShufflePos = m_ShuffleArray[j] - m_lngSeed2;
+ m_ShuffleArray[j] = m_lngSeed1;
+
+ if ( m_lngShufflePos < 1 )
+ {
+ m_lngShufflePos += sMM1;
+ }
+}
+
+void
+KRandomSequence::modulate(int i)
+{
+ m_lngSeed2 -= i;
+ if ( m_lngSeed2 < 0 )
+ {
+ m_lngShufflePos += sMod2;
+ }
+ Draw();
+ m_lngSeed1 -= i;
+ if ( m_lngSeed1 < 0 )
+ {
+ m_lngSeed1 += sMod1;
+ }
+ Draw();
+}
+
+double
+KRandomSequence::getDouble()
+{
+ static const double finalAmp = 1.0 / double( sMod1 );
+ static const double epsilon = 1.2E-7;
+ static const double maxRand = 1.0 - epsilon;
+ double temp;
+ Draw();
+ // Return a value that is not one of the endpoints
+ if ( ( temp = finalAmp * m_lngShufflePos ) > maxRand )
+ {
+ // We don't want to return 1.0
+ return maxRand;
+ }
+ else
+ {
+ return temp;
+ }
+}
+
+unsigned long
+KRandomSequence::getLong(unsigned long max)
+{
+ Draw();
+
+ return max ? (((unsigned long) m_lngShufflePos) % max) : 0;
+}
+
+bool
+KRandomSequence::getBool()
+{
+ Draw();
+
+ return (((unsigned long) m_lngShufflePos) & 1);
+}
+
+class KRandomSequenceList : public TQGList
+{
+ friend class KRandomSequence;
+public:
+ KRandomSequenceList() : TQGList() { }
+ virtual void deleteItem( TQPtrCollection::Item ) {}
+};
+
+void
+KRandomSequence::randomize(TQGList *_list)
+{
+ KRandomSequenceList *list = (KRandomSequenceList *)_list;
+ KRandomSequenceList l;
+ while(list->count())
+ l.append(list->takeFirst());
+
+ list->append(l.takeFirst()); // Start with 1
+ while(l.count())
+ list->insertAt(getLong(list->count()+1), l.takeFirst());
+}