minmax_test.cc (7767B)
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 using MinMaxFunc = void (*)(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: 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 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 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 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 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 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 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 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 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 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 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