Skip to content
Open
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
25 changes: 25 additions & 0 deletions cpp/Platform.Random.Tests/RandomExtensionsTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,31 @@
ASSERT_LT(theSameCount, 8);
}

TEST(RandomExtensionsTests, NextUIntTemplateTest)
{
// Test NextUInt with different unsigned integer types
auto value8 = NextUInt<std::uint8_t>(RandomHelpers::Default);
auto value16 = NextUInt<std::uint16_t>(RandomHelpers::Default);
auto value32 = NextUInt<std::uint32_t>(RandomHelpers::Default);
auto value64 = NextUInt<std::uint64_t>(RandomHelpers::Default);

// Test with ranges
auto rangedValue8 = NextUInt<std::uint8_t>(RandomHelpers::Default, {0, 10});
auto rangedValue16 = NextUInt<std::uint16_t>(RandomHelpers::Default, {0, 100});
auto rangedValue32 = NextUInt<std::uint32_t>(RandomHelpers::Default, {0, 1000});
auto rangedValue64 = NextUInt<std::uint64_t>(RandomHelpers::Default, {0UL, 10000UL});

// Verify ranges
ASSERT_LE(rangedValue8, 10);
ASSERT_GE(rangedValue8, 0);
ASSERT_LE(rangedValue16, 100);
ASSERT_GE(rangedValue16, 0);
ASSERT_LE(rangedValue32, 1000);
ASSERT_GE(rangedValue32, 0);
ASSERT_LE(rangedValue64, 10000UL);
ASSERT_GE(rangedValue64, 0UL);
}

TEST(RandomExtensionsTests, NextBooleanTest)
{
auto trueCount = 0;
Expand Down
1 change: 1 addition & 0 deletions cpp/Platform.Random/Platform.Random.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#pragma once

#include <random>
#include <type_traits>

#include <Platform.Ranges.h>

Expand Down
22 changes: 20 additions & 2 deletions cpp/Platform.Random/RandomExtensions.h
Original file line number Diff line number Diff line change
@@ -1,8 +1,26 @@
namespace Platform::Random
{
std::uint64_t NextUInt64(std::mt19937_64& random, const Ranges::Range<std::uint64_t>& range) { return std::uniform_int_distribution<std::uint64_t>{range.Minimum, range.Maximum}(random); }
template<typename T>
T NextUInt(std::mt19937_64& random, const Ranges::Range<T>& range)
{
static_assert(std::is_unsigned_v<T>, "T must be an unsigned integer type");
return std::uniform_int_distribution<T>{range.Minimum, range.Maximum}(random);
}

std::uint64_t NextUInt64(std::mt19937_64& random) { return NextUInt64(random, Ranges::UInt64); }
template<typename T>
T NextUInt(std::mt19937_64& random)
{
static_assert(std::is_unsigned_v<T>, "T must be an unsigned integer type");
if constexpr (std::is_same_v<T, std::uint8_t>) return NextUInt<T>(random, Ranges::UInt8);
else if constexpr (std::is_same_v<T, std::uint16_t>) return NextUInt<T>(random, Ranges::UInt16);
else if constexpr (std::is_same_v<T, std::uint32_t>) return NextUInt<T>(random, Ranges::UInt32);
else if constexpr (std::is_same_v<T, std::uint64_t>) return NextUInt<T>(random, Ranges::UInt64);
else static_assert(std::false_type::value, "Unsupported unsigned integer type");
}

std::uint64_t NextUInt64(std::mt19937_64& random, const Ranges::Range<std::uint64_t>& range) { return NextUInt<std::uint64_t>(random, range); }

std::uint64_t NextUInt64(std::mt19937_64& random) { return NextUInt<std::uint64_t>(random); }

bool NextBoolean(std::mt19937_64& random) { return std::uniform_int_distribution<int>{}(random) % 2 == 0; }
}
64 changes: 64 additions & 0 deletions examples/syntax_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
#include <random>
#include <type_traits>

// Mock the Range structure for syntax check
namespace Ranges {
template<typename T>
struct Range {
T Minimum;
T Maximum;
};

inline Range<std::uint8_t> UInt8{0, 255};
inline Range<std::uint16_t> UInt16{0, 65535};
inline Range<std::uint32_t> UInt32{0, 4294967295U};
inline Range<std::uint64_t> UInt64{0UL, 18446744073709551615UL};
}

// Copy of our implementation
namespace Platform::Random
{
template<typename T>
T NextUInt(std::mt19937_64& random, const Ranges::Range<T>& range)
{
static_assert(std::is_unsigned_v<T>, "T must be an unsigned integer type");
return std::uniform_int_distribution<T>{range.Minimum, range.Maximum}(random);
}

template<typename T>
T NextUInt(std::mt19937_64& random)
{
static_assert(std::is_unsigned_v<T>, "T must be an unsigned integer type");
if constexpr (std::is_same_v<T, std::uint8_t>) return NextUInt<T>(random, Ranges::UInt8);
else if constexpr (std::is_same_v<T, std::uint16_t>) return NextUInt<T>(random, Ranges::UInt16);
else if constexpr (std::is_same_v<T, std::uint32_t>) return NextUInt<T>(random, Ranges::UInt32);
else if constexpr (std::is_same_v<T, std::uint64_t>) return NextUInt<T>(random, Ranges::UInt64);
else static_assert(std::false_type::value, "Unsupported unsigned integer type");
}

std::uint64_t NextUInt64(std::mt19937_64& random, const Ranges::Range<std::uint64_t>& range) { return NextUInt<std::uint64_t>(random, range); }

std::uint64_t NextUInt64(std::mt19937_64& random) { return NextUInt<std::uint64_t>(random); }

bool NextBoolean(std::mt19937_64& random) { return std::uniform_int_distribution<int>{}(random) % 2 == 0; }
}

int main() {
std::mt19937_64 rng;

// Test the template functions
auto val8 = Platform::Random::NextUInt<std::uint8_t>(rng);
auto val16 = Platform::Random::NextUInt<std::uint16_t>(rng);
auto val32 = Platform::Random::NextUInt<std::uint32_t>(rng);
auto val64 = Platform::Random::NextUInt<std::uint64_t>(rng);

// Test with ranges
auto ranged8 = Platform::Random::NextUInt<std::uint8_t>(rng, {0, 10});
auto ranged64 = Platform::Random::NextUInt<std::uint64_t>(rng, {0UL, 100UL});

// Test existing functions still work
auto oldVal = Platform::Random::NextUInt64(rng);
auto oldRanged = Platform::Random::NextUInt64(rng, {0UL, 50UL});

return 0;
}
Binary file added examples/syntax_test.o
Binary file not shown.
Loading