1 // Copyright 2019 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "util/saturate_cast.h"
6
7 #include "gtest/gtest.h"
8
9 namespace openscreen {
10 namespace {
11
TEST(SaturateCastTest,LargerToSmallerSignedInteger)12 TEST(SaturateCastTest, LargerToSmallerSignedInteger) {
13 struct ValuePair {
14 int64_t from;
15 int32_t to;
16 };
17 constexpr ValuePair kValuePairs[] = {
18 {std::numeric_limits<int64_t>::max(),
19 std::numeric_limits<int32_t>::max()},
20 {std::numeric_limits<int64_t>::max() / 2 + 42,
21 std::numeric_limits<int32_t>::max()},
22 {std::numeric_limits<int32_t>::max(),
23 std::numeric_limits<int32_t>::max()},
24 {42, 42},
25 {0, 0},
26 {-42, -42},
27 {std::numeric_limits<int32_t>::min(),
28 std::numeric_limits<int32_t>::min()},
29 {std::numeric_limits<int64_t>::min() / 2 - 42,
30 std::numeric_limits<int32_t>::min()},
31 {std::numeric_limits<int64_t>::min(),
32 std::numeric_limits<int32_t>::min()},
33 };
34 for (const ValuePair& value_pair : kValuePairs) {
35 EXPECT_EQ(value_pair.to, saturate_cast<int32_t>(value_pair.from));
36 }
37 }
38
TEST(SaturateCastTest,LargerToSmallerUnsignedInteger)39 TEST(SaturateCastTest, LargerToSmallerUnsignedInteger) {
40 struct ValuePair {
41 uint64_t from;
42 uint32_t to;
43 };
44 constexpr ValuePair kValuePairs[] = {
45 {std::numeric_limits<uint64_t>::max(),
46 std::numeric_limits<uint32_t>::max()},
47 {std::numeric_limits<uint64_t>::max() / 2 + 42,
48 std::numeric_limits<uint32_t>::max()},
49 {std::numeric_limits<uint32_t>::max(),
50 std::numeric_limits<uint32_t>::max()},
51 {42, 42},
52 {0, 0},
53 };
54 for (const ValuePair& value_pair : kValuePairs) {
55 EXPECT_EQ(value_pair.to, saturate_cast<uint32_t>(value_pair.from));
56 }
57 }
58
TEST(SaturateCastTest,LargerSignedToSmallerUnsignedInteger)59 TEST(SaturateCastTest, LargerSignedToSmallerUnsignedInteger) {
60 struct ValuePair {
61 int64_t from;
62 uint32_t to;
63 };
64 constexpr ValuePair kValuePairs[] = {
65 {std::numeric_limits<int64_t>::max(),
66 std::numeric_limits<uint32_t>::max()},
67 {std::numeric_limits<int64_t>::max() / 2 + 42,
68 std::numeric_limits<uint32_t>::max()},
69 {std::numeric_limits<uint32_t>::max(),
70 std::numeric_limits<uint32_t>::max()},
71 {42, 42},
72 {0, 0},
73 {-42, 0},
74 {std::numeric_limits<int64_t>::min() / 2 - 42, 0},
75 {std::numeric_limits<int64_t>::min(), 0},
76 };
77 for (const ValuePair& value_pair : kValuePairs) {
78 EXPECT_EQ(value_pair.to, saturate_cast<uint32_t>(value_pair.from));
79 }
80 }
81
TEST(SaturateCastTest,LargerUnsignedToSmallerSignedInteger)82 TEST(SaturateCastTest, LargerUnsignedToSmallerSignedInteger) {
83 struct ValuePair {
84 uint64_t from;
85 int32_t to;
86 };
87 constexpr ValuePair kValuePairs[] = {
88 {std::numeric_limits<uint64_t>::max(),
89 std::numeric_limits<int32_t>::max()},
90 {std::numeric_limits<uint64_t>::max() / 2 + 42,
91 std::numeric_limits<int32_t>::max()},
92 {std::numeric_limits<int32_t>::max(),
93 std::numeric_limits<int32_t>::max()},
94 {42, 42},
95 {0, 0},
96 };
97 for (const ValuePair& value_pair : kValuePairs) {
98 EXPECT_EQ(value_pair.to, saturate_cast<int32_t>(value_pair.from));
99 }
100 }
101
TEST(SaturateCastTest,SignedToUnsigned32BitInteger)102 TEST(SaturateCastTest, SignedToUnsigned32BitInteger) {
103 struct ValuePair {
104 int32_t from;
105 uint32_t to;
106 };
107 constexpr ValuePair kValuePairs[] = {
108 {std::numeric_limits<int32_t>::max(),
109 std::numeric_limits<int32_t>::max()},
110 {42, 42},
111 {0, 0},
112 {-42, 0},
113 {std::numeric_limits<int32_t>::min(), 0},
114 };
115 for (const ValuePair& value_pair : kValuePairs) {
116 EXPECT_EQ(value_pair.to, saturate_cast<uint32_t>(value_pair.from));
117 }
118 }
119
TEST(SaturateCastTest,UnsignedToSigned32BitInteger)120 TEST(SaturateCastTest, UnsignedToSigned32BitInteger) {
121 struct ValuePair {
122 uint32_t from;
123 int32_t to;
124 };
125 constexpr ValuePair kValuePairs[] = {
126 {std::numeric_limits<uint32_t>::max(),
127 std::numeric_limits<int32_t>::max()},
128 {std::numeric_limits<uint32_t>::max() / 2 + 42,
129 std::numeric_limits<int32_t>::max()},
130 {std::numeric_limits<int32_t>::max(),
131 std::numeric_limits<int32_t>::max()},
132 {42, 42},
133 {0, 0},
134 };
135 for (const ValuePair& value_pair : kValuePairs) {
136 EXPECT_EQ(value_pair.to, saturate_cast<int32_t>(value_pair.from));
137 }
138 }
139
TEST(SaturateCastTest,SignedToUnsigned64BitInteger)140 TEST(SaturateCastTest, SignedToUnsigned64BitInteger) {
141 struct ValuePair {
142 int64_t from;
143 uint64_t to;
144 };
145 constexpr ValuePair kValuePairs[] = {
146 {std::numeric_limits<int64_t>::max(),
147 std::numeric_limits<int64_t>::max()},
148 {42, 42},
149 {0, 0},
150 {-42, 0},
151 {std::numeric_limits<int64_t>::min(), 0},
152 };
153 for (const ValuePair& value_pair : kValuePairs) {
154 EXPECT_EQ(value_pair.to, saturate_cast<uint64_t>(value_pair.from));
155 }
156 }
157
TEST(SaturateCastTest,UnsignedToSigned64BitInteger)158 TEST(SaturateCastTest, UnsignedToSigned64BitInteger) {
159 struct ValuePair {
160 uint64_t from;
161 int64_t to;
162 };
163 constexpr ValuePair kValuePairs[] = {
164 {std::numeric_limits<uint64_t>::max(),
165 std::numeric_limits<int64_t>::max()},
166 {std::numeric_limits<uint64_t>::max() / 2 + 42,
167 std::numeric_limits<int64_t>::max()},
168 {std::numeric_limits<int64_t>::max(),
169 std::numeric_limits<int64_t>::max()},
170 {42, 42},
171 {0, 0},
172 };
173 for (const ValuePair& value_pair : kValuePairs) {
174 EXPECT_EQ(value_pair.to, saturate_cast<int64_t>(value_pair.from));
175 }
176 }
177
TEST(SaturateCastTest,Float32ToSigned32)178 TEST(SaturateCastTest, Float32ToSigned32) {
179 struct ValuePair {
180 float from;
181 int32_t to;
182 };
183 constexpr float kFloatMax = std::numeric_limits<float>::max();
184 // Note: kIntMax is one larger because float cannot represent the exact value.
185 constexpr float kIntMax =
186 static_cast<float>(std::numeric_limits<int32_t>::max());
187 constexpr float kIntMin = std::numeric_limits<int32_t>::min();
188 const ValuePair kValuePairs[] = {
189 {kFloatMax, std::numeric_limits<int32_t>::max()},
190 {std::nextafter(kIntMax, kFloatMax), std::numeric_limits<int32_t>::max()},
191 {kIntMax, std::numeric_limits<int32_t>::max()},
192 {std::nextafter(kIntMax, 0.f), 2147483520},
193 {42, 42},
194 {0, 0},
195 {-42, -42},
196 {std::nextafter(kIntMin, 0.f), -2147483520},
197 {kIntMin, std::numeric_limits<int32_t>::min()},
198 {std::nextafter(kIntMin, -kFloatMax),
199 std::numeric_limits<int32_t>::min()},
200 {-kFloatMax, std::numeric_limits<int32_t>::min()},
201 };
202 for (const ValuePair& value_pair : kValuePairs) {
203 EXPECT_EQ(value_pair.to, saturate_cast<int32_t>(value_pair.from));
204 }
205 }
206
TEST(SaturateCastTest,Float32ToSigned64)207 TEST(SaturateCastTest, Float32ToSigned64) {
208 struct ValuePair {
209 float from;
210 int64_t to;
211 };
212 constexpr float kFloatMax = std::numeric_limits<float>::max();
213 // Note: kIntMax is one larger because float cannot represent the exact value.
214 constexpr float kIntMax =
215 static_cast<float>(std::numeric_limits<int64_t>::max());
216 constexpr float kIntMin = std::numeric_limits<int64_t>::min();
217 const ValuePair kValuePairs[] = {
218 {kFloatMax, std::numeric_limits<int64_t>::max()},
219 {std::nextafter(kIntMax, kFloatMax), std::numeric_limits<int64_t>::max()},
220 {kIntMax, std::numeric_limits<int64_t>::max()},
221 {std::nextafter(kIntMax, 0.f), INT64_C(9223371487098961920)},
222 {42, 42},
223 {0, 0},
224 {-42, -42},
225 {std::nextafter(kIntMin, 0.f), INT64_C(-9223371487098961920)},
226 {kIntMin, std::numeric_limits<int64_t>::min()},
227 {std::nextafter(kIntMin, -kFloatMax),
228 std::numeric_limits<int64_t>::min()},
229 {-kFloatMax, std::numeric_limits<int64_t>::min()},
230 };
231 for (const ValuePair& value_pair : kValuePairs) {
232 EXPECT_EQ(value_pair.to, saturate_cast<int64_t>(value_pair.from));
233 }
234 }
235
TEST(SaturateCastTest,Float64ToSigned32)236 TEST(SaturateCastTest, Float64ToSigned32) {
237 struct ValuePair {
238 double from;
239 int32_t to;
240 };
241 constexpr double kDoubleMax = std::numeric_limits<double>::max();
242 constexpr double kIntMax = std::numeric_limits<int32_t>::max();
243 constexpr double kIntMin = std::numeric_limits<int32_t>::min();
244 const ValuePair kValuePairs[] = {
245 {kDoubleMax, std::numeric_limits<int32_t>::max()},
246 {std::nextafter(kIntMax, kDoubleMax),
247 std::numeric_limits<int32_t>::max()},
248 {kIntMax, std::numeric_limits<int32_t>::max()},
249 {std::nextafter(kIntMax, 0.0), std::numeric_limits<int32_t>::max() - 1},
250 {42, 42},
251 {0, 0},
252 {-42, -42},
253 {std::nextafter(kIntMin, 0.0), std::numeric_limits<int32_t>::min() + 1},
254 {kIntMin, std::numeric_limits<int32_t>::min()},
255 {std::nextafter(kIntMin, -kDoubleMax),
256 std::numeric_limits<int32_t>::min()},
257 {-kDoubleMax, std::numeric_limits<int32_t>::min()},
258 };
259 for (const ValuePair& value_pair : kValuePairs) {
260 EXPECT_EQ(value_pair.to, saturate_cast<int32_t>(value_pair.from));
261 }
262 }
263
TEST(SaturateCastTest,Float64ToSigned64)264 TEST(SaturateCastTest, Float64ToSigned64) {
265 struct ValuePair {
266 double from;
267 int64_t to;
268 };
269 constexpr double kDoubleMax = std::numeric_limits<double>::max();
270 // Note: kIntMax is one larger because double cannot represent the exact
271 // value.
272 constexpr double kIntMax =
273 static_cast<double>(std::numeric_limits<int64_t>::max());
274 constexpr double kIntMin = std::numeric_limits<int64_t>::min();
275 const ValuePair kValuePairs[] = {
276 {kDoubleMax, std::numeric_limits<int64_t>::max()},
277 {std::nextafter(kIntMax, kDoubleMax),
278 std::numeric_limits<int64_t>::max()},
279 {kIntMax, std::numeric_limits<int64_t>::max()},
280 {std::nextafter(kIntMax, 0.0), INT64_C(9223372036854774784)},
281 {42, 42},
282 {0, 0},
283 {-42, -42},
284 {std::nextafter(kIntMin, 0.0), INT64_C(-9223372036854774784)},
285 {kIntMin, std::numeric_limits<int64_t>::min()},
286 {std::nextafter(kIntMin, -kDoubleMax),
287 std::numeric_limits<int64_t>::min()},
288 {-kDoubleMax, std::numeric_limits<int64_t>::min()},
289 };
290 for (const ValuePair& value_pair : kValuePairs) {
291 EXPECT_EQ(value_pair.to, saturate_cast<int64_t>(value_pair.from));
292 }
293 }
294
TEST(SaturateCastTest,Float32ToUnsigned64)295 TEST(SaturateCastTest, Float32ToUnsigned64) {
296 struct ValuePair {
297 float from;
298 uint64_t to;
299 };
300 constexpr float kFloatMax = std::numeric_limits<float>::max();
301 // Note: kIntMax is one larger because float cannot represent the exact value.
302 constexpr float kIntMax =
303 static_cast<float>(std::numeric_limits<uint64_t>::max());
304 const ValuePair kValuePairs[] = {
305 {kFloatMax, std::numeric_limits<uint64_t>::max()},
306 {std::nextafter(kIntMax, kFloatMax),
307 std::numeric_limits<uint64_t>::max()},
308 {kIntMax, std::numeric_limits<uint64_t>::max()},
309 {std::nextafter(kIntMax, 0.f), UINT64_C(18446742974197923840)},
310 {42, 42},
311 {0, 0},
312 {-42, 0},
313 {-kFloatMax, 0},
314 };
315 for (const ValuePair& value_pair : kValuePairs) {
316 EXPECT_EQ(value_pair.to, saturate_cast<uint64_t>(value_pair.from));
317 }
318 }
319
TEST(SaturateCastTest,RoundingFloat32ToSigned64)320 TEST(SaturateCastTest, RoundingFloat32ToSigned64) {
321 struct ValuePair {
322 float from;
323 int64_t to;
324 };
325 constexpr float kFloatMax = std::numeric_limits<float>::max();
326 // Note: kIntMax is one larger because float cannot represent the exact value.
327 constexpr float kIntMax =
328 static_cast<float>(std::numeric_limits<int64_t>::max());
329 constexpr float kIntMin = std::numeric_limits<int64_t>::min();
330 const ValuePair kValuePairs[] = {
331 {kFloatMax, std::numeric_limits<int64_t>::max()},
332 {std::nextafter(kIntMax, kFloatMax), std::numeric_limits<int64_t>::max()},
333 {kIntMax, std::numeric_limits<int64_t>::max()},
334 {std::nextafter(kIntMax, 0.f), INT64_C(9223371487098961920)},
335 {41.9, 42},
336 {42, 42},
337 {42.6, 43},
338 {42.5, 43},
339 {42.4, 42},
340 {0.5, 1},
341 {0.1, 0},
342 {0, 0},
343 {-0.1, 0},
344 {-0.5, -1},
345 {-41.9, -42},
346 {-42, -42},
347 {-42.4, -42},
348 {-42.5, -43},
349 {-42.6, -43},
350 {std::nextafter(kIntMin, 0.f), INT64_C(-9223371487098961920)},
351 {kIntMin, std::numeric_limits<int64_t>::min()},
352 {std::nextafter(kIntMin, -kFloatMax),
353 std::numeric_limits<int64_t>::min()},
354 {-kFloatMax, std::numeric_limits<int64_t>::min()},
355 };
356 for (const ValuePair& value_pair : kValuePairs) {
357 EXPECT_EQ(value_pair.to, rounded_saturate_cast<int64_t>(value_pair.from));
358 }
359 }
360
361 } // namespace
362 } // namespace openscreen
363