tenflowers_core/tensor/
creation.rs1use super::core::{Tensor, TensorStorage};
8use crate::{Device, Result, Shape, TensorError};
9use scirs2_core::ndarray::{ArrayD, IxDyn};
10
11impl<T: Clone + Default> Tensor<T> {
13 pub fn zeros(shape: &[usize]) -> Self
15 where
16 T: scirs2_core::num_traits::Zero,
17 {
18 let array = ArrayD::zeros(IxDyn(shape));
19 Self {
20 storage: TensorStorage::Cpu(array),
21 shape: Shape::from_slice(shape),
22 device: Device::Cpu,
23 requires_grad: false,
24 grad: None,
25 }
26 }
27
28 pub fn ones(shape: &[usize]) -> Self
30 where
31 T: scirs2_core::num_traits::One,
32 {
33 let array = ArrayD::ones(IxDyn(shape));
34 Self {
35 storage: TensorStorage::Cpu(array),
36 shape: Shape::from_slice(shape),
37 device: Device::Cpu,
38 requires_grad: false,
39 grad: None,
40 }
41 }
42
43 pub fn from_data(data: Vec<T>, shape: &[usize]) -> Result<Self> {
45 let total_elements: usize = shape.iter().product();
46 if data.len() != total_elements {
47 return Err(TensorError::invalid_shape_simple(format!(
48 "Data length {} does not match shape {:?} (expected {} elements)",
49 data.len(),
50 shape,
51 total_elements
52 )));
53 }
54
55 let array = ArrayD::from_shape_vec(IxDyn(shape), data)
56 .map_err(|e| TensorError::invalid_shape_simple(e.to_string()))?;
57
58 Ok(Self {
59 storage: TensorStorage::Cpu(array),
60 shape: Shape::from_slice(shape),
61 device: Device::Cpu,
62 requires_grad: false,
63 grad: None,
64 })
65 }
66
67 pub fn from_array(array: ArrayD<T>) -> Self {
69 let shape = Shape::from_slice(array.shape());
70 Self {
71 storage: TensorStorage::Cpu(array),
72 shape,
73 device: Device::Cpu,
74 requires_grad: false,
75 grad: None,
76 }
77 }
78
79 pub fn randn(shape: &[usize]) -> Result<Self>
81 where
82 T: Clone + Default + From<f32>,
83 {
84 let total_elements: usize = shape.iter().product();
85 let mut data = Vec::with_capacity(total_elements);
86
87 for i in 0..total_elements {
89 let val = ((i as f32 * 17.0 + 7.0).sin() * 10000.0).fract() - 0.5;
91 data.push(T::from(val));
92 }
93
94 Self::from_data(data, shape)
95 }
96
97 pub fn from_storage(storage: TensorStorage<T>, device: Device) -> Self {
99 let shape = match &storage {
100 TensorStorage::Cpu(array) => Shape::from_slice(array.shape()),
101 #[cfg(feature = "gpu")]
102 TensorStorage::Gpu(_buffer) => {
103 panic!("from_storage not supported for GPU buffers - use from_gpu_buffer instead")
106 }
107 };
108 Self {
109 storage,
110 shape,
111 device,
112 requires_grad: false,
113 grad: None,
114 }
115 }
116
117 #[cfg(feature = "gpu")]
119 pub fn from_gpu_buffer(buffer: crate::gpu::buffer::GpuBuffer<T>, shape: Shape) -> Self {
120 let device = crate::Device::Gpu(0);
122 Self {
123 storage: TensorStorage::Gpu(buffer),
124 shape,
125 device,
126 requires_grad: false,
127 grad: None,
128 }
129 }
130
131 pub fn from_scalar(value: T) -> Self {
133 Self::from_array(ArrayD::from_elem(IxDyn(&[]), value))
134 }
135
136 pub fn from_vec(data: Vec<T>, shape: &[usize]) -> Result<Self> {
138 let total_size: usize = shape.iter().product();
139 if data.len() != total_size {
140 return Err(TensorError::invalid_shape_simple(format!(
141 "Data length {} doesn't match shape {:?} (size {})",
142 data.len(),
143 shape,
144 total_size
145 )));
146 }
147
148 let array = ArrayD::from_shape_vec(IxDyn(shape), data)
149 .map_err(|e| TensorError::invalid_shape_simple(e.to_string()))?;
150
151 Ok(Self::from_array(array))
152 }
153
154 pub fn full(shape: &[usize], value: T) -> Self
156 where
157 T: Clone,
158 {
159 let array = ArrayD::from_elem(IxDyn(shape), value);
160 Self {
161 storage: TensorStorage::Cpu(array),
162 shape: Shape::from_slice(shape),
163 device: Device::Cpu,
164 requires_grad: false,
165 grad: None,
166 }
167 }
168
169 pub fn eye(n: usize) -> Self
171 where
172 T: scirs2_core::num_traits::Zero + scirs2_core::num_traits::One + Clone,
173 {
174 let mut array = ArrayD::zeros(IxDyn(&[n, n]));
175 for i in 0..n {
176 array[[i, i]] = T::one();
177 }
178 Self {
179 storage: TensorStorage::Cpu(array),
180 shape: Shape::from_slice(&[n, n]),
181 device: Device::Cpu,
182 requires_grad: false,
183 grad: None,
184 }
185 }
186
187 pub fn arange(start: T, end: T, step: T) -> Result<Self>
189 where
190 T: scirs2_core::num_traits::Float
191 + scirs2_core::num_traits::ToPrimitive
192 + scirs2_core::num_traits::FromPrimitive,
193 {
194 let start_f = start.to_f64().ok_or_else(|| {
195 crate::TensorError::invalid_argument("Invalid start value".to_string())
196 })?;
197 let end_f = end
198 .to_f64()
199 .ok_or_else(|| crate::TensorError::invalid_argument("Invalid end value".to_string()))?;
200 let step_f = step.to_f64().ok_or_else(|| {
201 crate::TensorError::invalid_argument("Invalid step value".to_string())
202 })?;
203
204 if step_f == 0.0 {
205 return Err(crate::TensorError::invalid_argument(
206 "Step cannot be zero".to_string(),
207 ));
208 }
209
210 let size = ((end_f - start_f) / step_f).ceil() as usize;
211 let mut data = Vec::with_capacity(size);
212
213 let mut current = start_f;
214 while (step_f > 0.0 && current < end_f) || (step_f < 0.0 && current > end_f) {
215 if let Some(val) = T::from_f64(current) {
216 data.push(val);
217 } else {
218 return Err(crate::TensorError::invalid_argument(
219 "Failed to convert value".to_string(),
220 ));
221 }
222 current += step_f;
223 }
224
225 let size = data.len();
226 Self::from_vec(data, &[size])
227 }
228
229 pub fn linspace(start: T, end: T, steps: usize) -> Result<Self>
231 where
232 T: scirs2_core::num_traits::Float
233 + scirs2_core::num_traits::ToPrimitive
234 + scirs2_core::num_traits::FromPrimitive,
235 {
236 if steps == 0 {
237 return Err(crate::TensorError::invalid_argument(
238 "Steps must be greater than 0".to_string(),
239 ));
240 }
241
242 let start_f = start.to_f64().ok_or_else(|| {
243 crate::TensorError::invalid_argument("Invalid start value".to_string())
244 })?;
245 let end_f = end
246 .to_f64()
247 .ok_or_else(|| crate::TensorError::invalid_argument("Invalid end value".to_string()))?;
248
249 if steps == 1 {
250 let val = T::from_f64(start_f).ok_or_else(|| {
251 crate::TensorError::invalid_argument("Failed to convert value".to_string())
252 })?;
253 return Self::from_vec(vec![val], &[1]);
254 }
255
256 let step = (end_f - start_f) / (steps - 1) as f64;
257 let mut data = Vec::with_capacity(steps);
258
259 for i in 0..steps {
260 let val = start_f + step * i as f64;
261 let tensor_val = T::from_f64(val).ok_or_else(|| {
262 crate::TensorError::invalid_argument("Failed to convert value".to_string())
263 })?;
264 data.push(tensor_val);
265 }
266
267 Self::from_vec(data, &[steps])
268 }
269}