blob: 584804b6a8965f3d3846d1c9b82479808974716e [file] [log] [blame]
Brian Silverman246cb222019-02-02 16:38:18 -08001#include "aos/util/bitpacking.h"
2
Tyler Chatowbf0609c2021-07-31 16:13:27 -07003#include <cstdint>
Brian Silverman246cb222019-02-02 16:38:18 -08004
5#include "gtest/gtest.h"
6
7namespace aos {
8namespace testing {
9
10// Tests MaskOnes with small arguments.
11TEST(MaskOnesTest, Small) {
12 EXPECT_EQ(0u, MaskOnes<uint8_t>(0));
13 EXPECT_EQ(0u, MaskOnes<uint64_t>(0));
14 EXPECT_EQ(1u, MaskOnes<uint8_t>(1));
15 EXPECT_EQ(1u, MaskOnes<uint64_t>(1));
16}
17
18// Tests MaskOnes with large arguments.
19TEST(MaskOnesTest, Large) {
20 EXPECT_EQ(0xFFu, MaskOnes<uint8_t>(8));
21 EXPECT_EQ(0x7Fu, MaskOnes<uint8_t>(7));
22
23 EXPECT_EQ(0xFFu, MaskOnes<uint64_t>(8));
24 EXPECT_EQ(UINT64_C(0xFFFFFFFFFFFFFFFF), MaskOnes<uint64_t>(64));
25 EXPECT_EQ(UINT64_C(0x7FFFFFFFFFFFFFFF), MaskOnes<uint64_t>(63));
26}
27
28// Tests some simple non-edge-case use cases for PackBits.
29TEST(PackBitsTest, Basic) {
30 {
31 std::array<char, 3> buffer{};
32 PackBits<uint8_t, 8, 0>(0, buffer);
33 EXPECT_EQ((std::array<char, 3>{}), buffer);
34 PackBits<uint8_t, 8, 0>(9, buffer);
35 EXPECT_EQ((std::array<char, 3>{{9, 0, 0}}), buffer);
36 PackBits<uint8_t, 8, 8>(7, buffer);
37 EXPECT_EQ((std::array<char, 3>{{9, 7, 0}}), buffer);
38 PackBits<uint8_t, 8, 16>(1, buffer);
39 EXPECT_EQ((std::array<char, 3>{{9, 7, 1}}), buffer);
40 }
41 {
42 std::array<char, 3> buffer{};
43 PackBits<uint16_t, 16, 0>(0xdead, buffer);
44 EXPECT_EQ((std::array<char, 3>{
45 {static_cast<char>(0xad), static_cast<char>(0xde), 0}}),
46 buffer);
47 }
48 {
49 std::array<char, 3> buffer{};
50 PackBits<uint8_t, 4, 0>(0xd7, buffer);
51 EXPECT_EQ((std::array<char, 3>{{0x7, 0, 0}}), buffer);
52 }
53 {
54 std::array<char, 3> buffer{};
55 PackBits<uint8_t, 4, 4>(0xd7, buffer);
56 EXPECT_EQ((std::array<char, 3>{{0x70, 0, 0}}), buffer);
57 }
58}
59
60// Verifies that PackBits puts bits in an order consistent with increasing
61// offsets.
62TEST(PackBitsTest, Consistency) {
63 {
64 std::array<char, 3> buffer1{};
65 PackBits<uint8_t, 8, 0>(0x80, buffer1);
66 std::array<char, 3> buffer2{};
67 PackBits<uint8_t, 1, 7>(0x1, buffer2);
68 EXPECT_EQ(buffer1, buffer2);
69 }
70 {
71 std::array<char, 1> buffer1{{static_cast<char>(0xFF)}};
72 PackBits<uint8_t, 8, 0>(0x7F, buffer1);
73 std::array<char, 1> buffer2{{static_cast<char>(0xFF)}};
74 PackBits<uint8_t, 1, 7>(0x0, buffer2);
75 EXPECT_EQ(buffer1, buffer2);
76 }
77 {
78 std::array<char, 1> buffer1{};
79 PackBits<uint8_t, 3, 5>(0x7, buffer1);
80 std::array<char, 1> buffer2{};
81 PackBits<uint8_t, 5, 3>(0x3C, buffer2);
82 EXPECT_EQ(buffer1, buffer2);
83 }
84 {
85 std::array<char, 1> buffer1{{static_cast<char>(0xFF)}};
86 PackBits<uint8_t, 3, 5>(0x0, buffer1);
87 std::array<char, 1> buffer2{{static_cast<char>(0xFF)}};
88 PackBits<uint8_t, 5, 3>(0x03, buffer2);
89 EXPECT_EQ(buffer1, buffer2);
90 }
91}
92
93// Tests some simple non-edge-case use cases for UnpackBits.
94TEST(UnpackBitsTest, Basic) {
95 {
96 std::array<char, 3> buffer{};
97 EXPECT_EQ(0u, (UnpackBits<uint8_t, 8, 0>(buffer)));
98 buffer = {{9, 0, 0}};
99 EXPECT_EQ(9u, (UnpackBits<uint8_t, 8, 0>(buffer)));
100 buffer = {{9, 7, 0}};
101 EXPECT_EQ(9u, (UnpackBits<uint8_t, 8, 0>(buffer)));
102 EXPECT_EQ(7u, (UnpackBits<uint8_t, 8, 8>(buffer)));
103 buffer = {{9, 7, 1}};
104 EXPECT_EQ(9u, (UnpackBits<uint8_t, 8, 0>(buffer)));
105 EXPECT_EQ(7u, (UnpackBits<uint8_t, 8, 8>(buffer)));
106 EXPECT_EQ(1u, (UnpackBits<uint8_t, 8, 16>(buffer)));
107 }
108 {
109 const std::array<char, 3> buffer = {
110 {static_cast<char>(0xad), static_cast<char>(0xde), 0}};
111 EXPECT_EQ(0xdead, (UnpackBits<uint16_t, 16, 0>(buffer)));
112 }
113 {
114 const std::array<char, 3> buffer = {{static_cast<char>(0xF7), 0, 0}};
115 EXPECT_EQ(7u, (UnpackBits<uint8_t, 4, 0>(buffer)));
116 }
117 {
118 const std::array<char, 3> buffer = {{static_cast<char>(0x7F), 0, 0}};
119 EXPECT_EQ(7u, (UnpackBits<uint8_t, 4, 4>(buffer)));
120 }
121}
122
123// Tests PackBits split across multiple bytes.
124TEST(PackBitsTest, AcrossBytes) {
125 {
126 std::array<char, 2> buffer{};
127 PackBits<uint8_t, 8, 7>(0xFF, buffer);
128 EXPECT_EQ((std::array<char, 2>{
129 {static_cast<char>(0x80), static_cast<char>(0x7F)}}),
130 buffer);
131 }
132 {
133 std::array<char, 2> buffer{};
134 PackBits<uint8_t, 8, 6>(0xFF, buffer);
135 EXPECT_EQ((std::array<char, 2>{
136 {static_cast<char>(0xC0), static_cast<char>(0x3F)}}),
137 buffer);
138 }
139 {
140 std::array<char, 2> buffer{};
141 PackBits<uint8_t, 8, 5>(0xFF, buffer);
142 EXPECT_EQ((std::array<char, 2>{
143 {static_cast<char>(0xE0), static_cast<char>(0x1F)}}),
144 buffer);
145 }
146 {
147 std::array<char, 2> buffer{};
148 PackBits<uint8_t, 8, 4>(0xFF, buffer);
149 EXPECT_EQ((std::array<char, 2>{
150 {static_cast<char>(0xF0), static_cast<char>(0x0F)}}),
151 buffer);
152 }
153 {
154 std::array<char, 2> buffer{};
155 PackBits<uint8_t, 8, 3>(0xFF, buffer);
156 EXPECT_EQ((std::array<char, 2>{
157 {static_cast<char>(0xF8), static_cast<char>(0x07)}}),
158 buffer);
159 }
160 {
161 std::array<char, 2> buffer{};
162 PackBits<uint8_t, 8, 2>(0xFF, buffer);
163 EXPECT_EQ((std::array<char, 2>{
164 {static_cast<char>(0xFC), static_cast<char>(0x03)}}),
165 buffer);
166 }
167 {
168 std::array<char, 2> buffer{};
169 PackBits<uint8_t, 8, 1>(0xFF, buffer);
170 EXPECT_EQ((std::array<char, 2>{
171 {static_cast<char>(0xFE), static_cast<char>(0x01)}}),
172 buffer);
173 }
174}
175
176// Tests UnpackBits split across multiple bytes.
177TEST(UnpackBitsTest, AcrossBytes) {
178 {
179 const std::array<char, 2> buffer = {
180 {static_cast<char>(0x80), static_cast<char>(0x7F)}};
181 EXPECT_EQ(0xFFu, (UnpackBits<uint8_t, 8, 7>(buffer)));
182 }
183 {
184 const std::array<char, 2> buffer = {
185 {static_cast<char>(0xC0), static_cast<char>(0x3F)}};
186 EXPECT_EQ(0xFFu, (UnpackBits<uint8_t, 8, 6>(buffer)));
187 }
188 {
189 const std::array<char, 2> buffer = {
190 {static_cast<char>(0xE0), static_cast<char>(0x1F)}};
191 EXPECT_EQ(0xFFu, (UnpackBits<uint8_t, 8, 5>(buffer)));
192 }
193 {
194 const std::array<char, 2> buffer = {
195 {static_cast<char>(0xF0), static_cast<char>(0x0F)}};
196 EXPECT_EQ(0xFFu, (UnpackBits<uint8_t, 8, 4>(buffer)));
197 }
198 {
199 const std::array<char, 2> buffer = {
200 {static_cast<char>(0xF8), static_cast<char>(0x07)}};
201 EXPECT_EQ(0xFFu, (UnpackBits<uint8_t, 8, 3>(buffer)));
202 }
203 {
204 const std::array<char, 2> buffer = {
205 {static_cast<char>(0xFC), static_cast<char>(0x03)}};
206 EXPECT_EQ(0xFFu, (UnpackBits<uint8_t, 8, 2>(buffer)));
207 }
208 {
209 const std::array<char, 2> buffer = {
210 {static_cast<char>(0xFE), static_cast<char>(0x01)}};
211 EXPECT_EQ(0xFFu, (UnpackBits<uint8_t, 8, 1>(buffer)));
212 }
213}
214
215// Verifies that PackBits avoids touching adjacent bits.
216TEST(PackBitsTest, AdjacentBits) {
217 {
218 std::array<char, 2> buffer{
219 {static_cast<char>(0xFF), static_cast<char>(0xFF)}};
220 PackBits<uint8_t, 1, 0>(0, buffer);
221 EXPECT_EQ((std::array<char, 2>{
222 {static_cast<char>(0xFE), static_cast<char>(0xFF)}}),
223 buffer);
224 }
225 {
226 std::array<char, 2> buffer{
227 {static_cast<char>(0xFF), static_cast<char>(0xFF)}};
228 PackBits<uint8_t, 7, 0>(0, buffer);
229 EXPECT_EQ((std::array<char, 2>{
230 {static_cast<char>(0x80), static_cast<char>(0xFF)}}),
231 buffer);
232 }
233 {
234 std::array<char, 2> buffer{
235 {static_cast<char>(0xFF), static_cast<char>(0xFF)}};
236 PackBits<uint8_t, 8, 0>(0, buffer);
237 EXPECT_EQ((std::array<char, 2>{
238 {static_cast<char>(0x00), static_cast<char>(0xFF)}}),
239 buffer);
240 }
241 {
242 std::array<char, 2> buffer{
243 {static_cast<char>(0xFF), static_cast<char>(0xFF)}};
244 PackBits<uint16_t, 9, 0>(0, buffer);
245 EXPECT_EQ((std::array<char, 2>{
246 {static_cast<char>(0x00), static_cast<char>(0xFE)}}),
247 buffer);
248 }
249 {
250 std::array<char, 2> buffer{
251 {static_cast<char>(0xFF), static_cast<char>(0xFF)}};
252 PackBits<uint16_t, 14, 0>(0, buffer);
253 EXPECT_EQ((std::array<char, 2>{
254 {static_cast<char>(0x00), static_cast<char>(0xC0)}}),
255 buffer);
256 }
257 {
258 std::array<char, 2> buffer{
259 {static_cast<char>(0xFF), static_cast<char>(0xFF)}};
260 PackBits<uint16_t, 15, 0>(0, buffer);
261 EXPECT_EQ((std::array<char, 2>{
262 {static_cast<char>(0x00), static_cast<char>(0x80)}}),
263 buffer);
264 }
265 {
266 std::array<char, 2> buffer{
267 {static_cast<char>(0xFF), static_cast<char>(0xFF)}};
268 PackBits<uint16_t, 15, 1>(0, buffer);
269 EXPECT_EQ((std::array<char, 2>{
270 {static_cast<char>(0x01), static_cast<char>(0x00)}}),
271 buffer);
272 }
273 {
274 std::array<char, 2> buffer{
275 {static_cast<char>(0xFF), static_cast<char>(0xFF)}};
276 PackBits<uint16_t, 6, 8>(0, buffer);
277 EXPECT_EQ((std::array<char, 2>{
278 {static_cast<char>(0xFF), static_cast<char>(0xC0)}}),
279 buffer);
280 }
281 {
282 std::array<char, 4> buffer{
283 {static_cast<char>(0xFF), static_cast<char>(0xFF),
284 static_cast<char>(0xFF), static_cast<char>(0xFF)}};
285 PackBits<uint16_t, 6, 24>(0, buffer);
286 EXPECT_EQ((std::array<char, 4>{
287 {static_cast<char>(0xFF), static_cast<char>(0xFF),
288 static_cast<char>(0xFF), static_cast<char>(0xC0)}}),
289 buffer);
290 }
291}
292
293// Tests FloatToIntLinear with values near or outside of its boundaries.
294TEST(FloatToIntLinearTest, OutOfBounds) {
295 EXPECT_EQ(0u, (FloatToIntLinear<1>(0.0f, 1.0f, 0.0f)));
296 EXPECT_EQ(0u, (FloatToIntLinear<1>(0.0f, 1.0f, -0.1f)));
297 EXPECT_EQ(0u, (FloatToIntLinear<1>(0.0f, 1.0f, -1.0f)));
298 EXPECT_EQ(1u, (FloatToIntLinear<1>(0.0f, 1.0f, 1.0f)));
299 EXPECT_EQ(1u, (FloatToIntLinear<1>(0.0f, 1.0f, 1.1f)));
300 EXPECT_EQ(1u, (FloatToIntLinear<1>(0.0f, 1.0f, 2.0f)));
301
302 EXPECT_EQ(0u, (FloatToIntLinear<1>(0.0f, 4.0f, 0.0f)));
303 EXPECT_EQ(1u, (FloatToIntLinear<1>(0.0f, 4.0f, 4.0f)));
304 EXPECT_EQ(1u, (FloatToIntLinear<1>(0.0f, 4.0f, 10.0f)));
305
306 EXPECT_EQ(0u, (FloatToIntLinear<3>(0.0f, 4.0f, 0.0f)));
307 EXPECT_EQ(0u, (FloatToIntLinear<3>(0.0f, 4.0f, -100.0f)));
308 EXPECT_EQ(7u, (FloatToIntLinear<3>(0.0f, 4.0f, 4.0f)));
309 EXPECT_EQ(7u, (FloatToIntLinear<3>(0.0f, 4.0f, 4.01f)));
310
311 EXPECT_EQ(0u, (FloatToIntLinear<3>(-3.0f, 5.0f, -3.0f)));
312 EXPECT_EQ(0u, (FloatToIntLinear<3>(-3.0f, 5.0f, -3.1f)));
313 EXPECT_EQ(7u, (FloatToIntLinear<3>(-3.0f, 5.0f, 5.0f)));
314 EXPECT_EQ(7u, (FloatToIntLinear<3>(-3.0f, 5.0f, 5.1f)));
315}
316
317// Tests that FloatToIntLinear rounds correctly at the boundaries between output
318// values.
319TEST(FloatToIntLinearTest, Rounding) {
320 EXPECT_EQ(0u, (FloatToIntLinear<1>(0.0f, 1.0f, 0.49f)));
321 EXPECT_EQ(1u, (FloatToIntLinear<1>(0.0f, 1.0f, 0.51f)));
322 EXPECT_EQ(1u, (FloatToIntLinear<1>(-1.0f, 0.0f, -0.49f)));
323 EXPECT_EQ(0u, (FloatToIntLinear<1>(-1.0f, 0.0f, -0.51f)));
324 EXPECT_EQ(1u, (FloatToIntLinear<1>(-1.0f, 1.0f, 0.01f)));
325 EXPECT_EQ(0u, (FloatToIntLinear<1>(-1.0f, 1.0f, -0.01f)));
326
327 EXPECT_EQ(0u, (FloatToIntLinear<3>(0.0f, 1.0f, 0.124f)));
328 EXPECT_EQ(1u, (FloatToIntLinear<3>(0.0f, 1.0f, 0.126f)));
329 EXPECT_EQ(1u, (FloatToIntLinear<3>(0.0f, 1.0f, 0.249f)));
330 EXPECT_EQ(2u, (FloatToIntLinear<3>(0.0f, 1.0f, 0.251f)));
331 EXPECT_EQ(2u, (FloatToIntLinear<3>(0.0f, 1.0f, 0.374f)));
332 EXPECT_EQ(3u, (FloatToIntLinear<3>(0.0f, 1.0f, 0.376f)));
333 EXPECT_EQ(3u, (FloatToIntLinear<3>(0.0f, 1.0f, 0.499f)));
334 EXPECT_EQ(4u, (FloatToIntLinear<3>(0.0f, 1.0f, 0.501f)));
335 EXPECT_EQ(4u, (FloatToIntLinear<3>(0.0f, 1.0f, 0.624f)));
336 EXPECT_EQ(5u, (FloatToIntLinear<3>(0.0f, 1.0f, 0.626f)));
337 EXPECT_EQ(5u, (FloatToIntLinear<3>(0.0f, 1.0f, 0.749f)));
338 EXPECT_EQ(6u, (FloatToIntLinear<3>(0.0f, 1.0f, 0.751f)));
339 EXPECT_EQ(6u, (FloatToIntLinear<3>(0.0f, 1.0f, 0.874f)));
340 EXPECT_EQ(7u, (FloatToIntLinear<3>(0.0f, 1.0f, 0.876f)));
341}
342
343// Tests IntToFloatLinear with values near or outside of its boundaries.
344TEST(IntToFloatLinearTest, OutOfBounds) {
345 EXPECT_EQ(0.25f, (IntToFloatLinear<1>(0.0f, 1.0f, 0)));
346 EXPECT_EQ(0.75f, (IntToFloatLinear<1>(0.0f, 1.0f, 1)));
347 EXPECT_EQ(0.75f, (IntToFloatLinear<1>(0.0f, 1.0f, 2)));
348 EXPECT_EQ(0.75f, (IntToFloatLinear<1>(0.0f, 1.0f, 3)));
349
350 EXPECT_EQ(1.0f, (IntToFloatLinear<1>(0.0f, 4.0f, 0)));
351 EXPECT_EQ(3.0f, (IntToFloatLinear<1>(0.0f, 4.0f, 1)));
352
353 EXPECT_EQ(0.0625f, (IntToFloatLinear<3>(0.0f, 1.0f, 0)));
354 EXPECT_EQ(0.9375f, (IntToFloatLinear<3>(0.0f, 1.0f, 7)));
355 EXPECT_EQ(0.9375f, (IntToFloatLinear<3>(0.0f, 1.0f, 8)));
356}
357
358// Tests IntToFloatLinear with some specific values which are easy to calculate
359// by hand.
360TEST(IntToFloatLinearTest, Values) {
361 EXPECT_EQ(0.125f, (IntToFloatLinear<2>(0.0f, 1.0f, 0)));
362 EXPECT_EQ(0.375f, (IntToFloatLinear<2>(0.0f, 1.0f, 1)));
363 EXPECT_EQ(0.625f, (IntToFloatLinear<2>(0.0f, 1.0f, 2)));
364 EXPECT_EQ(0.875f, (IntToFloatLinear<2>(0.0f, 1.0f, 3)));
365
366 EXPECT_EQ(0.0625f, (IntToFloatLinear<3>(0.0f, 1.0f, 0)));
367 EXPECT_EQ(0.1875f, (IntToFloatLinear<3>(0.0f, 1.0f, 1)));
368 EXPECT_EQ(0.3125f, (IntToFloatLinear<3>(0.0f, 1.0f, 2)));
369 EXPECT_EQ(0.4375f, (IntToFloatLinear<3>(0.0f, 1.0f, 3)));
370 EXPECT_EQ(0.5625f, (IntToFloatLinear<3>(0.0f, 1.0f, 4)));
371 EXPECT_EQ(0.6875f, (IntToFloatLinear<3>(0.0f, 1.0f, 5)));
372 EXPECT_EQ(0.8125f, (IntToFloatLinear<3>(0.0f, 1.0f, 6)));
373 EXPECT_EQ(0.9375f, (IntToFloatLinear<3>(0.0f, 1.0f, 7)));
374
375 EXPECT_EQ(-0.875f, (IntToFloatLinear<2>(-1.0f, 0.0f, 0)));
376 EXPECT_EQ(-0.625f, (IntToFloatLinear<2>(-1.0f, 0.0f, 1)));
377 EXPECT_EQ(-0.375f, (IntToFloatLinear<2>(-1.0f, 0.0f, 2)));
378 EXPECT_EQ(-0.125f, (IntToFloatLinear<2>(-1.0f, 0.0f, 3)));
379
380 EXPECT_EQ(-0.75f, (IntToFloatLinear<2>(-1.0f, 1.0f, 0)));
381 EXPECT_EQ(-0.25f, (IntToFloatLinear<2>(-1.0f, 1.0f, 1)));
382 EXPECT_EQ(0.25f, (IntToFloatLinear<2>(-1.0f, 1.0f, 2)));
383 EXPECT_EQ(0.75f, (IntToFloatLinear<2>(-1.0f, 1.0f, 3)));
384}
385
386} // namespace testing
387} // namespace aos