1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
//! # Matamorph
//!
//! Seamless conversions between Rust's major matrix libraries: [ndarray], [faer], [nalgebra], and [mdarray].
//!
//! ## Overview
//!
//! Matamorph provides a unified interface for converting 2D matrices between the four main Rust crates
//! for matrix manipulation.
//!
//! The crate provides three types of conversions:
//! - **Owned conversions** : Create a new matrix with copied data
//! - **Immutable reference conversions** : Zero-copy read-only views
//! - **Mutable reference conversions** : Zero-copy read-write views
//!
//! ## Memory Layout Considerations
//!
//! Different crates use different memory layouts:
//! - **Row-major**: [ndarray], [mdarray]
//! - **Column-major**: [faer], [nalgebra]
//!
//! Additionally, [nalgebra] requires data to be contiguous along the first dimension and doesn't support
//! arbitrary strides. This constraint affects certain conversions:
//!
//! ### Conversion Compatibility Matrix
//!
//! | From ↓ \ To → | [ndarray] | [faer] | [nalgebra] | [mdarray] |
//! |---------------|-----------|--------|------------|-----------|
//! | **owned** | ✓ | ✓ | ✓ | ✓ |
//! | **ref** | ✓ | ✓ | ✓ᵀ | ✓ |
//! | **mut** | ✓ | ✓ | ✓ᵀ | ✓ |
//!
//! - ✓ = Conversion preserves layout
//! - ✓ᵀ = Conversion returns a transposed view (only when converting from row-major [ndarray]/[mdarray]
//! references to column-major [nalgebra])
//!
//! **Note**: Owned conversions always copy data and ensure correct layout for the target crate.
//! Reference conversions (`ref` and `mut`) are zero-copy operations.
//!
//! ## Example
//!
//! ### Basic Usage
//!
//! ```
//! use matamorph::own::MataConvertOwn;
//! use matamorph::ref_::MataConvertRef;
//! use matamorph::mut_::MataConvertMut;
//!
//! // Owned conversion (copies data): ndarray → nalgebra
//! let a = ndarray::array![[1.0, 2.0], [3.0, 4.0]];
//! let b = a.to_nalgebra();
//! assert_eq!(b[(0, 1)], 2.0);
//!
//! // Reference conversion (zero-copy): mdarray → faer
//! let c = mdarray::tensor![[5.0, 6.0], [7.0, 8.0]];
//! let d = c.view(.., ..).to_faer();
//! assert_eq!(d[(1, 0)], 7.0);
//!
//! // Mutable reference conversion (zero-copy): ndarray → faer
//! let mut e = ndarray::array![[9.0, 10.0], [11.0, 12.0]];
//! let mut f = e.view_mut().to_faer();
//! f[(0, 0)] = 0.0;
//! assert_eq!(e[[0, 0]], 0.0); // Original is modified
//! ```
//! ### Memory Layout Considerations (nalgebra)
//!
//! ```
//! use matamorph::ref_::MataConvertRef;
//! // ⚠️ Warning: conversions to nalgebra from row-major references are transposed!
//! let g = ndarray::array![[1.0, 2.0], [3.0, 4.0]];
//! let h = g.view().to_nalgebra();
//! assert_eq!(h[(1, 0)], 2.0); // h is transposed: h[(row, col)] = g[(col, row)]
//!
//! // But conversions FROM nalgebra preserve layout (no transposition)
//! let i = nalgebra::dmatrix![1.0, 2.0; 3.0, 4.0];
//! let i_view = i.view((0,0), (2,2));
//! let j = i_view.to_ndarray();
//! assert_eq!(j[[0, 1]], 2.0); // No transposition
//! assert_eq!(i[(0, 1)], 2.0); // Same element accessed
//!
//! // Similarly, conversions between column-major crates (faer ↔ nalgebra) preserve layout
//! let k = faer::mat![[1.0, 2.0], [3.0, 4.0]];
//! let l = k.as_ref().to_nalgebra();
//! assert_eq!(l[(1, 0)], 3.0); // No transposition
//! assert_eq!(k[(1, 0)], 3.0); // Same element accessed
//! ```
//!
//!
//! [ndarray]: https://docs.rs/ndarray
//! [faer]: https://docs.rs/faer
//! [nalgebra]: https://docs.rs/nalgebra
//! [mdarray]: https://docs.rs/mdarray