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