| 314 | } |
| 315 | |
| 316 | const Result<std::shared_ptr<Tensor>> FixedShapeTensorArray::ToTensor() const { |
| 317 | // To convert an array of n dimensional tensors to a n+1 dimensional tensor we |
| 318 | // interpret the array's length as the first dimension the new tensor. |
| 319 | |
| 320 | const auto& ext_type = |
| 321 | internal::checked_cast<const FixedShapeTensorType&>(*this->type()); |
| 322 | const auto& value_type = ext_type.value_type(); |
| 323 | ARROW_RETURN_IF( |
| 324 | !is_fixed_width(*value_type), |
| 325 | Status::TypeError(value_type->ToString(), " is not valid data type for a tensor")); |
| 326 | |
| 327 | // ext_type->permutation() gives us permutation for a single row with values in |
| 328 | // range [0, ndim). Here want to create a ndim + 1 dimensional tensor from the entire |
| 329 | // array and we assume the first dimension will always have the greatest stride, so it |
| 330 | // will get permutation index 0 and remaining values from ext_type->permutation() need |
| 331 | // to be shifted to fill the [1, ndim+1) range. Computed permutation will be used to |
| 332 | // generate the new tensor's shape, strides and dim_names. |
| 333 | std::vector<int64_t> permutation = ext_type.permutation(); |
| 334 | if (permutation.empty()) { |
| 335 | permutation.resize(ext_type.ndim() + 1); |
| 336 | std::iota(permutation.begin(), permutation.end(), 0); |
| 337 | } else { |
| 338 | for (auto i = 0; i < static_cast<int64_t>(ext_type.ndim()); i++) { |
| 339 | permutation[i] += 1; |
| 340 | } |
| 341 | permutation.insert(permutation.begin(), 1, 0); |
| 342 | } |
| 343 | |
| 344 | std::vector<std::string> dim_names = ext_type.dim_names(); |
| 345 | if (!dim_names.empty()) { |
| 346 | dim_names.insert(dim_names.begin(), 1, ""); |
| 347 | internal::Permute<std::string>(permutation, &dim_names); |
| 348 | } |
| 349 | |
| 350 | std::vector<int64_t> shape = ext_type.shape(); |
| 351 | ARROW_ASSIGN_OR_RAISE(const int64_t cell_size, internal::ComputeShapeProduct(shape)); |
| 352 | shape.insert(shape.begin(), 1, this->length()); |
| 353 | internal::Permute<int64_t>(permutation, &shape); |
| 354 | |
| 355 | ARROW_ASSIGN_OR_RAISE(auto tensor_strides, |
| 356 | internal::ComputeStrides(value_type, shape, permutation)); |
| 357 | |
| 358 | const auto& raw_buffer = this->storage()->data()->child_data[0]->buffers[1]; |
| 359 | ARROW_ASSIGN_OR_RAISE( |
| 360 | const auto buffer, |
| 361 | SliceBufferSafe(raw_buffer, this->offset() * cell_size * value_type->byte_width())); |
| 362 | |
| 363 | return Tensor::Make(value_type, buffer, shape, tensor_strides, dim_names); |
| 364 | } |
| 365 | |
| 366 | Result<std::shared_ptr<DataType>> FixedShapeTensorType::Make( |
| 367 | const std::shared_ptr<DataType>& value_type, const std::vector<int64_t>& shape, |