Table of Contents

Namespace NumSharp

Primary NumSharp namespace containing the NDArray type, NumPy-style API facade, dtype metadata, slicing and shape helpers, random state, and NumPy-compatible exception types.

Use this namespace when writing NumSharp code:

  • np is the NumPy-style static API, equivalent to Python's import numpy as np.
  • NDArray is the main n-dimensional array container.
  • Shape, Slice, and NPTypeCode define shape, view, indexing, and dtype behavior.
  • NumPyRandom exposes NumPy-compatible MT19937 random generation.

NumSharp targets NumPy 2.x API and behavioral compatibility. Arrays use unmanaged storage, slicing returns views that share storage, broadcasting follows NumPy shape rules, and the public NDArray dtype set covers Boolean, Byte, SByte, Int16, UInt16, Int32, UInt32, Int64, UInt64, Char, Half, Single, Double, Decimal, and Complex. NPTypeCode.Empty, NPTypeCode.String, and the NPTypeCode.Float alias are enum/compatibility values, not additional public array dtypes; Float resolves to Single.

using NumSharp;

var a = np.arange(6).reshape(2, 3);
var b = np.array(new[] { 10, 20, 30 });
NDArray c = a + b;        // NumPy-style broadcasting
NDArray col = c[":, 1"];  // Slicing returns a view

Classes

ArrayMethod

NEP 43's ArrayMethod — ONE object per (input DTypes → output DTypes) implementation of an operation: it resolves the loop descriptors for the given operand descriptors (ResolveDescriptors(DType[], DType[], out long)) and hands out the strided inner loop that runs them (GetStridedLoop(ArrayMethodContext, bool, long[], out NDArrayMethodFlags)). Casts are the first family (CastingImpl); ufunc loops for a new dtype register the same way (Stage C) instead of adding a case NPTypeCode.X: to the IL generators.

ArrayMethodContext

NEP 43's PyArrayMethod_Context: the method being run plus the resolved descriptors — what a strided loop receives so it can read parameters (a datetime unit) without re-resolving.

AttributeError

Exception that corresponds to Python/NumPy's AttributeError. Raised when an attribute reference or assignment fails.

AxisError

NumPy-compatible AxisError exception. Raised when an axis argument is out of bounds for the array's dimensions.

AxisOutOfRangeException
BitGenerator

Base class for the pseudo-random bit generators that drive Generator.

BuiltinCastingImpl

The cast between two storage-backed builtin classes (NumPy's add_numeric_cast, convert_datatype.c). Its Casting is computed the way NumPy computes spec.casting: the same class → equiv (a copy or byte swap); safe when the frozen promotion table says promote(from, to) == to (NumPy's _npy_can_cast_safely_table); otherwise same_kind when the source kind orders at or below the destination kind (b < u < i < f < c), else unsafe. These are exactly the rules np.can_cast(NPTypeCode, NPTypeCode) always applied, so the builtin answers are unchanged; the class pair now owns them.

CastingImpl

An ArrayMethod with one input and one output: the cast from From to To (NumPy's castingimpl). Looked up per class pair by GetCastingImpl(DTypeMeta) and consulted by DTypeCasting (can_cast, cast-safety, descriptor adaptation) and by CastDescrToDType(DType, DTypeMeta) (which is how a parametric class learns the instance an operand of another class should become).

Char8SpanExtensions
DType

NumSharp's data-type descriptor — the INSTANCE of a DTypeMeta class, standing in for NumPy's numpy.dtype object (np.dtype('f8'), np.dtype('M8[ns]')), and the single dtype spelling every dtype-taking API in NumSharp accepts.

DTypeCasting

The NEP 43 casting engine over descriptors — the ports of NumPy's convert_datatype.c entry points: GetCastingImpl(DTypeMeta, DTypeMeta) (PyArray_GetCastingImpl), GetCastInfo(DType, DType, DTypeMeta, out long) (PyArray_GetCastInfo), CheckCastSafety(NPY_CASTING, DType, DType, DTypeMeta) (PyArray_CheckCastSafety), CanCastTypeTo(DType, DType, NPY_CASTING) (PyArray_CanCastTypeTo — the engine behind np.can_cast), EquivTypes(DType, DType) (PyArray_EquivTypes), MinCastSafety(NPY_CASTING, NPY_CASTING) and the casting-string parser. Every question is answered by the CastingImpl registered for the CLASS pair, so a new dtype joins np.can_cast by registering its casts — no table edit.

DTypeMeta

The DType CLASS — NumPy's PyArray_DTypeMeta (type(np.dtype('f8')), i.e. np.dtypes.Float64DType). One live object per dtype class; a DType is an INSTANCE of it (the descriptor). This is NEP 41/42's two-level model: behaviour lives on the class as virtual "slots" (CommonDType(DTypeMeta), CommonInstance(DType, DType), DefaultDescr(), EnsureCanonical(DType), DiscoverDescrFromObject(object), IsKnownScalarType(Type), the casting implementations), parameters live on the instance (a datetime unit, a byte order).

DTypePromotion

The NEP 42 / NEP 50 promotion engine over DType classes and descriptors — the ports of NumPy's common_dtype.c and convert_datatype.c: CommonDType(DTypeMeta, DTypeMeta) (PyArray_CommonDType), PromoteDTypeSequence(IReadOnlyList<DTypeMeta>) (PyArray_PromoteDTypeSequence with its reduce_dtypes_to_most_knowledgeable pass), PromoteTypes(DType, DType) (PyArray_PromoteTypes), CastDescrToDType(DType, DTypeMeta) (PyArray_CastDescrToDType), CastToDTypeAndPromoteDescriptors(IReadOnlyList<DType>, DTypeMeta) and ResultType(params object[]) (PyArray_ResultType, the NEP 50 entry point where C# literals are weak and arrays — 0-d included — are strong).

DTypePromotionError

numpy.exceptions.DTypePromotionError — raised when two (or more) DTypes have no common DType, i.e. np.promote_types / np.result_type cannot find a dtype that can hold every input (NEP 42's common_dtype protocol returned NotImplemented in both directions).

DTypeRegistry

The table of live DTypeMeta classes and their casting implementations — NumPy's _builtin_descrs / typenum_to_dtypemeta / _PyArray_MapPyTypeToDType rolled into one static registry. Lookups by NPTypeCode, C# scalar Type, NumPy type number and class name (aliases included); Register(DTypeMeta) admits a new class (a Stage C/D dtype, a user dtype) without touching the kernel switches — the class registers its code and its casts, and the promotion/casting engines pick it up.

DatetimeDTypeMeta

The DType classes of datetime64 (np.dtypes.DateTime64DType, type number 21, kind/char 'M') and timedelta64 (np.dtypes.TimeDelta64DType, 22, 'm') — NumSharp's first PARAMETRIC classes: the unit metadata (DatetimeMetaData) lives on the descriptor INSTANCE, so M8[ns] and M8[s] are two descriptors of one class, and promotion runs CommonInstance(DType, DType) (the unit GCD) instead of returning a class default.

DatetimeTimedeltaCastingImpl

The cast between datetime64 and timedelta64 (either direction) — NumPy's datetime_to_timedelta_resolve_descriptors: the destination inherits the SOURCE's unit when none is given (which is how promote_types turns m8[Y] into M8[Y] before taking the GCD), and the cast is always unsafe.

EnvVars

Central, typed accessor for every environment variable NumSharp reads. Each property RETURNS THE VALUE (not the name), read through the shared Get(string) / GetBool(string, bool) helpers, so null/blank handling, trimming and boolean parsing live in ONE place. Read-sites use e.g. if (EnvVars.DebugGuardPages) or var lib = EnvVars.OpenBlasLibrary; instead of repeating Environment.GetEnvironmentVariable(...) and its parsing.

FourierModule

The numpy.fft module surface, reachable as fft. Holds the 18 public transforms/helpers (standard fft/ifft/fft2/ifft2/fftn/ifftn, real rfft/irfft/rfft2/irfft2/rfftn/irfftn, hermitian hfft/ihfft, and helpers fftfreq/rfftfreq/fftshift/ifftshift).

The helpers (fftfreq/rfftfreq/fftshift/ifftshift) are pure compositions of existing np.* functions. The transforms validate and resolve everything NumPy's Python layer does — n/axis/norm/shape/dtype and the N-D→1-D decomposition — then compute through PocketFFTDriver.Execute, the managed port of pocketfft's 1-D engine (bit-identical to NumPy 2.4.2 on the double/complex128 path). The N-D wrappers are pure compositions of the 1-D transforms.

Generator

The modern NumPy random number container returned by np.random.default_rng.

IncorrectShapeException
IncorrectSizeException
IncorrectTypeException
IndexError

Exception that corresponds to Python/NumPy's IndexError. Raised when a sequence subscript is out of range, or when an index type is invalid (e.g. float/complex index on an ndarray).

KeyError

Exception that corresponds to Python/NumPy's KeyError. Raised when a mapping (dict) key is not found.

LegacyBuiltinDTypeMeta

The DType class of a storage-backed NumSharp dtype — the 15 element types (plus the vestigial String), wrapped the way NumPy's dtypemeta_wrap_legacy_descriptor wraps its builtin descriptors into numpy.dtypes.*DType classes. Data-driven: the registry constructs one per NPTypeCode with its NumPy type number, kind, char, size, alignment and aliases; the behaviour slots are the builtin ones — the singleton is the default descriptor, and CommonDType(DTypeMeta) is NumPy's default_builtin_common_dtype over NumSharp's frozen promotion table (NumSharp.np._nptypemap_arr_arr), so every existing promote_types answer is reproduced bit-for-bit.

LegacyWrappingCastingImpl

A cast whose safety is fixed per class pair with the plain descriptor resolution — NumPy's PyArray_AddLegacyWrapping_CastingImpl, used for the numeric ↔ datetime/timedelta casts: every cast to or from datetime64 is unsafe; an integer or bool casts safely to timedelta64 (a 64-bit unsigned one only same_kind), a float or complex only unsafely.

LinAlgError

NumPy-compatible numpy.linalg.LinAlgError. Raised by np.linalg when a matrix is unsuitable for the requested factorisation — the wrong rank, not square, singular, or not positive definite.

MT19937

Mersenne Twister MT19937 pseudo-random number generator. This implementation matches NumPy's MT19937 exactly, producing identical sequences for the same seed.

MethodImplOptionsConstants

Method implementation option constants for use with MethodImplAttribute.

MissingBackendException

Raised when an operation needs a pluggable compute backend — an IBlasBackend assigned to NumSharp.Backends.TensorEngine.Blas — and none is installed, or the installed one declined these operands.

ModuleNameAttribute

Marks a public type as the C# host of a NumPy module surface — the type whose public members ARE that module's functions. np itself carries "np", NDArray carries "ndarray", and each function-namespace facade carries its dotted Python path ("np.random" on NumPyRandom, "np.fft" on FourierModule, "np.linalg" on the nested np.linalg class).

NDArray

Container protocol implementation for NDArray. Provides Python-compatible container protocol methods: contains, hash, len, iter, getitem, setitem

NDArrayFlags

The memory-layout flags of an NDArray — a byte-for-byte port of NumPy 2.4.2's arrayflags object (numpy/_core/src/multiarray/flagsobject.c): the lowercase dotted attributes (c_contiguous, f_contiguous, owndata, writeable, aligned, writebackifcopy, and the derived fnc/forc/behaved/ carray/farray/num), the bracket-key accessor (flags["C"], flags["F_CONTIGUOUS"], …), the six-line ToString() repr, and equality by the integer num. Values are read live from the array's Shape and storage, verified equal to NumPy across every layout (C/F/strided/transposed/broadcast/0-d/empty).

ALIGNED is true for every fresh array (managed allocations are always aligned) and can only be cleared through setflags(bool?, bool?, bool?) / flags["A"] = false — NumPy parity, the flag then reads back False and num/behaved/carray/farray follow. WRITEBACKIFCOPY is always false (NumSharp has no copy-on-write handoff), matching what a NumSharp array can be.

NDArrayNetInterop

Fluent bridges from NumSharp iteration to built-in .NET types — the "other types (foreach or non-foreach)" companions to the by-ref T/Span<T> walks and to NDArray._Unsafe.

These are the SAFE side of the integration: AsEnumerable<T>(NDArray) gives LINQ/collection interop with UNBOXED elements (only the enumerator is heap-allocated, once, not each element), and the iterator ToArray/CopyTo extensions MATERIALIZE or COPY into caller-owned .NET storage — so, unlike the aliasing nd.Unsafe.* views, the result does not depend on the NDArray staying alive. For a zero-copy aliasing Span<T>/Memory<T> over the buffer, use nd.Unsafe (see Unsafe).

NDBorrowedAttribute

Marks a field, property, class or struct as borrowing the NDArray(s) it references — they are owned and disposed by someone else — so the compile-time ownership analyzer (NumSharp.Build.Analyzer) must not demand that the containing type dispose them.

NDScope

Ambient reclamation scope for transient NDArray intermediates — the library's standard way to make a composition method eagerly return its temporaries' pooled buffers instead of waiting on the finalizer (see DISPOSAL-GUIDELINES.md). Every NDArray constructed on the current thread while a scope is open is tracked by it; disposing the scope disposes every tracked array that was not yielded via Returns<T>(T). Tracked disposal is ordinary ARC release (the buffer frees only at refcount 0), so releasing a base whose view was yielded never corrupts — the same safety as a hand-written Dispose, with the bookkeeping automated.

NDScopedAsyncAttribute

The ASYNC counterpart of NDScopedAttribute: marks an async method, an async iterator, or a non-async method returning Task/ValueTask[<T>] as an NDScope boundary. At build time the NumSharp IL weaver (tools/NumSharp.Build, shipped to consumer projects as the NumSharp.Build NuGet package) weaves the method's compiler STATE MACHINE — or, for a non-async Task-returning body, its DEFERRAL egress — so the NDArray temporaries it drops are reclaimed at the invocation's completion instead of waiting on the finalizer, with the source keeping its 100% original body exactly as NDScopedAttribute does for synchronous ones.

NDScopedAttribute

Marks a method (or a property accessor) as an NDScope boundary: at build time the NumSharp IL weaver (tools/NumSharp.Build, shipped to consumer projects as the NumSharp.Build NuGet package) injects the exact code the hand-written pattern spells —

using var scope = NDScope.Open();
...original body, byte-for-byte...
return scope.Returns(result);        // NDArray-like returns

— so the source keeps its 100% original body and the reclamation is invisible.

NDScopedCoveredAttribute

Marks a method (or property accessor) as covered by an ambient NDScope opened by its caller — a [NDScoped] OR [NDScopedAsync] boundary (or a hand-written scope) — so its NDArray temporaries are reclaimed by that caller's scope, and the NDW012 leak analyzer must treat the method as covered instead of flagging its transients.

NDScopedExitAttribute

Marks a by-value parameter as one the callee RETAINS — a reference it keeps past the call (stores in a field/property, adds to a long-lived collection, captures in a closure/task that outlives the call). At build time the NumSharp IL weaver detaches the argument from whatever NDScope tracks it, so the CALLER's scope will NOT reclaim an NDArray the callee is still holding.

NPTypeCodeExtensions
NameError

Exception that corresponds to Python/NumPy's NameError. Raised when a name referenced by value is not defined.

NumPyRandom

A class that serves as numpy.random.RandomState in python. Uses MT19937 (Mersenne Twister) for NumPy-compatible random number generation.

NumSharpException
OpenBlasMissingBackendException

A MissingBackendException whose message says how to make the operation work: reference the NumSharp.Interop.OpenBLAS NuGet package.

PCG64

PCG64 (XSL-RR 128/64) bit generator — the default BitGenerator behind np.random.default_rng.

PocketFFTDriver
PyScalarDTypeMeta

NumPy's abstract DType classes for Python scalars — numpy.dtypes._PyLongDType, _PyFloatDType, _PyComplexDType (abstractdtypes.c). They are how NEP 50 "weak" promotion works: a literal contributes only its abstract CLASS to result_type (no descriptor, so no value or width), and the class's CommonDType(DTypeMeta) lets the other operand's dtype win within its kind (int8 + 300 → int8, float32 + 1e300 → float32) while still lifting across kinds (int8 + 1.5 → float64). A literal that survives alone falls back to the class default (int64 / float64 / complex128).

RuntimeError

Exception that corresponds to Python/NumPy's RuntimeError. Raised when an error is detected that does not fall into any of the other categories.

SeedSequence

Mixes an arbitrary seed into a high-quality initial state for a bit generator.

Slice

NDArray can be indexed using slicing
A slice is constructed by start:stop:step notation

Examples:

a[start:stop] # items start through stop-1
a[start:] # items start through the rest of the array
a[:stop] # items from the beginning through stop-1

The key point to remember is that the :stop value represents the first value that is not
in the selected slice. So, the difference between stop and start is the number of elements
selected (if step is 1, the default).

There is also the step value, which can be used with any of the above:
a[:] # a copy of the whole array
a[start:stop:step] # start through not past stop, by step

The other feature is that start or stop may be a negative number, which means it counts
from the end of the array instead of the beginning. So:
a[-1] # last item in the array
a[-2:] # last two items in the array
a[:-2] # everything except the last two items
Similarly, step may be a negative number:

a[::- 1] # all items in the array, reversed
a[1::- 1] # the first two items, reversed
a[:-3:-1] # the last two items, reversed
a[-3::- 1] # everything except the last two items, reversed

NumSharp is kind to the programmer if there are fewer items than
you ask for. For example, if you ask for a[:-2] and a only contains one element, you get an
empty list instead of an error.Sometimes you would prefer the error, so you have to be aware
that this may happen.

Adapted from Greg Hewgill's answer on Stackoverflow: https://stackoverflow.com/questions/509211/understanding-slice-notation

Note: special IsIndex == true
It will pick only a single value at Start in this dimension effectively reducing the Shape of the sliced matrix by 1 dimension.
It can be used to reduce an N-dimensional array/matrix to a (N-1)-dimensional array/matrix

Example:
a=[[1, 2], [3, 4]]
a[:, 1] returns the second column of that 2x2 matrix as a 1-D vector
TensorEngine

The linear-algebra entry points beyond dot/matmul: the matrix products (managed fallback, backend optional), the LU-based factorisations det/slogdet/ solve/inv (managed fallback via NumSharp.Backends.ManagedLu, backend optional), and the remaining factorisations (backend required, no fallback).

TensorEngine.Threading

Process-wide threading configuration — one named, environment-variable-backed knob per threading domain (NumSharp's own kernels, and the native BLAS / OpenMP runtimes NumPy and the rest of the ecosystem thread through: OpenBLAS, MKL, BLIS, NumExpr, vecLib). It is the single surface for reading and setting them, and it is extensible per module: a module registers (or upgrades) its own knob via Register(string, string, Func<int?>, Action<int?>) — that is how NumSharp.Interop.OpenBLAS attaches a native applier to the OpenBlas knob so a change reaches the loaded library, and how any future backend adds its own.

TensorEngine.Threading.Variable

One threading knob: a logical name, an optional backing environment variable, and the module hooks that read and apply its value. Read-only from outside; mutated only through TensorEngine.Threading.

TimeToTimeCastingImpl

The within-class cast of datetime64 / timedelta64 — a unit conversion. Port of NumPy's time_to_time_resolve_descriptors (datetime.c): identical metadata (or an exact 10³ᵏ metric-prefix fold such as [1000ms] → [s]) is a no-op view / equiv byte swap; a generic source is safe; a generic destination or, for timedelta, a jump across the years-months barrier is unsafe; towards a finer unit that divides exactly is safe, anything else same_kind.

TypeError

Exception that corresponds to Python/NumPy's TypeError. Raised when an operation or function receives an argument of inappropriate type.

ValueError

NumPy-compatible ValueError exception. Raised when an operation receives an argument with the right type but inappropriate value.

finfo

Machine limits for floating point types.

iinfo

Machine limits for integer types.

np

API bridge between NumSharp and Python NumPy

np.AxisConcatenator

Translates slice expressions to concatenation along an axis — the machinery shared by r_ and c_.

np.Broadcast

NumPy's numpy.broadcast — the broadcast result of N operands, usable as an iterator. Like NumPy, the object is its OWN iterator (iter(b) is b): it keeps a single live cursor exposed as index, iterating it yields one tuple of per-operand values per step (advancing the cursor), and reset() rewinds it.

np.CClass

Translates slice expressions to concatenation along the SECOND axis.

np.FlatIterator

A flat, C-order iterator over an NDArray — the NumSharp analog of NumPy's flatiter (the type of ndarray.flat), obtained from flatiter or flat(NDArray).

Unlike NumSharp's flat (a raveled NDArray that materializes a COPY for a non-contiguous array, so writes through it are lost), this iterator always reads AND writes THROUGH to the base array in logical C-order, whatever the memory layout — matching NumPy's a.flat[i] = v semantics for transposed, sliced, strided, negative-stride and broadcast layouts alike. Every element access maps a flat C-order index to the base's coordinate and goes through the base's stride-aware element accessors, so no per-dtype branching and no buffer materialization occur.

Surface (probed against NumPy 2.4.2): this[long] single-element get (a 0-d write-through view, NumSharp's scalar analog) / set; fancy (int[]/long[]/ NDArray) and slice-string ("1:4", "::2") get/set; the index / coords cursor, Base, size, copy() (a fresh 1-D C-order array), and C-order iteration that shares the cursor (so a second pass RESUMES, as NumPy's iter(f) is f).

Scalar assignment matches NumPy's weak-scalar bounds check: an OUT-OF-RANGE C# primitive (NumSharp's NEP50 analog of a Python int/float) written to an integer element RAISES (OverflowException, "Python integer 300 out of bounds for int8") rather than wrapping, the truncate-then-check rule for floats included (127.9 stores 127, 128.0 raises, NaN/inf raise). A STRONG scalar — an NDArray, reached through the fancy/slice setters or a.astype — still wraps, exactly as in NumPy (which range-checks a Python int but wraps an np.int64 scalar).

One documented divergence remains ([Misaligned]): coords read at the EXHAUSTED position (index == size, after a full pass) on a truly non-contiguous array is implementation-defined — NumSharp returns the arithmetic continuation, NumPy an internal odometer artifact; every IN-RANGE coord (the values read during iteration) is bit-exact.

np.IndexExpression

A nicer way to build up index tuples for arrays — the type behind s_ and index_exp. Use those two instances rather than constructing this directly.

np.MGridClass

An instance which returns a dense ("fleshed out") multi-dimensional "meshgrid" when indexed, so that every returned axis-grid has the SAME shape. The number of stacked grids and their dimensionality equal the number of indexing slices. If the step length is not a complex number, the stop is NOT inclusive; a complex step (e.g. "…:5j") instead specifies the number of points, with the stop INCLUSIVE (i.e. linspace(double, double, long, bool, DType, string)).

np.MemoryView

The NumSharp analog of Python's memoryview — the buffer object returned by data. It is a lightweight, zero-copy HANDLE onto an array's raw memory plus the layout metadata needed to interpret it (NumPy's ndarray.data is literally memoryview(self)).

It owns no memory of its own: every member reads LIVE through the source array's Storage and Shape, so it stays valid while the source array (held as obj, keeping it alive exactly as NumPy's memoryview.obj does) is alive and not structurally mutated. The Pointer addresses the LOGICAL first element (base + offset·itemsize), matching NumPy's a.data / PyArray_DATA / a.ctypes.data / a.__array_interface__['data'][0] — for a sliced or reversed view this is the offset element, not the buffer base.

Surface (probed against NumPy 2.4.2's memoryview): obj, nbytes, itemsize, ndim, readonly (true for broadcast / non-writeable views), shape, strides (in BYTES like NumPy's — NumSharp's own strides are in elements), format (the struct-module type code), c_contiguous / f_contiguous / contiguous, Length (NumPy's len(mv)), tobytes(string) / hex(), the raw Pointer / Address, and write-through scalar element access via this[long[]].

Deliberately NOT modelled (documented boundaries, not gaps to close): partial-index sub-views (mv[1] on an N-D memoryview yields a sub-memoryview in Python — use the NDArray indexer for sub-arrays), cast, tolist, release / the context-manager protocol, and element iteration. NumSharp has no Python buffer protocol, so these Python-object conveniences have no counterpart; the buffer ESSENCE (pointer + metadata + write-through + tobytes) is what ndarray.data is for.

np.NDEnumerate

NumPy's numpy.ndenumerate — walks an array in C-order, yielding (index, value) for every element.

// numpy: list(np.ndenumerate(np.array([[1, 2], [3, 4]])))
//     -> [((0,0), 1), ((0,1), 2), ((1,0), 3), ((1,1), 4)]
foreach (var (index, value) in np.ndenumerate(a)) { … }

Like NumPy the object is its OWN iterator (iter(e) is e): it keeps a single live cursor, so a second enumeration resumes where the first stopped.

np.NDEnumerate<T>

Typed np.NDEnumerate — identical traversal, but reads elements as T without boxing. See ndenumerate<T>(NDArray).

np.NDIndex

NumPy's numpy.ndindex — a C-order odometer over the index space of a shape, yielding one index array per step with the LAST dimension varying fastest.

// numpy: list(np.ndindex(3, 2)) -> [(0,0), (0,1), (1,0), (1,1), (2,0), (2,1)]
foreach (var idx in np.ndindex(3, 2)) { /* idx = {0,0}, {0,1}, {1,0}, ... */ }

Like NumPy the object is its OWN iterator (iter(i) is i): it keeps a single live cursor, so a second enumeration resumes where the first stopped rather than restarting — the same contract np.Broadcast follows.

np.NDIterator

NumPy's numpy.nditer — the public, managed face of NumSharp's NDIterRef.

// numpy: for x in np.nditer(a): total += x
foreach (var vals in np.nditer(a))
    total += (int)vals[0];

// numpy: it = np.nditer(a, flags=['multi_index'])
//        while not it.finished: print(it.multi_index, it[0]); it.iternext()
var it = np.nditer(a, flags: new[] {"multi_index"});
while (!it.finished) { Use(it.multi_index, it[0]); it.iternext(); }
np.OGridClass

An instance which returns an open multi-dimensional "meshgrid" when indexed, so that only one dimension of each returned array is greater than 1. The number and dimensionality of the outputs equal the number of indexing slices. If the step length is not a complex number, the stop is NOT inclusive; a complex step (e.g. "…:5j") instead specifies the number of points, with the stop INCLUSIVE (i.e. linspace(double, double, long, bool, DType, string)).

np.RClass

Translates slice expressions to concatenation along the FIRST axis. Two use cases: comma-separated arrays are stacked along axis 0, and slice notation or scalars build a 1-D array.

np.dtypes

numpy.dtypes (NEP 56 / NumPy 1.25+): the DType CLASSES — np.dtypes.Float64DType is type(np.dtype('f8')). Each member is the live DTypeMeta singleton; its Instantiate() is NumPy's class call (Int8DType()dtype('int8'); DateTime64DType() raises the "Preliminary-API … can only be instantiated using np.dtype(...)" TypeError), and Meta is type(dtype).

np.linalg

NumPy's numpy.linalg module.

poly1d

A one-dimensional polynomial class — the NumSharp port of numpy.poly1d. Encapsulates a coefficient vector (highest power first) and the natural polynomial operations.

C# has no call syntax, so NumPy's p(x) evaluation is spelled np.polyval(p, x); the indexer p[k] retrieves the coefficient of x**k exactly like NumPy. NumPy's p ** n (polynomial power) has no ** operator in C# — spell it with repeated multiplication (p * p * p), which NumPy defines it to equal. ToString() renders NumPy's repr form (poly1d([...])); NumPy's separate pretty str() form is not reproduced (C# has a single ToString).

Structs

Char8

Represents a single byte as a character. Equivalent to NumPy's dtype('S1') / numpy.bytes_ of length 1, and to a Python bytes object of length 1. Interoperable with byte, char (via Latin-1), and string (via ASCII/Latin-1 encoding).

DateTime64

A 64-bit signed tick count representing a date/time value with full long range and a NaT sentinel, matching NumPy's np.datetime64 semantics. Used as a conversion-helper type in Converts.

DatetimeMetaData

The per-INSTANCE parameter of a datetime64 / timedelta64 descriptor — NumPy's PyArray_DatetimeMetaData ({ NPY_DATETIMEUNIT base; int num; }): the unit and an integer multiplier, so datetime64[5m] counts five-minute ticks. This is what makes the datetime pair PARAMETRIC: M8[ns] and M8[s] share one DTypeMeta and one 8-byte storage but are different dtypes, and promotion / casting between units is arithmetic on these two fields.

EinsumPath

The contraction path returned by einsum_path(string, NDArray[]) — NumPy's ['einsum_path', (1, 2), (0, 1)] list expressed as a value.

NDArray._Unsafe
NDArray._Unsafe._Pinning
NativeRandomState

Represents the stored state of MT19937 random number generator. This format is compatible with NumPy's random state.

PCG64.Pcg64StateData

Snapshot of the PCG64 internal state (the typed stand-in for NumPy's bit_generator.state dict; field names match its keys).

PolyfitResult

The polymorphic return of polyfit(NDArray, NDArray, int, double?, bool, NDArray, object). Converts implicitly to the coefficient array (the bare-return case); deconstructs to NumPy's full five-tuple (coeffs, residuals, rank, singular_values, rcond) or the cov two-tuple (coeffs, covariance).

Shape

Broadcasting operations for Shape.

SliceDef
np.FlatRefIter<T>

The foreach-able returned by flat<T>(NDArray, bool) and AsTyped<T>(bool) — the typed, unboxed, by-reference flat iterator. Yields ref T in logical C-order (matching flatiter), write-through for every memory layout.

It is exactly a C-order np.NDRefIter<T>. This type reuses np.NDRefIter<T>.Enumerator verbatim — the same NDIterRef cursor that np.nditer<T> drives — pinned to NPY_CORDER. It exists as its own type only so the flat contract (always C-order, never memory order) is stated in the type rather than left to a parameter default; there is no separate iteration logic. Everything documented on np.NDRefIter<T> — why the enumerator is a ref struct, that this value holds no unmanaged state while the enumerator does, that foreach disposes it and re-enumeration restarts — applies identically.

np.MGridResult

The result of an mgrid index expression: a dense mesh — one array. NumPy's mgrid is a single ndarray (a 1-D array for one slice; a stacked (N, *sizes) array for several), and the idiom X, Y = np.mgrid[…] works by iterating that array's first axis. This value carries the array and reproduces both spellings: it converts implicitly to the bare NDArray, and it Deconstructs (var (x, y) = np.mgrid["0:5", "0:3"];) or indexes ([k]) into the per-axis grids along that first axis.

np.MeshgridResult

The result of meshgrid(NDArray[], string, bool, bool): a tuple of N coordinate grids (NumPy returns a Python tuple). C# cannot return a variadic tuple, so this value stands in for it — it converts implicitly to NDArray[], Deconstructs (var (xx, yy) = np.meshgrid(x, y);) and indexes ([k]).

np.NDChunkIter<T>

The foreach-able returned by nditer_chunks<T>(NDArray, bool, char). See np.NDRefIter<T> for the ref struct, disposal, re-enumeration and iteration-order rationale, which apply identically.

The yielded Span<T> points straight at the operand, so writes go through and the span is invalidated by the next step.

np.NDChunkIter<T>.Enumerator

The cursor — one Span<T> per inner loop.

np.NDEnumerateRef<T>

The foreach-able returned by AsRef(bool) — the typed, allocation-free, by-ref T ndenumerate. Yields, per element, a np.NDEnumerateRef<T>.Entry carrying the coordinate (a ReadOnlySpan<T> over a reused buffer) and the value BY REFERENCE, in logical C-order (matching ndenumerate(NDArray)), write-through for every memory layout.

It composes two things that are already correct: the value ref comes from np.NDRefIter<T>.Enumerator pinned to C-order (the same engine flat<T>(NDArray, bool) drives), and the coordinate comes from a C-order odometer advanced in lockstep — since a C-order walk visits logical positions 0, 1, …, size-1, the k-th value and the k-th unravelled coordinate always line up. Everything documented on np.NDRefIter<T> about the ref struct enumerator, disposal under foreach, and restart-on-re-enumeration applies.

np.NDEnumerateRef<T>.Entry

One enumerated element: its coordinate and its value by reference.

np.NDEnumerateRef<T>.Enumerator

The cursor — pairs the C-order value ref with a lockstep coordinate odometer.

np.NDIndexSpans

The foreach-able returned by AsSpans() — the allocation-free odometer. Yields the current multi-index as a ReadOnlySpan<T> over a buffer REUSED each step (C-order, last axis fastest — identical order to np.NDIndex), so an entire index-space walk allocates nothing per step.

Re-enumeration RESTARTS (each foreach builds a fresh enumerator with its own buffer) — deliberately unlike np.NDIndex, which is its own iterator (NumPy's iter(i) is i) and resumes. Copy the span (.ToArray()) to keep an index past the current iteration; storing the span itself, or the whole enumeration, is a use-after-overwrite.

np.NDIndexSpans.Enumerator

The cursor — one ReadOnlySpan<T> (over a reused buffer) per step.

np.NDRefIter<T>

The foreach-able returned by nditer<T>(NDArray, bool, char).

Why a ref struct enumerator. C#'s foreach is pattern-based — it needs only GetEnumerator/MoveNext/Current, no interface — so an enumerator exposing ref T Current gives foreach (ref T x in …) with no allocation, no boxing and no interface dispatch. Being a ref struct also makes the compiler enforce what this API needs anyway: neither the enumerator nor the ref it hands out can escape to a field, a lambda or an async frame.

This type holds no unmanaged state; the ENUMERATOR does. Each GetEnumerator() builds a fresh NDIterRef, which foreach then disposes through the same pattern (no IDisposable required). That is why this value is safe to keep and re-enumerate, and why every pass starts from the beginning — deliberately UNLIKE the class-based np.NDIterator, which is its own iterator (NumPy's iter(x) is x) and therefore resumes. Returning this from GetEnumerator — the np.Broadcast pattern — would be a use-after-free here: the first foreach frees the state that the second would then walk.

Order is 'K', i.e. MEMORY order — not logical C-order. This matches np.nditer exactly (probed against NumPy 2.4.2: a reversed view a[:, ::-1] of arange(6).reshape(2,3) yields 0 1 2 3 4 5 under the default order in BOTH libraries, and 2 1 0 5 4 3 under order='C'). It is also what lets reversed / F-contiguous / transposed views coalesce to a single chunk. For logical order — the order ndenumerate(NDArray) uses — pass order: 'C'.

np.NDRefIter<T>.Enumerator

The cursor. Walks the inner loop with plain pointer arithmetic and only touches the iterator at a chunk boundary, so a contiguous array costs one iterator call for the whole walk.

np.OGridResult

The result of an ogrid index expression: an open mesh — a set of N arrays, each 1 in every axis but its own. NumPy's ogrid is polymorphic (a single slice yields a bare ndarray, several slices yield a tuple), which C# cannot express from one indexer, so this value stands in for both:

  • a single-slice result converts implicitly to a bare NDArray;
  • any result converts implicitly to NDArray[] and can be Deconstructed (var (y, x) = np.ogrid["0:3", "0:5"];) or indexed ([k]).
np.UniqueAllResult

The result of unique_all(NDArray): NumPy's UniqueAllResult namedtuple (values, indices, inverse_indices, counts). Converts implicitly to NDArray[], Deconstructs (var (values, indices, inv, counts) = np.unique_all(x);) and indexes ([k]).

np.UniqueCountsResult

The result of unique_counts(NDArray): NumPy's UniqueCountsResult namedtuple (values, counts). Converts implicitly to NDArray[], Deconstructs (var (values, counts) = np.unique_counts(x);) and indexes.

np.UniqueInverseResult

The result of unique_inverse(NDArray): NumPy's UniqueInverseResult namedtuple (values, inverse_indices). Converts implicitly to NDArray[], Deconstructs (var (values, inv) = np.unique_inverse(x);) and indexes.

np.UniqueResult
The result of <xref href="NumSharp.np.unique(NumSharp.NDArray%2cSystem.Boolean%2cSystem.Boolean%2cSystem.Boolean%2cSystem.Nullable%7bSystem.Int32%7d%2cSystem.Boolean%2cSystem.Boolean)" data-throw-if-not-resolved="false"></xref> — NumPy's
bare-array-OR-tuple return expressed as one type. It carries the sorted unique
<xref href="NumSharp.np.UniqueResult.values" data-throw-if-not-resolved="false"></xref> plus whichever of <xref href="NumSharp.np.UniqueResult.indices" data-throw-if-not-resolved="false"></xref>/<xref href="NumSharp.np.UniqueResult.inverse_indices" data-throw-if-not-resolved="false"></xref>/
<xref href="NumSharp.np.UniqueResult.counts" data-throw-if-not-resolved="false"></xref> were requested (the others are <code>null</code>), so
<code>np.unique(ar, return_counts=True)</code> ports from Python verbatim.

It stands in for both NumPy return shapes: it converts implicitly to NDArray (the bare form — yields values, so NDArray u = np.unique(ar); works) and implicitly to NDArray[] (the tuple form — the present outputs in NumPy field order). It also indexes ([k] = the k-th present output, matching the old NDArray[] return) and Deconstructs (var (values, counts) = np.unique(ar, return_counts: true);).

Interfaces

IIndex

Represents a class that can be served as an index, e.g. ndarray[new Slice(...)]

INDArrayCarrier

Opt-in seam a tuple-standin result struct (np.UniqueResult, np.MeshgridResult, PolyfitResult, …) implements so the NDScopedAttribute weaver can weave a boundary method that RETURNS it: YieldTo(NDScope) hands every NDArray the struct carries back to the ambient scope (via Returns<T>(T)), so the method's temporaries are reclaimed while its results survive.

INumSharpException

Enums

ArrayFlags

NumPy-aligned array flags. Cached at shape creation for O(1) access. Matches numpy/core/include/numpy/ndarraytypes.h flag definitions.

BackendType
DTypeFlags

Flags describing a DTypeMeta — the DType CLASS — mirroring NumPy's NPY_DT_* bits (dtypemeta.h / dtype_api.h): NPY_DT_LEGACY = 1, NPY_DT_ABSTRACT = 2, NPY_DT_PARAMETRIC = 4, NPY_DT_NUMERIC = 8.

NPTypeCode

Represents all available types in numpy.

NPTypeKind

Abstract type categories in NumPy's type hierarchy. These mirror NumPy's abstract scalar types (np.generic, np.number, etc.)

NPY_DATETIMEUNIT

NumPy's NPY_DATETIMEUNIT (ndarraytypes.h): the time unit a datetime64 / timedelta64 value counts in. The enum values are NumPy's — including the gap at 3 where the 1.6 business-day unit sat — because unit ORDER is semantic (a larger value is a finer unit) and NumPy's casting rules compare them.

NPY_SCALARKIND
NPY_TYPECHAR

https://numpy.org/doc/stable/reference/c-api/dtype.html#enumerated-types

PyScalarKind

The three NEP 50 "weak" literal categories: a Python int, float, complex.

Delegates

np.PadFunc