tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

image_test.cc (4765B)


      1 // Copyright (c) the JPEG XL Project
      2 // SPDX-License-Identifier: Apache-2.0
      3 //
      4 // Licensed under the Apache License, Version 2.0 (the "License");
      5 // you may not use this file except in compliance with the License.
      6 // You may obtain a copy of the License at
      7 //
      8 //      http://www.apache.org/licenses/LICENSE-2.0
      9 //
     10 // Unless required by applicable law or agreed to in writing, software
     11 // distributed under the License is distributed on an "AS IS" BASIS,
     12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13 // See the License for the specific language governing permissions and
     14 // limitations under the License.
     15 
     16 #include "hwy/contrib/image/image.h"
     17 
     18 #include <stddef.h>
     19 #include <stdio.h>
     20 #include <stdlib.h>
     21 
     22 #include <random>
     23 
     24 #undef HWY_TARGET_INCLUDE
     25 #define HWY_TARGET_INCLUDE "hwy/contrib/image/image_test.cc"
     26 #include "hwy/foreach_target.h"  // IWYU pragma: keep
     27 #include "hwy/highway.h"
     28 #include "hwy/tests/test_util-inl.h"
     29 
     30 HWY_BEFORE_NAMESPACE();
     31 namespace hwy {
     32 namespace HWY_NAMESPACE {
     33 namespace {
     34 
     35 // Ensure we can always write full aligned vectors.
     36 struct TestAlignedT {
     37  template <typename T>
     38  void operator()(T /*unused*/) const {
     39    std::mt19937 rng(129);
     40    std::uniform_int_distribution<int> dist(0, 16);
     41    const ScalableTag<T> d;
     42 
     43    for (size_t ysize = 1; ysize < 4; ++ysize) {
     44      for (size_t xsize = 1; xsize < 64; ++xsize) {
     45        Image<T> img(xsize, ysize);
     46 
     47        for (size_t y = 0; y < ysize; ++y) {
     48          T* HWY_RESTRICT row = img.MutableRow(y);
     49          for (size_t x = 0; x < xsize; x += Lanes(d)) {
     50            const auto values = Iota(d, dist(rng));
     51            Store(values, d, row + x);
     52          }
     53        }
     54 
     55        // Sanity check to prevent optimizing out the writes
     56        const auto x = std::uniform_int_distribution<size_t>(0, xsize - 1)(rng);
     57        const auto y = std::uniform_int_distribution<size_t>(0, ysize - 1)(rng);
     58        HWY_ASSERT(img.ConstRow(y)[x] < 16 + Lanes(d));
     59      }
     60    }
     61  }
     62 };
     63 
     64 void TestAligned() { ForUnsignedTypes(TestAlignedT()); }
     65 
     66 // Ensure we can write an unaligned vector starting at the last valid value.
     67 struct TestUnalignedT {
     68  template <typename T>
     69  void operator()(T /*unused*/) const {
     70    std::mt19937 rng(129);
     71    std::uniform_int_distribution<int> dist(0, 3);
     72    const ScalableTag<T> d;
     73 
     74    for (size_t ysize = 1; ysize < 4; ++ysize) {
     75      for (size_t xsize = 1; xsize < 128; ++xsize) {
     76        Image<T> img(xsize, ysize);
     77        img.InitializePaddingForUnalignedAccesses();
     78 
     79 // This test reads padding, which only works if it was initialized,
     80 // which only happens in MSAN builds.
     81 #if HWY_IS_MSAN || HWY_IDE
     82        // Initialize only the valid samples
     83        for (size_t y = 0; y < ysize; ++y) {
     84          T* HWY_RESTRICT row = img.MutableRow(y);
     85          for (size_t x = 0; x < xsize; ++x) {
     86            row[x] = ConvertScalarTo<T>(1u << dist(rng));
     87          }
     88        }
     89 
     90        // Read padding bits
     91        auto accum = Zero(d);
     92        for (size_t y = 0; y < ysize; ++y) {
     93          T* HWY_RESTRICT row = img.MutableRow(y);
     94          for (size_t x = 0; x < xsize; ++x) {
     95            accum = Or(accum, LoadU(d, row + x));
     96          }
     97        }
     98 
     99        // Ensure padding was zero
    100        const size_t N = Lanes(d);
    101        auto lanes = AllocateAligned<T>(N);
    102        HWY_ASSERT(lanes);
    103        Store(accum, d, lanes.get());
    104        for (size_t i = 0; i < N; ++i) {
    105          HWY_ASSERT(lanes[i] < 16);
    106        }
    107 #else  // Check that writing padding does not overwrite valid samples
    108       // Initialize only the valid samples
    109        for (size_t y = 0; y < ysize; ++y) {
    110          T* HWY_RESTRICT row = img.MutableRow(y);
    111          for (size_t x = 0; x < xsize; ++x) {
    112            row[x] = ConvertScalarTo<T>(x);
    113          }
    114        }
    115 
    116        // Zero padding and rightmost sample
    117        for (size_t y = 0; y < ysize; ++y) {
    118          T* HWY_RESTRICT row = img.MutableRow(y);
    119          StoreU(Zero(d), d, row + xsize - 1);
    120        }
    121 
    122        // Ensure no samples except the rightmost were overwritten
    123        for (size_t y = 0; y < ysize; ++y) {
    124          T* HWY_RESTRICT row = img.MutableRow(y);
    125          for (size_t x = 0; x < xsize - 1; ++x) {
    126            HWY_ASSERT_EQ(ConvertScalarTo<T>(x), row[x]);
    127          }
    128        }
    129 #endif
    130      }
    131    }
    132  }
    133 };
    134 
    135 void TestUnaligned() { ForUnsignedTypes(TestUnalignedT()); }
    136 
    137 }  // namespace
    138 // NOLINTNEXTLINE(google-readability-namespace-comments)
    139 }  // namespace HWY_NAMESPACE
    140 }  // namespace hwy
    141 HWY_AFTER_NAMESPACE();
    142 
    143 #if HWY_ONCE
    144 namespace hwy {
    145 namespace {
    146 HWY_BEFORE_TEST(ImageTest);
    147 HWY_EXPORT_AND_TEST_P(ImageTest, TestAligned);
    148 HWY_EXPORT_AND_TEST_P(ImageTest, TestUnaligned);
    149 HWY_AFTER_TEST();
    150 }  // namespace
    151 }  // namespace hwy
    152 HWY_TEST_MAIN();
    153 #endif  // HWY_ONCE