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