1use faer::{mat, Mat, MatRef};
2
3use crate::scalar::Rfloat;
4use crate::*;
5
6impl From<Mat<f64>> for RMatrix<f64> {
8 fn from(value: Mat<f64>) -> Self {
9 RMatrix::new_matrix(value.nrows(), value.ncols(), |i, j| value.read(i, j))
10 }
11}
12
13impl From<Mat<f64>> for Robj {
14 fn from(value: Mat<f64>) -> Self {
15 RMatrix::<f64>::from(value).into()
16 }
17}
18
19impl From<MatRef<'_, f64>> for RMatrix<f64> {
21 fn from(value: MatRef<'_, f64>) -> Self {
23 RMatrix::new_matrix(value.nrows(), value.ncols(), |i, j| value.read(i, j))
24 }
25}
26
27impl From<MatRef<'_, f64>> for Robj {
28 fn from(value: MatRef<'_, f64>) -> Self {
29 RMatrix::<f64>::from(value).into_robj()
30 }
31}
32
33impl From<Mat<f64>> for RMatrix<Rfloat> {
34 fn from(value: Mat<f64>) -> Self {
35 RMatrix::new_matrix(value.nrows(), value.ncols(), |i, j| value.read(i, j).into())
36 }
37}
38
39impl From<MatRef<'_, f64>> for RMatrix<Rfloat> {
40 fn from(value: MatRef<f64>) -> Self {
41 RMatrix::new_matrix(value.nrows(), value.ncols(), |i, j| {
42 Rfloat::from(value.read(i, j))
43 })
44 }
45}
46
47impl From<RMatrix<f64>> for Mat<f64> {
48 fn from(value: RMatrix<f64>) -> Self {
49 let nrow = value.nrows();
50 let ncol = value.ncols();
51 let slice = value.as_real_slice().expect("RMatrix should be doubles");
52 Mat::from_fn(nrow, ncol, |i, j| slice[i + j * nrow])
53 }
54}
55
56impl<'a> From<&'_ RMatrix<f64>> for MatRef<'a, f64> {
57 fn from(value: &RMatrix<f64>) -> Self {
58 let nrow = value.nrows();
59 let ncol = value.ncols();
60 let slice = value.as_typed_slice().expect("RMatrix should be doubles");
61 let mat_ref = faer::mat::from_column_major_slice(slice, nrow, ncol);
62 mat_ref
63 }
64}
65
66impl TryFrom<&Robj> for Mat<f64> {
67 type Error = Error;
68
69 fn try_from(robj: &Robj) -> Result<Self> {
70 let rmat = &RMatrix::<f64>::try_from(robj)?;
71 let nrow = rmat.nrows();
72 let ncol = rmat.ncols();
73
74 if let Some(slice) = robj.as_real_slice() {
75 let fmat = Mat::from_fn(nrow, ncol, |i, j| slice[i + j * nrow]);
76 Ok(fmat)
77 } else {
78 Err(Error::ExpectedReal(robj.clone()))
79 }
80 }
81}
82
83impl<'a> TryFrom<&'_ Robj> for MatRef<'a, f64> {
84 type Error = Error;
85
86 fn try_from(robj: &Robj) -> Result<Self> {
87 let rmat = &RMatrix::<f64>::try_from(robj)?;
88 let nrows = rmat.nrows();
89 let ncols = rmat.ncols();
90
91 if let Some(slice) = robj.as_typed_slice() {
92 let fmat = mat::from_column_major_slice(slice, nrows, ncols);
93 Ok(fmat)
94 } else {
95 Err(Error::ExpectedReal(robj.clone()))
96 }
97 }
98}
99
100impl TryFrom<Robj> for Mat<f64> {
101 type Error = crate::Error;
102
103 fn try_from(robj: Robj) -> Result<Self> {
104 Self::try_from(&robj)
105 }
106}
107
108impl<'a> TryFrom<Robj> for MatRef<'a, f64> {
109 type Error = crate::Error;
110
111 fn try_from(robj: Robj) -> Result<Self> {
112 Self::try_from(&robj)
113 }
114}
115
116impl From<RMatrix<i32>> for Mat<f64> {
117 fn from(value: RMatrix<i32>) -> Self {
118 let nrow = value.nrows();
119 let ncol = value.ncols();
120 let slice = value
121 .as_integer_slice()
122 .expect("RMatrix should be integers");
123 Mat::from_fn(nrow, ncol, |i, j| slice[i + j * nrow] as f64)
124 }
125}
126
127#[cfg(test)]
128mod test {
129 use crate as extendr_api;
130 use crate::*;
131 use faer::{mat, Mat, MatRef};
132
133 #[test]
134 fn test_rmatrix_to_faer_mat() {
135 test! {
136 let values = [
137 [1.0, 5.0, 9.0],
138 [2.0, 6.0, 10.0],
139 [3.0, 7.0, 11.0],
140 [4.0, 8.0, 12.0f64]
141 ];
142 let a = Mat::<f64>::from_fn(4, 3, |i, j| values[i][j] as f64);
143
144 let rmatrix = RMatrix::new_matrix(4, 3, |i, j| values[i][j]);
145 let b = Mat::<f64>::try_from(rmatrix);
146 assert_eq!(a, b.expect("matrix to be converted"));
147 }
148 }
149
150 #[test]
151 fn test_rmatrix_to_faer_mat_with_nan() {
152 test! {
153 let values = [
154 [1.0, 5.0, 9.0],
155 [2.0, 6.0, 10.0],
156 [3.0, 7.0, 11.0],
157 [f64::NAN, 8.0, 12.0f64]
158 ];
159
160 let rmatrix = RMatrix::new_matrix(4, 3, |i, j| values[i][j]);
161 let b = Mat::<f64>::try_from(rmatrix);
162 assert!(b.expect("matrix to be converted").read(3, 0).is_nan());
163 }
164 }
165
166 #[test]
167 fn test_rmatrix_to_faer_mat_ref() {
168 test! {
169 let values = [
170 [1.0, 5.0, 9.0],
171 [2.0, 6.0, 10.0],
172 [3.0, 7.0, 11.0],
173 [4.0, 8.0, 12.0f64]
174 ];
175 let mat = Mat::<f64>::from_fn(4, 3, |i, j| values[i][j] as f64);
176 let a = mat.as_ref();
177
178 let rmatrix = RMatrix::new_matrix(4, 3, |i, j| values[i][j]);
179 let b = MatRef::<f64>::try_from(&rmatrix);
180 assert_eq!(a, b.expect("matrix to be converted"));
181 }
182 }
183
184 #[test]
185 fn test_faer_mat_to_rmatrix() {
186 test! {
187 let vec: Vec<f64> = (1..13).map(f64::from).collect();
188 let a = mat![
189 [1.0, 5.0, 9.0],
190 [2.0, 6.0, 10.0],
191 [3.0, 7.0, 11.0],
192 [4.0, 8.0, 12.0f64],
193 ];
194 let rmatrix: RMatrix<f64> = a.into();
195 assert_eq!(rmatrix.as_real_slice().expect("slice"), &vec);
196 }
197 }
198
199 #[test]
200 fn test_faer_mat_ref_to_rmatrix() {
201 test! {
202 let vec: Vec<f64> = (1..13).map(f64::from).collect();
203 let a = mat![
204 [1.0, 5.0, 9.0],
205 [2.0, 6.0, 10.0],
206 [3.0, 7.0, 11.0],
207 [4.0, 8.0, 12.0f64],
208 ];
209 let rmatrix: RMatrix<f64> = a.as_ref().into();
210 assert_eq!(rmatrix.as_real_slice().expect("slice"), &vec);
211 }
212 }
213
214 #[test]
215 fn test_try_from_robj_to_faer_mat() {
216 test! {
217 let values = [
218 [1.0, 5.0, 9.0],
219 [2.0, 6.0, 10.0],
220 [3.0, 7.0, 11.0],
221 [4.0, 8.0, 12.0f64]
222 ];
223 let a = Mat::<f64>::from_fn(4, 3, |i, j| values[i][j] as f64);
224
225 let rmatrix = RMatrix::new_matrix(4, 3, |i, j| values[i][j]);
226 let b = Mat::<f64>::try_from(&Robj::from(rmatrix));
227 assert_eq!(a, b.expect("matrix to be converted"));
228 }
229 }
230
231 #[test]
232 fn test_try_from_robj_to_faer_mat_ref() {
233 test! {
234 let values = [
235 [1.0, 5.0, 9.0],
236 [2.0, 6.0, 10.0],
237 [3.0, 7.0, 11.0],
238 [4.0, 8.0, 12.0f64]
239 ];
240 let mat = Mat::<f64>::from_fn(4, 3, |i, j| values[i][j] as f64);
241 let a = mat.as_ref();
242
243 let rmatrix = RMatrix::new_matrix(4, 3, |i, j| values[i][j]);
244 let robj = Robj::from(rmatrix);
245 let b = MatRef::<f64>::try_from(&robj);
246 assert_eq!(a, b.expect("matrix to be converted"));
247 }
248 }
249
250 #[test]
251 fn test_int_rmatrix_to_faer_mat() {
252 test! {
253 let values = [
254 [1, 5, 9],
255 [2, 6, 10],
256 [3, 7, 11],
257 [4, 8, 12]
258 ];
259 let a = Mat::<f64>::from_fn(4, 3, |i, j| values[i][j] as f64);
260
261 let rmatrix = RMatrix::new_matrix(4, 3, |i, j| values[i][j]);
262 let b = Mat::<f64>::try_from(rmatrix);
263 assert_eq!(a, b.expect("matrix to be converted"));
264 }
265 }
266}