xref: /aosp_15_r20/external/libaom/test/minmax_test.cc (revision 77c1e3ccc04c968bd2bc212e87364f250e820521)
1 /*
2  * Copyright (c) 2023 The WebM project authors. All rights reserved.
3  * Copyright (c) 2023, Alliance for Open Media. All rights reserved.
4  *
5  *  This source code is subject to the terms of the BSD 2 Clause License and
6  *  the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
7  *  was not distributed with this source code in the LICENSE file, you can
8  *  obtain it at www.aomedia.org/license/software. If the Alliance for Open
9  *  Media Patent License 1.0 was not distributed with this source code in the
10  *  PATENTS file, you can obtain it at www.aomedia.org/license/patent.
11  */
12 
13 #include <stdlib.h>
14 #include <string.h>
15 
16 #include "gtest/gtest.h"
17 
18 #include "config/aom_config.h"
19 #include "config/aom_dsp_rtcd.h"
20 #include "aom_ports/mem.h"
21 #include "test/acm_random.h"
22 #include "test/register_state_check.h"
23 #include "test/util.h"
24 
25 namespace {
26 
27 using ::libaom_test::ACMRandom;
28 
29 typedef void (*MinMaxFunc)(const uint8_t *a, int a_stride, const uint8_t *b,
30                            int b_stride, int *min, int *max);
31 
32 class MinMaxTest : public ::testing::TestWithParam<MinMaxFunc> {
33  public:
SetUp()34   void SetUp() override {
35     mm_func_ = GetParam();
36     rnd_.Reset(ACMRandom::DeterministicSeed());
37   }
38 
39  protected:
40   MinMaxFunc mm_func_;
41   ACMRandom rnd_;
42 };
43 
reference_minmax(const uint8_t * a,int a_stride,const uint8_t * b,int b_stride,int * min_ret,int * max_ret)44 void reference_minmax(const uint8_t *a, int a_stride, const uint8_t *b,
45                       int b_stride, int *min_ret, int *max_ret) {
46   int min = 255;
47   int max = 0;
48   for (int i = 0; i < 8; i++) {
49     for (int j = 0; j < 8; j++) {
50       const int diff = abs(a[i * a_stride + j] - b[i * b_stride + j]);
51       if (min > diff) min = diff;
52       if (max < diff) max = diff;
53     }
54   }
55 
56   *min_ret = min;
57   *max_ret = max;
58 }
59 
TEST_P(MinMaxTest,MinValue)60 TEST_P(MinMaxTest, MinValue) {
61   for (int i = 0; i < 64; i++) {
62     uint8_t a[64], b[64];
63     memset(a, 0, sizeof(a));
64     memset(b, 255, sizeof(b));
65     b[i] = i;  // Set a minimum difference of i.
66 
67     int min, max;
68     API_REGISTER_STATE_CHECK(mm_func_(a, 8, b, 8, &min, &max));
69     EXPECT_EQ(255, max);
70     EXPECT_EQ(i, min);
71   }
72 }
73 
TEST_P(MinMaxTest,MaxValue)74 TEST_P(MinMaxTest, MaxValue) {
75   for (int i = 0; i < 64; i++) {
76     uint8_t a[64], b[64];
77     memset(a, 0, sizeof(a));
78     memset(b, 0, sizeof(b));
79     b[i] = i;  // Set a maximum difference of i.
80 
81     int min, max;
82     API_REGISTER_STATE_CHECK(mm_func_(a, 8, b, 8, &min, &max));
83     EXPECT_EQ(i, max);
84     EXPECT_EQ(0, min);
85   }
86 }
87 
TEST_P(MinMaxTest,CompareReference)88 TEST_P(MinMaxTest, CompareReference) {
89   uint8_t a[64], b[64];
90   for (int j = 0; j < 64; j++) {
91     a[j] = rnd_.Rand8();
92     b[j] = rnd_.Rand8();
93   }
94 
95   int min_ref, max_ref, min, max;
96   reference_minmax(a, 8, b, 8, &min_ref, &max_ref);
97   API_REGISTER_STATE_CHECK(mm_func_(a, 8, b, 8, &min, &max));
98   EXPECT_EQ(max_ref, max);
99   EXPECT_EQ(min_ref, min);
100 }
101 
TEST_P(MinMaxTest,CompareReferenceAndVaryStride)102 TEST_P(MinMaxTest, CompareReferenceAndVaryStride) {
103   uint8_t a[8 * 64], b[8 * 64];
104   for (int i = 0; i < 8 * 64; i++) {
105     a[i] = rnd_.Rand8();
106     b[i] = rnd_.Rand8();
107   }
108   for (int a_stride = 8; a_stride <= 64; a_stride += 8) {
109     for (int b_stride = 8; b_stride <= 64; b_stride += 8) {
110       int min_ref, max_ref, min, max;
111       reference_minmax(a, a_stride, b, b_stride, &min_ref, &max_ref);
112       API_REGISTER_STATE_CHECK(mm_func_(a, a_stride, b, b_stride, &min, &max));
113       EXPECT_EQ(max_ref, max)
114           << "when a_stride = " << a_stride << " and b_stride = " << b_stride;
115       EXPECT_EQ(min_ref, min)
116           << "when a_stride = " << a_stride << " and b_stride = " << b_stride;
117     }
118   }
119 }
120 
121 #if CONFIG_AV1_HIGHBITDEPTH
122 
123 using HBDMinMaxTest = MinMaxTest;
124 
highbd_reference_minmax(const uint8_t * a,int a_stride,const uint8_t * b,int b_stride,int * min_ret,int * max_ret)125 void highbd_reference_minmax(const uint8_t *a, int a_stride, const uint8_t *b,
126                              int b_stride, int *min_ret, int *max_ret) {
127   int min = 65535;
128   int max = 0;
129   const uint16_t *a_ptr = CONVERT_TO_SHORTPTR(a);
130   const uint16_t *b_ptr = CONVERT_TO_SHORTPTR(b);
131   for (int i = 0; i < 8; i++) {
132     for (int j = 0; j < 8; j++) {
133       const int diff = abs(a_ptr[i * a_stride + j] - b_ptr[i * b_stride + j]);
134       if (min > diff) min = diff;
135       if (max < diff) max = diff;
136     }
137   }
138 
139   *min_ret = min;
140   *max_ret = max;
141 }
142 
TEST_P(HBDMinMaxTest,MinValue)143 TEST_P(HBDMinMaxTest, MinValue) {
144   uint8_t *a = CONVERT_TO_BYTEPTR(
145       reinterpret_cast<uint16_t *>(aom_malloc(64 * sizeof(uint16_t))));
146   uint8_t *b = CONVERT_TO_BYTEPTR(
147       reinterpret_cast<uint16_t *>(aom_malloc(64 * sizeof(uint16_t))));
148   for (int i = 0; i < 64; i++) {
149     aom_memset16(CONVERT_TO_SHORTPTR(a), 0, 64);
150     aom_memset16(CONVERT_TO_SHORTPTR(b), 65535, 64);
151     CONVERT_TO_SHORTPTR(b)[i] = i;  // Set a minimum difference of i.
152 
153     int min, max;
154     API_REGISTER_STATE_CHECK(mm_func_(a, 8, b, 8, &min, &max));
155     EXPECT_EQ(65535, max);
156     EXPECT_EQ(i, min);
157   }
158   aom_free(CONVERT_TO_SHORTPTR(a));
159   aom_free(CONVERT_TO_SHORTPTR(b));
160 }
161 
TEST_P(HBDMinMaxTest,MaxValue)162 TEST_P(HBDMinMaxTest, MaxValue) {
163   uint8_t *a = CONVERT_TO_BYTEPTR(
164       reinterpret_cast<uint16_t *>(aom_malloc(64 * sizeof(uint16_t))));
165   uint8_t *b = CONVERT_TO_BYTEPTR(
166       reinterpret_cast<uint16_t *>(aom_malloc(64 * sizeof(uint16_t))));
167   for (int i = 0; i < 64; i++) {
168     aom_memset16(CONVERT_TO_SHORTPTR(a), 0, 64);
169     aom_memset16(CONVERT_TO_SHORTPTR(b), 0, 64);
170     CONVERT_TO_SHORTPTR(b)[i] = i;  // Set a minimum difference of i.
171 
172     int min, max;
173     API_REGISTER_STATE_CHECK(mm_func_(a, 8, b, 8, &min, &max));
174     EXPECT_EQ(i, max);
175     EXPECT_EQ(0, min);
176   }
177   aom_free(CONVERT_TO_SHORTPTR(a));
178   aom_free(CONVERT_TO_SHORTPTR(b));
179 }
180 
TEST_P(HBDMinMaxTest,CompareReference)181 TEST_P(HBDMinMaxTest, CompareReference) {
182   uint8_t *a = CONVERT_TO_BYTEPTR(
183       reinterpret_cast<uint16_t *>(aom_malloc(64 * sizeof(uint16_t))));
184   uint8_t *b = CONVERT_TO_BYTEPTR(
185       reinterpret_cast<uint16_t *>(aom_malloc(64 * sizeof(uint16_t))));
186   for (int j = 0; j < 64; j++) {
187     CONVERT_TO_SHORTPTR(a)[j] = rnd_.Rand16();
188     CONVERT_TO_SHORTPTR(b)[j] = rnd_.Rand16();
189   }
190 
191   int min_ref, max_ref, min, max;
192   highbd_reference_minmax(a, 8, b, 8, &min_ref, &max_ref);
193   API_REGISTER_STATE_CHECK(mm_func_(a, 8, b, 8, &min, &max));
194   aom_free(CONVERT_TO_SHORTPTR(a));
195   aom_free(CONVERT_TO_SHORTPTR(b));
196   EXPECT_EQ(max_ref, max);
197   EXPECT_EQ(min_ref, min);
198 }
199 
TEST_P(HBDMinMaxTest,CompareReferenceAndVaryStride)200 TEST_P(HBDMinMaxTest, CompareReferenceAndVaryStride) {
201   uint8_t *a = CONVERT_TO_BYTEPTR(
202       reinterpret_cast<uint16_t *>(aom_malloc((8 * 64) * sizeof(uint16_t))));
203   uint8_t *b = CONVERT_TO_BYTEPTR(
204       reinterpret_cast<uint16_t *>(aom_malloc((8 * 64) * sizeof(uint16_t))));
205   for (int i = 0; i < 8 * 64; i++) {
206     CONVERT_TO_SHORTPTR(a)[i] = rnd_.Rand16();
207     CONVERT_TO_SHORTPTR(b)[i] = rnd_.Rand16();
208   }
209   for (int a_stride = 8; a_stride <= 64; a_stride += 8) {
210     for (int b_stride = 8; b_stride <= 64; b_stride += 8) {
211       int min_ref, max_ref, min, max;
212       highbd_reference_minmax(a, a_stride, b, b_stride, &min_ref, &max_ref);
213       API_REGISTER_STATE_CHECK(mm_func_(a, a_stride, b, b_stride, &min, &max));
214       EXPECT_EQ(max_ref, max)
215           << "when a_stride = " << a_stride << " and b_stride = " << b_stride;
216       EXPECT_EQ(min_ref, min)
217           << "when a_stride = " << a_stride << " and b_stride = " << b_stride;
218     }
219   }
220   aom_free(CONVERT_TO_SHORTPTR(a));
221   aom_free(CONVERT_TO_SHORTPTR(b));
222 }
223 #endif  // CONFIG_AV1_HIGHBITDEPTH
224 
225 INSTANTIATE_TEST_SUITE_P(C, MinMaxTest, ::testing::Values(&aom_minmax_8x8_c));
226 #if CONFIG_AV1_HIGHBITDEPTH
227 INSTANTIATE_TEST_SUITE_P(C, HBDMinMaxTest,
228                          ::testing::Values(&aom_highbd_minmax_8x8_c));
229 #if HAVE_NEON
230 INSTANTIATE_TEST_SUITE_P(NEON, HBDMinMaxTest,
231                          ::testing::Values(&aom_highbd_minmax_8x8_neon));
232 #endif
233 #endif
234 
235 #if HAVE_SSE2
236 INSTANTIATE_TEST_SUITE_P(SSE2, MinMaxTest,
237                          ::testing::Values(&aom_minmax_8x8_sse2));
238 #endif
239 
240 #if HAVE_NEON
241 INSTANTIATE_TEST_SUITE_P(NEON, MinMaxTest,
242                          ::testing::Values(&aom_minmax_8x8_neon));
243 #endif
244 }  // namespace
245