xref: /aosp_15_r20/external/libgav1/src/dsp/intrapred_directional_test.cc (revision 095378508e87ed692bf8dfeb34008b65b3735891)
1 // Copyright 2021 The libgav1 Authors
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //      http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include "src/dsp/intrapred_directional.h"
16 
17 #include <cmath>
18 #include <cstddef>
19 #include <cstdint>
20 #include <cstring>
21 #include <memory>
22 #include <ostream>
23 
24 #include "absl/strings/match.h"
25 #include "absl/time/clock.h"
26 #include "absl/time/time.h"
27 #include "gtest/gtest.h"
28 #include "src/dsp/constants.h"
29 #include "src/dsp/dsp.h"
30 #include "src/utils/common.h"
31 #include "src/utils/compiler_attributes.h"
32 #include "src/utils/constants.h"
33 #include "src/utils/cpu.h"
34 #include "src/utils/memory.h"
35 #include "tests/block_utils.h"
36 #include "tests/third_party/libvpx/acm_random.h"
37 #include "tests/utils.h"
38 
39 namespace libgav1 {
40 namespace dsp {
41 namespace {
42 
43 constexpr int kMaxBlockSize = 64;
44 constexpr int kTotalPixels = kMaxBlockSize * kMaxBlockSize;
45 constexpr int kNumDirectionalIntraPredictors = 3;
46 
47 constexpr int kBaseAngles[] = {45, 67, 90, 113, 135, 157, 180, 203};
48 
49 const char* const kDirectionalPredNames[kNumDirectionalIntraPredictors] = {
50     "kDirectionalIntraPredictorZone1", "kDirectionalIntraPredictorZone2",
51     "kDirectionalIntraPredictorZone3"};
52 
GetDirectionalIntraPredictorDerivative(const int angle)53 int16_t GetDirectionalIntraPredictorDerivative(const int angle) {
54   EXPECT_GE(angle, 3);
55   EXPECT_LE(angle, 87);
56   return kDirectionalIntraPredictorDerivative[DivideBy2(angle) - 1];
57 }
58 
59 template <int bitdepth, typename Pixel>
60 class IntraPredTestBase : public testing::TestWithParam<TransformSize>,
61                           public test_utils::MaxAlignedAllocable {
62  public:
63   static_assert(bitdepth >= kBitdepth8 && bitdepth <= LIBGAV1_MAX_BITDEPTH, "");
IntraPredTestBase()64   IntraPredTestBase() {
65     switch (tx_size_) {
66       case kNumTransformSizes:
67         EXPECT_NE(tx_size_, kNumTransformSizes);
68         break;
69       default:
70         block_width_ = kTransformWidth[tx_size_];
71         block_height_ = kTransformHeight[tx_size_];
72         break;
73     }
74   }
75 
76   IntraPredTestBase(const IntraPredTestBase&) = delete;
77   IntraPredTestBase& operator=(const IntraPredTestBase&) = delete;
78   ~IntraPredTestBase() override = default;
79 
80  protected:
81   struct IntraPredMem {
Resetlibgav1::dsp::__anonab1825120111::IntraPredTestBase::IntraPredMem82     void Reset(libvpx_test::ACMRandom* rnd) {
83       ASSERT_NE(rnd, nullptr);
84 #if LIBGAV1_MSAN
85       // Match the behavior of Tile::IntraPrediction to prevent warnings due to
86       // assembly code (safely) overreading to fill a register.
87       memset(left_mem, 0, sizeof(left_mem));
88       memset(top_mem, 0, sizeof(top_mem));
89 #endif  // LIBGAV1_MSAN
90       Pixel* const left = left_mem + 16;
91       Pixel* const top = top_mem + 16;
92       const int mask = (1 << bitdepth) - 1;
93       for (auto& r : ref_src) r = rnd->Rand16() & mask;
94       for (int i = 0; i < kMaxBlockSize; ++i) left[i] = rnd->Rand16() & mask;
95       for (int i = -1; i < kMaxBlockSize; ++i) top[i] = rnd->Rand16() & mask;
96 
97       // Some directional predictors require top-right, bottom-left.
98       for (int i = kMaxBlockSize; i < 2 * kMaxBlockSize; ++i) {
99         left[i] = rnd->Rand16() & mask;
100         top[i] = rnd->Rand16() & mask;
101       }
102       // TODO(jzern): reorder this and regenerate the digests after switching
103       // random number generators.
104       // Upsampling in the directional predictors extends left/top[-1] to [-2].
105       left[-1] = rnd->Rand16() & mask;
106       left[-2] = rnd->Rand16() & mask;
107       top[-2] = rnd->Rand16() & mask;
108       memset(left_mem, 0, sizeof(left_mem[0]) * 14);
109       memset(top_mem, 0, sizeof(top_mem[0]) * 14);
110       memset(top_mem + kMaxBlockSize * 2 + 16, 0,
111              sizeof(top_mem[0]) * kTopMemPadding);
112     }
113 
114     // Set ref_src, top-left, top and left to |pixel|.
Setlibgav1::dsp::__anonab1825120111::IntraPredTestBase::IntraPredMem115     void Set(const Pixel pixel) {
116 #if LIBGAV1_MSAN
117       // Match the behavior of Tile::IntraPrediction to prevent warnings due to
118       // assembly code (safely) overreading to fill a register.
119       memset(left_mem, 0, sizeof(left_mem));
120       memset(top_mem, 0, sizeof(top_mem));
121 #endif  // LIBGAV1_MSAN
122       Pixel* const left = left_mem + 16;
123       Pixel* const top = top_mem + 16;
124       for (auto& r : ref_src) r = pixel;
125       // Upsampling in the directional predictors extends left/top[-1] to [-2].
126       for (int i = -2; i < 2 * kMaxBlockSize; ++i) {
127         left[i] = top[i] = pixel;
128       }
129     }
130 
131     // DirectionalZone1_Large() overreads up to 7 pixels in |top_mem|.
132     static constexpr int kTopMemPadding = 7;
133     alignas(kMaxAlignment) Pixel dst[kTotalPixels];
134     alignas(kMaxAlignment) Pixel ref_src[kTotalPixels];
135     alignas(kMaxAlignment) Pixel left_mem[kMaxBlockSize * 2 + 16];
136     alignas(
137         kMaxAlignment) Pixel top_mem[kMaxBlockSize * 2 + 16 + kTopMemPadding];
138   };
139 
SetUp()140   void SetUp() override { test_utils::ResetDspTable(bitdepth); }
141 
142   const TransformSize tx_size_ = GetParam();
143   int block_width_;
144   int block_height_;
145   IntraPredMem intra_pred_mem_;
146 };
147 
148 //------------------------------------------------------------------------------
149 // DirectionalIntraPredTest
150 
151 template <int bitdepth, typename Pixel>
152 class DirectionalIntraPredTest : public IntraPredTestBase<bitdepth, Pixel> {
153  public:
154   static_assert(bitdepth >= kBitdepth8 && bitdepth <= LIBGAV1_MAX_BITDEPTH, "");
155   DirectionalIntraPredTest() = default;
156   DirectionalIntraPredTest(const DirectionalIntraPredTest&) = delete;
157   DirectionalIntraPredTest& operator=(const DirectionalIntraPredTest&) = delete;
158   ~DirectionalIntraPredTest() override = default;
159 
160  protected:
161   using IntraPredTestBase<bitdepth, Pixel>::tx_size_;
162   using IntraPredTestBase<bitdepth, Pixel>::block_width_;
163   using IntraPredTestBase<bitdepth, Pixel>::block_height_;
164   using IntraPredTestBase<bitdepth, Pixel>::intra_pred_mem_;
165 
166   enum Zone { kZone1, kZone2, kZone3, kNumZones };
167 
168   enum { kAngleDeltaStart = -9, kAngleDeltaStop = 9, kAngleDeltaStep = 3 };
169 
SetUp()170   void SetUp() override {
171     IntraPredTestBase<bitdepth, Pixel>::SetUp();
172     IntraPredDirectionalInit_C();
173 
174     const Dsp* const dsp = GetDspTable(bitdepth);
175     ASSERT_NE(dsp, nullptr);
176     base_directional_intra_pred_zone1_ = dsp->directional_intra_predictor_zone1;
177     base_directional_intra_pred_zone2_ = dsp->directional_intra_predictor_zone2;
178     base_directional_intra_pred_zone3_ = dsp->directional_intra_predictor_zone3;
179 
180     const testing::TestInfo* const test_info =
181         testing::UnitTest::GetInstance()->current_test_info();
182     const char* const test_case = test_info->test_suite_name();
183     if (absl::StartsWith(test_case, "C/")) {
184       base_directional_intra_pred_zone1_ = nullptr;
185       base_directional_intra_pred_zone2_ = nullptr;
186       base_directional_intra_pred_zone3_ = nullptr;
187     } else if (absl::StartsWith(test_case, "NEON/")) {
188       IntraPredDirectionalInit_NEON();
189     } else if (absl::StartsWith(test_case, "SSE41/")) {
190       if ((GetCpuInfo() & kSSE4_1) == 0) GTEST_SKIP() << "No SSE4.1 support!";
191       IntraPredDirectionalInit_SSE4_1();
192     } else {
193       FAIL() << "Unrecognized architecture prefix in test case name: "
194              << test_case;
195     }
196 
197     cur_directional_intra_pred_zone1_ = dsp->directional_intra_predictor_zone1;
198     cur_directional_intra_pred_zone2_ = dsp->directional_intra_predictor_zone2;
199     cur_directional_intra_pred_zone3_ = dsp->directional_intra_predictor_zone3;
200 
201     // Skip functions that haven't been specialized for this particular
202     // architecture.
203     if (cur_directional_intra_pred_zone1_ ==
204         base_directional_intra_pred_zone1_) {
205       cur_directional_intra_pred_zone1_ = nullptr;
206     }
207     if (cur_directional_intra_pred_zone2_ ==
208         base_directional_intra_pred_zone2_) {
209       cur_directional_intra_pred_zone2_ = nullptr;
210     }
211     if (cur_directional_intra_pred_zone3_ ==
212         base_directional_intra_pred_zone3_) {
213       cur_directional_intra_pred_zone3_ = nullptr;
214     }
215   }
216 
IsEdgeUpsampled(int delta,const int filter_type) const217   bool IsEdgeUpsampled(int delta, const int filter_type) const {
218     delta = std::abs(delta);
219     if (delta == 0 || delta >= 40) return false;
220     const int block_wh = block_width_ + block_height_;
221     return (filter_type == 1) ? block_wh <= 8 : block_wh <= 16;
222   }
223 
224   // Returns the minimum and maximum (exclusive) range of angles that the
225   // predictor should be applied to.
GetZoneAngleRange(const Zone zone,int * const min_angle,int * const max_angle) const226   void GetZoneAngleRange(const Zone zone, int* const min_angle,
227                          int* const max_angle) const {
228     ASSERT_NE(min_angle, nullptr);
229     ASSERT_NE(max_angle, nullptr);
230     switch (zone) {
231         // The overall minimum angle comes from mode D45_PRED, yielding:
232         // min_angle = 45-(MAX_ANGLE_DELTA*ANGLE_STEP) = 36
233         // The overall maximum angle comes from mode D203_PRED, yielding:
234         // max_angle = 203+(MAX_ANGLE_DELTA*ANGLE_STEP) = 212
235         // The angles 180 and 90 are not permitted because they correspond to
236         // V_PRED and H_PRED, which are handled in distinct functions.
237       case kZone1:
238         *min_angle = 36;
239         *max_angle = 87;
240         break;
241       case kZone2:
242         *min_angle = 93;
243         *max_angle = 177;
244         break;
245       case kZone3:
246         *min_angle = 183;
247         *max_angle = 212;
248         break;
249       case kNumZones:
250         FAIL() << "Invalid zone value: " << zone;
251         break;
252     }
253   }
254 
255   // These tests modify intra_pred_mem_.
256   void TestSpeed(const char* const digests[kNumDirectionalIntraPredictors],
257                  Zone zone, int num_runs);
258   void TestSaturatedValues();
259   void TestRandomValues();
260 
261   DirectionalIntraPredictorZone1Func base_directional_intra_pred_zone1_;
262   DirectionalIntraPredictorZone2Func base_directional_intra_pred_zone2_;
263   DirectionalIntraPredictorZone3Func base_directional_intra_pred_zone3_;
264   DirectionalIntraPredictorZone1Func cur_directional_intra_pred_zone1_;
265   DirectionalIntraPredictorZone2Func cur_directional_intra_pred_zone2_;
266   DirectionalIntraPredictorZone3Func cur_directional_intra_pred_zone3_;
267 };
268 
269 template <int bitdepth, typename Pixel>
TestSpeed(const char * const digests[kNumDirectionalIntraPredictors],const Zone zone,const int num_runs)270 void DirectionalIntraPredTest<bitdepth, Pixel>::TestSpeed(
271     const char* const digests[kNumDirectionalIntraPredictors], const Zone zone,
272     const int num_runs) {
273   switch (zone) {
274     case kZone1:
275       if (cur_directional_intra_pred_zone1_ == nullptr) return;
276       break;
277     case kZone2:
278       if (cur_directional_intra_pred_zone2_ == nullptr) return;
279       break;
280     case kZone3:
281       if (cur_directional_intra_pred_zone3_ == nullptr) return;
282       break;
283     case kNumZones:
284       FAIL() << "Invalid zone value: " << zone;
285       break;
286   }
287   ASSERT_NE(digests, nullptr);
288   const Pixel* const left = intra_pred_mem_.left_mem + 16;
289   const Pixel* const top = intra_pred_mem_.top_mem + 16;
290 
291   libvpx_test::ACMRandom rnd(libvpx_test::ACMRandom::DeterministicSeed());
292   intra_pred_mem_.Reset(&rnd);
293 
294   // Allocate separate blocks for each angle + filter + upsampled combination.
295   // Add a 1 pixel right border to test for overwrites.
296   static constexpr int kMaxZoneAngles = 27;  // zone 2
297   static constexpr int kMaxFilterTypes = 2;
298   static constexpr int kBlockBorder = 1;
299   static constexpr int kBorderSize =
300       kBlockBorder * kMaxZoneAngles * kMaxFilterTypes;
301   const int ref_stride =
302       kMaxZoneAngles * kMaxFilterTypes * block_width_ + kBorderSize;
303   const size_t ref_alloc_size = sizeof(Pixel) * ref_stride * block_height_;
304 
305   using AlignedPtr = std::unique_ptr<Pixel[], decltype(&AlignedFree)>;
306   AlignedPtr ref_src(static_cast<Pixel*>(AlignedAlloc(16, ref_alloc_size)),
307                      &AlignedFree);
308   AlignedPtr dest(static_cast<Pixel*>(AlignedAlloc(16, ref_alloc_size)),
309                   &AlignedFree);
310   ASSERT_NE(ref_src, nullptr);
311   ASSERT_NE(dest, nullptr);
312 
313   const int mask = (1 << bitdepth) - 1;
314   for (size_t i = 0; i < ref_alloc_size / sizeof(ref_src[0]); ++i) {
315     ref_src[i] = rnd.Rand16() & mask;
316   }
317 
318   int min_angle = 0, max_angle = 0;
319   ASSERT_NO_FATAL_FAILURE(GetZoneAngleRange(zone, &min_angle, &max_angle));
320 
321   absl::Duration elapsed_time;
322   for (int run = 0; run < num_runs; ++run) {
323     Pixel* dst = dest.get();
324     memcpy(dst, ref_src.get(), ref_alloc_size);
325     for (const auto& base_angle : kBaseAngles) {
326       for (int filter_type = 0; filter_type <= 1; ++filter_type) {
327         for (int angle_delta = kAngleDeltaStart; angle_delta <= kAngleDeltaStop;
328              angle_delta += kAngleDeltaStep) {
329           const int predictor_angle = base_angle + angle_delta;
330           if (predictor_angle < min_angle || predictor_angle > max_angle) {
331             continue;
332           }
333 
334           ASSERT_GT(predictor_angle, 0) << "base_angle: " << base_angle
335                                         << " angle_delta: " << angle_delta;
336           const bool upsampled_left =
337               IsEdgeUpsampled(predictor_angle - 180, filter_type);
338           const bool upsampled_top =
339               IsEdgeUpsampled(predictor_angle - 90, filter_type);
340           const ptrdiff_t stride = ref_stride * sizeof(ref_src[0]);
341           if (predictor_angle < 90) {
342             ASSERT_EQ(zone, kZone1);
343             const int xstep =
344                 GetDirectionalIntraPredictorDerivative(predictor_angle);
345             const absl::Time start = absl::Now();
346             cur_directional_intra_pred_zone1_(dst, stride, top, block_width_,
347                                               block_height_, xstep,
348                                               upsampled_top);
349             elapsed_time += absl::Now() - start;
350           } else if (predictor_angle < 180) {
351             ASSERT_EQ(zone, kZone2);
352             const int xstep =
353                 GetDirectionalIntraPredictorDerivative(180 - predictor_angle);
354             const int ystep =
355                 GetDirectionalIntraPredictorDerivative(predictor_angle - 90);
356             const absl::Time start = absl::Now();
357             cur_directional_intra_pred_zone2_(
358                 dst, stride, top, left, block_width_, block_height_, xstep,
359                 ystep, upsampled_top, upsampled_left);
360             elapsed_time += absl::Now() - start;
361           } else {
362             ASSERT_EQ(zone, kZone3);
363             ASSERT_LT(predictor_angle, 270);
364             const int ystep =
365                 GetDirectionalIntraPredictorDerivative(270 - predictor_angle);
366             const absl::Time start = absl::Now();
367             cur_directional_intra_pred_zone3_(dst, stride, left, block_width_,
368                                               block_height_, ystep,
369                                               upsampled_left);
370             elapsed_time += absl::Now() - start;
371           }
372           dst += block_width_ + kBlockBorder;
373         }
374       }
375     }
376   }
377 
378   test_utils::CheckMd5Digest(ToString(tx_size_), kDirectionalPredNames[zone],
379                              digests[zone], dest.get(), ref_alloc_size,
380                              elapsed_time);
381 }
382 
383 template <int bitdepth, typename Pixel>
TestSaturatedValues()384 void DirectionalIntraPredTest<bitdepth, Pixel>::TestSaturatedValues() {
385   const Pixel* const left = intra_pred_mem_.left_mem + 16;
386   const Pixel* const top = intra_pred_mem_.top_mem + 16;
387   const auto kMaxPixel = static_cast<Pixel>((1 << bitdepth) - 1);
388   intra_pred_mem_.Set(kMaxPixel);
389 
390   for (int i = kZone1; i < kNumZones; ++i) {
391     switch (i) {
392       case kZone1:
393         if (cur_directional_intra_pred_zone1_ == nullptr) continue;
394         break;
395       case kZone2:
396         if (cur_directional_intra_pred_zone2_ == nullptr) continue;
397         break;
398       case kZone3:
399         if (cur_directional_intra_pred_zone3_ == nullptr) continue;
400         break;
401       case kNumZones:
402         FAIL() << "Invalid zone value: " << i;
403         break;
404     }
405     int min_angle = 0, max_angle = 0;
406     ASSERT_NO_FATAL_FAILURE(
407         GetZoneAngleRange(static_cast<Zone>(i), &min_angle, &max_angle));
408 
409     for (const auto& base_angle : kBaseAngles) {
410       for (int filter_type = 0; filter_type <= 1; ++filter_type) {
411         for (int angle_delta = kAngleDeltaStart; angle_delta <= kAngleDeltaStop;
412              angle_delta += kAngleDeltaStep) {
413           const int predictor_angle = base_angle + angle_delta;
414           if (predictor_angle <= min_angle || predictor_angle >= max_angle) {
415             continue;
416           }
417           ASSERT_GT(predictor_angle, 0) << "base_angle: " << base_angle
418                                         << " angle_delta: " << angle_delta;
419 
420           memcpy(intra_pred_mem_.dst, intra_pred_mem_.ref_src,
421                  sizeof(intra_pred_mem_.dst));
422 
423           const bool upsampled_left =
424               IsEdgeUpsampled(predictor_angle - 180, filter_type);
425           const bool upsampled_top =
426               IsEdgeUpsampled(predictor_angle - 90, filter_type);
427           const ptrdiff_t stride = kMaxBlockSize * sizeof(Pixel);
428           if (predictor_angle < 90) {
429             const int xstep =
430                 GetDirectionalIntraPredictorDerivative(predictor_angle);
431             cur_directional_intra_pred_zone1_(intra_pred_mem_.dst, stride, top,
432                                               block_width_, block_height_,
433                                               xstep, upsampled_top);
434           } else if (predictor_angle < 180) {
435             const int xstep =
436                 GetDirectionalIntraPredictorDerivative(180 - predictor_angle);
437             const int ystep =
438                 GetDirectionalIntraPredictorDerivative(predictor_angle - 90);
439             cur_directional_intra_pred_zone2_(
440                 intra_pred_mem_.dst, stride, top, left, block_width_,
441                 block_height_, xstep, ystep, upsampled_top, upsampled_left);
442           } else {
443             ASSERT_LT(predictor_angle, 270);
444             const int ystep =
445                 GetDirectionalIntraPredictorDerivative(270 - predictor_angle);
446             cur_directional_intra_pred_zone3_(intra_pred_mem_.dst, stride, left,
447                                               block_width_, block_height_,
448                                               ystep, upsampled_left);
449           }
450 
451           if (!test_utils::CompareBlocks(
452                   intra_pred_mem_.dst, intra_pred_mem_.ref_src, block_width_,
453                   block_height_, kMaxBlockSize, kMaxBlockSize, true)) {
454             ADD_FAILURE() << "Expected " << kDirectionalPredNames[i]
455                           << " (angle: " << predictor_angle
456                           << " filter type: " << filter_type
457                           << ") to produce a block containing '"
458                           << static_cast<int>(kMaxPixel) << "'";
459             return;
460           }
461         }
462       }
463     }
464   }
465 }
466 
467 template <int bitdepth, typename Pixel>
TestRandomValues()468 void DirectionalIntraPredTest<bitdepth, Pixel>::TestRandomValues() {
469   const Pixel* const left = intra_pred_mem_.left_mem + 16;
470   const Pixel* const top = intra_pred_mem_.top_mem + 16;
471   // Use an alternate seed to differentiate this test from TestSpeed().
472   libvpx_test::ACMRandom rnd(test_utils::kAlternateDeterministicSeed);
473 
474   for (int i = kZone1; i < kNumZones; ++i) {
475     // Only run when there is a reference version (base) and a different
476     // optimized version (cur).
477     switch (i) {
478       case kZone1:
479         if (base_directional_intra_pred_zone1_ == nullptr ||
480             cur_directional_intra_pred_zone1_ == nullptr) {
481           continue;
482         }
483         break;
484       case kZone2:
485         if (base_directional_intra_pred_zone2_ == nullptr ||
486             cur_directional_intra_pred_zone2_ == nullptr) {
487           continue;
488         }
489         break;
490       case kZone3:
491         if (base_directional_intra_pred_zone3_ == nullptr ||
492             cur_directional_intra_pred_zone3_ == nullptr) {
493           continue;
494         }
495         break;
496       case kNumZones:
497         FAIL() << "Invalid zone value: " << i;
498         break;
499     }
500     int min_angle = 0, max_angle = 0;
501     ASSERT_NO_FATAL_FAILURE(
502         GetZoneAngleRange(static_cast<Zone>(i), &min_angle, &max_angle));
503 
504     for (const auto& base_angle : kBaseAngles) {
505       for (int n = 0; n < 1000; ++n) {
506         for (int filter_type = 0; filter_type <= 1; ++filter_type) {
507           for (int angle_delta = kAngleDeltaStart;
508                angle_delta <= kAngleDeltaStop; angle_delta += kAngleDeltaStep) {
509             const int predictor_angle = base_angle + angle_delta;
510             if (predictor_angle <= min_angle || predictor_angle >= max_angle) {
511               continue;
512             }
513             ASSERT_GT(predictor_angle, 0) << "base_angle: " << base_angle
514                                           << " angle_delta: " << angle_delta;
515 
516             intra_pred_mem_.Reset(&rnd);
517             memcpy(intra_pred_mem_.dst, intra_pred_mem_.ref_src,
518                    sizeof(intra_pred_mem_.dst));
519 
520             const bool upsampled_left =
521                 IsEdgeUpsampled(predictor_angle - 180, filter_type);
522             const bool upsampled_top =
523                 IsEdgeUpsampled(predictor_angle - 90, filter_type);
524             const ptrdiff_t stride = kMaxBlockSize * sizeof(Pixel);
525             if (predictor_angle < 90) {
526               const int xstep =
527                   GetDirectionalIntraPredictorDerivative(predictor_angle);
528               base_directional_intra_pred_zone1_(
529                   intra_pred_mem_.ref_src, stride, top, block_width_,
530                   block_height_, xstep, upsampled_top);
531               cur_directional_intra_pred_zone1_(
532                   intra_pred_mem_.dst, stride, top, block_width_, block_height_,
533                   xstep, upsampled_top);
534             } else if (predictor_angle < 180) {
535               const int xstep =
536                   GetDirectionalIntraPredictorDerivative(180 - predictor_angle);
537               const int ystep =
538                   GetDirectionalIntraPredictorDerivative(predictor_angle - 90);
539               base_directional_intra_pred_zone2_(
540                   intra_pred_mem_.ref_src, stride, top, left, block_width_,
541                   block_height_, xstep, ystep, upsampled_top, upsampled_left);
542               cur_directional_intra_pred_zone2_(
543                   intra_pred_mem_.dst, stride, top, left, block_width_,
544                   block_height_, xstep, ystep, upsampled_top, upsampled_left);
545             } else {
546               ASSERT_LT(predictor_angle, 270);
547               const int ystep =
548                   GetDirectionalIntraPredictorDerivative(270 - predictor_angle);
549               base_directional_intra_pred_zone3_(
550                   intra_pred_mem_.ref_src, stride, left, block_width_,
551                   block_height_, ystep, upsampled_left);
552               cur_directional_intra_pred_zone3_(
553                   intra_pred_mem_.dst, stride, left, block_width_,
554                   block_height_, ystep, upsampled_left);
555             }
556 
557             if (!test_utils::CompareBlocks(
558                     intra_pred_mem_.dst, intra_pred_mem_.ref_src, block_width_,
559                     block_height_, kMaxBlockSize, kMaxBlockSize, true)) {
560               ADD_FAILURE() << "Result from optimized version of "
561                             << kDirectionalPredNames[i]
562                             << " differs from reference at angle "
563                             << predictor_angle << " with filter type "
564                             << filter_type << " in iteration #" << n;
565               return;
566             }
567           }
568         }
569       }
570     }
571   }
572 }
573 
574 using DirectionalIntraPredTest8bpp = DirectionalIntraPredTest<8, uint8_t>;
575 
GetDirectionalIntraPredDigests8bpp(TransformSize tx_size)576 const char* const* GetDirectionalIntraPredDigests8bpp(TransformSize tx_size) {
577   static const char* const kDigests4x4[kNumDirectionalIntraPredictors] = {
578       "9cfc1da729ad08682e165826c29b280b",
579       "bb73539c7afbda7bddd2184723b932d6",
580       "9d2882800ffe948196e984a26a2da72c",
581   };
582   static const char* const kDigests4x8[kNumDirectionalIntraPredictors] = {
583       "090efe6f83cc6fa301f65d3bbd5c38d2",
584       "d0fba4cdfb90f8bd293a94cae9db1a15",
585       "f7ad0eeab4389d0baa485d30fec87617",
586   };
587   static const char* const kDigests4x16[kNumDirectionalIntraPredictors] = {
588       "1d32b33c75fe85248c48cdc8caa78d84",
589       "7000e18159443d366129a6cc6ef8fcee",
590       "06c02fac5f8575f687abb3f634eb0b4c",
591   };
592   static const char* const kDigests8x4[kNumDirectionalIntraPredictors] = {
593       "1b591799685bc135982114b731293f78",
594       "5cd9099acb9f7b2618dafa6712666580",
595       "d023883efede88f99c19d006044d9fa1",
596   };
597   static const char* const kDigests8x8[kNumDirectionalIntraPredictors] = {
598       "f1e46ecf62a2516852f30c5025adb7ea",
599       "864442a209c16998065af28d8cdd839a",
600       "411a6e554868982af577de69e53f12e8",
601   };
602   static const char* const kDigests8x16[kNumDirectionalIntraPredictors] = {
603       "89278302be913a85cfb06feaea339459",
604       "6c42f1a9493490cd4529fd40729cec3c",
605       "2516b5e1c681e5dcb1acedd5f3d41106",
606   };
607   static const char* const kDigests8x32[kNumDirectionalIntraPredictors] = {
608       "aea7078f3eeaa8afbfe6c959c9e676f1",
609       "cad30babf12729dda5010362223ba65c",
610       "ff384ebdc832007775af418a2aae1463",
611   };
612   static const char* const kDigests16x4[kNumDirectionalIntraPredictors] = {
613       "964a821c313c831e12f4d32e616c0b55",
614       "adf6dad3a84ab4d16c16eea218bec57a",
615       "a54fa008d43895e523474686c48a81c2",
616   };
617   static const char* const kDigests16x8[kNumDirectionalIntraPredictors] = {
618       "fe2851b4e4f9fcf924cf17d50415a4c0",
619       "50a0e279c481437ff315d08eb904c733",
620       "0682065c8fb6cbf9be4949316c87c9e5",
621   };
622   static const char* const kDigests16x16[kNumDirectionalIntraPredictors] = {
623       "ef15503b1943642e7a0bace1616c0e11",
624       "bf1a4d3f855f1072a902a88ec6ce0350",
625       "7e87a03e29cd7fd843fd71b729a18f3f",
626   };
627   static const char* const kDigests16x32[kNumDirectionalIntraPredictors] = {
628       "f7b636615d2e5bf289b5db452a6f188d",
629       "e95858c532c10d00b0ce7a02a02121dd",
630       "34a18ccf58ef490f32268e85ce8c7de4",
631   };
632   static const char* const kDigests16x64[kNumDirectionalIntraPredictors] = {
633       "b250099986c2fab9670748598058846b",
634       "f25d80af4da862a9b6b72979f1e17cb4",
635       "5347dc7bc346733b4887f6c8ad5e0898",
636   };
637   static const char* const kDigests32x8[kNumDirectionalIntraPredictors] = {
638       "72e4c9f8af043b1cb1263490351818ab",
639       "1fc010d2df011b9e4e3d0957107c78df",
640       "f4cbfa3ca941ef08b972a68d7e7bafc4",
641   };
642   static const char* const kDigests32x16[kNumDirectionalIntraPredictors] = {
643       "37e5a1aaf7549d2bce08eece9d20f0f6",
644       "6a2794025d0aca414ab17baa3cf8251a",
645       "63dd37a6efdc91eeefef166c99ce2db1",
646   };
647   static const char* const kDigests32x32[kNumDirectionalIntraPredictors] = {
648       "198aabc958992eb49cceab97d1acb43e",
649       "aee88b6c8bacfcf38799fe338e6c66e7",
650       "01e8f8f96696636f6d79d33951907a16",
651   };
652   static const char* const kDigests32x64[kNumDirectionalIntraPredictors] = {
653       "0611390202c4f90f7add7aec763ded58",
654       "960240c7ceda2ccfac7c90b71460578a",
655       "7e7d97594aab8ad56e8c01c340335607",
656   };
657   static const char* const kDigests64x16[kNumDirectionalIntraPredictors] = {
658       "7e1f567e7fc510757f2d89d638bc826f",
659       "c929d687352ce40a58670be2ce3c8c90",
660       "f6881e6a9ba3c3d3d730b425732656b1",
661   };
662   static const char* const kDigests64x32[kNumDirectionalIntraPredictors] = {
663       "27b4c2a7081d4139f22003ba8b6dfdf2",
664       "301e82740866b9274108a04c872fa848",
665       "98d3aa4fef838f4abf00dac33806659f",
666   };
667   static const char* const kDigests64x64[kNumDirectionalIntraPredictors] = {
668       "b31816db8fade3accfd975b21aa264c7",
669       "2adce01a03b9452633d5830e1a9b4e23",
670       "7b988fadba8b07c36e88d7be6b270494",
671   };
672 
673   switch (tx_size) {
674     case kTransformSize4x4:
675       return kDigests4x4;
676     case kTransformSize4x8:
677       return kDigests4x8;
678     case kTransformSize4x16:
679       return kDigests4x16;
680     case kTransformSize8x4:
681       return kDigests8x4;
682     case kTransformSize8x8:
683       return kDigests8x8;
684     case kTransformSize8x16:
685       return kDigests8x16;
686     case kTransformSize8x32:
687       return kDigests8x32;
688     case kTransformSize16x4:
689       return kDigests16x4;
690     case kTransformSize16x8:
691       return kDigests16x8;
692     case kTransformSize16x16:
693       return kDigests16x16;
694     case kTransformSize16x32:
695       return kDigests16x32;
696     case kTransformSize16x64:
697       return kDigests16x64;
698     case kTransformSize32x8:
699       return kDigests32x8;
700     case kTransformSize32x16:
701       return kDigests32x16;
702     case kTransformSize32x32:
703       return kDigests32x32;
704     case kTransformSize32x64:
705       return kDigests32x64;
706     case kTransformSize64x16:
707       return kDigests64x16;
708     case kTransformSize64x32:
709       return kDigests64x32;
710     case kTransformSize64x64:
711       return kDigests64x64;
712     default:
713       ADD_FAILURE() << "Unknown transform size: " << tx_size;
714       return nullptr;
715   }
716 }
717 
TEST_P(DirectionalIntraPredTest8bpp,DISABLED_Speed)718 TEST_P(DirectionalIntraPredTest8bpp, DISABLED_Speed) {
719 #if LIBGAV1_ENABLE_NEON
720   const auto num_runs = static_cast<int>(2e5 / (block_width_ * block_height_));
721 #else
722   const int num_runs = static_cast<int>(4e7 / (block_width_ * block_height_));
723 #endif
724   for (int i = kZone1; i < kNumZones; ++i) {
725     TestSpeed(GetDirectionalIntraPredDigests8bpp(tx_size_),
726               static_cast<Zone>(i), num_runs);
727   }
728 }
729 
TEST_P(DirectionalIntraPredTest8bpp,FixedInput)730 TEST_P(DirectionalIntraPredTest8bpp, FixedInput) {
731   for (int i = kZone1; i < kNumZones; ++i) {
732     TestSpeed(GetDirectionalIntraPredDigests8bpp(tx_size_),
733               static_cast<Zone>(i), 1);
734   }
735 }
736 
TEST_P(DirectionalIntraPredTest8bpp,Overflow)737 TEST_P(DirectionalIntraPredTest8bpp, Overflow) { TestSaturatedValues(); }
TEST_P(DirectionalIntraPredTest8bpp,Random)738 TEST_P(DirectionalIntraPredTest8bpp, Random) { TestRandomValues(); }
739 
740 //------------------------------------------------------------------------------
741 
742 #if LIBGAV1_MAX_BITDEPTH >= 10
743 using DirectionalIntraPredTest10bpp = DirectionalIntraPredTest<10, uint16_t>;
744 
GetDirectionalIntraPredDigests10bpp(TransformSize tx_size)745 const char* const* GetDirectionalIntraPredDigests10bpp(TransformSize tx_size) {
746   static const char* const kDigests4x4[kNumDirectionalIntraPredictors] = {
747       "a683f4d7ccd978737615f61ecb4d638d",
748       "90c94374eaf7e9501f197863937b8639",
749       "0d3969cd081523ac6a906eecc7980c43",
750   };
751   static const char* const kDigests4x8[kNumDirectionalIntraPredictors] = {
752       "c3ffa2979b325644e4a56c882fe27347",
753       "1f61f5ee413a9a3b8d1d93869ec2aee0",
754       "4795ea944779ec4a783408769394d874",
755   };
756   static const char* const kDigests4x16[kNumDirectionalIntraPredictors] = {
757       "45c3282c9aa51024c1d64a40f230aa45",
758       "5cd47dd69f8bd0b15365a0c5cfc0a49a",
759       "06336c507b05f98c1d6a21abc43e6182",
760   };
761   static const char* const kDigests8x4[kNumDirectionalIntraPredictors] = {
762       "7370476ff0abbdc5e92f811b8879c861",
763       "a239a50adb28a4791b52a0dfff3bee06",
764       "4779a17f958a9ca04e8ec08c5aba1d36",
765   };
766   static const char* const kDigests8x8[kNumDirectionalIntraPredictors] = {
767       "305463f346c376594f82aad8304e0362",
768       "0cd481e5bda286c87a645417569fd948",
769       "48c7899dc9b7163b0b1f61b3a2b4b73e",
770   };
771   static const char* const kDigests8x16[kNumDirectionalIntraPredictors] = {
772       "5c18fd5339be90628c82b1fb6af50d5e",
773       "35eaa566ebd3bb7c903cfead5dc9ac78",
774       "9fdb0e790e5965810d02c02713c84071",
775   };
776   static const char* const kDigests8x32[kNumDirectionalIntraPredictors] = {
777       "2168d6cc858c704748b7b343ced2ac3a",
778       "1d3ce273107447faafd2e55877e48ffb",
779       "d344164049d1fe9b65a3ae8764bbbd37",
780   };
781   static const char* const kDigests16x4[kNumDirectionalIntraPredictors] = {
782       "dcef2cf51abe3fe150f388a14c762d30",
783       "6a810b289b1c14f8eab8ca1274e91ecd",
784       "c94da7c11f3fb11963d85c8804fce2d9",
785   };
786   static const char* const kDigests16x8[kNumDirectionalIntraPredictors] = {
787       "50a0d08b0d99b7a574bad2cfb36efc39",
788       "2dcb55874db39da70c8ca1318559f9fe",
789       "6390bcd30ff3bc389ecc0a0952bea531",
790   };
791   static const char* const kDigests16x16[kNumDirectionalIntraPredictors] = {
792       "7146c83c2620935606d49f3cb5876f41",
793       "2318ddf30c070a53c9b9cf199cd1b2c5",
794       "e9042e2124925aa7c1b6110617cb10e8",
795   };
796   static const char* const kDigests16x32[kNumDirectionalIntraPredictors] = {
797       "c970f401de7b7c5bb4e3ad447fcbef8f",
798       "a18cc70730eecdaa31dbcf4306ff490f",
799       "32c1528ad4a576a2210399d6b4ccd46e",
800   };
801   static const char* const kDigests16x64[kNumDirectionalIntraPredictors] = {
802       "00b3f0007da2e5d01380594a3d7162d5",
803       "1971af519e4a18967b7311f93efdd1b8",
804       "e6139769ce5a9c4982cfab9363004516",
805   };
806   static const char* const kDigests32x8[kNumDirectionalIntraPredictors] = {
807       "08107ad971179cc9f465ae5966bd4901",
808       "b215212a3c0dfe9182c4f2e903d731f7",
809       "791274416a0da87c674e1ae318b3ce09",
810   };
811   static const char* const kDigests32x16[kNumDirectionalIntraPredictors] = {
812       "94ea6cccae35b5d08799aa003ac08ccf",
813       "ae105e20e63fb55d4fd9d9e59dc62dde",
814       "973d0b2358ea585e4f486e7e645c5310",
815   };
816   static const char* const kDigests32x32[kNumDirectionalIntraPredictors] = {
817       "d14c695c4853ddf5e5d8256bc1d1ed60",
818       "6bd0ebeb53adecc11442b1218b870cb7",
819       "e03bc402a9999aba8272275dce93e89f",
820   };
821   static const char* const kDigests32x64[kNumDirectionalIntraPredictors] = {
822       "b21a8a8723758392ee659eeeae518a1e",
823       "e50285454896210ce44d6f04dfde05a7",
824       "f0f8ea0c6c2acc8d7d390927c3a90370",
825   };
826   static const char* const kDigests64x16[kNumDirectionalIntraPredictors] = {
827       "ce51db16fd4fa56e601631397b098c89",
828       "aa87a8635e02c1e91d13158c61e443f6",
829       "4c1ee3afd46ef34bd711a34d0bf86f13",
830   };
831   static const char* const kDigests64x32[kNumDirectionalIntraPredictors] = {
832       "25aaf5971e24e543e3e69a47254af777",
833       "eb6f444b3df127d69460778ab5bf8fc1",
834       "2f846cc0d506f90c0a58438600819817",
835   };
836   static const char* const kDigests64x64[kNumDirectionalIntraPredictors] = {
837       "b26ce5b5f4b5d4a438b52e5987877fb8",
838       "35721a00a70938111939cf69988d928e",
839       "0af7ec35939483fac82c246a13845806",
840   };
841 
842   switch (tx_size) {
843     case kTransformSize4x4:
844       return kDigests4x4;
845     case kTransformSize4x8:
846       return kDigests4x8;
847     case kTransformSize4x16:
848       return kDigests4x16;
849     case kTransformSize8x4:
850       return kDigests8x4;
851     case kTransformSize8x8:
852       return kDigests8x8;
853     case kTransformSize8x16:
854       return kDigests8x16;
855     case kTransformSize8x32:
856       return kDigests8x32;
857     case kTransformSize16x4:
858       return kDigests16x4;
859     case kTransformSize16x8:
860       return kDigests16x8;
861     case kTransformSize16x16:
862       return kDigests16x16;
863     case kTransformSize16x32:
864       return kDigests16x32;
865     case kTransformSize16x64:
866       return kDigests16x64;
867     case kTransformSize32x8:
868       return kDigests32x8;
869     case kTransformSize32x16:
870       return kDigests32x16;
871     case kTransformSize32x32:
872       return kDigests32x32;
873     case kTransformSize32x64:
874       return kDigests32x64;
875     case kTransformSize64x16:
876       return kDigests64x16;
877     case kTransformSize64x32:
878       return kDigests64x32;
879     case kTransformSize64x64:
880       return kDigests64x64;
881     default:
882       ADD_FAILURE() << "Unknown transform size: " << tx_size;
883       return nullptr;
884   }
885 }
886 
TEST_P(DirectionalIntraPredTest10bpp,DISABLED_Speed)887 TEST_P(DirectionalIntraPredTest10bpp, DISABLED_Speed) {
888 #if LIBGAV1_ENABLE_NEON
889   const int num_runs = static_cast<int>(2e5 / (block_width_ * block_height_));
890 #else
891   const int num_runs = static_cast<int>(4e7 / (block_width_ * block_height_));
892 #endif
893   for (int i = kZone1; i < kNumZones; ++i) {
894     TestSpeed(GetDirectionalIntraPredDigests10bpp(tx_size_),
895               static_cast<Zone>(i), num_runs);
896   }
897 }
898 
TEST_P(DirectionalIntraPredTest10bpp,FixedInput)899 TEST_P(DirectionalIntraPredTest10bpp, FixedInput) {
900   for (int i = kZone1; i < kNumZones; ++i) {
901     TestSpeed(GetDirectionalIntraPredDigests10bpp(tx_size_),
902               static_cast<Zone>(i), 1);
903   }
904 }
905 
TEST_P(DirectionalIntraPredTest10bpp,Overflow)906 TEST_P(DirectionalIntraPredTest10bpp, Overflow) { TestSaturatedValues(); }
TEST_P(DirectionalIntraPredTest10bpp,Random)907 TEST_P(DirectionalIntraPredTest10bpp, Random) { TestRandomValues(); }
908 #endif  // LIBGAV1_MAX_BITDEPTH >= 10
909 
910 //------------------------------------------------------------------------------
911 
912 #if LIBGAV1_MAX_BITDEPTH == 12
913 using DirectionalIntraPredTest12bpp = DirectionalIntraPredTest<12, uint16_t>;
914 
GetDirectionalIntraPredDigests12bpp(TransformSize tx_size)915 const char* const* GetDirectionalIntraPredDigests12bpp(TransformSize tx_size) {
916   static const char* const kDigests4x4[kNumDirectionalIntraPredictors] = {
917       "78f3297743f75e928e755b6ffa2d3050",
918       "7315da39861c6e3ef2e47c913e3be349",
919       "5609cb40b575f24d05880df202a60bd3",
920   };
921   static const char* const kDigests4x8[kNumDirectionalIntraPredictors] = {
922       "efb2363d3c25427abe198806c8ba4d6b",
923       "b5aaa41665a10e7e7944fb7fc90fd59a",
924       "5a85610342339ca3109d775fa18dc25c",
925   };
926   static const char* const kDigests4x16[kNumDirectionalIntraPredictors] = {
927       "9045679914980ea1f579d84509397b6e",
928       "f9f50bdc9f81a93095fd9d6998174aa7",
929       "46c1f82e85b8ba5b03bab41a2f561483",
930   };
931   static const char* const kDigests8x4[kNumDirectionalIntraPredictors] = {
932       "a0ae0956b2b667c528b7803d733d49da",
933       "5d9f60ef8904c4faedb6cfc19e54418a",
934       "4ffdcbbbcb23bca8286f1c286b9cb3e8",
935   };
936   static const char* const kDigests8x8[kNumDirectionalIntraPredictors] = {
937       "086116c6b116613b8b47a086726566ea",
938       "141dca7fcae0e4d4b88887a618271ea1",
939       "3575a34278aa0fb1eed934290982f4a7",
940   };
941   static const char* const kDigests8x16[kNumDirectionalIntraPredictors] = {
942       "7922f40216c78a40abaf675667e79493",
943       "55d20588240171df2e24d105ee1563ad",
944       "674b4d8f4dbf514d22e21cc4baeda1d3",
945   };
946   static const char* const kDigests8x32[kNumDirectionalIntraPredictors] = {
947       "32d4d7e256d3b304026ddb5430cf6a09",
948       "72f4be2569f4e067c252d51ff4030de3",
949       "6779a132e1bac0ac43c2373f56553ed8",
950   };
951   static const char* const kDigests16x4[kNumDirectionalIntraPredictors] = {
952       "1be2e0efc1403f9e22cfb8aeb28763d9",
953       "558c8a5418ac91d21a5839c454a9391f",
954       "7693ebef9b86416ebd6e78e98fcafba7",
955   };
956   static const char* const kDigests16x8[kNumDirectionalIntraPredictors] = {
957       "e6217ed1c673ae42e84f8757316b580d",
958       "028aa582c11a9733f0cd693211a067c5",
959       "082de9fc7c4bc80a8ec8522b5a5cb52c",
960   };
961   static const char* const kDigests16x16[kNumDirectionalIntraPredictors] = {
962       "e3b293c09bdc9c5c543ad046a3f0d64f",
963       "2de5803a6ed497c1039c8e6d675c1dd3",
964       "05742f807560f5d5206e54b70097dc4a",
965   };
966   static const char* const kDigests16x32[kNumDirectionalIntraPredictors] = {
967       "57f2ca4ba56be253eff7e6b73df5003d",
968       "ef8bea00437e01fb798a22cda59f0191",
969       "989ff38c96600c2f108d6e6fa381fd13",
970   };
971   static const char* const kDigests16x64[kNumDirectionalIntraPredictors] = {
972       "f5540f4874c02aa2222a3ba75106f841",
973       "17e5d20f798a96c39abc8a81e7aa7bc6",
974       "0fe9ea14c9dcae466b4a36f1c7db6978",
975   };
976   static const char* const kDigests32x8[kNumDirectionalIntraPredictors] = {
977       "aff9429951ab1885c0d9ed29aa1b6a9f",
978       "4b686e2a879bf0b4aadd06b412e0eb48",
979       "39325d71cddc272bfa1dd2dc80d09ffe",
980   };
981   static const char* const kDigests32x16[kNumDirectionalIntraPredictors] = {
982       "b83dffdf8bad2b7c3808925b6138ca1e",
983       "3656b58c7aaf2025979b4a3ed8a2841e",
984       "cfcc0c6ae3fa5e7d45dec581479459f6",
985   };
986   static const char* const kDigests32x32[kNumDirectionalIntraPredictors] = {
987       "3c91b3b9e2df73ffb718e0bf53c5a5c2",
988       "0dbe27603e111158e70d99e181befb83",
989       "edecbffb32ae1e49b66b6e55ad0af6c6",
990   };
991   static const char* const kDigests32x64[kNumDirectionalIntraPredictors] = {
992       "a3290917f755c7ccdc7b77eb3c6c89a7",
993       "42f89db41fbb366ddb78ef79a043f3e3",
994       "7f7bcbe33aa003b166677c68d12490e9",
995   };
996   static const char* const kDigests64x16[kNumDirectionalIntraPredictors] = {
997       "d4f4c6b70a82695f843e9227bd7d9cc8",
998       "550a0bd87936801651d552e229b683e9",
999       "a4c730ad71f566a930c5672e1b2f48f1",
1000   };
1001   static const char* const kDigests64x32[kNumDirectionalIntraPredictors] = {
1002       "2087c9264c4c5fea9a6fe20dcedbe2b9",
1003       "d4dd51d9578a3fc2eb75086fba867c22",
1004       "6121a67d63e40107e780d0938aeb3d21",
1005   };
1006   static const char* const kDigests64x64[kNumDirectionalIntraPredictors] = {
1007       "09c3818a07bc54467634c2bfce66f58f",
1008       "8da453b8d72d73d71ba15a14ddd59db4",
1009       "9bc939aa54445722469b120b8a505cb3",
1010   };
1011 
1012   switch (tx_size) {
1013     case kTransformSize4x4:
1014       return kDigests4x4;
1015     case kTransformSize4x8:
1016       return kDigests4x8;
1017     case kTransformSize4x16:
1018       return kDigests4x16;
1019     case kTransformSize8x4:
1020       return kDigests8x4;
1021     case kTransformSize8x8:
1022       return kDigests8x8;
1023     case kTransformSize8x16:
1024       return kDigests8x16;
1025     case kTransformSize8x32:
1026       return kDigests8x32;
1027     case kTransformSize16x4:
1028       return kDigests16x4;
1029     case kTransformSize16x8:
1030       return kDigests16x8;
1031     case kTransformSize16x16:
1032       return kDigests16x16;
1033     case kTransformSize16x32:
1034       return kDigests16x32;
1035     case kTransformSize16x64:
1036       return kDigests16x64;
1037     case kTransformSize32x8:
1038       return kDigests32x8;
1039     case kTransformSize32x16:
1040       return kDigests32x16;
1041     case kTransformSize32x32:
1042       return kDigests32x32;
1043     case kTransformSize32x64:
1044       return kDigests32x64;
1045     case kTransformSize64x16:
1046       return kDigests64x16;
1047     case kTransformSize64x32:
1048       return kDigests64x32;
1049     case kTransformSize64x64:
1050       return kDigests64x64;
1051     default:
1052       ADD_FAILURE() << "Unknown transform size: " << tx_size;
1053       return nullptr;
1054   }
1055 }
1056 
TEST_P(DirectionalIntraPredTest12bpp,DISABLED_Speed)1057 TEST_P(DirectionalIntraPredTest12bpp, DISABLED_Speed) {
1058 #if LIBGAV1_ENABLE_NEON
1059   const int num_runs = static_cast<int>(2e7 / (block_width_ * block_height_));
1060 #else
1061   const int num_runs = static_cast<int>(4e7 / (block_width_ * block_height_));
1062 #endif
1063   for (int i = kZone1; i < kNumZones; ++i) {
1064     TestSpeed(GetDirectionalIntraPredDigests12bpp(tx_size_),
1065               static_cast<Zone>(i), num_runs);
1066   }
1067 }
1068 
TEST_P(DirectionalIntraPredTest12bpp,FixedInput)1069 TEST_P(DirectionalIntraPredTest12bpp, FixedInput) {
1070   for (int i = kZone1; i < kNumZones; ++i) {
1071     TestSpeed(GetDirectionalIntraPredDigests12bpp(tx_size_),
1072               static_cast<Zone>(i), 1);
1073   }
1074 }
1075 
TEST_P(DirectionalIntraPredTest12bpp,Overflow)1076 TEST_P(DirectionalIntraPredTest12bpp, Overflow) { TestSaturatedValues(); }
TEST_P(DirectionalIntraPredTest12bpp,Random)1077 TEST_P(DirectionalIntraPredTest12bpp, Random) { TestRandomValues(); }
1078 #endif  // LIBGAV1_MAX_BITDEPTH == 12
1079 
1080 constexpr TransformSize kTransformSizes[] = {
1081     kTransformSize4x4,   kTransformSize4x8,   kTransformSize4x16,
1082     kTransformSize8x4,   kTransformSize8x8,   kTransformSize8x16,
1083     kTransformSize8x32,  kTransformSize16x4,  kTransformSize16x8,
1084     kTransformSize16x16, kTransformSize16x32, kTransformSize16x64,
1085     kTransformSize32x8,  kTransformSize32x16, kTransformSize32x32,
1086     kTransformSize32x64, kTransformSize64x16, kTransformSize64x32,
1087     kTransformSize64x64};
1088 
1089 INSTANTIATE_TEST_SUITE_P(C, DirectionalIntraPredTest8bpp,
1090                          testing::ValuesIn(kTransformSizes));
1091 #if LIBGAV1_ENABLE_SSE4_1
1092 INSTANTIATE_TEST_SUITE_P(SSE41, DirectionalIntraPredTest8bpp,
1093                          testing::ValuesIn(kTransformSizes));
1094 #endif  // LIBGAV1_ENABLE_SSE4_1
1095 #if LIBGAV1_ENABLE_NEON
1096 INSTANTIATE_TEST_SUITE_P(NEON, DirectionalIntraPredTest8bpp,
1097                          testing::ValuesIn(kTransformSizes));
1098 #endif  // LIBGAV1_ENABLE_NEON
1099 
1100 #if LIBGAV1_MAX_BITDEPTH >= 10
1101 INSTANTIATE_TEST_SUITE_P(C, DirectionalIntraPredTest10bpp,
1102                          testing::ValuesIn(kTransformSizes));
1103 #if LIBGAV1_ENABLE_SSE4_1
1104 INSTANTIATE_TEST_SUITE_P(SSE41, DirectionalIntraPredTest10bpp,
1105                          testing::ValuesIn(kTransformSizes));
1106 #endif  // LIBGAV1_ENABLE_SSE4_1
1107 #if LIBGAV1_ENABLE_NEON
1108 INSTANTIATE_TEST_SUITE_P(NEON, DirectionalIntraPredTest10bpp,
1109                          testing::ValuesIn(kTransformSizes));
1110 #endif  // LIBGAV1_ENABLE_NEON
1111 #endif  // LIBGAV1_MAX_BITDEPTH >= 10
1112 
1113 #if LIBGAV1_MAX_BITDEPTH == 12
1114 INSTANTIATE_TEST_SUITE_P(C, DirectionalIntraPredTest12bpp,
1115                          testing::ValuesIn(kTransformSizes));
1116 #endif  // LIBGAV1_MAX_BITDEPTH == 12
1117 
1118 }  // namespace
1119 }  // namespace dsp
1120 
operator <<(std::ostream & os,const TransformSize tx_size)1121 static std::ostream& operator<<(std::ostream& os, const TransformSize tx_size) {
1122   return os << ToString(tx_size);
1123 }
1124 
1125 }  // namespace libgav1
1126