Merge pull request #22314 from Chaosus/rng

Random number generator(remake)
This commit is contained in:
Rémi Verschelde 2018-11-13 09:37:31 +01:00 committed by GitHub
commit a9f6bbe1fb
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 287 additions and 17 deletions

View file

@ -30,30 +30,27 @@
#include "math_funcs.h"
#include "core/os/os.h"
pcg32_random_t Math::default_pcg = { 12047754176567800795ULL, PCG_DEFAULT_INC_64 };
RandomPCG Math::default_rand(RandomPCG::DEFAULT_SEED, RandomPCG::DEFAULT_INC);
#define PHI 0x9e3779b9
// TODO: we should eventually expose pcg.inc too
uint32_t Math::rand_from_seed(uint64_t *seed) {
pcg32_random_t pcg = { *seed, PCG_DEFAULT_INC_64 };
uint32_t r = pcg32_random_r(&pcg);
*seed = pcg.state;
RandomPCG rng = RandomPCG(*seed, RandomPCG::DEFAULT_INC);
uint32_t r = rng.rand();
*seed = rng.get_seed();
return r;
}
void Math::seed(uint64_t x) {
default_pcg.state = x;
default_rand.seed(x);
}
void Math::randomize() {
seed(OS::get_singleton()->get_ticks_usec() * default_pcg.state + PCG_DEFAULT_INC_64);
default_rand.randomize();
}
uint32_t Math::rand() {
return pcg32_random_r(&default_pcg);
return default_rand.rand();
}
int Math::step_decimals(double p_step) {
@ -169,13 +166,9 @@ uint32_t Math::larger_prime(uint32_t p_val) {
}
double Math::random(double from, double to) {
unsigned int r = Math::rand();
double ret = (double)r / (double)RANDOM_MAX;
return (ret) * (to - from) + from;
return default_rand.random(from, to);
}
float Math::random(float from, float to) {
unsigned int r = Math::rand();
float ret = (float)r / (float)RANDOM_MAX;
return (ret) * (to - from) + from;
return default_rand.random(from, to);
}

View file

@ -32,6 +32,7 @@
#define MATH_FUNCS_H
#include "core/math/math_defs.h"
#include "core/math/random_pcg.h"
#include "core/typedefs.h"
#include "thirdparty/misc/pcg.h"
@ -41,7 +42,7 @@
class Math {
static pcg32_random_t default_pcg;
static RandomPCG default_rand;
public:
Math() {} // useless to instance

View file

@ -0,0 +1,45 @@
/*************************************************************************/
/* random_number_generator.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "random_number_generator.h"
RandomNumberGenerator::RandomNumberGenerator() :
randbase() {}
void RandomNumberGenerator::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_seed", "seed"), &RandomNumberGenerator::set_seed);
ClassDB::bind_method(D_METHOD("get_seed"), &RandomNumberGenerator::get_seed);
ADD_PROPERTY(PropertyInfo(Variant::INT, "seed"), "set_seed", "get_seed");
ClassDB::bind_method(D_METHOD("randi"), &RandomNumberGenerator::randi);
ClassDB::bind_method(D_METHOD("randf"), &RandomNumberGenerator::randf);
ClassDB::bind_method(D_METHOD("rand_range", "from", "to"), &RandomNumberGenerator::rand_range);
ClassDB::bind_method(D_METHOD("randomize"), &RandomNumberGenerator::randomize);
}

View file

@ -0,0 +1,61 @@
/*************************************************************************/
/* random_number_generator.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#ifndef RANDOM_NUMBER_GENERATOR_H
#define RANDOM_NUMBER_GENERATOR_H
#include "core/math/random_pcg.h"
#include "core/reference.h"
class RandomNumberGenerator : public Reference {
GDCLASS(RandomNumberGenerator, Reference);
RandomPCG randbase;
protected:
static void _bind_methods();
public:
_FORCE_INLINE_ void set_seed(uint64_t seed) { randbase.seed(seed); }
_FORCE_INLINE_ uint64_t get_seed() { return randbase.get_seed(); }
_FORCE_INLINE_ void randomize() { return randbase.randomize(); }
_FORCE_INLINE_ uint32_t randi() { return randbase.rand(); }
_FORCE_INLINE_ real_t randf() { return randbase.randf(); }
_FORCE_INLINE_ real_t rand_range(real_t from, real_t to) { return randbase.random(from, to); }
RandomNumberGenerator();
};
#endif // RANDOM_NUMBER_GENERATOR_H

55
core/math/random_pcg.cpp Normal file
View file

@ -0,0 +1,55 @@
/*************************************************************************/
/* random_pcg.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "random_pcg.h"
#include "core/os/os.h"
RandomPCG::RandomPCG(uint64_t seed, uint64_t inc) :
pcg() {
pcg.state = seed;
pcg.inc = inc;
}
void RandomPCG::randomize() {
seed(OS::get_singleton()->get_ticks_usec() * pcg.state + PCG_DEFAULT_INC_64);
}
double RandomPCG::random(double from, double to) {
unsigned int r = rand();
double ret = (double)r / (double)RANDOM_MAX;
return (ret) * (to - from) + from;
}
float RandomPCG::random(float from, float to) {
unsigned int r = rand();
float ret = (float)r / (float)RANDOM_MAX;
return (ret) * (to - from) + from;
}

61
core/math/random_pcg.h Normal file
View file

@ -0,0 +1,61 @@
/*************************************************************************/
/* random_pcg.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#ifndef RANDOM_PCG_H
#define RANDOM_PCG_H
#include "core/math/math_defs.h"
#include "thirdparty/misc/pcg.h"
class RandomPCG {
pcg32_random_t pcg;
public:
static const uint64_t DEFAULT_SEED = 12047754176567800795ULL;
static const uint64_t DEFAULT_INC = PCG_DEFAULT_INC_64;
static const uint64_t RANDOM_MAX = 4294967295;
RandomPCG(uint64_t seed = DEFAULT_SEED, uint64_t inc = PCG_DEFAULT_INC_64);
_FORCE_INLINE_ void seed(uint64_t seed) { pcg.state = seed; }
_FORCE_INLINE_ uint64_t get_seed() { return pcg.state; }
void randomize();
_FORCE_INLINE_ uint32_t rand() { return pcg32_random_r(&pcg); }
_FORCE_INLINE_ double randf() { return (double)rand() / (double)RANDOM_MAX; }
_FORCE_INLINE_ float randd() { return (float)rand() / (float)RANDOM_MAX; }
double random(double from, double to);
float random(float from, float to);
real_t random(int from, int to) { return (real_t)random((real_t)from, (real_t)to); }
};
#endif // RANDOM_PCG_H

View file

@ -55,6 +55,7 @@
#include "core/math/a_star.h"
#include "core/math/expression.h"
#include "core/math/geometry.h"
#include "core/math/random_number_generator.h"
#include "core/math/triangle_mesh.h"
#include "core/os/input.h"
#include "core/os/main_loop.h"
@ -180,6 +181,7 @@ void register_core_types() {
ClassDB::register_virtual_class<PackedDataContainerRef>();
ClassDB::register_class<AStar>();
ClassDB::register_class<EncodedObjectAsID>();
ClassDB::register_class<RandomNumberGenerator>();
ClassDB::register_class<JSONParseResult>();

View file

@ -0,0 +1,52 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="RandomNumberGenerator" inherits="Reference" category="Core" version="3.1">
<brief_description>
A class for generation pseudo-random numbers.
</brief_description>
<description>
</description>
<tutorials>
</tutorials>
<demos>
</demos>
<methods>
<method name="randi">
<return type="int">
</return>
<description>
Generates pseudo-random 32-bit integer between '0' and '4294967295'.
</description>
</method>
<method name="randf">
<return type="float">
</return>
<description>
Generates pseudo-random float between '0.0' and '1.0'.
</description>
</method>
<method name="rand_range">
<return type="float">
</return>
<argument index="0" name="from" type="float">
</argument>
<argument index="1" name="to" type="float">
</argument>
<description>
Generates pseudo-random float between [code]from[/code] and [code]to[/code].
</description>
</method>
<method name="randomize">
<return type="void">
</return>
<description>
Setups a time-based seed to generator.
</description>
</method>
</methods>
<members>
<member name="seed" type="int" setter="set_seed" getter="get_seed">
</member>
</members>
<constants>
</constants>
</class>