use smallvec::smallvec;
use crate::{Element, Recordable, Shape, Tensor};
use super::{Cotangents, Operation, Reads, unary};
#[derive(Debug, Clone, PartialEq, Eq)]
pub(crate) struct Reshape {
pub(crate) shape: Shape,
}
impl Reshape {
pub(crate) fn arity(&self) -> usize {
1
}
pub(crate) fn reads(&self) -> Reads {
Reads::NOTHING
}
pub(crate) fn infer_shape(&self, operands: &[Shape]) -> Shape {
let operand = unary(operands);
assert_eq!(
operand.volume(),
self.shape.volume(),
"reshape from {operand} to {} changes the number of elements",
self.shape
);
self.shape.clone()
}
}
impl Reshape {
pub(crate) fn forward<E: Element>(&self, operands: &[&Tensor<E>]) -> Tensor<E> {
unary(operands).reshape(self.shape.clone())
}
}
impl<Rule: Recordable> Operation<Rule> for Reshape {
fn backward(&self, operands: &[&Rule], _output: &Rule, gradient: &Rule) -> Cotangents<Rule> {
let &operand = unary(operands);
smallvec![Some(gradient.reshape(operand.shape()))]
}
}