Take the following R function:
'# @param x A nxn matrix
'# @param y A 1xn matrix (vector)
foo = function(x, y) {
return(x %*% diag(1 / y)
}
What it does is to transform each element of the 1xn y
vector into 1/y and diagonalize it into a nxn matrix with 1/y in it’s diagonal. Then the matrix product x %*% diag(1/y)
produces a nxn matrix consisting of each element from the jth column of x
matrix divided by the jth element of y
. Pretty standard.
Since R may be slow working with big matrices (e.g., 5000×5000), I’d like to take a shot with Rust. After setting up the project structure with {extendr}, lib.rs
looks like:
use extendr_api::prelude::*;
use nalgebra as na;
/// Calculates ratio x/y.
/// @param x A nxn matrix.
/// @param y A 1xn vector.
/// @return A nxn matrix.
/// @export
#[extendr]
fn foo(
x: na::DMatrix<f64>,
y: na::DVector<f64>,
) -> na::DMatrix<f64> {
let inv_y = y.map(|y| 1.0 / y);
let m = x * na::Matrix::from_diagonal(&inv_y);
m
}
// Macro to generate exports.
// This ensures exported functions are registered with R.
// See corresponding C code in `entrypoint.c`.
extendr_module! {
mod package_name;
fn foo;
}
foo
does compile with no errors in Rust. But trying to integrate with R, I get the error no function or associated item named 'from_robj' found for struct 'Matrix' in the current scope
. I guess what is missing is constructing a {extendr} wrapper for Matrix type.
How to proceed from here?
Reproducible example of foo
in Rust:
use nalgebra as na;
fn foo(
x: na::DMatrix<f64>,
y: na::DVector<f64>,
) -> na::DMatrix<f64> {
let inv_y = y.map(|y| 1.0 / y);
let m = x * na::Matrix::from_diagonal(&inv_y);
m
}
fn main() {
let x = na::DMatrix::from_row_slice(3, 3, &[100.0, 150.0, 200.0, 200.0, 100.0, 300.0, 400.0, 100.0, 50.0]);
let y = na::DVector::from_row_slice(&[1000.0, 2000.0, 4000.0]);
let m = foo(x, y);
println!("{:?}", m);
}