use cauchy::Scalar;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum MatrixLayout {
C { row: i32, lda: i32 },
F { col: i32, lda: i32 },
}
impl MatrixLayout {
pub fn size(&self) -> (i32, i32) {
match *self {
MatrixLayout::C { row, lda } => (row, lda),
MatrixLayout::F { col, lda } => (lda, col),
}
}
pub fn resized(&self, row: i32, col: i32) -> MatrixLayout {
match *self {
MatrixLayout::C { .. } => MatrixLayout::C { row, lda: col },
MatrixLayout::F { .. } => MatrixLayout::F { col, lda: row },
}
}
pub fn lda(&self) -> i32 {
std::cmp::max(
1,
match *self {
MatrixLayout::C { lda, .. } | MatrixLayout::F { lda, .. } => lda,
},
)
}
pub fn len(&self) -> i32 {
match *self {
MatrixLayout::C { row, .. } => row,
MatrixLayout::F { col, .. } => col,
}
}
pub fn is_empty(&self) -> bool {
self.len() == 0
}
pub fn same_order(&self, other: &MatrixLayout) -> bool {
match (self, other) {
(MatrixLayout::C { .. }, MatrixLayout::C { .. }) => true,
(MatrixLayout::F { .. }, MatrixLayout::F { .. }) => true,
_ => false,
}
}
pub fn toggle_order(&self) -> Self {
match *self {
MatrixLayout::C { row, lda } => MatrixLayout::F { lda: row, col: lda },
MatrixLayout::F { col, lda } => MatrixLayout::C { row: lda, lda: col },
}
}
pub fn t(&self) -> Self {
match *self {
MatrixLayout::C { row, lda } => MatrixLayout::F { col: row, lda },
MatrixLayout::F { col, lda } => MatrixLayout::C { row: col, lda },
}
}
}
pub fn square_transpose<T: Scalar>(layout: MatrixLayout, a: &mut [T]) {
let (m, n) = layout.size();
let n = n as usize;
let m = m as usize;
assert_eq!(a.len(), n * m);
for i in 0..m {
for j in (i + 1)..n {
let a_ij = a[i * n + j];
let a_ji = a[j * m + i];
a[i * n + j] = a_ji.conj();
a[j * m + i] = a_ij.conj();
}
}
}
pub fn transpose<T: Scalar>(layout: MatrixLayout, from: &[T], to: &mut [T]) -> MatrixLayout {
let (m, n) = layout.size();
let transposed = layout.resized(n, m).t();
let m = m as usize;
let n = n as usize;
assert_eq!(from.len(), m * n);
assert_eq!(to.len(), m * n);
match layout {
MatrixLayout::C { .. } => {
for i in 0..m {
for j in 0..n {
to[j * m + i] = from[i * n + j];
}
}
}
MatrixLayout::F { .. } => {
for i in 0..m {
for j in 0..n {
to[i * n + j] = from[j * m + i];
}
}
}
}
transposed
}