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
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
use lapack::c;
use ndarray::*;
use super::error::*;
pub type LDA = i32;
pub type LEN = i32;
pub type Col = i32;
pub type Row = i32;
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum MatrixLayout {
C((Row, LDA)),
F((Col, LDA)),
}
impl MatrixLayout {
pub fn size(&self) -> (Row, Col) {
match *self {
MatrixLayout::C((row, lda)) => (row, lda),
MatrixLayout::F((col, lda)) => (lda, col),
}
}
pub fn resized(&self, row: Row, col: Col) -> MatrixLayout {
match *self {
MatrixLayout::C(_) => MatrixLayout::C((row, col)),
MatrixLayout::F(_) => MatrixLayout::F((col, row)),
}
}
pub fn lda(&self) -> LDA {
match *self {
MatrixLayout::C((_, lda)) => lda,
MatrixLayout::F((_, lda)) => lda,
}
}
pub fn len(&self) -> LEN {
match *self {
MatrixLayout::C((row, _)) => row,
MatrixLayout::F((col, _)) => col,
}
}
pub fn lapacke_layout(&self) -> c::Layout {
match *self {
MatrixLayout::C(_) => c::Layout::RowMajor,
MatrixLayout::F(_) => c::Layout::ColumnMajor,
}
}
pub fn same_order(&self, other: &MatrixLayout) -> bool {
self.lapacke_layout() == other.lapacke_layout()
}
pub fn as_shape(&self) -> Shape<Ix2> {
match *self {
MatrixLayout::C((row, col)) => (row as usize, col as usize).into_shape(),
MatrixLayout::F((col, row)) => (row as usize, col as usize).f().into_shape(),
}
}
pub fn toggle_order(&self) -> Self {
match *self {
MatrixLayout::C((row, col)) => MatrixLayout::F((col, row)),
MatrixLayout::F((col, row)) => MatrixLayout::C((row, col)),
}
}
}
pub trait AllocatedArray {
type Elem;
fn layout(&self) -> Result<MatrixLayout>;
fn square_layout(&self) -> Result<MatrixLayout>;
fn as_allocated(&self) -> Result<&[Self::Elem]>;
}
pub trait AllocatedArrayMut: AllocatedArray {
fn as_allocated_mut(&mut self) -> Result<&mut [Self::Elem]>;
}
impl<A, S> AllocatedArray for ArrayBase<S, Ix2>
where
S: Data<Elem = A>,
{
type Elem = A;
fn layout(&self) -> Result<MatrixLayout> {
let shape = self.shape();
let strides = self.strides();
if shape[0] == strides[1] as usize {
return Ok(MatrixLayout::F((self.cols() as i32, self.rows() as i32)));
}
if shape[1] == strides[0] as usize {
return Ok(MatrixLayout::C((self.rows() as i32, self.cols() as i32)));
}
Err(StrideError::new(strides[0], strides[1]).into())
}
fn square_layout(&self) -> Result<MatrixLayout> {
let l = self.layout()?;
let (n, m) = l.size();
if n == m {
Ok(l)
} else {
Err(NotSquareError::new(n, m).into())
}
}
fn as_allocated(&self) -> Result<&[A]> {
Ok(self.as_slice_memory_order().ok_or(MemoryContError::new())?)
}
}
impl<A, S> AllocatedArrayMut for ArrayBase<S, Ix2>
where
S: DataMut<Elem = A>,
{
fn as_allocated_mut(&mut self) -> Result<&mut [A]> {
Ok(self.as_slice_memory_order_mut().ok_or(
MemoryContError::new(),
)?)
}
}