// 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. #pragma once #include #include #include #include #include "arrow/buffer.h" #include "arrow/compare.h" #include "arrow/result.h" #include "arrow/status.h" #include "arrow/type.h" #include "arrow/type_traits.h" #include "arrow/util/macros.h" #include "arrow/util/visibility.h" namespace arrow { static inline bool is_tensor_supported(Type::type type_id) { switch (type_id) { case Type::UINT8: case Type::INT8: case Type::UINT16: case Type::INT16: case Type::UINT32: case Type::INT32: case Type::UINT64: case Type::INT64: case Type::HALF_FLOAT: case Type::FLOAT: case Type::DOUBLE: return true; default: break; } return false; } namespace internal { ARROW_EXPORT Status ComputeRowMajorStrides(const FixedWidthType& type, const std::vector& shape, std::vector* strides); ARROW_EXPORT Status ComputeColumnMajorStrides(const FixedWidthType& type, const std::vector& shape, std::vector* strides); ARROW_EXPORT bool IsTensorStridesContiguous(const std::shared_ptr& type, const std::vector& shape, const std::vector& strides); ARROW_EXPORT Status ValidateTensorParameters(const std::shared_ptr& type, const std::shared_ptr& data, const std::vector& shape, const std::vector& strides, const std::vector& dim_names); } // namespace internal class ARROW_EXPORT Tensor { public: /// \brief Create a Tensor with full parameters /// /// This factory function will return Status::Invalid when the parameters are /// inconsistent /// /// \param[in] type The data type of the tensor values /// \param[in] data The buffer of the tensor content /// \param[in] shape The shape of the tensor /// \param[in] strides The strides of the tensor /// (if this is empty, the data assumed to be row-major) /// \param[in] dim_names The names of the tensor dimensions static inline Result> Make( const std::shared_ptr& type, const std::shared_ptr& data, const std::vector& shape, const std::vector& strides = {}, const std::vector& dim_names = {}) { ARROW_RETURN_NOT_OK( internal::ValidateTensorParameters(type, data, shape, strides, dim_names)); return std::make_shared(type, data, shape, strides, dim_names); } virtual ~Tensor() = default; /// Constructor with no dimension names or strides, data assumed to be row-major Tensor(const std::shared_ptr& type, const std::shared_ptr& data, const std::vector& shape); /// Constructor with non-negative strides Tensor(const std::shared_ptr& type, const std::shared_ptr& data, const std::vector& shape, const std::vector& strides); /// Constructor with non-negative strides and dimension names Tensor(const std::shared_ptr& type, const std::shared_ptr& data, const std::vector& shape, const std::vector& strides, const std::vector& dim_names); std::shared_ptr type() const { return type_; } std::shared_ptr data() const { return data_; } const uint8_t* raw_data() const { return data_->data(); } uint8_t* raw_mutable_data() { return data_->mutable_data(); } const std::vector& shape() const { return shape_; } const std::vector& strides() const { return strides_; } int ndim() const { return static_cast(shape_.size()); } const std::vector& dim_names() const { return dim_names_; } const std::string& dim_name(int i) const; /// Total number of value cells in the tensor int64_t size() const; /// Return true if the underlying data buffer is mutable bool is_mutable() const { return data_->is_mutable(); } /// Either row major or column major bool is_contiguous() const; /// AKA "C order" bool is_row_major() const; /// AKA "Fortran order" bool is_column_major() const; Type::type type_id() const; bool Equals(const Tensor& other, const EqualOptions& = EqualOptions::Defaults()) const; /// Compute the number of non-zero values in the tensor Result CountNonZero() const; /// Return the offset of the given index on the given strides static int64_t CalculateValueOffset(const std::vector& strides, const std::vector& index) { const int64_t n = static_cast(index.size()); int64_t offset = 0; for (int64_t i = 0; i < n; ++i) { offset += index[i] * strides[i]; } return offset; } int64_t CalculateValueOffset(const std::vector& index) const { return Tensor::CalculateValueOffset(strides_, index); } /// Returns the value at the given index without data-type and bounds checks template const typename ValueType::c_type& Value(const std::vector& index) const { using c_type = typename ValueType::c_type; const int64_t offset = CalculateValueOffset(index); const c_type* ptr = reinterpret_cast(raw_data() + offset); return *ptr; } Status Validate() const { return internal::ValidateTensorParameters(type_, data_, shape_, strides_, dim_names_); } protected: Tensor() {} std::shared_ptr type_; std::shared_ptr data_; std::vector shape_; std::vector strides_; /// These names are optional std::vector dim_names_; template friend class SparseTensorImpl; private: ARROW_DISALLOW_COPY_AND_ASSIGN(Tensor); }; template class NumericTensor : public Tensor { public: using TypeClass = TYPE; using value_type = typename TypeClass::c_type; /// \brief Create a NumericTensor with full parameters /// /// This factory function will return Status::Invalid when the parameters are /// inconsistent /// /// \param[in] data The buffer of the tensor content /// \param[in] shape The shape of the tensor /// \param[in] strides The strides of the tensor /// (if this is empty, the data assumed to be row-major) /// \param[in] dim_names The names of the tensor dimensions static Result>> Make( const std::shared_ptr& data, const std::vector& shape, const std::vector& strides = {}, const std::vector& dim_names = {}) { ARROW_RETURN_NOT_OK(internal::ValidateTensorParameters( TypeTraits::type_singleton(), data, shape, strides, dim_names)); return std::make_shared>(data, shape, strides, dim_names); } /// Constructor with non-negative strides and dimension names NumericTensor(const std::shared_ptr& data, const std::vector& shape, const std::vector& strides, const std::vector& dim_names) : Tensor(TypeTraits::type_singleton(), data, shape, strides, dim_names) {} /// Constructor with no dimension names or strides, data assumed to be row-major NumericTensor(const std::shared_ptr& data, const std::vector& shape) : NumericTensor(data, shape, {}, {}) {} /// Constructor with non-negative strides NumericTensor(const std::shared_ptr& data, const std::vector& shape, const std::vector& strides) : NumericTensor(data, shape, strides, {}) {} const value_type& Value(const std::vector& index) const { return Tensor::Value(index); } }; } // namespace arrow