blob: 8d5f9f4210af5bf6d9a9dbefb63348cd604a4225 [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 "gandiva/selection_vector.h"
#include <memory>
#include <sstream>
#include <utility>
#include <vector>
#include "arrow/util/bit_util.h"
#include "arrow/util/endian.h"
#include "gandiva/selection_vector_impl.h"
namespace gandiva {
constexpr SelectionVector::Mode SelectionVector::kAllModes[kNumModes];
Status SelectionVector::PopulateFromBitMap(const uint8_t* bitmap, int64_t bitmap_size,
int64_t max_bitmap_index) {
const uint64_t max_idx = static_cast<uint64_t>(max_bitmap_index);
ARROW_RETURN_IF(bitmap_size % 8, Status::Invalid("Bitmap size ", bitmap_size,
" must be aligned to 64-bit size"));
ARROW_RETURN_IF(max_bitmap_index < 0,
Status::Invalid("Max bitmap index must be positive"));
ARROW_RETURN_IF(
max_idx > GetMaxSupportedValue(),
Status::Invalid("max_bitmap_index ", max_idx, " must be <= maxSupportedValue ",
GetMaxSupportedValue(), " in selection vector"));
int64_t max_slots = GetMaxSlots();
// jump 8-bytes at a time, add the index corresponding to each valid bit to the
// the selection vector.
int64_t selection_idx = 0;
const uint64_t* bitmap_64 = reinterpret_cast<const uint64_t*>(bitmap);
for (int64_t bitmap_idx = 0; bitmap_idx < bitmap_size / 8; ++bitmap_idx) {
uint64_t current_word = arrow::bit_util::ToLittleEndian(bitmap_64[bitmap_idx]);
while (current_word != 0) {
#if defined(_MSC_VER)
# pragma warning(push)
# pragma warning(disable : 4146)
#endif
// MSVC warns about negating an unsigned type. We suppress it for now
uint64_t highest_only = current_word & -current_word;
#if defined(_MSC_VER)
# pragma warning(pop)
#endif
int pos_in_word = arrow::bit_util::CountTrailingZeros(highest_only);
int64_t pos_in_bitmap = bitmap_idx * 64 + pos_in_word;
if (pos_in_bitmap > max_bitmap_index) {
// the bitmap may be slightly larger for alignment/padding.
break;
}
ARROW_RETURN_IF(selection_idx >= max_slots,
Status::Invalid("selection vector has no remaining slots"));
SetIndex(selection_idx, pos_in_bitmap);
++selection_idx;
current_word ^= highest_only;
}
}
SetNumSlots(selection_idx);
return Status::OK();
}
Status SelectionVector::MakeInt16(int64_t max_slots,
std::shared_ptr<arrow::Buffer> buffer,
std::shared_ptr<SelectionVector>* selection_vector) {
ARROW_RETURN_NOT_OK(SelectionVectorInt16::ValidateBuffer(max_slots, buffer));
*selection_vector = std::make_shared<SelectionVectorInt16>(max_slots, buffer);
return Status::OK();
}
Status SelectionVector::MakeInt16(int64_t max_slots, arrow::MemoryPool* pool,
std::shared_ptr<SelectionVector>* selection_vector) {
std::shared_ptr<arrow::Buffer> buffer;
ARROW_RETURN_NOT_OK(SelectionVectorInt16::AllocateBuffer(max_slots, pool, &buffer));
*selection_vector = std::make_shared<SelectionVectorInt16>(max_slots, buffer);
return Status::OK();
}
Status SelectionVector::MakeImmutableInt16(
int64_t num_slots, std::shared_ptr<arrow::Buffer> buffer,
std::shared_ptr<SelectionVector>* selection_vector) {
*selection_vector =
std::make_shared<SelectionVectorInt16>(num_slots, num_slots, buffer);
return Status::OK();
}
Status SelectionVector::MakeInt32(int64_t max_slots,
std::shared_ptr<arrow::Buffer> buffer,
std::shared_ptr<SelectionVector>* selection_vector) {
ARROW_RETURN_NOT_OK(SelectionVectorInt32::ValidateBuffer(max_slots, buffer));
*selection_vector = std::make_shared<SelectionVectorInt32>(max_slots, buffer);
return Status::OK();
}
Status SelectionVector::MakeInt32(int64_t max_slots, arrow::MemoryPool* pool,
std::shared_ptr<SelectionVector>* selection_vector) {
std::shared_ptr<arrow::Buffer> buffer;
ARROW_RETURN_NOT_OK(SelectionVectorInt32::AllocateBuffer(max_slots, pool, &buffer));
*selection_vector = std::make_shared<SelectionVectorInt32>(max_slots, buffer);
return Status::OK();
}
Status SelectionVector::MakeImmutableInt32(
int64_t num_slots, std::shared_ptr<arrow::Buffer> buffer,
std::shared_ptr<SelectionVector>* selection_vector) {
*selection_vector =
std::make_shared<SelectionVectorInt32>(num_slots, num_slots, buffer);
return Status::OK();
}
Status SelectionVector::MakeInt64(int64_t max_slots,
std::shared_ptr<arrow::Buffer> buffer,
std::shared_ptr<SelectionVector>* selection_vector) {
ARROW_RETURN_NOT_OK(SelectionVectorInt64::ValidateBuffer(max_slots, buffer));
*selection_vector = std::make_shared<SelectionVectorInt64>(max_slots, buffer);
return Status::OK();
}
Status SelectionVector::MakeInt64(int64_t max_slots, arrow::MemoryPool* pool,
std::shared_ptr<SelectionVector>* selection_vector) {
std::shared_ptr<arrow::Buffer> buffer;
ARROW_RETURN_NOT_OK(SelectionVectorInt64::AllocateBuffer(max_slots, pool, &buffer));
*selection_vector = std::make_shared<SelectionVectorInt64>(max_slots, buffer);
return Status::OK();
}
template <typename C_TYPE, typename A_TYPE, SelectionVector::Mode mode>
Status SelectionVectorImpl<C_TYPE, A_TYPE, mode>::AllocateBuffer(
int64_t max_slots, arrow::MemoryPool* pool, std::shared_ptr<arrow::Buffer>* buffer) {
auto buffer_len = max_slots * sizeof(C_TYPE);
ARROW_ASSIGN_OR_RAISE(*buffer, arrow::AllocateBuffer(buffer_len, pool));
return Status::OK();
}
template <typename C_TYPE, typename A_TYPE, SelectionVector::Mode mode>
Status SelectionVectorImpl<C_TYPE, A_TYPE, mode>::ValidateBuffer(
int64_t max_slots, std::shared_ptr<arrow::Buffer> buffer) {
ARROW_RETURN_IF(!buffer->is_mutable(),
Status::Invalid("buffer for selection vector must be mutable"));
const int64_t min_len = max_slots * sizeof(C_TYPE);
ARROW_RETURN_IF(buffer->size() < min_len,
Status::Invalid("Buffer for selection vector is too small"));
return Status::OK();
}
} // namespace gandiva