Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/prngs/prng.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ double PseudoRandomNumberGenerator::generateFloatingPointRandomValue(float min,

int64_t PseudoRandomNumberGenerator::generateIntegerRandomValue(int32_t min, int32_t max) {
double random_val = generateUnitNormalRandomValue();
double random_val_magnitude = random_val * (max - min);
double random_val_magnitude = random_val * (max - min + 1);
int64_t scaled_value = static_cast<int64_t>(min + random_val_magnitude);
return scaled_value;
}
88 changes: 88 additions & 0 deletions tests/test_LinearCongruentialGenerator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include "linear_congruential_generator.hpp"
#include <cstdint>
#include <limits>
#include <cmath>

// Test that the lcg constructors do not fail
TEST(TestLinearCongruentialGenerator, BlankConstructor) {
Expand Down Expand Up @@ -61,3 +62,90 @@ TEST(TestLinearCongruentialGenerator, GenerateUnitNormalRandomValueEquidistribut
const double confidence_interval = 0.01;
EXPECT_NEAR(average, expected_average, confidence_interval);
}


TEST(TestLinearCongruentialGenerator, GenerateFloatingPointRandomValueInRange){
LinearCongruentialGenerator lcg = LinearCongruentialGenerator();
const float min = -25.678f;
const float max = 3242.342f;
const int num_iterations = 1000;
for (int i = 0; i < num_iterations; ++i){
double value = lcg.generateFloatingPointRandomValue(min, max);
ASSERT_GE(value, min);
ASSERT_LE(value, max);
}
}

TEST(TestLinearCongruentialGenerator, GenerateFloatingPointRandomValueEquidistributed){
LinearCongruentialGenerator lcg = LinearCongruentialGenerator();
const double min = -300.0;
const double max = 700.0;
const int num_iterations = 10000;
double sum = 0.0;
double variance_sum = 0.0;
double expected_value = (min + max) / 2.0;
for (int i = 0; i < num_iterations; ++i){
double value = lcg.generateFloatingPointRandomValue(min, max);
sum += value;
variance_sum += (value - expected_value) * (value - expected_value);
}
double average = sum / num_iterations;
double variance = variance_sum / num_iterations;
double standard_deviation = std::sqrt(variance);
double three_sigma = 3 * standard_deviation;
ASSERT_NEAR(expected_value, average, three_sigma);;

}

TEST(TestLinearCongruentialGenerator, GenerateIntegerRandomValueInRange){
LinearCongruentialGenerator lcg = LinearCongruentialGenerator();
const int32_t min = -70;
const int32_t max = 141;
const int num_iterations = 1000;
for (int i = 0; i < num_iterations; ++i){
int64_t value = lcg.generateIntegerRandomValue(min, max);
ASSERT_GE(value, min);
ASSERT_LE(value, max);
}
}

TEST(TestLinearCongruentialGenerator, GenerateIntegerRandomValueEquidistributed){
LinearCongruentialGenerator lcg = LinearCongruentialGenerator();
const int32_t min = 1;
const int32_t max = 6;
const int num_iterations = 10000;
double sum = 0;
double expected_value = (min + max) / 2.0;
for (int i = 0; i < num_iterations; ++i){
sum += static_cast<double>(lcg.generateIntegerRandomValue(min, max));
}
double average = sum / num_iterations;
double margin_of_error = 0.02 * expected_value;
ASSERT_NEAR(expected_value, average, margin_of_error);
}


TEST(TestLinearCongruentialGenerator, GenerateIntegerRandomValueProducesInclusiveRange){
LinearCongruentialGenerator lcg = LinearCongruentialGenerator();
const int32_t min = 1;
const int32_t max = 6;
const int max_iterations = 1000;
bool found_min = false;
bool found_max = false;

for (int i = 0; i < max_iterations; ++i) {
int64_t value = lcg.generateIntegerRandomValue(min, max);
if (value == min) {
found_min = true;
}
if (value == max) {
found_max = true;
}
if (found_min && found_max) {
break; // No need to continue if both values are found
}
}

ASSERT_TRUE(found_min);
ASSERT_TRUE(found_max);
}
89 changes: 88 additions & 1 deletion tests/test_XORShift.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include "xorshift.hpp"
#include <cstdint>
#include <limits>
#include <cmath>

// Test that the lcg constructors do not fail
TEST(TestXORShift, BlankConstructor) {
Expand Down Expand Up @@ -34,7 +35,7 @@ TEST(TestXORShift, SeedAndConstantsConstructor) {
TEST(TestXORShift, GenerateUnitNormalRandomValueHasCorrectRange) {
XORShift xor_shift = XORShift();

const int enough_iterations_to_be_confident = 10000;
const int enough_iterations_to_be_confident = 1000;
for (int i = 0; i < enough_iterations_to_be_confident; ++i) {
const double value = xor_shift.generateUnitNormalRandomValue();
EXPECT_GE(value, 0.0);
Expand All @@ -59,4 +60,90 @@ TEST(TestXORShift, GenerateUnitNormalRandomValueEquidistributed) {
const double average = sum / enough_iterations_to_be_confident;
const double confidence_interval = 0.01;
EXPECT_NEAR(average, expected_average, confidence_interval);
}


TEST(TestXORShift, GenerateFloatingPointRandomValueInRange){
XORShift xor_shift = XORShift();
const float min = -25.678f;
const float max = 3242.342f;
const int num_iterations = 1000;
for (int i = 0; i < num_iterations; ++i){
double value = xor_shift.generateFloatingPointRandomValue(min, max);
ASSERT_GE(value, min);
ASSERT_LE(value, max);
}
}

TEST(TestXORShift, GenerateFloatingPointRandomValueEquidistributed){
XORShift xor_shift = XORShift();
const double min = -300.0;
const double max = 700.0;
const int num_iterations = 10000;
double sum = 0.0;
double variance_sum = 0.0;
double expected_value = (min + max) / 2.0;
for (int i = 0; i < num_iterations; ++i){
double value = xor_shift.generateFloatingPointRandomValue(min, max);
sum += value;
variance_sum += (value - expected_value) * (value - expected_value);
}
double average = sum / num_iterations;
double variance = variance_sum / num_iterations;
double standard_deviation = std::sqrt(variance);
double three_sigma = 3 * standard_deviation;
ASSERT_NEAR(expected_value, average, three_sigma);

}

TEST(TestXORShift, GenerateIntegerRandomValueInRange){
XORShift xor_shift = XORShift();
const int32_t min = -70;
const int32_t max = 141;
const int num_iterations = 1000;
for (int i = 0; i < num_iterations; ++i){
int64_t value = xor_shift.generateIntegerRandomValue(min, max);
ASSERT_GE(value, min);
ASSERT_LE(value, max);
}
}

TEST(TestXORShift, GenerateIntegerRandomValueEquidistributed){
XORShift xor_shift = XORShift();
const int32_t min = 1;
const int32_t max = 6;
const int num_iterations = 10000;
double sum = 0.0;
double expected_value = (min + max) / 2.0;
for (int i = 0; i < num_iterations; ++i){
sum += static_cast<double>(xor_shift.generateIntegerRandomValue(min, max));
}
double average = sum / num_iterations;
double margin_of_error = 0.02 * expected_value;
ASSERT_NEAR(expected_value, average, margin_of_error);
}

TEST(TestXORShift, GenerateIntegerRandomValueProducesInclusiveRange){
XORShift xor_shift = XORShift();
const int32_t min = 1;
const int32_t max = 6;
const int max_iterations = 1000;
bool found_min = false;
bool found_max = false;

for (int i = 0; i < max_iterations; ++i) {
int64_t value = xor_shift.generateIntegerRandomValue(min, max);
if (value == min) {
found_min = true;
}
if (value == max) {
found_max = true;
}
if (found_min && found_max) {
break; // No need to continue if both values are found
}
}

ASSERT_TRUE(found_min);
ASSERT_TRUE(found_max);
}
Loading