diff options
Diffstat (limited to 'lib/jxl/inverse_mtf-inl.h')
-rw-r--r-- | lib/jxl/inverse_mtf-inl.h | 90 |
1 files changed, 90 insertions, 0 deletions
diff --git a/lib/jxl/inverse_mtf-inl.h b/lib/jxl/inverse_mtf-inl.h new file mode 100644 index 0000000..fcb01d7 --- /dev/null +++ b/lib/jxl/inverse_mtf-inl.h @@ -0,0 +1,90 @@ +// Copyright (c) the JPEG XL Project Authors. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// SIMDified inverse-move-to-front transform. + +#if defined(LIB_JXL_INVERSE_MTF_INL_H_) == defined(HWY_TARGET_TOGGLE) +#ifdef LIB_JXL_INVERSE_MTF_INL_H_ +#undef LIB_JXL_INVERSE_MTF_INL_H_ +#else +#define LIB_JXL_INVERSE_MTF_INL_H_ +#endif + +#include <hwy/highway.h> + +#include "lib/jxl/sanitizers.h" + +HWY_BEFORE_NAMESPACE(); +namespace jxl { +namespace HWY_NAMESPACE { + +// These templates are not found via ADL. +using hwy::HWY_NAMESPACE::FirstN; +using hwy::HWY_NAMESPACE::IfThenElse; +using hwy::HWY_NAMESPACE::Load; +using hwy::HWY_NAMESPACE::LoadU; +using hwy::HWY_NAMESPACE::StoreU; + +inline void MoveToFront(uint8_t* v, uint8_t index) { + uint8_t value = v[index]; + uint8_t i = index; + if (i < 4) { + for (; i; --i) v[i] = v[i - 1]; + } else { + const HWY_CAPPED(uint8_t, 64) d; + int tail = i & (Lanes(d) - 1); + if (tail) { + i -= tail; + const auto vec = Load(d, v + i); + const auto prev = LoadU(d, v + i + 1); + StoreU(IfThenElse(FirstN(d, tail), vec, prev), d, v + i + 1); + } + while (i) { + i -= Lanes(d); + const auto vec = Load(d, v + i); + StoreU(vec, d, v + i + 1); + } + } + v[0] = value; +} + +inline void InverseMoveToFrontTransform(uint8_t* v, int v_len) { + HWY_ALIGN uint8_t mtf[256 + 64]; + int i; + for (i = 0; i < 256; ++i) { + mtf[i] = static_cast<uint8_t>(i); + } +#if JXL_MEMORY_SANITIZER + const HWY_CAPPED(uint8_t, 64) d; + for (size_t j = 0; j < Lanes(d); ++j) { + mtf[256 + j] = 0; + } +#endif // JXL_MEMORY_SANITIZER + for (i = 0; i < v_len; ++i) { + uint8_t index = v[i]; + v[i] = mtf[index]; + if (index) MoveToFront(mtf, index); + } +} + +// NOLINTNEXTLINE(google-readability-namespace-comments) +} // namespace HWY_NAMESPACE +} // namespace jxl +HWY_AFTER_NAMESPACE(); + +#endif // LIB_JXL_INVERSE_MTF_INL_H_ + +#if HWY_ONCE +#ifndef INVERSE_MTF_ONCE +#define INVERSE_MTF_ONCE + +namespace jxl { +inline void InverseMoveToFrontTransform(uint8_t* v, int v_len) { + return HWY_STATIC_DISPATCH(InverseMoveToFrontTransform)(v, v_len); +} +} // namespace jxl + +#endif // INVERSE_MTF_ONCE +#endif // HWY_ONCE |