Skip to content

feat: np.resize and ndarray.resize (NumPy 2.x parity)#618

Merged
Nucs merged 1 commit into
masterfrom
np_resize
Jul 18, 2026
Merged

feat: np.resize and ndarray.resize (NumPy 2.x parity)#618
Nucs merged 1 commit into
masterfrom
np_resize

Conversation

@Nucs

@Nucs Nucs commented Jul 18, 2026

Copy link
Copy Markdown
Member

Overview

Adds NumPy's two resize entry points to NumSharp with full 2.x behavioral parity: the np.resize(a, new_shape) function and the in-place ndarray.resize(new_shape, refcheck=true) method. They deliberately differ in fill semantics, exactly like NumPy.

What's added

np.resize(a, new_shape) — function

  • Enlarges by tiling repeated copies of a in C-order; result is always C-contiguous, any input layout is raveled first.
  • Exact-sized doubling byte-tile fill: allocates exactly new_size and grows the filled region by self-copying (dtype-agnostic, O(new_size) bytes, O(log(new_size/size)) memcpys) — avoids NumPy's concatenate((a,)*repeats)[:new_size] over-allocation.
  • Empty source / zero new-size → zeros.
  • Negative dim → ArgumentException ("all elements of \new_shape` must be non-negative"`).

ndarray.resize(new_shape, refcheck=true) — in-place

  • Grows with zeros, shrinks by truncation, on the raw contiguous buffer (an F-contiguous resize relabels memory column-major).
  • Mirrors NumPy's guards verbatim (IncorrectShapeException): single-segment only; on byte-size change must own its data (not a view) and — under refcheck — not be shared. refcheck:false bypasses.
  • Same-size resize is a pure in-place reshape (no ownership/reference check).
  • ARC-correct buffer swap: add-ref the fresh block, release the old (freed when uniquely owned, kept alive for any sharer under refcheck:false).
  • params overload takes long[] (long-indexing aligned).

IArraySlice.IsUniquelyReferenced — refcount probe

  • Added to IArraySlice, ArraySlice<T>, UnmanagedMemoryBlock<T> (+ inner Disposer). true when the block is held by ≤ 1 logical reference; non-owning Wrap allocations (external/pinned) report true (immortal refcount). Backs resize's "references or is referenced by another array" guard.

Tests

39 ResizeTests (test/NumSharp.UnitTest/Manipulation/np.resize.Test.cs): function tiling / zeros / scalar / empty / negative / dtype, method grow / shrink / reshape / no-op, view & F-order, refcheck sharing guards, and error-parity. All green on net10.0.

Breaking changes

None — both entry points are new API.

Notes

Branch is based on origin/master and contains only the resize feature.

Implements both NumPy resize entry points with their distinct fill semantics,
plus the ARC-refcount plumbing that ndarray.resize's refcheck requires.

np.resize(a, new_shape) - function (Manipulation/np.resize.cs)
  * Enlarges by tiling REPEATED COPIES of `a` in C-order; result is always
    C-contiguous and any input layout is raveled first.
  * Fills via an exact-sized doubling byte-tile: allocates exactly new_size and
    grows the filled region by self-copying (dtype-agnostic raw memory,
    O(new_size) bytes, O(log(new_size/size)) memcpys) - beats NumPy's
    concatenate((a,)*repeats)[:new_size] which over-allocates then slices.
  * Empty source or zero new-size -> zeros(new_shape, a.dtype).
  * Negative dim -> ArgumentException ("all elements of `new_shape` must be
    non-negative"), matching np.resize's wording.

ndarray.resize(new_shape, refcheck=true) - in-place (Manipulation/NDArray.resize.cs)
  * Grows with ZEROS, shrinks by truncation, operating on the raw contiguous
    buffer (so an F-contiguous resize relabels memory column-major).
  * Mirrors NumPy's guards verbatim (IncorrectShapeException): single-segment
    only; when byte size changes it must own its data (not a view) and - under
    refcheck - not be shared. refcheck:false bypasses the sharing check.
  * Same-size resize is a pure in-place reshape (no ownership/reference check).
  * ARC-correct buffer swap: add-ref the fresh block, release the old (freed
    when uniquely owned, kept alive for any sharer under refcheck:false).
  * params overload takes long[] (long-indexing aligned), not int[].

IArraySlice.IsUniquelyReferenced - new refcount probe
  * Added to IArraySlice, ArraySlice<T>, UnmanagedMemoryBlock<T> (+ inner
    Disposer). True when the block is held by <= 1 logical reference; non-owning
    Wrap allocations (external/pinned) report true (immortal refcount). Backs
    resize's "references or is referenced by another array" guard.

Tests: 39 ResizeTests (Manipulation/np.resize.Test.cs) - function tiling/zeros/
scalar/empty/negative/dtype + method grow/shrink/reshape/no-op + view & F-order
+ refcheck sharing guards + error parity. All green on this base.

Docs: .claude/CLAUDE.md Shape Manipulation section documents both entry points.
@Nucs
Nucs merged commit 7a01b55 into master Jul 18, 2026
7 checks passed
@Nucs
Nucs deleted the np_resize branch July 19, 2026 04:11
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