use std::ops::Mul;
use ariadnetor_core::Scalar;
use num_traits::Float;
use super::Tensor;
use crate::{BlockCoord, BlockMeta, BlockSparseLayout, BlockSparseStorage, QNIndex, Sector};
impl<T, S> Tensor<BlockSparseStorage<T>, BlockSparseLayout<S>>
where
S: Sector,
{
pub fn order(&self) -> ariadnetor_core::backend::MemoryOrder {
self.data.layout().order()
}
pub fn indices(&self) -> &[QNIndex<S>] {
self.data.layout().indices()
}
pub fn flux(&self) -> &S {
self.data.layout().flux()
}
pub fn num_blocks(&self) -> usize {
self.data.layout().num_blocks()
}
pub fn block_metas(&self) -> &[BlockMeta] {
self.data.layout().block_metas()
}
pub fn block_shape(&self, coord: &BlockCoord) -> Option<Vec<usize>> {
self.data.layout().block_shape(coord)
}
pub fn block_data(&self, coord: &BlockCoord) -> Option<&[T]> {
self.data.block_data(coord)
}
pub fn block_data_mut(&mut self, coord: &BlockCoord) -> Option<&mut [T]>
where
T: Clone,
{
self.data.block_data_mut(coord)
}
}
impl<T, S> Tensor<BlockSparseStorage<T>, BlockSparseLayout<S>>
where
T: Scalar,
S: Sector,
{
pub fn norm(&self) -> T::Real {
let mut sq = <T::Real as num_traits::Zero>::zero();
for &x in self.data.storage().data() {
let a = x.abs();
sq = sq + a * a;
}
<T::Real as Float>::sqrt(sq)
}
pub fn dagger(&self) -> Self {
let td = self.data.dagger();
Self { data: td }
}
pub fn conj(&self) -> Self {
let td = self.data.conj();
Self { data: td }
}
}
impl<T, S> Tensor<BlockSparseStorage<T>, BlockSparseLayout<S>>
where
T: Clone,
S: Sector,
{
pub fn scale<F>(&mut self, factor: F)
where
T: Mul<F, Output = T>,
F: Clone,
{
self.data.scale(factor);
}
pub fn scaled<F>(&self, factor: F) -> Self
where
T: Mul<F, Output = T>,
F: Clone,
{
Self {
data: self.data.scaled(factor),
}
}
}