// 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. #if defined(LIB_JXL_QUANTIZER_INL_H_) == defined(HWY_TARGET_TOGGLE) #ifdef LIB_JXL_QUANTIZER_INL_H_ #undef LIB_JXL_QUANTIZER_INL_H_ #else #define LIB_JXL_QUANTIZER_INL_H_ #endif #include #include HWY_BEFORE_NAMESPACE(); namespace jxl { namespace HWY_NAMESPACE { namespace { // These templates are not found via ADL. using hwy::HWY_NAMESPACE::Rebind; using hwy::HWY_NAMESPACE::Vec; template HWY_INLINE HWY_MAYBE_UNUSED Vec> AdjustQuantBias( DI di, const size_t c, const Vec quant_i, const float* HWY_RESTRICT biases) { const Rebind df; const auto quant = ConvertTo(df, quant_i); // Compare |quant|, keep sign bit for negating result. const auto kSign = BitCast(df, Set(di, INT32_MIN)); const auto sign = And(quant, kSign); // TODO(janwas): = abs ^ orig const auto abs_quant = AndNot(kSign, quant); // If |x| is 1, kZeroBias creates a different bias for each channel. // We're implementing the following: // if (quant == 0) return 0; // if (quant == 1) return biases[c]; // if (quant == -1) return -biases[c]; // return quant - biases[3] / quant; // Integer comparison is not helpful because Clang incurs bypass penalties // from unnecessarily mixing integer and float. const auto is_01 = abs_quant < Set(df, 1.125f); const auto not_0 = abs_quant > Zero(df); // Bitwise logic is faster than quant * biases[c]. const auto one_bias = IfThenElseZero(not_0, Xor(Set(df, biases[c]), sign)); // About 2E-5 worse than ReciprocalNR or division. const auto bias = NegMulAdd(Set(df, biases[3]), ApproximateReciprocal(quant), quant); return IfThenElse(is_01, one_bias, bias); } } // namespace // NOLINTNEXTLINE(google-readability-namespace-comments) } // namespace HWY_NAMESPACE } // namespace jxl HWY_AFTER_NAMESPACE(); #endif // LIB_JXL_QUANTIZER_INL_H_