``` 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
```
```//! Contains mathematical functions that operate on tensors. These functions are largely modelled
//! after what is available natively in Rust.

use num::traits::Float;
use tensor::Tensor;
use traits::NumericTrait;

(\$(\$f:ident)*) => (\$(
pub fn \$f<T: NumericTrait + Float>(x: Tensor<T>) -> Tensor<T> {
let mut y = x;
y.canonize_inplace();
{
let n = y.size();
let mut data = y.slice_mut();
for i in 0..n {
data[i] = data[i].\$f();
}
}
y
}
)*)
}

add_impl! { ln log10 log2 sin cos tan asin acos atan exp_m1 exp exp2
ln_1p sinh cosh tanh asinh acosh atanh sqrt
floor ceil round trunc fract abs signum }

(\$(\$f:ident)*) => (\$(
pub fn \$f<T: NumericTrait + Float>(x: &Tensor<T>) -> Tensor<bool> {
let mut y: Tensor<bool> = Tensor::empty(&x.shape());
{
let mut data = y.slice_mut();
for (i, v) in x.iter().enumerate() {
data[i] = v.\$f();
}
}
y
}
)*)
}

add_impl_to_bool! { is_nan is_finite is_infinite is_normal is_sign_positive is_sign_negative }

pub fn log<T: NumericTrait + Float>(x: Tensor<T>, base: T) -> Tensor<T> {
let mut y = x;
y.canonize_inplace();
{
let n = y.size();
let mut data = y.slice_mut();
for i in 0..n {
data[i] = data[i].log(base);
}
}
y
}

/// Calculates atan(y/x).
pub fn atan2<T: NumericTrait + Float>(y: &Tensor<T>, x: &Tensor<T>) -> Tensor<T> {
assert!(x.shape() == y.shape(), "Shapes must match");
let mut z = Tensor::empty(&x.shape());
{
let mut data = z.slice_mut();
for (i, (v1, v2)) in y.iter().zip(x.iter()).enumerate() {
data[i] = v1.atan2(v2);
}
}
z
}

pub fn powf<T: NumericTrait + Float>(y: &Tensor<T>, x: &Tensor<T>) -> Tensor<T> {
assert!(x.shape() == y.shape(), "Shapes must match");
let mut z = Tensor::empty(&x.shape());
{
let mut data = z.slice_mut();
for (i, (v1, v2)) in y.iter().zip(x.iter()).enumerate() {
data[i] = v1.powf(v2);
}
}
z
}

pub fn powi<T: NumericTrait + Float>(y: &Tensor<T>, x: &Tensor<i32>) -> Tensor<T> {
assert!(x.shape() == y.shape(), "Shapes must match");
let mut z = Tensor::empty(&x.shape());
{
let mut data = z.slice_mut();
for (i, (v1, v2)) in y.iter().zip(x.iter()).enumerate() {
data[i] = v1.powi(v2);
}
}
z
}
```