summaryrefslogtreecommitdiffstats
path: root/third_party/jpeg-xl/lib/jxl/lehmer_code.h
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/jpeg-xl/lib/jxl/lehmer_code.h')
-rw-r--r--third_party/jpeg-xl/lib/jxl/lehmer_code.h102
1 files changed, 102 insertions, 0 deletions
diff --git a/third_party/jpeg-xl/lib/jxl/lehmer_code.h b/third_party/jpeg-xl/lib/jxl/lehmer_code.h
new file mode 100644
index 0000000000..dd1d21c6f7
--- /dev/null
+++ b/third_party/jpeg-xl/lib/jxl/lehmer_code.h
@@ -0,0 +1,102 @@
+// 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.
+
+#ifndef LIB_JXL_LEHMER_CODE_H_
+#define LIB_JXL_LEHMER_CODE_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include "lib/jxl/base/bits.h"
+#include "lib/jxl/base/compiler_specific.h"
+#include "lib/jxl/base/status.h"
+
+namespace jxl {
+
+// Permutation <=> factorial base representation (Lehmer code).
+
+using LehmerT = uint32_t;
+
+template <typename T>
+constexpr T ValueOfLowest1Bit(T t) {
+ return t & -t;
+}
+
+// Computes the Lehmer (factorial basis) code of permutation, an array of n
+// unique indices in [0..n), and stores it in code[0..len). N*logN time.
+// temp must have n + 1 elements but need not be initialized.
+template <typename PermutationT>
+void ComputeLehmerCode(const PermutationT* JXL_RESTRICT permutation,
+ uint32_t* JXL_RESTRICT temp, const size_t n,
+ LehmerT* JXL_RESTRICT code) {
+ for (size_t idx = 0; idx < n + 1; ++idx) temp[idx] = 0;
+
+ for (size_t idx = 0; idx < n; ++idx) {
+ const PermutationT s = permutation[idx];
+
+ // Compute sum in Fenwick tree
+ uint32_t penalty = 0;
+ uint32_t i = s + 1;
+ while (i != 0) {
+ penalty += temp[i];
+ i &= i - 1; // clear lowest bit
+ }
+ JXL_DASSERT(s >= penalty);
+ code[idx] = s - penalty;
+ i = s + 1;
+ // Add operation in Fenwick tree
+ while (i < n + 1) {
+ temp[i] += 1;
+ i += ValueOfLowest1Bit(i);
+ }
+ }
+}
+
+// Decodes the Lehmer code in code[0..n) into permutation[0..n).
+// temp must have 1 << CeilLog2(n) elements but need not be initialized.
+template <typename PermutationT>
+void DecodeLehmerCode(const LehmerT* JXL_RESTRICT code,
+ uint32_t* JXL_RESTRICT temp, size_t n,
+ PermutationT* JXL_RESTRICT permutation) {
+ JXL_DASSERT(n != 0);
+ const size_t log2n = CeilLog2Nonzero(n);
+ const size_t padded_n = 1ull << log2n;
+
+ for (size_t i = 0; i < padded_n; i++) {
+ const int32_t i1 = static_cast<int32_t>(i + 1);
+ temp[i] = static_cast<uint32_t>(ValueOfLowest1Bit(i1));
+ }
+
+ for (size_t i = 0; i < n; i++) {
+ JXL_DASSERT(code[i] + i < n);
+ uint32_t rank = code[i] + 1;
+
+ // Extract i-th unused element via implicit order-statistics tree.
+ size_t bit = padded_n;
+ size_t next = 0;
+ for (size_t i = 0; i <= log2n; i++) {
+ const size_t cand = next + bit;
+ JXL_DASSERT(cand >= 1);
+ bit >>= 1;
+ if (temp[cand - 1] < rank) {
+ next = cand;
+ rank -= temp[cand - 1];
+ }
+ }
+
+ permutation[i] = next;
+
+ // Mark as used
+ next += 1;
+ while (next <= padded_n) {
+ temp[next - 1] -= 1;
+ next += ValueOfLowest1Bit(next);
+ }
+ }
+}
+
+} // namespace jxl
+
+#endif // LIB_JXL_LEHMER_CODE_H_