random_test.cxx 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. //
  2. // random_test.cpp
  3. // shared_random_generator-test
  4. //
  5. // Created by Sam Jaffe on 8/14/20.
  6. // Copyright © 2020 Sam Jaffe. All rights reserved.
  7. //
  8. #include "shared_random_generator/random_impl.h"
  9. #include "shared_random_generator/random.h"
  10. #include <gmock/gmock.h>
  11. struct mock_random_impl : engine::detail::random_impl {
  12. MOCK_METHOD1(exclusive, uint32_t(uint32_t));
  13. MOCK_METHOD2(exclusive, double(double, double));
  14. MOCK_METHOD2(inclusive, double(double, double));
  15. };
  16. TEST(RandomTest, PassesThroughExclusiveIntegerCall) {
  17. auto mock = std::make_shared<mock_random_impl>();
  18. engine::random_number_generator generator{mock};
  19. EXPECT_CALL(*mock, exclusive(10)).Times(1);
  20. generator.exclusive(10);
  21. }
  22. TEST(RandomTest, PassesThroughExclusiveDoubleCall) {
  23. auto mock = std::make_shared<mock_random_impl>();
  24. engine::random_number_generator generator{mock};
  25. EXPECT_CALL(*mock, exclusive(1.0, 10.0)).Times(1);
  26. generator.exclusive(1.0, 10.0);
  27. }
  28. TEST(RandomTest, PassesThroughInclusiveDoubleCall) {
  29. auto mock = std::make_shared<mock_random_impl>();
  30. engine::random_number_generator generator{mock};
  31. EXPECT_CALL(*mock, inclusive(1.0, 10.0)).Times(1);
  32. generator.inclusive(1.0, 10.0);
  33. }
  34. class kahan_summation {
  35. private:
  36. double sum_{0.0};
  37. double carry_{0.0};
  38. public:
  39. kahan_summation() = default;
  40. kahan_summation & operator+=(double d);
  41. explicit operator double() const { return sum_; }
  42. };
  43. kahan_summation & kahan_summation::operator+=(double num) {
  44. double const yield = num - carry_;
  45. double const total = sum_ + yield;
  46. carry_ = (total - sum_) - yield;
  47. sum_ = total;
  48. return *this;
  49. }
  50. TEST(DefaultRandomTest, RandomDistributionIntIsUniform) {
  51. engine::random_number_generator generator{};
  52. kahan_summation sum{};
  53. size_t const iters = 2000000;
  54. for (size_t i = 0; i < iters; ++i) {
  55. // All values from 0 - 100 are allowable
  56. sum += generator.exclusive(101);
  57. }
  58. // Expected result is (0+99)/2 +/- 0.1%
  59. EXPECT_THAT(double(sum) / iters, testing::DoubleNear(50, 0.05));
  60. }
  61. TEST(DefaultRandomTest, RandomDistributionDblIsUniform) {
  62. engine::random_number_generator generator{};
  63. kahan_summation sum{};
  64. size_t const iters = 2000000;
  65. for (size_t i = 0; i < iters; ++i) {
  66. // All values from 0 - 99 are allowable
  67. sum += generator.exclusive(0.0, 100.0);
  68. }
  69. // Expected result is [0.0, 100.0) +/- 0.1%
  70. EXPECT_THAT(double(sum) / iters, testing::DoubleNear(50, 0.05));
  71. }
  72. TEST(DefaultRandomTest, InclusiveRangeMayIncludeValue) {
  73. engine::random_number_generator generator{};
  74. EXPECT_THAT(generator.inclusive(1.0, 1.0), testing::DoubleNear(1.0, 1E-6));
  75. }
  76. TEST(DefaultRandomTest, RandomDistributionDblInclIsUniform) {
  77. engine::random_number_generator generator{};
  78. kahan_summation sum{};
  79. size_t const iters = 2000000;
  80. for (size_t i = 0; i < iters; ++i) {
  81. // All values in [0.0, 100.0] are allowable
  82. sum += generator.inclusive(0.0, 100.0);
  83. }
  84. // Expected result is (0+100)/2 +/- 0.1%
  85. EXPECT_THAT(double(sum) / iters, testing::DoubleNear(50, 0.05));
  86. }