1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
/*
    Appellation: arith <mod>
    Contrib: FL03 <jo3mccain@icloud.com>
*/
use crate::prelude::{Scalar, TensorExpr};
use crate::tensor::*;
use acme::ops::unary::UnaryOp;
use core::ops;

impl<T> ops::Neg for TensorBase<T>
where
    T: Copy + ops::Neg<Output = T>,
{
    type Output = Self;

    fn neg(self) -> Self::Output {
        let shape = self.shape().clone();
        let store = self.data().iter().map(|a| (*a).neg()).collect();
        let op = TensorExpr::unary(self, UnaryOp::Neg);
        from_vec_with_op(false, op, shape, store)
    }
}

impl<'a, T> ops::Neg for &'a TensorBase<T>
where
    T: Copy + ops::Neg<Output = T>,
{
    type Output = TensorBase<T>;

    fn neg(self) -> Self::Output {
        let shape = self.shape();
        let store = self.data().iter().map(|a| (*a).neg()).collect();
        let op = TensorExpr::unary(self.clone(), UnaryOp::Neg);
        from_vec_with_op(false, op, shape, store)
    }
}

impl<T> ops::Not for TensorBase<T>
where
    T: Copy + ops::Not<Output = T>,
{
    type Output = Self;

    fn not(self) -> Self::Output {
        let shape = self.shape().clone();
        let store = self.data().iter().map(|a| (*a).not()).collect();
        let op = TensorExpr::unary(self, UnaryOp::Not);
        from_vec_with_op(false, op, shape, store)
    }
}

impl<'a, T> ops::Not for &'a TensorBase<T>
where
    T: Copy + ops::Not<Output = T>,
{
    type Output = TensorBase<T>;

    fn not(self) -> Self::Output {
        let shape = self.shape();
        let store = self.data.iter().copied().map(|a| !a).collect();
        let op = TensorExpr::unary(self.clone(), UnaryOp::Not);
        from_vec_with_op(false, op, shape, store)
    }
}

macro_rules! impl_unary_op {
    ($variant:ident, $method:ident) => {
        pub fn $method(&self) -> Self {
            let shape = self.shape();
            let store = self.data().iter().copied().map(|v| v.$method()).collect();
            let op = TensorExpr::unary(self.clone(), UnaryOp::$variant);
            from_vec_with_op(false, op, shape, store)
        }
    };
    (custom $variant:ident, $method:ident, $f:expr) => {
        pub fn $method(self) -> Self {
            let shape = self.shape().clone();
            let store = self.store.iter().copied().map($f).collect();
            let op = TensorExpr::unary(self, UnaryOp::$variant);
            from_vec_with_op(false, op, shape, store)
        }
    };
}

impl<T> TensorBase<T>
where
    T: Scalar,
{
    pub fn abs(&self) -> TensorBase<<T as Scalar>::Real>
    where
        T: Scalar<Real = T>,
    {
        let shape = self.shape();
        let store = self.data.iter().copied().map(|v| v.abs()).collect();
        let op = TensorExpr::unary(self.clone(), UnaryOp::Abs);
        from_vec_with_op(false, op, shape, store)
    }

    impl_unary_op!(Cos, cos);
    impl_unary_op!(Cosh, cosh);
    impl_unary_op!(Exp, exp);
    impl_unary_op!(Ln, ln);
    impl_unary_op!(Sin, sin);
    impl_unary_op!(Sinh, sinh);
    impl_unary_op!(Square, sqr);
    impl_unary_op!(Sqrt, sqrt);
    impl_unary_op!(Tan, tan);
    impl_unary_op!(Tanh, tanh);
}