gloss_utils/nshare.rs
1#![allow(unexpected_cfgs)]
2#![cfg(not(doctest))]
3
4/// Converts a 1d type to a ndarray 1d array type.
5///
6/// This uses an associated type to avoid ambiguity for the compiler.
7/// By calling this, the compiler always knows the returned type.
8pub trait ToNdarray1 {
9 type Out;
10
11 fn into_ndarray1(self) -> Self::Out;
12}
13
14/// Converts a 2d type to a ndarray 2d array type.
15///
16/// Coordinates are in (row, col).
17///
18/// This uses an associated type to avoid ambiguity for the compiler.
19/// By calling this, the compiler always knows the returned type.
20pub trait ToNdarray2 {
21 type Out;
22
23 fn into_ndarray2(self) -> Self::Out;
24}
25
26/// Converts a 3d type to a ndarray 2d array type.
27///
28/// Coordinates are in `(channel, row, col)`, where channel is typically a color
29/// channel, or they are in `(z, y, x)`.
30///
31/// This uses an associated type to avoid ambiguity for the compiler.
32/// By calling this, the compiler always knows the returned type.
33pub trait ToNdarray3 {
34 type Out;
35
36 fn into_ndarray3(self) -> Self::Out;
37}
38
39/// Borrows a 1d type to a ndarray 1d array type.
40///
41/// This uses an associated type to avoid ambiguity for the compiler.
42/// By calling this, the compiler always knows the returned type.
43pub trait RefNdarray1 {
44 type Out;
45
46 fn ref_ndarray1(self) -> Self::Out;
47}
48
49/// Borrows a 2d type to a ndarray 2d array type.
50///
51/// Coordinates are in (row, col).
52///
53/// This uses an associated type to avoid ambiguity for the compiler.
54/// By calling this, the compiler always knows the returned type.
55pub trait RefNdarray2 {
56 type Out;
57
58 fn ref_ndarray2(self) -> Self::Out;
59}
60
61/// Borrows a 3d type to a ndarray 2d array type.
62///
63/// Coordinates are in `(channel, row, col)`, where channel is typically a color
64/// channel, or they are in `(z, y, x)`.
65///
66/// This uses an associated type to avoid ambiguity for the compiler.
67/// By calling this, the compiler always knows the returned type.
68pub trait RefNdarray3 {
69 type Out;
70
71 fn ref_ndarray3(self) -> Self::Out;
72}
73
74/// Mutably borrows a 1d type to a ndarray 1d array type.
75///
76/// This uses an associated type to avoid ambiguity for the compiler.
77/// By calling this, the compiler always knows the returned type.
78pub trait MutNdarray1 {
79 type Out;
80
81 fn mut_ndarray1(self) -> Self::Out;
82}
83
84/// Mutably borrows a 2d type to a ndarray 2d array type.
85///
86/// Coordinates are in (row, col).
87///
88/// This uses an associated type to avoid ambiguity for the compiler.
89/// By calling this, the compiler always knows the returned type.
90pub trait MutNdarray2 {
91 type Out;
92
93 fn mut_ndarray2(self) -> Self::Out;
94}
95
96/// Mutably borrows a 3d type to a ndarray 2d array type.
97///
98/// Coordinates are in `(channel, row, col)`, where channel is typically a color
99/// channel, or they are in `(z, y, x)`.
100///
101/// This uses an associated type to avoid ambiguity for the compiler.
102/// By calling this, the compiler always knows the returned type.
103pub trait MutNdarray3 {
104 type Out;
105
106 fn mut_ndarray3(self) -> Self::Out;
107}
108
109/// Converts a 1 or 2 dimensional type to a nalgebra type.
110///
111/// This uses an associated type to avoid ambiguity for the compiler.
112/// By calling this, the compiler always knows the returned type.
113pub trait ToNalgebra {
114 type Out;
115
116 fn into_nalgebra(self) -> Self::Out;
117}
118
119use core::convert::TryFrom;
120use nalgebra::Dyn as Dy;
121
122/// ```
123/// use nshare::ToNalgebra;
124///
125/// let arr = ndarray::arr1(&[0.1, 0.2, 0.3, 0.4]);
126/// let m = arr.view().into_nalgebra();
127/// assert!(m.iter().eq(&[0.1, 0.2, 0.3, 0.4]));
128/// assert_eq!(m.shape(), (4, 1));
129/// ```
130impl<'a, T> ToNalgebra for ndarray::ArrayView1<'a, T>
131where
132 T: nalgebra::Scalar,
133{
134 // type Out = nalgebra::DVectorSlice<'a, T>;
135 type Out = nalgebra::DVectorView<'a, T>;
136 fn into_nalgebra(self) -> Self::Out {
137 let len = Dy(self.len());
138 let ptr = self.as_ptr();
139 let stride: usize = TryFrom::try_from(self.strides()[0]).expect("Negative stride");
140 let storage = unsafe { nalgebra::ViewStorage::from_raw_parts(ptr, (len, nalgebra::Const::<1>), (nalgebra::Const::<1>, Dy(stride))) };
141 nalgebra::Matrix::from_data(storage)
142 }
143}
144/// ```
145/// use nshare::ToNalgebra;
146///
147/// let mut arr = ndarray::arr1(&[0.1, 0.2, 0.3, 0.4]);
148/// let m = arr.view_mut().into_nalgebra();
149/// assert!(m.iter().eq(&[0.1, 0.2, 0.3, 0.4]));
150/// assert_eq!(m.shape(), (4, 1));
151/// ```
152#[allow(clippy::drop_non_drop)]
153impl<'a, T> ToNalgebra for ndarray::ArrayViewMut1<'a, T>
154where
155 T: nalgebra::Scalar,
156{
157 type Out = nalgebra::DVectorViewMut<'a, T>;
158 fn into_nalgebra(mut self) -> Self::Out {
159 let len = Dy(self.len());
160 let stride: usize = TryFrom::try_from(self.strides()[0]).expect("Negative stride");
161 let ptr = self.as_mut_ptr();
162 let storage = unsafe {
163 // Drop to not have simultaneously the ndarray and nalgebra valid.
164 drop(self);
165 nalgebra::ViewStorageMut::from_raw_parts(ptr, (len, nalgebra::Const::<1>), (nalgebra::Const::<1>, Dy(stride)))
166 };
167 nalgebra::Matrix::from_data(storage)
168 }
169}
170
171/// ```
172/// use nshare::ToNalgebra;
173///
174/// let arr = ndarray::arr1(&[0.1, 0.2, 0.3, 0.4]);
175/// let m = arr.into_nalgebra();
176/// assert!(m.iter().eq(&[0.1, 0.2, 0.3, 0.4]));
177/// assert_eq!(m.shape(), (4, 1));
178/// ```
179impl<T> ToNalgebra for ndarray::Array1<T>
180where
181 T: nalgebra::Scalar,
182{
183 type Out = nalgebra::DVector<T>;
184 fn into_nalgebra(self) -> Self::Out {
185 let len = Dy(self.len());
186 Self::Out::from_vec_generic(len, nalgebra::Const::<1>, self.into_raw_vec_and_offset().0)
187 }
188}
189
190/// ```
191/// use nshare::ToNalgebra;
192///
193/// let arr = ndarray::arr2(&[
194/// [0.1, 0.2, 0.3, 0.4],
195/// [0.5, 0.6, 0.7, 0.8],
196/// [1.1, 1.2, 1.3, 1.4],
197/// [1.5, 1.6, 1.7, 1.8],
198/// ]);
199/// let m = arr.view().into_nalgebra();
200/// assert!(m.row(1).iter().eq(&[0.5, 0.6, 0.7, 0.8]));
201/// assert_eq!(m.shape(), (4, 4));
202/// assert!(arr
203/// .t()
204/// .into_nalgebra()
205/// .column(1)
206/// .iter()
207/// .eq(&[0.5, 0.6, 0.7, 0.8]));
208/// ```
209impl<'a, T> ToNalgebra for ndarray::ArrayView2<'a, T>
210where
211 T: nalgebra::Scalar,
212{
213 type Out = nalgebra::DMatrixView<'a, T, Dy, Dy>;
214 fn into_nalgebra(self) -> Self::Out {
215 let nrows = Dy(self.nrows());
216 let ncols = Dy(self.ncols());
217 let ptr = self.as_ptr();
218 let stride_row: usize = TryFrom::try_from(self.strides()[0]).expect("Negative row stride");
219 let stride_col: usize = TryFrom::try_from(self.strides()[1]).expect("Negative column stride");
220 let storage = unsafe { nalgebra::ViewStorage::from_raw_parts(ptr, (nrows, ncols), (Dy(stride_row), Dy(stride_col))) };
221 nalgebra::Matrix::from_data(storage)
222 }
223}
224
225/// ```
226/// use nshare::ToNalgebra;
227///
228/// let mut arr = ndarray::arr2(&[
229/// [0.1, 0.2, 0.3, 0.4],
230/// [0.5, 0.6, 0.7, 0.8],
231/// [1.1, 1.2, 1.3, 1.4],
232/// [1.5, 1.6, 1.7, 1.8],
233/// ]);
234/// let m = arr.view_mut().into_nalgebra();
235/// assert!(m.row(1).iter().eq(&[0.5, 0.6, 0.7, 0.8]));
236/// assert_eq!(m.shape(), (4, 4));
237/// assert!(arr
238/// .view_mut()
239/// .reversed_axes()
240/// .into_nalgebra()
241/// .column(1)
242/// .iter()
243/// .eq(&[0.5, 0.6, 0.7, 0.8]));
244/// ```
245#[allow(clippy::drop_non_drop)]
246impl<'a, T> ToNalgebra for ndarray::ArrayViewMut2<'a, T>
247where
248 T: nalgebra::Scalar,
249{
250 type Out = nalgebra::DMatrixViewMut<'a, T, Dy, Dy>;
251 fn into_nalgebra(mut self) -> Self::Out {
252 let nrows = Dy(self.nrows());
253 let ncols = Dy(self.ncols());
254 let stride_row: usize = TryFrom::try_from(self.strides()[0]).expect("Negative row stride");
255 let stride_col: usize = TryFrom::try_from(self.strides()[1]).expect("Negative column stride");
256 let ptr = self.as_mut_ptr();
257 let storage = unsafe {
258 // Drop to not have simultaneously the ndarray and nalgebra valid.
259 drop(self);
260 nalgebra::ViewStorageMut::from_raw_parts(ptr, (nrows, ncols), (Dy(stride_row), Dy(stride_col)))
261 };
262 nalgebra::Matrix::from_data(storage)
263 }
264}
265
266/// ```
267/// use nshare::ToNalgebra;
268///
269/// let mut arr = ndarray::arr2(&[
270/// [0.1, 0.2, 0.3, 0.4],
271/// [0.5, 0.6, 0.7, 0.8],
272/// [1.1, 1.2, 1.3, 1.4],
273/// [1.5, 1.6, 1.7, 1.8],
274/// ]);
275/// let m = arr.clone().into_nalgebra();
276/// assert!(m.row(1).iter().eq(&[0.5, 0.6, 0.7, 0.8]));
277/// assert_eq!(m.shape(), (4, 4));
278/// assert!(arr
279/// .reversed_axes()
280/// .into_nalgebra()
281/// .column(1)
282/// .iter()
283/// .eq(&[0.5, 0.6, 0.7, 0.8]));
284/// ```
285impl<T> ToNalgebra for ndarray::Array2<T>
286where
287 T: nalgebra::Scalar,
288{
289 type Out = nalgebra::DMatrix<T>;
290 fn into_nalgebra(self) -> Self::Out {
291 let std_layout = self.is_standard_layout();
292 let nrows = Dy(self.nrows());
293 let ncols = Dy(self.ncols());
294 // let mut res = Self::Out::from_vec_generic(nrows, ncols, self.into_raw_vec());
295 let res = {
296 if std_layout {
297 let res = Self::Out::from_row_slice(self.nrows(), self.ncols(), self.as_slice().unwrap());
298 res
299 } else {
300 Self::Out::from_vec_generic(nrows, ncols, self.into_raw_vec_and_offset().0)
301 }
302 };
303 // if std_layout {
304 // // This can be expensive, but we have no choice since nalgebra VecStorage
305 // is always // column-based.
306 // res.transpose_mut();
307 // }
308 res
309 }
310}
311
312use nalgebra::{
313 dimension::U1,
314 storage::{Storage, StorageMut},
315 Dim, Matrix, Scalar, Vector, ViewStorage, ViewStorageMut,
316};
317use ndarray::{ArrayView1, ArrayView2, ArrayViewMut1, ArrayViewMut2, ShapeBuilder};
318
319/// ```
320/// use nalgebra::Vector4;
321/// use ndarray::s;
322/// use nshare::RefNdarray1;
323///
324/// let m = Vector4::new(0.1, 0.2, 0.3, 0.4f32);
325/// let arr = m.ref_ndarray1();
326/// assert!(arr.iter().eq(&[0.1, 0.2, 0.3, 0.4]));
327/// assert_eq!(arr.dim(), 4);
328/// ```
329impl<'a, N: Scalar, R: Dim, S> RefNdarray1 for &'a Vector<N, R, S>
330where
331 S: Storage<N, R, U1>,
332{
333 type Out = ArrayView1<'a, N>;
334
335 fn ref_ndarray1(self) -> Self::Out {
336 unsafe { ArrayView1::from_shape_ptr((self.shape().0,).strides((self.strides().0,)), self.as_ptr()) }
337 }
338}
339
340/// ```
341/// use nalgebra::Vector4;
342/// use ndarray::s;
343/// use nshare::MutNdarray1;
344///
345/// let mut m = Vector4::new(0.1, 0.2, 0.3, 0.4f32);
346/// // Set everything to 0.
347/// m.mut_ndarray1().fill(0.0);
348/// assert!(m.iter().eq(&[0.0; 4]));
349/// ```
350impl<'a, N: Scalar, R: Dim, S> MutNdarray1 for &'a mut Vector<N, R, S>
351where
352 S: StorageMut<N, R, U1>,
353{
354 type Out = ArrayViewMut1<'a, N>;
355
356 fn mut_ndarray1(self) -> Self::Out {
357 unsafe { ArrayViewMut1::from_shape_ptr((self.shape().0,).strides((self.strides().0,)), self.as_ptr().cast_mut()) }
358 }
359}
360
361/// ```
362/// use nalgebra::Vector4;
363/// use nshare::ToNdarray1;
364///
365/// let m = Vector4::new(0.1, 0.2, 0.3, 0.4f32);
366/// let arr = m.rows(0, 4).into_ndarray1();
367/// assert!(arr.iter().eq(&[0.1, 0.2, 0.3, 0.4]));
368/// assert_eq!(arr.dim(), 4);
369/// ```
370impl<'a, N: Scalar, R: Dim, RStride: Dim, CStride: Dim> ToNdarray1 for Vector<N, R, ViewStorage<'a, N, R, U1, RStride, CStride>> {
371 type Out = ArrayView1<'a, N>;
372
373 fn into_ndarray1(self) -> Self::Out {
374 unsafe { ArrayView1::from_shape_ptr((self.shape().0,).strides((self.strides().0,)), self.as_ptr()) }
375 }
376}
377
378/// ```
379/// use nalgebra::{dimension::U2, Const, Vector4};
380/// use nshare::ToNdarray1;
381///
382/// let mut m = Vector4::new(0.1, 0.2, 0.3, 0.4);
383/// let arr = m
384/// .rows_generic_with_step_mut::<Const<2>>(0, Const::<2>, 1)
385/// .into_ndarray1()
386/// .fill(0.0);
387/// assert!(m.iter().eq(&[0.0, 0.2, 0.0, 0.4]));
388/// ```
389impl<'a, N: Scalar, R: Dim, RStride: Dim, CStride: Dim> ToNdarray1 for Matrix<N, R, U1, ViewStorageMut<'a, N, R, U1, RStride, CStride>> {
390 type Out = ArrayViewMut1<'a, N>;
391
392 fn into_ndarray1(self) -> Self::Out {
393 unsafe { ArrayViewMut1::from_shape_ptr((self.shape().0,).strides((self.strides().0,)), self.as_ptr().cast_mut()) }
394 }
395}
396
397/// ```
398/// use nalgebra::Matrix4;
399/// use ndarray::s;
400/// use nshare::RefNdarray2;
401///
402/// let m = Matrix4::new(
403/// 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8,
404/// );
405/// let arr = m.ref_ndarray2();
406/// assert!(arr.slice(s![1, ..]).iter().eq(&[0.5, 0.6, 0.7, 0.8]));
407/// assert_eq!(arr.dim(), (4, 4));
408/// ```
409impl<'a, N: Scalar, R: Dim, C: Dim, S> RefNdarray2 for &'a Matrix<N, R, C, S>
410where
411 S: Storage<N, R, C>,
412{
413 type Out = ArrayView2<'a, N>;
414
415 fn ref_ndarray2(self) -> Self::Out {
416 unsafe { ArrayView2::from_shape_ptr(self.shape().strides(self.strides()), self.as_ptr()) }
417 }
418}
419
420/// ```
421/// use nalgebra::Matrix4;
422/// use ndarray::s;
423/// use nshare::MutNdarray2;
424///
425/// let mut m = Matrix4::new(
426/// 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8,
427/// );
428/// let arr = m.mut_ndarray2().slice_mut(s![1, ..]).fill(0.0);
429/// assert!(m.row(1).iter().eq(&[0.0; 4]));
430/// ```
431impl<'a, N: Scalar, R: Dim, C: Dim, S> MutNdarray2 for &'a mut Matrix<N, R, C, S>
432where
433 S: StorageMut<N, R, C>,
434{
435 type Out = ArrayViewMut2<'a, N>;
436
437 fn mut_ndarray2(self) -> Self::Out {
438 unsafe { ArrayViewMut2::from_shape_ptr(self.shape().strides(self.strides()), self.as_ptr().cast_mut()) }
439 }
440}
441
442/// ```
443/// use nalgebra::Matrix4;
444/// use nshare::ToNdarray2;
445///
446/// let m = Matrix4::new(
447/// 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8,
448/// );
449/// let arr = m.row(1).into_ndarray2();
450/// assert!(arr.iter().eq(&[0.5, 0.6, 0.7, 0.8]));
451/// assert_eq!(arr.dim(), (1, 4));
452/// ```
453impl<'a, N: Scalar, R: Dim, C: Dim, RStride: Dim, CStride: Dim> ToNdarray2 for Matrix<N, R, C, ViewStorage<'a, N, R, C, RStride, CStride>> {
454 type Out = ArrayView2<'a, N>;
455
456 fn into_ndarray2(self) -> Self::Out {
457 unsafe { ArrayView2::from_shape_ptr(self.shape().strides(self.strides()), self.as_ptr()) }
458 }
459}
460
461/// ```
462/// use nalgebra::Matrix4;
463/// use nshare::ToNdarray2;
464///
465/// let mut m = Matrix4::new(
466/// 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8,
467/// );
468/// let arr = m.row_mut(1).into_ndarray2().fill(0.0);
469/// assert!(m.row(1).iter().eq(&[0.0; 4]));
470/// ```
471impl<'a, N: Scalar, R: Dim, C: Dim, RStride: Dim, CStride: Dim> ToNdarray2 for Matrix<N, R, C, ViewStorageMut<'a, N, R, C, RStride, CStride>> {
472 type Out = ArrayViewMut2<'a, N>;
473
474 fn into_ndarray2(self) -> Self::Out {
475 unsafe { ArrayViewMut2::from_shape_ptr(self.shape().strides(self.strides()), self.as_ptr().cast_mut()) }
476 }
477}
478
479#[cfg(feature = "nalgebra_std")]
480mod std_impl {
481 use super::*;
482 use nalgebra::{allocator::Allocator, DVector, DefaultAllocator, Dynamic, VecStorage};
483 use ndarray::{Array1, Array2};
484 /// ```
485 /// use nalgebra::DVector;
486 /// use ndarray::s;
487 /// use nshare::ToNdarray1;
488 ///
489 /// let m = DVector::from_vec(vec![0.1, 0.2, 0.3, 0.4]);
490 /// let arr = m.into_ndarray1();
491 /// assert_eq!(arr.dim(), 4);
492 /// assert!(arr.iter().eq(&[0.1, 0.2, 0.3, 0.4]));
493 /// ```
494 impl<'a, N: Scalar> ToNdarray1 for DVector<N> {
495 type Out = Array1<N>;
496
497 fn into_ndarray1(self) -> Self::Out {
498 Array1::from_shape_vec((self.shape().0,), self.data.into()).unwrap()
499 }
500 }
501
502 /// ```
503 /// use nalgebra::{
504 /// dimension::{Dynamic, U4},
505 /// Matrix,
506 /// };
507 /// use ndarray::s;
508 /// use nshare::ToNdarray2;
509 ///
510 /// // Note: from_vec takes data column-by-column !
511 /// let m = Matrix::<f32, Dynamic, Dynamic, _>::from_vec(
512 /// 3,
513 /// 4,
514 /// vec![0.1, 0.2, 0.3, 0.5, 0.6, 0.7, 1.1, 1.2, 1.3, 1.5, 1.6, 1.7],
515 /// );
516 /// let arr = m.into_ndarray2();
517 /// assert!(arr.slice(s![.., 0]).iter().eq(&[0.1, 0.2, 0.3]));
518 /// assert!(arr.slice(s![0, ..]).iter().eq(&[0.1, 0.5, 1.1, 1.5]));
519 /// ```
520 impl<'a, N: Scalar> ToNdarray2 for Matrix<N, Dynamic, Dynamic, VecStorage<N, Dynamic, Dynamic>>
521 where
522 DefaultAllocator: Allocator<N, Dynamic, Dynamic, Buffer = VecStorage<N, Dynamic, Dynamic>>,
523 {
524 type Out = Array2<N>;
525
526 fn into_ndarray2(self) -> Self::Out {
527 Array2::from_shape_vec(self.shape().strides(self.strides()), self.data.into()).unwrap()
528 }
529 }
530}