#![allow(private_bounds)]
use crate::OpError;
use crate::tensor::backend::{Backend, ComputeFor, DefaultBackend};
use crate::tensor::graph::{NodeKind, TensorGraphEdge};
use crate::tensor::iter::{InformedIter, Iter, StepInfo};
use crate::tensor::mem_formats::layout::Layout;
use crate::tensor::promise::TensorPromise;
use crate::tensor::skeleton::SkeletonSlot;
use crate::tensor::skeleton::{Clean, Tainting};
use crate::tensor::storage::TensorData;
use crate::tensor::traits::{Composable, Dimension, Numeric, Operand};
use std::ops::Index;
use std::sync::Arc;
pub struct Tensor<T, B: Backend = DefaultBackend> {
pub(crate) graph: Arc<TensorGraphEdge<T, B>>,
}
impl<T: ComputeFor<DefaultBackend>> Tensor<T> {
#[inline]
pub fn from_scalar(scalar: T, shape: &[usize]) -> Self {
Self {
graph: Arc::new(TensorGraphEdge::from_tensor_data(TensorData::from_scalar(
scalar, shape,
))),
}
}
#[inline]
pub fn from_vec(vector: Vec<T>, shape: &[usize]) -> Self {
Self {
graph: Arc::new(TensorGraphEdge::from_tensor_data(TensorData::from_vec(
vector, shape, 0,
))),
}
}
#[inline]
pub fn from_slice(data: &[T], shape: &[usize]) -> Self {
Self::from_vec(data.to_vec(), shape)
}
#[inline]
pub fn from_iter<I>(iter: I, shape: &[usize]) -> Self
where
I: IntoIterator<Item = T>,
{
let vector: Vec<T> = std::vec::Vec::from_iter(iter);
Self::from_vec(vector, shape)
}
#[inline]
pub fn eye(n: usize, m: usize) -> Self {
let mut data: Vec<T> = vec![T::ZERO; n * m];
let mut i: usize = 0;
while i < data.len() {
data[i] = T::ONE;
i += m + 1;
}
Self::from_vec(data, &[n, m])
}
}
impl<T: Clone, B: Backend> Tensor<T, B> {
#[inline]
pub(crate) fn from_data(data: TensorData<T>) -> Self {
Self {
graph: Arc::new(TensorGraphEdge::from_tensor_data(data)),
}
}
#[inline]
pub fn data(&self) -> &[T] {
self.graph.get().data()
}
#[inline]
pub fn iter(&self) -> Iter<'_, T> {
self.graph.get().iter()
}
#[inline]
pub unsafe fn iter_as_layout<'a>(&'a self, layout: &'a Layout) -> Iter<'a, T> {
unsafe { self.graph.get().iter_as_layout(layout) }
}
#[inline]
pub fn informed_iter(&self) -> InformedIter<'_, T> {
self.graph.get().informed_iter()
}
#[inline]
pub fn deep_clone(&self) -> Self {
let data = self.graph.get();
Self {
graph: Arc::new(TensorGraphEdge::from_tensor_data(data.deep_clone())),
}
}
#[inline]
pub fn clone_detached(&self) -> Self {
let data = self.graph.get();
Self {
graph: Arc::new(TensorGraphEdge::from_tensor_data(data.clone())),
}
}
}
impl<T: Numeric, B: Backend> Tensor<T, B> {
#[inline]
pub fn to_promise(&self) -> TensorPromise<T, B> {
unsafe {
TensorPromise::new(
super::ops::def_op::OpKind::NoOp,
[NodeKind::Edge(self.graph.clone())].into(),
)
.unwrap_unchecked()
}
}
pub fn get(&self, index: &[usize]) -> Result<&T, OpError> {
self.graph.get().get(index)
}
pub fn item(&self) -> &T {
self.graph.get().item()
}
pub fn to_slot(&self) -> SkeletonSlot<T, B> {
SkeletonSlot::new(self.layout().clone())
}
}
impl<T, B: Backend> Dimension for Tensor<T, B> {
#[inline]
fn layout(&self) -> &super::mem_formats::layout::Layout {
self.graph.layout()
}
}
impl<T, B: Backend> Operand<T, B> for Tensor<T, B> {
fn to_node(&self) -> NodeKind<T, B> {
NodeKind::Edge(self.graph.clone())
}
}
impl<T, B: Backend> Tainting for Tensor<T, B> {
type Mark = Clean;
}
impl<T, B: Backend> Composable<T, B> for Tensor<T, B> {}
impl<T, B: Backend> Clone for Tensor<T, B> {
#[inline]
fn clone(&self) -> Self {
Self {
graph: self.graph.clone(),
}
}
}
#[allow(private_bounds)]
impl<T: std::fmt::Display + Copy, B: Backend> std::fmt::Debug for Tensor<T, B> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
writeln!(f, "Tensor {:?}", self.layout())?;
std::fmt::Display::fmt(self, f)
}
}
impl<T, B> Index<&[usize]> for Tensor<T, B>
where
T: Copy,
B: Backend,
{
type Output = T;
fn index(&self, index: &[usize]) -> &Self::Output {
&self.graph.get()[index]
}
}
#[allow(private_bounds)]
impl<T: std::fmt::Display + Copy, B: Backend> std::fmt::Display for Tensor<T, B> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let mut indent = 0;
let mut in_seq = false;
debug_assert!(!self.shape().is_empty(), "Tensor rank must be >= 1");
let last = self.shape().len() - 1;
for step in self.informed_iter() {
match step {
StepInfo::EnterDimension(dim) => {
write!(f, "{:indent$}[", "", indent = indent)?;
indent += 2;
if dim != last {
writeln!(f)?;
}
}
StepInfo::ExitDimension(dim) => {
indent -= 2;
in_seq = false;
if dim != last {
write!(f, "{:indent$}", "", indent = indent)?;
}
writeln!(f, "]")?;
}
StepInfo::Value(v) => {
if in_seq {
write!(f, ", ")?;
}
write!(f, "{:>4}", v)?;
in_seq = true;
}
_ => {}
}
}
Ok(())
}
}