[Bug][Function] Fix rand() function return same value (#4709)

fix rand function return same value when no parameter
This commit is contained in:
Zhengguo Yang
2020-10-11 15:40:38 +08:00
committed by GitHub
parent 04f26e4b7f
commit 98e71a8b9f
6 changed files with 83 additions and 18 deletions

View File

@ -20,6 +20,7 @@
#include <iomanip>
#include <sstream>
#include <cmath>
#include <random>
#include <stdlib.h>
#include "common/compiler_util.h"
@ -276,10 +277,17 @@ DoubleVal MathFunctions::pow(
void MathFunctions::rand_prepare(
FunctionContext* ctx, FunctionContext::FunctionStateScope scope) {
std::mt19937* generator = reinterpret_cast<std::mt19937*>(
ctx->allocate(sizeof(std::mt19937)));
if (UNLIKELY(generator == NULL)) {
LOG(ERROR) << "allocate random seed generator failed.";
return;
}
ctx->set_function_state(scope, generator);
new (generator) std::mt19937();
if (scope == FunctionContext::THREAD_LOCAL) {
uint32_t* seed = reinterpret_cast<uint32_t*>(ctx->allocate(sizeof(uint32_t)));
ctx->set_function_state(scope, seed);
if (ctx->get_num_args() == 1) {
uint32_t seed = 0;
// This is a call to RandSeed, initialize the seed
// TODO: should we support non-constant seed?
if (!ctx->is_arg_constant(0)) {
@ -287,25 +295,24 @@ void MathFunctions::rand_prepare(
return;
}
BigIntVal* seed_arg = static_cast<BigIntVal*>(ctx->get_constant_arg(0));
if (seed_arg->is_null) {
seed = NULL;
} else {
*seed = seed_arg->val;
if (!seed_arg->is_null) {
seed = seed_arg->val;
}
generator->seed(seed);
} else {
// This is a call to Rand, initialize seed to 0
// TODO: can we change this behavior? This is stupid.
*seed = 0;
generator->seed(std::random_device()());
}
}
}
DoubleVal MathFunctions::rand(FunctionContext* ctx) {
uint32_t* seed = reinterpret_cast<uint32_t*>(
std::mt19937* generator = reinterpret_cast<std::mt19937*>(
ctx->get_function_state(FunctionContext::THREAD_LOCAL));
*seed = ::rand_r(seed);
// Normalize to [0,1].
return DoubleVal(static_cast<double>(*seed) / RAND_MAX);
DCHECK(generator != nullptr);
static const double min = 0.0;
static const double max = 1.0;
std::uniform_real_distribution<double> distribution(min, max);
return DoubleVal(distribution(*generator));
}
DoubleVal MathFunctions::rand_seed(FunctionContext* ctx, const BigIntVal& seed) {
@ -315,6 +322,16 @@ DoubleVal MathFunctions::rand_seed(FunctionContext* ctx, const BigIntVal& seed)
return rand(ctx);
}
void MathFunctions::rand_close(FunctionContext* ctx,
FunctionContext::FunctionStateScope scope) {
if (scope == FunctionContext::THREAD_LOCAL) {
uint8_t* generator = reinterpret_cast<uint8_t*>(
ctx->get_function_state(FunctionContext::THREAD_LOCAL));
ctx->free(generator);
ctx->set_function_state(FunctionContext::THREAD_LOCAL, nullptr);
}
}
StringVal MathFunctions::bin(FunctionContext* ctx, const BigIntVal& v) {
if (v.is_null) {
return StringVal::null();