Expand description
N-dimensional R arrays with const generic dimension count. N-dimensional R arrays with const generic dimension count.
This module provides RArray<T, NDIM>, a wrapper around R arrays that
tracks the number of dimensions at compile time.
§Type Aliases
| Alias | Type | R Equivalent |
|---|---|---|
RVector<T> | RArray<T, 1> | vector (with dim) |
RMatrix<T> | RArray<T, 2> | matrix |
RArray3D<T> | RArray<T, 3> | array(..., dim=c(a,b,c)) |
§Memory Layout
R arrays are stored in column-major (Fortran) order. For a 2×3 matrix:
Logical layout: Memory layout:
[0,0] [0,1] [0,2] [0,0] [1,0] [0,1] [1,1] [0,2] [1,2]
[1,0] [1,1] [1,2]The get method handles index translation automatically.
§Thread Safety
RArray is !Send and !Sync - it cannot be transferred to or accessed
from other threads. This is because the underlying R APIs (DATAPTR_RO, etc.)
must be called on the R main thread.
For functions that use RArray/RMatrix parameters, you must use
#[miniextendr(unsafe(main_thread))] to ensure execution on the main thread.
For worker-thread usability, use to_vec() to copy data
on the main thread, then pass the owned Vec to worker threads.
§Performance
For best performance, prefer slice-based and column-based access over per-element indexing:
| Method | Speed | Use Case |
|---|---|---|
as_slice() | Fastest | Full-buffer iteration, SIMD |
column() | Fast | Per-column operations (matrices) |
column_mut() | Fast | Per-column mutation |
get() / get_rc() | Slower | Single-element access |
Why? Per-element methods like get() perform index translation and bounds
checks on every call. For tight loops, this overhead dominates.
// Slow: per-element access
for row in 0..nrow {
for col in 0..ncol {
let val = unsafe { matrix.get_rc(row, col) };
}
}
// Fast: slice-based iteration
for val in unsafe { matrix.as_slice() } {
// ...
}
// Fast: column-wise iteration (columns are contiguous in R)
for col in 0..ncol {
for val in unsafe { matrix.column(col) } {
// ...
}
}§Example
use miniextendr_api::rarray::{RMatrix, RArray};
// Must run on main thread due to RMatrix parameter
#[miniextendr(unsafe(main_thread))]
fn matrix_sum(m: RMatrix<f64>) -> f64 {
unsafe { m.as_slice().iter().sum() }
}Macros§
- impl_
rarray_ 🔒try_ from_ sexp_ coerce - Implement
TryFromSexp for RArray<$target, NDIM>by reading R’s native$sourcetype.
Structs§
- RArray
- An N-dimensional R array.
Functions§
- get_
dims 🔒 ⚠ - Get dimensions from SEXP as array.
- get_
ndim 🔒 - Get number of dimensions from SEXP.
- set_
dims 🔒 ⚠ - Set dimensions on a SEXP.
- validate_
coercion 🔒 - Helper to validate all elements can be coerced.