use super::super::Matrix;
use super::super::layout::Layout;
use super::super::order::{ColMajor, Order};
use crate::convert::{FromColIterator, TryFromCols};
use crate::error::{Error, Result};
use crate::shape::Shape;
use alloc::boxed::Box;
use alloc::vec::Vec;
use core::mem;
impl<T, O, const R: usize, const C: usize> TryFromCols<[[T; R]; C]> for Matrix<T, O>
where
O: Order,
{
fn try_from_cols(value: [[T; R]; C]) -> Result<Self> {
let nrows = R;
let ncols = C;
let shape = Shape::new(nrows, ncols);
let (layout, size) = Layout::<T, ColMajor>::from_shape(shape)?;
let mut data = Vec::with_capacity(size);
if size_of::<T>() == 0 {
mem::forget(value);
unsafe {
data.set_len(size);
}
} else {
for col in value {
data.extend(col);
}
}
Ok(Matrix { layout, data }.with_order())
}
}
impl<T, O, const R: usize, const C: usize> TryFromCols<Box<[[T; R]; C]>> for Matrix<T, O>
where
O: Order,
{
fn try_from_cols(value: Box<[[T; R]; C]>) -> Result<Self> {
Self::try_from_cols(value as Box<[[T; R]]>)
}
}
impl<T, O, const R: usize> TryFromCols<Box<[[T; R]]>> for Matrix<T, O>
where
O: Order,
{
fn try_from_cols(value: Box<[[T; R]]>) -> Result<Self> {
Self::try_from_cols(value.into_vec())
}
}
impl<T, O, const R: usize> TryFromCols<Vec<[T; R]>> for Matrix<T, O>
where
O: Order,
{
fn try_from_cols(value: Vec<[T; R]>) -> Result<Self> {
let nrows = R;
let ncols = value.len();
let shape = Shape::new(nrows, ncols);
let (layout, size) = Layout::<T, ColMajor>::from_shape(shape)?;
let mut data = Vec::with_capacity(size);
if size_of::<T>() == 0 {
mem::forget(value);
unsafe {
data.set_len(size);
}
} else {
for col in value {
data.extend(col);
}
}
Ok(Matrix { layout, data }.with_order())
}
}
impl<T, O, const R: usize, const C: usize> TryFromCols<[Box<[T; R]>; C]> for Matrix<T, O>
where
O: Order,
{
fn try_from_cols(value: [Box<[T; R]>; C]) -> Result<Self> {
let nrows = R;
let ncols = C;
let shape = Shape::new(nrows, ncols);
let (layout, size) = Layout::<T, ColMajor>::from_shape(shape)?;
let mut data = Vec::with_capacity(size);
for col in value {
data.extend(col as Box<[T]>);
}
Ok(Matrix { layout, data }.with_order())
}
}
impl<T, O, const R: usize, const C: usize> TryFromCols<Box<[Box<[T; R]>; C]>> for Matrix<T, O>
where
O: Order,
{
fn try_from_cols(value: Box<[Box<[T; R]>; C]>) -> Result<Self> {
Self::try_from_cols(value as Box<[Box<[T; R]>]>)
}
}
impl<T, O, const R: usize> TryFromCols<Box<[Box<[T; R]>]>> for Matrix<T, O>
where
O: Order,
{
fn try_from_cols(value: Box<[Box<[T; R]>]>) -> Result<Self> {
Self::try_from_cols(value.into_vec())
}
}
impl<T, O, const R: usize> TryFromCols<Vec<Box<[T; R]>>> for Matrix<T, O>
where
O: Order,
{
fn try_from_cols(value: Vec<Box<[T; R]>>) -> Result<Self> {
let nrows = R;
let ncols = value.len();
let shape = Shape::new(nrows, ncols);
let (layout, size) = Layout::<T, ColMajor>::from_shape(shape)?;
let mut data = Vec::with_capacity(size);
for col in value {
data.extend(col as Box<[T]>);
}
Ok(Matrix { layout, data }.with_order())
}
}
impl<T, O, const C: usize> TryFromCols<[Box<[T]>; C]> for Matrix<T, O>
where
O: Order,
{
fn try_from_cols(value: [Box<[T]>; C]) -> Result<Self> {
let mut iter = value.into_iter();
let Some(first) = iter.next() else {
return Ok(Self::new());
};
let nrows = first.len();
let ncols = C;
let shape = Shape::new(nrows, ncols);
let (layout, size) = Layout::<T, ColMajor>::from_shape(shape)?;
let mut data = Vec::with_capacity(size);
data.extend(first);
for col in iter {
if col.len() != nrows {
return Err(Error::LengthInconsistent);
}
data.extend(col);
}
Ok(Matrix { layout, data }.with_order())
}
}
impl<T, O, const C: usize> TryFromCols<Box<[Box<[T]>; C]>> for Matrix<T, O>
where
O: Order,
{
fn try_from_cols(value: Box<[Box<[T]>; C]>) -> Result<Self> {
Self::try_from_cols(value as Box<[Box<[T]>]>)
}
}
impl<T, O> TryFromCols<Box<[Box<[T]>]>> for Matrix<T, O>
where
O: Order,
{
fn try_from_cols(value: Box<[Box<[T]>]>) -> Result<Self> {
Self::try_from_cols(value.into_vec())
}
}
impl<T, O> TryFromCols<Vec<Box<[T]>>> for Matrix<T, O>
where
O: Order,
{
fn try_from_cols(value: Vec<Box<[T]>>) -> Result<Self> {
let ncols = value.len();
let mut iter = value.into_iter();
let Some(first) = iter.next() else {
return Ok(Self::new());
};
let nrows = first.len();
let shape = Shape::new(nrows, ncols);
let (layout, size) = Layout::<T, ColMajor>::from_shape(shape)?;
let mut data = Vec::with_capacity(size);
data.extend(first);
for col in iter {
if col.len() != nrows {
return Err(Error::LengthInconsistent);
}
data.extend(col);
}
Ok(Matrix { layout, data }.with_order())
}
}
impl<T, O, const C: usize> TryFromCols<[Vec<T>; C]> for Matrix<T, O>
where
O: Order,
{
fn try_from_cols(value: [Vec<T>; C]) -> Result<Self> {
let mut iter = value.into_iter();
let Some(first) = iter.next() else {
return Ok(Self::new());
};
let nrows = first.len();
let ncols = C;
let shape = Shape::new(nrows, ncols);
let (layout, size) = Layout::<T, ColMajor>::from_shape(shape)?;
let mut data = Vec::with_capacity(size);
data.extend(first);
for col in iter {
if col.len() != nrows {
return Err(Error::LengthInconsistent);
}
data.extend(col);
}
Ok(Matrix { layout, data }.with_order())
}
}
impl<T, O, const C: usize> TryFromCols<Box<[Vec<T>; C]>> for Matrix<T, O>
where
O: Order,
{
fn try_from_cols(value: Box<[Vec<T>; C]>) -> Result<Self> {
Self::try_from_cols(value as Box<[Vec<T>]>)
}
}
impl<T, O> TryFromCols<Box<[Vec<T>]>> for Matrix<T, O>
where
O: Order,
{
fn try_from_cols(value: Box<[Vec<T>]>) -> Result<Self> {
Self::try_from_cols(value.into_vec())
}
}
impl<T, O> TryFromCols<Vec<Vec<T>>> for Matrix<T, O>
where
O: Order,
{
fn try_from_cols(value: Vec<Vec<T>>) -> Result<Self> {
let ncols = value.len();
let mut iter = value.into_iter();
let Some(first) = iter.next() else {
return Ok(Self::new());
};
let nrows = first.len();
let shape = Shape::new(nrows, ncols);
let (layout, size) = Layout::<T, ColMajor>::from_shape(shape)?;
let mut data = Vec::with_capacity(size);
data.extend(first);
for col in iter {
if col.len() != nrows {
return Err(Error::LengthInconsistent);
}
data.extend(col);
}
Ok(Matrix { layout, data }.with_order())
}
}
impl<T, O, C> FromColIterator<C, T> for Matrix<T, O>
where
O: Order,
C: IntoIterator<Item = T>,
{
fn from_col_iter<I>(iter: I) -> Self
where
I: IntoIterator<Item = C>,
{
let mut iter = iter.into_iter();
let Some(first) = iter.next() else {
return Self::new();
};
let mut data: Vec<T> = first.into_iter().collect();
let nrows = data.len();
let mut ncols = 1;
let mut size = nrows;
for col in iter {
data.extend(col);
assert!(data.len() - size == nrows, "{}", Error::LengthInconsistent);
ncols += 1;
size = data.len();
}
let shape = Shape::new(nrows, ncols);
let layout = Layout::<T, ColMajor>::from_shape_unchecked(shape);
Matrix { layout, data }.with_order()
}
}
#[cfg(test)]
mod tests {
use super::super::super::order::RowMajor;
use super::*;
use crate::convert::TryFromRows;
use crate::dispatch_unary;
use alloc::vec;
#[test]
fn test_try_from_cols() -> Result<()> {
const MAX: usize = isize::MAX as usize;
let expected = Matrix::<i32, RowMajor>::try_from_rows([[1, 4], [2, 5], [3, 6]])?;
dispatch_unary! {{
let seq: [[i32; 3]; 2] = [[1, 2, 3], [4, 5, 6]];
let output = Matrix::<i32, O>::try_from_cols(seq)?;
assert_eq!(output, expected);
let seq: Box<[[i32; 3]; 2]> = Box::new([[1, 2, 3], [4, 5, 6]]);
let output = Matrix::<i32, O>::try_from_cols(seq)?;
assert_eq!(output, expected);
let seq: Box<[[i32; 3]]> = Box::new([[1, 2, 3], [4, 5, 6]]);
let output = Matrix::<i32, O>::try_from_cols(seq)?;
assert_eq!(output, expected);
let seq: Vec<[i32; 3]> = vec![[1, 2, 3], [4, 5, 6]];
let output = Matrix::<i32, O>::try_from_cols(seq)?;
assert_eq!(output, expected);
let seq: [Box<[i32; 3]>; 2] = [Box::new([1, 2, 3]), Box::new([4, 5, 6])];
let output = Matrix::<i32, O>::try_from_cols(seq)?;
assert_eq!(output, expected);
let seq: Box<[Box<[i32; 3]>; 2]> = Box::new([Box::new([1, 2, 3]), Box::new([4, 5, 6])]);
let output = Matrix::<i32, O>::try_from_cols(seq)?;
assert_eq!(output, expected);
let seq: Box<[Box<[i32; 3]>]> = Box::new([Box::new([1, 2, 3]), Box::new([4, 5, 6])]);
let output = Matrix::<i32, O>::try_from_cols(seq)?;
assert_eq!(output, expected);
let seq: Vec<Box<[i32; 3]>> = vec![Box::new([1, 2, 3]), Box::new([4, 5, 6])];
let output = Matrix::<i32, O>::try_from_cols(seq)?;
assert_eq!(output, expected);
let seq: [Box<[i32]>; 2] = [Box::new([1, 2, 3]), Box::new([4, 5, 6])];
let output = Matrix::<i32, O>::try_from_cols(seq)?;
assert_eq!(output, expected);
let seq: Box<[Box<[i32]>; 2]> = Box::new([Box::new([1, 2, 3]), Box::new([4, 5, 6])]);
let output = Matrix::<i32, O>::try_from_cols(seq)?;
assert_eq!(output, expected);
let seq: Box<[Box<[i32]>]> = Box::new([Box::new([1, 2, 3]), Box::new([4, 5, 6])]);
let output = Matrix::<i32, O>::try_from_cols(seq)?;
assert_eq!(output, expected);
let seq: Vec<Box<[i32]>> = vec![Box::new([1, 2, 3]), Box::new([4, 5, 6])];
let output = Matrix::<i32, O>::try_from_cols(seq)?;
assert_eq!(output, expected);
let seq: [Vec<i32>; 2] = [vec![1, 2, 3], vec![4, 5, 6]];
let output = Matrix::<i32, O>::try_from_cols(seq)?;
assert_eq!(output, expected);
let seq: Box<[Vec<i32>; 2]> = Box::new([vec![1, 2, 3], vec![4, 5, 6]]);
let output = Matrix::<i32, O>::try_from_cols(seq)?;
assert_eq!(output, expected);
let seq: Box<[Vec<i32>]> = Box::new([vec![1, 2, 3], vec![4, 5, 6]]);
let output = Matrix::<i32, O>::try_from_cols(seq)?;
assert_eq!(output, expected);
let seq: Vec<Vec<i32>> = vec![vec![1, 2, 3], vec![4, 5, 6]];
let output = Matrix::<i32, O>::try_from_cols(seq)?;
assert_eq!(output, expected);
let seq: [[(); MAX]; 2] = [[(); MAX], [(); MAX]];
assert!(Matrix::<(), O>::try_from_cols(seq).is_ok());
let seq: Box<[[(); MAX]; 2]> = Box::new([[(); MAX], [(); MAX]]);
assert!(Matrix::<(), O>::try_from_cols(seq).is_ok());
let seq: Box<[[(); MAX]]> = Box::new([[(); MAX], [(); MAX]]);
assert!(Matrix::<(), O>::try_from_cols(seq).is_ok());
let seq: Vec<[(); MAX]> = vec![[(); MAX], [(); MAX]];
assert!(Matrix::<(), O>::try_from_cols(seq).is_ok());
let seq: [Box<[(); MAX]>; 2] = [Box::new([(); MAX]), Box::new([(); MAX])];
assert!(Matrix::<(), O>::try_from_cols(seq).is_ok());
let seq: Box<[Box<[(); MAX]>; 2]> =
Box::new([Box::new([(); MAX]), Box::new([(); MAX])]);
assert!(Matrix::<(), O>::try_from_cols(seq).is_ok());
let seq: Box<[Box<[(); MAX]>]> = Box::new([Box::new([(); MAX]), Box::new([(); MAX])]);
assert!(Matrix::<(), O>::try_from_cols(seq).is_ok());
let seq: Vec<Box<[(); MAX]>> = vec![Box::new([(); MAX]), Box::new([(); MAX])];
assert!(Matrix::<(), O>::try_from_cols(seq).is_ok());
let seq: [Box<[()]>; 2] = [Box::new([(); MAX]), Box::new([(); MAX])];
assert!(Matrix::<(), O>::try_from_cols(seq).is_ok());
let seq: Box<[Box<[()]>; 2]> = Box::new([Box::new([(); MAX]), Box::new([(); MAX])]);
assert!(Matrix::<(), O>::try_from_cols(seq).is_ok());
let seq: Box<[Box<[()]>]> = Box::new([Box::new([(); MAX]), Box::new([(); MAX])]);
assert!(Matrix::<(), O>::try_from_cols(seq).is_ok());
let seq: Vec<Box<[()]>> = vec![Box::new([(); MAX]), Box::new([(); MAX])];
assert!(Matrix::<(), O>::try_from_cols(seq).is_ok());
let seq: [Vec<()>; 2] = [vec![(); MAX], vec![(); MAX]];
assert!(Matrix::<(), O>::try_from_cols(seq).is_ok());
let seq: Box<[Vec<()>; 2]> = Box::new([vec![(); MAX], vec![(); MAX]]);
assert!(Matrix::<(), O>::try_from_cols(seq).is_ok());
let seq: Box<[Vec<()>]> = Box::new([vec![(); MAX], vec![(); MAX]]);
assert!(Matrix::<(), O>::try_from_cols(seq).is_ok());
let seq: Vec<Vec<()>> = vec![vec![(); MAX], vec![(); MAX]];
assert!(Matrix::<(), O>::try_from_cols(seq).is_ok());
let seq: [[(); MAX]; 3] = [[(); MAX], [(); MAX], [(); MAX]];
let error = Matrix::<(), O>::try_from_cols(seq).unwrap_err();
assert_eq!(error, Error::SizeOverflow);
let seq: Box<[[(); MAX]; 3]> = Box::new([[(); MAX], [(); MAX], [(); MAX]]);
let error = Matrix::<(), O>::try_from_cols(seq).unwrap_err();
assert_eq!(error, Error::SizeOverflow);
let seq: Box<[[(); MAX]]> = Box::new([[(); MAX], [(); MAX], [(); MAX]]);
let error = Matrix::<(), O>::try_from_cols(seq).unwrap_err();
assert_eq!(error, Error::SizeOverflow);
let seq: Vec<[(); MAX]> = vec![[(); MAX], [(); MAX], [(); MAX]];
let error = Matrix::<(), O>::try_from_cols(seq).unwrap_err();
assert_eq!(error, Error::SizeOverflow);
let seq: [Box<[(); MAX]>; 3] = [
Box::new([(); MAX]),
Box::new([(); MAX]),
Box::new([(); MAX]),
];
let error = Matrix::<(), O>::try_from_cols(seq).unwrap_err();
assert_eq!(error, Error::SizeOverflow);
let seq: Box<[Box<[(); MAX]>; 3]> = Box::new([
Box::new([(); MAX]),
Box::new([(); MAX]),
Box::new([(); MAX]),
]);
let error = Matrix::<(), O>::try_from_cols(seq).unwrap_err();
assert_eq!(error, Error::SizeOverflow);
let seq: Box<[Box<[(); MAX]>]> = Box::new([
Box::new([(); MAX]),
Box::new([(); MAX]),
Box::new([(); MAX]),
]);
let error = Matrix::<(), O>::try_from_cols(seq).unwrap_err();
assert_eq!(error, Error::SizeOverflow);
let seq: Vec<Box<[(); MAX]>> = vec![
Box::new([(); MAX]),
Box::new([(); MAX]),
Box::new([(); MAX]),
];
let error = Matrix::<(), O>::try_from_cols(seq).unwrap_err();
assert_eq!(error, Error::SizeOverflow);
let seq: [Box<[()]>; 3] = [
Box::new([(); MAX]),
Box::new([(); MAX]),
Box::new([(); MAX]),
];
let error = Matrix::<(), O>::try_from_cols(seq).unwrap_err();
assert_eq!(error, Error::SizeOverflow);
let seq: Box<[Box<[()]>; 3]> = Box::new([
Box::new([(); MAX]),
Box::new([(); MAX]),
Box::new([(); MAX]),
]);
let error = Matrix::<(), O>::try_from_cols(seq).unwrap_err();
assert_eq!(error, Error::SizeOverflow);
let seq: Box<[Box<[()]>]> = Box::new([
Box::new([(); MAX]),
Box::new([(); MAX]),
Box::new([(); MAX]),
]);
let error = Matrix::<(), O>::try_from_cols(seq).unwrap_err();
assert_eq!(error, Error::SizeOverflow);
let seq: Vec<Box<[()]>> = vec![
Box::new([(); MAX]),
Box::new([(); MAX]),
Box::new([(); MAX]),
];
let error = Matrix::<(), O>::try_from_cols(seq).unwrap_err();
assert_eq!(error, Error::SizeOverflow);
let seq: [Vec<()>; 3] = [vec![(); MAX], vec![(); MAX], vec![(); MAX]];
let error = Matrix::<(), O>::try_from_cols(seq).unwrap_err();
assert_eq!(error, Error::SizeOverflow);
let seq: Box<[Vec<()>; 3]> = Box::new([vec![(); MAX], vec![(); MAX], vec![(); MAX]]);
let error = Matrix::<(), O>::try_from_cols(seq).unwrap_err();
assert_eq!(error, Error::SizeOverflow);
let seq: Box<[Vec<()>]> = Box::new([vec![(); MAX], vec![(); MAX], vec![(); MAX]]);
let error = Matrix::<(), O>::try_from_cols(seq).unwrap_err();
assert_eq!(error, Error::SizeOverflow);
let seq: Vec<Vec<()>> = vec![vec![(); MAX], vec![(); MAX], vec![(); MAX]];
let error = Matrix::<(), O>::try_from_cols(seq).unwrap_err();
assert_eq!(error, Error::SizeOverflow);
let seq: [Box<[i32]>; 2] = [Box::new([1, 2, 3]), Box::new([4, 5])];
let error = Matrix::<i32, O>::try_from_cols(seq).unwrap_err();
assert_eq!(error, Error::LengthInconsistent);
let seq: Box<[Box<[i32]>]> = Box::new([Box::new([1, 2, 3]), Box::new([4, 5])]);
let error = Matrix::<i32, O>::try_from_cols(seq).unwrap_err();
assert_eq!(error, Error::LengthInconsistent);
let seq: Box<[Box<[i32]>; 2]> = Box::new([Box::new([1, 2, 3]), Box::new([4, 5])]);
let error = Matrix::<i32, O>::try_from_cols(seq).unwrap_err();
assert_eq!(error, Error::LengthInconsistent);
let seq: Vec<Box<[i32]>> = vec![Box::new([1, 2, 3]), Box::new([4, 5])];
let error = Matrix::<i32, O>::try_from_cols(seq).unwrap_err();
assert_eq!(error, Error::LengthInconsistent);
let seq: [Vec<i32>; 2] = [vec![1, 2, 3], vec![4, 5]];
let error = Matrix::<i32, O>::try_from_cols(seq).unwrap_err();
assert_eq!(error, Error::LengthInconsistent);
let seq: Box<[Vec<i32>; 2]> = Box::new([vec![1, 2, 3], vec![4, 5]]);
let error = Matrix::<i32, O>::try_from_cols(seq).unwrap_err();
assert_eq!(error, Error::LengthInconsistent);
let seq: Box<[Vec<i32>]> = Box::new([vec![1, 2, 3], vec![4, 5]]);
let error = Matrix::<i32, O>::try_from_cols(seq).unwrap_err();
assert_eq!(error, Error::LengthInconsistent);
let seq: Vec<Vec<i32>> = vec![vec![1, 2, 3], vec![4, 5]];
let error = Matrix::<i32, O>::try_from_cols(seq).unwrap_err();
assert_eq!(error, Error::LengthInconsistent);
}}
Ok(())
}
#[test]
fn test_from_col_iter() -> Result<()> {
let expected = Matrix::<i32, RowMajor>::try_from_rows([[1, 4], [2, 5], [3, 6]]).unwrap();
dispatch_unary! {{
let iter = [[1, 2, 3], [4, 5, 6]];
let output = Matrix::<i32, O>::from_col_iter(iter);
assert_eq!(output, expected);
}}
Ok(())
}
#[test]
#[should_panic]
fn test_from_col_iter_fails_row_major() {
let iter = [vec![1, 2, 3], vec![4, 5]];
Matrix::<i32, RowMajor>::from_col_iter(iter);
}
#[test]
#[should_panic]
fn test_from_col_iter_fails_col_major() {
let iter = [vec![1, 2, 3], vec![4, 5]];
Matrix::<i32, ColMajor>::from_col_iter(iter);
}
}