Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rarray rebuild #610

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
8 changes: 6 additions & 2 deletions extendr-api/src/error.rs
Expand Up @@ -62,8 +62,8 @@ pub enum Error {

ExpectedScalar(Robj),
ExpectedVector(Robj),
ExpectedArray(Robj),
ExpectedMatrix(Robj),
ExpectedMatrix3D(Robj),
ExpectedNumeric(Robj),
ExpectedAltrep(Robj),
ExpectedDataframe(Robj),
Expand All @@ -76,6 +76,7 @@ pub enum Error {
TypeMismatch(Robj),
NamespaceNotFound(Robj),
NoGraphicsDevices(Robj),
DimensionMismatch(usize, usize),

ExpectedExternalPtrType(Robj, String),
Other(String),
Expand Down Expand Up @@ -136,8 +137,8 @@ impl std::fmt::Display for Error {

Error::ExpectedScalar(robj) => write!(f, "Expected Scalar, got {:?}", robj.rtype()),
Error::ExpectedVector(robj) => write!(f, "Expected Vector, got {:?}", robj.rtype()),
Error::ExpectedArray(robj) => write!(f, "Expected Array, got {:?}", robj.rtype()),
Error::ExpectedMatrix(robj) => write!(f, "Expected Matrix, got {:?}", robj.rtype()),
Error::ExpectedMatrix3D(robj) => write!(f, "Expected Matrix3D, got {:?}", robj.rtype()),
Error::ExpectedNumeric(robj) => write!(f, "Expected Numeric, got {:?}", robj.rtype()),
Error::ExpectedAltrep(robj) => write!(f, "Expected Altrep, got {:?}", robj.rtype()),
Error::ExpectedDataframe(robj) => {
Expand All @@ -162,6 +163,9 @@ impl std::fmt::Display for Error {
write!(f, "Incorrect external pointer type {}", type_name)
}
Error::NoGraphicsDevices(_robj) => write!(f, "No graphics devices active."),
Error::DimensionMismatch(vec_len, dim_len) => {
write!(f, "The slice length ({}) does not match the length implied by the dimensions ({})", vec_len, dim_len)
}
Error::Other(str) => write!(f, "{}", str),

#[cfg(feature = "ndarray")]
Expand Down
9 changes: 4 additions & 5 deletions extendr-api/src/lib.rs
Expand Up @@ -763,12 +763,12 @@ mod tests {
// }

#[extendr]
pub fn symbol(x: Symbol) -> Symbol {
pub fn matrix(x: RMatrix<i32>) -> RMatrix<i32> {
x
}

#[extendr]
pub fn matrix(x: RMatrix<f64>) -> RMatrix<f64> {
pub fn symbol(x: Symbol) -> Symbol {
x
}

Expand Down Expand Up @@ -925,10 +925,9 @@ mod tests {
assert_eq!(Robj::from_sexp(wrap__symbol(robj.get())), robj);

// #[extendr]
// pub fn matrix(x: Matrix<&[f64]>) -> Matrix<&[f64]> { x }
// pub fn matrix(x: RMatrix<i32>) -> RMatrix<i32> { x }

let m = RMatrix::new_matrix(1, 2, |r, c| if r == c {1.0} else {0.});
let robj = r!(m);
let robj = r!(RMatrix::from_slice(&[1,2,3,4,5,6], [2,3]));
assert_eq!(Robj::from_sexp(wrap__matrix(robj.get())), robj);
}
}
Expand Down
4 changes: 2 additions & 2 deletions extendr-api/src/prelude.rs
Expand Up @@ -38,12 +38,12 @@ pub use crate::{

pub use super::wrapper::{
AltComplexImpl, AltIntegerImpl, AltLogicalImpl, AltRawImpl, AltRealImpl, AltStringImpl, Altrep,
AltrepImpl, RArray, RColumn, RMatrix, RMatrix3D,
AltrepImpl, RArray, RMatrix,
};

pub use super::wrapper::s4::S4;

pub use super::wrapper::{Conversions, MatrixConversions};
pub use super::wrapper::Conversions;

pub use super::robj::{
AsStrIter, Attributes, Eval, GetSexp, IntoRobj, Length, Operators, Rinternals, Robj,
Expand Down
23 changes: 3 additions & 20 deletions extendr-api/src/robj/from_robj.rs
@@ -1,5 +1,4 @@
use super::*;
use crate::wrapper::matrix::MatrixConversions;

/// Trait used for incomming parameter conversion.
pub trait FromRobj<'a>: Sized {
Expand Down Expand Up @@ -264,28 +263,12 @@ where
}
}

// Matrix input parameters.
impl<'a, T: 'a> FromRobj<'a> for RArray<T, [usize; 2]>
// RMatrix input parameters.
impl<'a, T: 'a> FromRobj<'a> for RMatrix<T>
where
Robj: AsTypedSlice<'a, T>,
{
fn from_robj(robj: &'a Robj) -> std::result::Result<Self, &'static str> {
match robj.as_matrix() {
Some(x) => Ok(x),
_ => Err("Expected a matrix."),
}
}
}

// Matrix input parameters.
impl<'a, T: 'a> FromRobj<'a> for RMatrix3D<T>
where
Robj: AsTypedSlice<'a, T>,
{
fn from_robj(robj: &'a Robj) -> std::result::Result<Self, &'static str> {
match robj.as_matrix3d() {
Some(x) => Ok(x),
_ => Err("Expected a matrix."),
}
RArray::try_from(robj).or_else(|_| Err("Expected a matrix."))
}
}
35 changes: 12 additions & 23 deletions extendr-api/src/robj/into_robj.rs
Expand Up @@ -618,35 +618,24 @@ pub trait RobjItertools: Iterator {
/// # Arguments
///
/// * `dims` - an array containing the length of each dimension
fn collect_rarray<'a, const LEN: usize>(
self,
dims: [usize; LEN],
) -> Result<RArray<Self::Item, [usize; LEN]>>
fn collect_rarray<'a, D>(self, dims: D) -> Result<RArray<Self::Item, D>>
where
Self: Iterator,
Self: Sized,
Self::Item: ToVectorValue,
D: AsRef<[usize]> + 'a,
Self: Iterator + Sized,
Self::Item: ToVectorValue + 'a + Clone,
Robj: AsTypedSlice<'a, Self::Item>,
Self::Item: 'a,
{
let vector = self.collect_robj();
let prod = dims.iter().product::<usize>();
let dims_ref = dims.as_ref();
let prod = dims_ref.iter().product::<usize>();
if prod != vector.len() {
return Err(Error::Other(format!(
"The vector length ({}) does not match the length implied by the dimensions ({})",
vector.len(),
prod
)));
return Err(Error::DimensionMismatch(vector.len(), prod));
}
let mut robj =
vector.set_attrib(wrapper::symbol::dim_symbol(), dims.iter().collect_robj())?;
let data = robj
.as_typed_slice_mut()
.ok_or(Error::Other(
"Unknown error in converting to slice".to_string(),
))?
.as_mut_ptr();
Ok(RArray::from_parts(robj, data, dims))
let robj = vector.set_attrib(
wrapper::symbol::dim_symbol(),
dims_ref.iter().collect_robj(),
)?;
Ok(RArray::new(robj, dims))
}
}

Expand Down