@@ -117,12 +117,12 @@ const uint8_t* GetNextAlignedByte(const uint8_t* ptr, std::size_t alignment) {
117
117
return ptr + bytes_to_add;
118
118
}
119
119
120
- struct UnpackingData {
120
+ struct TestUnpackSize {
121
121
int32_t num_values;
122
122
int32_t bit_width;
123
123
};
124
124
125
- class UnpackingRandomRoundTrip : public ::testing::TestWithParam<UnpackingData > {
125
+ class TestUnpack : public ::testing::TestWithParam<TestUnpackSize > {
126
126
protected:
127
127
template <typename Int>
128
128
void TestRoundtripAlignment (UnpackFunc<Int> unpack, std::size_t alignment_offset) {
@@ -132,61 +132,119 @@ class UnpackingRandomRoundTrip : public ::testing::TestWithParam<UnpackingData>
132
132
// So we allocate more values than necessary and skip to the next byte with the
133
133
// desired (non) alignment to test the proper condition.
134
134
constexpr int32_t kExtraValues = sizeof (Int) * 8 ;
135
- auto const packed = GenerateRandomPackedValues (num_values + kExtraValues , bit_width);
135
+ const auto packed = GenerateRandomPackedValues (num_values + kExtraValues , bit_width);
136
136
const uint8_t * packed_unaligned =
137
137
GetNextAlignedByte (packed.data (), sizeof (Int)) + alignment_offset;
138
138
139
139
CheckUnpackPackRoundtrip (packed_unaligned, num_values, bit_width, unpack);
140
140
}
141
141
142
142
template <typename Int>
143
- void TestRoundtrip (UnpackFunc<Int> unpack) {
144
- // Aligned test
145
- TestRoundtripAlignment (unpack, 0 );
146
- // Unaligned test
147
- TestRoundtripAlignment (unpack, 1 );
143
+ void TestUnpackZeros (UnpackFunc<Int> unpack) {
144
+ auto [num_values, bit_width] = GetParam ();
145
+ const auto num_bytes = GetNumBytes (num_values, bit_width);
146
+
147
+ const std::vector<uint8_t > packed (static_cast <std::size_t >(num_bytes), uint8_t {0 });
148
+ const auto unpacked = UnpackValues (packed.data (), num_values, bit_width, unpack);
149
+
150
+ const std::vector<Int> expected (static_cast <std::size_t >(num_values), Int{0 });
151
+ EXPECT_EQ (unpacked, expected);
152
+ }
153
+
154
+ template <typename Int>
155
+ void TestUnpackOnes (UnpackFunc<Int> unpack) {
156
+ auto [num_values, bit_width] = GetParam ();
157
+ const auto num_bytes = GetNumBytes (num_values, bit_width);
158
+
159
+ const std::vector<uint8_t > packed (static_cast <std::size_t >(num_bytes), uint8_t {0xFF });
160
+ const auto unpacked = UnpackValues (packed.data (), num_values, bit_width, unpack);
161
+
162
+ // Generate bit_width ones
163
+ Int expected_value = 0 ;
164
+ for (int i = 0 ; i < bit_width; ++i) {
165
+ expected_value = (expected_value << 1 ) | 1 ;
166
+ }
167
+ const std::vector<Int> expected (static_cast <std::size_t >(num_values), expected_value);
168
+ EXPECT_EQ (unpacked, expected);
169
+ }
170
+
171
+ template <typename Int>
172
+ void TestUnpackAlternating (UnpackFunc<Int> unpack) {
173
+ const auto [num_values, bit_width] = GetParam ();
174
+ const auto num_bytes = GetNumBytes (num_values, bit_width);
175
+
176
+ const std::vector<uint8_t > packed (static_cast <std::size_t >(num_bytes), uint8_t {0xAA });
177
+ const auto unpacked = UnpackValues (packed.data (), num_values, bit_width, unpack);
178
+
179
+ // Generate alternative bit sequence sratring with either 0 or 1
180
+ Int one_zero_value = 0 ;
181
+ Int zero_one_value = 0 ;
182
+ for (int i = 0 ; i < bit_width; ++i) {
183
+ zero_one_value = (zero_one_value << 1 ) | (i % 2 );
184
+ one_zero_value = (one_zero_value << 1 ) | ((i + 1 ) % 2 );
185
+ }
186
+
187
+ std::vector<Int> expected;
188
+ if (bit_width % 2 == 0 ) {
189
+ // For even bit_width, the same pattern repeats every time
190
+ expected.resize (static_cast <std::size_t >(num_values), one_zero_value);
191
+ } else {
192
+ // For odd bit_width, we alternate a pattern leading with 0 and 1
193
+ for (int i = 0 ; i < num_values; ++i) {
194
+ expected.push_back (i % 2 == 0 ? zero_one_value : one_zero_value);
195
+ }
196
+ }
197
+ EXPECT_EQ (unpacked, expected);
198
+ }
199
+
200
+ template <typename Int>
201
+ void TestAll (UnpackFunc<Int> unpack) {
202
+ // Known values
203
+ TestUnpackZeros (unpack);
204
+ TestUnpackOnes (unpack);
205
+ TestUnpackAlternating (unpack);
206
+
207
+ // Roundtrips
208
+ TestRoundtripAlignment (unpack, /* alignment_offset= */ 0 );
209
+ TestRoundtripAlignment (unpack, /* alignment_offset= */ 1 );
148
210
}
149
211
};
150
212
151
213
INSTANTIATE_TEST_SUITE_P (
152
- MutpliesOf64Values, UnpackingRandomRoundTrip,
153
- ::testing::Values (UnpackingData{64 , 1 }, UnpackingData{128 , 1 }, UnpackingData{2048 , 1 },
154
- UnpackingData{64 , 31 }, UnpackingData{128 , 31 },
155
- UnpackingData{2048 , 31 }, UnpackingData{64000 , 7 },
156
- UnpackingData{64000 , 8 }, UnpackingData{64000 , 13 },
157
- UnpackingData{64000 , 16 }, UnpackingData{64000 , 31 },
158
- UnpackingData{64000 , 32 }));
159
-
160
- TEST_P (UnpackingRandomRoundTrip, unpack32Default) {
161
- this ->TestRoundtrip (&unpack32_default);
162
- }
163
- TEST_P (UnpackingRandomRoundTrip, unpack64Default) {
164
- this ->TestRoundtrip (&unpack64_default);
165
- }
214
+ MutpliesOf64Values, TestUnpack,
215
+ ::testing::Values (TestUnpackSize{64 , 1 }, TestUnpackSize{128 , 1 },
216
+ TestUnpackSize{2048 , 1 }, TestUnpackSize{64 , 31 },
217
+ TestUnpackSize{128 , 31 }, TestUnpackSize{2048 , 31 },
218
+ TestUnpackSize{64000 , 7 }, TestUnpackSize{64000 , 8 },
219
+ TestUnpackSize{64000 , 13 }, TestUnpackSize{64000 , 16 },
220
+ TestUnpackSize{64000 , 31 }, TestUnpackSize{64000 , 32 }));
221
+
222
+ TEST_P (TestUnpack, unpack32Default) { this ->TestAll (&unpack32_default); }
223
+ TEST_P (TestUnpack, unpack64Default) { this ->TestAll (&unpack64_default); }
166
224
167
225
#if defined(ARROW_HAVE_RUNTIME_AVX2)
168
- TEST_P (UnpackingRandomRoundTrip , unpack32Avx2) {
226
+ TEST_P (TestUnpack , unpack32Avx2) {
169
227
if (!CpuInfo::GetInstance ()->IsSupported (CpuInfo::AVX2)) {
170
228
GTEST_SKIP () << " Test requires AVX2" ;
171
229
}
172
- this ->testRoundtrip (&unpack32_avx2);
230
+ this ->TestAll (&unpack32_avx2);
173
231
}
174
232
#endif
175
233
176
234
#if defined(ARROW_HAVE_RUNTIME_AVX512)
177
- TEST_P (UnpackingRandomRoundTrip , unpack32Avx512) {
235
+ TEST_P (TestUnpack , unpack32Avx512) {
178
236
if (!CpuInfo::GetInstance ()->IsSupported (CpuInfo::AVX512)) {
179
237
GTEST_SKIP () << " Test requires AVX512" ;
180
238
}
181
- this ->testRoundtrip (&unpack32_avx512);
239
+ this ->TestAll (&unpack32_avx512);
182
240
}
183
241
#endif
184
242
185
243
#if defined(ARROW_HAVE_NEON)
186
- TEST_P (UnpackingRandomRoundTrip , unpack32Neon) { this ->TestRoundtrip (&unpack32_neon); }
244
+ TEST_P (TestUnpack , unpack32Neon) { this ->TestAll (&unpack32_neon); }
187
245
#endif
188
246
189
- TEST_P (UnpackingRandomRoundTrip , unpack32) { this ->TestRoundtrip (&unpack32); }
190
- TEST_P (UnpackingRandomRoundTrip , unpack64) { this ->TestRoundtrip (&unpack64); }
247
+ TEST_P (TestUnpack , unpack32) { this ->TestAll (&unpack32); }
248
+ TEST_P (TestUnpack , unpack64) { this ->TestAll (&unpack64); }
191
249
192
250
} // namespace arrow::internal
0 commit comments