[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