abseil-cpp/absl/random/internal/uniform_helper_test.cc
Go to the documentation of this file.
1 // Copyright 2017 The Abseil Authors.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include "absl/random/internal/uniform_helper.h"
16 
17 #include <cmath>
18 #include <cstdint>
19 #include <random>
20 
21 #include "gtest/gtest.h"
22 
23 namespace {
24 
32 
33 class UniformHelperTest : public testing::Test {};
34 
35 TEST_F(UniformHelperTest, UniformBoundFunctionsGeneral) {
36  constexpr IntervalClosedClosedTag IntervalClosedClosed;
37  constexpr IntervalClosedOpenTag IntervalClosedOpen;
38  constexpr IntervalOpenClosedTag IntervalOpenClosed;
39  constexpr IntervalOpenOpenTag IntervalOpenOpen;
40 
41  // absl::uniform_int_distribution natively assumes IntervalClosedClosed
42  // absl::uniform_real_distribution natively assumes IntervalClosedOpen
43 
44  EXPECT_EQ(uniform_lower_bound(IntervalOpenClosed, 0, 100), 1);
45  EXPECT_EQ(uniform_lower_bound(IntervalOpenOpen, 0, 100), 1);
46  EXPECT_GT(uniform_lower_bound<float>(IntervalOpenClosed, 0, 1.0), 0);
47  EXPECT_GT(uniform_lower_bound<float>(IntervalOpenOpen, 0, 1.0), 0);
48  EXPECT_GT(uniform_lower_bound<double>(IntervalOpenClosed, 0, 1.0), 0);
49  EXPECT_GT(uniform_lower_bound<double>(IntervalOpenOpen, 0, 1.0), 0);
50 
51  EXPECT_EQ(uniform_lower_bound(IntervalClosedClosed, 0, 100), 0);
52  EXPECT_EQ(uniform_lower_bound(IntervalClosedOpen, 0, 100), 0);
53  EXPECT_EQ(uniform_lower_bound<float>(IntervalClosedClosed, 0, 1.0), 0);
54  EXPECT_EQ(uniform_lower_bound<float>(IntervalClosedOpen, 0, 1.0), 0);
55  EXPECT_EQ(uniform_lower_bound<double>(IntervalClosedClosed, 0, 1.0), 0);
56  EXPECT_EQ(uniform_lower_bound<double>(IntervalClosedOpen, 0, 1.0), 0);
57 
58  EXPECT_EQ(uniform_upper_bound(IntervalOpenOpen, 0, 100), 99);
59  EXPECT_EQ(uniform_upper_bound(IntervalClosedOpen, 0, 100), 99);
60  EXPECT_EQ(uniform_upper_bound<float>(IntervalOpenOpen, 0, 1.0), 1.0);
61  EXPECT_EQ(uniform_upper_bound<float>(IntervalClosedOpen, 0, 1.0), 1.0);
62  EXPECT_EQ(uniform_upper_bound<double>(IntervalOpenOpen, 0, 1.0), 1.0);
63  EXPECT_EQ(uniform_upper_bound<double>(IntervalClosedOpen, 0, 1.0), 1.0);
64 
65  EXPECT_EQ(uniform_upper_bound(IntervalOpenClosed, 0, 100), 100);
66  EXPECT_EQ(uniform_upper_bound(IntervalClosedClosed, 0, 100), 100);
67  EXPECT_GT(uniform_upper_bound<float>(IntervalOpenClosed, 0, 1.0), 1.0);
68  EXPECT_GT(uniform_upper_bound<float>(IntervalClosedClosed, 0, 1.0), 1.0);
69  EXPECT_GT(uniform_upper_bound<double>(IntervalOpenClosed, 0, 1.0), 1.0);
70  EXPECT_GT(uniform_upper_bound<double>(IntervalClosedClosed, 0, 1.0), 1.0);
71 
72  // Negative value tests
73  EXPECT_EQ(uniform_lower_bound(IntervalOpenClosed, -100, -1), -99);
74  EXPECT_EQ(uniform_lower_bound(IntervalOpenOpen, -100, -1), -99);
75  EXPECT_GT(uniform_lower_bound<float>(IntervalOpenClosed, -2.0, -1.0), -2.0);
76  EXPECT_GT(uniform_lower_bound<float>(IntervalOpenOpen, -2.0, -1.0), -2.0);
77  EXPECT_GT(uniform_lower_bound<double>(IntervalOpenClosed, -2.0, -1.0), -2.0);
78  EXPECT_GT(uniform_lower_bound<double>(IntervalOpenOpen, -2.0, -1.0), -2.0);
79 
80  EXPECT_EQ(uniform_lower_bound(IntervalClosedClosed, -100, -1), -100);
81  EXPECT_EQ(uniform_lower_bound(IntervalClosedOpen, -100, -1), -100);
82  EXPECT_EQ(uniform_lower_bound<float>(IntervalClosedClosed, -2.0, -1.0), -2.0);
83  EXPECT_EQ(uniform_lower_bound<float>(IntervalClosedOpen, -2.0, -1.0), -2.0);
84  EXPECT_EQ(uniform_lower_bound<double>(IntervalClosedClosed, -2.0, -1.0),
85  -2.0);
86  EXPECT_EQ(uniform_lower_bound<double>(IntervalClosedOpen, -2.0, -1.0), -2.0);
87 
88  EXPECT_EQ(uniform_upper_bound(IntervalOpenOpen, -100, -1), -2);
89  EXPECT_EQ(uniform_upper_bound(IntervalClosedOpen, -100, -1), -2);
90  EXPECT_EQ(uniform_upper_bound<float>(IntervalOpenOpen, -2.0, -1.0), -1.0);
91  EXPECT_EQ(uniform_upper_bound<float>(IntervalClosedOpen, -2.0, -1.0), -1.0);
92  EXPECT_EQ(uniform_upper_bound<double>(IntervalOpenOpen, -2.0, -1.0), -1.0);
93  EXPECT_EQ(uniform_upper_bound<double>(IntervalClosedOpen, -2.0, -1.0), -1.0);
94 
95  EXPECT_EQ(uniform_upper_bound(IntervalOpenClosed, -100, -1), -1);
96  EXPECT_EQ(uniform_upper_bound(IntervalClosedClosed, -100, -1), -1);
97  EXPECT_GT(uniform_upper_bound<float>(IntervalOpenClosed, -2.0, -1.0), -1.0);
98  EXPECT_GT(uniform_upper_bound<float>(IntervalClosedClosed, -2.0, -1.0), -1.0);
99  EXPECT_GT(uniform_upper_bound<double>(IntervalOpenClosed, -2.0, -1.0), -1.0);
100  EXPECT_GT(uniform_upper_bound<double>(IntervalClosedClosed, -2.0, -1.0),
101  -1.0);
102 
103  EXPECT_GT(uniform_lower_bound(IntervalOpenClosed, 1.0, 2.0), 1.0);
104  EXPECT_LT(uniform_lower_bound(IntervalOpenClosed, 1.0, +0.0), 1.0);
105  EXPECT_LT(uniform_lower_bound(IntervalOpenClosed, 1.0, -0.0), 1.0);
106  EXPECT_LT(uniform_lower_bound(IntervalOpenClosed, 1.0, -1.0), 1.0);
107 }
108 
109 TEST_F(UniformHelperTest, UniformBoundFunctionsIntBounds) {
110  // Verifies the saturating nature of uniform_lower_bound and
111  // uniform_upper_bound
112  constexpr IntervalOpenOpenTag IntervalOpenOpen;
113 
114  // uint max.
115  constexpr auto m = (std::numeric_limits<uint64_t>::max)();
116 
117  EXPECT_EQ(1, uniform_lower_bound(IntervalOpenOpen, 0u, 0u));
118  EXPECT_EQ(m, uniform_lower_bound(IntervalOpenOpen, m, m));
119  EXPECT_EQ(m, uniform_lower_bound(IntervalOpenOpen, m - 1, m - 1));
120  EXPECT_EQ(0, uniform_upper_bound(IntervalOpenOpen, 0u, 0u));
121  EXPECT_EQ(m - 1, uniform_upper_bound(IntervalOpenOpen, m, m));
122 
123  // int min/max
124  constexpr auto l = (std::numeric_limits<int64_t>::min)();
125  constexpr auto r = (std::numeric_limits<int64_t>::max)();
126  EXPECT_EQ(1, uniform_lower_bound(IntervalOpenOpen, 0, 0));
127  EXPECT_EQ(l + 1, uniform_lower_bound(IntervalOpenOpen, l, l));
128  EXPECT_EQ(r, uniform_lower_bound(IntervalOpenOpen, r - 1, r - 1));
129  EXPECT_EQ(r, uniform_lower_bound(IntervalOpenOpen, r, r));
130  EXPECT_EQ(-1, uniform_upper_bound(IntervalOpenOpen, 0, 0));
131  EXPECT_EQ(l, uniform_upper_bound(IntervalOpenOpen, l, l));
132  EXPECT_EQ(r - 1, uniform_upper_bound(IntervalOpenOpen, r, r));
133 }
134 
135 TEST_F(UniformHelperTest, UniformBoundFunctionsRealBounds) {
136  // absl::uniform_real_distribution natively assumes IntervalClosedOpen;
137  // use the inverse here so each bound has to change.
138  constexpr IntervalOpenClosedTag IntervalOpenClosed;
139 
140  // Edge cases: the next value toward itself is itself.
141  EXPECT_EQ(1.0, uniform_lower_bound(IntervalOpenClosed, 1.0, 1.0));
142  EXPECT_EQ(1.0f, uniform_lower_bound(IntervalOpenClosed, 1.0f, 1.0f));
143 
144  // rightmost and leftmost finite values.
145  constexpr auto r = (std::numeric_limits<double>::max)();
146  const auto re = std::nexttoward(r, 0.0);
147  constexpr auto l = -r;
148  const auto le = std::nexttoward(l, 0.0);
149 
150  EXPECT_EQ(l, uniform_lower_bound(IntervalOpenClosed, l, l)); // (l,l)
151  EXPECT_EQ(r, uniform_lower_bound(IntervalOpenClosed, r, r)); // (r,r)
152  EXPECT_EQ(le, uniform_lower_bound(IntervalOpenClosed, l, r)); // (l,r)
153  EXPECT_EQ(le, uniform_lower_bound(IntervalOpenClosed, l, 0.0)); // (l, 0)
154  EXPECT_EQ(le, uniform_lower_bound(IntervalOpenClosed, l, le)); // (l, le)
155  EXPECT_EQ(r, uniform_lower_bound(IntervalOpenClosed, re, r)); // (re, r)
156 
157  EXPECT_EQ(le, uniform_upper_bound(IntervalOpenClosed, l, l)); // (l,l)
158  EXPECT_EQ(r, uniform_upper_bound(IntervalOpenClosed, r, r)); // (r,r)
159  EXPECT_EQ(r, uniform_upper_bound(IntervalOpenClosed, l, r)); // (l,r)
160  EXPECT_EQ(r, uniform_upper_bound(IntervalOpenClosed, l, re)); // (l,re)
161  EXPECT_EQ(r, uniform_upper_bound(IntervalOpenClosed, 0.0, r)); // (0, r)
162  EXPECT_EQ(r, uniform_upper_bound(IntervalOpenClosed, re, r)); // (re, r)
163  EXPECT_EQ(r, uniform_upper_bound(IntervalOpenClosed, le, re)); // (le, re)
164 
165  const double e = std::nextafter(1.0, 2.0); // 1 + epsilon
166  const double f = std::nextafter(1.0, 0.0); // 1 - epsilon
167 
168  // (1.0, 1.0 + epsilon)
169  EXPECT_EQ(e, uniform_lower_bound(IntervalOpenClosed, 1.0, e));
170  EXPECT_EQ(std::nextafter(e, 2.0),
171  uniform_upper_bound(IntervalOpenClosed, 1.0, e));
172 
173  // (1.0-epsilon, 1.0)
174  EXPECT_EQ(1.0, uniform_lower_bound(IntervalOpenClosed, f, 1.0));
175  EXPECT_EQ(e, uniform_upper_bound(IntervalOpenClosed, f, 1.0));
176 
177  // denorm cases.
178  const double g = std::numeric_limits<double>::denorm_min();
179  const double h = std::nextafter(g, 1.0);
180 
181  // (0, denorm_min)
182  EXPECT_EQ(g, uniform_lower_bound(IntervalOpenClosed, 0.0, g));
183  EXPECT_EQ(h, uniform_upper_bound(IntervalOpenClosed, 0.0, g));
184 
185  // (denorm_min, 1.0)
186  EXPECT_EQ(h, uniform_lower_bound(IntervalOpenClosed, g, 1.0));
187  EXPECT_EQ(e, uniform_upper_bound(IntervalOpenClosed, g, 1.0));
188 
189  // Edge cases: invalid bounds.
190  EXPECT_EQ(f, uniform_lower_bound(IntervalOpenClosed, 1.0, -1.0));
191 }
192 
193 struct Invalid {};
194 
195 template <typename A, typename B>
196 auto InferredUniformReturnT(int) -> uniform_inferred_return_t<A, B>;
197 
198 template <typename, typename>
199 Invalid InferredUniformReturnT(...);
200 
201 // Given types <A, B, Expect>, CheckArgsInferType() verifies that
202 //
203 // uniform_inferred_return_t<A, B> and
204 // uniform_inferred_return_t<B, A>
205 //
206 // returns the type "Expect".
207 //
208 // This interface can also be used to assert that a given inferred return types
209 // are invalid. Writing:
210 //
211 // CheckArgsInferType<float, int, Invalid>()
212 //
213 // will assert that this overload does not exist.
214 template <typename A, typename B, typename Expect>
215 void CheckArgsInferType() {
216  static_assert(
218  std::is_same<Expect, decltype(InferredUniformReturnT<A, B>(0))>,
219  std::is_same<Expect,
220  decltype(InferredUniformReturnT<B, A>(0))>>::value,
221  "");
222 }
223 
224 TEST_F(UniformHelperTest, UniformTypeInference) {
225  // Infers common types.
226  CheckArgsInferType<uint16_t, uint16_t, uint16_t>();
227  CheckArgsInferType<uint32_t, uint32_t, uint32_t>();
228  CheckArgsInferType<uint64_t, uint64_t, uint64_t>();
229  CheckArgsInferType<int16_t, int16_t, int16_t>();
230  CheckArgsInferType<int32_t, int32_t, int32_t>();
231  CheckArgsInferType<int64_t, int64_t, int64_t>();
232  CheckArgsInferType<float, float, float>();
233  CheckArgsInferType<double, double, double>();
234 
235  // Properly promotes uint16_t.
236  CheckArgsInferType<uint16_t, uint32_t, uint32_t>();
237  CheckArgsInferType<uint16_t, uint64_t, uint64_t>();
238  CheckArgsInferType<uint16_t, int32_t, int32_t>();
239  CheckArgsInferType<uint16_t, int64_t, int64_t>();
240  CheckArgsInferType<uint16_t, float, float>();
241  CheckArgsInferType<uint16_t, double, double>();
242 
243  // Properly promotes int16_t.
244  CheckArgsInferType<int16_t, int32_t, int32_t>();
245  CheckArgsInferType<int16_t, int64_t, int64_t>();
246  CheckArgsInferType<int16_t, float, float>();
247  CheckArgsInferType<int16_t, double, double>();
248 
249  // Invalid (u)int16_t-pairings do not compile.
250  // See "CheckArgsInferType" comments above, for how this is achieved.
251  CheckArgsInferType<uint16_t, int16_t, Invalid>();
252  CheckArgsInferType<int16_t, uint32_t, Invalid>();
253  CheckArgsInferType<int16_t, uint64_t, Invalid>();
254 
255  // Properly promotes uint32_t.
256  CheckArgsInferType<uint32_t, uint64_t, uint64_t>();
257  CheckArgsInferType<uint32_t, int64_t, int64_t>();
258  CheckArgsInferType<uint32_t, double, double>();
259 
260  // Properly promotes int32_t.
261  CheckArgsInferType<int32_t, int64_t, int64_t>();
262  CheckArgsInferType<int32_t, double, double>();
263 
264  // Invalid (u)int32_t-pairings do not compile.
265  CheckArgsInferType<uint32_t, int32_t, Invalid>();
266  CheckArgsInferType<int32_t, uint64_t, Invalid>();
267  CheckArgsInferType<int32_t, float, Invalid>();
268  CheckArgsInferType<uint32_t, float, Invalid>();
269 
270  // Invalid (u)int64_t-pairings do not compile.
271  CheckArgsInferType<uint64_t, int64_t, Invalid>();
272  CheckArgsInferType<int64_t, float, Invalid>();
273  CheckArgsInferType<int64_t, double, Invalid>();
274 
275  // Properly promotes float.
276  CheckArgsInferType<float, double, double>();
277 }
278 
279 } // namespace
absl::IntervalOpenClosedTag
Definition: abseil-cpp/absl/random/internal/uniform_helper.h:58
absl::IntervalOpenOpenTag
Definition: abseil-cpp/absl/random/internal/uniform_helper.h:60
absl::random_internal::uniform_inferred_return_t
absl::enable_if_t< absl::disjunction< is_widening_convertible< A, B >, is_widening_convertible< B, A > >::value, typename std::conditional< is_widening_convertible< A, B >::value, B, A >::type > uniform_inferred_return_t
Definition: abseil-cpp/absl/random/internal/uniform_helper.h:82
absl::conjunction
Definition: abseil-cpp/absl/meta/type_traits.h:230
EXPECT_GT
#define EXPECT_GT(val1, val2)
Definition: bloaty/third_party/googletest/googletest/include/gtest/gtest.h:2036
u
OPENSSL_EXPORT pem_password_cb void * u
Definition: pem.h:351
testing::Test
Definition: bloaty/third_party/googletest/googletest/include/gtest/gtest.h:402
absl::IntervalClosedClosedTag
Definition: abseil-cpp/absl/random/internal/uniform_helper.h:54
EXPECT_EQ
#define EXPECT_EQ(a, b)
Definition: iomgr/time_averaged_stats_test.cc:27
absl::FormatConversionChar::e
@ e
autogen_x86imm.f
f
Definition: autogen_x86imm.py:9
max
int max
Definition: bloaty/third_party/zlib/examples/enough.c:170
min
#define min(a, b)
Definition: qsort.h:83
g
struct @717 g
absl::random_internal::uniform_lower_bound
absl::enable_if_t< absl::conjunction< IsIntegral< IntType >, absl::disjunction< std::is_same< Tag, IntervalOpenClosedTag >, std::is_same< Tag, IntervalOpenOpenTag > > >::value, IntType > uniform_lower_bound(Tag, IntType a, IntType)
Definition: abseil-cpp/absl/random/internal/uniform_helper.h:107
value
const char * value
Definition: hpack_parser_table.cc:165
testing::internal::Invalid
T Invalid()
Definition: bloaty/third_party/googletest/googlemock/include/gmock/internal/gmock-internal-utils.h:356
absl::IntervalClosedOpenTag
Definition: abseil-cpp/absl/random/internal/uniform_helper.h:56
fix_build_deps.r
r
Definition: fix_build_deps.py:491
EXPECT_LT
#define EXPECT_LT(val1, val2)
Definition: bloaty/third_party/googletest/googletest/include/gtest/gtest.h:2032
run_grpclb_interop_tests.l
dictionary l
Definition: run_grpclb_interop_tests.py:410
regress.m
m
Definition: regress/regress.py:25
absl::random_internal::uniform_upper_bound
absl::enable_if_t< absl::conjunction< IsIntegral< IntType >, absl::disjunction< std::is_same< Tag, IntervalClosedOpenTag >, std::is_same< Tag, IntervalOpenOpenTag > > >::value, IntType > uniform_upper_bound(Tag, IntType, IntType b)
Definition: abseil-cpp/absl/random/internal/uniform_helper.h:138
absl::str_format_internal::LengthMod::h
@ h
testing::internal::Expect
void Expect(bool condition, const char *file, int line, const std::string &msg)
Definition: bloaty/third_party/googletest/googlemock/include/gmock/internal/gmock-internal-utils.h:282
TEST_F
#define TEST_F(test_fixture, test_name)
Definition: bloaty/third_party/googletest/googletest/include/gtest/gtest.h:2367


grpc
Author(s):
autogenerated on Fri May 16 2025 03:00:44