acme_tensor/impls/ops/
unary.rs

1/*
2    Appellation: arith <mod>
3    Contrib: FL03 <jo3mccain@icloud.com>
4*/
5use crate::prelude::{Scalar, ScalarExt, TensorExpr};
6use crate::tensor::*;
7use acme::ops::unary::UnaryOp;
8use core::ops;
9
10impl<T> ops::Neg for TensorBase<T>
11where
12    T: Copy + ops::Neg<Output = T>,
13{
14    type Output = Self;
15
16    fn neg(self) -> Self::Output {
17        let shape = self.shape().clone();
18        let store = self.data().iter().map(|a| (*a).neg()).collect();
19        let op = TensorExpr::unary(self, UnaryOp::Neg);
20        from_vec_with_op(false, op, shape, store)
21    }
22}
23
24impl<'a, T> ops::Neg for &'a TensorBase<T>
25where
26    T: Copy + ops::Neg<Output = T>,
27{
28    type Output = TensorBase<T>;
29
30    fn neg(self) -> Self::Output {
31        let shape = self.shape();
32        let store = self.data().iter().map(|a| (*a).neg()).collect();
33        let op = TensorExpr::unary(self.clone(), UnaryOp::Neg);
34        from_vec_with_op(false, op, shape, store)
35    }
36}
37
38impl<T> ops::Not for TensorBase<T>
39where
40    T: Copy + ops::Not<Output = T>,
41{
42    type Output = Self;
43
44    fn not(self) -> Self::Output {
45        let shape = self.shape().clone();
46        let store = self.data().iter().map(|a| (*a).not()).collect();
47        let op = TensorExpr::unary(self, UnaryOp::Not);
48        from_vec_with_op(false, op, shape, store)
49    }
50}
51
52impl<'a, T> ops::Not for &'a TensorBase<T>
53where
54    T: Copy + ops::Not<Output = T>,
55{
56    type Output = TensorBase<T>;
57
58    fn not(self) -> Self::Output {
59        let shape = self.shape();
60        let store = self.data.iter().copied().map(|a| !a).collect();
61        let op = TensorExpr::unary(self.clone(), UnaryOp::Not);
62        from_vec_with_op(false, op, shape, store)
63    }
64}
65
66macro_rules! impl_unary_op {
67    ($variant:ident, $method:ident) => {
68        pub fn $method(&self) -> Self {
69            let shape = self.shape();
70            let store = self.data().iter().copied().map(|v| v.$method()).collect();
71            let op = TensorExpr::unary(self.clone(), UnaryOp::$variant);
72            from_vec_with_op(false, op, shape, store)
73        }
74    };
75    (custom $variant:ident, $method:ident, $f:expr) => {
76        pub fn $method(self) -> Self {
77            let shape = self.shape().clone();
78            let store = self.store.iter().copied().map($f).collect();
79            let op = TensorExpr::unary(self, UnaryOp::$variant);
80            from_vec_with_op(false, op, shape, store)
81        }
82    };
83}
84
85impl<T> TensorBase<T>
86where
87    T: Scalar,
88{
89    pub fn abs(&self) -> TensorBase<<T as Scalar>::Real>
90    where
91        T: Scalar<Real = T>,
92    {
93        let shape = self.shape();
94        let store = self.data.iter().copied().map(Scalar::abs).collect();
95        let op = TensorExpr::unary(self.clone(), UnaryOp::Abs);
96        from_vec_with_op(false, op, shape, store)
97    }
98
99    pub fn sigmoid(&self) -> TensorBase<T>
100    where
101        T: ScalarExt,
102    {
103        let op = TensorExpr::sigmoid(self.clone());
104        let shape = self.shape();
105        let store = self.iter().copied().map(ScalarExt::sigmoid).collect();
106        from_vec_with_op(false, op, shape, store)
107    }
108
109    impl_unary_op!(Cos, cos);
110    impl_unary_op!(Cosh, cosh);
111    impl_unary_op!(Exp, exp);
112    impl_unary_op!(Ln, ln);
113    impl_unary_op!(Recip, recip);
114    impl_unary_op!(Sin, sin);
115    impl_unary_op!(Sinh, sinh);
116    impl_unary_op!(Square, sqr);
117    impl_unary_op!(Sqrt, sqrt);
118    impl_unary_op!(Tan, tan);
119    impl_unary_op!(Tanh, tanh);
120}