| 199 | |
| 200 | template <typename NativeT> |
| 201 | Status MutableLiteralBase::CopySliceFromInternal( |
| 202 | const LiteralBase& src_literal, absl::Span<const int64> src_base, |
| 203 | absl::Span<const int64> dest_base, absl::Span<const int64> copy_size) { |
| 204 | TF_RET_CHECK(src_literal.shape().rank() == src_base.size()); |
| 205 | TF_RET_CHECK(shape().rank() == dest_base.size()); |
| 206 | |
| 207 | auto linear_index = [](const Shape& shape, |
| 208 | absl::Span<const int64> multi_index) { |
| 209 | return IndexUtil::MultidimensionalIndexToLinearIndex(shape, multi_index); |
| 210 | }; |
| 211 | |
| 212 | if (src_literal.shape().rank() == 0 || shape().rank() == 0) { |
| 213 | // If any of the two shapes are scalars, we can just call the StridedCopy() |
| 214 | // directly, and we know we will be copying only one value. |
| 215 | TF_RET_CHECK(copy_size.empty()); |
| 216 | StridedCopy(data<NativeT>(), linear_index(shape(), dest_base), 0, |
| 217 | src_literal.data<NativeT>(), |
| 218 | linear_index(src_literal.shape(), src_base), 0, 1); |
| 219 | } else if (!ShapeUtil::IsZeroElementArray(shape()) && |
| 220 | !ShapeUtil::IsZeroElementArray(src_literal.shape())) { |
| 221 | // Perform copy if neither src nor dest has dimensions with zero element, |
| 222 | // otherwise it's a no-op. |
| 223 | TF_RET_CHECK(src_base.size() == dest_base.size()); |
| 224 | TF_RET_CHECK(src_base.size() == copy_size.size()); |
| 225 | |
| 226 | // Scan the source from minor, stepping in copy size blocks, then within |
| 227 | // the index enumeration functor, do a strided copy advancing source index |
| 228 | // by one (walking through the minor dimension), and destination index by |
| 229 | // proper stride size at the matching dimension. |
| 230 | DimensionVector src_indexes(src_base.size(), 0); |
| 231 | DimensionVector dest_indexes(dest_base.size(), 0); |
| 232 | MutableLiteralBase::StrideConfig stride_config(src_literal.shape(), shape(), |
| 233 | copy_size); |
| 234 | |
| 235 | auto copy_proc = [&](absl::Span<const int64> indexes) { |
| 236 | // Map from multi-dimensional index, to source index. |
| 237 | std::transform(indexes.begin(), indexes.end(), src_base.begin(), |
| 238 | src_indexes.begin(), std::plus<int64>()); |
| 239 | // Map from multi-dimensional index, to destination index. |
| 240 | std::transform(indexes.begin(), indexes.end(), dest_base.begin(), |
| 241 | dest_indexes.begin(), std::plus<int64>()); |
| 242 | |
| 243 | int64 src_index = linear_index(src_literal.shape(), src_indexes); |
| 244 | int64 dest_index = linear_index(shape(), dest_indexes); |
| 245 | |
| 246 | // `this->` is needed to workaround MSVC bug: #16882 |
| 247 | StridedCopy(this->data<NativeT>(), dest_index, stride_config.dest_stride, |
| 248 | src_literal.data<NativeT>(), src_index, |
| 249 | stride_config.source_stride, stride_config.minor_loop_size); |
| 250 | return true; |
| 251 | }; |
| 252 | |
| 253 | ShapeUtil::ForEachIndex(src_literal.shape(), stride_config.base, |
| 254 | stride_config.dimensions, stride_config.step, |
| 255 | copy_proc); |
| 256 | } |
| 257 | return Status::OK(); |
| 258 | } |
nothing calls this directly
no test coverage detected