Author: pfg
Date: Mon Sep 14 16:41:03 2015
New Revision: 1702992
URL: http://svn.apache.org/r1702992
Log:
Replace the random generator in RANDBETWEEN()
For consistency with RAND(), replace the old Wichman-Hill with
an even older version of George Marsaglia's KISS algorithm.
For the intended use this is more than enough and
still should pass all statistics tests.
Modified:
openoffice/trunk/main/scaddins/source/analysis/analysis.cxx
Modified: openoffice/trunk/main/scaddins/source/analysis/analysis.cxx
URL:
http://svn.apache.org/viewvc/openoffice/trunk/main/scaddins/source/analysis/analysis.cxx?rev=1702992&r1=1702991&r2=1702992&view=diff
==============================================================================
--- openoffice/trunk/main/scaddins/source/analysis/analysis.cxx (original)
+++ openoffice/trunk/main/scaddins/source/analysis/analysis.cxx Mon Sep 14
16:41:03 2015
@@ -805,11 +805,14 @@ double SAL_CALL AnalysisAddIn::getSqrtpi
RETURN_FINITE( fRet );
}
+#define SCRANDOMQ_SIZE 4
double SAL_CALL AnalysisAddIn::getRandbetween( double fMin, double fMax )
THROWDEF_RTE_IAE
{
- static sal_Int32 nScRandomIx = 0, nScRandomIy = 0, nScRandomIz = 0,
nScRandomIt = 0;
+ static sal_uInt32 nScRandomSeed[SCRANDOMQ_SIZE];
+ static sal_Bool SqSeeded = sal_False;
static rtlRandomPool aPool = rtl_random_createPool();
+ sal_uInt64 nScRandomt, nScRandoma = 698769069LL;
double fScRandomW;
fMin = ::rtl::math::round( fMin, 0, rtl_math_RoundingMode_Up );
@@ -817,43 +820,25 @@ double SAL_CALL AnalysisAddIn::getRandbe
if( fMin > fMax )
THROW_IAE;
- // Seeding for the PRNG: should be good enough but we
- // monitor the values to keep things under control.
- if (nScRandomIx <= 0)
- rtl_random_getBytes(aPool, &nScRandomIx, sizeof(nScRandomIx));
- if (nScRandomIy <= 0)
- rtl_random_getBytes(aPool, &nScRandomIy, sizeof(nScRandomIy));
- if (nScRandomIz <= 0)
- rtl_random_getBytes(aPool, &nScRandomIz, sizeof(nScRandomIz));
- if (nScRandomIt <= 0)
- rtl_random_getBytes(aPool, &nScRandomIt, sizeof(nScRandomIt));
+ // Seeding for the PRNG: should be pretty good.
+ if (SqSeeded == sal_False) {
+ rtl_random_getBytes(aPool, &nScRandomSeed, SCRANDOMQ_SIZE *
sizeof(nScRandomSeed[0]));
+ SqSeeded = sal_True;
+ }
- // Basically unmodified algorithm from
- // Wichman and Hill, "Generating good pseudo-random numbers",
- // December 5, 2005.
-
- nScRandomIx = 11600L * (nScRandomIx % 185127L) - 10379L * (nScRandomIx /
185127L);
- nScRandomIy = 47003L * (nScRandomIy % 45688L) - 10479L * (nScRandomIy /
45688L);
- nScRandomIz = 23000L * (nScRandomIz % 93368L) - 19423L * (nScRandomIz /
93368L);
- nScRandomIt = 33000L * (nScRandomIt % 65075L) - 8123L * (nScRandomIt /
65075L);
- if (nScRandomIx < 0)
- nScRandomIx += 2147483579L;
- if (nScRandomIy < 0)
- nScRandomIy += 2147483543L;
- if (nScRandomIz < 0)
- nScRandomIz += 2147483123L;
- if (nScRandomIt < 0)
- nScRandomIt += 2147483123L;
-
- fScRandomW = (double)nScRandomIx*0.0000000004656613022670 +
- (double)nScRandomIy*0.0000000004656613100760 +
- (double)nScRandomIz*0.0000000004656613360968 +
- (double)nScRandomIt*0.0000000004656614011490;
+ // Use George Marsaglia's 1998 KISS PRNG algorithm.
+ nScRandomSeed[0] = 69069 * nScRandomSeed[0] + 12345;
+ nScRandomSeed[1] ^= (nScRandomSeed[1] << 13);
+ nScRandomSeed[1] ^= (nScRandomSeed[1] >> 17);
+ nScRandomSeed[1] ^= (nScRandomSeed[1] << 5);
+ nScRandomt = nScRandoma * nScRandomSeed[2] + nScRandomSeed[3];
+ nScRandomSeed[1] = (nScRandomt >> 32);
+ fScRandomW = (nScRandomSeed[0] + nScRandomSeed[1] + (nScRandomSeed[3] =
nScRandomt));
// fMax -> range
double fRet = fMax - fMin + 1.0;
- fRet *= fScRandomW - (sal_Int32)fScRandomW ;
+ fRet *= fScRandomW / SAL_MAX_UINT32 ;
fRet += fMin;
fRet = floor( fRet ); // simple floor is sufficient here
RETURN_FINITE( fRet );