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
//! `matten::Tensor` ↔ `ndarray::ArrayD<f64>` conversions (RFC-027 §4).
//!
//! Both directions copy: `matten::Tensor` owns a contiguous row-major
//! `Vec<f64>`, and these functions hand over / materialize owned buffers. No
//! zero-copy is claimed (RFC-025 §3).
use crateMattenNdarrayError;
use Tensor;
use ;
/// Converts a numeric [`Tensor`] into an [`ndarray::ArrayD<f64>`].
///
/// The result is standard (row-major) layout. A dynamic tensor returns
/// [`MattenNdarrayError::DynamicTensor`] rather than panicking. This guard is
/// unconditional — it does not depend on the companion `dynamic` feature being
/// enabled (RFC-031).
///
/// ```
/// use matten::Tensor;
/// use matten_ndarray::to_arrayd;
///
/// let t = Tensor::new(vec![1.0, 2.0, 3.0, 4.0], &[2, 2]);
/// let arr = to_arrayd(&t).unwrap();
/// assert_eq!(arr.shape(), &[2, 2]);
/// assert_eq!(arr[[1, 0]], 3.0);
/// ```
/// Converts an [`ndarray::ArrayD<f64>`] into a [`Tensor`].
///
/// Conversion preserves **logical** element order: an `ArrayD` may be in
/// non-standard (transposed / sliced / non-standard-stride) layout, so the raw
/// backing buffer is not read directly — that would silently transpose the
/// data. A shape with any zero-length axis is rejected, because core `matten`
/// does not support zero-sized dimensions.
///
/// ```
/// use matten_ndarray::from_arrayd;
/// use ndarray::{ArrayD, IxDyn};
///
/// // A transposed (non-standard-layout) array still converts by logical order.
/// let a = ArrayD::from_shape_vec(IxDyn(&[2, 3]), vec![1., 2., 3., 4., 5., 6.]).unwrap();
/// let t = from_arrayd(a.t().to_owned()).unwrap(); // logical shape [3, 2]
/// assert_eq!(t.shape(), &[3, 2]);
/// assert_eq!(t.as_slice(), &[1.0, 4.0, 2.0, 5.0, 3.0, 6.0]);
/// ```