Kaydet (Commit) bff635be authored tarafından Tor Lillqvist's avatar Tor Lillqvist

Make the RAND() and RANDBETWEEN() Calc functions non-random when requested

We don't want such a mode to affect other uses of randomness, though. Thus use
a separate random number generator object for these two functions, and use a
fixed seed for it if the SC_RAND_REPEATABLE environment variable is set.

As RAND() is implemented in sc, and RANDBETWEEN() is implemented in scaddins,
it was a bit hard to figure out where to add the new functions needed, without
having to over-engineer things with UNO. (This functionality is totally
Calc-specific, but neither sc nor scaddins has any public (non-UNO) API.)
Caolan suggested the formula module, which seems like a good enough place to
me.

Change-Id: I4b0cb327392e51a18bce28478af91b0174d6b726
üst f1cf63c2
......@@ -42,6 +42,7 @@ $(eval $(call gb_Library_add_exception_objects,for,\
formula/source/core/api/FormulaCompiler \
formula/source/core/api/FormulaOpCodeMapperObj \
formula/source/core/api/grammar \
formula/source/core/api/random \
formula/source/core/api/services \
formula/source/core/api/token \
formula/source/core/api/vectortoken \
......
Contains parts of the formula parser used outside Calc code.
Contains parts of the formula parser used outside Calc code that has
been pulled out from Calc's formula parser code.
Has been pulled out from Calc's formula parser code.
Also contains some functions that are needed by code in both sc and
scaddins. Located here just for convenience. So sue me.
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
#include <time.h>
#include <random>
#include <formula/random.hxx>
#include <rtl/instance.hxx>
namespace {
struct CalcFormulaRandomGenerator
{
std::mt19937 aRng;
CalcFormulaRandomGenerator()
{
// initialises the state of this RNG.
// should only be called once.
bool bRepeatable = (getenv("SC_RAND_REPEATABLE") != 0);
aRng.seed(bRepeatable ? 42 : time(NULL));
}
};
class theCalcFormulaRandomGenerator : public rtl::Static<CalcFormulaRandomGenerator, theCalcFormulaRandomGenerator> {};
}
namespace formula
{
namespace rng
{
double fRandom(double a, double b)
{
std::uniform_real_distribution<double> dist(a, b);
return dist(theCalcFormulaRandomGenerator::get().aRng);
}
sal_Int32 nRandom(sal_Int32 a, sal_Int32 b)
{
std::uniform_int_distribution<sal_Int32> dist(a, b);
return dist(theCalcFormulaRandomGenerator::get().aRng);
}
} // rng
} // formula
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
#ifndef INCLUDED_FORMULA_RANDOM_HXX
#define INCLUDED_FORMULA_RANDOM_HXX
#include <formula/formuladllapi.h>
namespace formula
{
namespace rng
{
// These two functions obey the SC_RAND_REPEATABLE environment
// variable: If it is set, use a fixed seed.
double FORMULA_DLLPUBLIC fRandom(double a, double b);
sal_Int32 FORMULA_DLLPUBLIC nRandom(sal_Int32 a, sal_Int32 b);
} // rng
} // formula
#endif // INCLUDED_FORMULA_RANDOM_HXX
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
......@@ -16,7 +16,7 @@
#include "tokenarray.hxx"
#include "compiler.hxx"
#include "interpre.hxx"
#include <comphelper/random.hxx>
#include <formula/random.hxx>
#include <formula/vectortoken.hxx>
#include "scmatrix.hxx"
......@@ -703,7 +703,7 @@ threefry2x32 (threefry2x32_ctr_t in, threefry2x32_key_t k)\n\
/// Create buffer and pass the buffer to a given kernel
virtual size_t Marshal( cl_kernel k, int argno, int, cl_program ) SAL_OVERRIDE
{
cl_int seed = comphelper::rng::uniform_int_distribution(0, SAL_MAX_INT32);
cl_int seed = formula::rng::nRandom(0, SAL_MAX_INT32);
// Pass the scalar result back to the rest of the formula kernel
SAL_INFO("sc.opencl", "Kernel " << k << " arg " << argno << ": cl_int: " << seed);
cl_int err = clSetKernelArg(k, argno, sizeof(cl_int), (void*)&seed);
......
......@@ -22,6 +22,7 @@
#include "scitems.hxx"
#include <editeng/langitem.hxx>
#include <editeng/justifyitem.hxx>
#include <formula/random.hxx>
#include <osl/thread.h>
#include <svx/algitem.hxx>
#include <unotools/textsearch.hxx>
......@@ -1662,7 +1663,7 @@ void ScInterpreter::ScPi()
void ScInterpreter::ScRandom()
{
PushDouble(::comphelper::rng::uniform_real_distribution());
PushDouble(formula::rng::fRandom(0, 1));
}
void ScInterpreter::ScTrue()
......
......@@ -33,6 +33,7 @@ $(eval $(call gb_Library_use_libraries,analysis,\
comphelper \
cppu \
cppuhelper \
for \
sal \
tl \
i18nlangtag \
......
......@@ -22,8 +22,8 @@
#include "bessel.hxx"
#include <cppuhelper/factory.hxx>
#include <comphelper/processfactory.hxx>
#include <comphelper/random.hxx>
#include <cppuhelper/supportsservice.hxx>
#include <formula/random.hxx>
#include <osl/diagnose.h>
#include <rtl/ustrbuf.hxx>
#include <rtl/math.hxx>
......@@ -703,7 +703,7 @@ double SAL_CALL AnalysisAddIn::getRandbetween( double fMin, double fMax ) throw(
if( fMin > fMax )
throw lang::IllegalArgumentException();
double fRet = floor(comphelper::rng::uniform_real_distribution(fMin, nextafter(fMax+1, -DBL_MAX)));
double fRet = floor(formula::rng::fRandom(fMin, nextafter(fMax+1, -DBL_MAX)));
RETURN_FINITE( fRet );
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment