summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorRoland Reichwein <mail@reichwein.it>2022-01-04 19:45:01 +0100
committerRoland Reichwein <mail@reichwein.it>2022-01-04 19:45:01 +0100
commitd75cefda8a5ea08976d6bb512150d7c6891ac73e (patch)
tree47519da89eb2d4d833368fddf33bcd02b12da86c
parent037aab267c81f0bedff1ff21b2ff82217f6a9d59 (diff)
Performance tests on deterministic data
-rw-r--r--src/test-performance.cpp80
1 files changed, 46 insertions, 34 deletions
diff --git a/src/test-performance.cpp b/src/test-performance.cpp
index 629aadd..64535c6 100644
--- a/src/test-performance.cpp
+++ b/src/test-performance.cpp
@@ -19,7 +19,6 @@
#include <limits>
#include <list>
#include <locale>
-#include <random>
#include <string>
#include <tuple>
#include <type_traits>
@@ -34,49 +33,68 @@ using namespace std::string_literals;
typedef std::tuple<std::basic_string<utf8_t>, std::basic_string<char16_t>, std::basic_string<char32_t>> types_collection_type;
-struct random_context {
- random_context(int max_value = 0x10FFFF - 0x800): code_point_distribution(0, max_value) {}
- std::random_device rd; // OS random number engine to seed RNG (below)
- std::mt19937 gen{rd()};
- std::uniform_int_distribution<size_t> sequence_length{0, 100000}; // length of sequence: 0 ... 100000 code units
- std::uniform_int_distribution<unsigned long> code_point_distribution;
-};
+// LCG for generating deterministic mixed data, see also https://arxiv.org/pdf/2001.05304.pdf
+uint8_t generate_byte()
+{
+ static uint64_t x{1};
+ const static uint32_t a{0x915f77f5};
+ const static uint32_t c{12345};
+ const static uint32_t m_mask{0xFFFFFFFF};
+
+ x = (x * a + c) & m_mask;
+
+ return (x >> 16) & 0xFF;
+}
+
+// max is inclusive
+template<typename T>
+T generate_value(T max = std::numeric_limits<T>::max())
+{
+ uint64_t max_modulo{ static_cast<uint64_t>(0x100000000ULL) - (0x100000000ULL % (max + 1))};
+
+ uint32_t value{};
+ do {
+ for (int i = 0; i < sizeof(value); ++i) {
+ value = (value << 8) | generate_byte();
+ }
+ } while (static_cast<uint64_t>(value) >= max_modulo);
+
+ return static_cast<T>(value % (max + 1));
+}
// generates valid and invalid strings of different type
template<typename T>
-T generate_random_invalid(random_context& rc, size_t length)
+T generate_string_invalid(size_t length)
{
- // Using unsigned long for std::uniform_int_distribution<> because it needs to be basic type according to MSVC
- std::uniform_int_distribution<unsigned long> code_unit{0, std::numeric_limits<typename T::value_type>::max()}; // code unit value
T result;
- std::generate_n(std::back_inserter(result), length, [&](){return static_cast<typename T::value_type>(code_unit(rc.gen));});
+ std::generate_n(std::back_inserter(result), length, [&](){return generate_value<typename T::value_type>();});
return result;
}
-char32_t generate_random_char(random_context& rc)
+char32_t generate_char(char32_t max = 0x10FFFF - 0x800)
{
- auto result {rc.code_point_distribution(rc.gen)};
+ char32_t result {generate_value<char32_t>(max)};
if (result >= 0xD800)
result += 0x800;
return static_cast<char32_t>(result);
}
-std::u32string generate_random_string(random_context& rc, size_t length)
+std::u32string generate_string(char32_t max, size_t length)
{
std::u32string result;
- std::generate_n(std::back_inserter(result), length, [&](){return generate_random_char(rc);});
+ std::generate_n(std::back_inserter(result), length, [&](){return generate_char(max);});
return result;
}
template<typename From, typename ToTypesCollectionType, size_t i = 0>
-void test_random_invalid(random_context& rc, size_t length)
+void test_string_invalid(size_t length)
{
//std::cerr << "LENGTH: " << length << std::endl;
typedef typename std::tuple_element<i,ToTypesCollectionType>::type To;
- From r {static_cast<From>(generate_random_invalid<From>(rc, length))};
+ From r {static_cast<From>(generate_string_invalid<From>(length))};
// base type interface
try {
@@ -125,15 +143,13 @@ void test_random_invalid(random_context& rc, size_t length)
// iterate over remaining To types
if constexpr (i + 1 < std::tuple_size<ToTypesCollectionType>::value)
- test_random_invalid<From, ToTypesCollectionType, i + 1>(rc, length);
+ test_string_invalid<From, ToTypesCollectionType, i + 1>(length);
}
-BOOST_AUTO_TEST_CASE_TEMPLATE(random_sequences_invalid, T, types_collection_type)
+BOOST_AUTO_TEST_CASE_TEMPLATE(sequences_invalid, T, types_collection_type)
{
- random_context rc;
-
for (int i = 0; i < 10; i++) {
- test_random_invalid<T,types_collection_type>(rc, rc.sequence_length(rc.gen));
+ test_string_invalid<T,types_collection_type>(generate_value<size_t>(100000));
}
}
@@ -166,13 +182,13 @@ private:
};
template<typename From, typename ToTypesCollectionType, size_t index = 0>
-void test_random_valid(random_context& rc, size_t length, const std::string& description)
+void test_string_valid(char32_t max, size_t length, const std::string& description)
{
typedef typename std::tuple_element<index,ToTypesCollectionType>::type To;
// Fill UTF-32 data list: source for tests
std::vector<std::u32string> u32list;
- std::generate_n(std::back_inserter(u32list), 1000, [&](){return generate_random_string(rc, rc.sequence_length(rc.gen));});
+ std::generate_n(std::back_inserter(u32list), 1000, [&](){return generate_string(max, generate_value<size_t>(100000));});
// Fill From data list
std::vector<From> list;
@@ -211,20 +227,16 @@ void test_random_valid(random_context& rc, size_t length, const std::string& des
// iterate over remaining To types
if constexpr (index + 1 < std::tuple_size<ToTypesCollectionType>::value)
- test_random_valid<From, ToTypesCollectionType, index + 1>(rc, length, description);
+ test_string_valid<From, ToTypesCollectionType, index + 1>(max, length, description);
}
-BOOST_AUTO_TEST_CASE_TEMPLATE(random_sequences_valid_ascii, T, types_collection_type)
+BOOST_AUTO_TEST_CASE_TEMPLATE(sequences_valid_ascii, T, types_collection_type)
{
- random_context rc{127};
-
- test_random_valid<T,types_collection_type>(rc, rc.sequence_length(rc.gen), "ASCII only strings");
+ test_string_valid<T,types_collection_type>(127, generate_value<size_t>(100000), "ASCII only strings");
}
-BOOST_AUTO_TEST_CASE_TEMPLATE(random_sequences_valid_all_unicode, T, types_collection_type)
+BOOST_AUTO_TEST_CASE_TEMPLATE(sequences_valid_all_unicode, T, types_collection_type)
{
- random_context rc;
-
- test_random_valid<T,types_collection_type>(rc, rc.sequence_length(rc.gen), "All Unicode strings");
+ test_string_valid<T,types_collection_type>(0x10FFFF - 0x800, generate_value<size_t>(100000), "All Unicode strings");
}