static */
| 2348 | } |
| 2349 | |
| 2350 | /* static */ StatusOr<Shape> ShapeInference::InferSliceShape( |
| 2351 | const Shape& arg, absl::Span<const int64> starts, |
| 2352 | absl::Span<const int64> limits, absl::Span<const int64> strides) { |
| 2353 | auto error = [&](const string& message) { |
| 2354 | return InvalidArgument( |
| 2355 | "%s in slice operation; argument shape: %s; starts: {%s}; limits: " |
| 2356 | "{%s}; strides: {%s}.", |
| 2357 | message, ShapeUtil::HumanString(arg), StrJoin(starts, ","), |
| 2358 | StrJoin(limits, ","), StrJoin(strides, ",")); |
| 2359 | }; |
| 2360 | TF_RETURN_IF_ERROR(ExpectArray(arg, "operand of slice")); |
| 2361 | VLOG(2) << StrFormat("slicing shape %s starts={%s} limits={%s}", |
| 2362 | ShapeUtil::HumanString(arg), StrJoin(starts, ", "), |
| 2363 | StrJoin(limits, ", ")); |
| 2364 | |
| 2365 | if (starts.size() != limits.size()) { |
| 2366 | return error(StrFormat("slice start and limit sizes differ: %u vs %u", |
| 2367 | starts.size(), limits.size())); |
| 2368 | } |
| 2369 | |
| 2370 | if (starts.size() != strides.size()) { |
| 2371 | return error(StrFormat("slice start and strides sizes differ: %u vs %u", |
| 2372 | starts.size(), strides.size())); |
| 2373 | } |
| 2374 | |
| 2375 | if (starts.size() != arg.rank()) { |
| 2376 | return InvalidArgument( |
| 2377 | "Slice index count does not match argument rank: %u vs %d.", |
| 2378 | starts.size(), arg.rank()); |
| 2379 | } |
| 2380 | |
| 2381 | std::vector<int64> sizes; |
| 2382 | for (int64 dimension = 0; dimension < starts.size(); ++dimension) { |
| 2383 | int64 start_index = starts[dimension]; |
| 2384 | int64 limit_index = limits[dimension]; |
| 2385 | int64 stride = strides[dimension]; |
| 2386 | if (start_index < 0) { |
| 2387 | return InvalidArgument("Negative start index to slice: %d.", start_index); |
| 2388 | } |
| 2389 | if (limit_index > arg.dimensions(dimension)) { |
| 2390 | return error( |
| 2391 | StrFormat("limit index (%d) must be less than or equal to dimension " |
| 2392 | "size (%d)", |
| 2393 | limit_index, arg.dimensions(dimension))); |
| 2394 | } |
| 2395 | VLOG(2) << StrFormat("starts[%d] = %d", dimension, start_index); |
| 2396 | VLOG(2) << StrFormat("limits[%d] = %d", dimension, limit_index); |
| 2397 | if (start_index > limit_index) { |
| 2398 | return error( |
| 2399 | StrFormat("limit index (%d) must be greater or equal to " |
| 2400 | "start index (%d) in slice with positive stride", |
| 2401 | limit_index, start_index)); |
| 2402 | } |
| 2403 | if (stride <= 0) { |
| 2404 | return InvalidArgument("Stride (%d) must be positive.", stride); |
| 2405 | } |
| 2406 | sizes.push_back((limit_index - start_index + stride - 1) / stride); |
| 2407 | } |
nothing calls this directly
no test coverage detected