Repository navigation
This release moves NumSharp to NumPy 2.5.4, gives its functions NumPy's own signatures and brings NumPy's scalars, every Python and NumPy exception class, and 17 new np.* functions.
An NDArray now shares its memory with TorchSharp tensors, in both directions.
🧭 Overview
- NumPy 2.x API coverage around 96.2%, everything except datetime, complex64 and other exotic dtypes is fully supported, with byte-to-byte equality and compatibility to NumPy.
- NumPy's scalars - a 0-d result is NumPy's read-only scalar, an element read
a[i, j]returns one, and NumPy's 36 scalar classes are callable (np.float64(1.5),np.int8("12")).
- NumPy's scalars - a 0-d result is NumPy's read-only scalar, an element read
- NumPy 2.5.4 is the reference (0.80.0: NumPy 2.4.2) - every oracle test case is NumPy 2.5.4's answer, with NumPy 2.5's behavior across linear algebra, random, numpy.ma,
np.fft, text, sorting, reductions and dtypes, its keyword-onlydescending=sort, and NumPy 2.5.4's own OpenBLAS in NumSharp.Interop.OpenBLAS. - Fresh results laid out as NumPy's - ufunc results take NumPy's trivial-loop C / F or NpyIter K layout down to the strides of length-1 axes, keepdims reductions and
np.medianlay out as NumPy's, and every zero-size array has NumPy's all-zero strides. - NumSharp on phones - proven end to end on two Android phones with ONNX Runtime's CPU, XNNPACK and NNAPI providers: an XNNPACK session's outputs now import without a copy, and float-to-int casts on Mono run 4.5-5.7x faster with NumPy's bytes.
- New documentation - the TorchSharp, Exceptions and NumPy Scalars pages, and a diagram of NumSharp's 18 released integrations opening the README and the Interoperability page.
- 36 NumPy-parity, memory-safety and tooling fixes, 2 measured speedups and 20 breaking changes, across the release's 243 commits.
- 1 new NuGet package - NumSharp.Interop.TorchSharp.
- 1,122,248 NumPy 2.5.4 oracle test cases (0.80.0: 1,119,305 NumPy 2.4.2 cases) and 21,115 test methods (0.80.0: 20,506).
📦 New NuGet Packages
- NumSharp.Interop.TorchSharp - zero-copy interop between
NDArrayand TorchSharp's tensors in both directions, withAuto/View/Copymodes.
Detailed Breakdown
Show All
📦 New NuGet Packages
One optional companion package ships for the first time, co-versioned with NumSharp (it depends on NumSharp). It converts arrays between NumSharp and TorchSharp, with no engine backend and no native asset of its own (it calls the libtorch that TorchSharp loads), so Core stays 100% managed without it.
- NumSharp.Interop.TorchSharp - zero-copy interop between
NDArrayand TorchSharp'storch.Tensor(the .NET bindings for libtorch, the engine under PyTorch), in both directions and without Python.- Modes - every verb takes
Auto(a view when the dtype and the layout allow it, else a copy; the default),View(shares memory or throws, naming what prevents the view) orCopy(always independent). - Export -
AsTensorhands the array's buffer to libtorch: every non-negative-stride layout (contiguous, sliced, transposed, stepped) crosses as the same strided tensor, a broadcast of writeable memory as torch's ownexpand, and libtorch releases the buffer when the last tensor over it is freed;ToTensorcopies. - Import -
AsNDArrayviews a CPU tensor's storage through its owndetach(), so the view survivesset_and the tensor'sDispose;ToNDArraycopies; a tensor that requires grad, and an expanded one, import read-only (t.detach().AsNDArray()is the writeable route). - Dtypes - the ten dtypes both sides share cross as themselves; uint16 / uint32 / uint64 / char / decimal export by NumPy's NEP 50 promotion (int32 / int64 / float64 / int32 / float64), and an explicit
dtypeconverts under NumPy's casting rule (same_kindby default); complex64 and bfloat16 tensors import widened exactly underAuto/Copy; a reversed view, a read-only array, a sparse, conjugated or non-CPU tensor copies underAuto; text arrays and quantized or meta tensors are refused in every mode. - Checks -
MayShareMemorytells whether a result shares the source's memory,ToScalarType/ToDTypemap the dtypes, and live export / import counters help leak checks. - Proven - a state matrix holds 45 array states x the ten shared dtypes x the three modes to NumPy 2.5.4's flags and
torch.from_numpy's layout, and 24 tensor states toTensor.numpy(), with the deliberate differences asserted (read-only, misaligned and off-16-byte complex128 arrays copy wherefrom_numpyshares). - Depends - TorchSharp 0.100.0 or later, the managed package only, with no upper bound (tested on 0.100.0 and 0.107.0); you reference the libtorch flavour you run (
TorchSharp-cpuor a CUDA package), and on macOS install Homebrew's OpenMP first (brew install libomp), which libtorch links by Homebrew's path.
- Modes - every verb takes
📊 Dashboards & Docs
- Supported Features Dashboard - headline 96.2% (538 / 559 in NumPy 2.5.4's catalog), 368 with NumPy's exact signature and 539 oracle-verified; its coverage generator 1.18.0 counts the whole NumPy API at 70.3% (2,747 of 3,908; 0.80.0's generator read 41.6% of 4,844), because it credits what NumSharp provides and stops counting what NumPy itself refuses.
- The ndarray operators and
numpy.char/chararrayare credited from the oracle cases that run them, NumPy's scalar types againstNDArray(which now models them), andStringDType's members againstDType. - Calls NumPy refuses (
np.sin.reduce,del a[i]) and the members a class only inherits (memmap,recarray,MaskedRecords,record) show as "Not counted" instead of gaps.
- The ndarray operators and
- Tests & Oracle Dashboard - 1,122,248 committed NumPy 2.5.4 oracle test cases over 1,455 operations (0.80.0: 1,119,305 NumPy 2.4.2 cases over 1,448), and 21,115 test declarations (0.80.0: 20,506).
- Benchmark Dashboard - benchmark evidence for 441 of 520 benchmarkable APIs (0.80.0: 452 of 518).
np.acos,np.asin,np.atan,np.atan2,np.pow,np.bitwise_invert,np.bitwise_left_shift,np.bitwise_right_shift,np.cumulative_sumandnp.cumulative_prod, which 0.80.0 credited through the functions they alias, are functions of their own now with no benchmark of their own, andnp.fromiter,np.fromfunctionandnp.ndimhave none yet.
- Documentation site - new pages and sections, whose code samples run as tests:
- TorchSharp - the new bridge, with what shares and what copies for 45 array states and 24 tensor states beside NumPy's and PyTorch's own answers.
- Exceptions - every Python and NumPy class NumSharp raises, in one hierarchy with its .NET base, Python's attributes and the catch footguns (
OverflowErroris notOverflowException). - NumPy Scalars - the class calls, read-only scalars, and a scalar against a 0-d array.
- The README and the Interoperability page open with a diagram of NumSharp's 18 released integrations.
✨ New APIs & Modules
- NumPy's scalars - NumSharp keeps no scalar classes of its own: NumPy's scalar is a read-only 0-d
NDArray, made at NumPy's own C-API points (PyArray_Return,PyArray_Scalar).np.float64(1.5),np.int8("12"),np.complex128(1, 2),np.str_(5),np.bytes_(5)- the class calls of NumPy's 36 scalar class names, ported from NumPy's*_arrtype_new(C# 14;NDScalarClassCalls.float64(x)on C# 12): 3,042 of 3,210 NumPy calls answered identically, every other one understood.- A 0-d result is the read-only scalar NumPy returns - every ufunc and operator over 0-d operands,
np.clip,np.round,np.dot/np.vdot/np.inner,np.sinc,np.nan_to_num,np.interpand the reductions; anout=array stays the array it was. - A full integer index (
a[1, 2],a[0]of a 1-D array,z[()],m[0, 1]) reads NumPy's scalar, a read-only copy of the element; every key of a scalar indexes a copy of its value (s[...]is a writeable 0-d array,s[0]NumPy's "invalid index to scalar variable.").
- Python's and NumPy's exceptions - every exception class of CPython 3.12 and NumPy 2.5.4 (47 new), each under a .NET twin and then Python's hierarchy, with Python's constructors, attributes and
str()texts, raised where NumPy and CPython raise them.ArithmeticError,OverflowError,ZeroDivisionError,FloatingPointError,MemoryError,ArrayMemoryError,EOFError,RecursionError,ReferenceError,NotImplementedError- the arithmetic, memory and runtime families, underArithmeticException,OutOfMemoryExceptionandEndOfStreamExceptionwhere .NET has a twin.OSErrorwitherrno/strerror/filename/winerrorand its 15 subclasses (FileNotFoundError,PermissionError,IsADirectoryError, ...), chosen by errno throughOSError.Createas Python's class call chooses them.UFuncTypeError,UFuncNoLoopError,UFuncBinaryResolutionError,UFuncInputCastingError,UFuncOutputCastingError- NumPy's ufunc refusals, withufunc,dtypes,casting,from_andto.SyntaxError/IndentationError/TabError(the location),NameError/UnboundLocalError/AttributeError(name,obj),UnicodeEncodeError/UnicodeDecodeError/UnicodeTranslateError(encoding,object,start,end,reason),StopIteration(value),SystemExit(code),KeyboardInterrupt,GeneratorExit,ImportError/ModuleNotFoundError,LapackError,ConverterError- Python's attributes.BaseExceptionGroup/ExceptionGroup- Python's groups, withsubgroup,splitandderive.- Every class takes .NET's
(message, innerException), Python'sraise X(msg) from e, and a bareX()reads Python'sstr().
- New functions and modules (17 new
np.*functions; the ten most used on GitHub:np.round,np.shape,np.ndim,np.fromiter,np.astype,np.row_stack(kept, although NumPy 2.5 removed it),np.pow,np.fromfunction,np.atanandnp.atan2) -np.round- NumPy 2's name for rounding (np.round_is gone).np.acos,np.asin,np.atan,np.atan2,np.pow,np.bitwise_invert,np.bitwise_left_shift,np.bitwise_right_shift- NumPy 2.0's Array-API names.np.cumulative_sum,np.cumulative_prod- NumPy 2.1's scans, withinclude_initial.np.ndim,np.shape,np.astype,np.fromiter,np.fromfunction,np.row_stackand the constantnp.little_endian.np.lib.stride_tricks.sliding_window_viewandnp.lib.stride_tricks.as_strided(NumPy's byte strides, kept inside the array's buffer).np.lib.array_utils(byte_bounds,normalize_axis_index,normalize_axis_tuple) andnp.lib.format(read_magic,read_array_header_1_0/2_0,write_array_header_1_0/2_0,read_array,write_array,header_data_from_array_1_0,dtype_to_descr,descr_to_dtype,drop_metadata).np.ma.MaskedArray(...),new np.NDIndex(2, 3),new np.NDIterator(...),new np.Broadcast(...)andnew NDCharArray(...)- NumPy's class calls, with NumPy's defaults.
descending=- NumPy 2.5's keyword-only descending sort onnp.sort,np.argsort,ndarray.sortandndarray.argsort: NaN still sorts last, ties land where NumPy's default introsort or its stable timsort / radix sort puts them, and aStringDTypearray, a masked array or akind=beside it is refused as NumPy refuses it.- NumPy's one signature - one overload in NumPy's parameter order, with NumPy's names, defaults and
Nones, over thirteen validated rounds (each pick compiled before and after at C# 12, with NumPy 2.4.2's answers as its tests): 1,047 NumPy names now take NumPy's exact signature (0.80.0: 719).NDAxis- NumPy's axis argument (None, an int or a tuple) as one type, sonp.sum(a, axis: (0, 2))is one reduction over the set with NumPy's bits; taken bysum,prod,mean,var,std,max/amax,min/amin, the seven nan reductions,all,any,count_nonzero,ptp,median/percentile/quantileand their nan forms,average,flip,squeeze,expand_dims,moveaxis,roll,trim_zeros,size,gradient,fft.fftshift,linalg.norm/vector_normandapply_over_axes, with theintandint[]forms kept beside it.Nonewherever NumPy takes it -axis: null(it was ambiguous for nine functions),size: nullfor everynp.randomsampler,order,density, and theshapeof the*_likefamily.- Creation -
np.linspaceandnp.geomspacetake array_like ends (float32 ends compute in float32,axis=, andretstep=for linspace),np.arange(start, stop, step, dtype, device)takes any array_like,np.zeros/ones/empty/fulltakeorderanddevice,np.reshapeNumPy'scopymodes,np.asanyarraycopy, andShapeis a C# collection (np.zeros([2, 3]),foreach (long d in a.Shape)). - Keywords -
np.stack(out,dtype,casting),np.hstack/np.vstack(dtype,casting),np.nansum/np.nanprod(initial,where),np.nanmean/np.nanvar/np.nanstd(where,mean,correction),np.ldexp(dtype),np.frexp/np.modf(out=(o1, o2)),np.tensordot(axes=(a, b)),np.require(any iterable of requirements), andnp.interp's fill values converted as NumPy converts them. - Result structs -
np.intersect1d(return_indices),np.average(returned),np.indices(sparse)andnp.linspace(retstep)return one value that converts to the array and deconstructs into NumPy's tuple. numpy.ma- the 48 masked ufuncs takeout/where/dtype, the reductions tuple axes and NumPy'sout=,ma.sort/ma.argsorttakekind/order/stable,ma.medianout/overwrite_input,ma.array/masked_arrayNumPy's argument order, andMaskedArraygainsbase,device,to_device,getfield,setfieldanditem(*args).finfo-nmant,iexp,nexp,machepandnegep;np.iinfo/np.finforead dtype strings as NumPy does.
- The bit generators'
Statesnapshots (MT19937,PCG64,PCG64DXSM,Philox,SFC64) andpoly1dare unsealed: a subclass engine carries its own state, and apoly1dsubclass's operations return a plainpoly1d, as NumPy's do.
🧩 ndarray surface
astype(dtype, order, casting, copy),reshape(shape, order, copy)(and loose integers),transpose(*axes),dot(b, out)and the reductions' tuple axes - NumPy's method signatures onNDArray,NDArray<T>,NDMatrix,NDCharArrayandNDMaskedArray.
⚡ Performance
Ratios are NumPy ÷ NumSharp - higher is better (x2 = twice NumPy's speed); xLOW->xHIGH spans the worst→best measured cell across sizes and dtypes.
x4.0->x6.7-np.argpartition/np.partitionwith onekthnear either end of a long contiguous line (a top-k) find it in one read: a 51,200-wide float32 row's top 5 and 1M elements (the argpartition was x0.44).x1.6->x2.0- the ONNX Runtime and ML.NET bridges'Postprocess.TopKselects withnp.argpartition(andnp.argmaxfor k = 1) instead of sorting the whole row, measured against NumPy's argpartition idiom over a 51,200-wide row (it was x0.12).
🎯 Parity & Fixes
- NumPy 2.5's behavior, as NumPy 2.5.4 answers -
- Linear algebra -
np.linalg.eig/eigvalsalways return complex,svd/lstsqrefuse inf or NaN withLinAlgErrorbefore LAPACK runs,condreads a failed SVD as NaN andp='nuc'sums the singular values,svd(hermitian=True)signs a zero eigenvalue +1, andtensorsolvereturns a view. - Random -
Generator'sbinomial,negative_binomialandmultinomialdraw through NumPy 2.5's corrected BTPE (RandomStatekeeps the legacy stream),SeedSequencerefuses nested sequences andspawna negative count,np.random.seedover a swapped bit generator drops the cached Gaussian, andchoice/multivariate_normalreturn views. - numpy.ma - a stored
fill_valueno longer follows a dtype change (converted with its errors caught, else dropped),mask_orpassesshrinkon, and the shared-maskresizetext is NumPy 2.5's. np.fft-ifft2,irfft2andhfftwrite the caller'sout=(it was checked, then ignored), and the forward transforms' invalid-normtext is NumPy 2.5's.- Text -
StringDTypecompares every byte (trailing NULs are characters), a loop takes the effective NA descriptor, products over text resolve a common descriptor, bytes cast toStringDTypeare checked as UTF-8, andmultiply/replace/zfill/ slicing follow NumPy 2.5's count and overflow rules. - Sorting and searching -
np.searchsortedruns NumPy 2.5's batched bisection and checks a sorter's middle entry even with no keys, andnp.uniqueand the set routines keep each NaN's own bits. - Reductions -
np.cumsum/np.cumprodrefuse anout=whose dimensions differ from the input's, and the quantile family answers several reduced axes beside a kept axis of length 0 (an empty result, not a reshape error). - Dtypes -
np.finfo(null)raisesTypeErrorand a non-float dtype names NumPy 2.5's text,np.isdtypeaccepts aStringDTypedescriptor, aStringDTypesub-array ('2T') is NumPy'sTypeError, the'a'alias is gone, andnp.sctypeDict/np.typecodesraiseKeyErrorfor a missing key. - Core -
np.wheremakes a Python-literal operand in the common dtype (an out-of-range literal isOverflowError; it wrapped),take/compresscheckout=in NumPy 2.5's direction, float16nextafterof equal zeros returns y, andndarray.resize's refusal is NumPy 2.5's wording.
- Linear algebra -
np.partition/np.argpartitionwith severalkth, and the quantile family, run NumPy'sintroselect_statement for statement: equal values land where NumPy puts them (the bytes, the sign of a ±0 tie innp.percentile/np.quantile,argpartition's tied indices, which NaN a NaN slice answers), with a singlekthand the speed kept; a zeronp.medianis +0.0 and a complex median followsnp.mean's statements (np.median([1+infj])isnan+infj).- float32 / float64
np.prodmultiplies in NumPy's sequentialmultiply.reduceorder on every route: NumPy's last bits, and an overflow before a zero is NaN (it was 0). - A fresh ufunc result takes NumPy's trivial-loop C / F allocation or NpyIter's K order, down to the strides of length-1 axes; a keepdims reduction keeps its axis at NumPy's stride,
np.medianis laid out as NumPy's mean of the partitioned copy (keepdims a stride-0 view), and every zero-size allocation has all-zero strides. np.ldexpof a contiguous view at an offset (annp.splitchild) reads the view (it scaled the owner's first elements), andnp.positiveof a read-only array is writeable.np.unwrap(p, 4)reads4asdiscont, NumPy's second parameter (it was the period-4 unwrap, a silent wrong answer).np.empty_like(a, null, 'F')is NumPy's F-ordered array ofa's shape (the order letter bound theShapeparameter and returned a(70,)array).np.zeros(t.Shape),np.ones,np.emptyandnp.fullof a transposed view's shape are C-ordered, as NumPy'snp.zeros(t.shape)is (they were F).np.arangewith C# float bounds is float64, as NumPy's Python floats give (it computed in float32), and a C#ulongbound is a Python int (np.arange(18446744073709551610UL, 18446744073709551615UL, 2UL)was an empty float32 array).np.linspacekeeps integer ends past 2^24 exact (np.linspace(-20000001, 20000001, 3); they were rounded to float32).np.asanyarray(300, np.int8)raises NumPy'sOverflowError(it wrapped to 44), andnp.asanyarray(5, np.str_)is<U1.np.finfo(float32 / float64).minexpis NumPy's -126 / -1022 (it was C's -125 / -1021), and float32'ssmallest_normal/tinyare exactly 2^-126.item()of a non-size-1 array anditem(i, j)with the wrong number of indices raise NumPy'sValueErrorand texts, andnp.repeat's negative-count text ends with NumPy's period.np.array(["SFFF", "FHFH", "FFFH", "HFFG"], "c")splits each text into its characters, NumPy's character dtype (Gymnasium's maps), and keeps the'c'type.np.subtractof two bool arrays withdtype=float64orint8computes as NumPy's (only the bool loop refuses).np.all/np.anyof anumpy.matrixalong an axis return NumPy's matrix (they returned plain arrays).np.unravel_index/np.ravel_multi_indextake shapes past int32 (a(2**40, 3)shape unravels).- numpy.ma -
np.ma.clipwith a masked bound masks those elements (the bound's mask was lost).np.ma.make_mask(m, False)/np.ma.mask_or(m1, m2, False)readFalseas NumPy'scopy(it wasshrink).np.ma.choosereads the choices filled with their own fill values (it read the raw data), andMaskedArray.chooseisndarray.choose(it ran the module form).- An F-ordered
astype/*_likeresult gets an F-ordered mask (it was C).
- Smaller alignments -
np.isscalar(np.array("x"))is False, as for any arraynp.arraybuilds.np.concatenatereports a later 0-d array as NumPy's rank mismatch.np.fft.fftshift/ifftshiftof a 0-d array raise NumPy's error (they returned a copy).
- NumSharp.Interop.OpenBLAS - bundles OpenBLAS 0.3.34.106.0, the build NumPy 2.5.4 ships (byte-identical to its library), so the products and LAPACK factorizations give NumPy 2.5.4's bits; the build-time version override now finds glibc Linux wheels by platform family, so it can move between manylinux2014 and manylinux_2_27 / 2_28 releases (it found no wheel).
- NumSharp.Build - deconstructing a result struct (
np.meshgrid,np.unique,np.gradient, the histograms, ...) after a deconstruction that held matrices returned the previous statement's arrays; the weaver no longer touches aDeconstruct. - NumSharp.Interop.OnnxRuntime - the outputs of an XNNPACK session (ONNX Runtime's Android / iOS CPU accelerator) import without a copy (they were refused as device memory), proven end to end for the CPU, XNNPACK and NNAPI providers on two Android phones, and the synchronous
Run's own overhead drops 30% per step of a 27-input decoder. - Float to int8 / uint8 / int16 / uint16 / int32 casts on hosts without the x86 vector cast (Mono's .NET for Android, iOS and WebAssembly) no longer call
Math.Truncateper element, which Mono compiles to a call: 4.5-5.7x faster on an arm64 Android phone, with NumPy's bytes for all 2^32 float32 inputs.
🧰 Testing & Tooling
- NumPy 2.5.4 is the oracle's NumPy, written once in
numpy-version.txt(the generators, the coverage generator, the workflows, the interop environments and the C# corpus gates read it), and every corpus and fixture is regenerated under it: the cases NumPy 2.5 fixed return (StringDTypebyteswap/place, raw text cell copies inchoose/put/putmask, invalid UTF-8,tofileof non-ASCII text), and the sort tier gainsdescending=True. - A second NumPy parity QA journey - about 372,000 probe comparisons over 160 log rows (random fuzzers, an ambiguity fuzzer compiling NumPy's call spellings at C# 12 and 14, NaN-identity, aliasing and layout sweeps): 62 findings, 58 of them new, each an
[OpenBugs]reproduction with a journal entry; 9 are fixed in this release. - Every answer of the 0.80.0 issue triage (34 issues closed, 4 progress comments) is a test: 35
Issue<n>classes assert each answer's claims against NumPy 2.4.2, and each gap an answer admits is an[OpenBugs]pin. - The np.* signature gap map is validated against its ground truth (the C# compiler for missing keywords, NumPy's runtime for refusals, tuples and defaults; 19 findings refuted), and
docs/plans/API_PARITY_DIFF.mdlists each change as a patch: the list the thirteen rounds were picked from. - Oracle tiers -
cast_boundary(float32 / float64 -> int8 ... int32 at every integer edge, NaN payloads and infinities, zero excuses; all 2^32 float32 inputs proven once against NumPy), the layout-parityufuncfamily (263 cases),np.linspaceover array ends, and the surface tier'scumulative_sum/cumulative_prod,fromiter,fromfunctionandsliding_window_view. - Releases pause before nuget.org until the owner approves the deployment: the publish job runs in the GitHub environment
nuget, and the nuget.org Trusted Publishing policy accepts only that environment.
💥 Breaking Changes
- NumPy's parameter names (calls that name the old ones must be renamed):
np.transpose(a, axes)(waspremute),np.array_equal(a1, a2),np.iscomplex/isreal/iscomplexobj/isrealobj(x),np.isscalar(element),np.array_repr(arr),np.cumsum/np.cumprod(a, axis, dtype, out)(werearr/typeCode),reshape(shape)(wasnewShape),np.unravel_index(indices, shape),np.ravel_multi_index(multi_index, dims, mode),np.insert(arr, obj, values),np.tensordot(a, b, axes: (a, b))(were two lists),np.ma.default_fill_value(obj),np.ma.size(obj)andMaskedArray.clip(min, max). - Removed names:
np.round_(usenp.round),np.average_returned/np.ma.average_returned(returned: true),np.indices_sparse(sparse: true), the genericnp.zeros<T>/ones<T>/empty<T>/full<T>/argsort<T>/finfo<T>/iinfo<T>/can_cast<TFrom, TTo>(pass the dtype),NDArray.Normalize()andAxisOutOfRangeException. - Calls that no longer compile:
np.zeros(shape, 'F')(nameorder: 'F'; NumPy reads that letter as a dtype),np.tile(a, 2, 2)(np.tile(a, (2, 2))),np.random.random_sample(2, 3)/rand(Shape)(random_sample((2, 3))/rand(2, 3)),astype(t, false)(astype(t, copy: false)),np.frexp(x, m, e)(out: (m, e)),np.ma.array(data, mask)(namemask:),np.ma.reshape(a, 2, 3)(a tuple),np.fft.fftfreqwith a floatn,dtype.newbyteorder('>')(">"), anobject-typed value tonp.insert/np.append, and a method group of a unary ufunc (Select(np.exp)needs a lambda). - Positional arguments that now land on NumPy's parameter: the fourth argument of
np.average/np.ma.averageisreturned(it waskeepdims, so namekeepdims:; a silent change), the second argument ofnp.unwrapisdiscont(it was the period; silent too), and akeepdimspassed after the axis ofnp.all/np.any/np.argmax/np.argminlands inoutand raises NumPy'sTypeError. - Refusals that follow NumPy:
np.can_castrefuses a Python number with NumPy's NEP 50TypeError(pass an array or a dtype),np.isdtype/np.issubdtype/np.iinfo/np.finforefuse arrays (passa.dtype),np.requireraisesKeyErrorfor an unknown requirement (it wasValueError), andnp.ma.amax/np.ma.amintake nofill_value. NpzFilehas NumPy's names:files,f,zip,fid,allow_pickle,max_header_size,keys(),values(),items(),get()andclose()(Files,F,Zip,AllowPickle,MaxHeaderSizeandClose()are gone).- Engine and subclass hooks: the
TensorEnginereductions (ReduceAdd...NanStd) andCountNonZerotakeNDAxis?,NDArray._collapse(result, NDAxis?)replaces theint?hook,TensorEngine.Geomspace/Interptake arrays, andUnravelIndex/RavelMultiIndextakelong[]dims. NDArray.Scalar(...)returns NumPy's read-only scalar (a write raisesValueError); build a mutable 0-d buffer withnp.array(x)ornp.zeros(Shape.Scalar, dtype).- A 0-d result of a ufunc, an operator,
np.clip,np.round,np.dotand the other return points is a read-only scalar, andnp.isscalar(np.array(5))is False. - An element read (
a[i, j],a[i]of a 1-D array) is a read-only copy, not a writeable 0-d view: write through the setter (a[i, j] = v); a read costs ~0.55 us (the view 0.36 us), so a hot loop keepsGetValue<T>/GetDouble. - NumPy's errors are Python's classes:
catch (OverflowException)/(DivideByZeroException)/(FileNotFoundException)/(KeyNotFoundException)no longer see them (catchOverflowError,ZeroDivisionError,FileNotFoundError,KeyError, or the .NET basesArithmeticException/IOException), and an exact-type check forTypeErrorno longer matches a ufunc refusal (aUFuncTypeError). - A bare Python-named exception's
Messageis Python'sstr()(""; it was the class name or .NET's default text); numpy.ma'stofile/compress_rows/compress_cols/compress_rowcols/mask_rowcols,notmasked_contiguousover more than 2-D and a seedlessSeedSequenceraise NumPy'sNotImplementedError, aRuntimeError(they raisedNotImplementedException/NotSupportedException); anditem()/MaskedArray.resizeraiseValueError(they raisedIncorrectSizeException/NotSupportedException). .stridesof fresh results follow NumPy's: length-1 axes of trivial-loop results and of keepdims reductions, every zero-size allocation (np.zeros((2, 0)).stridesis(0, 0)),np.median(..., keepdims: true)(a stride-0 view, OWNDATA false), andnp.zeros/ones/empty/full, which lay out from the dimensions alone (an FShapegives C; passorder: 'F').- float32 / float64
np.prodmultiplies sequentially, as NumPy does: the last bits change, an overflow before a zero is NaN, and a flat product runs at NumPy's speed (the SIMD lanes ran it 6-16x faster). np.partition/np.argpartitionwith severalktharrange equal values as NumPy's introselect does, so the bytes around tied values change.np.arangewith C# float bounds returns float64 (np.arange(0f, 1f, 0.1f)was float32).np.appendof a C# number appends NumPy's array of the Python number:np.append(int32_array, 5)is int64 andnp.append(float32_array, 1.5f)float64 (they kept the array's dtype).- NumPy 2.5's answers:
np.linalg.eig/eigvalsreturn complex even when every eigenvalue is real (take.real), a seededGenerator'sbinomial,negative_binomialandmultinomialdraw NumPy 2.5's corrected stream (np.random.*andRandomStatekeep the legacy one), andnp.unique/ the set routines keep a NaN's own bits (they returned the canonical NaN). - NumPy 2.5's refusals:
np.cross/np.linalg.crossof 2-element vectors (give them a zero third component),np.cumsum/np.cumprodinto anout=whose dimensions differ from the input's, the'a'dtype alias (np.dtype("a5"); write"S5"), andnp.finfo(null)(a null gave float64's limits). - NumPy 2.5's text rules: a
StringDTypetext's trailing NULs are characters (its length, the comparisons andstripsee them),byteswapof aStringDTypearray raises NumPy'sTypeError(it copied), a view orgetfieldthrough a separateStringDType()descriptor raises, and bytes that are not UTF-8 no longer cast toStringDType.
Install via NuGet
dotnet add package NumSharp --version 0.81.0
dotnet add package NumSharp.Bitmap --version 0.81.0
dotnet add package NumSharp.Interop.MLNet --version 0.81.0
dotnet add package NumSharp.Interop.OnnxRuntime --version 0.81.0
dotnet add package NumSharp.Interop.OpenBLAS --version 0.81.0
dotnet add package NumSharp.Interop.System.Numerics.Tensors --version 0.81.0
dotnet add package NumSharp.Interop.TorchSharp --version 0.81.0
dotnet add package NumSharp.Interop.pythonnet --version 0.81.0
dotnet add package NumSharp.Build --version 0.81.0