use core::{ops::{Mul, AddAssign}, borrow::Borrow, marker::Destruct};
use super::*;
#[const_trait]
pub trait Array2dOps<T, const M: usize, const N: usize>: ArrayOps<[T; N], M>
{
type Array2d<I, const H: usize, const W: usize>: Array2dOps<I, H, W>;
type Resized2d<const H: usize, const W: usize>: Array2dOps<T, H, W> = Self::Array2d<T, H, W>;
type Transposed: Array2dOps<T, N, M> = Self::Resized2d<N, M>;
fn transpose(self) -> Self::Transposed;
fn into_diagonal(self) -> [T; crate::min_len(M, N)]
where
T: ~const Destruct;
fn diagonal_ref(&self) -> [&T; crate::min_len(M, N)];
fn diagonal_mut(&mut self) -> [&mut T; crate::min_len(M, N)];
}
pub const fn transpose<T, const M: usize, const N: usize>(matrix: [[T; N]; M]) -> [[T; M]; N]
{
let mut this_t: [[T; M]; N] = unsafe {private::uninit()};
let mut i = 0;
while i != M
{
let mut j = 0;
while j != N
{
unsafe {core::ptr::copy_nonoverlapping(
&matrix[i][j] as *const T,
&mut this_t[j][i] as *mut T,
1
)};
j += 1;
}
i += 1;
}
core::mem::forget(matrix);
this_t
}
pub fn into_diagonal<T, const M: usize, const N: usize>(array: [[T; N]; M]) -> [T; crate::min_len(M, N)]
where
T: Destruct
{
let mut dst: [T; crate::min_len(M, N)] = unsafe {private::uninit()};
let mut m = 0;
while m != M
{
let mut n = 0;
while n != N
{
unsafe {
let src = array[m].as_ptr().add(n);
if m == n
{
core::ptr::copy_nonoverlapping(src, dst.as_mut_ptr().add(n), 1)
}
else
{
let _ = core::ptr::read(src);
}
}
n += 1;
}
m += 1;
}
core::mem::forget(array);
dst
}
pub const fn diagonal_ref<T, const M: usize, const N: usize>(array: &[[T; N]; M]) -> [&T; crate::min_len(M, N)]
{
let mut dst: [&T; crate::min_len(M, N)] = unsafe {private::uninit()};
let mut n = 0;
while n != crate::min_len(M, N)
{
dst[n] = &array[n][n];
n += 1;
}
dst
}
pub const fn diagonal_mut<T, const M: usize, const N: usize>(array: &mut [[T; N]; M]) -> [&mut T; crate::min_len(M, N)]
{
let mut dst: [&mut T; crate::min_len(M, N)] = unsafe {private::uninit()};
let mut n = 0;
while n != crate::min_len(M, N)
{
dst[n] = unsafe {core::mem::transmute(&mut array[n][n])};
n += 1;
}
dst
}
impl<T, const M: usize, const N: usize> Array2dOps<T, M, N> for [[T; N]; M]
{
type Array2d<I, const H: usize, const W: usize> = [[I; W]; H];
fn transpose(self) -> Self::Transposed
{
crate::transpose(self)
}
fn into_diagonal(self) -> [T; crate::min_len(M, N)]
where
T: Destruct
{
crate::into_diagonal(self)
}
fn diagonal_ref(&self) -> [&T; crate::min_len(M, N)]
{
crate::diagonal_ref(self)
}
fn diagonal_mut(&mut self) -> [&mut T; crate::min_len(M, N)]
{
crate::diagonal_mut(self)
}
}