Skip to content
Open
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
384 changes: 362 additions & 22 deletions cpp/src/arrow/sparse_tensor.cc

Large diffs are not rendered by default.

4 changes: 4 additions & 0 deletions cpp/src/arrow/sparse_tensor.h
Original file line number Diff line number Diff line change
Expand Up @@ -508,6 +508,10 @@ class ARROW_EXPORT SparseTensor {
return ToTensor(default_memory_pool());
}

/// \brief Check whether the sparse tensor is valid and is the
/// correct compressed form of the given tensor.
Status Validate(const Tensor& tensor) const;

protected:
// Constructor with all attributes
SparseTensor(const std::shared_ptr<DataType>& type, const std::shared_ptr<Buffer>& data,
Expand Down
349 changes: 344 additions & 5 deletions cpp/src/arrow/sparse_tensor_test.cc

Large diffs are not rendered by default.

12 changes: 7 additions & 5 deletions cpp/src/arrow/tensor.cc
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
#include "arrow/util/checked_cast.h"
#include "arrow/util/int_util_overflow.h"
#include "arrow/util/logging_internal.h"
#include "arrow/util/macros.h"
#include "arrow/util/unreachable.h"
#include "arrow/visit_type_inline.h"

Expand Down Expand Up @@ -85,7 +86,7 @@ Status ComputeColumnMajorStrides(const FixedWidthType& type,
if (!shape.empty() && shape.back() > 0) {
total = byte_width;
for (size_t i = 0; i < ndim - 1; ++i) {
if (internal::MultiplyWithOverflow(total, shape[i], &total)) {
if (ARROW_PREDICT_FALSE(internal::MultiplyWithOverflow(total, shape[i], &total))) {
return Status::Invalid(
"Column-major strides computed from shape would not fit in 64-bit "
"integer");
Expand Down Expand Up @@ -485,13 +486,14 @@ namespace {
template <typename TYPE>
int64_t StridedTensorCountNonZero(int dim_index, int64_t offset, const Tensor& tensor) {
using c_type = typename TYPE::c_type;
const c_type zero = c_type(0);
int64_t nnz = 0;
if (dim_index == tensor.ndim() - 1) {
for (int64_t i = 0; i < tensor.shape()[dim_index]; ++i) {
const auto* ptr = tensor.raw_data() + offset + i * tensor.strides()[dim_index];
auto& elem = *reinterpret_cast<const c_type*>(ptr);
if (elem != zero) ++nnz;
auto elem = *reinterpret_cast<const c_type*>(ptr);
if (internal::is_not_zero<TYPE>(elem)) {
++nnz;
}
}
return nnz;
}
Expand All @@ -507,7 +509,7 @@ int64_t ContiguousTensorCountNonZero(const Tensor& tensor) {
using c_type = typename TYPE::c_type;
auto* data = reinterpret_cast<const c_type*>(tensor.raw_data());
return std::count_if(data, data + tensor.size(),
[](const c_type& x) { return x != 0; });
[](const c_type& x) { return internal::is_not_zero<TYPE>(x); });
}

template <typename TYPE>
Expand Down
7 changes: 7 additions & 0 deletions cpp/src/arrow/tensor.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,13 @@ constexpr bool is_tensor_supported(Type::type type_id) {

namespace internal {

// TODO(GH-47578): Enable HalfFloatType
template <typename ValueDataType>
inline bool is_not_zero(typename ValueDataType::c_type value) {
typename ValueDataType::c_type zero = 0;
return value != zero;
Comment thread
andishgar marked this conversation as resolved.
}

Comment thread
andishgar marked this conversation as resolved.
ARROW_EXPORT
Status ComputeRowMajorStrides(const FixedWidthType& type,
const std::vector<int64_t>& shape,
Expand Down
67 changes: 0 additions & 67 deletions cpp/src/arrow/tensor/converter.h

This file was deleted.

111 changes: 43 additions & 68 deletions cpp/src/arrow/tensor/converter_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,72 +17,47 @@

#pragma once

#include "arrow/tensor/converter.h"
#include "arrow/sparse_tensor.h" // IWYU pragma: export

#define DISPATCH(ACTION, index_elsize, value_elsize, ...) \
switch (index_elsize) { \
case 1: \
switch (value_elsize) { \
case 1: \
ACTION(uint8_t, uint8_t, __VA_ARGS__); \
break; \
case 2: \
ACTION(uint8_t, uint16_t, __VA_ARGS__); \
break; \
case 4: \
ACTION(uint8_t, uint32_t, __VA_ARGS__); \
break; \
case 8: \
ACTION(uint8_t, uint64_t, __VA_ARGS__); \
break; \
} \
break; \
case 2: \
switch (value_elsize) { \
case 1: \
ACTION(uint16_t, uint8_t, __VA_ARGS__); \
break; \
case 2: \
ACTION(uint16_t, uint16_t, __VA_ARGS__); \
break; \
case 4: \
ACTION(uint16_t, uint32_t, __VA_ARGS__); \
break; \
case 8: \
ACTION(uint16_t, uint64_t, __VA_ARGS__); \
break; \
} \
break; \
case 4: \
switch (value_elsize) { \
case 1: \
ACTION(uint32_t, uint8_t, __VA_ARGS__); \
break; \
case 2: \
ACTION(uint32_t, uint16_t, __VA_ARGS__); \
break; \
case 4: \
ACTION(uint32_t, uint32_t, __VA_ARGS__); \
break; \
case 8: \
ACTION(uint32_t, uint64_t, __VA_ARGS__); \
break; \
} \
break; \
case 8: \
switch (value_elsize) { \
case 1: \
ACTION(int64_t, uint8_t, __VA_ARGS__); \
break; \
case 2: \
ACTION(int64_t, uint16_t, __VA_ARGS__); \
break; \
case 4: \
ACTION(int64_t, uint32_t, __VA_ARGS__); \
break; \
case 8: \
ACTION(int64_t, uint64_t, __VA_ARGS__); \
break; \
} \
break; \
}
#include <memory>

namespace arrow::internal {

struct SparseTensorConverterMixin {
static void AssignIndex(uint8_t* indices, int64_t val, const int elsize);

static int64_t GetIndexValue(const uint8_t* value_ptr, const int elsize);
};

Status MakeSparseCOOTensorFromTensor(const Tensor& tensor,
const std::shared_ptr<DataType>& index_value_type,
MemoryPool* pool,
std::shared_ptr<SparseIndex>* out_sparse_index,
std::shared_ptr<Buffer>* out_data);

Status MakeSparseCSXMatrixFromTensor(SparseMatrixCompressedAxis axis,
const Tensor& tensor,
const std::shared_ptr<DataType>& index_value_type,
MemoryPool* pool,
std::shared_ptr<SparseIndex>* out_sparse_index,
std::shared_ptr<Buffer>* out_data);

Status MakeSparseCSFTensorFromTensor(const Tensor& tensor,
const std::shared_ptr<DataType>& index_value_type,
MemoryPool* pool,
std::shared_ptr<SparseIndex>* out_sparse_index,
std::shared_ptr<Buffer>* out_data);

Result<std::shared_ptr<Tensor>> MakeTensorFromSparseCOOTensor(
MemoryPool* pool, const SparseCOOTensor* sparse_tensor);

Result<std::shared_ptr<Tensor>> MakeTensorFromSparseCSRMatrix(
MemoryPool* pool, const SparseCSRMatrix* sparse_tensor);

Result<std::shared_ptr<Tensor>> MakeTensorFromSparseCSCMatrix(
MemoryPool* pool, const SparseCSCMatrix* sparse_tensor);

Result<std::shared_ptr<Tensor>> MakeTensorFromSparseCSFTensor(
MemoryPool* pool, const SparseCSFTensor* sparse_tensor);

} // namespace arrow::internal
Loading
Loading