blob: 2f6380c62e9be572257ffb14c7997326898f91d1 [file] [log] [blame]
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
#include <algorithm>
#include <cstdint>
#include <utility>
#include <vector>
#include <gtest/gtest.h>
#include "arrow/util/align_util.h"
namespace arrow {
namespace internal {
template <int64_t NBYTES>
void CheckBitmapWordAlign(const uint8_t* data, int64_t bit_offset, int64_t length,
BitmapWordAlignParams expected) {
auto p = BitmapWordAlign<static_cast<uint64_t>(NBYTES)>(data, bit_offset, length);
ASSERT_EQ(p.leading_bits, expected.leading_bits);
ASSERT_EQ(p.trailing_bits, expected.trailing_bits);
if (p.trailing_bits > 0) {
// Only relevant if trailing_bits > 0
ASSERT_EQ(p.trailing_bit_offset, expected.trailing_bit_offset);
}
ASSERT_EQ(p.aligned_bits, expected.aligned_bits);
ASSERT_EQ(p.aligned_words, expected.aligned_words);
if (p.aligned_bits > 0) {
// Only relevant if aligned_bits > 0
ASSERT_EQ(p.aligned_start, expected.aligned_start);
}
// Invariants
ASSERT_LT(p.leading_bits, NBYTES * 8);
ASSERT_LT(p.trailing_bits, NBYTES * 8);
ASSERT_EQ(p.leading_bits + p.aligned_bits + p.trailing_bits, length);
ASSERT_EQ(p.aligned_bits, NBYTES * 8 * p.aligned_words);
if (p.aligned_bits > 0) {
ASSERT_EQ(reinterpret_cast<size_t>(p.aligned_start) & (NBYTES - 1), 0);
}
if (p.trailing_bits > 0) {
ASSERT_EQ(p.trailing_bit_offset, bit_offset + p.leading_bits + p.aligned_bits);
ASSERT_EQ(p.trailing_bit_offset + p.trailing_bits, bit_offset + length);
}
}
TEST(BitmapWordAlign, AlignedDataStart) {
alignas(8) char buf[136];
// A 8-byte aligned pointer
const uint8_t* P = reinterpret_cast<const uint8_t*>(buf);
const uint8_t* A = P;
// {leading_bits, trailing_bits, trailing_bit_offset,
// aligned_start, aligned_bits, aligned_words}
CheckBitmapWordAlign<8>(P, 0, 0, {0, 0, 0, A, 0, 0});
CheckBitmapWordAlign<8>(P, 0, 13, {0, 13, 0, A, 0, 0});
CheckBitmapWordAlign<8>(P, 0, 63, {0, 63, 0, A, 0, 0});
CheckBitmapWordAlign<8>(P, 0, 64, {0, 0, 0, A, 64, 1});
CheckBitmapWordAlign<8>(P, 0, 73, {0, 9, 64, A, 64, 1});
CheckBitmapWordAlign<8>(P, 0, 191, {0, 63, 128, A, 128, 2});
CheckBitmapWordAlign<8>(P, 5, 0, {0, 0, 0, A, 0, 0});
CheckBitmapWordAlign<8>(P, 5, 13, {13, 0, 0, A, 0, 0});
CheckBitmapWordAlign<8>(P, 5, 59, {59, 0, 0, A, 0, 0});
CheckBitmapWordAlign<8>(P, 5, 60, {59, 1, 64, A, 0, 0});
CheckBitmapWordAlign<8>(P, 5, 64, {59, 5, 64, A, 0, 0});
CheckBitmapWordAlign<8>(P, 5, 122, {59, 63, 64, A, 0, 0});
CheckBitmapWordAlign<8>(P, 5, 123, {59, 0, 64, A + 8, 64, 1});
CheckBitmapWordAlign<8>(P, 5, 314, {59, 63, 256, A + 8, 192, 3});
CheckBitmapWordAlign<8>(P, 5, 315, {59, 0, 320, A + 8, 256, 4});
CheckBitmapWordAlign<8>(P, 63, 0, {0, 0, 0, A, 0, 0});
CheckBitmapWordAlign<8>(P, 63, 1, {1, 0, 0, A, 0, 0});
CheckBitmapWordAlign<8>(P, 63, 2, {1, 1, 64, A, 0, 0});
CheckBitmapWordAlign<8>(P, 63, 64, {1, 63, 64, A, 0, 0});
CheckBitmapWordAlign<8>(P, 63, 65, {1, 0, 128, A + 8, 64, 1});
CheckBitmapWordAlign<8>(P, 63, 128, {1, 63, 128, A + 8, 64, 1});
CheckBitmapWordAlign<8>(P, 63, 129, {1, 0, 192, A + 8, 128, 2});
CheckBitmapWordAlign<8>(P, 1024, 0, {0, 0, 0, A, 0, 0});
CheckBitmapWordAlign<8>(P, 1024, 130, {0, 2, 1152, A + 128, 128, 2});
CheckBitmapWordAlign<8>(P, 1025, 1, {1, 0, 0, A, 0, 0});
CheckBitmapWordAlign<8>(P, 1025, 63, {63, 0, 0, A, 0, 0});
CheckBitmapWordAlign<8>(P, 1025, 64, {63, 1, 1088, A, 0, 0});
CheckBitmapWordAlign<8>(P, 1025, 128, {63, 1, 1152, A + 136, 64, 1});
}
TEST(BitmapWordAlign, UnalignedDataStart) {
alignas(8) char buf[136];
const uint8_t* P = reinterpret_cast<const uint8_t*>(buf) + 1;
const uint8_t* A = P + 7;
// {leading_bits, trailing_bits, trailing_bit_offset,
// aligned_start, aligned_bits, aligned_words}
CheckBitmapWordAlign<8>(P, 0, 0, {0, 0, 0, A, 0, 0});
CheckBitmapWordAlign<8>(P, 0, 13, {13, 0, 0, A, 0, 0});
CheckBitmapWordAlign<8>(P, 0, 56, {56, 0, 0, A, 0, 0});
CheckBitmapWordAlign<8>(P, 0, 57, {56, 1, 56, A, 0, 0});
CheckBitmapWordAlign<8>(P, 0, 119, {56, 63, 56, A, 0, 0});
CheckBitmapWordAlign<8>(P, 0, 120, {56, 0, 120, A, 64, 1});
CheckBitmapWordAlign<8>(P, 0, 184, {56, 0, 184, A, 128, 2});
CheckBitmapWordAlign<8>(P, 0, 185, {56, 1, 184, A, 128, 2});
CheckBitmapWordAlign<8>(P, 55, 0, {0, 0, 0, A, 0, 0});
CheckBitmapWordAlign<8>(P, 55, 1, {1, 0, 0, A, 0, 0});
CheckBitmapWordAlign<8>(P, 55, 2, {1, 1, 56, A, 0, 0});
CheckBitmapWordAlign<8>(P, 55, 66, {1, 1, 120, A, 64, 1});
// (P + 56 bits) is 64-bit aligned
CheckBitmapWordAlign<8>(P, 56, 0, {0, 0, 0, A, 0, 0});
CheckBitmapWordAlign<8>(P, 56, 1, {0, 1, 56, A, 0, 0});
CheckBitmapWordAlign<8>(P, 56, 63, {0, 63, 56, A, 0, 0});
CheckBitmapWordAlign<8>(P, 56, 191, {0, 63, 184, A, 128, 2});
// (P + 1016 bits) is 64-bit aligned
CheckBitmapWordAlign<8>(P, 1016, 0, {0, 0, 0, A, 0, 0});
CheckBitmapWordAlign<8>(P, 1016, 5, {0, 5, 1016, A, 0, 0});
CheckBitmapWordAlign<8>(P, 1016, 63, {0, 63, 1016, A, 0, 0});
CheckBitmapWordAlign<8>(P, 1016, 64, {0, 0, 1080, A + 120, 64, 1});
CheckBitmapWordAlign<8>(P, 1016, 129, {0, 1, 1144, A + 120, 128, 2});
CheckBitmapWordAlign<8>(P, 1017, 0, {0, 0, 0, A, 0, 0});
CheckBitmapWordAlign<8>(P, 1017, 1, {1, 0, 0, A, 0, 0});
CheckBitmapWordAlign<8>(P, 1017, 63, {63, 0, 0, A, 0, 0});
CheckBitmapWordAlign<8>(P, 1017, 64, {63, 1, 1080, A, 0, 0});
CheckBitmapWordAlign<8>(P, 1017, 128, {63, 1, 1144, A + 128, 64, 1});
}
} // namespace internal
} // namespace arrow