Skip to content
Closed
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
51 changes: 21 additions & 30 deletions cpp/src/arrow/compare.cc
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
#include "arrow/tensor.h"
#include "arrow/type.h"
#include "arrow/type_traits.h"
#include "arrow/util/bit_block_counter.h"
#include "arrow/util/bit_run_reader.h"
#include "arrow/util/bit_util.h"
#include "arrow/util/bitmap_ops.h"
#include "arrow/util/bitmap_reader.h"
Expand All @@ -54,7 +54,6 @@ using internal::BitmapEquals;
using internal::BitmapReader;
using internal::BitmapUInt64Reader;
using internal::checked_cast;
using internal::OptionalBitBlockCounter;
using internal::OptionalBitmapEquals;

// ----------------------------------------------------------------------
Expand Down Expand Up @@ -412,41 +411,33 @@ class RangeDataEqualsImpl {

template <typename CompareValues>
void VisitValues(CompareValues&& compare_values) {
internal::VisitBitBlocksVoid(
left_.buffers[0], left_.offset + left_start_idx_, range_length_,
[&](int64_t position) { result_ &= compare_values(position); }, []() {});
internal::VisitSetBitRunsVoid(left_.buffers[0], left_.offset + left_start_idx_,
range_length_, [&](int64_t position, int64_t length) {
for (int64_t i = 0; i < length; ++i) {
result_ &= compare_values(position + i);
}
});
}

// Visit and compare runs of non-null values
template <typename CompareRuns>
void VisitValidRuns(CompareRuns&& compare_runs) {
int64_t i = 0;
const uint8_t* left_null_bitmap = left_.GetValues<uint8_t>(0, 0);
// TODO may use BitRunReader or equivalent?
OptionalBitBlockCounter bit_blocks(left_null_bitmap, left_.offset + left_start_idx_,
range_length_);

while (result_ && i < range_length_) {
const auto block = bit_blocks.NextBlock();
if (block.AllSet()) {
if (!compare_runs(i, block.length)) {
result_ = false;
return;
}
} else if (block.NoneSet()) {
// Nothing to do
} else {
// Compare non-null values one at a time
for (int64_t j = i; j < i + block.length; ++j) {
if (BitUtil::GetBit(left_null_bitmap, left_.offset + left_start_idx_ + j)) {
if (!compare_runs(j, 1)) {
result_ = false;
return;
}
}
}
if (left_null_bitmap == nullptr) {
result_ = compare_runs(0, range_length_);
return;
}
internal::SetBitRunReader reader(left_null_bitmap, left_.offset + left_start_idx_,
range_length_);
while (true) {
const auto run = reader.NextRun();
if (run.length == 0) {
return;
}
if (!compare_runs(run.position, run.length)) {
result_ = false;
return;
}
i += block.length;
}
}

Expand Down
86 changes: 61 additions & 25 deletions cpp/src/arrow/compute/kernels/aggregate_mode.cc
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@
#include "arrow/compute/api_aggregate.h"
#include "arrow/compute/kernels/aggregate_internal.h"
#include "arrow/compute/kernels/common.h"
#include "arrow/type_traits.h"
#include "arrow/util/bit_run_reader.h"

namespace arrow {
namespace compute {
Expand All @@ -41,19 +43,22 @@ template <typename ArrayType, typename CType = typename ArrayType::TypeClass::c_
enable_if_t<std::is_floating_point<CType>::value, CounterMap<CType>> CountValuesByMap(
const ArrayType& array, int64_t& nan_count) {
CounterMap<CType> value_counts_map;
const ArrayData& data = *array.data();
const CType* values = data.GetValues<CType>(1);

nan_count = 0;
if (array.length() > array.null_count()) {
VisitArrayDataInline<typename ArrayType::TypeClass>(
*array.data(),
[&](CType value) {
if (std::isnan(value)) {
++nan_count;
} else {
++value_counts_map[value];
}
},
[]() {});
arrow::internal::VisitSetBitRunsVoid(data.buffers[0], data.offset, data.length,
[&](int64_t pos, int64_t len) {
for (int64_t i = 0; i < len; ++i) {
const auto value = values[pos + i];
if (std::isnan(value)) {
++nan_count;
} else {
++value_counts_map[value];
}
}
});
}

return value_counts_map;
Expand All @@ -64,25 +69,37 @@ template <typename ArrayType, typename CType = typename ArrayType::TypeClass::c_
enable_if_t<!std::is_floating_point<CType>::value, CounterMap<CType>> CountValuesByMap(
const ArrayType& array) {
CounterMap<CType> value_counts_map;
const ArrayData& data = *array.data();
const CType* values = data.GetValues<CType>(1);

if (array.length() > array.null_count()) {
VisitArrayDataInline<typename ArrayType::TypeClass>(
*array.data(), [&](CType value) { ++value_counts_map[value]; }, []() {});
arrow::internal::VisitSetBitRunsVoid(data.buffers[0], data.offset, data.length,
[&](int64_t pos, int64_t len) {
for (int64_t i = 0; i < len; ++i) {
++value_counts_map[values[pos + i]];
}
});
}

return value_counts_map;
}

// vector based counter for bool/int8 or integers with small value range
// vector based counter for int8 or integers with small value range
template <typename ArrayType, typename CType = typename ArrayType::TypeClass::c_type>
CounterMap<CType> CountValuesByVector(const ArrayType& array, CType min, CType max) {
const int range = static_cast<int>(max - min);
DCHECK(range >= 0 && range < 64 * 1024 * 1024);
const ArrayData& data = *array.data();
const CType* values = data.GetValues<CType>(1);

std::vector<int64_t> value_counts_vector(range + 1);
if (array.length() > array.null_count()) {
VisitArrayDataInline<typename ArrayType::TypeClass>(
*array.data(), [&](CType value) { ++value_counts_vector[value - min]; }, []() {});
arrow::internal::VisitSetBitRunsVoid(data.buffers[0], data.offset, data.length,
[&](int64_t pos, int64_t len) {
for (int64_t i = 0; i < len; ++i) {
++value_counts_vector[values[pos + i] - min];
}
});
}

// Transfer value counts to a map to be consistent with other chunks
Expand All @@ -104,18 +121,21 @@ CounterMap<CType> CountValuesByMapOrVector(const ArrayType& array) {
// see https://issues.apache.org/jira/browse/ARROW-9873
static constexpr int kMinArraySize = 8192 / sizeof(CType);
static constexpr int kMaxValueRange = 16384;
const ArrayData& data = *array.data();
const CType* values = data.GetValues<CType>(1);

if ((array.length() - array.null_count()) >= kMinArraySize) {
CType min = std::numeric_limits<CType>::max();
CType max = std::numeric_limits<CType>::min();

VisitArrayDataInline<typename ArrayType::TypeClass>(
*array.data(),
[&](CType value) {
min = std::min(min, value);
max = std::max(max, value);
},
[]() {});
arrow::internal::VisitSetBitRunsVoid(data.buffers[0], data.offset, data.length,
[&](int64_t pos, int64_t len) {
for (int64_t i = 0; i < len; ++i) {
const auto value = values[pos + i];
min = std::min(min, value);
max = std::max(max, value);
}
});

if (static_cast<uint64_t>(max) - static_cast<uint64_t>(min) <= kMaxValueRange) {
return CountValuesByVector(array, min, max);
Expand All @@ -124,9 +144,24 @@ CounterMap<CType> CountValuesByMapOrVector(const ArrayType& array) {
return CountValuesByMap(array);
}

// bool, int8
// bool
template <typename ArrayType, typename CType = typename ArrayType::TypeClass::c_type>
enable_if_t<std::is_integral<CType>::value && sizeof(CType) == 1, CounterMap<CType>>
enable_if_t<is_boolean_type<typename ArrayType::TypeClass>::value, CounterMap<CType>>
CountValues(const ArrayType& array, int64_t& nan_count) {
// we need just count ones and zeros
CounterMap<CType> map;
if (array.length() > array.null_count()) {
map[true] = array.true_count();
map[false] = array.length() - array.null_count() - map[true];
}
nan_count = 0;
return map;
}

// int8
template <typename ArrayType, typename CType = typename ArrayType::TypeClass::c_type>
enable_if_t<is_integer_type<typename ArrayType::TypeClass>::value && sizeof(CType) == 1,
CounterMap<CType>>
CountValues(const ArrayType& array, int64_t& nan_count) {
using Limits = std::numeric_limits<CType>;
nan_count = 0;
Expand All @@ -135,7 +170,8 @@ CountValues(const ArrayType& array, int64_t& nan_count) {

// int16/32/64
template <typename ArrayType, typename CType = typename ArrayType::TypeClass::c_type>
enable_if_t<std::is_integral<CType>::value && (sizeof(CType) > 1), CounterMap<CType>>
enable_if_t<is_integer_type<typename ArrayType::TypeClass>::value && (sizeof(CType) > 1),
CounterMap<CType>>
CountValues(const ArrayType& array, int64_t& nan_count) {
nan_count = 0;
return CountValuesByMapOrVector(array);
Expand Down
44 changes: 27 additions & 17 deletions cpp/src/arrow/compute/kernels/aggregate_var_std.cc
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include "arrow/compute/api_aggregate.h"
#include "arrow/compute/kernels/aggregate_internal.h"
#include "arrow/compute/kernels/common.h"
#include "arrow/util/bit_run_reader.h"
#include "arrow/util/int128_internal.h"

namespace arrow {
Expand Down Expand Up @@ -49,18 +50,24 @@ struct VarStdState {
using SumType =
typename std::conditional<is_floating_type<T>::value, double, int128_t>::type;
SumType sum = 0;
VisitArrayDataInline<ArrowType>(
*array.data(), [&sum](CType value) { sum += static_cast<SumType>(value); },
[]() {});

const ArrayData& data = *array.data();
const CType* values = data.GetValues<CType>(1);
arrow::internal::VisitSetBitRunsVoid(data.buffers[0], data.offset, data.length,
[&](int64_t pos, int64_t len) {
for (int64_t i = 0; i < len; ++i) {
sum += static_cast<SumType>(values[pos + i]);
}
});

double mean = static_cast<double>(sum) / count, m2 = 0;
VisitArrayDataInline<ArrowType>(
*array.data(),
[mean, &m2](CType value) {
double v = static_cast<double>(value);
m2 += (v - mean) * (v - mean);
},
[]() {});
arrow::internal::VisitSetBitRunsVoid(
data.buffers[0], data.offset, data.length, [&](int64_t pos, int64_t len) {
for (int64_t i = 0; i < len; ++i) {
const double v = static_cast<double>(values[pos + i]);
m2 += (v - mean) * (v - mean);
}
});

this->count = count;
this->mean = mean;
Expand Down Expand Up @@ -89,13 +96,16 @@ struct VarStdState {
if (count > 0) {
int64_t sum = 0;
int128_t square_sum = 0;
VisitArrayDataInline<ArrowType>(
*slice->data(),
[&sum, &square_sum](CType value) {
sum += value;
square_sum += static_cast<uint64_t>(value) * value;
},
[]() {});
const ArrayData& data = *slice->data();
const CType* values = data.GetValues<CType>(1);
arrow::internal::VisitSetBitRunsVoid(
data.buffers[0], data.offset, data.length, [&](int64_t pos, int64_t len) {
for (int64_t i = 0; i < len; ++i) {
const auto value = values[pos + i];
sum += value;
square_sum += static_cast<uint64_t>(value) * value;
}
});

const double mean = static_cast<double>(sum) / count;
// calculate m2 = square_sum - sum * sum / count
Expand Down
Loading