diff mupdf-source/thirdparty/zxing-cpp/core/src/BitHacks.h @ 2:b50eed0cc0ef upstream

ADD: MuPDF v1.26.7: the MuPDF source as downloaded by a default build of PyMuPDF 1.26.4. The directory name has changed: no version number in the expanded directory now.
author Franz Glasner <fzglas.hg@dom66.de>
date Mon, 15 Sep 2025 11:43:07 +0200
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mupdf-source/thirdparty/zxing-cpp/core/src/BitHacks.h	Mon Sep 15 11:43:07 2025 +0200
@@ -0,0 +1,210 @@
+/*
+* Copyright 2016 Huy Cuong Nguyen
+* Copyright 2017 Axel Waggershauser
+*/
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include <cassert>
+#include <cstdint>
+#include <cstring>
+#include <vector>
+
+// MSVC has the <bit> header but then warns about including it.
+// We check for _MSVC_LANG here as well, so client code is depending on /Zc:__cplusplus
+#if __has_include(<bit>) && (__cplusplus > 201703L || (defined(_MSVC_LANG) && _MSVC_LANG > 201703L))
+#include <bit>
+#if __cplusplus > 201703L && defined(__ANDROID__) // NDK 25.1.8937393 has the implementation but fails to advertise it
+#define __cpp_lib_bitops 201907L
+#endif
+#elif defined(_MSC_VER)
+// accoring to #863 MSVC defines __cpp_lib_bitops even when <bit> it not included and bitops are not available
+#undef __cpp_lib_bitops
+#endif
+
+#if defined(__clang__) || defined(__GNUC__)
+#define ZX_HAS_GCC_BUILTINS
+#elif defined(_MSC_VER) && !defined(_M_ARM) && !defined(_M_ARM64)
+#include <intrin.h>
+#define ZX_HAS_MSC_BUILTINS
+#endif
+
+namespace ZXing::BitHacks {
+
+/**
+* The code below is taken from https://graphics.stanford.edu/~seander/bithacks.html
+* All credits go to Sean Eron Anderson and other authors mentioned in that page.
+*/
+
+/// <summary>
+/// Compute the number of zero bits on the left.
+/// </summary>
+template<typename T, typename = std::enable_if_t<std::is_integral_v<T>>>
+inline int NumberOfLeadingZeros(T x)
+{
+#ifdef __cpp_lib_bitops
+	return std::countl_zero(static_cast<std::make_unsigned_t<T>>(x));
+#else
+	if constexpr (sizeof(x) <= 4) {
+		static_assert(sizeof(x) == 4, "NumberOfLeadingZeros not implemented for 8 and 16 bit ints.");
+		if (x == 0)
+			return 32;
+#ifdef ZX_HAS_GCC_BUILTINS
+		return __builtin_clz(x);
+#elif defined(ZX_HAS_MSC_BUILTINS)
+		unsigned long where;
+		if (_BitScanReverse(&where, x))
+			return 31 - static_cast<int>(where);
+		return 32;
+#else
+		int n = 0;
+		if ((x & 0xFFFF0000) == 0) { n = n + 16; x = x << 16; }
+		if ((x & 0xFF000000) == 0) { n = n + 8; x = x << 8; }
+		if ((x & 0xF0000000) == 0) { n = n + 4; x = x << 4; }
+		if ((x & 0xC0000000) == 0) { n = n + 2; x = x << 2; }
+		if ((x & 0x80000000) == 0) { n = n + 1; }
+		return n;
+#endif
+	} else {
+		if (x == 0)
+			return 64;
+#ifdef ZX_HAS_GCC_BUILTINS
+		return __builtin_clzll(x);
+#else // including ZX_HAS_MSC_BUILTINS
+		int n = NumberOfLeadingZeros(static_cast<uint32_t>(x >> 32));
+		if (n == 32)
+			n += NumberOfLeadingZeros(static_cast<uint32_t>(x));
+		return n;
+#endif
+	}
+#endif
+}
+
+/// <summary>
+/// Compute the number of zero bits on the right.
+/// </summary>
+template<typename T, typename = std::enable_if_t<std::is_integral_v<T>>>
+inline int NumberOfTrailingZeros(T v)
+{
+#ifdef __cpp_lib_bitops
+	return std::countr_zero(static_cast<std::make_unsigned_t<T>>(v));
+#else
+	if constexpr (sizeof(v) <= 4) {
+		static_assert(sizeof(v) == 4, "NumberOfTrailingZeros not implemented for 8 and 16 bit ints.");
+#ifdef ZX_HAS_GCC_BUILTINS
+		return v == 0 ? 32 : __builtin_ctz(v);
+#elif defined(ZX_HAS_MSC_BUILTINS)
+		unsigned long where;
+		if (_BitScanForward(&where, v))
+			return static_cast<int>(where);
+		return 32;
+#else
+		int c = 32;
+		v &= -int32_t(v);
+		if (v) c--;
+		if (v & 0x0000FFFF) c -= 16;
+		if (v & 0x00FF00FF) c -= 8;
+		if (v & 0x0F0F0F0F) c -= 4;
+		if (v & 0x33333333) c -= 2;
+		if (v & 0x55555555) c -= 1;
+		return c;
+#endif
+	} else {
+#ifdef ZX_HAS_GCC_BUILTINS
+		return v == 0 ? 64 : __builtin_ctzll(v);
+#else // including ZX_HAS_MSC_BUILTINS
+		int n = NumberOfTrailingZeros(static_cast<uint32_t>(v));
+		if (n == 32)
+			n += NumberOfTrailingZeros(static_cast<uint32_t>(v >> 32));
+		return n;
+#endif
+	}
+#endif
+}
+
+inline uint32_t Reverse(uint32_t v)
+{
+#if 0
+	return __builtin_bitreverse32(v);
+#else
+	v = ((v >> 1) & 0x55555555) | ((v & 0x55555555) << 1);
+	// swap consecutive pairs
+	v = ((v >> 2) & 0x33333333) | ((v & 0x33333333) << 2);
+	// swap nibbles ...
+	v = ((v >> 4) & 0x0F0F0F0F) | ((v & 0x0F0F0F0F) << 4);
+	// swap bytes
+	v = ((v >> 8) & 0x00FF00FF) | ((v & 0x00FF00FF) << 8);
+	// swap 2-byte long pairs
+	v = (v >> 16) | (v << 16);
+	return v;
+#endif
+}
+
+inline int CountBitsSet(uint32_t v)
+{
+#ifdef __cpp_lib_bitops
+	return std::popcount(v);
+#elif defined(ZX_HAS_GCC_BUILTINS)
+	return __builtin_popcount(v);
+#else
+	v = v - ((v >> 1) & 0x55555555);							// reuse input as temporary
+	v = (v & 0x33333333) + ((v >> 2) & 0x33333333);				// temp
+	return (((v + (v >> 4)) & 0xF0F0F0F) * 0x1010101) >> 24;	// count
+#endif
+}
+
+// this is the same as log base 2 of v
+inline int HighestBitSet(uint32_t v)
+{
+	return 31 - NumberOfLeadingZeros(v);
+}
+
+// shift a whole array of bits by offset bits to the right (thinking of the array as a contiguous stream of bits
+// starting with the LSB of the first int and ending with the MSB of the last int, this is actually a left shift)
+template <typename T>
+void ShiftRight(std::vector<T>& bits, std::size_t offset)
+{
+	assert(offset < sizeof(T) * 8);
+
+	if (offset == 0 || bits.empty())
+		return;
+
+	std::size_t leftOffset = sizeof(T) * 8 - offset;
+	for (std::size_t i = 0; i < bits.size() - 1; ++i) {
+		bits[i] = (bits[i] >> offset) | (bits[i + 1] << leftOffset);
+	}
+	bits.back() >>= offset;
+}
+
+// reverse a whole array of bits. padding is the number of 'dummy' bits at the end of the array
+template <typename T>
+void Reverse(std::vector<T>& bits, std::size_t padding)
+{
+	static_assert(sizeof(T) == sizeof(uint32_t), "Reverse only implemented for 32 bit types");
+
+	// reverse all int's first (reversing the ints in the array and the bits in the ints at the same time)
+	auto first = bits.begin(), last = bits.end();
+	for (; first < --last; ++first) {
+		auto t = *first;
+		*first = BitHacks::Reverse(*last);
+		*last = BitHacks::Reverse(t);
+	}
+	if (first == last)
+		*last = BitHacks::Reverse(*last);
+
+	// now correct the int's if the bit size isn't a multiple of 32
+	ShiftRight(bits, padding);
+}
+
+// use to avoid "load of misaligned address" when using a simple type cast
+template <typename T>
+T LoadU(const void* ptr)
+{
+	static_assert(std::is_integral<T>::value, "T must be an integer");
+	T res;
+	memcpy(&res, ptr, sizeof(T));
+	return res;
+}
+
+} // namespace ZXing::BitHacks