use super::*;
use crate::{Idx, IdxInc, TryReserveError, assert};
#[derive(Clone)]
pub struct Own<T, Rows: Shape = usize> {
column: Mat<T, Rows, usize>,
}
#[inline]
fn idx_to_pair<T, R>(f: impl FnMut(T) -> R) -> impl FnMut(T, usize) -> R {
let mut f = f;
#[inline(always)]
move |i, _| f(i)
}
impl<T, Rows: Shape> Col<T, Rows> {
pub fn from_fn(nrows: Rows, f: impl FnMut(Idx<Rows>) -> T) -> Self {
Self {
0: Own {
column: Mat::from_fn(nrows, 1, idx_to_pair(f)),
},
}
}
#[inline]
pub fn zeros(nrows: Rows) -> Self
where
T: ComplexField,
{
Self {
0: Own {
column: Mat::zeros(nrows, 1),
},
}
}
#[inline]
pub fn ones(nrows: Rows) -> Self
where
T: ComplexField,
{
Self {
0: Own {
column: Mat::ones(nrows, 1),
},
}
}
#[inline]
pub fn full(nrows: Rows, value: T) -> Self
where
T: Clone,
{
Self {
0: Own {
column: Mat::full(nrows, 1, value),
},
}
}
pub fn try_reserve(
&mut self,
new_row_capacity: usize,
) -> Result<(), TryReserveError> {
self.column.try_reserve(new_row_capacity, 1)
}
#[track_caller]
pub fn reserve(&mut self, new_row_capacity: usize) {
self.column.reserve(new_row_capacity, 1)
}
pub fn resize_with(
&mut self,
new_nrows: Rows,
f: impl FnMut(Idx<Rows>) -> T,
) {
self.column.resize_with(new_nrows, 1, idx_to_pair(f));
}
pub fn truncate(&mut self, new_nrows: Rows) {
self.column.truncate(new_nrows, 1);
}
#[inline]
pub fn into_row_shape<V: Shape>(self, nrows: V) -> Col<T, V> {
assert!(all(self.nrows().unbound() == nrows.unbound()));
Col {
0: Own {
column: self.0.column.into_shape(nrows, 1),
},
}
}
#[inline]
pub fn into_diagonal(self) -> Diag<T, Rows> {
Diag {
0: crate::diag::Own { inner: self },
}
}
#[inline]
pub fn into_transpose(self) -> Row<T, Rows> {
Row {
0: crate::row::Own { trans: self },
}
}
}
impl<T> Col<T> {
pub(crate) fn from_iter_imp<I: Iterator<Item = T>>(iter: I) -> Self {
let mut iter = iter;
let (min, max) = iter.size_hint();
if max == Some(min) {
let cap = min;
let mut col = Mat::<T>::with_capacity(cap, 1);
let mut count = 0;
iter.take(cap).for_each(|item| unsafe {
col.as_ptr_mut().add(count).write(item);
count += 1;
if const { core::mem::needs_drop::<T>() } {
col.set_dims(count, 1);
}
});
unsafe {
col.set_dims(count, 1);
}
assert_eq!(count, cap);
Col {
0: Own { column: col },
}
} else {
let mut cap = Ord::max(4, min);
let mut col = Mat::<T>::with_capacity(cap, 1);
let mut count = 0;
loop {
let expected = cap;
iter.by_ref().take(cap - count).for_each(|item| unsafe {
col.as_ptr_mut().add(count).write(item);
count += 1;
if const { core::mem::needs_drop::<T>() } {
col.set_dims(count, 1);
}
});
unsafe {
col.set_dims(count, 1);
}
if count < expected {
break;
}
if let Some(item) = iter.next() {
cap = cap.checked_mul(2).unwrap();
col.reserve(cap, 1);
unsafe {
col.as_ptr_mut().add(count).write(item);
count += 1;
col.set_dims(count, 1);
}
} else {
break;
}
}
Col {
0: Own { column: col },
}
}
}
}
impl<T> FromIterator<T> for Col<T> {
fn from_iter<I>(iter: I) -> Self
where
I: IntoIterator<Item = T>,
{
Self::from_iter_imp(iter.into_iter()).into()
}
}
impl<T, Rows: Shape> Col<T, Rows> {
#[inline]
pub fn nrows(&self) -> Rows {
self.column.nrows()
}
#[inline]
pub fn ncols(&self) -> usize {
1
}
}
impl<T: core::fmt::Debug, Rows: Shape> core::fmt::Debug for Own<T, Rows> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
self.rb().fmt(f)
}
}
impl<T, Rows: Shape> Col<T, Rows> {
#[inline(always)]
pub fn as_ptr(&self) -> *const T {
self.as_ref().as_ptr()
}
#[inline(always)]
pub fn shape(&self) -> (Rows, usize) {
(self.nrows(), self.ncols())
}
#[inline(always)]
pub fn row_stride(&self) -> isize {
1
}
#[inline]
pub fn map<U>(&self, f: impl Fn(&T) -> U) -> Col<U, Rows> {
self.rb().map(f)
}
#[inline]
pub fn for_each(&self, f: impl Fn(&T)) {
self.rb().for_each(f)
}
#[inline]
pub fn map_mut<U>(&mut self, f: impl FnMut(&mut T) -> U) -> Col<U, Rows> {
self.rb_mut().map_mut(f)
}
#[inline]
pub fn for_each_mut(&mut self, f: impl FnMut(&mut T)) {
self.rb_mut().for_each_mut(f)
}
#[inline(always)]
pub fn ptr_at(&self, row: IdxInc<Rows>) -> *const T {
self.as_ref().ptr_at(row)
}
#[inline(always)]
#[track_caller]
pub unsafe fn ptr_inbounds_at(&self, row: Idx<Rows>) -> *const T {
self.as_ref().ptr_inbounds_at(row)
}
#[inline]
#[track_caller]
pub fn split_at_row(
&self,
row: IdxInc<Rows>,
) -> (ColRef<'_, T, usize>, ColRef<'_, T, usize>) {
self.as_ref().split_at_row(row)
}
#[inline(always)]
pub fn transpose(&self) -> RowRef<'_, T, Rows> {
self.as_ref().transpose()
}
#[inline(always)]
pub fn conjugate(&self) -> ColRef<'_, T::Conj, Rows>
where
T: Conjugate,
{
self.as_ref().conjugate()
}
#[inline(always)]
pub fn canonical(&self) -> ColRef<'_, T::Canonical, Rows>
where
T: Conjugate,
{
self.as_ref().canonical()
}
#[inline(always)]
pub fn adjoint(&self) -> RowRef<'_, T::Conj, Rows>
where
T: Conjugate,
{
self.as_ref().adjoint()
}
#[track_caller]
#[inline(always)]
pub fn get<RowRange>(
&self,
row: RowRange,
) -> <ColRef<'_, T, Rows> as ColIndex<RowRange>>::Target
where
for<'a> ColRef<'a, T, Rows>: ColIndex<RowRange>,
{
<ColRef<'_, T, Rows> as ColIndex<RowRange>>::get(self.as_ref(), row)
}
#[track_caller]
#[inline(always)]
pub unsafe fn get_unchecked<RowRange>(
&self,
row: RowRange,
) -> <ColRef<'_, T, Rows> as ColIndex<RowRange>>::Target
where
for<'a> ColRef<'a, T, Rows>: ColIndex<RowRange>,
{
unsafe {
<ColRef<'_, T, Rows> as ColIndex<RowRange>>::get_unchecked(
self.as_ref(),
row,
)
}
}
#[inline]
pub fn reverse_rows(&self) -> ColRef<'_, T, Rows> {
self.as_ref().reverse_rows()
}
#[inline]
pub fn subrows<V: Shape>(
&self,
row_start: IdxInc<Rows>,
nrows: V,
) -> ColRef<'_, T, V> {
self.as_ref().subrows(row_start, nrows)
}
#[inline]
pub fn as_row_shape<V: Shape>(&self, nrows: V) -> ColRef<'_, T, V> {
self.as_ref().as_row_shape(nrows)
}
#[inline]
pub fn as_dyn_rows(&self) -> ColRef<'_, T, usize> {
self.as_ref().as_dyn_rows()
}
#[inline]
pub fn as_dyn_stride(&self) -> ColRef<'_, T, Rows, isize> {
self.as_ref().as_dyn_stride()
}
#[inline]
pub fn iter(
&self,
) -> impl '_ + ExactSizeIterator + DoubleEndedIterator<Item = &'_ T> {
self.as_ref().iter()
}
#[inline]
#[cfg(feature = "rayon")]
pub fn par_iter(
&self,
) -> impl '_ + rayon::iter::IndexedParallelIterator<Item = &'_ T>
where
T: Sync,
{
self.as_ref().par_iter()
}
#[inline]
#[track_caller]
#[cfg(feature = "rayon")]
pub fn par_partition(
&self,
count: usize,
) -> impl '_ + rayon::iter::IndexedParallelIterator<Item = ColRef<'_, T, usize>>
where
T: Sync,
{
self.as_ref().par_partition(count)
}
#[inline]
pub fn try_as_col_major(
&self,
) -> Option<ColRef<'_, T, Rows, ContiguousFwd>> {
self.as_ref().try_as_col_major()
}
#[inline]
pub fn try_as_col_major_mut(
&mut self,
) -> Option<ColMut<'_, T, Rows, ContiguousFwd>> {
self.as_ref()
.try_as_col_major()
.map(|x| unsafe { x.const_cast() })
}
#[inline]
pub fn as_mat(&self) -> MatRef<'_, T, Rows, usize, isize> {
self.as_ref().as_mat()
}
#[inline]
pub fn as_mat_mut(&mut self) -> MatMut<'_, T, Rows, usize, isize> {
unsafe { self.as_ref().as_mat().const_cast() }
}
#[inline]
pub fn as_diagonal(&self) -> DiagRef<'_, T, Rows> {
self.rb().as_diagonal()
}
}
impl<T, Rows: Shape> Col<T, Rows> {
#[inline(always)]
pub fn as_ptr_mut(&mut self) -> *mut T {
self.as_mut().as_ptr_mut()
}
#[inline(always)]
pub fn ptr_at_mut(&mut self, row: IdxInc<Rows>) -> *mut T {
self.as_mut().ptr_at_mut(row)
}
#[inline(always)]
#[track_caller]
pub unsafe fn ptr_inbounds_at_mut(&mut self, row: Idx<Rows>) -> *mut T {
self.as_mut().ptr_inbounds_at_mut(row)
}
#[inline]
#[track_caller]
pub fn split_at_row_mut(
&mut self,
row: IdxInc<Rows>,
) -> (ColMut<'_, T, usize>, ColMut<'_, T, usize>) {
self.as_mut().split_at_row_mut(row)
}
#[inline(always)]
pub fn transpose_mut(&mut self) -> RowMut<'_, T, Rows> {
self.as_mut().transpose_mut()
}
#[inline(always)]
pub fn conjugate_mut(&mut self) -> ColMut<'_, T::Conj, Rows>
where
T: Conjugate,
{
self.as_mut().conjugate_mut()
}
#[inline(always)]
pub fn canonical_mut(&mut self) -> ColMut<'_, T::Canonical, Rows>
where
T: Conjugate,
{
self.as_mut().canonical_mut()
}
#[inline(always)]
pub fn adjoint_mut(&mut self) -> RowMut<'_, T::Conj, Rows>
where
T: Conjugate,
{
self.as_mut().adjoint_mut()
}
#[track_caller]
#[inline(always)]
pub fn get_mut<RowRange>(
&mut self,
row: RowRange,
) -> <ColMut<'_, T, Rows> as ColIndex<RowRange>>::Target
where
for<'a> ColMut<'a, T, Rows>: ColIndex<RowRange>,
{
<ColMut<'_, T, Rows> as ColIndex<RowRange>>::get(self.as_mut(), row)
}
#[track_caller]
#[inline(always)]
pub unsafe fn get_mut_unchecked<RowRange>(
&mut self,
row: RowRange,
) -> <ColMut<'_, T, Rows> as ColIndex<RowRange>>::Target
where
for<'a> ColMut<'a, T, Rows>: ColIndex<RowRange>,
{
unsafe {
<ColMut<'_, T, Rows> as ColIndex<RowRange>>::get_unchecked(
self.as_mut(),
row,
)
}
}
#[inline]
pub fn reverse_rows_mut(&mut self) -> ColMut<'_, T, Rows> {
self.as_mut().reverse_rows_mut()
}
#[inline]
pub fn subrows_mut<V: Shape>(
&mut self,
row_start: IdxInc<Rows>,
nrows: V,
) -> ColMut<'_, T, V> {
self.as_mut().subrows_mut(row_start, nrows)
}
#[inline]
pub fn as_row_shape_mut<V: Shape>(&mut self, nrows: V) -> ColMut<'_, T, V> {
self.as_mut().as_row_shape_mut(nrows)
}
#[inline]
pub fn as_dyn_rows_mut(&mut self) -> ColMut<'_, T, usize> {
self.as_mut().as_dyn_rows_mut()
}
#[inline]
pub fn as_dyn_stride_mut(&mut self) -> ColMut<'_, T, Rows, isize> {
self.as_mut().as_dyn_stride_mut()
}
#[inline]
pub fn iter_mut(
&mut self,
) -> impl '_ + ExactSizeIterator + DoubleEndedIterator<Item = &'_ mut T> {
self.as_mut().iter_mut()
}
#[inline]
#[cfg(feature = "rayon")]
pub fn par_iter_mut(
&mut self,
) -> impl '_ + rayon::iter::IndexedParallelIterator<Item = &'_ mut T>
where
T: Send,
{
self.as_mut().par_iter_mut()
}
#[inline]
#[track_caller]
#[cfg(feature = "rayon")]
pub fn par_partition_mut(
&mut self,
count: usize,
) -> impl '_ + rayon::iter::IndexedParallelIterator<Item = ColMut<'_, T, usize>>
where
T: Send,
{
self.as_mut().par_partition_mut(count)
}
#[inline]
pub fn as_diagonal_mut(&mut self) -> DiagMut<'_, T, Rows> {
self.as_mut().as_diagonal_mut()
}
}
impl<'short, T, Rows: Shape> Reborrow<'short> for Own<T, Rows> {
type Target = Ref<'short, T, Rows>;
#[inline]
fn rb(&'short self) -> Self::Target {
Ref {
imp: ColView {
nrows: self.column.nrows(),
row_stride: 1,
ptr: unsafe {
NonNull::new_unchecked(self.column.as_ptr() as *mut T)
},
},
__marker: core::marker::PhantomData,
}
}
}
impl<'short, T, Rows: Shape> ReborrowMut<'short> for Own<T, Rows> {
type Target = Mut<'short, T, Rows>;
#[inline]
fn rb_mut(&'short mut self) -> Self::Target {
Mut {
imp: ColView {
nrows: self.column.nrows(),
row_stride: 1,
ptr: unsafe {
NonNull::new_unchecked(self.column.as_ptr_mut())
},
},
__marker: core::marker::PhantomData,
}
}
}
impl<T, Rows: Shape> Col<T, Rows>
where
T: RealField,
{
pub fn max(&self) -> Option<T> {
self.as_dyn_rows().as_dyn_stride().internal_max()
}
pub fn min(&self) -> Option<T> {
self.as_dyn_rows().as_dyn_stride().internal_min()
}
}
#[cfg(test)]
mod tests {
use crate::Col;
#[test]
fn test_col_min() {
let col: Col<f64> = Col::from_fn(5, |x| (x + 1) as f64);
assert_eq!(col.min(), Some(1.0));
let empty: Col<f64> = Col::from_fn(0, |_| 0.0);
assert_eq!(empty.min(), None);
}
#[test]
fn test_col_max() {
let col: Col<f64> = Col::from_fn(5, |x| (x + 1) as f64);
assert_eq!(col.max(), Some(5.0));
let empty: Col<f64> = Col::from_fn(0, |_| 0.0);
assert_eq!(empty.max(), None);
}
#[test]
fn test_from_iter() {
let col: Col<i32> = (0..10).collect();
assert_eq!(col.nrows(), 10);
assert_eq!(col[0], 0);
assert_eq!(col[9], 9);
}
}