ndarray 0.3.0
ndarray: ^0.3.0 copied to clipboard
High-performance N-dimensional arrays and numerical operations with SIMD acceleration and BLAS/LAPACK bindings.
0.3.0 #
-
Breaking — Layered Single-Slot DType Projections &
SelfOf<R>:- Introduced eight one-parameter projection interfaces:
RealOf<R>,ElementOf<E>,RealFloatOf<R>,ComplexOf<R>,InexactOf<R>,AccumulatorOf<R>,DoublePrecisionOf<R>, andDivideOf<R>, plus the self-identity projection interfaceSelfOf<R>(each implementingDTypeTag), implemented byDTypeSpec. - Replaced the 8-positional-slot
DTypeSpec<...>wildcard bounds across library operation signatures and operator extensions (e.g.sin,sum,divide,abs,real,NDArrayDivide,NDArrayElements) with the single relevant*Of<R>interface bound. - Bounded same-dtype binary and multi-array operations (
add,subtract,multiply,divide,matmul,dot,atan2,hypot,bitwiseAnd,gcd,concatenate,stack,vstack,hstack,pad,copyto,binaryUfunc,outerUfunc,multivariateNormal, etc.) bySelfOf<...>. BecauseDTypeSpecimplementsSelfOfwhile the common supertypes of distinct concrete tags (DTypeTag,BitwiseDType,IntegerDType, or a shared projection interface such asDoublePrecisionOf<Float64>forFloat32/Int32) do not, mixed-dtype calls such asadd(f64, f32),add(i64, i32),divide(i64, i32),floatPower(f32, i32),bitwiseAnd(i64, i32), andconcatenate([f64, f32]), as well as mismatched output buffers such asadd(f64, f64, out: f32), are now rejected symmetrically at compile time in standarddart analyzewhile retaining a single type parameter<T>on dtype-preserving operations. - Multi-projection linear algebra operations (
slogdet,svd,eigh) retain fullDTypeSpectable bounds. - Public call sites with matching concrete dtypes preserve exact static type inference without requiring explicit type arguments or casts.
- Introduced eight one-parameter projection interfaces:
-
Breaking — True Division Projection (
DivideOf<R>&NDArrayDivide):- Added
DivideOf<R>(DivideTaginDTypeSpec) sodivide(a, b)anda / b(NDArrayDivide, withNDArrayBaseDividefallback onNDArray<DTypeTag>) both follow NumPy'strue_dividerule statically and at runtime: integer andBooleanoperands divide toFloat64, whileFloat16,BFloat16,Float32,Float64,Complex64, andComplex128divide to themselves (fixingFloat16andBFloat16/previously projectingFloat32statically while returning half-floats at runtime). - Fixed
Boolean'sInexactOf(InexactTag) projection fromFloat32toFloat64to match runtime promotion in transcendental operations.
- Added
-
Breaking — Non-Generic
BitwiseDType&IntegerDTypeCapability Markers (AnyBitwiseSpec&AnyIntegerSpec):- Converted
BitwiseDTypeandIntegerDTypeinto non-generic capability markers that statically pin constant projections across integer and boolean types:BitwiseDTypepinsRealFloatOf<Float64>,ComplexOf<Complex128>,InexactOf<Float64>,DoublePrecisionOf<Float64>, andDivideOf<Float64>.IntegerDTypeextendsBitwiseDTypeand additionally pinsElementOf<int>.- Neither marker pins
RealOforAccumulatorOf, which differ per integer tag; those remain specified only by each tag'sDTypeSpecrow.
- All eight integer tags (
Int64throughUint8) implementIntegerDType, andBooleanimplementsBitwiseDType. - Constrained
bitwiseAnd,bitwiseOr,bitwiseXor(T extends SelfOf<RealOf<BitwiseDType>>) andinvert(T extends RealOf<BitwiseDType>),leftShift,rightShift,gcd,lcm(T extends SelfOf<RealOf<IntegerDType>>), rejecting floating-point and complex arrays (as well as widenedNDArray<AnySpec>) at compile time. - The operator extensions stay on the markers (
NDArrayBitwise<T extends BitwiseDType>for&,|,^,~;NDArrayShift<T extends IntegerDType>for<<,>>), so concrete integer/boolean arrays,NDArray<IntegerDType>/NDArray<BitwiseDType>least upper bounds and marker-bounded generic code keep the operators. The newNDArrayBitwiseSpec/NDArrayShiftSpecextensions provide the same operators on the run-time-checked rows below. - Added
AnyBitwiseSpecandAnyIntegerSpec(DTypeSpecrows whoseRealTagisBitwiseDType/IntegerDType), changedasBitwiseDTypeto returnNDArray<AnyBitwiseSpec>andasIntegerDTypeto returnNDArray<AnyIntegerSpec>so run-time-typed arrays satisfy both the capability and theSelfOfbounds, and simplifiedasAnySpecto a zero-allocation cast. - Heterogeneous collections and least upper bounds (LUBs) such as
[i64, i32](List<NDArray<IntegerDType>>) and[i32, b](List<NDArray<BitwiseDType>>) preserve their pinned unary projections statically without requiring.asAnySpec(e.g.,sin([i64, i32].first)statically infersNDArray<Float64>), while rejecting mixed-dtype binary or concatenation calls (add(i64, i32),concatenate([i64, i32])) viaSelfOf. Because the markers do not implementRealOf, such values accept the bitwise operators but not thebitwiseAnd/invert/gcdfunctions; use.asIntegerDType/.asBitwiseDTypefor those.
- Converted
-
Composable Row Bounds for Generic Code (
InexactSpec<R>,DivideSpec<R>,DoublePrecisionSpec<R>):SelfOf<X>is not a subtype ofX, so a helper bounded byT extends SelfOf<InexactOf<R>>can callatan2(a, b)but notsin(a). AddedDTypeSpecrow aliases that pin a single projection slot —InexactSpec<R>,DivideSpec<R>,DoublePrecisionSpec<R>— alongsideAnySpec,AnyBitwiseSpecandAnyIntegerSpec: a row implements bothSelfOfand the projection, still rejects the LUB of two distinct tags, and infersRat call sites exactly like theSelfOfform (genericSinOfSum<T extends InexactSpec<R>, R>(a, b)on twoInt32arrays returnsNDArray<Float64>). Library signatures keepSelfOf<...>because its diagnostics name the one relevant projection.
-
Run-Time-Determined Result DTypes Default to
AnySpec:choose,multi_dot,lstsq,average,binaryUfunc,outerUfunc,unaryUfuncandUfuncNDArrayExtension.outertype their result only through an optionalout:/ explicit type argument (selectlikewise through its optionaldtype:). Their result type parameter is now bounded byAnySpecinstead ofDTypeTag, so withoutout:the result isNDArray<AnySpec>and composes with every operation (add(multi_dot([a, b]), c),sin(multi_dot([a, b]))) with run-time dtype validation, whileout: NDArray<Float32>still infersNDArray<Float32>. A bareNDArray<DTypeTag>can no longer be passed as thatout:(widen with.asAnySpec).
-
Breaking —
schur/complexSchurReplaceschur(output: SchurForm):schur(a)now computes the real Schur form with the exact static result dtypeInexactOfof the input (float64,float32,complex128,complex64preserved; integers,Booleanand half-precision floats computed infloat64), and the newcomplexSchur(a)computes the complex Schur form with theComplexOfprojection (complex64forfloat32/complex64,complex128otherwise). TheSchurFormenum and theoutput:parameter are removed;Booleaninput is now promoted like integer input instead of throwing.
-
Breaking —
out:Buffers Are Checked at Compile Time (Out extends T):- Every function whose
out:dtype must equal an input's dtype or a projection of it now types that buffer by a dependent type parameter declared last:sort<T extends DTypeTag, Out extends T>(NDArray<T> a, {NDArray<Out>? out}),sin<R extends DTypeTag, Out extends R>(NDArray<InexactOf<R>> x, {NDArray<Out>? out}),divide<T extends SelfOf<DivideOf<R>>, R extends DTypeTag, Out extends R>,sumAs<T, R, Out extends R>(a, DType<R> dtype, {NDArray<Out>? out}),schur<R, OutT extends R, OutZ extends R>,eig<R, OutEigenvalues extends R, OutEigenvectors extends R>,svd<T, R, OutU extends T, OutS extends R, OutVh extends T>(one parameter per field of a record-typedout),modf<R, Out1 extends R, Out2 extends R>, and so on across ~220 functions. Previouslysort(f64, out: f32)inferredT = DTypeTagand failed at run time; it is now a compile-timecould_not_infererror, whilesort(f64),sort(f64, out: f64),sort(dyn)andT extends DTypeTaggeneric callers are unchanged. Return types are unchanged (NDArray<T>/NDArray<R>). The same-dtype binary functions (add,matmul, ...) did not need this: theirSelfOf-boundedTalready rejects a mismatchedout:. - Creation-style functions whose dtype is chosen only by an optional
dtype:—uniform,randint,normal,exponential,poisson,binomial,multinomial,indices,hanning,hammingand theRandomGeneratormethods — are instead bounded byT extends AnySpecwithout: NDArray<T>, sodtype: DType.float32orout: f32alone infersNDArray<Float32>,uniform(shape, dtype: DType.float64, out: f32)is rejected, and the default result is the composableNDArray<AnySpec>. - Added
DType.asAnySpec(theDTypecounterpart ofNDArray.asAnySpec) for passing a run-time-chosen dtype to these functions.
- Every function whose
-
Mixed-DType
*AsBinary Operations & Expanded*AsCoverage:- Allowed mixed input dtypes (
<Ta, Tb, R>) inaddAs,subtractAs,multiplyAs, anddivideAswhen the targetDType<R>is explicitly specified, dispatching directly to single-pass mixed-dtype C++/SIMD kernels when the kernel output matchesdtype. - Added
floorDivideAs,remainderAs,modAs,fmodAs,divmodAs,powerAs,floatPower,floatPowerAs,minimum,minimumAs,maximum,maximumAs,fmin,fminAs,fmax,fmaxAs,matmulAs,dot,dotAs,tensordotAs,innerAs,vdotAs,kronAs,outerAs,crossAs,atan2As,hypotAs,logaddexpAs,logaddexp2As,copysignAs,heavisideAs,gcdAs,lcmAs,bitwiseAndAs,bitwiseOrAs,bitwiseXorAs,leftShiftAs, andrightShiftAs.
- Allowed mixed input dtypes (
-
dart2wasmFFI Compatibility:- Updated
r_nanmedian_complex128andr_nanmedian_complex64C/C++ reduction kernels and@ffi.Nativebindings to write results via an output pointer (cpx_t*/cpx_f_t*) rather than returningffi.Structby value, satisfyingdart2wasm's@ffi.Nativerestrictions.
- Updated
-
Native C++ Kernel Size & Compile-Time Optimization:
- Factored
s_cast_generic,ndarray_compare,s_histogram_uniform,s_histogram_binsearch, and masked/overlapping ufunc loops inhook/custom_ufuncs.cppto eliminate quadratic template instantiation and cold-loop unrolling, reducing native library binary size by ~74% (from ~19 MB to ~5 MB) and C++ source-build compile time by ~20x while preserving contiguous SIMD fast paths.
- Factored
-
Migration Guide:
- Explicit type arguments on
out:-bearing functions:sin<Float64>(x),sumAs<Int32, Int64>(a, DType.int64),schur<Float64, Float64>(a)no longer match the parameter count. Drop them — inference produces the same types — or add the new trailing parameter(s). out:buffers must match statically: create the buffer with the concrete dtype of the input (NDArray.zeros(shape, DType.float64)for aFloat64input), or, when the dtype is only known at run time, widen both the input and the buffer with.asAnySpecso the dtype is validated at run time as before. AnNDArray<DTypeTag>input still accepts anyout:(sort(dyn, out: f32)).- Creation functions with a run-time dtype: pass
dtype: dt.asAnySpec(or declare dtype lists as<DType<AnySpec>>[...]); aDType<DTypeTag>argument no longer compiles foruniform,hanning, etc. - Wildcard Bounds: Replace generic helper bounds that previously spelled 8-slot wildcards such as
T extends DTypeSpec<DTypeTag, Object?, DTypeTag, DTypeTag, R, DTypeTag, DTypeTag, DTypeTag>with the single relevant projection interface, e.g.T extends InexactOf<R>(for transcendental and math operations),T extends AccumulatorOf<R>(forsum/prod),T extends DivideOf<R>(for division),T extends ElementOf<E>(for element extraction),T extends RealFloatOf<R>,T extends ComplexOf<R>, orT extends DoublePrecisionOf<R>. - Generic Helpers Calling Same-DType Operations: A helper that forwards arrays of one type parameter
Ttoadd,matmul,concatenate,gcd,atan2, etc. must boundTthe same way the callee does:T extends SelfOf<DTypeTag>,T extends SelfOf<RealOf<IntegerDType>>, orT extends SelfOf<InexactOf<R>>.T extends DTypeTagandT extends IntegerDTypeno longer compile for those calls. If the helper also needs a projecting unary operation on the sameT(sin,invert,/), bound it by the corresponding row instead —AnySpec,InexactSpec<R>,DivideSpec<R>,DoublePrecisionSpec<R>,AnyBitwiseSpec,AnyIntegerSpec— and prefer the function forms (invert(a),bitwiseAnd(a, b)) over the operators there, which resolve to the non-generic*Specextensions and widen to the row. - Calling Same-DType Operations on Widened
NDArray<DTypeTag>: Passing dynamically-typedNDArray(NDArray<DTypeTag>),NDArray<BitwiseDType>, orNDArray<IntegerDType>directly toadd,matmul,concatenate, etc. requires widening toNDArray<AnySpec>(via.asAnySpec, or by creating the array with aDType<AnySpec>),NDArray<AnyBitwiseSpec>(via.asBitwiseDType), orNDArray<AnyIntegerSpec>(via.asIntegerDType), or using the*Asvariants (addAs,matmulAs, ...) with an explicit targetDType<R>. schur(a, output: SchurForm.complex)becomescomplexSchur(a);schur(a, output: SchurForm.real)and explicitschur<T, R>(a)type arguments becomeschur(a).- Capability Marker Type Arguments: Remove generic type arguments from
BitwiseDType<...>andIntegerDType<...>. Reference them as plain non-generic markers (BitwiseDType,IntegerDType) or useAnyBitwiseSpec/AnyIntegerSpecwhenSelfOfcompatibility is required. - Element Access on
NDArray<BitwiseDType>/NDArray<AnyBitwiseSpec>: Static element-access expressions (asBitwiseDType.toList(),getCell,scalar) onNDArray<BitwiseDType>/NDArray<AnyBitwiseSpec>now inferList<dynamic>/dynamicrather thanList<Object>/Object. This occurs becauseBitwiseDTypeencompasses both integer tags (ElementOf<int>) andBoolean(ElementOf<bool>), and Dart interface type parameters are invariant. When integer element types are needed, useNDArray<IntegerDType>or.asIntegerDType(which providesElementOf<int>).
- Explicit type arguments on
0.2.0 #
- 64-Bit Array Dimensions, Strides, & Native Kernels: Removed the 32-bit (
2^31 - 1) element count, shape dimension, and stride ceiling acrossNDArraycreation, slicing, broadcasting,.npy/.npzI/O, FFT (package:pocketfft0.2.0), and native C/C++ kernels (int64_t), with division-based 64-bit signed integer overflow checks. - Breaking —
NDArray<Int64>Index, Count, & Choice Operations: Widenedargsort,argpartition,searchsorted,argmax,argmin,nonzero,flatnonzero,argwhere,count_nonzero, anddigitize(along withNDArray.argsort,NDArray.argmax,NDArray.argmin, and 1-argumentwhere) fromNDArray<Int32>toNDArray<Int64>to match 64-bit NumPyintp(argsortAs,argpartitionAs,searchsortedAs, anddigitizeAsremain available for explicitDType.int32outputs). Updatedselectandmultinomialto default toDType.int64instead ofDType.int32, and alignedchooseandselectwith NEP 50 weak scalar promotion rules when mixing Dartintscalars with narrow integer arrays. - 64-Bit Index Generation & Coordinate Utilities: Added
unravel_index(unravelIndex),ravel_multi_index(ravelMultiIndex),indices,sparse_indices(sparseIndices),diag_indices(diagIndices),diag_indices_from(diagIndicesFrom),tril_indices(trilIndices),tril_indices_from(trilIndicesFrom),triu_indices(triuIndices),triu_indices_from(triuIndicesFrom),mask_indices(maskIndices), andIndexOrder, all returningNDArray<Int64>coordinates. - OpenBLAS / LAPACK
blasintBoundary Guards: Added explicit LP64 32-bitblasintboundary checks across linear algebra and tensor contraction routines, throwing anUnsupportedErrorwhen matrix dimensions or leading strides exceed2^31 - 1.
0.1.0 #
- Initial release with N-dimensional arrays, slicing, broadcasting, BLAS/LAPACK linear algebra, and FFT.