2011-09-20 17:12 UTC+0200 Viktor Szakats (harbour.01 syenar.hu)

* include/hbapi.h
  * src/rtl/hbrandom.c
    + Changed Harbour's core pseudo-random generator from STD C rand()/srand()
      to superior implementation. New implementation fixed MT problems with 
      the standard solution on certain targets (f.e. win/mingw, win/msvc)
      Based on Przemek's patch which is in turn based on algorithm by 
      Steve Park: http://www.cs.wm.edu/~va/software/park/ suggested by me 
      on the list. Further modifications:
         * HB_RANDOMINTMAX() adapted. Checkme, I'm not sure about this.
         * HB_RANDOMSEED() updated.
         + headers cleaned, copyright updated, note added
         + automatic seed defaulting like in previous version (checkme, 
           we may as well drop it, though it will be create incompatibility)
         ; per-thread seed didn't work well for me (even with new engine) 
           so I didn't implement it.
         + added proto for hb_random_seed()
This commit is contained in:
Viktor Szakats
2011-09-22 15:14:21 +00:00
parent 2243ed5e92
commit 2ae90b92ba
3 changed files with 53 additions and 14 deletions

View File

@@ -16,6 +16,24 @@
The license applies to all entries newer than 2009-04-28.
*/
2011-09-20 17:12 UTC+0200 Viktor Szakats (harbour.01 syenar.hu)
* include/hbapi.h
* src/rtl/hbrandom.c
+ Changed Harbour's core pseudo-random generator from STD C rand()/srand()
to superior implementation. New implementation fixed MT problems with
the standard solution on certain targets (f.e. win/mingw, win/msvc)
Based on Przemek's patch which is in turn based on algorithm by
Steve Park: http://www.cs.wm.edu/~va/software/park/ suggested by me
on the list. Further modifications:
* HB_RANDOMINTMAX() adapted. Checkme, I'm not sure about this.
* HB_RANDOMSEED() updated.
+ headers cleaned, copyright updated, note added
+ automatic seed defaulting like in previous version (checkme,
we may as well drop it, though it will be create incompatibility)
; per-thread seed didn't work well for me (even with new engine)
so I didn't implement it.
+ added proto for hb_random_seed()
2011-09-20 13:56 UTC+0200 Viktor Szakats (harbour.01 syenar.hu)
* src/rtl/teditor.prg
! fixed following issue: in MEMOEDIT() insert mode the word wrap inserts

View File

@@ -968,6 +968,7 @@ extern HB_EXPORT char * hb_strRemEscSeq( char * szText, HB_SIZE * nLen ); /*
extern HB_EXPORT char * hb_numToStr( char * szBuf, HB_SIZE nSize, HB_MAXINT nNumber );
extern HB_EXPORT double hb_numRound( double dResult, int iDec ); /* round a number to a specific number of digits */
extern HB_EXPORT double hb_numInt( double dNum ); /* take the integer part of the number */
extern HB_EXPORT void hb_random_seed( HB_I32 seed );
extern HB_EXPORT double hb_random_num( void );
extern HB_EXPORT void hb_random_block( void * data, HB_SIZE len );
extern HB_EXPORT double hb_numDecConv( double dNum, int iDec );

View File

@@ -3,9 +3,10 @@
*/
/*
* xHarbour Project source code:
* Harbour Project source code:
* Random number generator routine
*
* Copyright 2011 Przemyslaw Czerpak <druzus / at / priv.onet.pl>
* Copyright 2003 Giancarlo Niccolai <gian@niccolai.ws>
* www - http://harbour-project.org
*
@@ -53,11 +54,17 @@
#include "hbapi.h"
#include "hbdate.h"
#include <stdlib.h>
#include <float.h>
/* NOTE: core random generator algorithm is the work of Steve Park
http://www.cs.wm.edu/~va/software/park/
*/
/* Globally available data, no need to MT it */
static volatile HB_BOOL s_fInit = HB_FALSE;
#define MODULUS 2147483647 /* DON'T CHANGE THIS VALUE */
#define MULTIPLIER 48271 /* DON'T CHANGE THIS VALUE */
#define DEFAULT 123456789 /* initial seed, use 0 < DEFAULT < MODULUS */
#define MAXIMUM 0xFFFFFFFF
static HB_BOOL s_fInit = HB_FALSE;
static HB_I32 s_seed = DEFAULT;
/*
* HB_RANDOM
@@ -120,32 +127,45 @@ HB_FUNC( HB_RANDOMINT )
HB_FUNC( HB_RANDOMSEED )
{
srand( HB_ISNUM( 1 ) ? ( unsigned ) hb_parni( 1 ) : ( unsigned ) hb_dateMilliSeconds() );
hb_random_seed( HB_ISNUM( 1 ) ? ( HB_I32 ) hb_parni( 1 ) : ( HB_I32 ) hb_dateMilliSeconds() );
s_fInit = HB_TRUE;
}
HB_FUNC( HB_RANDOMINTMAX )
{
#if RAND_MAX > HB_VMLONG_MAX
hb_retnd( RAND_MAX );
#if MAXIMUM > HB_VMLONG_MAX
hb_retnd( MAXIMUM );
#else
hb_retnint( RAND_MAX );
hb_retnint( MAXIMUM );
#endif
}
/* Returns a double value between 0 and 1 */
double hb_random_num( void )
{
double d1, d2;
const HB_I32 Q = MODULUS / MULTIPLIER;
const HB_I32 R = MODULUS % MULTIPLIER;
HB_I32 t;
if( ! s_fInit )
{
srand( ( unsigned ) hb_dateMilliSeconds() );
hb_random_seed( ( HB_I32 ) hb_dateMilliSeconds() );
s_fInit = HB_TRUE;
}
d1 = ( double ) rand();
d2 = ( double ) RAND_MAX + 1.0;
t = s_seed;
t = MULTIPLIER * ( t % Q ) - R * ( t / Q );
if( t <= 0 )
t += MODULUS;
s_seed = t;
return d1 / d2;
return ( ( double ) t / MODULUS );
}
void hb_random_seed( HB_I32 seed )
{
seed %= MODULUS;
s_seed = ( seed <= 0 ) ? seed + MODULUS : seed;
}