use num_traits::{One, Zero};
use crate::{
array::traits::GetWriteableBuffer,
backend::{host::host_backend::HostBackend, traits},
dimension::{axes::Axes, dim::Dimension},
};
#[allow(clippy::module_name_repetitions)]
pub struct ArrayBase<
Backend: traits::Backend,
StorageType: traits::Storage,
NDims: Dimension,
> {
pub(crate) axes: Axes<NDims>,
pub(crate) storage: StorageType,
pub(crate) phantom_backend: std::marker::PhantomData<Backend>,
}
impl<Backend, StorageType, NDims> ArrayBase<Backend, StorageType, NDims>
where
Backend: traits::Backend,
StorageType: traits::Storage,
NDims: Dimension,
{
pub const fn new(axes: Axes<NDims>, storage: StorageType) -> Self
where
StorageType: traits::OwnedStorage,
{
Self { axes, storage, phantom_backend: std::marker::PhantomData }
}
pub unsafe fn new_empty(shape: NDims) -> Self
where
StorageType: traits::OwnedStorage,
{
let storage = StorageType::new_from_shape_uninit(&shape);
Self::new(Axes::<NDims>::new_with_default_stride(shape), storage)
}
pub fn zeros(shape: NDims) -> Self
where
StorageType: traits::OwnedStorage,
StorageType::Scalar: Zero,
{
let mut storage = unsafe { StorageType::new_from_shape_uninit(&shape) };
storage.fill(StorageType::Scalar::zero());
Self::new(Axes::<NDims>::new_with_default_stride(shape), storage)
}
pub fn ones(shape: NDims) -> Self
where
StorageType: traits::OwnedStorage,
StorageType::Scalar: One,
{
let mut storage = unsafe { StorageType::new_from_shape_uninit(&shape) };
storage.fill(StorageType::Scalar::one());
Self::new(Axes::<NDims>::new_with_default_stride(shape), storage)
}
pub fn new_with(shape: NDims, value: StorageType::Scalar) -> Self
where
StorageType: traits::OwnedStorage,
{
let mut storage = unsafe { StorageType::new_from_shape_uninit(&shape) };
storage.fill(value);
Self::new(Axes::<NDims>::new_with_default_stride(shape), storage)
}
pub fn fill(&mut self, value: StorageType::Scalar) {
self.storage.fill(value);
}
pub const fn shape(&self) -> &NDims {
&self.axes.shape
}
pub const fn strides(&self) -> &NDims {
&self.axes.stride
}
}
impl<Backend, StorageType, NDims> traits::ContainerLength
for ArrayBase<Backend, StorageType, NDims>
where
Backend: traits::Backend,
StorageType: traits::Storage,
NDims: Dimension,
{
fn len(&self) -> usize {
self.storage.len()
}
}
impl<'a, Backend, StorageType, NDims> traits::ContainerLength
for &'a ArrayBase<Backend, StorageType, NDims>
where
Backend: traits::Backend,
StorageType: traits::Storage,
NDims: Dimension,
{
fn len(&self) -> usize {
self.storage.len()
}
}
impl<'a, Backend, StorageType, NDims> traits::ContainerLength
for &'a mut ArrayBase<Backend, StorageType, NDims>
where
Backend: traits::Backend,
StorageType: traits::Storage,
NDims: Dimension,
{
fn len(&self) -> usize {
self.storage.len()
}
}
impl<Backend, StorageType, NDims> traits::ContainerScalarType
for ArrayBase<Backend, StorageType, NDims>
where
Backend: traits::Backend,
StorageType: traits::Storage,
NDims: Dimension,
{
type Scalar = StorageType::Scalar;
}
impl<'a, Backend, StorageType, NDims> traits::ContainerScalarType
for &'a ArrayBase<Backend, StorageType, NDims>
where
Backend: traits::Backend,
StorageType: traits::Storage,
NDims: Dimension,
{
type Scalar = StorageType::Scalar;
}
impl<'a, Backend, StorageType, NDims> traits::ContainerScalarType
for &'a mut ArrayBase<Backend, StorageType, NDims>
where
Backend: traits::Backend,
StorageType: traits::Storage,
NDims: Dimension,
{
type Scalar = StorageType::Scalar;
}
impl<Backend, StorageType, NDims> traits::ContainerStorageType
for ArrayBase<Backend, StorageType, NDims>
where
Backend: traits::Backend,
StorageType: traits::Storage,
NDims: Dimension,
{
type Storage = StorageType;
}
impl<'a, Backend, StorageType, NDims> traits::ContainerStorageType
for &'a ArrayBase<Backend, StorageType, NDims>
where
Backend: traits::Backend,
StorageType: traits::Storage,
NDims: Dimension,
{
type Storage = StorageType;
}
impl<'a, Backend, StorageType, NDims> traits::ContainerStorageType
for &'a mut ArrayBase<Backend, StorageType, NDims>
where
Backend: traits::Backend,
StorageType: traits::Storage,
NDims: Dimension,
{
type Storage = StorageType;
}
impl<Backend, StorageType, NDims> traits::ContainerStorageAccessor
for ArrayBase<Backend, StorageType, NDims>
where
Backend: traits::Backend,
StorageType: traits::Storage,
NDims: Dimension,
{
#[inline(always)]
fn get_storage(&self) -> &Self::Storage {
&self.storage
}
}
impl<Backend, StorageType, NDims> traits::MutableContainerStorageAccessor
for ArrayBase<Backend, StorageType, NDims>
where
Backend: traits::Backend,
StorageType: traits::Storage,
NDims: Dimension,
{
#[inline(always)]
fn get_storage_mut(&mut self) -> &mut Self::Storage {
&mut self.storage
}
}
impl<'a, Backend, StorageType, NDims> traits::ContainerStorageAccessor
for &'a ArrayBase<Backend, StorageType, NDims>
where
Backend: traits::Backend,
StorageType: traits::Storage,
NDims: Dimension,
{
#[inline(always)]
fn get_storage(&self) -> &Self::Storage {
&self.storage
}
}
impl<'a, Backend, StorageType, NDims> traits::ContainerStorageAccessor
for &'a mut ArrayBase<Backend, StorageType, NDims>
where
Backend: traits::Backend,
StorageType: traits::Storage,
NDims: Dimension,
{
#[inline(always)]
fn get_storage(&self) -> &Self::Storage {
&self.storage
}
}
impl<'a, Backend, StorageType, NDims> traits::MutableContainerStorageAccessor
for &'a mut ArrayBase<Backend, StorageType, NDims>
where
Backend: traits::Backend,
StorageType: traits::Storage,
NDims: Dimension,
{
#[inline(always)]
fn get_storage_mut(&mut self) -> &mut Self::Storage {
&mut self.storage
}
}
impl<Backend, StorageType, NDims> traits::ContainerBackendType
for ArrayBase<Backend, StorageType, NDims>
where
Backend: traits::Backend,
StorageType: traits::Storage,
NDims: Dimension,
{
type Backend = Backend;
}
impl<'a, Backend, StorageType, NDims> traits::ContainerBackendType
for &'a ArrayBase<Backend, StorageType, NDims>
where
Backend: traits::Backend,
StorageType: traits::Storage,
NDims: Dimension,
{
type Backend = Backend;
}
impl<'a, Backend, StorageType, NDims> traits::ContainerBackendType
for &'a mut ArrayBase<Backend, StorageType, NDims>
where
Backend: traits::Backend,
StorageType: traits::Storage,
NDims: Dimension,
{
type Backend = Backend;
}
impl<Backend, StorageType, NDims> GetWriteableBuffer
for ArrayBase<Backend, StorageType, NDims>
where
Backend: traits::Backend,
StorageType: traits::Storage + GetWriteableBuffer,
NDims: Dimension,
{
type Buffer = StorageType::Buffer;
#[inline(always)]
unsafe fn get_buffer_and_set_no_free(
&mut self,
len: usize,
) -> Option<Self::Buffer> {
self.storage.get_buffer_and_set_no_free(len)
}
}
impl<'a, Backend, StorageType, NDims> GetWriteableBuffer
for &'a ArrayBase<Backend, StorageType, NDims>
where
Backend: traits::Backend,
StorageType: traits::Storage + GetWriteableBuffer,
NDims: Dimension,
{
type Buffer = StorageType::Buffer;
#[inline(always)]
unsafe fn get_buffer_and_set_no_free(
&mut self,
_: usize,
) -> Option<Self::Buffer> {
None
}
}
impl<'a, Backend, StorageType, NDims> GetWriteableBuffer
for &'a mut ArrayBase<Backend, StorageType, NDims>
where
Backend: traits::Backend,
StorageType: traits::Storage + GetWriteableBuffer,
NDims: Dimension,
{
type Buffer = StorageType::Buffer;
#[inline(always)]
unsafe fn get_buffer_and_set_no_free(
&mut self,
_: usize,
) -> Option<Self::Buffer> {
self.storage.get_buffer_and_set_no_free(self.storage.len())
}
}
impl<StorageType, NDims> traits::ScalarAccessor
for ArrayBase<HostBackend, StorageType, NDims>
where
StorageType: traits::Storage,
NDims: Dimension,
{
#[inline(always)]
fn get_scalar(&self, index: usize) -> Self::Scalar {
self.storage[index]
}
}
impl<StorageType, NDims> traits::ScalarWriter
for ArrayBase<HostBackend, StorageType, NDims>
where
StorageType: traits::Storage,
NDims: Dimension,
{
#[inline(always)]
fn write_scalar(&mut self, value: Self::Scalar, index: usize) {
self.storage[index] = value;
}
}
impl<'a, StorageType, NDims> traits::ScalarAccessor
for &'a ArrayBase<HostBackend, StorageType, NDims>
where
StorageType: traits::Storage,
NDims: Dimension,
{
#[inline(always)]
fn get_scalar(&self, index: usize) -> Self::Scalar {
self.storage[index]
}
}
impl<'a, StorageType, NDims> traits::ScalarAccessor
for &'a mut ArrayBase<HostBackend, StorageType, NDims>
where
StorageType: traits::Storage,
NDims: Dimension,
{
#[inline(always)]
fn get_scalar(&self, index: usize) -> Self::Scalar {
self.storage[index]
}
}
impl<'a, StorageType, NDims> traits::ScalarWriter
for &'a mut ArrayBase<HostBackend, StorageType, NDims>
where
StorageType: traits::Storage,
NDims: Dimension,
{
#[inline(always)]
fn write_scalar(&mut self, value: Self::Scalar, index: usize) {
self.storage[index] = value;
}
}