use std::{marker::PhantomData, ops::Neg};
use crate::{
EvaluateArray, InnerProductSpace, LinearSpace, RlstScalar, dense::array::DynArray,
operator::element::Element,
};
pub struct ArrayVectorSpace<Item> {
dimension: usize,
_marker: PhantomData<Item>,
}
impl<Item> ArrayVectorSpace<Item> {
pub fn new(dimension: usize) -> Self {
Self {
dimension,
_marker: PhantomData,
}
}
}
impl<Item> LinearSpace for ArrayVectorSpace<Item>
where
Item: Copy
+ Default
+ 'static
+ std::ops::Add<Output = Item>
+ std::ops::Sub<Output = Item>
+ std::ops::Neg<Output = Item>
+ std::ops::AddAssign<Item>
+ std::ops::SubAssign<Item>
+ std::ops::Mul<Item, Output = Item>
+ std::ops::MulAssign<Item>,
{
type F = Item;
type Impl = DynArray<Item, 1>;
fn zero(&self) -> crate::operator::element::Element<'_, Self> {
Element::new(self, DynArray::<Item, 1>::from_shape([self.dimension]))
}
fn add(
&self,
x: &crate::operator::element::Element<Self>,
y: &crate::operator::element::Element<Self>,
) -> crate::operator::element::Element<'_, Self> {
Element::new(self, (x.imp().r() + y.imp().r()).eval())
}
fn sub(
&self,
x: &crate::operator::element::Element<Self>,
y: &crate::operator::element::Element<Self>,
) -> crate::operator::element::Element<'_, Self> {
Element::new(self, (x.imp().r() - y.imp().r()).eval())
}
fn scalar_mul(
&self,
scalar: &Self::F,
x: &crate::operator::element::Element<Self>,
) -> crate::operator::element::Element<'_, Self> {
Element::new(
self,
DynArray::<_, 1>::new_from(&x.imp().r().scalar_mul(*scalar)),
)
}
fn neg(
&self,
x: &crate::operator::element::Element<Self>,
) -> crate::operator::element::Element<'_, Self> {
Element::new(self, x.imp().r().neg().eval())
}
fn sum_inplace(
&self,
x: &mut crate::operator::element::Element<Self>,
y: &crate::operator::element::Element<Self>,
) {
*x.imp_mut() += y.imp().r();
}
fn sub_inplace(
&self,
x: &mut crate::operator::element::Element<Self>,
y: &crate::operator::element::Element<Self>,
) {
*x.imp_mut() -= y.imp().r();
}
fn scale_inplace(&self, scalar: &Self::F, x: &mut crate::operator::element::Element<Self>) {
*x.imp_mut() *= *scalar;
}
fn copy_from(
&self,
x: &crate::operator::element::Element<Self>,
) -> crate::operator::element::Element<'_, Self> {
Element::new(self, x.imp().eval())
}
fn axpy_inplace(
&self,
alpha: &Self::F,
x: &crate::operator::element::Element<Self>,
y: &mut crate::operator::element::Element<Self>,
) {
*y.imp_mut() += x.imp().r().scalar_mul(*alpha);
}
}
impl<Item> crate::IndexableSpace for ArrayVectorSpace<Item>
where
Self: LinearSpace,
{
fn dimension(&self) -> usize {
self.dimension
}
}
impl<Item> InnerProductSpace for ArrayVectorSpace<Item>
where
Item: Copy
+ Default
+ RlstScalar
+ 'static
+ std::ops::Add<Output = Item>
+ std::ops::Sub<Output = Item>
+ std::ops::Neg<Output = Item>
+ std::ops::AddAssign<Item>
+ std::ops::SubAssign<Item>
+ std::ops::Mul<Item, Output = Item>
+ std::ops::MulAssign<Item>,
{
fn inner_product(&self, x: &Element<Self>, other: &Element<Self>) -> Self::F {
if x.imp().shape() == [0] && other.imp().shape() == [0] {
return Item::zero();
}
x.imp().inner(other.imp()).unwrap()
}
}