ndarray/
impl_constructors.rs

1// Copyright 2014-2016 bluss and ndarray developers.
2//
3// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
4// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
5// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
6// option. This file may not be copied, modified, or distributed
7// except according to those terms.
8
9//! Constructor methods for ndarray
10//!
11//!
12
13#![allow(clippy::match_wild_err_arm)]
14#[cfg(feature = "std")]
15use num_traits::Float;
16use num_traits::{One, Zero};
17use std::mem;
18use std::mem::MaybeUninit;
19use alloc::vec;
20use alloc::vec::Vec;
21
22use crate::dimension;
23use crate::dimension::offset_from_low_addr_ptr_to_logical_ptr;
24use crate::error::{self, ShapeError};
25use crate::extension::nonnull::nonnull_from_vec_data;
26use crate::imp_prelude::*;
27use crate::indexes;
28use crate::indices;
29#[cfg(feature = "std")]
30use crate::iterators::to_vec;
31use crate::iterators::to_vec_mapped;
32use crate::iterators::TrustedIterator;
33use crate::StrideShape;
34#[cfg(feature = "std")]
35use crate::{geomspace, linspace, logspace};
36use rawpointer::PointerExt;
37
38
39/// # Constructor Methods for Owned Arrays
40///
41/// Note that the constructor methods apply to `Array` and `ArcArray`,
42/// the two array types that have owned storage.
43///
44/// ## Constructor methods for one-dimensional arrays.
45impl<S, A> ArrayBase<S, Ix1>
46where
47    S: DataOwned<Elem = A>,
48{
49    /// Create a one-dimensional array from a vector (no copying needed).
50    ///
51    /// **Panics** if the length is greater than `isize::MAX`.
52    ///
53    /// ```rust
54    /// use ndarray::Array;
55    ///
56    /// let array = Array::from_vec(vec![1., 2., 3., 4.]);
57    /// ```
58    pub fn from_vec(v: Vec<A>) -> Self {
59        if mem::size_of::<A>() == 0 {
60            assert!(
61                v.len() <= isize::MAX as usize,
62                "Length must fit in `isize`.",
63            );
64        }
65        unsafe { Self::from_shape_vec_unchecked(v.len() as Ix, v) }
66    }
67
68    /// Create a one-dimensional array from an iterator or iterable.
69    ///
70    /// **Panics** if the length is greater than `isize::MAX`.
71    ///
72    /// ```rust
73    /// use ndarray::Array;
74    ///
75    /// let array = Array::from_iter(0..10);
76    /// ```
77    #[allow(clippy::should_implement_trait)]
78    pub fn from_iter<I: IntoIterator<Item = A>>(iterable: I) -> Self {
79        Self::from_vec(iterable.into_iter().collect())
80    }
81
82    /// Create a one-dimensional array with `n` evenly spaced elements from
83    /// `start` to `end` (inclusive). `A` must be a floating point type.
84    ///
85    /// Note that if `start > end`, the first element will still be `start`,
86    /// and the following elements will be decreasing. This is different from
87    /// the behavior of `std::ops::RangeInclusive`, which interprets `start >
88    /// end` to mean that the range is empty.
89    ///
90    /// **Panics** if `n` is greater than `isize::MAX` or if converting `n - 1`
91    /// to type `A` fails.
92    ///
93    /// ```rust
94    /// use ndarray::{Array, arr1};
95    ///
96    /// let array = Array::linspace(0., 1., 5);
97    /// assert!(array == arr1(&[0.0, 0.25, 0.5, 0.75, 1.0]))
98    /// ```
99    #[cfg(feature = "std")]
100    pub fn linspace(start: A, end: A, n: usize) -> Self
101    where
102        A: Float,
103    {
104        Self::from(to_vec(linspace::linspace(start, end, n)))
105    }
106
107    /// Create a one-dimensional array with elements from `start` to `end`
108    /// (exclusive), incrementing by `step`. `A` must be a floating point type.
109    ///
110    /// **Panics** if the length is greater than `isize::MAX`.
111    ///
112    /// ```rust
113    /// use ndarray::{Array, arr1};
114    ///
115    /// let array = Array::range(0., 5., 1.);
116    /// assert!(array == arr1(&[0., 1., 2., 3., 4.]))
117    /// ```
118    #[cfg(feature = "std")]
119    pub fn range(start: A, end: A, step: A) -> Self
120    where
121        A: Float,
122    {
123        Self::from(to_vec(linspace::range(start, end, step)))
124    }
125
126    /// Create a one-dimensional array with `n` logarithmically spaced
127    /// elements, with the starting value being `base.powf(start)` and the
128    /// final one being `base.powf(end)`. `A` must be a floating point type.
129    ///
130    /// If `base` is negative, all values will be negative.
131    ///
132    /// **Panics** if `n` is greater than `isize::MAX` or if converting `n - 1`
133    /// to type `A` fails.
134    ///
135    /// ```rust
136    /// # #[cfg(feature = "approx")] {
137    /// use approx::assert_abs_diff_eq;
138    /// use ndarray::{Array, arr1};
139    ///
140    /// let array = Array::logspace(10.0, 0.0, 3.0, 4);
141    /// assert_abs_diff_eq!(array, arr1(&[1e0, 1e1, 1e2, 1e3]));
142    ///
143    /// let array = Array::logspace(-10.0, 3.0, 0.0, 4);
144    /// assert_abs_diff_eq!(array, arr1(&[-1e3, -1e2, -1e1, -1e0]));
145    /// # }
146    /// ```
147    #[cfg(feature = "std")]
148    pub fn logspace(base: A, start: A, end: A, n: usize) -> Self
149    where
150        A: Float,
151    {
152        Self::from(to_vec(logspace::logspace(base, start, end, n)))
153    }
154
155    /// Create a one-dimensional array with `n` geometrically spaced elements
156    /// from `start` to `end` (inclusive). `A` must be a floating point type.
157    ///
158    /// Returns `None` if `start` and `end` have different signs or if either
159    /// one is zero. Conceptually, this means that in order to obtain a `Some`
160    /// result, `end / start` must be positive.
161    ///
162    /// **Panics** if `n` is greater than `isize::MAX` or if converting `n - 1`
163    /// to type `A` fails.
164    ///
165    /// ```rust
166    /// # fn example() -> Option<()> {
167    /// # #[cfg(feature = "approx")] {
168    /// use approx::assert_abs_diff_eq;
169    /// use ndarray::{Array, arr1};
170    ///
171    /// let array = Array::geomspace(1e0, 1e3, 4)?;
172    /// assert_abs_diff_eq!(array, arr1(&[1e0, 1e1, 1e2, 1e3]), epsilon = 1e-12);
173    ///
174    /// let array = Array::geomspace(-1e3, -1e0, 4)?;
175    /// assert_abs_diff_eq!(array, arr1(&[-1e3, -1e2, -1e1, -1e0]), epsilon = 1e-12);
176    /// # }
177    /// # Some(())
178    /// # }
179    /// #
180    /// # example().unwrap();
181    /// ```
182    #[cfg(feature = "std")]
183    pub fn geomspace(start: A, end: A, n: usize) -> Option<Self>
184    where
185        A: Float,
186    {
187        Some(Self::from(to_vec(geomspace::geomspace(start, end, n)?)))
188    }
189}
190
191/// ## Constructor methods for two-dimensional arrays.
192impl<S, A> ArrayBase<S, Ix2>
193where
194    S: DataOwned<Elem = A>,
195{
196    /// Create an identity matrix of size `n` (square 2D array).
197    ///
198    /// **Panics** if `n * n` would overflow `isize`.
199    pub fn eye(n: Ix) -> Self
200    where
201        S: DataMut,
202        A: Clone + Zero + One,
203    {
204        let mut eye = Self::zeros((n, n));
205        for a_ii in eye.diag_mut() {
206            *a_ii = A::one();
207        }
208        eye
209    }
210
211    /// Create a 2D matrix from its diagonal
212    ///
213    /// **Panics** if `diag.len() * diag.len()` would overflow `isize`.
214    ///
215    /// ```rust
216    /// use ndarray::{Array2, arr1, arr2};
217    ///
218    /// let diag = arr1(&[1, 2]);
219    /// let array = Array2::from_diag(&diag);
220    /// assert_eq!(array, arr2(&[[1, 0], [0, 2]]));
221    /// ```
222    pub fn from_diag<S2>(diag: &ArrayBase<S2, Ix1>) -> Self
223    where
224        A: Clone + Zero,
225        S: DataMut,
226        S2: Data<Elem = A>,
227    {
228        let n = diag.len();
229        let mut arr = Self::zeros((n, n));
230        arr.diag_mut().assign(diag);
231        arr
232    }
233
234    /// Create a square 2D matrix of the specified size, with the specified
235    /// element along the diagonal and zeros elsewhere.
236    ///
237    /// **Panics** if `n * n` would overflow `isize`.
238    ///
239    /// ```rust
240    /// use ndarray::{array, Array2};
241    ///
242    /// let array = Array2::from_diag_elem(2, 5.);
243    /// assert_eq!(array, array![[5., 0.], [0., 5.]]);
244    /// ```
245    pub fn from_diag_elem(n: usize, elem: A) -> Self
246    where
247        S: DataMut,
248        A: Clone + Zero,
249    {
250        let mut eye = Self::zeros((n, n));
251        for a_ii in eye.diag_mut() {
252            *a_ii = elem.clone();
253        }
254        eye
255    }
256}
257
258#[cfg(not(debug_assertions))]
259#[allow(clippy::match_wild_err_arm)]
260macro_rules! size_of_shape_checked_unwrap {
261    ($dim:expr) => {
262        match dimension::size_of_shape_checked($dim) {
263            Ok(sz) => sz,
264            Err(_) => {
265                panic!("ndarray: Shape too large, product of non-zero axis lengths overflows isize")
266            }
267        }
268    };
269}
270
271#[cfg(debug_assertions)]
272macro_rules! size_of_shape_checked_unwrap {
273    ($dim:expr) => {
274        match dimension::size_of_shape_checked($dim) {
275            Ok(sz) => sz,
276            Err(_) => panic!(
277                "ndarray: Shape too large, product of non-zero axis lengths \
278                 overflows isize in shape {:?}",
279                $dim
280            ),
281        }
282    };
283}
284
285/// ## Constructor methods for n-dimensional arrays.
286///
287/// The `shape` argument can be an integer or a tuple of integers to specify
288/// a static size. For example `10` makes a length 10 one-dimensional array
289/// (dimension type `Ix1`) and `(5, 6)` a 5 × 6 array (dimension type `Ix2`).
290///
291/// With the trait `ShapeBuilder` in scope, there is the method `.f()` to select
292/// column major (“f” order) memory layout instead of the default row major.
293/// For example `Array::zeros((5, 6).f())` makes a column major 5 × 6 array.
294///
295/// Use [`type@IxDyn`] for the shape to create an array with dynamic
296/// number of axes.
297///
298/// Finally, the few constructors that take a completely general
299/// `Into<StrideShape>` argument *optionally* support custom strides, for
300/// example a shape given like `(10, 2, 2).strides((1, 10, 20))` is valid.
301impl<S, A, D> ArrayBase<S, D>
302where
303    S: DataOwned<Elem = A>,
304    D: Dimension,
305{
306    /// Create an array with copies of `elem`, shape `shape`.
307    ///
308    /// **Panics** if the product of non-zero axis lengths overflows `isize`.
309    ///
310    /// ```
311    /// use ndarray::{Array, arr3, ShapeBuilder};
312    ///
313    /// let a = Array::from_elem((2, 2, 2), 1.);
314    ///
315    /// assert!(
316    ///     a == arr3(&[[[1., 1.],
317    ///                  [1., 1.]],
318    ///                 [[1., 1.],
319    ///                  [1., 1.]]])
320    /// );
321    /// assert!(a.strides() == &[4, 2, 1]);
322    ///
323    /// let b = Array::from_elem((2, 2, 2).f(), 1.);
324    /// assert!(b.strides() == &[1, 2, 4]);
325    /// ```
326    pub fn from_elem<Sh>(shape: Sh, elem: A) -> Self
327    where
328        A: Clone,
329        Sh: ShapeBuilder<Dim = D>,
330    {
331        let shape = shape.into_shape();
332        let size = size_of_shape_checked_unwrap!(&shape.dim);
333        let v = vec![elem; size];
334        unsafe { Self::from_shape_vec_unchecked(shape, v) }
335    }
336
337    /// Create an array with zeros, shape `shape`.
338    ///
339    /// **Panics** if the product of non-zero axis lengths overflows `isize`.
340    pub fn zeros<Sh>(shape: Sh) -> Self
341    where
342        A: Clone + Zero,
343        Sh: ShapeBuilder<Dim = D>,
344    {
345        Self::from_elem(shape, A::zero())
346    }
347
348    /// Create an array with ones, shape `shape`.
349    ///
350    /// **Panics** if the product of non-zero axis lengths overflows `isize`.
351    pub fn ones<Sh>(shape: Sh) -> Self
352    where
353        A: Clone + One,
354        Sh: ShapeBuilder<Dim = D>,
355    {
356        Self::from_elem(shape, A::one())
357    }
358
359    /// Create an array with default values, shape `shape`
360    ///
361    /// **Panics** if the product of non-zero axis lengths overflows `isize`.
362    pub fn default<Sh>(shape: Sh) -> Self
363    where
364        A: Default,
365        Sh: ShapeBuilder<Dim = D>,
366    {
367        Self::from_shape_simple_fn(shape, A::default)
368    }
369
370    /// Create an array with values created by the function `f`.
371    ///
372    /// `f` is called with no argument, and it should return the element to
373    /// create. If the precise index of the element to create is needed,
374    /// use [`from_shape_fn`](ArrayBase::from_shape_fn) instead.
375    ///
376    /// This constructor can be useful if the element order is not important,
377    /// for example if they are identical or random.
378    ///
379    /// **Panics** if the product of non-zero axis lengths overflows `isize`.
380    pub fn from_shape_simple_fn<Sh, F>(shape: Sh, mut f: F) -> Self
381    where
382        Sh: ShapeBuilder<Dim = D>,
383        F: FnMut() -> A,
384    {
385        let shape = shape.into_shape();
386        let len = size_of_shape_checked_unwrap!(&shape.dim);
387        let v = to_vec_mapped(0..len, move |_| f());
388        unsafe { Self::from_shape_vec_unchecked(shape, v) }
389    }
390
391    /// Create an array with values created by the function `f`.
392    ///
393    /// `f` is called with the index of the element to create; the elements are
394    /// visited in arbitrary order.
395    ///
396    /// **Panics** if the product of non-zero axis lengths overflows `isize`.
397    ///
398    /// ```
399    /// use ndarray::{Array, arr2};
400    ///
401    /// // Create a table of i × j (with i and j from 1 to 3)
402    /// let ij_table = Array::from_shape_fn((3, 3), |(i, j)| (1 + i) * (1 + j));
403    ///
404    /// assert_eq!(
405    ///     ij_table,
406    ///     arr2(&[[1, 2, 3],
407    ///            [2, 4, 6],
408    ///            [3, 6, 9]])
409    /// );
410    /// ```
411    pub fn from_shape_fn<Sh, F>(shape: Sh, f: F) -> Self
412    where
413        Sh: ShapeBuilder<Dim = D>,
414        F: FnMut(D::Pattern) -> A,
415    {
416        let shape = shape.into_shape();
417        let _ = size_of_shape_checked_unwrap!(&shape.dim);
418        if shape.is_c() {
419            let v = to_vec_mapped(indices(shape.dim.clone()).into_iter(), f);
420            unsafe { Self::from_shape_vec_unchecked(shape, v) }
421        } else {
422            let dim = shape.dim.clone();
423            let v = to_vec_mapped(indexes::indices_iter_f(dim), f);
424            unsafe { Self::from_shape_vec_unchecked(shape, v) }
425        }
426    }
427
428    /// Create an array with the given shape from a vector. (No cloning of
429    /// elements needed.)
430    ///
431    /// ----
432    ///
433    /// For a contiguous c- or f-order shape, the following applies:
434    ///
435    /// **Errors** if `shape` does not correspond to the number of elements in
436    /// `v` or if the shape/strides would result in overflowing `isize`.
437    ///
438    /// ----
439    ///
440    /// For custom strides, the following applies:
441    ///
442    /// **Errors** if strides and dimensions can point out of bounds of `v`, if
443    /// strides allow multiple indices to point to the same element, or if the
444    /// shape/strides would result in overflowing `isize`.
445    ///
446    /// ```
447    /// use ndarray::Array;
448    /// use ndarray::ShapeBuilder; // Needed for .strides() method
449    /// use ndarray::arr2;
450    ///
451    /// let a = Array::from_shape_vec((2, 2), vec![1., 2., 3., 4.]);
452    /// assert!(a.is_ok());
453    ///
454    /// let b = Array::from_shape_vec((2, 2).strides((1, 2)),
455    ///                               vec![1., 2., 3., 4.]).unwrap();
456    /// assert!(
457    ///     b == arr2(&[[1., 3.],
458    ///                 [2., 4.]])
459    /// );
460    /// ```
461    pub fn from_shape_vec<Sh>(shape: Sh, v: Vec<A>) -> Result<Self, ShapeError>
462    where
463        Sh: Into<StrideShape<D>>,
464    {
465        // eliminate the type parameter Sh as soon as possible
466        Self::from_shape_vec_impl(shape.into(), v)
467    }
468
469    fn from_shape_vec_impl(shape: StrideShape<D>, v: Vec<A>) -> Result<Self, ShapeError> {
470        let dim = shape.dim;
471        let is_custom = shape.strides.is_custom();
472        dimension::can_index_slice_with_strides(&v, &dim, &shape.strides)?;
473        if !is_custom && dim.size() != v.len() {
474            return Err(error::incompatible_shapes(&Ix1(v.len()), &dim));
475        }
476        let strides = shape.strides.strides_for_dim(&dim);
477        unsafe { Ok(Self::from_vec_dim_stride_unchecked(dim, strides, v)) }
478    }
479
480    /// Creates an array from a vector and interpret it according to the
481    /// provided shape and strides. (No cloning of elements needed.)
482    ///
483    /// # Safety
484    ///
485    /// The caller must ensure that the following conditions are met:
486    ///
487    /// 1. The ndim of `dim` and `strides` must be the same.
488    ///
489    /// 2. The product of non-zero axis lengths must not exceed `isize::MAX`.
490    ///
491    /// 3. For axes with length > 1, the pointer cannot move outside the
492    ///    slice.
493    ///
494    /// 4. If the array will be empty (any axes are zero-length), the
495    ///    difference between the least address and greatest address accessible
496    ///    by moving along all axes must be ≤ `v.len()`.
497    ///
498    ///    If the array will not be empty, the difference between the least
499    ///    address and greatest address accessible by moving along all axes
500    ///    must be < `v.len()`.
501    ///
502    /// 5. The strides must not allow any element to be referenced by two different
503    ///    indices.
504    pub unsafe fn from_shape_vec_unchecked<Sh>(shape: Sh, v: Vec<A>) -> Self
505    where
506        Sh: Into<StrideShape<D>>,
507    {
508        let shape = shape.into();
509        let dim = shape.dim;
510        let strides = shape.strides.strides_for_dim(&dim);
511        Self::from_vec_dim_stride_unchecked(dim, strides, v)
512    }
513
514    unsafe fn from_vec_dim_stride_unchecked(dim: D, strides: D, mut v: Vec<A>) -> Self {
515        // debug check for issues that indicates wrong use of this constructor
516        debug_assert!(dimension::can_index_slice(&v, &dim, &strides).is_ok());
517
518        let ptr = nonnull_from_vec_data(&mut v).add(offset_from_low_addr_ptr_to_logical_ptr(&dim, &strides));
519        ArrayBase::from_data_ptr(DataOwned::new(v), ptr).with_strides_dim(strides, dim)
520    }
521
522    /// Creates an array from an iterator, mapped by `map` and interpret it according to the
523    /// provided shape and strides.
524    ///
525    /// # Safety
526    ///
527    /// See from_shape_vec_unchecked
528    pub(crate) unsafe fn from_shape_trusted_iter_unchecked<Sh, I, F>(shape: Sh, iter: I, map: F)
529        -> Self
530    where
531        Sh: Into<StrideShape<D>>,
532        I: TrustedIterator + ExactSizeIterator,
533        F: FnMut(I::Item) -> A,
534    {
535        let shape = shape.into();
536        let dim = shape.dim;
537        let strides = shape.strides.strides_for_dim(&dim);
538        let v = to_vec_mapped(iter, map);
539        Self::from_vec_dim_stride_unchecked(dim, strides, v)
540    }
541
542
543    /// Create an array with uninitialized elements, shape `shape`.
544    ///
545    /// The uninitialized elements of type `A` are represented by the type `MaybeUninit<A>`,
546    /// an easier way to handle uninit values correctly.
547    ///
548    /// Only *when* the array is completely initialized with valid elements, can it be
549    /// converted to an array of `A` elements using [`.assume_init()`].
550    ///
551    /// **Panics** if the number of elements in `shape` would overflow isize.
552    ///
553    /// ### Safety
554    ///
555    /// The whole of the array must be initialized before it is converted
556    /// using [`.assume_init()`] or otherwise traversed/read with the element type `A`.
557    ///
558    /// ### Examples
559    ///
560    /// It is possible to assign individual values through `*elt = MaybeUninit::new(value)`
561    /// and so on.
562    ///
563    /// [`.assume_init()`]: ArrayBase::assume_init
564    ///
565    /// ```
566    /// use ndarray::{s, Array2};
567    ///
568    /// // Example Task: Let's create a column shifted copy of the input
569    ///
570    /// fn shift_by_two(a: &Array2<f32>) -> Array2<f32> {
571    ///     // create an uninitialized array
572    ///     let mut b = Array2::uninit(a.dim());
573    ///
574    ///     // two first columns in b are two last in a
575    ///     // rest of columns in b are the initial columns in a
576    ///
577    ///     a.slice(s![.., -2..]).assign_to(b.slice_mut(s![.., ..2]));
578    ///     a.slice(s![.., 2..]).assign_to(b.slice_mut(s![.., ..-2]));
579    ///
580    ///     // Now we can promise that `b` is safe to use with all operations
581    ///     unsafe {
582    ///         b.assume_init()
583    ///     }
584    /// }
585    /// 
586    /// # let _ = shift_by_two;
587    /// ```
588    pub fn uninit<Sh>(shape: Sh) -> ArrayBase<S::MaybeUninit, D>
589    where
590        Sh: ShapeBuilder<Dim = D>,
591    {
592        unsafe {
593            let shape = shape.into_shape();
594            let size = size_of_shape_checked_unwrap!(&shape.dim);
595            let mut v = Vec::with_capacity(size);
596            v.set_len(size);
597            ArrayBase::from_shape_vec_unchecked(shape, v)
598        }
599    }
600
601    /// Create an array with uninitialized elements, shape `shape`.
602    ///
603    /// The uninitialized elements of type `A` are represented by the type `MaybeUninit<A>`,
604    /// an easier way to handle uninit values correctly.
605    ///
606    /// The `builder` closure gets unshared access to the array through a view and can use it to
607    /// modify the array before it is returned. This allows initializing the array for any owned
608    /// array type (avoiding clone requirements for copy-on-write, because the array is unshared
609    /// when initially created).
610    ///
611    /// Only *when* the array is completely initialized with valid elements, can it be
612    /// converted to an array of `A` elements using [`.assume_init()`].
613    ///
614    /// **Panics** if the number of elements in `shape` would overflow isize.
615    ///
616    /// ### Safety
617    ///
618    /// The whole of the array must be initialized before it is converted
619    /// using [`.assume_init()`] or otherwise traversed/read with the element type `A`.
620    ///
621    /// [`.assume_init()`]: ArrayBase::assume_init
622    pub fn build_uninit<Sh, F>(shape: Sh, builder: F) -> ArrayBase<S::MaybeUninit, D>
623    where
624        Sh: ShapeBuilder<Dim = D>,
625        F: FnOnce(ArrayViewMut<MaybeUninit<A>, D>),
626    {
627        let mut array = Self::uninit(shape);
628        // Safe because: the array is unshared here
629        unsafe {
630            builder(array.raw_view_mut_unchecked().deref_into_view_mut());
631        }
632        array
633    }
634
635    #[deprecated(note = "This method is hard to use correctly. Use `uninit` instead.",
636                 since = "0.15.0")]
637    #[allow(clippy::uninit_vec)]  // this is explicitly intended to create uninitialized memory
638    /// Create an array with uninitialized elements, shape `shape`.
639    ///
640    /// Prefer to use [`uninit()`](ArrayBase::uninit) if possible, because it is
641    /// easier to use correctly.
642    ///
643    /// **Panics** if the number of elements in `shape` would overflow isize.
644    ///
645    /// ### Safety
646    ///
647    /// Accessing uninitialized values is undefined behaviour. You must overwrite *all* the elements
648    /// in the array after it is created; for example using
649    /// [`raw_view_mut`](ArrayBase::raw_view_mut) or other low-level element access.
650    ///
651    /// The contents of the array is indeterminate before initialization and it
652    /// is an error to perform operations that use the previous values. For
653    /// example it would not be legal to use `a += 1.;` on such an array.
654    ///
655    /// This constructor is limited to elements where `A: Copy` (no destructors)
656    /// to avoid users shooting themselves too hard in the foot.
657    ///
658    /// (Also note that the constructors `from_shape_vec` and
659    /// `from_shape_vec_unchecked` allow the user yet more control, in the sense
660    /// that Arrays can be created from arbitrary vectors.)
661    pub unsafe fn uninitialized<Sh>(shape: Sh) -> Self
662    where
663        A: Copy,
664        Sh: ShapeBuilder<Dim = D>,
665    {
666        let shape = shape.into_shape();
667        let size = size_of_shape_checked_unwrap!(&shape.dim);
668        let mut v = Vec::with_capacity(size);
669        v.set_len(size);
670        Self::from_shape_vec_unchecked(shape, v)
671    }
672
673}
674
675impl<S, A, D> ArrayBase<S, D>
676where
677    S: DataOwned<Elem = MaybeUninit<A>>,
678    D: Dimension,
679{
680    /// Create an array with uninitialized elements, shape `shape`.
681    ///
682    /// This method has been renamed to `uninit`
683    #[deprecated(note = "Renamed to `uninit`", since = "0.15.0")]
684    pub fn maybe_uninit<Sh>(shape: Sh) -> Self
685    where
686        Sh: ShapeBuilder<Dim = D>,
687    {
688        unsafe {
689            let shape = shape.into_shape();
690            let size = size_of_shape_checked_unwrap!(&shape.dim);
691            let mut v = Vec::with_capacity(size);
692            v.set_len(size);
693            Self::from_shape_vec_unchecked(shape, v)
694        }
695    }
696}