arr_rs/numeric/operations/create.rs
1use crate::{
2 core::prelude::*,
3 errors::prelude::*,
4 numeric::prelude::*,
5 validators::prelude::*,
6};
7
8/// `ArrayTrait` - Array Create functions
9pub trait ArrayCreateNumeric<N: Numeric> where Self: Sized + Clone {
10
11 /// Creates new array with random elements from (0 ..= 1) range
12 ///
13 /// # Arguments
14 ///
15 /// * `shape` - vector representing array elements
16 ///
17 /// # Examples
18 ///
19 /// ```
20 /// use arr_rs::prelude::*;
21 ///
22 /// assert_eq!(4, Array::<f64>::rand(vec![4]).len().unwrap());
23 /// assert_eq!(64, Array::<f64>::rand(vec![4, 4, 4]).len().unwrap());
24 /// ```
25 ///
26 /// # Errors
27 ///
28 /// may returns `ArrayError`
29 fn rand(shape: Vec<usize>) -> Result<Self, ArrayError>;
30
31 /// Creates new 2d array with ones on the diagonal and zeros elsewhere
32 ///
33 /// # Arguments
34 ///
35 /// * `n` - number of rows
36 /// * `m` - number of columns. optional, defaulted to n
37 /// * `k` - index of diagonal. optional, defaulted to 0
38 ///
39 /// # Examples
40 ///
41 /// ```
42 /// use arr_rs::prelude::*;
43 ///
44 /// assert_eq!(array!(i32, [[1, 0, 0], [0, 1, 0]]), Array::<i32>::eye(2, Some(3), Some(0)));
45 /// assert_eq!(array!(i32, [[0, 1, 0], [0, 0, 1]]), Array::<i32>::eye(2, Some(3), Some(1)));
46 /// ```
47 ///
48 /// # Errors
49 ///
50 /// may returns `ArrayError`
51 fn eye(n: usize, m: Option<usize>, k: Option<usize>) -> Result<Self, ArrayError>;
52
53 /// Creates new identity 2d array
54 ///
55 /// # Arguments
56 ///
57 /// * `n` - numbers of rows and columns of resulting array
58 ///
59 /// # Examples
60 ///
61 /// ```
62 /// use arr_rs::prelude::*;
63 ///
64 /// assert_eq!(array!(i32, [[1, 0], [0, 1]]), Array::<i32>::identity(2));
65 /// assert_eq!(array!(i32, [[1, 0, 0], [0, 1, 0], [0, 0, 1]]), Array::<i32>::identity(3));
66 /// ```
67 ///
68 /// # Errors
69 ///
70 /// may returns `ArrayError`
71 fn identity(dim: usize) -> Result<Self, ArrayError>;
72
73 /// Creates new array of zeros
74 ///
75 /// # Arguments
76 ///
77 /// * `shape` - vector representing array elements
78 ///
79 /// # Examples
80 ///
81 /// ```
82 /// use arr_rs::prelude::*;
83 ///
84 /// assert_eq!(array!(f64, [0, 0, 0, 0]), Array::<f64>::zeros(vec![4]));
85 /// ```
86 ///
87 /// # Errors
88 ///
89 /// may returns `ArrayError`
90 fn zeros(shape: Vec<usize>) -> Result<Self, ArrayError>;
91
92 /// Creates new array of zeros like other array
93 ///
94 /// # Arguments
95 ///
96 /// * `other` - array defining the shape of new one
97 ///
98 /// # Examples
99 ///
100 /// ```
101 /// use arr_rs::prelude::*;
102 ///
103 /// assert_eq!(array!(f64, [0, 0, 0, 0]), Array::<f64>::zeros_like(&array!(f64, [1, 2, 3, 4]).unwrap()));
104 /// ```
105 ///
106 /// # Errors
107 ///
108 /// may returns `ArrayError`
109 fn zeros_like(other: &Self) -> Result<Self, ArrayError>;
110
111 /// Creates new array of ones
112 ///
113 /// # Arguments
114 ///
115 /// * `shape` - vector representing array shape
116 ///
117 /// # Examples
118 ///
119 /// ```
120 /// use arr_rs::prelude::*;
121 ///
122 /// assert_eq!(array!(f64, [1, 1, 1, 1]), Array::<f64>::ones(vec![4]));
123 /// ```
124 ///
125 /// # Errors
126 ///
127 /// may returns `ArrayError`
128 fn ones(shape: Vec<usize>) -> Result<Self, ArrayError>;
129
130 /// Creates new array of ones like other array
131 ///
132 /// # Arguments
133 ///
134 /// * `other` - array defining the shape of new one
135 ///
136 /// # Examples
137 ///
138 /// ```
139 /// use arr_rs::prelude::*;
140 ///
141 /// assert_eq!(array!(f64, [1, 1, 1, 1]), Array::<f64>::ones_like(&array!(f64, [1, 2, 3, 4]).unwrap()));
142 /// ```
143 ///
144 /// # Errors
145 ///
146 /// may returns `ArrayError`
147 fn ones_like(other: &Self) -> Result<Self, ArrayError>;
148
149 /// Creates new array of `fill_value`
150 ///
151 /// # Arguments
152 ///
153 /// * `shape` - vector representing array shape
154 /// * `fill_value` - value to fill the array with
155 ///
156 /// # Examples
157 ///
158 /// ```
159 /// use arr_rs::prelude::*;
160 ///
161 /// assert_eq!(array!(f64, [2, 2, 2, 2]), Array::<f64>::full(vec![4], 2.));
162 /// ```
163 ///
164 /// # Errors
165 ///
166 /// may returns `ArrayError`
167 fn full(shape: Vec<usize>, fill_value: N) -> Result<Self, ArrayError>;
168
169 /// Creates new array of `fill_value` like other array
170 ///
171 /// # Arguments
172 ///
173 /// * `other` - array defining the shape of new one
174 /// * `fill_value` - value to fill the array with
175 ///
176 /// # Examples
177 ///
178 /// ```
179 /// use arr_rs::prelude::*;
180 ///
181 /// assert_eq!(array!(f64, [2, 2, 2, 2]), Array::<f64>::full_like(&array!(f64, [1, 2, 3, 4]).unwrap(), 2.));
182 /// ```
183 ///
184 /// # Errors
185 ///
186 /// may returns `ArrayError`
187 fn full_like(other: &Self, fill_value: N) -> Result<Self, ArrayError>;
188
189 // ==== from range
190
191 /// Creates new array from range
192 ///
193 /// # Arguments
194 ///
195 /// * `start` - start of interval
196 /// * `stop` - end of interval
197 /// * `step` - spacing between values. optional, defaults to 1
198 ///
199 /// # Examples
200 ///
201 /// ```
202 /// use arr_rs::prelude::*;
203 ///
204 /// assert_eq!(array!(f64, [0., 1., 2., 3., 4.]), Array::arange(0., 4., None));
205 /// ```
206 ///
207 /// # Errors
208 ///
209 /// may returns `ArrayError`
210 fn arange(start: N, stop: N, step: Option<N>) -> Result<Self, ArrayError>;
211
212 /// Creates new array of numbers evenly spaced over a specified interval
213 ///
214 /// # Arguments
215 ///
216 /// * `start` - start of interval
217 /// * `stop` - end of interval
218 /// * `num` - number of samples to generate. optional, defaults to 50
219 /// * `endpoint` - determines if `stop` should be included in returned data. optional, defaults to true
220 ///
221 /// # Examples
222 ///
223 /// ```
224 /// use arr_rs::prelude::*;
225 ///
226 /// assert_eq!(array!(f64, [0., 2.5, 5.]), Array::<f64>::linspace(0., 5., Some(3), None));
227 /// ```
228 ///
229 /// # Errors
230 ///
231 /// may returns `ArrayError`
232 fn linspace(start: N, stop: N, num: Option<usize>, endpoint: Option<bool>) -> Result<Self, ArrayError>;
233
234 /// Creates new array of numbers evenly spaced over a specified interval
235 ///
236 /// # Arguments
237 ///
238 /// * `start` - start of interval
239 /// * `stop` - end of interval
240 /// * `num` - number of samples to generate. optional, defaults to 50
241 /// * `endpoint` - determines if `stop` should be included in returned data. optional, defaults to true
242 ///
243 /// # Examples
244 ///
245 /// ```
246 /// use arr_rs::prelude::*;
247 ///
248 /// let arr = Array::linspace_a(&array!(f64, [0., 2.]).unwrap(), &array!(f64, [4., 6.]).unwrap(), Some(3), None).unwrap();
249 /// assert_eq!(array!(f64, [[0., 2.], [2., 4.], [4., 6.]]).unwrap(), arr);
250 /// let arr = Array::linspace_a(&array!(f64, [[0., 2.], [2., 4.]]).unwrap(), &array!(f64, [[4., 6.], [6., 8.]]).unwrap(), Some(3), None).unwrap();
251 /// assert_eq!(array!(f64, [[[0., 2.], [2., 4.]], [[2., 4.], [4., 6.]], [[4., 6.], [6., 8.]]]).unwrap(), arr);
252 /// ```
253 ///
254 /// # Errors
255 ///
256 /// may returns `ArrayError`
257 fn linspace_a(start: &Self, stop: &Self, num: Option<usize>, endpoint: Option<bool>) -> Result<Self, ArrayError>;
258
259 /// Creates new array of numbers evenly spaced on a log scale over a specified interval
260 ///
261 /// # Arguments
262 ///
263 /// * `start` - start of interval
264 /// * `stop` - end of interval
265 /// * `num` - number of samples to generate. optional, defaults to 50
266 /// * `endpoint` - determines if `stop` should be included in returned data. optional, defaults to true
267 /// * `base` - the base of the log space. optional, defaults to 10
268 ///
269 /// # Examples
270 ///
271 /// ```
272 /// use arr_rs::prelude::*;
273 ///
274 /// assert_eq!(array!(f64, [1., 316.22776601683796, 100000.]), Array::<f64>::logspace(0., 5., Some(3), None, None));
275 /// ```
276 ///
277 /// # Errors
278 ///
279 /// may returns `ArrayError`
280 fn logspace(start: N, stop: N, num: Option<usize>, endpoint: Option<bool>, base: Option<usize>) -> Result<Self, ArrayError>;
281
282 /// Creates new array of numbers evenly spaced on a log scale over a specified interval
283 ///
284 /// # Arguments
285 ///
286 /// * `start` - start of interval
287 /// * `stop` - end of interval
288 /// * `num` - number of samples to generate. optional, defaults to 50
289 /// * `endpoint` - determines if `stop` should be included in returned data. optional, defaults to true
290 /// * `base` - the base of the log space. optional, defaults to 10
291 ///
292 /// # Examples
293 ///
294 /// ```
295 /// use arr_rs::prelude::*;
296 ///
297 /// let arr = Array::logspace_a(&array!(f64, [0., 2.]).unwrap(), &array!(f64, [4., 6.]).unwrap(), Some(3), None, None).unwrap();
298 /// assert_eq!(array!(f64, [[1., 100.], [100., 10000.], [10000., 1000000.]]).unwrap(), arr);
299 /// let arr = Array::logspace_a(&array!(f64, [[0., 2.], [2., 4.]]).unwrap(), &array!(f64, [[4., 6.], [6., 8.]]).unwrap(), Some(3), None, None).unwrap();
300 /// assert_eq!(array!(f64, [[[1., 100.], [100., 10000.]], [[100., 10000.], [10000., 1000000.]], [[10000., 1000000.], [1000000., 100000000.]]]).unwrap(), arr);
301 /// ```
302 ///
303 /// # Errors
304 ///
305 /// may returns `ArrayError`
306 fn logspace_a(start: &Self, stop: &Self, num: Option<usize>, endpoint: Option<bool>, base: Option<&Array<usize>>) -> Result<Self, ArrayError>;
307
308 /// Creates new array of numbers evenly spaced on a log scale (a geometric progression) over a specified interval
309 ///
310 /// # Arguments
311 ///
312 /// * `start` - start of interval
313 /// * `stop` - end of interval
314 /// * `num` - number of samples to generate. optional, defaults to 50
315 /// * `endpoint` - determines if `stop` should be included in returned data. optional, defaults to true
316 ///
317 /// # Examples
318 ///
319 /// ```
320 /// use arr_rs::prelude::*;
321 ///
322 /// let expected = array!(f64, [1., 10., 100., 1000.]).unwrap();
323 /// let arr = Array::geomspace(1., 1000., Some(4), None).unwrap();
324 /// assert_eq!(format!("{expected:.4}"), format!("{arr:.4}"));
325 /// ```
326 ///
327 /// # Errors
328 ///
329 /// may returns `ArrayError`
330 fn geomspace(start: N, stop: N, num: Option<usize>, endpoint: Option<bool>) -> Result<Self, ArrayError>;
331
332 /// Creates new array of numbers evenly spaced on a log scale (a geometric progression) over a specified interval
333 ///
334 /// # Arguments
335 ///
336 /// * `start` - start of interval
337 /// * `stop` - end of interval
338 /// * `num` - number of samples to generate. optional, defaults to 50
339 /// * `endpoint` - determines if `stop` should be included in returned data. optional, defaults to true
340 ///
341 /// # Examples
342 ///
343 /// ```
344 /// use arr_rs::prelude::*;
345 ///
346 /// let expected = array!(f64, [[1., 10.], [10., 100.], [100., 1000.], [1000., 10000.]]).unwrap();
347 /// let arr = Array::geomspace_a(&array!(f64, [1., 10.]).unwrap(), &array!(f64, [1000., 10000.]).unwrap(), Some(4), None).unwrap();
348 /// assert_eq!(format!("{expected:.4}"), format!("{arr:.4}"));
349 /// let expected = array!(f64, [[[1., 10.], [10., 100.]], [[10., 100.], [100., 1000.]], [[100., 1000.], [1000., 10000.]]]).unwrap();
350 /// let arr = Array::geomspace_a(&array!(f64, [[1., 10.], [10., 100.]]).unwrap(), &array!(f64, [[100., 1000.], [1000., 10000.]]).unwrap(), Some(3), None).unwrap();
351 /// assert_eq!(format!("{expected:.4}"), format!("{arr:.4}"));
352 /// ```
353 ///
354 /// # Errors
355 ///
356 /// may returns `ArrayError`
357 fn geomspace_a(start: &Self, stop: &Self, num: Option<usize>, endpoint: Option<bool>) -> Result<Self, ArrayError>;
358
359 // ==== matrices
360
361 /// Construct an array with ones at and below the given diagonal and zeros elsewhere
362 ///
363 /// # Arguments
364 ///
365 /// * `n` - number of rows
366 /// * `m` - number of columns. optional, defaults to `n`
367 /// * `k` - chosen diagonal. optional, defaults to 0
368 ///
369 /// # Examples
370 ///
371 /// ```
372 /// use arr_rs::prelude::*;
373 ///
374 /// let expected = array!(i32, [[1, 0], [1, 1]]).unwrap();
375 /// assert_eq!(expected, Array::<i32>::tri(2, Some(2), None).unwrap());
376 ///
377 /// let expected = array!(i32, [[1, 0, 0], [1, 1, 0], [1, 1, 1]]).unwrap();
378 /// assert_eq!(expected, Array::<i32>::tri(3, Some(3), None).unwrap());
379 /// ```
380 ///
381 /// # Errors
382 ///
383 /// may returns `ArrayError`
384 fn tri(n: usize, m: Option<usize>, k: Option<isize>) -> Result<Self, ArrayError>;
385}
386
387impl <N: Numeric> ArrayCreateNumeric<N> for Array<N> {
388
389 fn rand(shape: Vec<usize>) -> Result<Self, ArrayError> {
390 let size = shape.iter().product();
391 let mut elements: Vec<N> = Vec::with_capacity(size);
392 (0..size).for_each(|_| elements.push(N::rand(N::zero()..=N::one())));
393 Self::new(elements, shape)
394 }
395
396 fn eye(n: usize, m: Option<usize>, k: Option<usize>) -> Result<Self, ArrayError> {
397 let m = m.unwrap_or(n);
398 let k = k.unwrap_or(0);
399
400 let elements = (0..n * m)
401 .map(|i| {
402 let (row, col) = (i / m, i % m);
403 if col >= k && col - k == row { N::one() } else { N::zero() }
404 })
405 .collect();
406
407 Self::new(elements, vec![n, m])
408 }
409
410 fn identity(n: usize) -> Result<Self, ArrayError> {
411 let elements = (0..n * n)
412 .map(|i|
413 if i % (n + 1) == 0 { N::one() }
414 else { N::zero() })
415 .collect();
416 Self::new(elements, vec![n, n])
417 }
418
419 fn zeros(shape: Vec<usize>) -> Result<Self, ArrayError> {
420 Self::new(vec![N::zero(); shape.iter().product()], shape.clone())
421 }
422
423 fn zeros_like(other: &Self) -> Result<Self, ArrayError> {
424 Self::new(vec![N::zero(); other.get_shape()?.iter().product()], other.get_shape()?)
425 }
426
427 fn ones(shape: Vec<usize>) -> Result<Self, ArrayError> {
428 Self::new(vec![N::one(); shape.iter().product()], shape.clone())
429 }
430
431 fn ones_like(other: &Self) -> Result<Self, ArrayError> {
432 Self::new(vec![N::one(); other.get_shape()?.iter().product()], other.get_shape()?)
433 }
434
435 fn full(shape: Vec<usize>, fill_value: N) -> Result<Self, ArrayError> {
436 Self::new(vec![fill_value; shape.iter().product()], shape.clone())
437 }
438
439 fn full_like(other: &Self, fill_value: N) -> Result<Self, ArrayError> {
440 Self::new(vec![fill_value; other.get_shape()?.iter().product()], other.get_shape()?)
441 }
442
443 // ==== from range
444
445 fn arange(start: N, stop: N, step: Option<N>) -> Result<Self, ArrayError> {
446 let step = step.unwrap_or_else(N::one).to_f64();
447 let size = ((stop.to_f64() + 1. - start.to_f64()) / step).to_usize();
448 let mut elements = Vec::with_capacity(size);
449 let mut value = start.to_f64();
450 for _ in 0..size {
451 elements.push(value);
452 value += step;
453 }
454 Self::flat(elements.into_iter().map(N::from).collect())
455 }
456
457 fn linspace(start: N, stop: N, num: Option<usize>, endpoint: Option<bool>) -> Result<Self, ArrayError> {
458 let (num, endpoint) = (num.unwrap_or(50), endpoint.unwrap_or(true));
459 let delta = endpoint.to_usize();
460 let step = (stop.to_f64() - start.to_f64()) / (num - delta).to_f64();
461
462 let result = (0..num)
463 .map(|i| i.to_f64().mul_add(step, start.to_f64())).enumerate()
464 .map(|(i, val)| if endpoint && i == num - 1 { stop.to_f64() } else { val })
465 .map(N::from).collect();
466 Ok(result)
467 }
468
469 fn linspace_a(start: &Self, stop: &Self, num: Option<usize>, endpoint: Option<bool>) -> Result<Self, ArrayError> {
470 let start = if start.len()? == 1 { Self::full_like(stop, start[0])? } else { start.clone() };
471 let stop = if stop.len()? == 1 { Self::full_like(&start, stop[0])? } else { stop.clone() };
472 assert_eq!(start.get_shape(), stop.get_shape());
473 let mut new_shape = vec![num.unwrap_or(50)];
474 new_shape.extend(start.get_shape()?.iter().copied());
475 new_shape.reverse();
476
477 let values = start.into_iter().zip(stop)
478 .map(|(a, b)| Self::linspace(a, b, num, endpoint).get_elements())
479 .collect::<Vec<Result<Vec<N>, ArrayError>>>().has_error()?.iter()
480 .flat_map(|a| a.as_ref().unwrap().clone())
481 .collect();
482 let reshaped = Self::flat(values).reshape(&new_shape);
483 if let Err(error) = reshaped { Err(error) }
484 else { reshaped?.transpose(None) }
485 }
486
487 fn logspace(start: N, stop: N, num: Option<usize>, endpoint: Option<bool>, base: Option<usize>) -> Result<Self, ArrayError> {
488 let (num, endpoint, base) = (num.unwrap_or(50), endpoint.unwrap_or(true), base.unwrap_or(10).to_f64());
489 let delta = endpoint.to_usize();
490 let (log_start, log_stop) = (base.powf(start.to_f64()), base.powf(stop.to_f64()));
491 let log_step = (log_stop / log_start).powf(1. / (num - delta).to_f64());
492
493 let result = (0..num)
494 .map(|i| log_start * log_step.powf(i.to_f64()))
495 .enumerate()
496 .map(|(i, val)| if endpoint && i == num - 1 { log_stop } else { val })
497 .map(N::from)
498 .collect();
499 Ok(result)
500 }
501
502 fn logspace_a(start: &Self, stop: &Self, num: Option<usize>, endpoint: Option<bool>, base: Option<&Array<usize>>) -> Result<Self, ArrayError> {
503 let start = if start.len()? == 1 { Self::full_like(stop, start[0])? } else { start.clone() };
504 let stop = if stop.len()? == 1 { Self::full_like(&start, stop[0])? } else { stop.clone() };
505 start.matches_shape(&stop.get_shape()?)?;
506
507 let mut new_shape = vec![num.unwrap_or(50)];
508 new_shape.extend(start.get_shape()?.iter().copied());
509 new_shape.reverse();
510
511 let base = base.unwrap_or(&Array::flat(vec![10])?).clone();
512 let base = if base.len()? == 1 { Array::<usize>::full_like(&Array::rand(start.get_shape()?)?, base[0])? } else { base };
513 start.matches_shape(&base.get_shape()?)?;
514
515 let values = start.into_iter().zip(stop).zip(base)
516 .map(|((a, b), c)| Self::logspace(a, b, num, endpoint, Some(c)).get_elements())
517 .collect::<Vec<Result<Vec<N>, ArrayError>>>()
518 .has_error()?.iter()
519 .flat_map(|a| a.as_ref().unwrap().clone())
520 .collect();
521 let reshaped = Self::flat(values).reshape(&new_shape);
522 if let Err(error) = reshaped { Err(error) }
523 else { reshaped.unwrap().transpose(None) }
524 }
525
526 fn geomspace(start: N, stop: N, num: Option<usize>, endpoint: Option<bool>) -> Result<Self, ArrayError> {
527 if start == N::zero() {
528 return Err(ArrayError::ParameterError { param: "start", message: "geometric sequence cannot include zero" });
529 } else if stop == N::zero() {
530 return Err(ArrayError::ParameterError { param: "stop", message: "geometric sequence cannot include zero" });
531 }
532
533 let (num, endpoint) = (num.unwrap_or(50), endpoint.unwrap_or(true));
534 let delta = endpoint.to_usize();
535 let ratio = (stop.to_f64() / start.to_f64()).to_f64().powf(1.0 / (num - delta).to_f64());
536
537 let result = (0..num)
538 .map(|i| start.to_f64() * ratio.powf(i.to_f64()))
539 .enumerate()
540 .map(|(i, val)| if endpoint && i == num - 1 { stop.to_f64() } else { val })
541 .map(N::from)
542 .collect();
543 Ok(result)
544 }
545
546 fn geomspace_a(start: &Self, stop: &Self, num: Option<usize>, endpoint: Option<bool>) -> Result<Self, ArrayError> {
547 let start = if start.len()? == 1 { Self::full_like(stop, start[0])? } else { start.clone() };
548 let stop = if stop.len()? == 1 { Self::full_like(&start, stop[0])? } else { stop.clone() };
549 start.matches_shape(&stop.get_shape()?)?;
550
551 let mut new_shape = vec![num.unwrap_or(50)];
552 new_shape.extend(start.get_shape()?.iter().copied());
553 new_shape.reverse();
554
555 let values = start.into_iter().zip(stop)
556 .map(|(a, b)| Self::geomspace(a, b, num, endpoint))
557 .collect::<Vec<Result<Self, _>>>()
558 .has_error()?.iter()
559 .map(Result::<Self, _>::get_elements).collect::<Vec<Result<Vec<N>, ArrayError>>>()
560 .has_error()?.into_iter()
561 .flat_map(Result::unwrap)
562 .collect();
563 Self::flat(values)
564 .reshape(&new_shape)?
565 .transpose(None)
566 }
567
568 // ==== matrices
569
570 fn tri(n: usize, m: Option<usize>, k: Option<isize>) -> Result<Self, ArrayError> {
571 let (m, k) = (m.unwrap_or(n), k.unwrap_or(0));
572
573 let elements = (0..n)
574 .flat_map(|i| (0..m).map(move |j|
575 if j.to_isize() <= i.to_isize() + k { N::one() }
576 else { N::zero() }
577 ))
578 .collect();
579
580 Self::new(elements, vec![n, m])
581 }
582}