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
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
/*
    Appellation: create <impls>
    Contrib: FL03 <jo3mccain@icloud.com>
*/
use crate::prelude::IntoShape;
use crate::tensor::{from_vec_with_kind, TensorBase};
use num::traits::real::Real;
use num::traits::{FromPrimitive, NumAssign, One, Zero};

impl<T> TensorBase<T>
where
    T: Clone,
{
    /// Create a new tensor, whose elements are set to their default value
    /// from the current shape.
    pub fn default_like(&self) -> Self
    where
        T: Default,
    {
        Self::fill(self.shape(), T::default())
    }
    /// Create an empty tensor from the given shape
    pub fn empty(shape: impl IntoShape) -> Self
    where
        T: Default,
    {
        Self::fill(shape, T::default())
    }
    /// Create a tensor, from the given shape, filled with the given value
    pub fn fill(shape: impl IntoShape, value: T) -> Self {
        let shape = shape.into_shape();
        let store = vec![value; shape.size()];
        from_vec_with_kind(false, shape, store)
    }
    /// Create a tensor, filled with some value, from the current shape
    pub fn fill_like(&self, value: T) -> Self {
        Self::fill(self.shape(), value)
    }
}

impl<T> TensorBase<T>
where
    T: Copy + NumAssign + PartialOrd,
{
    /// Create a tensor within a range of values
    pub fn arange(start: T, end: T, step: T) -> Self {
        if T::is_zero(&step) {
            panic!("step must be non-zero");
        }
        let mut store = Vec::new();
        let mut value = start;
        while value < end {
            store.push(value);
            value += step;
        }
        Self::from_vec(store)
    }
    /// Create an identity matrix of a certain size
    pub fn eye(size: usize) -> Self {
        let mut store = Vec::with_capacity(size * size);
        for i in 0..size {
            for j in 0..size {
                store.push(if i == j { T::one() } else { T::zero() });
            }
        }
        Self::from_shape_vec((size, size), store)
    }
    /// Create a tensor with a certain number of elements, evenly spaced
    /// between the provided start and end values
    pub fn linspace(start: T, end: T, steps: usize) -> Self
    where
        T: FromPrimitive,
    {
        let step = (end - start) / T::from_usize(steps).unwrap();
        Self::arange(start, end, step)
    }

    pub fn logspace(start: T, end: T, steps: usize) -> Self
    where
        T: Real,
    {
        let start = start.log2();
        let end = end.log2();
        let step = (end - start) / T::from(steps).unwrap();
        let mut store = Vec::with_capacity(steps);
        let mut value: T = start;
        for _ in 0..steps {
            store.push(value.exp2());
            value += step;
        }
        from_vec_with_kind(false, (store.len(),), store)
    }

    pub fn geomspace(start: T, end: T, steps: usize) -> Self
    where
        T: Real,
    {
        let start = start.log10();
        let end = end.log10();
        let step = (end - start) / T::from(steps).unwrap();
        let mut store = Vec::with_capacity(steps);
        let mut value: T = start;
        for _ in 0..steps {
            store.push(value.exp());
            value += step;
        }
        from_vec_with_kind(false, (store.len(),), store)
    }
}

impl<T> TensorBase<T>
where
    T: Clone + One,
{
    /// Create a tensor, filled with ones, from the given shape
    pub fn ones(shape: impl IntoShape) -> Self {
        Self::fill(shape, T::one())
    }
    /// Create a tensor, filled with ones, from the shape of another tensor
    pub fn ones_from(tensor: &TensorBase<T>) -> Self {
        Self::ones(tensor.shape())
    }
    /// Create a tensor, filled with ones, from the shape of the tensor
    pub fn ones_like(&self) -> Self {
        Self::ones(self.shape())
    }
}

impl<T> TensorBase<T>
where
    T: Clone + Zero,
{
    /// Create a tensor, filled with zeros, from the given shape
    pub fn zeros(shape: impl IntoShape) -> Self {
        Self::fill(shape, T::zero())
    }
    /// Create a tensor, filled with zeros, from the shape of another tensor
    pub fn zeros_from(tensor: &TensorBase<T>) -> Self {
        Self::zeros(tensor.shape())
    }
    /// Create a tensor, filled with zeros, from the shape of the tensor
    pub fn zeros_like(&self) -> Self {
        Self::zeros(self.shape())
    }
}