quantizer-inl.h (2354B)
1 // Copyright (c) the JPEG XL Project Authors. All rights reserved. 2 // 3 // Use of this source code is governed by a BSD-style 4 // license that can be found in the LICENSE file. 5 6 #if defined(LIB_JXL_QUANTIZER_INL_H_) == defined(HWY_TARGET_TOGGLE) 7 #ifdef LIB_JXL_QUANTIZER_INL_H_ 8 #undef LIB_JXL_QUANTIZER_INL_H_ 9 #else 10 #define LIB_JXL_QUANTIZER_INL_H_ 11 #endif 12 13 #include <stddef.h> 14 15 #include <hwy/highway.h> 16 HWY_BEFORE_NAMESPACE(); 17 namespace jxl { 18 namespace HWY_NAMESPACE { 19 namespace { 20 21 // These templates are not found via ADL. 22 using hwy::HWY_NAMESPACE::And; 23 using hwy::HWY_NAMESPACE::AndNot; 24 using hwy::HWY_NAMESPACE::ApproximateReciprocal; 25 using hwy::HWY_NAMESPACE::Gt; 26 using hwy::HWY_NAMESPACE::IfThenElse; 27 using hwy::HWY_NAMESPACE::IfThenElseZero; 28 using hwy::HWY_NAMESPACE::Lt; 29 using hwy::HWY_NAMESPACE::Rebind; 30 using hwy::HWY_NAMESPACE::Vec; 31 using hwy::HWY_NAMESPACE::Xor; 32 33 template <class DI> 34 HWY_INLINE HWY_MAYBE_UNUSED Vec<Rebind<float, DI>> AdjustQuantBias( 35 DI di, const size_t c, const Vec<DI> quant_i, 36 const float* HWY_RESTRICT biases) { 37 const Rebind<float, DI> df; 38 39 const auto quant = ConvertTo(df, quant_i); 40 41 // Compare |quant|, keep sign bit for negating result. 42 const auto kSign = BitCast(df, Set(di, INT32_MIN)); 43 const auto sign = And(quant, kSign); // TODO(janwas): = abs ^ orig 44 const auto abs_quant = AndNot(kSign, quant); 45 46 // If |x| is 1, kZeroBias creates a different bias for each channel. 47 // We're implementing the following: 48 // if (quant == 0) return 0; 49 // if (quant == 1) return biases[c]; 50 // if (quant == -1) return -biases[c]; 51 // return quant - biases[3] / quant; 52 53 // Integer comparison is not helpful because Clang incurs bypass penalties 54 // from unnecessarily mixing integer and float. 55 const auto is_01 = Lt(abs_quant, Set(df, 1.125f)); 56 const auto not_0 = Gt(abs_quant, Zero(df)); 57 58 // Bitwise logic is faster than quant * biases[c]. 59 const auto one_bias = IfThenElseZero(not_0, Xor(Set(df, biases[c]), sign)); 60 61 // About 2E-5 worse than ReciprocalNR or division. 62 const auto bias = 63 NegMulAdd(Set(df, biases[3]), ApproximateReciprocal(quant), quant); 64 65 return IfThenElse(is_01, one_bias, bias); 66 } 67 68 } // namespace 69 // NOLINTNEXTLINE(google-readability-namespace-comments) 70 } // namespace HWY_NAMESPACE 71 } // namespace jxl 72 HWY_AFTER_NAMESPACE(); 73 74 #endif // LIB_JXL_QUANTIZER_INL_H_