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}