summaryrefslogtreecommitdiffstats
path: root/third_party/jpeg-xl/lib/jxl/field_encodings.h
blob: 613e8fad334d48058220559e2a21d26cb69bd82d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
// 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_FIELD_ENCODINGS_H_
#define LIB_JXL_FIELD_ENCODINGS_H_

// Constants needed to encode/decode fields; avoids including the full fields.h.

#include <stddef.h>
#include <stdint.h>

#include <hwy/base.h>
#include <vector>

#include "lib/jxl/base/bits.h"
#include "lib/jxl/base/status.h"

namespace jxl {

// Macro to define the Fields' derived class Name when compiling with debug
// names.
#if JXL_IS_DEBUG_BUILD
#define JXL_FIELDS_NAME(X) \
  const char* Name() const override { return #X; }
#else
#define JXL_FIELDS_NAME(X)
#endif  // JXL_IS_DEBUG_BUILD

class Visitor;
class Fields {
 public:
  virtual ~Fields() = default;
#if JXL_IS_DEBUG_BUILD
  virtual const char* Name() const = 0;
#endif  // JXL_IS_DEBUG_BUILD
  virtual Status VisitFields(Visitor* JXL_RESTRICT visitor) = 0;
};

// Distribution of U32 values for one particular selector. Represents either a
// power of two-sized range, or a single value. A separate type ensures this is
// only passed to the U32Enc ctor.
struct U32Distr {
  // No need to validate - all `d` are legitimate.
  constexpr explicit U32Distr(uint32_t d) : d(d) {}

  static constexpr uint32_t kDirect = 0x80000000u;

  constexpr bool IsDirect() const { return (d & kDirect) != 0; }

  // Only call if IsDirect().
  constexpr uint32_t Direct() const { return d & (kDirect - 1); }

  // Only call if !IsDirect().
  constexpr size_t ExtraBits() const { return (d & 0x1F) + 1; }
  uint32_t Offset() const { return (d >> 5) & 0x3FFFFFF; }

  uint32_t d;
};

// A direct-coded 31-bit value occupying 2 bits in the bitstream.
constexpr U32Distr Val(uint32_t value) {
  return U32Distr(value | U32Distr::kDirect);
}

// Value - `offset` will be signaled in `bits` extra bits.
constexpr U32Distr BitsOffset(uint32_t bits, uint32_t offset) {
  return U32Distr(((bits - 1) & 0x1F) + ((offset & 0x3FFFFFF) << 5));
}

// Value will be signaled in `bits` extra bits.
constexpr U32Distr Bits(uint32_t bits) { return BitsOffset(bits, 0); }

// See U32Coder documentation in fields.h.
class U32Enc {
 public:
  constexpr U32Enc(const U32Distr d0, const U32Distr d1, const U32Distr d2,
                   const U32Distr d3)
      : d_{d0, d1, d2, d3} {}

  // Returns the U32Distr at `selector` = 0..3, least-significant first.
  U32Distr GetDistr(const uint32_t selector) const {
    JXL_ASSERT(selector < 4);
    return d_[selector];
  }

 private:
  U32Distr d_[4];
};

// Returns bit with the given `index` (0 = least significant).
template <typename T>
static inline constexpr uint64_t MakeBit(T index) {
  return 1ULL << static_cast<uint32_t>(index);
}

// Returns vector of all possible values of an Enum type. Relies on each Enum
// providing an overload of EnumBits() that returns a bit array of its values,
// which implies values must be in [0, 64).
template <typename Enum>
std::vector<Enum> Values() {
  uint64_t bits = EnumBits(Enum());

  std::vector<Enum> values;
  values.reserve(hwy::PopCount(bits));

  // For each 1-bit in bits: add its index as value
  while (bits != 0) {
    const int index = Num0BitsBelowLS1Bit_Nonzero(bits);
    values.push_back(static_cast<Enum>(index));
    bits &= bits - 1;  // clear least-significant bit
  }
  return values;
}

// Returns true if value is one of Values<Enum>().
template <class Enum>
Status EnumValid(const Enum value) {
  if (static_cast<uint32_t>(value) >= 64) {
    return JXL_FAILURE("Value %u too large for %s\n",
                       static_cast<uint32_t>(value), EnumName(Enum()));
  }
  const uint64_t bit = MakeBit(value);
  if ((EnumBits(Enum()) & bit) == 0) {
    return JXL_FAILURE("Invalid value %u for %s\n",
                       static_cast<uint32_t>(value), EnumName(Enum()));
  }
  return true;
}

}  // namespace jxl

#endif  // LIB_JXL_FIELD_ENCODINGS_H_