You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openoffice.apache.org by pf...@apache.org on 2015/03/26 23:05:43 UTC
svn commit: r1669455 -
/openoffice/trunk/main/sc/source/core/tool/interpr1.cxx
Author: pfg
Date: Thu Mar 26 22:05:42 2015
New Revision: 1669455
URL: http://svn.apache.org/r1669455
Log:
Re-implement Calc's RAND() function using a variant of KISS PRNG.
George Marsaglia's KISS algorithm is a rather simple implementation
of a random number generator but it has interesting properties with
respect ot the traditional Mersenne Twister.
I used the 2011 32 bit Multiply-with-carry variant, with an
undetermined period which is known to be not less than 10^40000000;
it is known to pass all the statistical tests.
The Apache OpenOffice implementation uses an aggressive seeding
scheme based on the internal rtl_random functions, rendering the
function basically unpredictable. As a side effect it is also not
possible to specify a seed for repeatability. No claims are made
concerning crypto-safeness.
The specific adaption for Apache OpenOffice is:
Copyright 2015 Pedro Giffuni
All rights reserved.
Huge thanks to Steve Kargl for pointing me to the algorithm and
the late George Marsaglia for creating it in the first place.
Modified:
openoffice/trunk/main/sc/source/core/tool/interpr1.cxx
Modified: openoffice/trunk/main/sc/source/core/tool/interpr1.cxx
URL: http://svn.apache.org/viewvc/openoffice/trunk/main/sc/source/core/tool/interpr1.cxx?rev=1669455&r1=1669454&r2=1669455&view=diff
==============================================================================
--- openoffice/trunk/main/sc/source/core/tool/interpr1.cxx (original)
+++ openoffice/trunk/main/sc/source/core/tool/interpr1.cxx Thu Mar 26 22:05:42 2015
@@ -40,6 +40,7 @@
#include <unotools/transliterationwrapper.hxx>
#include <rtl/ustring.hxx>
#include <rtl/logfile.hxx>
+#include <rtl/random.h>
#include <unicode/uchar.h>
#include "interpre.hxx"
@@ -71,9 +72,6 @@
#include "doubleref.hxx"
#include "queryparam.hxx"
-#include <boost/random/mersenne_twister.hpp>
-#include <boost/random/uniform_01.hpp>
-
#include <boost/math/special_functions/acosh.hpp>
#include <boost/math/special_functions/asinh.hpp>
#include <boost/math/special_functions/atanh.hpp>
@@ -1545,17 +1543,47 @@ void ScInterpreter::ScPi()
PushDouble(F_PI);
}
+#define SCRANDOMQ_SIZE 4194304
+static sal_uInt32 nScRandomQ[SCRANDOMQ_SIZE], nScCarry = 0;
-void ScInterpreter::ScRandom()
+// Multiply with Carry
+sal_uInt32
+b32MWC(void)
{
- RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "bst", "ScInterpreter::ScRandom" );
+ sal_uInt32 t, x;
+ static int j = (SCRANDOMQ_SIZE - 1);
- boost::random::mt19937 ScGen(static_cast<unsigned int>(std::time(0)));
- static boost::uniform_01<boost::mt19937> ScZeroOne(ScGen);
-
- PushDouble(ScZeroOne());
+ j = (j + 1) & (SCRANDOMQ_SIZE - 1);
+ x = nScRandomQ[j];
+ t = (x << 28) + nScCarry;
+ nScCarry = (x >> 4) - (t < x);
+ return (nScRandomQ[j] = t - x);
}
+// Congruential
+#define CNG ( cng = 69069 * cng + 13579 )
+// Xorshift
+#define XS ( xs ^= (xs << 13), xs ^= (xs >> 17), xs ^= (xs << 5) )
+
+#define KISS (b32MWC() + CNG + XS)
+
+void ScInterpreter::ScRandom()
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "pfg", "ScInterpreter::ScRandom" );
+
+ static rtlRandomPool aPool = rtl_random_createPool();
+ static sal_Bool SqSeeded = sal_False;
+ static sal_uInt32 i, x, cng, xs = 362436069;
+
+ // Seeding for the PRNG
+ if (SqSeeded == sal_False) {
+ rtl_random_getBytes(aPool, &cng, sizeof(cng));
+ rtl_random_getBytes(aPool, &nScRandomQ,
+ sizeof(nScRandomQ[0]) * SCRANDOMQ_SIZE);
+ SqSeeded = sal_True;
+ }
+ PushDouble(static_cast<double>(KISS) / SAL_MAX_UINT32);
+}
void ScInterpreter::ScTrue()
{