Skip to content

Conversation

@michal-bakshi
Copy link

@michal-bakshi michal-bakshi commented Jan 22, 2026

Type

  • Bug fix (non-breaking change which fixes an issue): Fixes #
  • [ x ] New feature (non-breaking change which adds functionality). Resolves #
  • Breaking change (fix or feature that would cause existing functionality to not work as expected) Resolves #

Motivation and Context

This PR implements support for negative step values in the Tensor::Slice function, addressing a TODO item for reverse traversal slicing operations.

Checklist:

  • [ x ] I have run python util/check_style.py --apply to apply Open3D code style
    to my code.
  • [ x ] This PR changes Open3D behavior or adds new functionality.
    • Both C++ (Doxygen) and Python (Sphinx / Google style) documentation is
      updated accordingly.
    • [ x ] I have added or updated C++ and / or Python unit tests OR included test
      results
      (e.g. screenshots or numbers) here.
  • [ x ] I will follow up and update the code if CI fails.
  • [ x ] For fork PRs, I have selected Allow edits from maintainers.

Description

Problem:
Previously, the Slice function only supported positive step values, which limited tensor slicing to forward traversal only.

Solution:

  • Added support for negative step values in the Slice function
  • Implemented proper handling of negative steps with correct index wrapping and boundary checks
  • Added special handling for stop=-1 case which means "before index 0" in Python semantics
  • Ensured the implementation matches Python/NumPy slicing behavior for negative steps
  • Added comprehensive test cases covering various negative step scenarios

close #7409

@update-docs
Copy link

update-docs bot commented Jan 22, 2026

Thanks for submitting this pull request! The maintainers of this repository would appreciate if you could update the CHANGELOG.md based on your changes.

@michal-bakshi michal-bakshi changed the title core: Refactor tensor slicing logic for negative steps #7409 tensor slicing logic for negative steps Jan 22, 2026
@ssheorey ssheorey requested review from Copilot and ssheorey January 22, 2026 22:05
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR implements support for negative step values in tensor slicing operations, enabling reverse traversal similar to Python/NumPy behavior. Previously, the Slice function only supported forward traversal with positive steps.

Changes:

  • Removed the restriction that prevented negative step values in Tensor::Slice
  • Added logic to handle negative steps with proper index wrapping, boundary checks, and special handling for stop=-1 (meaning "before index 0")
  • Updated default slice parameters to correctly initialize based on step direction (forward vs reverse)

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.

File Description
cpp/open3d/core/Tensor.cpp Implements negative step support with proper boundary handling and stride calculation
cpp/open3d/core/TensorKey.cpp Updates default slice parameter initialization based on step direction
cpp/tests/core/Tensor.cpp Adds comprehensive test cases for negative step slicing scenarios

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

SizeVector new_shape = shape_;
SizeVector new_strides = strides_;
new_shape[dim] = (stop - start + step - 1) / step;
new_shape[dim] = (start - stop + abs_step - 1) / abs_step;
Copy link

Copilot AI Jan 22, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For negative steps, when stop == -1 (meaning before index 0), this calculation may produce incorrect results. The formula (start - stop + abs_step - 1) / abs_step becomes (start - (-1) + abs_step - 1) / abs_step = (start + abs_step) / abs_step, which doesn't correctly compute the number of elements from start down to (but not including) index 0. The correct calculation should be (start + 1) / abs_step when stop == -1, or more generally (start - stop) / abs_step since stop is already adjusted.

Copilot uses AI. Check for mistakes.
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe the current formula already handles the stop == -1 case correctly.
Below is the reasoning.

Logical Distance: When stop == -1 with a negative step, we intend to include index 0. The span is therefore start - (-1) = start + 1. This correctly represents the total pool of elements.

Element Counting Logic: The formula (start - stop + abs_step - 1) / abs_step ensures that any element touched by a step is counted. When stop == -1, this simplifies to (start + abs_step) / abs_step, which can be logically viewed as 1 + (start / abs_step). The 1 accounts for the initial element at start, and start / abs_step accounts for subsequent elements reachable within the distance to 0.

Validation against suggested formulas: Using (start + 1) / abs_step would fail whenever the distance is not perfectly divisible by the step. For example, with start = 2 and step = -2, the correct elements are {2, 0} (count = 2).

My formula: (2 - (-1) + 2 - 1) / 2 = 2 (Correct)

Suggested formula: (2 + 1) / 2 = 1 (Incorrect, misses index 0).

@ssheorey
Copy link
Member

Hi @michal-bakshi thanks for submitting this nice feature! Can you please check the CI errors?

@michal-bakshi
Copy link
Author

Hi @ssheorey
I’m pushing a whitespace-only style fix.
The other CI failures are Docker build issues (unrelated to this PR), so no need to rerun the full pipeline.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Finalize Tensor slicing logic (address previous TODO)

2 participants