hadamard_test.cc (18271B)
1 /* 2 * Copyright (c) 2019, Alliance for Open Media. All rights reserved. 3 * 4 * This source code is subject to the terms of the BSD 2 Clause License and 5 * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License 6 * was not distributed with this source code in the LICENSE file, you can 7 * obtain it at www.aomedia.org/license/software. If the Alliance for Open 8 * Media Patent License 1.0 was not distributed with this source code in the 9 * PATENTS file, you can obtain it at www.aomedia.org/license/patent. 10 */ 11 12 #include <algorithm> 13 #include <ostream> 14 15 #include "gtest/gtest.h" 16 17 #include "config/aom_dsp_rtcd.h" 18 19 #include "test/acm_random.h" 20 #include "test/register_state_check.h" 21 #include "test/util.h" 22 23 namespace { 24 25 using libaom_test::ACMRandom; 26 27 using HadamardFunc = void (*)(const int16_t *a, ptrdiff_t a_stride, 28 tran_low_t *b); 29 // Low precision version of Hadamard Transform 30 using HadamardLPFunc = void (*)(const int16_t *a, ptrdiff_t a_stride, 31 int16_t *b); 32 // Low precision version of Hadamard Transform 8x8 - Dual 33 using HadamardLP8x8DualFunc = void (*)(const int16_t *a, ptrdiff_t a_stride, 34 int16_t *b); 35 36 template <typename OutputType> 37 void Hadamard4x4(const OutputType *a, OutputType *out) { 38 OutputType b[8]; 39 for (int i = 0; i < 4; i += 2) { 40 b[i + 0] = (a[i * 4] + a[(i + 1) * 4]) >> 1; 41 b[i + 1] = (a[i * 4] - a[(i + 1) * 4]) >> 1; 42 } 43 44 out[0] = b[0] + b[2]; 45 out[1] = b[1] + b[3]; 46 out[2] = b[0] - b[2]; 47 out[3] = b[1] - b[3]; 48 } 49 50 template <typename OutputType> 51 void ReferenceHadamard4x4(const int16_t *a, int a_stride, OutputType *b) { 52 OutputType input[16]; 53 OutputType buf[16]; 54 for (int i = 0; i < 4; ++i) { 55 for (int j = 0; j < 4; ++j) { 56 input[i * 4 + j] = static_cast<OutputType>(a[i * a_stride + j]); 57 } 58 } 59 for (int i = 0; i < 4; ++i) Hadamard4x4(input + i, buf + i * 4); 60 for (int i = 0; i < 4; ++i) Hadamard4x4(buf + i, b + i * 4); 61 62 // Extra transpose to match C and SSE2 behavior(i.e., aom_hadamard_4x4). 63 for (int i = 0; i < 4; i++) { 64 for (int j = i + 1; j < 4; j++) { 65 OutputType temp = b[j * 4 + i]; 66 b[j * 4 + i] = b[i * 4 + j]; 67 b[i * 4 + j] = temp; 68 } 69 } 70 } 71 72 template <typename OutputType> 73 void HadamardLoop(const OutputType *a, OutputType *out) { 74 OutputType b[8]; 75 for (int i = 0; i < 8; i += 2) { 76 b[i + 0] = a[i * 8] + a[(i + 1) * 8]; 77 b[i + 1] = a[i * 8] - a[(i + 1) * 8]; 78 } 79 OutputType c[8]; 80 for (int i = 0; i < 8; i += 4) { 81 c[i + 0] = b[i + 0] + b[i + 2]; 82 c[i + 1] = b[i + 1] + b[i + 3]; 83 c[i + 2] = b[i + 0] - b[i + 2]; 84 c[i + 3] = b[i + 1] - b[i + 3]; 85 } 86 out[0] = c[0] + c[4]; 87 out[7] = c[1] + c[5]; 88 out[3] = c[2] + c[6]; 89 out[4] = c[3] + c[7]; 90 out[2] = c[0] - c[4]; 91 out[6] = c[1] - c[5]; 92 out[1] = c[2] - c[6]; 93 out[5] = c[3] - c[7]; 94 } 95 96 template <typename OutputType> 97 void ReferenceHadamard8x8(const int16_t *a, int a_stride, OutputType *b) { 98 OutputType input[64]; 99 OutputType buf[64]; 100 for (int i = 0; i < 8; ++i) { 101 for (int j = 0; j < 8; ++j) { 102 input[i * 8 + j] = static_cast<OutputType>(a[i * a_stride + j]); 103 } 104 } 105 for (int i = 0; i < 8; ++i) HadamardLoop(input + i, buf + i * 8); 106 for (int i = 0; i < 8; ++i) HadamardLoop(buf + i, b + i * 8); 107 108 // Extra transpose to match SSE2 behavior (i.e., aom_hadamard_8x8 and 109 // aom_hadamard_lp_8x8). 110 for (int i = 0; i < 8; i++) { 111 for (int j = i + 1; j < 8; j++) { 112 OutputType temp = b[j * 8 + i]; 113 b[j * 8 + i] = b[i * 8 + j]; 114 b[i * 8 + j] = temp; 115 } 116 } 117 } 118 119 template <typename OutputType> 120 void ReferenceHadamard8x8Dual(const int16_t *a, int a_stride, OutputType *b) { 121 /* The source is a 8x16 block. The destination is rearranged to 8x16. 122 * Input is 9 bit. */ 123 ReferenceHadamard8x8(a, a_stride, b); 124 ReferenceHadamard8x8(a + 8, a_stride, b + 64); 125 } 126 127 template <typename OutputType> 128 void ReferenceHadamard16x16(const int16_t *a, int a_stride, OutputType *b, 129 bool shift) { 130 /* The source is a 16x16 block. The destination is rearranged to 8x32. 131 * Input is 9 bit. */ 132 ReferenceHadamard8x8(a + 0 + 0 * a_stride, a_stride, b + 0); 133 ReferenceHadamard8x8(a + 8 + 0 * a_stride, a_stride, b + 64); 134 ReferenceHadamard8x8(a + 0 + 8 * a_stride, a_stride, b + 128); 135 ReferenceHadamard8x8(a + 8 + 8 * a_stride, a_stride, b + 192); 136 137 /* Overlay the 8x8 blocks and combine. */ 138 for (int i = 0; i < 64; ++i) { 139 /* 8x8 steps the range up to 15 bits. */ 140 const OutputType a0 = b[0]; 141 const OutputType a1 = b[64]; 142 const OutputType a2 = b[128]; 143 const OutputType a3 = b[192]; 144 145 /* Prevent the result from escaping int16_t. */ 146 const OutputType b0 = (a0 + a1) >> 1; 147 const OutputType b1 = (a0 - a1) >> 1; 148 const OutputType b2 = (a2 + a3) >> 1; 149 const OutputType b3 = (a2 - a3) >> 1; 150 151 /* Store a 16 bit value. */ 152 b[0] = b0 + b2; 153 b[64] = b1 + b3; 154 b[128] = b0 - b2; 155 b[192] = b1 - b3; 156 157 ++b; 158 } 159 160 if (shift) { 161 b -= 64; 162 // Extra shift to match aom_hadamard_16x16_c and aom_hadamard_16x16_avx2. 163 for (int i = 0; i < 16; i++) { 164 for (int j = 0; j < 4; j++) { 165 OutputType temp = b[i * 16 + 4 + j]; 166 b[i * 16 + 4 + j] = b[i * 16 + 8 + j]; 167 b[i * 16 + 8 + j] = temp; 168 } 169 } 170 } 171 } 172 173 template <typename OutputType> 174 void ReferenceHadamard32x32(const int16_t *a, int a_stride, OutputType *b, 175 bool shift) { 176 ReferenceHadamard16x16(a + 0 + 0 * a_stride, a_stride, b + 0, shift); 177 ReferenceHadamard16x16(a + 16 + 0 * a_stride, a_stride, b + 256, shift); 178 ReferenceHadamard16x16(a + 0 + 16 * a_stride, a_stride, b + 512, shift); 179 ReferenceHadamard16x16(a + 16 + 16 * a_stride, a_stride, b + 768, shift); 180 181 for (int i = 0; i < 256; ++i) { 182 const OutputType a0 = b[0]; 183 const OutputType a1 = b[256]; 184 const OutputType a2 = b[512]; 185 const OutputType a3 = b[768]; 186 187 const OutputType b0 = (a0 + a1) >> 2; 188 const OutputType b1 = (a0 - a1) >> 2; 189 const OutputType b2 = (a2 + a3) >> 2; 190 const OutputType b3 = (a2 - a3) >> 2; 191 192 b[0] = b0 + b2; 193 b[256] = b1 + b3; 194 b[512] = b0 - b2; 195 b[768] = b1 - b3; 196 197 ++b; 198 } 199 } 200 201 template <typename OutputType> 202 void ReferenceHadamard(const int16_t *a, int a_stride, OutputType *b, int bw, 203 int bh, bool shift) { 204 if (bw == 32 && bh == 32) { 205 ReferenceHadamard32x32(a, a_stride, b, shift); 206 } else if (bw == 16 && bh == 16) { 207 ReferenceHadamard16x16(a, a_stride, b, shift); 208 } else if (bw == 8 && bh == 8) { 209 ReferenceHadamard8x8(a, a_stride, b); 210 } else if (bw == 4 && bh == 4) { 211 ReferenceHadamard4x4(a, a_stride, b); 212 } else if (bw == 8 && bh == 16) { 213 ReferenceHadamard8x8Dual(a, a_stride, b); 214 } else { 215 GTEST_FAIL() << "Invalid Hadamard transform size " << bw << bh << std::endl; 216 } 217 } 218 219 template <typename HadamardFuncType> 220 struct FuncWithSize { 221 FuncWithSize(HadamardFuncType f, int bw, int bh) 222 : func(f), block_width(bw), block_height(bh) {} 223 HadamardFuncType func; 224 int block_width; 225 int block_height; 226 }; 227 228 using HadamardFuncWithSize = FuncWithSize<HadamardFunc>; 229 using HadamardLPFuncWithSize = FuncWithSize<HadamardLPFunc>; 230 using HadamardLP8x8DualFuncWithSize = FuncWithSize<HadamardLP8x8DualFunc>; 231 232 template <typename OutputType, typename HadamardFuncType> 233 class HadamardTestBase 234 : public ::testing::TestWithParam<FuncWithSize<HadamardFuncType>> { 235 public: 236 HadamardTestBase(const FuncWithSize<HadamardFuncType> &func_param, 237 bool do_shift) { 238 h_func_ = func_param.func; 239 bw_ = func_param.block_width; 240 bh_ = func_param.block_height; 241 shift_ = do_shift; 242 } 243 244 void SetUp() override { rnd_.Reset(ACMRandom::DeterministicSeed()); } 245 246 // The Rand() function generates values in the range [-((1 << BitDepth) - 1), 247 // (1 << BitDepth) - 1]. This is because the input to the Hadamard transform 248 // is the residual pixel, which is defined as 'source pixel - predicted 249 // pixel'. Source pixel and predicted pixel take values in the range 250 // [0, (1 << BitDepth) - 1] and thus the residual pixel ranges from 251 // -((1 << BitDepth) - 1) to ((1 << BitDepth) - 1). 252 virtual int16_t Rand() = 0; 253 254 void CompareReferenceRandom() { 255 const int kMaxBlockSize = 32 * 32; 256 const int block_size = bw_ * bh_; 257 258 DECLARE_ALIGNED(16, int16_t, a[kMaxBlockSize]); 259 DECLARE_ALIGNED(16, OutputType, b[kMaxBlockSize]); 260 memset(a, 0, sizeof(a)); 261 memset(b, 0, sizeof(b)); 262 263 OutputType b_ref[kMaxBlockSize]; 264 memset(b_ref, 0, sizeof(b_ref)); 265 266 for (int i = 0; i < block_size; ++i) a[i] = Rand(); 267 ReferenceHadamard(a, bw_, b_ref, bw_, bh_, shift_); 268 API_REGISTER_STATE_CHECK(h_func_(a, bw_, b)); 269 270 // The order of the output is not important. Sort before checking. 271 std::sort(b, b + block_size); 272 std::sort(b_ref, b_ref + block_size); 273 EXPECT_EQ(memcmp(b, b_ref, sizeof(b)), 0); 274 } 275 276 void CompareReferenceExtreme() { 277 const int kMaxBlockSize = 32 * 32; 278 const int block_size = bw_ * bh_; 279 const int kBitDepth = 8; 280 DECLARE_ALIGNED(16, int16_t, a[kMaxBlockSize]); 281 DECLARE_ALIGNED(16, OutputType, b[kMaxBlockSize]); 282 memset(b, 0, sizeof(b)); 283 284 OutputType b_ref[kMaxBlockSize]; 285 memset(b_ref, 0, sizeof(b_ref)); 286 for (int i = 0; i < 2; ++i) { 287 const int sign = (i == 0) ? 1 : -1; 288 for (int j = 0; j < block_size; ++j) a[j] = sign * ((1 << kBitDepth) - 1); 289 290 ReferenceHadamard(a, bw_, b_ref, bw_, bh_, shift_); 291 API_REGISTER_STATE_CHECK(h_func_(a, bw_, b)); 292 293 // The order of the output is not important. Sort before checking. 294 std::sort(b, b + block_size); 295 std::sort(b_ref, b_ref + block_size); 296 EXPECT_EQ(memcmp(b, b_ref, sizeof(b)), 0); 297 } 298 } 299 300 void VaryStride() { 301 const int kMaxBlockSize = 32 * 32; 302 const int block_size = bw_ * bh_; 303 304 DECLARE_ALIGNED(16, int16_t, a[kMaxBlockSize * 8]); 305 DECLARE_ALIGNED(16, OutputType, b[kMaxBlockSize]); 306 memset(a, 0, sizeof(a)); 307 for (int i = 0; i < block_size * 8; ++i) a[i] = Rand(); 308 309 OutputType b_ref[kMaxBlockSize]; 310 for (int i = 8; i < 64; i += 8) { 311 memset(b, 0, sizeof(b)); 312 memset(b_ref, 0, sizeof(b_ref)); 313 314 ReferenceHadamard(a, i, b_ref, bw_, bh_, shift_); 315 API_REGISTER_STATE_CHECK(h_func_(a, i, b)); 316 317 // The order of the output is not important. Sort before checking. 318 std::sort(b, b + block_size); 319 std::sort(b_ref, b_ref + block_size); 320 EXPECT_EQ(0, memcmp(b, b_ref, sizeof(b))); 321 } 322 } 323 324 void SpeedTest(int times) { 325 const int kMaxBlockSize = 32 * 32; 326 DECLARE_ALIGNED(16, int16_t, input[kMaxBlockSize]); 327 DECLARE_ALIGNED(16, OutputType, output[kMaxBlockSize]); 328 memset(input, 1, sizeof(input)); 329 memset(output, 0, sizeof(output)); 330 331 aom_usec_timer timer; 332 aom_usec_timer_start(&timer); 333 for (int i = 0; i < times; ++i) { 334 h_func_(input, bw_, output); 335 } 336 aom_usec_timer_mark(&timer); 337 338 const int elapsed_time = static_cast<int>(aom_usec_timer_elapsed(&timer)); 339 printf("Hadamard%dx%d[%12d runs]: %d us\n", bw_, bh_, times, elapsed_time); 340 } 341 342 protected: 343 ACMRandom rnd_; 344 345 private: 346 HadamardFuncType h_func_; 347 int bw_; 348 int bh_; 349 bool shift_; 350 }; 351 352 class HadamardLowbdTest : public HadamardTestBase<tran_low_t, HadamardFunc> { 353 public: 354 HadamardLowbdTest() : HadamardTestBase(GetParam(), /*do_shift=*/true) {} 355 // Use values between -255 (0xFF01) and 255 (0x00FF) 356 int16_t Rand() override { 357 int16_t src = rnd_.Rand8(); 358 int16_t pred = rnd_.Rand8(); 359 return src - pred; 360 } 361 }; 362 363 TEST_P(HadamardLowbdTest, CompareReferenceRandom) { CompareReferenceRandom(); } 364 365 TEST_P(HadamardLowbdTest, CompareReferenceExtreme) { 366 CompareReferenceExtreme(); 367 } 368 369 TEST_P(HadamardLowbdTest, VaryStride) { VaryStride(); } 370 371 TEST_P(HadamardLowbdTest, DISABLED_SpeedTest) { SpeedTest(1000000); } 372 373 INSTANTIATE_TEST_SUITE_P( 374 C, HadamardLowbdTest, 375 ::testing::Values(HadamardFuncWithSize(&aom_hadamard_4x4_c, 4, 4), 376 HadamardFuncWithSize(&aom_hadamard_8x8_c, 8, 8), 377 HadamardFuncWithSize(&aom_hadamard_16x16_c, 16, 16), 378 HadamardFuncWithSize(&aom_hadamard_32x32_c, 32, 32))); 379 380 #if HAVE_SSE2 381 INSTANTIATE_TEST_SUITE_P( 382 SSE2, HadamardLowbdTest, 383 ::testing::Values(HadamardFuncWithSize(&aom_hadamard_4x4_sse2, 4, 4), 384 HadamardFuncWithSize(&aom_hadamard_8x8_sse2, 8, 8), 385 HadamardFuncWithSize(&aom_hadamard_16x16_sse2, 16, 16), 386 HadamardFuncWithSize(&aom_hadamard_32x32_sse2, 32, 32))); 387 #endif // HAVE_SSE2 388 389 #if HAVE_AVX2 390 INSTANTIATE_TEST_SUITE_P( 391 AVX2, HadamardLowbdTest, 392 ::testing::Values(HadamardFuncWithSize(&aom_hadamard_16x16_avx2, 16, 16), 393 HadamardFuncWithSize(&aom_hadamard_32x32_avx2, 32, 32))); 394 #endif // HAVE_AVX2 395 396 // TODO(aomedia:3314): Disable NEON unit test for now, since hadamard 16x16 NEON 397 // need modifications to match C/AVX2 behavior. 398 #if HAVE_NEON 399 INSTANTIATE_TEST_SUITE_P( 400 NEON, HadamardLowbdTest, 401 ::testing::Values(HadamardFuncWithSize(&aom_hadamard_4x4_neon, 4, 4), 402 HadamardFuncWithSize(&aom_hadamard_8x8_neon, 8, 8), 403 HadamardFuncWithSize(&aom_hadamard_16x16_neon, 16, 16), 404 HadamardFuncWithSize(&aom_hadamard_32x32_neon, 32, 32))); 405 #endif // HAVE_NEON 406 407 #if CONFIG_AV1_HIGHBITDEPTH 408 class HadamardHighbdTest : public HadamardTestBase<tran_low_t, HadamardFunc> { 409 protected: 410 HadamardHighbdTest() : HadamardTestBase(GetParam(), /*do_shift=*/true) {} 411 // Use values between -4095 (0xF001) and 4095 (0x0FFF) 412 int16_t Rand() override { 413 int16_t src = rnd_.Rand12(); 414 int16_t pred = rnd_.Rand12(); 415 return src - pred; 416 } 417 }; 418 419 TEST_P(HadamardHighbdTest, CompareReferenceRandom) { CompareReferenceRandom(); } 420 421 TEST_P(HadamardHighbdTest, VaryStride) { VaryStride(); } 422 423 TEST_P(HadamardHighbdTest, DISABLED_Speed) { 424 SpeedTest(10); 425 SpeedTest(10000); 426 SpeedTest(10000000); 427 } 428 429 INSTANTIATE_TEST_SUITE_P( 430 C, HadamardHighbdTest, 431 ::testing::Values( 432 HadamardFuncWithSize(&aom_highbd_hadamard_8x8_c, 8, 8), 433 HadamardFuncWithSize(&aom_highbd_hadamard_16x16_c, 16, 16), 434 HadamardFuncWithSize(&aom_highbd_hadamard_32x32_c, 32, 32))); 435 436 #if HAVE_AVX2 437 INSTANTIATE_TEST_SUITE_P( 438 AVX2, HadamardHighbdTest, 439 ::testing::Values( 440 HadamardFuncWithSize(&aom_highbd_hadamard_8x8_avx2, 8, 8), 441 HadamardFuncWithSize(&aom_highbd_hadamard_16x16_avx2, 16, 16), 442 HadamardFuncWithSize(&aom_highbd_hadamard_32x32_avx2, 32, 32))); 443 #endif // HAVE_AVX2 444 445 #if HAVE_NEON 446 INSTANTIATE_TEST_SUITE_P( 447 NEON, HadamardHighbdTest, 448 ::testing::Values( 449 HadamardFuncWithSize(&aom_highbd_hadamard_8x8_neon, 8, 8), 450 HadamardFuncWithSize(&aom_highbd_hadamard_16x16_neon, 16, 16), 451 HadamardFuncWithSize(&aom_highbd_hadamard_32x32_neon, 32, 32))); 452 #endif // HAVE_NEON 453 454 #endif // CONFIG_AV1_HIGHBITDEPTH 455 456 // Tests for low precision 457 class HadamardLowbdLPTest : public HadamardTestBase<int16_t, HadamardLPFunc> { 458 public: 459 HadamardLowbdLPTest() : HadamardTestBase(GetParam(), /*do_shift=*/false) {} 460 // Use values between -255 (0xFF01) and 255 (0x00FF) 461 int16_t Rand() override { 462 int16_t src = rnd_.Rand8(); 463 int16_t pred = rnd_.Rand8(); 464 return src - pred; 465 } 466 }; 467 468 TEST_P(HadamardLowbdLPTest, CompareReferenceRandom) { 469 CompareReferenceRandom(); 470 } 471 472 TEST_P(HadamardLowbdLPTest, VaryStride) { VaryStride(); } 473 474 TEST_P(HadamardLowbdLPTest, DISABLED_SpeedTest) { SpeedTest(1000000); } 475 476 INSTANTIATE_TEST_SUITE_P( 477 C, HadamardLowbdLPTest, 478 ::testing::Values(HadamardLPFuncWithSize(&aom_hadamard_lp_8x8_c, 8, 8), 479 HadamardLPFuncWithSize(&aom_hadamard_lp_16x16_c, 16, 480 16))); 481 482 #if HAVE_SSE2 483 INSTANTIATE_TEST_SUITE_P( 484 SSE2, HadamardLowbdLPTest, 485 ::testing::Values(HadamardLPFuncWithSize(&aom_hadamard_lp_8x8_sse2, 8, 8), 486 HadamardLPFuncWithSize(&aom_hadamard_lp_16x16_sse2, 16, 487 16))); 488 #endif // HAVE_SSE2 489 490 #if HAVE_AVX2 491 INSTANTIATE_TEST_SUITE_P(AVX2, HadamardLowbdLPTest, 492 ::testing::Values(HadamardLPFuncWithSize( 493 &aom_hadamard_lp_16x16_avx2, 16, 16))); 494 #endif // HAVE_AVX2 495 496 #if HAVE_NEON 497 INSTANTIATE_TEST_SUITE_P( 498 NEON, HadamardLowbdLPTest, 499 ::testing::Values(HadamardLPFuncWithSize(&aom_hadamard_lp_8x8_neon, 8, 8), 500 HadamardLPFuncWithSize(&aom_hadamard_lp_16x16_neon, 16, 501 16))); 502 #endif // HAVE_NEON 503 504 // Tests for 8x8 dual low precision 505 class HadamardLowbdLP8x8DualTest 506 : public HadamardTestBase<int16_t, HadamardLP8x8DualFunc> { 507 public: 508 HadamardLowbdLP8x8DualTest() 509 : HadamardTestBase(GetParam(), /*do_shift=*/false) {} 510 // Use values between -255 (0xFF01) and 255 (0x00FF) 511 int16_t Rand() override { 512 int16_t src = rnd_.Rand8(); 513 int16_t pred = rnd_.Rand8(); 514 return src - pred; 515 } 516 }; 517 518 TEST_P(HadamardLowbdLP8x8DualTest, CompareReferenceRandom) { 519 CompareReferenceRandom(); 520 } 521 522 TEST_P(HadamardLowbdLP8x8DualTest, VaryStride) { VaryStride(); } 523 524 TEST_P(HadamardLowbdLP8x8DualTest, DISABLED_SpeedTest) { SpeedTest(1000000); } 525 526 INSTANTIATE_TEST_SUITE_P(C, HadamardLowbdLP8x8DualTest, 527 ::testing::Values(HadamardLP8x8DualFuncWithSize( 528 &aom_hadamard_lp_8x8_dual_c, 8, 16))); 529 530 #if HAVE_SSE2 531 INSTANTIATE_TEST_SUITE_P(SSE2, HadamardLowbdLP8x8DualTest, 532 ::testing::Values(HadamardLP8x8DualFuncWithSize( 533 &aom_hadamard_lp_8x8_dual_sse2, 8, 16))); 534 #endif // HAVE_SSE2 535 536 #if HAVE_AVX2 537 INSTANTIATE_TEST_SUITE_P(AVX2, HadamardLowbdLP8x8DualTest, 538 ::testing::Values(HadamardLP8x8DualFuncWithSize( 539 &aom_hadamard_lp_8x8_dual_avx2, 8, 16))); 540 #endif // HAVE_AVX2 541 542 #if HAVE_NEON 543 INSTANTIATE_TEST_SUITE_P(NEON, HadamardLowbdLP8x8DualTest, 544 ::testing::Values(HadamardLP8x8DualFuncWithSize( 545 &aom_hadamard_lp_8x8_dual_neon, 8, 16))); 546 #endif // HAVE_NEON 547 548 } // namespace