/src/libjxl/lib/jxl/quantizer-inl.h
Line | Count | Source |
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 | 9.29M | const float* HWY_RESTRICT biases) { |
37 | 9.29M | const Rebind<float, DI> df; |
38 | | |
39 | 9.29M | const auto quant = ConvertTo(df, quant_i); |
40 | | |
41 | | // Compare |quant|, keep sign bit for negating result. |
42 | 9.29M | const auto kSign = BitCast(df, Set(di, INT32_MIN)); |
43 | 9.29M | const auto sign = And(quant, kSign); // TODO(janwas): = abs ^ orig |
44 | 9.29M | 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 | 9.29M | const auto is_01 = Lt(abs_quant, Set(df, 1.125f)); |
56 | 9.29M | const auto not_0 = Gt(abs_quant, Zero(df)); |
57 | | |
58 | | // Bitwise logic is faster than quant * biases[c]. |
59 | 9.29M | const auto one_bias = IfThenElseZero(not_0, Xor(Set(df, biases[c]), sign)); |
60 | | |
61 | | // About 2E-5 worse than ReciprocalNR or division. |
62 | 9.29M | const auto bias = |
63 | 9.29M | NegMulAdd(Set(df, biases[3]), ApproximateReciprocal(quant), quant); |
64 | | |
65 | 9.29M | return IfThenElse(is_01, one_bias, bias); |
66 | 9.29M | } Unexecuted instantiation: enc_group.cc:decltype (Zero((hwy::N_SCALAR::Simd<int, 1ul, 0>::Rebind<float>)())) jxl::N_SCALAR::(anonymous namespace)::AdjustQuantBias<hwy::N_SCALAR::Simd<int, 1ul, 0> >(hwy::N_SCALAR::Simd<int, 1ul, 0>, unsigned long, decltype (Zero((hwy::N_SCALAR::Simd<int, 1ul, 0>)())), float const*) dec_group.cc:decltype (Zero((hwy::N_SCALAR::Simd<int, 1ul, 0>::Rebind<float>)())) jxl::N_SCALAR::(anonymous namespace)::AdjustQuantBias<hwy::N_SCALAR::Simd<int, 1ul, 0> >(hwy::N_SCALAR::Simd<int, 1ul, 0>, unsigned long, decltype (Zero((hwy::N_SCALAR::Simd<int, 1ul, 0>)())), float const*) Line | Count | Source | 36 | 9.29M | const float* HWY_RESTRICT biases) { | 37 | 9.29M | const Rebind<float, DI> df; | 38 | | | 39 | 9.29M | const auto quant = ConvertTo(df, quant_i); | 40 | | | 41 | | // Compare |quant|, keep sign bit for negating result. | 42 | 9.29M | const auto kSign = BitCast(df, Set(di, INT32_MIN)); | 43 | 9.29M | const auto sign = And(quant, kSign); // TODO(janwas): = abs ^ orig | 44 | 9.29M | 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 | 9.29M | const auto is_01 = Lt(abs_quant, Set(df, 1.125f)); | 56 | 9.29M | const auto not_0 = Gt(abs_quant, Zero(df)); | 57 | | | 58 | | // Bitwise logic is faster than quant * biases[c]. | 59 | 9.29M | const auto one_bias = IfThenElseZero(not_0, Xor(Set(df, biases[c]), sign)); | 60 | | | 61 | | // About 2E-5 worse than ReciprocalNR or division. | 62 | 9.29M | const auto bias = | 63 | 9.29M | NegMulAdd(Set(df, biases[3]), ApproximateReciprocal(quant), quant); | 64 | | | 65 | 9.29M | return IfThenElse(is_01, one_bias, bias); | 66 | 9.29M | } |
|
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_ |