rlst 0.10.1

A Rust native linear algebra library.
Documentation
//! Reference to an array.
//!
//! A reference is an owned struct that holds a reference to an array. It is used to
//! pass arrays to functions without transferring ownership.

use crate::{
    ContainerType,
    dense::array::Array,
    traits::{
        accessors::{
            RawAccess, RawAccessMut, StableRawAccessMut, UnsafeDisjointRandom1DAccessMut,
            UnsafeRandom1DAccessByRef, UnsafeRandom1DAccessByValue, UnsafeRandom1DAccessMut,
            UnsafeRandomAccessByRef, UnsafeRandomAccessByValue, UnsafeRandomAccessMut,
        },
        base_operations::{BaseItem, ResizeInPlace, Shape, Stride},
    },
};

/// Array implementation forwarding operations through a shared borrow.
pub struct ArrayRef<'a, ArrayImpl, const NDIM: usize>(&'a Array<ArrayImpl, NDIM>);

impl<'a, ArrayImpl, const NDIM: usize> ContainerType for ArrayRef<'a, ArrayImpl, NDIM>
where
    ArrayImpl: ContainerType,
{
    type Type = ArrayImpl::Type;
}

impl<'a, ArrayImpl, const NDIM: usize> BaseItem for ArrayRef<'a, ArrayImpl, NDIM>
where
    ArrayImpl: BaseItem,
{
    type Item = ArrayImpl::Item;
}

impl<'a, ArrayImpl, const NDIM: usize> ArrayRef<'a, ArrayImpl, NDIM> {
    /// Wrap a shared borrow without copying array data.
    pub fn new(arr: &'a Array<ArrayImpl, NDIM>) -> Self {
        Self(arr)
    }
}

impl<ArrayImpl: Shape<NDIM>, const NDIM: usize> Shape<NDIM> for ArrayRef<'_, ArrayImpl, NDIM> {
    #[inline(always)]
    fn shape(&self) -> [usize; NDIM] {
        self.0.shape()
    }
}

impl<ArrayImpl: Stride<NDIM>, const NDIM: usize> Stride<NDIM> for ArrayRef<'_, ArrayImpl, NDIM> {
    #[inline(always)]
    fn stride(&self) -> [usize; NDIM] {
        self.0.stride()
    }
}

impl<ArrayImpl: RawAccess, const NDIM: usize> RawAccess for ArrayRef<'_, ArrayImpl, NDIM> {
    #[inline(always)]
    fn data(&self) -> Option<&[Self::Item]> {
        self.0.data()
    }
}

impl<ArrayImpl: UnsafeRandomAccessByValue<NDIM>, const NDIM: usize> UnsafeRandomAccessByValue<NDIM>
    for ArrayRef<'_, ArrayImpl, NDIM>
{
    #[inline(always)]
    unsafe fn get_value_unchecked(&self, multi_index: [usize; NDIM]) -> Self::Item {
        unsafe { self.0.get_value_unchecked(multi_index) }
    }
}

impl<ArrayImpl: UnsafeRandom1DAccessByValue, const NDIM: usize> UnsafeRandom1DAccessByValue
    for ArrayRef<'_, ArrayImpl, NDIM>
{
    #[inline(always)]
    unsafe fn get_value_1d_unchecked(&self, index: usize) -> Self::Item {
        unsafe { self.0.imp().get_value_1d_unchecked(index) }
    }
}

impl<ArrayImpl: UnsafeRandom1DAccessByRef, const NDIM: usize> UnsafeRandom1DAccessByRef
    for ArrayRef<'_, ArrayImpl, NDIM>
{
    #[inline(always)]
    unsafe fn get_1d_unchecked(&self, index: usize) -> &Self::Item {
        unsafe { self.0.imp().get_1d_unchecked(index) }
    }
}

impl<ArrayImpl: UnsafeRandomAccessByRef<NDIM>, const NDIM: usize> UnsafeRandomAccessByRef<NDIM>
    for ArrayRef<'_, ArrayImpl, NDIM>
{
    #[inline(always)]
    unsafe fn get_unchecked(&self, multi_index: [usize; NDIM]) -> &Self::Item {
        unsafe { self.0.get_unchecked(multi_index) }
    }
}

/////////// ArrayRefMut

/// Array implementation forwarding operations through an exclusive borrow.
pub struct ArrayRefMut<'a, ArrayImpl, const NDIM: usize>(&'a mut Array<ArrayImpl, NDIM>);

impl<Item: Copy + Default> crate::dense::macros::direct::Output<0>
    for Array<ArrayRefMut<'_, super::zero_dim::ScalarArrayImpl<Item>, 0>, 0>
{
    unsafe fn output_mut(&mut self, _index: [usize; 0]) -> &mut Item {
        self.imp_mut().0.scalar_mut()
    }
}

impl<'a, ArrayImpl, const NDIM: usize> BaseItem for ArrayRefMut<'a, ArrayImpl, NDIM>
where
    ArrayImpl: BaseItem,
{
    type Item = ArrayImpl::Item;
}

impl<'a, ArrayImpl, const NDIM: usize> ArrayRefMut<'a, ArrayImpl, NDIM> {
    /// Wrap an exclusive borrow without copying array data.
    pub fn new(arr: &'a mut Array<ArrayImpl, NDIM>) -> Self {
        Self(arr)
    }
}

impl<'a, ArrayImpl, const NDIM: usize> ContainerType for ArrayRefMut<'a, ArrayImpl, NDIM>
where
    ArrayImpl: ContainerType,
{
    type Type = ArrayImpl::Type;
}

impl<ArrayImpl: Shape<NDIM>, const NDIM: usize> Shape<NDIM> for ArrayRefMut<'_, ArrayImpl, NDIM> {
    #[inline(always)]
    fn shape(&self) -> [usize; NDIM] {
        self.0.shape()
    }
}

impl<ArrayImpl: Stride<NDIM>, const NDIM: usize> Stride<NDIM> for ArrayRefMut<'_, ArrayImpl, NDIM> {
    #[inline(always)]
    fn stride(&self) -> [usize; NDIM] {
        self.0.stride()
    }
}

impl<ArrayImpl: RawAccess, const NDIM: usize> RawAccess for ArrayRefMut<'_, ArrayImpl, NDIM> {
    #[inline(always)]
    fn data(&self) -> Option<&[Self::Item]> {
        self.0.data()
    }
}

unsafe impl<ArrayImpl: StableRawAccessMut, const NDIM: usize> StableRawAccessMut
    for ArrayRefMut<'_, ArrayImpl, NDIM>
{
}

impl<ArrayImpl: RawAccessMut, const NDIM: usize> RawAccessMut for ArrayRefMut<'_, ArrayImpl, NDIM> {
    #[inline(always)]
    fn data_mut(&mut self) -> Option<&mut [Self::Item]> {
        self.0.data_mut()
    }
}

impl<ArrayImpl: UnsafeRandomAccessByValue<NDIM>, const NDIM: usize> UnsafeRandomAccessByValue<NDIM>
    for ArrayRefMut<'_, ArrayImpl, NDIM>
{
    #[inline(always)]
    unsafe fn get_value_unchecked(&self, multi_index: [usize; NDIM]) -> Self::Item {
        unsafe { self.0.get_value_unchecked(multi_index) }
    }
}

impl<ArrayImpl: UnsafeRandom1DAccessByValue, const NDIM: usize> UnsafeRandom1DAccessByValue
    for ArrayRefMut<'_, ArrayImpl, NDIM>
{
    #[inline(always)]
    unsafe fn get_value_1d_unchecked(&self, index: usize) -> Self::Item {
        unsafe { self.0.imp().get_value_1d_unchecked(index) }
    }
}

impl<ArrayImpl: UnsafeRandom1DAccessByRef, const NDIM: usize> UnsafeRandom1DAccessByRef
    for ArrayRefMut<'_, ArrayImpl, NDIM>
{
    #[inline(always)]
    unsafe fn get_1d_unchecked(&self, index: usize) -> &Self::Item {
        unsafe { self.0.imp().get_1d_unchecked(index) }
    }
}

impl<ArrayImpl: UnsafeRandom1DAccessMut, const NDIM: usize> UnsafeRandom1DAccessMut
    for ArrayRefMut<'_, ArrayImpl, NDIM>
{
    #[inline(always)]
    unsafe fn get_1d_unchecked_mut(&mut self, index: usize) -> &mut Self::Item {
        unsafe { self.0.imp_mut().get_1d_unchecked_mut(index) }
    }
}

// SAFETY: the view forwards indices unchanged and its source provides the
// disjointness and stability guarantee.
unsafe impl<ArrayImpl: UnsafeDisjointRandom1DAccessMut, const NDIM: usize>
    UnsafeDisjointRandom1DAccessMut for ArrayRefMut<'_, ArrayImpl, NDIM>
{
}

impl<ArrayImpl: UnsafeRandomAccessByRef<NDIM>, const NDIM: usize> UnsafeRandomAccessByRef<NDIM>
    for ArrayRefMut<'_, ArrayImpl, NDIM>
{
    #[inline(always)]
    unsafe fn get_unchecked(&self, multi_index: [usize; NDIM]) -> &Self::Item {
        unsafe { self.0.get_unchecked(multi_index) }
    }
}

impl<ArrayImpl: UnsafeRandomAccessMut<NDIM>, const NDIM: usize> UnsafeRandomAccessMut<NDIM>
    for ArrayRefMut<'_, ArrayImpl, NDIM>
{
    #[inline(always)]
    unsafe fn get_unchecked_mut(&mut self, multi_index: [usize; NDIM]) -> &mut Self::Item {
        unsafe { self.0.get_unchecked_mut(multi_index) }
    }
}

impl<ArrayImpl: ResizeInPlace<NDIM>, const NDIM: usize> ResizeInPlace<NDIM>
    for ArrayRefMut<'_, ArrayImpl, NDIM>
{
    #[inline(always)]
    fn resize_in_place(&mut self, shape: [usize; NDIM]) {
        self.0.resize_in_place(shape)
    }
}