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 );


Reply via email to