Skip to content

Fix concatenate and stack access with a different number of indices - #2952

Open
gouarin wants to merge 1 commit into
xtensor-stack:masterfrom
gouarin:fix-builder-index-count
Open

gouarin wants to merge 1 commit into
xtensor-stack:masterfrom
gouarin:fix-builder-index-count

Conversation

@gouarin

@gouarin gouarin commented Oct 29, 2026

Copy link
Copy Markdown
Member

Checklist

  • The title and commit message(s) are descriptive.
  • Small commits made to fix your PR have been squashed to avoid history pollution.
  • Tests have been added for new features or bug fixes.
  • API of new functions and classes are documented (no public API changes).

Description

Like containers, builder expressions should accept fewer indices than dimensions (missing leading indices are 0) or more (extra leading ones are ignored). They did not:

xt::xarray<int> a = {{1, 2, 3}, {4, 5, 6}};
auto h = xt::hstack(xt::xtuple(a, a));
h(4);  // reads before the start of the index array

concatenate_access computed distance(first, last) - dimension() in std::size_t, which wraps around when there are fewer indices than dimensions: concatenate returned garbage and hstack crashed with a segmentation fault. stack_access ignored the number of indices, so stack and 1-D vstack returned wrong values in both directions.

Both now go through a detail::trailing_index helper that aligns the indices on the last dimensions, as containers do. This also removes the -Wsign-conversion warnings in xbuilder.hpp.

xbuilder.concatenate_stack_index_count checks concatenate, hstack, stack and vstack with fewer and more indices against the evaluated result. It fails on master and passes with the fix, also under AddressSanitizer and UBSan.

Containers accept fewer indices than dimensions (the missing leading
ones are 0) or more (the extra leading ones are ignored).
concatenate_access computed the offset into the index range as
distance(first, last) - dimension() in size_t. With fewer indices this
wrapped around, so concatenate and hstack read before the start of the
index array: c(1) returned garbage for a 2-D concatenation and hstack
crashed. stack_access ignored the index count entirely, so stack and
1-D vstack returned wrong values with both fewer and more indices.

Both access methods now go through detail::trailing_index, which
aligns the indices on the last dimensions like containers do. It also
converts the index values explicitly: flat_expression_adaptor passes
the signed indices returned by unravel_index, which are never negative.
This removes the -Wsign-conversion warnings in xbuilder.hpp.

The new test fails on master and passes with ASan and UBSan.
@codspeed

codspeed Bot commented Oct 29, 2026

Copy link
Copy Markdown
Contributor

Merging this PR will not alter performance

1 warning

⚠️ Unable to measure the execution of 1 benchmark

This benchmark measured no execution time, so its result is not comparable and counts as unchanged. This usually happens when the compiler removes the code under test.

Prevent compiler optimizations

See affected benchmarks

✅ 255 untouched benchmarks


Comparing gouarin:fix-builder-index-count (4026ec1) with master (57f3d07)

Open in CodSpeed

This branch has not been deployed

No deployments
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.

1 participant