Avatar for the xtensor-stack user
xtensor-stack
xtensor
BlogDocsChangelog

Performance History

Latest Results

Xexpresion fix (#2918) # 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. # Description <!--- Give any relevant description here. If your PR fixes an issue, please include "Fixes #ISSUE" (substituting the relevant issue ID). --> --------- Co-authored-by: Alexis Placet <2400067+Alex-PLACET@users.noreply.github.com>
master
4 days ago
Fix infinite loop in xt::roll on arrays with a zero-length dimension (#2922) # Checklist - [x] The title and commit message(s) are descriptive. - [x] Small commits made to fix your PR have been squashed to avoid history pollution. - [x] Tests have been added for new features or bug fixes. - [x] API of new functions and classes are documented. *(N/A — bug fix only, no API change)* # Description `xt::roll` enters an infinite loop (and then divides by zero) when the input has a zero-length axis: - No-axis overload `roll(e, shift)` when `e.size() == 0`: `while (shift < 0) shift += flat_size;` loops forever with `flat_size == 0`, then `shift %= 0` is undefined behaviour. - Axis-aware overload `roll(e, shift, axis)` when the rolled axis has length 0: same issue on `axis_dim == 0`. ### Fix For a shape $s = (s_0, \dots, s_{n-1})$, if $\exists k: s_k = 0$, then $\mathrm{roll}(a, \mathrm{shift}, \mathrm{axis}) = a$, i.e. roll is the identity. In both overloads, after constructing `cpy = empty_like(e)`, return `cpy` early when `cpy.size() == 0`. The no-axis overload's hand-rolled `std::accumulate(shape, 1L, multiplies<size_t>())` is replaced by `cpy.size()` (numerically equivalent, and O(1) on contiguous layouts). When the rolled axis is non-empty but another axis has length 0 (e.g. `shape={3,0,4}` rolled along axis 0), the original code didn't loop — `detail::roll`'s inner loops became no-ops because the stride product collapses to 0 — but the recursion was wasted work. The widened guard `cpy.size() == 0` skips it cleanly. Observable output is unchanged. ### Tests Three regression cases in `test_xmanipulation.cpp`, one per code path: | Shape | Axis | Path exercised | |-------------|---------|-----------------------------------------------| | `{0}` | (ravel) | no-axis overload's empty-input guard | | `{3, 0}` | `1` | axis-aware overload, rolled axis itself is 0 | | `{3, 0, 4}` | `0` | axis-aware overload, *other* axis is 0 | All `test_xmanipulation` tests pass: 28 cases, 188 assertions. Verified against `numpy.roll`, which returns a same-shape empty array for these inputs.
master
5 days ago
fix: handle empty arrays in xt::roll to avoid infinite loop
f14XuanLv:fix/roll-empty-array
6 days ago
fix format
Alex-PLACET:codspeed_runner
6 days ago
format
Alex-PLACET:xexpresion_fix
6 days ago
fix: correct negative axis handling in roll function
JohanMabille:fix/roll-negative-axis-handling
7 days ago

Latest Branches

CodSpeed Performance Gauge
0%
Fix infinite loop in xt::roll on arrays with a zero-length dimension#2922
6 days ago
10a24af
f14XuanLv:fix/roll-empty-array
CodSpeed Performance Gauge
N/A
Codspeed runner#2921
6 days ago
2d08eb6
Alex-PLACET:codspeed_runner
CodSpeed Performance Gauge
0%
6 days ago
9304d5c
Alex-PLACET:add_comparative_benchmarks_with_numpy
© 2026 CodSpeed Technology
Home Terms Privacy Docs