Skip to content

Implement a convenience method DenseMatrix::from_ndarray2 (in case the ndarray feature is on) #326

@Mec-iS

Description

@Mec-iS

Example code (place in a module that depends on both smartcore and ndarray)

use std::fmt::{Debug, Display};
use ndarray::{ArrayBase, Ix2, OwnedRepr};
use smartcore::linalg::basic::arrays::Array2;
use smartcore::linalg::basic::matrix::DenseMatrix;

// Convert an ndarray owned 2D array into a smartcore DenseMatrix by copying.
pub fn from_ndarray2<T>(a: &ArrayBase<OwnedRepr<T>, Ix2>) -> DenseMatrix<T>
where
    T: Debug + Display + Copy + Sized,
{
    // SmartCore’s Array2::from_iterator(iter, nrows, ncols, axis)
    // axis == 0 means values are consumed in row-major and DenseMatrix will be created row-major=false internally,
    // which DenseMatrix::from_iterator translates correctly into its internal representation. [1]
    DenseMatrix::from_iterator(a.iter().copied(), a.nrows(), a.ncols(), 0)
}

Why this works

  • smartcore defines a generic Array2::from_iterator for DenseMatrix that builds a matrix from any iterator of T with explicit shape and an axis flag to reconcile layout. Passing axis=0 matches the straightforward row-wise iteration over ndarray’s elements produced by a.iter().[1]
  • DenseMatrix’s Array2::from_iterator is implemented as DenseMatrix::new(nrows, ncols, iter.collect(), axis != 0), and DenseMatrix::new enforces shape consistency; this path is the same used throughout the library for safe construction.[1]

If a borrowed view is needed

  • For ArrayView<'_, T, Ix2> (or ArrayViewMut), convert to an owned array first: let owned = view.to_owned(); then call ndarray_to_densematrix(&owned).[1]

Optional: return Result instead of panicking

pub fn from_ndarray2_result<T>(
    a: &ArrayBase<OwnedRepr<T>, Ix2>,
) -> Result<DenseMatrix<T>, smartcore::error::Failed>
where
    T: Debug + Display + Copy + Sized,
{
    // Use the same constructor but avoid unwrap; if you prefer, replicate logic with DenseMatrix::new.
    Ok(DenseMatrix::from_iterator(a.iter().copied(), a.nrows(), a.ncols(), 0))
}

Notes

  • This copies data; a zero-copy adapter would require exposing DenseMatrix internals or constructing a DenseMatrix over ndarray’s buffer with exact column-major constraints. That’s not exposed in the current public API, so copying is the safe route.
  • smartcore already offers ndarray bindings to operate on ndarray-native matrices directly by implementing Array2 for ndarray::Array2, so in many cases DenseMatrix isn’t necessary — algorithms accept types implementing the Array2 trait. Prefer passing ndarray arrays directly to smartcore algorithms when possible.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions