RawSpeed
fast raw decoding library
Loading...
Searching...
No Matches
Bit.h
Go to the documentation of this file.
1/*
2 RawSpeed - RAW file decoder.
3
4 Copyright (C) 2009-2014 Klaus Post
5
6 This library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Lesser General Public
8 License as published by the Free Software Foundation; either
9 version 2 of the License, or (at your option) any later version.
10
11 This library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
15
16 You should have received a copy of the GNU Lesser General Public
17 License along with this library; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19*/
20
21#pragma once
22
23#include "rawspeedconfig.h"
24#include "adt/Casts.h"
25#include "adt/Invariant.h"
26#include <algorithm>
27#include <array>
28#include <bit>
29#include <climits>
30#include <concepts>
31#include <cstdint>
32#include <cstring>
33#include <type_traits>
34
35namespace rawspeed {
36
37// only works for positive values and zero
38template <typename T> constexpr bool RAWSPEED_READNONE isPowerOfTwo(T val) {
39 return (val & (~val + 1)) == val;
40}
41
42template <class T>
43constexpr unsigned RAWSPEED_READNONE bitwidth([[maybe_unused]] T unused = {}) {
44 return CHAR_BIT * sizeof(T);
45}
46
47template <class T>
48 requires std::unsigned_integral<T>
49unsigned numSignBits(const T v) {
50 using SignedT = std::make_signed_t<T>;
51 return static_cast<SignedT>(v) < 0 ? std::countl_one(v) : std::countl_zero(v);
52}
53
54template <class T>
55 requires(std::unsigned_integral<T> && bitwidth<T>() >= bitwidth<uint32_t>())
56unsigned numActiveBits(const T v) {
57 return bitwidth(v) - std::countl_zero(v);
58}
59
60template <class T>
61 requires(std::unsigned_integral<T> && bitwidth<T>() < bitwidth<uint32_t>())
62unsigned numActiveBits(const T v) {
63 return numActiveBits(static_cast<uint32_t>(v));
64}
65
66template <class T>
67 requires std::unsigned_integral<T>
68unsigned numSignificantBits(const T v) {
69 return bitwidth(v) - numSignBits(v) + 1;
70}
71
72// Clamps the given value to the range 0 .. 2^n-1, with n <= 16
73template <typename T>
74 requires std::is_arithmetic_v<T>
75constexpr auto RAWSPEED_READNONE clampBits(T value, unsigned int nBits) {
76 // We expect to produce uint16_t.
77 invariant(nBits <= 16);
78 // Check that the clamp is not a no-op. Not of uint16_t to 16 bits e.g.
79 // (Well, not really, if we are called from clampBits<signed>, it's ok..).
80 invariant(bitwidth<T>() > nBits); // If nBits >= bitwidth, then shift is UB.
81 const auto maxVal = implicit_cast<T>((T(1) << nBits) - T(1));
82 return implicit_cast<uint16_t>(std::clamp(value, T(0), maxVal));
83}
84
85template <typename T>
86 requires std::is_arithmetic_v<T>
87constexpr bool RAWSPEED_READNONE isIntN(T value, unsigned int nBits) {
88 invariant(nBits < bitwidth<T>() && "Check must not be tautological.");
89 using UnsignedT = std::make_unsigned_t<T>;
90 const auto highBits = static_cast<UnsignedT>(value) >> nBits;
91 return highBits == 0;
92}
93
94template <class T>
95 requires std::unsigned_integral<T>
96constexpr RAWSPEED_READNONE T extractLowBits(T value, unsigned nBits) {
97 // invariant(nBits >= 0);
98 invariant(nBits != 0); // Would result in out-of-bound shift.
99 invariant(nBits <= bitwidth<T>()); // No-op is fine.
100 unsigned numHighPaddingBits = bitwidth<T>() - nBits;
101 // invariant(numHighPaddingBits >= 0);
102 invariant(numHighPaddingBits < bitwidth<T>()); // Shift is in-bounds.
103 value <<= numHighPaddingBits;
104 value >>= numHighPaddingBits;
105 return value;
106}
107
108template <class T>
109 requires std::unsigned_integral<T>
110constexpr RAWSPEED_READNONE T extractLowBitsSafe(T value, unsigned nBits) {
111 // invariant(nBits >= 0);
112 invariant(nBits <= bitwidth<T>());
113 if (nBits == 0)
114 return 0;
115 return extractLowBits(value, nBits);
116}
117
118template <class T>
119 requires std::is_unsigned_v<T>
120constexpr RAWSPEED_READNONE T extractHighBits(
121 T value, unsigned nBits, unsigned effectiveBitwidth = bitwidth<T>()) {
122 invariant(effectiveBitwidth <= bitwidth<T>());
123 invariant(nBits <= effectiveBitwidth);
124 auto numLowBitsToSkip = effectiveBitwidth - nBits;
125 invariant(numLowBitsToSkip < bitwidth<T>());
126 return value >> numLowBitsToSkip;
127}
128
129template <typename T>
130 requires std::is_unsigned_v<T>
131constexpr typename std::make_signed_t<T>
132 RAWSPEED_READNONE signExtend(T value, unsigned int nBits) {
133 invariant(nBits != 0 && "Only valid for non-zero bit count.");
134 const T SpareSignBits = bitwidth<T>() - nBits;
135 using SignedT = std::make_signed_t<T>;
136 return static_cast<SignedT>(value << SpareSignBits) >> SpareSignBits;
137}
138
139template <class T>
140 requires std::same_as<T, uint8_t>
141T bitreverse(const T v) {
142#if __has_builtin(__builtin_bitreverse8)
143 return __builtin_bitreverse8(v);
144#endif
145 // Reverse the order of bits within each byte using a bit-twiddle trick.
146 // Three operation bit reversal from:
147 // https://graphics.stanford.edu/~seander/bithacks.html#ReverseByteWith64BitsDiv
148 return uint8_t((uint8_t(v) * 0x0202020202ULL & 0x010884422010ULL) % 1023);
149}
150
151#if __has_builtin(__builtin_bitreverse32)
152template <class T>
153 requires std::same_as<T, uint32_t>
154T bitreverse(const T v) {
155 return __builtin_bitreverse32(v);
156}
157#endif
158
159template <class T>
160 requires std::same_as<T, uint8_t>
161std::array<T, 4> bitreverse_each(std::array<T, 4> x) {
162#if !__has_builtin(__builtin_bitreverse32)
163 for (T& e : x)
164 e = bitreverse(e);
165#else
166 uint32_t tmp;
167 std::memcpy(&tmp, x.data(), sizeof(uint32_t));
168 tmp = bitreverse(tmp);
169 tmp = __builtin_bswap32(tmp);
170 std::memcpy(x.data(), &tmp, sizeof(uint32_t));
171#endif
172 return x;
173}
174
175} // namespace rawspeed
#define invariant(expr)
Definition Invariant.h:27
dim x
Definition Common.cpp:50
std::array< T, 4 > bitreverse_each(std::array< T, 4 > x)
Definition Bit.h:161
constexpr RAWSPEED_READNONE Ttgt implicit_cast(Tsrc value)
Definition Casts.h:32
constexpr RAWSPEED_READNONE T extractLowBitsSafe(T value, unsigned nBits)
Definition Bit.h:110
throw T(buf.data())
unsigned numSignificantBits(const T v)
Definition Bit.h:68
constexpr bool RAWSPEED_READNONE isIntN(T value, unsigned int nBits)
Definition Bit.h:87
T bitreverse(const T v)
Definition Bit.h:141
unsigned numActiveBits(const T v)
Definition Bit.h:56
constexpr bool RAWSPEED_READNONE isPowerOfTwo(T val)
Definition Bit.h:38
constexpr unsigned RAWSPEED_READNONE bitwidth(T unused={})
Definition Bit.h:43
constexpr std::make_signed_t< T > RAWSPEED_READNONE signExtend(T value, unsigned int nBits)
Definition Bit.h:132
unsigned numSignBits(const T v)
Definition Bit.h:49
constexpr RAWSPEED_READNONE T extractHighBits(T value, unsigned nBits, unsigned effectiveBitwidth=bitwidth< T >())
Definition Bit.h:120
constexpr RAWSPEED_READNONE T extractLowBits(T value, unsigned nBits)
Definition Bit.h:96
constexpr auto RAWSPEED_READNONE clampBits(T value, unsigned int nBits)
Definition Bit.h:75