Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 1 addition & 10 deletions cpp/src/arrow/util/align_util.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
#pragma once

#include <algorithm>
#include <bit>

#include "arrow/memory_pool.h"
#include "arrow/type_fwd.h"
Expand All @@ -44,16 +43,8 @@ struct BitmapWordAlignParams {
template <uint64_t ALIGN_IN_BYTES>
inline BitmapWordAlignParams BitmapWordAlign(const uint8_t* data, int64_t bit_offset,
int64_t length) {
// TODO: We can remove this condition once CRAN upgrades its macOS
// SDK from 11.3.
// __apple_build_version__ should be defined only on Apple clang
#if defined(__apple_build_version__) && !defined(__cpp_lib_bitops)
static_assert((ALIGN_IN_BYTES != 0) && ((ALIGN_IN_BYTES & (ALIGN_IN_BYTES - 1)) == 0),
static_assert(bit_util::HasSingleBit(ALIGN_IN_BYTES),
"ALIGN_IN_BYTES should be a positive power of two");
#else
static_assert(std::has_single_bit(ALIGN_IN_BYTES),
"ALIGN_IN_BYTES should be a positive power of two");
#endif
constexpr uint64_t ALIGN_IN_BITS = ALIGN_IN_BYTES * 8;

BitmapWordAlignParams p;
Expand Down
2 changes: 1 addition & 1 deletion cpp/src/arrow/util/alp/alp_codec.cc
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ Status ValidateEncodingPreset(const AlpEncodingPreset& preset) {
Status ValidateVectorSize(int32_t vector_size) {
constexpr int32_t kMin = 1 << AlpFormatConstants::kMinLogVectorSize;
constexpr int32_t kMax = 1 << AlpFormatConstants::kMaxLogVectorSize;
if (vector_size <= 0 || !std::has_single_bit(static_cast<uint32_t>(vector_size))) {
if (vector_size <= 0 || !bit_util::HasSingleBit(static_cast<uint32_t>(vector_size))) {
return Status::Invalid("ALP vector_size must be a positive power of 2, got ",
vector_size);
}
Expand Down
5 changes: 2 additions & 3 deletions cpp/src/arrow/util/alp/alp_compression.cc
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
#include "arrow/util/alp/alp_compression_internal.h"

#include <algorithm>
#include <bit>
#include <cmath>
#include <cstring>
#include <limits>
Expand Down Expand Up @@ -200,7 +199,7 @@ std::optional<int64_t> EstimateCompressedSizeBits(
const EncodedUnsigned delta = (static_cast<EncodedUnsigned>(max_encoded_value) -
static_cast<EncodedUnsigned>(min_encoded_value));

const int32_t estimated_bits_per_value = static_cast<int32_t>(std::bit_width(delta));
const int32_t estimated_bits_per_value = bit_util::BitWidth(delta);
int64_t estimated_compression_size =
static_cast<int64_t>(inputs.size()) * estimated_bits_per_value;
estimated_compression_size +=
Expand Down Expand Up @@ -445,7 +444,7 @@ typename AlpCompression<T>::BitPackingResult AlpCompression<T>::BitPackIntegers(
uint8_t bit_width = 0;

if (min_max_diff > 0) {
bit_width = static_cast<uint8_t>(std::bit_width(min_max_diff));
bit_width = static_cast<uint8_t>(bit_util::BitWidth(min_max_diff));
}
const int32_t bit_packed_size = static_cast<int32_t>(
bit_util::BytesForBits(bit_width * static_cast<int64_t>(for_deltas.size())));
Expand Down
37 changes: 29 additions & 8 deletions cpp/src/arrow/util/bit_util.h
Original file line number Diff line number Diff line change
Expand Up @@ -138,20 +138,41 @@ static inline uint64_t TrailingBits(uint64_t v, int num_bits) {
return (v << n) >> n;
}

// Returns ceil(log2(x)).
static inline int Log2(uint64_t x) {
// DCHECK_GT(x, 0);
// Returns the number of bits needed to represent x, i.e. std::bit_width(x).
//
// The libc++ in the macOS 11.3 SDK used by CRAN only has the pre-standard
// name std::log2p1. __apple_build_version__ should be defined only on Apple
// clang.
// TODO: We can remove this condition once CRAN upgrades its macOS SDK from 11.3.
template <typename T>
constexpr int BitWidth(T x) noexcept {
static_assert(std::is_unsigned_v<T>, "BitWidth requires an unsigned integer type");
#if defined(__apple_build_version__) && !defined(__cpp_lib_bitops)
return static_cast<int>(std::log2p1(x));
#else
return static_cast<int>(std::bit_width(x));
#endif
}

// TODO: We can remove this condition once CRAN upgrades its macOS
// SDK from 11.3.
// __apple_build_version__ should be defined only on Apple clang
// Returns true if x is a power of two, i.e. std::has_single_bit(x).
// See the note on BitWidth: the macOS 11.3 SDK only has the pre-standard
// name std::ispow2.
template <typename T>
constexpr bool HasSingleBit(T x) noexcept {
static_assert(std::is_unsigned_v<T>, "HasSingleBit requires an unsigned integer type");
#if defined(__apple_build_version__) && !defined(__cpp_lib_bitops)
return std::log2p1(x - 1);
return std::ispow2(x);
#else
return std::bit_width(x - 1);
return std::has_single_bit(x);
#endif
}

// Returns ceil(log2(x)).
static inline int Log2(uint64_t x) {
// DCHECK_GT(x, 0);
return BitWidth(x - 1);
}

//
// Utilities for reading and writing individual bits by their index
// in a memory area.
Expand Down
20 changes: 20 additions & 0 deletions cpp/src/arrow/util/bit_util_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1108,4 +1108,24 @@ TEST(BitUtil, CopyBits) {
0b01011010);
}

TEST(BitUtil, BitWidth) {
EXPECT_EQ(bit_util::BitWidth(uint8_t{0}), 0);
EXPECT_EQ(bit_util::BitWidth(uint8_t{1}), 1);
EXPECT_EQ(bit_util::BitWidth(uint32_t{1} << 20), 21);
EXPECT_EQ(bit_util::BitWidth((uint32_t{1} << 20) - 1), 20);
EXPECT_EQ(bit_util::BitWidth(std::numeric_limits<uint64_t>::max()), 64);
// constexpr-evaluable.
static_assert(bit_util::BitWidth(uint16_t{0x0100}) == 9);
}

TEST(BitUtil, HasSingleBit) {
EXPECT_FALSE(bit_util::HasSingleBit(uint8_t{0}));
EXPECT_TRUE(bit_util::HasSingleBit(uint8_t{1}));
EXPECT_TRUE(bit_util::HasSingleBit(uint32_t{1} << 20));
EXPECT_FALSE(bit_util::HasSingleBit((uint32_t{1} << 20) + 1));
EXPECT_FALSE(bit_util::HasSingleBit(std::numeric_limits<uint64_t>::max()));
// constexpr-evaluable.
static_assert(bit_util::HasSingleBit(uint16_t{0x0100}));
}
Comment on lines +1111 to +1129

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I feel like this is overtesting given that on most platforms are using the existing functions internally, so I'll trim this down


} // namespace arrow
10 changes: 1 addition & 9 deletions cpp/src/arrow/util/rle_encoding_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
// From Apache Impala (incubating) as of 2016-01-29

#include <algorithm>
#include <bit>
#include <cstdint>
#include <cstring>
#include <random>
Expand Down Expand Up @@ -942,14 +941,7 @@ TEST(BitRle, Random) {
}
parity = !parity;
}
// TODO: We can remove this condition once CRAN upgrades its macOS
// SDK from 11.3.
// __apple_build_version__ should be defined only on Apple clang
#if defined(__apple_build_version__) && !defined(__cpp_lib_bitops)
if (!CheckRoundTrip(values, std::log2p1(values.size()))) {
#else
if (!CheckRoundTrip(values, std::bit_width(values.size()))) {
#endif
if (!CheckRoundTrip(values, bit_util::BitWidth(values.size()))) {
FAIL() << "failing seed: " << seed;
}
}
Expand Down
12 changes: 2 additions & 10 deletions cpp/src/parquet/chunker_internal.cc
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@

#include "parquet/chunker_internal.h"

#include <bit>
#include <cstdint>
#include <iterator>
#include <string>
Expand Down Expand Up @@ -87,15 +86,8 @@ uint64_t CalculateMask(int64_t min_chunk_size, int64_t max_chunk_size, int norm_

// assuming that the gear hash has a uniform distribution, we can calculate the mask
// by taking the floor(log2(target_size))
// TODO: We can remove this condition once CRAN upgrades its macOS
// SDK from 11.3.
// __apple_build_version__ should be defined only on Apple clang
#if defined(__apple_build_version__) && !defined(__cpp_lib_bitops)
auto target_bits = std::log2p1(static_cast<uint64_t>(target_size));
#else
auto target_bits = std::bit_width(static_cast<uint64_t>(target_size));
#endif
int mask_bits = target_bits == 0 ? 0 : static_cast<int>(target_bits - 1);
auto target_bits = ::arrow::bit_util::BitWidth(static_cast<uint64_t>(target_size));
int mask_bits = target_bits == 0 ? 0 : target_bits - 1;

// a user defined `norm_level` can be used to adjust the mask size, hence the matching
// probability, by increasing the norm_level we increase the probability of matching
Expand Down
12 changes: 2 additions & 10 deletions cpp/src/parquet/encoder.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1261,16 +1261,8 @@ void DeltaBitPackEncoder<DType>::FlushBlock() {

// The minimum number of bits required to write any of values in deltas_ vector.
// See overflow comment above.
// TODO: We can remove this condition once CRAN upgrades its macOS
// SDK from 11.3.
// __apple_build_version__ should be defined only on Apple clang
#if defined(__apple_build_version__) && !defined(__cpp_lib_bitops)
const auto bit_width = bit_width_data[i] =
std::log2p1(static_cast<UT>(max_delta) - static_cast<UT>(min_delta));
#else
const auto bit_width = bit_width_data[i] =
std::bit_width(static_cast<UT>(max_delta) - static_cast<UT>(min_delta));
#endif
const auto bit_width = bit_width_data[i] = ::arrow::bit_util::BitWidth(
static_cast<UT>(max_delta) - static_cast<UT>(min_delta));

for (uint32_t j = start; j < start + values_current_mini_block; j++) {
// Convert delta to frame of reference. See overflow comment above.
Expand Down
Loading