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 <stdlib.h>
12 #include <string.h>
13
14 #include "gtest/gtest.h"
15
16 #include "vpx_config.h"
17 #include "./vpx_dsp_rtcd.h"
18 #include "vpx/vpx_integer.h"
19 #include "vpx_mem/vpx_mem.h"
20
21 #include "test/acm_random.h"
22 #include "test/register_state_check.h"
23
24 namespace {
25
26 using ::libvpx_test::ACMRandom;
27
28 typedef void (*MinMaxFunc)(const uint8_t *a, int a_stride, const uint8_t *b,
29 int b_stride, int *min, int *max);
30
31 class MinMaxTest : public ::testing::TestWithParam<MinMaxFunc> {
32 public:
SetUp()33 void SetUp() override {
34 mm_func_ = GetParam();
35 rnd_.Reset(ACMRandom::DeterministicSeed());
36 }
37
38 protected:
39 MinMaxFunc mm_func_;
40 ACMRandom rnd_;
41 };
42
reference_minmax(const uint8_t * a,int a_stride,const uint8_t * b,int b_stride,int * min_ret,int * max_ret)43 void reference_minmax(const uint8_t *a, int a_stride, const uint8_t *b,
44 int b_stride, int *min_ret, int *max_ret) {
45 int min = 255;
46 int max = 0;
47 for (int i = 0; i < 8; i++) {
48 for (int j = 0; j < 8; j++) {
49 const int diff = abs(a[i * a_stride + j] - b[i * b_stride + j]);
50 if (min > diff) min = diff;
51 if (max < diff) max = diff;
52 }
53 }
54
55 *min_ret = min;
56 *max_ret = max;
57 }
58
TEST_P(MinMaxTest,MinValue)59 TEST_P(MinMaxTest, MinValue) {
60 for (int i = 0; i < 64; i++) {
61 uint8_t a[64], b[64];
62 memset(a, 0, sizeof(a));
63 memset(b, 255, sizeof(b));
64 b[i] = i; // Set a minimum difference of i.
65
66 int min, max;
67 ASM_REGISTER_STATE_CHECK(mm_func_(a, 8, b, 8, &min, &max));
68 EXPECT_EQ(255, max);
69 EXPECT_EQ(i, min);
70 }
71 }
72
TEST_P(MinMaxTest,MaxValue)73 TEST_P(MinMaxTest, MaxValue) {
74 for (int i = 0; i < 64; i++) {
75 uint8_t a[64], b[64];
76 memset(a, 0, sizeof(a));
77 memset(b, 0, sizeof(b));
78 b[i] = i; // Set a maximum difference of i.
79
80 int min, max;
81 ASM_REGISTER_STATE_CHECK(mm_func_(a, 8, b, 8, &min, &max));
82 EXPECT_EQ(i, max);
83 EXPECT_EQ(0, min);
84 }
85 }
86
TEST_P(MinMaxTest,CompareReference)87 TEST_P(MinMaxTest, CompareReference) {
88 uint8_t a[64], b[64];
89 for (int j = 0; j < 64; j++) {
90 a[j] = rnd_.Rand8();
91 b[j] = rnd_.Rand8();
92 }
93
94 int min_ref, max_ref, min, max;
95 reference_minmax(a, 8, b, 8, &min_ref, &max_ref);
96 ASM_REGISTER_STATE_CHECK(mm_func_(a, 8, b, 8, &min, &max));
97 EXPECT_EQ(max_ref, max);
98 EXPECT_EQ(min_ref, min);
99 }
100
TEST_P(MinMaxTest,CompareReferenceAndVaryStride)101 TEST_P(MinMaxTest, CompareReferenceAndVaryStride) {
102 uint8_t a[8 * 64], b[8 * 64];
103 for (int i = 0; i < 8 * 64; i++) {
104 a[i] = rnd_.Rand8();
105 b[i] = rnd_.Rand8();
106 }
107 for (int a_stride = 8; a_stride <= 64; a_stride += 8) {
108 for (int b_stride = 8; b_stride <= 64; b_stride += 8) {
109 int min_ref, max_ref, min, max;
110 reference_minmax(a, a_stride, b, b_stride, &min_ref, &max_ref);
111 ASM_REGISTER_STATE_CHECK(mm_func_(a, a_stride, b, b_stride, &min, &max));
112 EXPECT_EQ(max_ref, max)
113 << "when a_stride = " << a_stride << " and b_stride = " << b_stride;
114 EXPECT_EQ(min_ref, min)
115 << "when a_stride = " << a_stride << " and b_stride = " << b_stride;
116 }
117 }
118 }
119
120 #if CONFIG_VP9_HIGHBITDEPTH
121
122 using HBDMinMaxTest = MinMaxTest;
123
highbd_reference_minmax(const uint8_t * a,int a_stride,const uint8_t * b,int b_stride,int * min_ret,int * max_ret)124 void highbd_reference_minmax(const uint8_t *a, int a_stride, const uint8_t *b,
125 int b_stride, int *min_ret, int *max_ret) {
126 int min = 65535;
127 int max = 0;
128 const uint16_t *a_ptr = CONVERT_TO_SHORTPTR(a);
129 const uint16_t *b_ptr = CONVERT_TO_SHORTPTR(b);
130 for (int i = 0; i < 8; i++) {
131 for (int j = 0; j < 8; j++) {
132 const int diff = abs(a_ptr[i * a_stride + j] - b_ptr[i * b_stride + j]);
133 if (min > diff) min = diff;
134 if (max < diff) max = diff;
135 }
136 }
137
138 *min_ret = min;
139 *max_ret = max;
140 }
141
TEST_P(HBDMinMaxTest,MinValue)142 TEST_P(HBDMinMaxTest, MinValue) {
143 uint8_t *a = CONVERT_TO_BYTEPTR(
144 reinterpret_cast<uint16_t *>(vpx_malloc(64 * sizeof(uint16_t))));
145 uint8_t *b = CONVERT_TO_BYTEPTR(
146 reinterpret_cast<uint16_t *>(vpx_malloc(64 * sizeof(uint16_t))));
147 for (int i = 0; i < 64; i++) {
148 vpx_memset16(CONVERT_TO_SHORTPTR(a), 0, 64);
149 vpx_memset16(CONVERT_TO_SHORTPTR(b), 65535, 64);
150 CONVERT_TO_SHORTPTR(b)[i] = i; // Set a minimum difference of i.
151
152 int min, max;
153 ASM_REGISTER_STATE_CHECK(mm_func_(a, 8, b, 8, &min, &max));
154 EXPECT_EQ(65535, max);
155 EXPECT_EQ(i, min);
156 }
157 vpx_free(CONVERT_TO_SHORTPTR(a));
158 vpx_free(CONVERT_TO_SHORTPTR(b));
159 }
160
TEST_P(HBDMinMaxTest,MaxValue)161 TEST_P(HBDMinMaxTest, MaxValue) {
162 uint8_t *a = CONVERT_TO_BYTEPTR(
163 reinterpret_cast<uint16_t *>(vpx_malloc(64 * sizeof(uint16_t))));
164 uint8_t *b = CONVERT_TO_BYTEPTR(
165 reinterpret_cast<uint16_t *>(vpx_malloc(64 * sizeof(uint16_t))));
166 for (int i = 0; i < 64; i++) {
167 vpx_memset16(CONVERT_TO_SHORTPTR(a), 0, 64);
168 vpx_memset16(CONVERT_TO_SHORTPTR(b), 0, 64);
169 CONVERT_TO_SHORTPTR(b)[i] = i; // Set a minimum difference of i.
170
171 int min, max;
172 ASM_REGISTER_STATE_CHECK(mm_func_(a, 8, b, 8, &min, &max));
173 EXPECT_EQ(i, max);
174 EXPECT_EQ(0, min);
175 }
176 vpx_free(CONVERT_TO_SHORTPTR(a));
177 vpx_free(CONVERT_TO_SHORTPTR(b));
178 }
179
TEST_P(HBDMinMaxTest,CompareReference)180 TEST_P(HBDMinMaxTest, CompareReference) {
181 uint8_t *a = CONVERT_TO_BYTEPTR(
182 reinterpret_cast<uint16_t *>(vpx_malloc(64 * sizeof(uint16_t))));
183 uint8_t *b = CONVERT_TO_BYTEPTR(
184 reinterpret_cast<uint16_t *>(vpx_malloc(64 * sizeof(uint16_t))));
185 for (int j = 0; j < 64; j++) {
186 CONVERT_TO_SHORTPTR(a)[j] = rnd_.Rand16();
187 CONVERT_TO_SHORTPTR(b)[j] = rnd_.Rand16();
188 }
189
190 int min_ref, max_ref, min, max;
191 highbd_reference_minmax(a, 8, b, 8, &min_ref, &max_ref);
192 ASM_REGISTER_STATE_CHECK(mm_func_(a, 8, b, 8, &min, &max));
193 vpx_free(CONVERT_TO_SHORTPTR(a));
194 vpx_free(CONVERT_TO_SHORTPTR(b));
195 EXPECT_EQ(max_ref, max);
196 EXPECT_EQ(min_ref, min);
197 }
198
TEST_P(HBDMinMaxTest,CompareReferenceAndVaryStride)199 TEST_P(HBDMinMaxTest, CompareReferenceAndVaryStride) {
200 uint8_t *a = CONVERT_TO_BYTEPTR(
201 reinterpret_cast<uint16_t *>(vpx_malloc((8 * 64) * sizeof(uint16_t))));
202 uint8_t *b = CONVERT_TO_BYTEPTR(
203 reinterpret_cast<uint16_t *>(vpx_malloc((8 * 64) * sizeof(uint16_t))));
204 for (int i = 0; i < 8 * 64; i++) {
205 CONVERT_TO_SHORTPTR(a)[i] = rnd_.Rand16();
206 CONVERT_TO_SHORTPTR(b)[i] = rnd_.Rand16();
207 }
208 for (int a_stride = 8; a_stride <= 64; a_stride += 8) {
209 for (int b_stride = 8; b_stride <= 64; b_stride += 8) {
210 int min_ref, max_ref, min, max;
211 highbd_reference_minmax(a, a_stride, b, b_stride, &min_ref, &max_ref);
212 ASM_REGISTER_STATE_CHECK(mm_func_(a, a_stride, b, b_stride, &min, &max));
213 EXPECT_EQ(max_ref, max)
214 << "when a_stride = " << a_stride << " and b_stride = " << b_stride;
215 EXPECT_EQ(min_ref, min)
216 << "when a_stride = " << a_stride << " and b_stride = " << b_stride;
217 }
218 }
219 vpx_free(CONVERT_TO_SHORTPTR(a));
220 vpx_free(CONVERT_TO_SHORTPTR(b));
221 }
222 #endif
223
224 INSTANTIATE_TEST_SUITE_P(C, MinMaxTest, ::testing::Values(&vpx_minmax_8x8_c));
225 #if CONFIG_VP9_HIGHBITDEPTH
226 INSTANTIATE_TEST_SUITE_P(C, HBDMinMaxTest,
227 ::testing::Values(&vpx_highbd_minmax_8x8_c));
228 #endif
229
230 #if HAVE_SSE2
231 INSTANTIATE_TEST_SUITE_P(SSE2, MinMaxTest,
232 ::testing::Values(&vpx_minmax_8x8_sse2));
233 #endif
234
235 #if HAVE_NEON
236 INSTANTIATE_TEST_SUITE_P(NEON, MinMaxTest,
237 ::testing::Values(&vpx_minmax_8x8_neon));
238 #if CONFIG_VP9_HIGHBITDEPTH
239 INSTANTIATE_TEST_SUITE_P(NEON, HBDMinMaxTest,
240 ::testing::Values(&vpx_highbd_minmax_8x8_neon));
241 #endif
242 #endif
243
244 #if HAVE_MSA
245 INSTANTIATE_TEST_SUITE_P(MSA, MinMaxTest,
246 ::testing::Values(&vpx_minmax_8x8_msa));
247 #endif
248
249 } // namespace
250