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}