[prev in list] [next in list] [prev in thread] [next in thread]
List: kde-devel
Subject: Re: Random (Was: Cannot run KDE snapshot :()
From: Sean Harmer <sh () astro ! keele ! ac ! uk>
Date: 1999-12-10 9:48:36
[Download RAW message or body]
> In java I have always solved this problem by using the this pointer as
> seed, sometimes you would multiply/add/something the current time, to
> facilitate multiple instances of java.lang.Random made with more than
> 20ms between. This will only be a problem, if one object sets a seed - in
> java instantiates Random - several times. In this case you can make dummy
> objects and use their pointers as seeds. It should be a fairly good hack
> for creating random numbers.
>
> If you want to make the class KSequence, I think you should rename it to
> KRandom. This could then have static to give you an integer, float etc.
> and there would be no distinction between having one random number and
> having a sequence of random numbers. I think it will be a cause of
> confusion if there is this distinction and even more so, if the random
> method is not even in the same class. It strikes me as very bad design.
>
> But I really enjoy having the Random class in java. I think it would be
> great to have something like it in Kde.
>
> --
>
> Bo Thorsen
> gobo@imada.sdu.dk
> Lahnsgade 31, st.
> DK-5000 Odense C
> Tlf: +45 66 11 83 85
Hi all,
This is my first post to this group and I am quite new to KDE. Concerning your
request/desire for a KSequence class to generate a series of random numbers. I
have a small class do do this which I have attached along with a simple array
template that I used when developing it. It should be very easy to port the
code to use any array class though. The class uses the Long period (>2*10^18)
random number generator of L'Ecuyer with Bayes-Durham shuffle and added
safeguards as described in the Numerical Recipes book. It produces a random
number on the interval (0,1). However I have not tested my implementation of
this method very thoroughly as of yet, but it certainly gives acceptable
results. Probably just a bit of fine tuning needed in the smallest
representable number etc.
Cheers,
Sean Harmer
Oh, and how is education supposed to make me feel smarter?
Everytime I learn something new, it pushes some old stuff
out of my head. Like that time I took the wine making
course and I forgot how to drive.
- Homer J. Simpson
["Rand.h" (text/english)]
/***************************************************************************
Rand.h - description
-------------------
begin : Tue Nov 9 1999
copyright : (C) 1999 by Sean Harmer
email : sh@astro.keele.ac.uk
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#ifndef RAND_H
#define RAND_H
#include "Array.h"
/**
*@author Sean Harmer
*/
class CRand
{
public:
CRand( long lngSeed = 1 );
~CRand();
void Seed( long lngSeed = 1 );
double Draw(); // Generate the random number
private:
long m_lngSeed1;
long m_lngSeed2;
long m_lngShufflePos;
CArray<long,long&> m_ShuffleArray;
static const long m_lngMod1;
static const long m_lngMod2;
static const long m_lngMM1;
static const double m_dFinalAmp;
static const long m_lngA1;
static const long m_lngA2;
static const long m_lngQ1;
static const long m_lngQ2;
static const long m_lngR1;
static const long m_lngR2;
static const int CRand::m_nShuffleTableSize;
static const long CRand::m_lngDiv;
static const double m_dEpsilon;
static const double m_dMaxRand;
};
#endif
["Rand.cpp" (text/english)]
/***************************************************************************
Rand.cpp - description
-------------------
begin : Tue Nov 9 1999
copyright : (C) 1999 by Sean Harmer
email : sh@astro.keele.ac.uk
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#include "Rand.h"
const long CRand::m_lngMod1 = 2147483563;
const long CRand::m_lngMod2 = 2147483399;
const long CRand::m_lngMM1 = m_lngMod1 - 1;
const double CRand::m_dFinalAmp = 1.0 / double( m_lngMod1 );
const long CRand::m_lngA1 = 40014;
const long CRand::m_lngA2 = 40692;
const long CRand::m_lngQ1 = 53668;
const long CRand::m_lngQ2 = 52774;
const long CRand::m_lngR1 = 12211;
const long CRand::m_lngR2 = 3791;
const int CRand::m_nShuffleTableSize = 32;
const long CRand::m_lngDiv = 1 + m_lngMM1 / m_nShuffleTableSize;
const double CRand::m_dEpsilon = 1.2E-7;
const double CRand::m_dMaxRand = 1.0 - m_dEpsilon;
//////////////////////////////////////////////////////////////////////////////
// Construction / Destruction
//////////////////////////////////////////////////////////////////////////////
CRand::CRand( long lngSeed1 )
{
// Seed the generator
Seed( lngSeed1 );
// Set the size of the shuffle table
m_ShuffleArray.SetSize( m_nShuffleTableSize );
}
CRand::~CRand()
{
}
//////////////////////////////////////////////////////////////////////////////
// Member Functions
//////////////////////////////////////////////////////////////////////////////
void CRand::Seed( 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 < 1 )
{
m_lngSeed1 = -1;
}
else
{
m_lngSeed1 = -lngSeed1;
}
}
double CRand::Draw()
{
/*
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;
//static long iy = 0; ->m_lngShufflePos
//static long iv[lngNTAB]; // ->m_ShuffleArray
double temp;
// Initialise
if ( m_lngSeed1 <= 0 )
{
m_lngSeed2 = m_lngSeed1;
// Load the shuffle table after 8 warm-ups
for ( j = m_ShuffleArray.GetSize() + 7; j >= 0; j-- )
{
k = m_lngSeed1 / m_lngQ1;
m_lngSeed1 = m_lngA1 * ( m_lngSeed1 - k*m_lngQ1) - k*m_lngR1;
if ( m_lngSeed1 < 0 )
{
m_lngSeed1 += m_lngMod1;
}
if ( j < m_ShuffleArray.GetSize() )
{
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 / m_lngQ1;
m_lngSeed1 = m_lngA1 * ( m_lngSeed1 - k*m_lngQ1 ) - k*m_lngR1;
if ( m_lngSeed1 < 0 )
{
m_lngSeed1 += m_lngMod1;
}
// Compute m_lngSeed2 = ( lngIA2*m_lngSeed2 ) % lngIM2 without overflows
// by Schrage's method
k = m_lngSeed2 / m_lngQ2;
m_lngSeed2 = m_lngA2 * ( m_lngSeed2 - k*m_lngQ2 ) - k*m_lngR2;
if ( m_lngSeed2 < 0 )
{
m_lngSeed2 += m_lngMod2;
}
j = m_lngShufflePos / m_lngDiv;
m_lngShufflePos = m_ShuffleArray[j] - m_lngSeed2;
m_ShuffleArray[j] = m_lngSeed1;
if ( m_lngShufflePos < 1 )
{
m_lngShufflePos += m_lngMM1;
}
// Return a value that is not one of the endpoints
if ( ( temp = m_dFinalAmp * m_lngShufflePos ) > m_dMaxRand )
{
// We don't want to return 1.0
return m_dMaxRand;
}
else
{
return temp;
}
}
["Array.h" (text/english)]
/***************************************************************************
Array.h - description
-------------------
begin : Tue Nov 9 1999
copyright : (C) 1999 by Sean Harmer
email : sh@astro.keele.ac.uk
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
/////////////////////////////////////////////////////////////////////////////
// Array.h: Template for dynamic arrays by Sean Harmer
//
/////////////////////////////////////////////////////////////////////////////
// When using arrays created with this template, if you need to pass the array
// to a function, be sure to pass it by reference as I have not yet written a
// copy constructor to handle proper memory allocation. The default constructor
// just does a member-wise copy, so when the temporary copy is destroyed when
// the function returns, the memory is deallocated by the destructor, and since
// the pointer in the copy points to the same memory as the original, the
// behaviour of the original will be undefined.
// Please feel free to implement any new member functions that you need - just
// be careful with memory allocation/deallocation.
// Mail sh@astro.keele.ac.uk with any bug-reports / queries.
#ifndef __CArray__
#define __CArray__
#include <stdlib.h>
#include "Array.h"
/////////////////////////////////////////////////////////////////////////////
// CArray<TYPE, ARG_TYPE>
/////////////////////////////////////////////////////////////////////////////
template<class TYPE, class ARG_TYPE>
class CArray
{
public:
// Construction/Destruction
CArray();
~CArray();
// Attributes
int GetSize() const;
int GetUpperBound() const;
void SetSize( int nNewSize );
// Operations
// Clean up
void RemoveAll();
// Accessing elements
TYPE GetAt( int nIndex ) const;
void SetAt( int nIndex, ARG_TYPE newElement );
TYPE& ElementAt( int nIndex );
// Direct Access to the element data (may return NULL)
const TYPE* GetData() const;
TYPE* GetData();
// Potentially growing the array
void SetAtGrow( int nIndex, ARG_TYPE newElement );
int Add( ARG_TYPE newElement );
int Append( const CArray& src );
void Copy( const CArray& src );
// overloaded operator helpers
TYPE operator[]( int nIndex ) const;
TYPE& operator[]( int nIndex );
// Operations that move elements around
//void InsertAt(int nIndex, ARG_TYPE newElement, int nCount = 1);
void RemoveAt( int nIndex, int nCount = 1 );
//void InsertAt(int nStartIndex, CArray* pNewArray);
// Implementation
protected:
TYPE* m_pData; // the actual array of data
int m_nSize; // # of elements (upperBound - 1)
};
/////////////////////////////////////////////////////////////////////////////
// CArray<TYPE, ARG_TYPE> inline functions
template<class TYPE, class ARG_TYPE>
inline int CArray<TYPE, ARG_TYPE>::GetSize() const
{
return m_nSize;
}
template<class TYPE, class ARG_TYPE>
inline int CArray<TYPE, ARG_TYPE>::GetUpperBound() const
{
return m_nSize-1;
}
template<class TYPE, class ARG_TYPE>
inline void CArray<TYPE, ARG_TYPE>::RemoveAll()
{
SetSize(0);
}
template<class TYPE, class ARG_TYPE>
inline TYPE CArray<TYPE, ARG_TYPE>::GetAt(int nIndex) const
{
return m_pData[nIndex];
}
template<class TYPE, class ARG_TYPE>
inline void CArray<TYPE, ARG_TYPE>::SetAt(int nIndex, ARG_TYPE newElement)
{
m_pData[nIndex] = newElement;
}
template<class TYPE, class ARG_TYPE>
inline TYPE& CArray<TYPE, ARG_TYPE>::ElementAt(int nIndex)
{
return m_pData[nIndex];
}
template<class TYPE, class ARG_TYPE>
inline const TYPE* CArray<TYPE, ARG_TYPE>::GetData() const
{
return (const TYPE*)m_pData;
}
template<class TYPE, class ARG_TYPE>
inline TYPE* CArray<TYPE, ARG_TYPE>::GetData()
{
return (TYPE*)m_pData;
}
template<class TYPE, class ARG_TYPE>
inline int CArray<TYPE, ARG_TYPE>::Add(ARG_TYPE newElement)
{
int nIndex = m_nSize;
SetAtGrow(nIndex, newElement);
return nIndex;
}
template<class TYPE, class ARG_TYPE>
inline TYPE CArray<TYPE, ARG_TYPE>::operator[](int nIndex) const
{
return GetAt(nIndex);
}
template<class TYPE, class ARG_TYPE>
inline TYPE& CArray<TYPE, ARG_TYPE>::operator[](int nIndex)
{
return ElementAt(nIndex);
}
/////////////////////////////////////////////////////////////////////////////
// CArray<TYPE, ARG_TYPE> out-of-line functions
template<class TYPE, class ARG_TYPE>
CArray<TYPE, ARG_TYPE>::CArray()
{
m_pData = NULL;
m_nSize = 0;
}
template<class TYPE, class ARG_TYPE>
CArray<TYPE, ARG_TYPE>::~CArray()
{
if (m_pData != NULL)
{
delete[] m_pData;
}
}
template<class TYPE, class ARG_TYPE>
void CArray<TYPE, ARG_TYPE>::SetSize(int nNewSize)
{
if (nNewSize == 0)
{
// shrink to nothing
if (m_pData != NULL)
{
delete[] m_pData;
m_pData = NULL;
}
m_nSize = 0;
}
else if (m_pData == NULL)
{
// create one with exact size
m_pData = new TYPE[nNewSize];
// Fill in the new elements with default objects by calling
// the default constructor
for ( int i = 0; i < nNewSize; i++ )
{
m_pData[i] = TYPE();
}
m_nSize = nNewSize;
}
else if (nNewSize <= m_nSize)
{
// Create a smaller array and copy the first nNewSize
// elements across to it
TYPE* pNewData = new TYPE[nNewSize];
for ( int i = 0; i < nNewSize; i++ )
{
pNewData[i] = m_pData[i];
}
// Get rid of old stuff
delete[] m_pData;
m_pData = pNewData;
m_nSize = nNewSize;
}
else
{
// Create a larger array and copy the elements across
TYPE* pNewData = new TYPE[nNewSize];
for ( int i = 0; i < m_nSize; i++ )
{
pNewData[i] = m_pData[i];
}
// Fill in the new elements with default objects by calling
// the default constructor
for ( int i = m_nSize; i < nNewSize; i++ )
{
pNewData[i] = TYPE();
}
// get rid of old stuff (note: no destructors called)
delete[] m_pData;
m_pData = pNewData;
m_nSize = nNewSize;
}
}
template<class TYPE, class ARG_TYPE>
int CArray<TYPE, ARG_TYPE>::Append(const CArray& src)
{
// Insert src at the end of *this - return the old size of the array
int nOldSize = m_nSize;
SetSize(m_nSize + src.m_nSize);
// Copy the data across
for (int i = nOldSize; i < src.m_nSize; i++)
{
m_pData[i] = src.m_pData[i];
}
return nOldSize;
}
template<class TYPE, class ARG_TYPE>
void CArray<TYPE, ARG_TYPE>::Copy(const CArray& src)
{
// Copy data from src to *this
SetSize(src.m_nSize);
for (int i = 0; i < src.m_nSize; i++)
{
m_pData[i] = src.m_pData[i];
}
}
template<class TYPE, class ARG_TYPE>
void CArray<TYPE, ARG_TYPE>::SetAtGrow(int nIndex, ARG_TYPE newElement)
{
if (nIndex >= m_nSize)
{
SetSize(nIndex+1);
}
m_pData[nIndex] = newElement;
}
template<class TYPE, class ARG_TYPE>
void CArray<TYPE, ARG_TYPE>::RemoveAt(int nIndex, int nCount)
{
// Do not remove past end of array!
if ( nIndex + nCount <= m_nSize )
{
// Create a new array to hold the data
int nNewSize = m_nSize - nCount;
TYPE* pNewData = new TYPE[nNewSize];
// Copy the elements before nIndex across to the new array
for ( int i = 0; i < nIndex; i++ )
{
pNewData[i] = m_pData[i];
}
// Skip over the elements we are removing and copy the rest
// across to the new array
for ( int i = nIndex; i < nNewSize; i++ )
{
pNewData[i] = m_pData[i + nCount];
}
// Get rid of the old stuff
delete[] m_pData;
m_pData = pNewData;
m_nSize = nNewSize;
}
}
#endif // __CArray__
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic