diff --git a/include/tscore/Random.h b/include/tscore/Random.h new file mode 100644 index 00000000000..6e13001b6a8 --- /dev/null +++ b/include/tscore/Random.h @@ -0,0 +1,56 @@ +/** @file + + Pseudorandom Number Generator + + @section license License + + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#include + +namespace ts +{ +class Random +{ +public: + Random() = delete; + + static uint64_t + random() + { + std::uniform_int_distribution dist{0, UINT64_MAX}; + return dist(_engine); + } + + static double + drandom() + { + std::uniform_real_distribution dist{0, 1}; + return dist(_engine); + } + + static void + seed(uint64_t s) + { + _engine.seed(s); + } + +private: + thread_local static std::mt19937_64 _engine; +}; +}; // namespace ts diff --git a/src/tscore/Makefile.am b/src/tscore/Makefile.am index 2f73d7b7fad..9610b2216b9 100644 --- a/src/tscore/Makefile.am +++ b/src/tscore/Makefile.am @@ -110,6 +110,7 @@ libtscore_la_SOURCES = \ MemArena.cc \ MMH.cc \ ParseRules.cc \ + Random.cc \ RbTree.cc \ Regex.cc \ Regression.cc \ @@ -190,7 +191,8 @@ test_tscore_SOURCES = \ unit_tests/test_ts_file.cc \ unit_tests/test_Version.cc \ unit_tests/test_Errata.cc \ - unit_tests/test_MMH.cc + unit_tests/test_MMH.cc \ + unit_tests/test_Random.cc if HAS_HKDF test_tscore_SOURCES += \ diff --git a/src/tscore/Random.cc b/src/tscore/Random.cc new file mode 100644 index 00000000000..155373f6d97 --- /dev/null +++ b/src/tscore/Random.cc @@ -0,0 +1,29 @@ +/** @file + + Pseudorandom Number Generator + + @section license License + + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#include "tscore/Random.h" + +namespace ts +{ +thread_local std::mt19937_64 Random::_engine{std::random_device{}()}; +}; // namespace ts diff --git a/src/tscore/unit_tests/test_Random.cc b/src/tscore/unit_tests/test_Random.cc new file mode 100644 index 00000000000..7d4b6a6619e --- /dev/null +++ b/src/tscore/unit_tests/test_Random.cc @@ -0,0 +1,52 @@ +/** @file + + Pseudorandom Number Generator test + + @section license License + + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#include "catch.hpp" +#include "tscore/Random.h" +#include "tscore/ink_rand.h" +#include + +TEST_CASE("test random", "[libts][random]") +{ + ts::Random::seed(13); + InkRand x(13); + + for (auto i = 0; i < 1000000; ++i) { + REQUIRE(ts::Random::random() == x.random()); + REQUIRE(uint64_t(ts::Random::drandom() * 100000000) == uint64_t(x.drandom() * 100000000)); // they are pretty close to the same + } + + auto start = std::chrono::high_resolution_clock::now(); + for (auto i = 0; i < 1000000; ++i) { + ts::Random::random(); + } + auto diff = std::chrono::duration_cast(std::chrono::high_resolution_clock::now() - start); + std::cout << std::endl << (double)diff.count() / 1000000 << " ns per Random::random()" << std::endl; + + start = std::chrono::high_resolution_clock::now(); + for (auto i = 0; i < 1000000; ++i) { + x.random(); + } + diff = std::chrono::duration_cast(std::chrono::high_resolution_clock::now() - start); + std::cout << (double)diff.count() / 1000000 << " ns per InkRand::random()" << std::endl; +}