1 /* 2 * Copyright (c) 2016 The WebM project authors. All Rights Reserved. 3 * 4 * Use of this source code is governed by a BSD-style license 5 * that can be found in the LICENSE file in the root of the source 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 11 #include <cmath> 12 #include <cstdlib> 13 #include <string> 14 15 #include "third_party/googletest/src/include/gtest/gtest.h" 16 17 #include "./vpx_config.h" 18 #include "./vpx_dsp_rtcd.h" 19 #include "test/acm_random.h" 20 #include "test/clear_system_state.h" 21 #include "test/register_state_check.h" 22 #include "test/util.h" 23 #include "vpx_ports/mem.h" 24 25 using libvpx_test::ACMRandom; 26 27 namespace { 28 const int kNumIterations = 10000; 29 30 typedef uint64_t (*SSI16Func)(const int16_t *src, int stride, int size); 31 typedef std::tr1::tuple<SSI16Func, SSI16Func> SumSquaresParam; 32 33 class SumSquaresTest : public ::testing::TestWithParam<SumSquaresParam> { 34 public: 35 virtual ~SumSquaresTest() {} 36 virtual void SetUp() { 37 ref_func_ = GET_PARAM(0); 38 tst_func_ = GET_PARAM(1); 39 } 40 41 virtual void TearDown() { libvpx_test::ClearSystemState(); } 42 43 protected: 44 SSI16Func ref_func_; 45 SSI16Func tst_func_; 46 }; 47 48 TEST_P(SumSquaresTest, OperationCheck) { 49 ACMRandom rnd(ACMRandom::DeterministicSeed()); 50 DECLARE_ALIGNED(16, int16_t, src[256 * 256]); 51 const int msb = 11; // Up to 12 bit input 52 const int limit = 1 << (msb + 1); 53 54 for (int k = 0; k < kNumIterations; k++) { 55 const int size = 4 << rnd(6); // Up to 128x128 56 int stride = 4 << rnd(7); // Up to 256 stride 57 while (stride < size) { // Make sure it's valid 58 stride = 4 << rnd(7); 59 } 60 61 for (int i = 0; i < size; ++i) { 62 for (int j = 0; j < size; ++j) { 63 src[i * stride + j] = rnd(2) ? rnd(limit) : -rnd(limit); 64 } 65 } 66 67 const uint64_t res_ref = ref_func_(src, stride, size); 68 uint64_t res_tst; 69 ASM_REGISTER_STATE_CHECK(res_tst = tst_func_(src, stride, size)); 70 71 ASSERT_EQ(res_ref, res_tst) << "Error: Sum Squares Test" 72 << " C output does not match optimized output."; 73 } 74 } 75 76 TEST_P(SumSquaresTest, ExtremeValues) { 77 ACMRandom rnd(ACMRandom::DeterministicSeed()); 78 DECLARE_ALIGNED(16, int16_t, src[256 * 256]); 79 const int msb = 11; // Up to 12 bit input 80 const int limit = 1 << (msb + 1); 81 82 for (int k = 0; k < kNumIterations; k++) { 83 const int size = 4 << rnd(6); // Up to 128x128 84 int stride = 4 << rnd(7); // Up to 256 stride 85 while (stride < size) { // Make sure it's valid 86 stride = 4 << rnd(7); 87 } 88 89 const int val = rnd(2) ? limit - 1 : -(limit - 1); 90 for (int i = 0; i < size; ++i) { 91 for (int j = 0; j < size; ++j) { 92 src[i * stride + j] = val; 93 } 94 } 95 96 const uint64_t res_ref = ref_func_(src, stride, size); 97 uint64_t res_tst; 98 ASM_REGISTER_STATE_CHECK(res_tst = tst_func_(src, stride, size)); 99 100 ASSERT_EQ(res_ref, res_tst) << "Error: Sum Squares Test" 101 << " C output does not match optimized output."; 102 } 103 } 104 105 using std::tr1::make_tuple; 106 107 #if HAVE_SSE2 108 INSTANTIATE_TEST_CASE_P( 109 SSE2, SumSquaresTest, 110 ::testing::Values(make_tuple(&vpx_sum_squares_2d_i16_c, 111 &vpx_sum_squares_2d_i16_sse2))); 112 #endif // HAVE_SSE2 113 114 #if HAVE_MSA 115 INSTANTIATE_TEST_CASE_P(MSA, SumSquaresTest, ::testing::Values(make_tuple( 116 &vpx_sum_squares_2d_i16_c, 117 &vpx_sum_squares_2d_i16_msa))); 118 #endif // HAVE_MSA 119 } // namespace 120