Add some binary ops.

This commit is contained in:
laurent
2023-06-21 08:32:35 +01:00
parent 3a5405ca6d
commit 0839954770
2 changed files with 70 additions and 0 deletions

View File

@ -301,6 +301,17 @@ impl Tensor {
self.id self.id
} }
pub fn is_contiguous(&self) -> bool {
let mut acc = 1;
for (&stride, &dim) in self.stride.iter().zip(self.shape.dims().iter()).rev() {
if stride != acc {
return false;
}
acc *= dim;
}
true
}
/// Return all the nodes that lead to this value in a topologically sorted vec, the first /// Return all the nodes that lead to this value in a topologically sorted vec, the first
/// elements having dependencies on the latter ones, e.g. the first element if any is the /// elements having dependencies on the latter ones, e.g. the first element if any is the
/// argument. /// argument.
@ -432,3 +443,44 @@ impl Tensor {
Ok(grads) Ok(grads)
} }
} }
macro_rules! bin_trait {
($trait:ident, $fn1:ident) => {
impl<B: std::borrow::Borrow<Tensor>> std::ops::$trait<B> for Tensor {
type Output = Result<Tensor>;
fn $fn1(self, rhs: B) -> Self::Output {
Tensor::$fn1(&self, rhs.borrow())
}
}
impl<B: std::borrow::Borrow<Tensor>> std::ops::$trait<B> for &Tensor {
type Output = Result<Tensor>;
fn $fn1(self, rhs: B) -> Self::Output {
Tensor::$fn1(&self, rhs.borrow())
}
}
impl<B: std::borrow::Borrow<Tensor>> std::ops::$trait<Result<B>> for Tensor {
type Output = Result<Tensor>;
fn $fn1(self, rhs: Result<B>) -> Self::Output {
Tensor::$fn1(&self, rhs?.borrow())
}
}
impl<B: std::borrow::Borrow<Tensor>> std::ops::$trait<Result<B>> for &Tensor {
type Output = Result<Tensor>;
fn $fn1(self, rhs: Result<B>) -> Self::Output {
Tensor::$fn1(&self, rhs?.borrow())
}
}
};
}
bin_trait!(Add, add);
bin_trait!(Sub, sub);
bin_trait!(Mul, mul);
bin_trait!(Div, div);

View File

@ -35,3 +35,21 @@ fn tensor_2d() -> Result<()> {
assert_eq!(content, data); assert_eq!(content, data);
Ok(()) Ok(())
} }
#[test]
fn binary_op() -> Result<()> {
let data = &[[3f32, 1., 4., 1., 5.], [2., 1., 7., 8., 2.]];
let tensor = Tensor::new(data, Device::Cpu)?;
let data2 = &[[5f32, 5., 5., 5., 5.], [2., 1., 7., 8., 2.]];
let tensor2 = Tensor::new(data2, Device::Cpu)?;
let tensor = (&tensor + (&tensor * &tensor)? / (&tensor + &tensor2))?;
let dims = tensor.shape().r2()?;
assert_eq!(dims, (2, 5));
let content: Vec<Vec<f32>> = tensor.to_vec2()?;
assert_eq!(content[0], [4.125, 1.1666666, 5.7777777, 1.1666666, 7.5]);
assert_eq!(content[1], [3.0, 1.5, 10.5, 12.0, 3.0]);
let tensor = (&tensor - &tensor)?;
let content: Vec<Vec<f32>> = tensor.to_vec2()?;
assert_eq!(content[0], [0., 0., 0., 0., 0.]);
Ok(())
}