Skip to main content

ndarray 0.3.0 copy "ndarray: ^0.3.0" to clipboard
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>, and DivideOf<R>, plus the self-identity projection interface SelfOf<R> (each implementing DTypeTag), implemented by DTypeSpec.
    • 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.) by SelfOf<...>. Because DTypeSpec implements SelfOf while the common supertypes of distinct concrete tags (DTypeTag, BitwiseDType, IntegerDType, or a shared projection interface such as DoublePrecisionOf<Float64> for Float32/Int32) do not, mixed-dtype calls such as add(f64, f32), add(i64, i32), divide(i64, i32), floatPower(f32, i32), bitwiseAnd(i64, i32), and concatenate([f64, f32]), as well as mismatched output buffers such as add(f64, f64, out: f32), are now rejected symmetrically at compile time in standard dart analyze while retaining a single type parameter <T> on dtype-preserving operations.
    • Multi-projection linear algebra operations (slogdet, svd, eigh) retain full DTypeSpec table bounds.
    • Public call sites with matching concrete dtypes preserve exact static type inference without requiring explicit type arguments or casts.
  • Breaking — True Division Projection (DivideOf<R> & NDArrayDivide):

    • Added DivideOf<R> (DivideTag in DTypeSpec) so divide(a, b) and a / b (NDArrayDivide, with NDArrayBaseDivide fallback on NDArray<DTypeTag>) both follow NumPy's true_divide rule statically and at runtime: integer and Boolean operands divide to Float64, while Float16, BFloat16, Float32, Float64, Complex64, and Complex128 divide to themselves (fixing Float16 and BFloat16 / previously projecting Float32 statically while returning half-floats at runtime).
    • Fixed Boolean's InexactOf (InexactTag) projection from Float32 to Float64 to match runtime promotion in transcendental operations.
  • Breaking — Non-Generic BitwiseDType & IntegerDType Capability Markers (AnyBitwiseSpec & AnyIntegerSpec):

    • Converted BitwiseDType and IntegerDType into non-generic capability markers that statically pin constant projections across integer and boolean types:
      • BitwiseDType pins RealFloatOf<Float64>, ComplexOf<Complex128>, InexactOf<Float64>, DoublePrecisionOf<Float64>, and DivideOf<Float64>.
      • IntegerDType extends BitwiseDType and additionally pins ElementOf<int>.
      • Neither marker pins RealOf or AccumulatorOf, which differ per integer tag; those remain specified only by each tag's DTypeSpec row.
    • All eight integer tags (Int64 through Uint8) implement IntegerDType, and Boolean implements BitwiseDType.
    • Constrained bitwiseAnd, bitwiseOr, bitwiseXor (T extends SelfOf<RealOf<BitwiseDType>>) and invert (T extends RealOf<BitwiseDType>), leftShift, rightShift, gcd, lcm (T extends SelfOf<RealOf<IntegerDType>>), rejecting floating-point and complex arrays (as well as widened NDArray<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 new NDArrayBitwiseSpec / NDArrayShiftSpec extensions provide the same operators on the run-time-checked rows below.
    • Added AnyBitwiseSpec and AnyIntegerSpec (DTypeSpec rows whose RealTag is BitwiseDType / IntegerDType), changed asBitwiseDType to return NDArray<AnyBitwiseSpec> and asIntegerDType to return NDArray<AnyIntegerSpec> so run-time-typed arrays satisfy both the capability and the SelfOf bounds, and simplified asAnySpec to 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 infers NDArray<Float64>), while rejecting mixed-dtype binary or concatenation calls (add(i64, i32), concatenate([i64, i32])) via SelfOf. Because the markers do not implement RealOf, such values accept the bitwise operators but not the bitwiseAnd / invert / gcd functions; use .asIntegerDType / .asBitwiseDType for those.
  • Composable Row Bounds for Generic Code (InexactSpec<R>, DivideSpec<R>, DoublePrecisionSpec<R>):

    • SelfOf<X> is not a subtype of X, so a helper bounded by T extends SelfOf<InexactOf<R>> can call atan2(a, b) but not sin(a). Added DTypeSpec row aliases that pin a single projection slot — InexactSpec<R>, DivideSpec<R>, DoublePrecisionSpec<R> — alongside AnySpec, AnyBitwiseSpec and AnyIntegerSpec: a row implements both SelfOf and the projection, still rejects the LUB of two distinct tags, and infers R at call sites exactly like the SelfOf form (genericSinOfSum<T extends InexactSpec<R>, R>(a, b) on two Int32 arrays returns NDArray<Float64>). Library signatures keep SelfOf<...> because its diagnostics name the one relevant projection.
  • Run-Time-Determined Result DTypes Default to AnySpec:

    • choose, multi_dot, lstsq, average, binaryUfunc, outerUfunc, unaryUfunc and UfuncNDArrayExtension.outer type their result only through an optional out: / explicit type argument (select likewise through its optional dtype:). Their result type parameter is now bounded by AnySpec instead of DTypeTag, so without out: the result is NDArray<AnySpec> and composes with every operation (add(multi_dot([a, b]), c), sin(multi_dot([a, b]))) with run-time dtype validation, while out: NDArray<Float32> still infers NDArray<Float32>. A bare NDArray<DTypeTag> can no longer be passed as that out: (widen with .asAnySpec).
  • Breaking — schur / complexSchur Replace schur(output: SchurForm):

    • schur(a) now computes the real Schur form with the exact static result dtype InexactOf of the input (float64, float32, complex128, complex64 preserved; integers, Boolean and half-precision floats computed in float64), and the new complexSchur(a) computes the complex Schur form with the ComplexOf projection (complex64 for float32 / complex64, complex128 otherwise). The SchurForm enum and the output: parameter are removed; Boolean input 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-typed out), modf<R, Out1 extends R, Out2 extends R>, and so on across ~220 functions. Previously sort(f64, out: f32) inferred T = DTypeTag and failed at run time; it is now a compile-time could_not_infer error, while sort(f64), sort(f64, out: f64), sort(dyn) and T extends DTypeTag generic callers are unchanged. Return types are unchanged (NDArray<T> / NDArray<R>). The same-dtype binary functions (add, matmul, ...) did not need this: their SelfOf-bounded T already rejects a mismatched out:.
    • Creation-style functions whose dtype is chosen only by an optional dtype: — uniform, randint, normal, exponential, poisson, binomial, multinomial, indices, hanning, hamming and the RandomGenerator methods — are instead bounded by T extends AnySpec with out: NDArray<T>, so dtype: DType.float32 or out: f32 alone infers NDArray<Float32>, uniform(shape, dtype: DType.float64, out: f32) is rejected, and the default result is the composable NDArray<AnySpec>.
    • Added DType.asAnySpec (the DType counterpart of NDArray.asAnySpec) for passing a run-time-chosen dtype to these functions.
  • Mixed-DType *As Binary Operations & Expanded *As Coverage:

    • Allowed mixed input dtypes (<Ta, Tb, R>) in addAs, subtractAs, multiplyAs, and divideAs when the target DType<R> is explicitly specified, dispatching directly to single-pass mixed-dtype C++/SIMD kernels when the kernel output matches dtype.
    • 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, and rightShiftAs.
  • dart2wasm FFI Compatibility:

    • Updated r_nanmedian_complex128 and r_nanmedian_complex64 C/C++ reduction kernels and @ffi.Native bindings to write results via an output pointer (cpx_t* / cpx_f_t*) rather than returning ffi.Struct by value, satisfying dart2wasm's @ffi.Native restrictions.
  • Native C++ Kernel Size & Compile-Time Optimization:

    • Factored s_cast_generic, ndarray_compare, s_histogram_uniform, s_histogram_binsearch, and masked/overlapping ufunc loops in hook/custom_ufuncs.cpp to 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.
  • 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 a Float64 input), or, when the dtype is only known at run time, widen both the input and the buffer with .asAnySpec so the dtype is validated at run time as before. An NDArray<DTypeTag> input still accepts any out: (sort(dyn, out: f32)).
    • Creation functions with a run-time dtype: pass dtype: dt.asAnySpec (or declare dtype lists as <DType<AnySpec>>[...]); a DType<DTypeTag> argument no longer compiles for uniform, 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> (for sum/prod), T extends DivideOf<R> (for division), T extends ElementOf<E> (for element extraction), T extends RealFloatOf<R>, T extends ComplexOf<R>, or T extends DoublePrecisionOf<R>.
    • Generic Helpers Calling Same-DType Operations: A helper that forwards arrays of one type parameter T to add, matmul, concatenate, gcd, atan2, etc. must bound T the same way the callee does: T extends SelfOf<DTypeTag>, T extends SelfOf<RealOf<IntegerDType>>, or T extends SelfOf<InexactOf<R>>. T extends DTypeTag and T extends IntegerDType no longer compile for those calls. If the helper also needs a projecting unary operation on the same T (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 *Spec extensions and widen to the row.
    • Calling Same-DType Operations on Widened NDArray<DTypeTag>: Passing dynamically-typed NDArray (NDArray<DTypeTag>), NDArray<BitwiseDType>, or NDArray<IntegerDType> directly to add, matmul, concatenate, etc. requires widening to NDArray<AnySpec> (via .asAnySpec, or by creating the array with a DType<AnySpec>), NDArray<AnyBitwiseSpec> (via .asBitwiseDType), or NDArray<AnyIntegerSpec> (via .asIntegerDType), or using the *As variants (addAs, matmulAs, ...) with an explicit target DType<R>.
    • schur(a, output: SchurForm.complex) becomes complexSchur(a); schur(a, output: SchurForm.real) and explicit schur<T, R>(a) type arguments become schur(a).
    • Capability Marker Type Arguments: Remove generic type arguments from BitwiseDType<...> and IntegerDType<...>. Reference them as plain non-generic markers (BitwiseDType, IntegerDType) or use AnyBitwiseSpec / AnyIntegerSpec when SelfOf compatibility is required.
    • Element Access on NDArray<BitwiseDType> / NDArray<AnyBitwiseSpec>: Static element-access expressions (asBitwiseDType.toList(), getCell, scalar) on NDArray<BitwiseDType> / NDArray<AnyBitwiseSpec> now infer List<dynamic> / dynamic rather than List<Object> / Object. This occurs because BitwiseDType encompasses both integer tags (ElementOf<int>) and Boolean (ElementOf<bool>), and Dart interface type parameters are invariant. When integer element types are needed, use NDArray<IntegerDType> or .asIntegerDType (which provides ElementOf<int>).

0.2.0 #

  • 64-Bit Array Dimensions, Strides, & Native Kernels: Removed the 32-bit (2^31 - 1) element count, shape dimension, and stride ceiling across NDArray creation, slicing, broadcasting, .npy/.npz I/O, FFT (package:pocketfft 0.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: Widened argsort, argpartition, searchsorted, argmax, argmin, nonzero, flatnonzero, argwhere, count_nonzero, and digitize (along with NDArray.argsort, NDArray.argmax, NDArray.argmin, and 1-argument where) from NDArray<Int32> to NDArray<Int64> to match 64-bit NumPy intp (argsortAs, argpartitionAs, searchsortedAs, and digitizeAs remain available for explicit DType.int32 outputs). Updated select and multinomial to default to DType.int64 instead of DType.int32, and aligned choose and select with NEP 50 weak scalar promotion rules when mixing Dart int scalars 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), and IndexOrder, all returning NDArray<Int64> coordinates.
  • OpenBLAS / LAPACK blasint Boundary Guards: Added explicit LP64 32-bit blasint boundary checks across linear algebra and tensor contraction routines, throwing an UnsupportedError when matrix dimensions or leading strides exceed 2^31 - 1.

0.1.0 #

  • Initial release with N-dimensional arrays, slicing, broadcasting, BLAS/LAPACK linear algebra, and FFT.
0
likes
150
points
228
downloads

Documentation

API reference

Publisher

unverified uploader

Weekly Downloads

High-performance N-dimensional arrays and numerical operations with SIMD acceleration and BLAS/LAPACK bindings.

Repository (GitHub)
View/report issues
Contributing

Topics

#numerical #math #ffi #science #matrix

License

unknown (license)

Dependencies

code_assets, crypto, ffi, hooks, meta, openblas, pocketfft, resource_scope

More

Packages that depend on ndarray