/rust/registry/src/index.crates.io-1949cf8c6b5b557f/ndarray-0.17.2/src/lib.rs
Line | Count | Source |
1 | | // Copyright 2014-2020 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 | | #![crate_name = "ndarray"] |
9 | | #![doc(html_root_url = "https://docs.rs/ndarray/0.15/")] |
10 | | #![doc(html_logo_url = "https://rust-ndarray.github.io/images/rust-ndarray_logo.svg")] |
11 | | #![allow( |
12 | | unstable_name_collisions, // our `PointerExt` collides with upcoming inherent methods on `NonNull` |
13 | | clippy::deref_addrof, |
14 | | clippy::manual_map, // is not an error |
15 | | clippy::while_let_on_iterator, // is not an error |
16 | | clippy::from_iter_instead_of_collect, // using from_iter is good style |
17 | | clippy::incompatible_msrv, // false positive PointerExt::offset |
18 | | )] |
19 | | #![doc(test(attr(deny(warnings))))] |
20 | | #![doc(test(attr(allow(unused_variables))))] |
21 | | #![doc(test(attr(allow(deprecated))))] |
22 | | #![cfg_attr(not(feature = "std"), no_std)] |
23 | | // Enable the doc_cfg nightly feature for including feature gate flags in the documentation |
24 | | #![cfg_attr(docsrs, feature(doc_cfg))] |
25 | | #![cfg_attr(docsrs, doc(auto_cfg))] |
26 | | #![warn(missing_docs)] |
27 | | |
28 | | //! The `ndarray` crate provides an *n*-dimensional container for general elements |
29 | | //! and for numerics. |
30 | | //! |
31 | | //! In *n*-dimensional we include, for example, 1-dimensional rows or columns, |
32 | | //! 2-dimensional matrices, and higher dimensional arrays. If the array has *n* |
33 | | //! dimensions, then an element in the array is accessed by using that many indices. |
34 | | //! Each dimension is also called an *axis*. |
35 | | //! |
36 | | //! To get started, functionality is provided in the following core types: |
37 | | //! - **[`ArrayBase`]**: |
38 | | //! The *n*-dimensional array type itself.<br> |
39 | | //! It is used to implement both the owned arrays and the views; see its docs |
40 | | //! for an overview of all array features.<br> |
41 | | //! - The main specific array type is **[`Array`]**, which owns |
42 | | //! its elements. |
43 | | //! - A reference type, **[`ArrayRef`]**, that contains most of the functionality |
44 | | //! for reading and writing to arrays. |
45 | | //! - A reference type, **[`LayoutRef`]**, that contains most of the functionality |
46 | | //! for reading and writing to array layouts: their shape and strides. |
47 | | //! |
48 | | //! ## Highlights |
49 | | //! |
50 | | //! - Generic *n*-dimensional array |
51 | | //! - [Slicing](ArrayBase#slicing), also with arbitrary step size, and negative |
52 | | //! indices to mean elements from the end of the axis. |
53 | | //! - Views and subviews of arrays; iterators that yield subviews. |
54 | | //! - Higher order operations and arithmetic are performant |
55 | | //! - Array views can be used to slice and mutate any `[T]` data using |
56 | | //! `ArrayView::from` and `ArrayViewMut::from`. |
57 | | //! - [`Zip`] for lock step function application across two or more arrays or other |
58 | | //! item producers ([`NdProducer`] trait). |
59 | | //! |
60 | | //! ## Crate Status |
61 | | //! |
62 | | //! - Still iterating on and evolving the crate |
63 | | //! + The crate is continuously developing, and breaking changes are expected |
64 | | //! during evolution from version to version. We adopt the newest stable |
65 | | //! rust features if we need them. |
66 | | //! + Note that functions/methods/traits/etc. hidden from the docs are not |
67 | | //! considered part of the public API, so changes to them are not |
68 | | //! considered breaking changes. |
69 | | //! - Performance: |
70 | | //! + Prefer higher order methods and arithmetic operations on arrays first, |
71 | | //! then iteration, and as a last priority using indexed algorithms. |
72 | | //! + The higher order functions like [`.map()`](ArrayRef::map), |
73 | | //! [`.map_inplace()`](ArrayRef::map_inplace), [`.zip_mut_with()`](ArrayRef::zip_mut_with), |
74 | | //! [`Zip`] and [`azip!()`](azip) are the most efficient ways |
75 | | //! to perform single traversal and lock step traversal respectively. |
76 | | //! + Performance of an operation depends on the memory layout of the array |
77 | | //! or array view. Especially if it's a binary operation, which |
78 | | //! needs matching memory layout to be efficient (with some exceptions). |
79 | | //! + Efficient floating point matrix multiplication even for very large |
80 | | //! matrices; can optionally use BLAS to improve it further. |
81 | | //! |
82 | | //! - **MSRV: Requires Rust 1.64 or later** |
83 | | //! |
84 | | //! ## Crate Feature Flags |
85 | | //! |
86 | | //! The following crate feature flags are available. They are configured in your |
87 | | //! `Cargo.toml`. See [`doc::crate_feature_flags`] for more information. |
88 | | //! |
89 | | //! - `std`: Rust standard library-using functionality (enabled by default) |
90 | | //! - `serde`: serialization support for serde 1.x |
91 | | //! - `rayon`: Parallel iterators, parallelized methods, the [`parallel`] module and [`par_azip!`]. |
92 | | //! - `approx` Implementations of traits from the [`approx`] crate. |
93 | | //! - `blas`: transparent BLAS support for matrix multiplication, needs configuration. |
94 | | //! - `matrixmultiply-threading`: Use threading from `matrixmultiply`. |
95 | | //! |
96 | | //! ## Documentation |
97 | | //! |
98 | | //! * The docs for [`ArrayBase`] provide an overview of |
99 | | //! the *n*-dimensional array type. Other good pages to look at are the |
100 | | //! documentation for the [`s![]`](s!) and |
101 | | //! [`azip!()`](azip!) macros. |
102 | | //! |
103 | | //! * If you have experience with NumPy, you may also be interested in |
104 | | //! [`ndarray_for_numpy_users`](doc::ndarray_for_numpy_users). |
105 | | //! |
106 | | //! ## The ndarray ecosystem |
107 | | //! |
108 | | //! `ndarray` provides a lot of functionality, but it's not a one-stop solution. |
109 | | //! |
110 | | //! `ndarray` includes matrix multiplication and other binary/unary operations out of the box. |
111 | | //! More advanced linear algebra routines (e.g. SVD decomposition or eigenvalue computation) |
112 | | //! can be found in [`ndarray-linalg`](https://crates.io/crates/ndarray-linalg). |
113 | | //! |
114 | | //! The same holds for statistics: `ndarray` provides some basic functionalities (e.g. `mean`) |
115 | | //! but more advanced routines can be found in [`ndarray-stats`](https://crates.io/crates/ndarray-stats). |
116 | | //! |
117 | | //! If you are looking to generate random arrays instead, check out [`ndarray-rand`](https://crates.io/crates/ndarray-rand). |
118 | | //! |
119 | | //! For conversion between `ndarray`, [`nalgebra`](https://crates.io/crates/nalgebra) and |
120 | | //! [`image`](https://crates.io/crates/image) check out [`nshare`](https://crates.io/crates/nshare). |
121 | | |
122 | | extern crate alloc; |
123 | | |
124 | | #[cfg(not(feature = "std"))] |
125 | | extern crate core as std; |
126 | | #[cfg(feature = "std")] |
127 | | extern crate std; |
128 | | |
129 | | #[cfg(feature = "blas")] |
130 | | extern crate cblas_sys; |
131 | | |
132 | | #[cfg(docsrs)] |
133 | | pub mod doc; |
134 | | |
135 | | use alloc::fmt::Debug; |
136 | | #[cfg(target_has_atomic = "ptr")] |
137 | | use alloc::sync::Arc; |
138 | | |
139 | | #[cfg(not(target_has_atomic = "ptr"))] |
140 | | use portable_atomic_util::Arc; |
141 | | |
142 | | use core::ptr::NonNull; |
143 | | use std::marker::PhantomData; |
144 | | |
145 | | pub use crate::dimension::dim::*; |
146 | | pub use crate::dimension::{Axis, AxisDescription, Dimension, IntoDimension, RemoveAxis}; |
147 | | pub use crate::dimension::{DimAdd, DimMax}; |
148 | | |
149 | | pub use crate::dimension::IxDynImpl; |
150 | | pub use crate::dimension::NdIndex; |
151 | | pub use crate::error::{ErrorKind, ShapeError}; |
152 | | pub use crate::indexes::{indices, indices_of}; |
153 | | pub use crate::order::Order; |
154 | | pub use crate::slice::{MultiSliceArg, NewAxis, Slice, SliceArg, SliceInfo, SliceInfoElem, SliceNextDim}; |
155 | | |
156 | | use crate::iterators::Baseiter; |
157 | | use crate::iterators::{ElementsBase, ElementsBaseMut}; |
158 | | |
159 | | pub use crate::arraytraits::AsArray; |
160 | | pub use crate::linalg_traits::LinalgScalar; |
161 | | #[cfg(feature = "std")] |
162 | | pub use crate::linalg_traits::NdFloat; |
163 | | |
164 | | pub use crate::stacking::{concatenate, stack}; |
165 | | |
166 | | pub use crate::impl_views::IndexLonger; |
167 | | pub use crate::math_cell::MathCell; |
168 | | pub use crate::shape_builder::{Shape, ShapeArg, ShapeBuilder, StrideShape}; |
169 | | |
170 | | #[macro_use] |
171 | | mod macro_utils; |
172 | | #[macro_use] |
173 | | mod private; |
174 | | mod impl_ref_types; |
175 | | mod aliases; |
176 | | #[macro_use] |
177 | | mod itertools; |
178 | | mod argument_traits; |
179 | | #[cfg(feature = "serde")] |
180 | | mod array_serde; |
181 | | mod arrayformat; |
182 | | mod arraytraits; |
183 | | pub use crate::argument_traits::AssignElem; |
184 | | mod data_repr; |
185 | | mod data_traits; |
186 | | |
187 | | pub use crate::aliases::*; |
188 | | |
189 | | pub use crate::data_traits::{Data, DataMut, DataOwned, DataShared, RawData, RawDataClone, RawDataMut, RawDataSubst}; |
190 | | |
191 | | mod free_functions; |
192 | | pub use crate::free_functions::*; |
193 | | pub use crate::iterators::iter; |
194 | | |
195 | | mod error; |
196 | | mod extension; |
197 | | mod geomspace; |
198 | | mod indexes; |
199 | | mod iterators; |
200 | | mod layout; |
201 | | mod linalg_traits; |
202 | | mod linspace; |
203 | | #[cfg(feature = "std")] |
204 | | pub use crate::linspace::{linspace, range, Linspace}; |
205 | | mod logspace; |
206 | | #[cfg(feature = "std")] |
207 | | pub use crate::logspace::{logspace, Logspace}; |
208 | | mod math_cell; |
209 | | mod numeric_util; |
210 | | mod order; |
211 | | mod partial; |
212 | | mod shape_builder; |
213 | | #[macro_use] |
214 | | mod slice; |
215 | | mod split_at; |
216 | | mod stacking; |
217 | | mod low_level_util; |
218 | | #[macro_use] |
219 | | mod zip; |
220 | | |
221 | | mod dimension; |
222 | | |
223 | | pub use crate::zip::{FoldWhile, IntoNdProducer, NdProducer, Zip}; |
224 | | |
225 | | pub use crate::layout::Layout; |
226 | | |
227 | | /// Implementation's prelude. Common types used everywhere. |
228 | | mod imp_prelude |
229 | | { |
230 | | pub use crate::dimension::DimensionExt; |
231 | | pub use crate::prelude::*; |
232 | | pub use crate::ArcArray; |
233 | | pub use crate::{ |
234 | | CowRepr, |
235 | | Data, |
236 | | DataMut, |
237 | | DataOwned, |
238 | | DataShared, |
239 | | Ix, |
240 | | Ixs, |
241 | | RawData, |
242 | | RawDataMut, |
243 | | RawViewRepr, |
244 | | RemoveAxis, |
245 | | ViewRepr, |
246 | | }; |
247 | | } |
248 | | |
249 | | pub mod prelude; |
250 | | |
251 | | /// Array index type |
252 | | pub type Ix = usize; |
253 | | /// Array index type (signed) |
254 | | pub type Ixs = isize; |
255 | | |
256 | | /// An *n*-dimensional array. |
257 | | /// |
258 | | /// The array is a general container of elements. |
259 | | /// The array supports arithmetic operations by applying them elementwise, if the |
260 | | /// elements are numeric, but it supports non-numeric elements too. |
261 | | /// |
262 | | /// The arrays rarely grow or shrink, since those operations can be costly. On |
263 | | /// the other hand there is a rich set of methods and operations for taking views, |
264 | | /// slices, and making traversals over one or more arrays. |
265 | | /// |
266 | | /// In *n*-dimensional we include for example 1-dimensional rows or columns, |
267 | | /// 2-dimensional matrices, and higher dimensional arrays. If the array has *n* |
268 | | /// dimensions, then an element is accessed by using that many indices. |
269 | | /// |
270 | | /// The `ArrayBase<S, D>` is parameterized by `S` for the data container and |
271 | | /// `D` for the dimensionality. |
272 | | /// |
273 | | /// Type aliases [`Array`], [`ArcArray`], [`CowArray`], [`ArrayView`], and |
274 | | /// [`ArrayViewMut`] refer to `ArrayBase` with different types for the data |
275 | | /// container: arrays with different kinds of ownership or different kinds of array views. |
276 | | /// |
277 | | /// ## Contents |
278 | | /// |
279 | | /// + [Array](#array) |
280 | | /// + [ArcArray](#arcarray) |
281 | | /// + [CowArray](#cowarray) |
282 | | /// + [Array Views](#array-views) |
283 | | /// + [Indexing and Dimension](#indexing-and-dimension) |
284 | | /// + [Loops, Producers and Iterators](#loops-producers-and-iterators) |
285 | | /// + [Slicing](#slicing) |
286 | | /// + [Subviews](#subviews) |
287 | | /// + [Arithmetic Operations](#arithmetic-operations) |
288 | | /// + [Broadcasting](#broadcasting) |
289 | | /// + [Conversions](#conversions) |
290 | | /// + [Constructor Methods for Owned Arrays](#constructor-methods-for-owned-arrays) |
291 | | /// + [Methods For All Array Types](#methods-for-all-array-types) |
292 | | /// + [Methods For 1-D Arrays](#methods-for-1-d-arrays) |
293 | | /// + [Methods For 2-D Arrays](#methods-for-2-d-arrays) |
294 | | /// + [Methods for Dynamic-Dimensional Arrays](#methods-for-dynamic-dimensional-arrays) |
295 | | /// + [Numerical Methods for Arrays](#numerical-methods-for-arrays) |
296 | | /// |
297 | | /// ## `Array` |
298 | | /// |
299 | | /// [`Array`] is an owned array that owns the underlying array |
300 | | /// elements directly (just like a `Vec`) and it is the default way to create and |
301 | | /// store n-dimensional data. `Array<A, D>` has two type parameters: `A` for |
302 | | /// the element type, and `D` for the dimensionality. A particular |
303 | | /// dimensionality's type alias like `Array3<A>` just has the type parameter |
304 | | /// `A` for element type. |
305 | | /// |
306 | | /// An example: |
307 | | /// |
308 | | /// ``` |
309 | | /// // Create a three-dimensional f64 array, initialized with zeros |
310 | | /// use ndarray::Array3; |
311 | | /// let mut temperature = Array3::<f64>::zeros((3, 4, 5)); |
312 | | /// // Increase the temperature in this location |
313 | | /// temperature[[2, 2, 2]] += 0.5; |
314 | | /// ``` |
315 | | /// |
316 | | /// ## `ArcArray` |
317 | | /// |
318 | | /// [`ArcArray`] is an owned array with reference counted |
319 | | /// data (shared ownership). |
320 | | /// Sharing requires that it uses copy-on-write for mutable operations. |
321 | | /// Calling a method for mutating elements on `ArcArray`, for example |
322 | | /// [`view_mut()`](ArrayRef::view_mut) or [`get_mut()`](ArrayRef::get_mut), |
323 | | /// will break sharing and require a clone of the data (if it is not uniquely held). |
324 | | /// |
325 | | /// ## `CowArray` |
326 | | /// |
327 | | /// [`CowArray`] is analogous to [`std::borrow::Cow`]. |
328 | | /// It can represent either an immutable view or a uniquely owned array. If a |
329 | | /// `CowArray` instance is the immutable view variant, then calling a method |
330 | | /// for mutating elements in the array will cause it to be converted into the |
331 | | /// owned variant (by cloning all the elements) before the modification is |
332 | | /// performed. |
333 | | /// |
334 | | /// ## Array Views |
335 | | /// |
336 | | /// [`ArrayView`] and [`ArrayViewMut`] are read-only and read-write array views |
337 | | /// respectively. They use dimensionality, indexing, and almost all other |
338 | | /// methods the same way as the other array types. |
339 | | /// |
340 | | /// Methods for `ArrayBase` apply to array views too, when the trait bounds |
341 | | /// allow. |
342 | | /// |
343 | | /// Please see the documentation for the respective array view for an overview |
344 | | /// of methods specific to array views: [`ArrayView`], [`ArrayViewMut`]. |
345 | | /// |
346 | | /// A view is created from an array using [`.view()`](ArrayRef::view), |
347 | | /// [`.view_mut()`](ArrayRef::view_mut), using |
348 | | /// slicing ([`.slice()`](ArrayRef::slice), [`.slice_mut()`](ArrayRef::slice_mut)) or from one of |
349 | | /// the many iterators that yield array views. |
350 | | /// |
351 | | /// You can also create an array view from a regular slice of data not |
352 | | /// allocated with `Array` — see array view methods or their `From` impls. |
353 | | /// |
354 | | /// Note that all `ArrayBase` variants can change their view (slicing) of the |
355 | | /// data freely, even when their data can’t be mutated. |
356 | | /// |
357 | | /// ## Indexing and Dimension |
358 | | /// |
359 | | /// The dimensionality of the array determines the number of *axes*, for example |
360 | | /// a 2D array has two axes. These are listed in “big endian” order, so that |
361 | | /// the greatest dimension is listed first, the lowest dimension with the most |
362 | | /// rapidly varying index is the last. |
363 | | /// |
364 | | /// In a 2D array the index of each element is `[row, column]` as seen in this |
365 | | /// 4 × 3 example: |
366 | | /// |
367 | | /// ```ignore |
368 | | /// [[ [0, 0], [0, 1], [0, 2] ], // row 0 |
369 | | /// [ [1, 0], [1, 1], [1, 2] ], // row 1 |
370 | | /// [ [2, 0], [2, 1], [2, 2] ], // row 2 |
371 | | /// [ [3, 0], [3, 1], [3, 2] ]] // row 3 |
372 | | /// // \ \ \ |
373 | | /// // column 0 \ column 2 |
374 | | /// // column 1 |
375 | | /// ``` |
376 | | /// |
377 | | /// The number of axes for an array is fixed by its `D` type parameter: `Ix1` |
378 | | /// for a 1D array, `Ix2` for a 2D array etc. The dimension type `IxDyn` allows |
379 | | /// a dynamic number of axes. |
380 | | /// |
381 | | /// A fixed size array (`[usize; N]`) of the corresponding dimensionality is |
382 | | /// used to index the `Array`, making the syntax `array[[` i, j, ...`]]` |
383 | | /// |
384 | | /// ``` |
385 | | /// use ndarray::Array2; |
386 | | /// let mut array = Array2::zeros((4, 3)); |
387 | | /// array[[1, 1]] = 7; |
388 | | /// ``` |
389 | | /// |
390 | | /// Important traits and types for dimension and indexing: |
391 | | /// |
392 | | /// - A [`struct@Dim`] value represents a dimensionality or index. |
393 | | /// - Trait [`Dimension`] is implemented by all |
394 | | /// dimensionalities. It defines many operations for dimensions and indices. |
395 | | /// - Trait [`IntoDimension`] is used to convert into a |
396 | | /// `Dim` value. |
397 | | /// - Trait [`ShapeBuilder`] is an extension of |
398 | | /// `IntoDimension` and is used when constructing an array. A shape describes |
399 | | /// not just the extent of each axis but also their strides. |
400 | | /// - Trait [`NdIndex`] is an extension of `Dimension` and is |
401 | | /// for values that can be used with indexing syntax. |
402 | | /// |
403 | | /// |
404 | | /// The default memory order of an array is *row major* order (a.k.a “c” order), |
405 | | /// where each row is contiguous in memory. |
406 | | /// A *column major* (a.k.a. “f” or fortran) memory order array has |
407 | | /// columns (or, in general, the outermost axis) with contiguous elements. |
408 | | /// |
409 | | /// The logical order of any array’s elements is the row major order |
410 | | /// (the rightmost index is varying the fastest). |
411 | | /// The iterators `.iter(), .iter_mut()` always adhere to this order, for example. |
412 | | /// |
413 | | /// ## Loops, Producers and Iterators |
414 | | /// |
415 | | /// Using [`Zip`] is the most general way to apply a procedure |
416 | | /// across one or several arrays or *producers*. |
417 | | /// |
418 | | /// [`NdProducer`] is like an iterable but for |
419 | | /// multidimensional data. All producers have dimensions and axes, like an |
420 | | /// array view, and they can be split and used with parallelization using `Zip`. |
421 | | /// |
422 | | /// For example, `ArrayView<A, D>` is a producer, it has the same dimensions |
423 | | /// as the array view and for each iteration it produces a reference to |
424 | | /// the array element (`&A` in this case). |
425 | | /// |
426 | | /// Another example, if we have a 10 × 10 array and use `.exact_chunks((2, 2))` |
427 | | /// we get a producer of chunks which has the dimensions 5 × 5 (because |
428 | | /// there are *10 / 2 = 5* chunks in either direction). The 5 × 5 chunks producer |
429 | | /// can be paired with any other producers of the same dimension with `Zip`, for |
430 | | /// example 5 × 5 arrays. |
431 | | /// |
432 | | /// ### `.iter()` and `.iter_mut()` |
433 | | /// |
434 | | /// These are the element iterators of arrays and they produce an element |
435 | | /// sequence in the logical order of the array, that means that the elements |
436 | | /// will be visited in the sequence that corresponds to increasing the |
437 | | /// last index first: *0, ..., 0, 0*; *0, ..., 0, 1*; *0, ...0, 2* and so on. |
438 | | /// |
439 | | /// ### `.outer_iter()` and `.axis_iter()` |
440 | | /// |
441 | | /// These iterators produce array views of one smaller dimension. |
442 | | /// |
443 | | /// For example, for a 2D array, `.outer_iter()` will produce the 1D rows. |
444 | | /// For a 3D array, `.outer_iter()` produces 2D subviews. |
445 | | /// |
446 | | /// `.axis_iter()` is like `outer_iter()` but allows you to pick which |
447 | | /// axis to traverse. |
448 | | /// |
449 | | /// The `outer_iter` and `axis_iter` are one dimensional producers. |
450 | | /// |
451 | | /// ## `.rows()`, `.columns()` and `.lanes()` |
452 | | /// |
453 | | /// [`.rows()`][gr] is a producer (and iterable) of all rows in an array. |
454 | | /// |
455 | | /// ``` |
456 | | /// use ndarray::Array; |
457 | | /// |
458 | | /// // 1. Loop over the rows of a 2D array |
459 | | /// let mut a = Array::zeros((10, 10)); |
460 | | /// for mut row in a.rows_mut() { |
461 | | /// row.fill(1.); |
462 | | /// } |
463 | | /// |
464 | | /// // 2. Use Zip to pair each row in 2D `a` with elements in 1D `b` |
465 | | /// use ndarray::Zip; |
466 | | /// let mut b = Array::zeros(a.nrows()); |
467 | | /// |
468 | | /// Zip::from(a.rows()) |
469 | | /// .and(&mut b) |
470 | | /// .for_each(|a_row, b_elt| { |
471 | | /// *b_elt = a_row[a.ncols() - 1] - a_row[0]; |
472 | | /// }); |
473 | | /// ``` |
474 | | /// |
475 | | /// The *lanes* of an array are 1D segments along an axis and when pointed |
476 | | /// along the last axis they are *rows*, when pointed along the first axis |
477 | | /// they are *columns*. |
478 | | /// |
479 | | /// A *m* × *n* array has *m* rows each of length *n* and conversely |
480 | | /// *n* columns each of length *m*. |
481 | | /// |
482 | | /// To generalize this, we say that an array of dimension *a* × *m* × *n* |
483 | | /// has *a m* rows. It's composed of *a* times the previous array, so it |
484 | | /// has *a* times as many rows. |
485 | | /// |
486 | | /// All methods: [`.rows()`][gr], [`.rows_mut()`][grm], |
487 | | /// [`.columns()`][gc], [`.columns_mut()`][gcm], |
488 | | /// [`.lanes(axis)`][l], [`.lanes_mut(axis)`][lm]. |
489 | | /// |
490 | | /// [gr]: ArrayRef::rows |
491 | | /// [grm]: ArrayRef::rows_mut |
492 | | /// [gc]: ArrayRef::columns |
493 | | /// [gcm]: ArrayRef::columns_mut |
494 | | /// [l]: ArrayRef::lanes |
495 | | /// [lm]: ArrayRef::lanes_mut |
496 | | /// |
497 | | /// Yes, for 2D arrays `.rows()` and `.outer_iter()` have about the same |
498 | | /// effect: |
499 | | /// |
500 | | /// + `rows()` is a producer with *n* - 1 dimensions of 1 dimensional items |
501 | | /// + `outer_iter()` is a producer with 1 dimension of *n* - 1 dimensional items |
502 | | /// |
503 | | /// ## Slicing |
504 | | /// |
505 | | /// You can use slicing to create a view of a subset of the data in |
506 | | /// the array. Slicing methods include [`.slice()`], [`.slice_mut()`], |
507 | | /// [`.slice_move()`], and [`.slice_collapse()`]. |
508 | | /// |
509 | | /// The slicing argument can be passed using the macro [`s![]`](s!), |
510 | | /// which will be used in all examples. (The explicit form is an instance of |
511 | | /// [`SliceInfo`] or another type which implements [`SliceArg`]; see their docs |
512 | | /// for more information.) |
513 | | /// |
514 | | /// If a range is used, the axis is preserved. If an index is used, that index |
515 | | /// is selected and the axis is removed; this selects a subview. See |
516 | | /// [*Subviews*](#subviews) for more information about subviews. If a |
517 | | /// [`NewAxis`] instance is used, a new axis is inserted. Note that |
518 | | /// [`.slice_collapse()`] panics on `NewAxis` elements and behaves like |
519 | | /// [`.collapse_axis()`] by preserving the number of dimensions. |
520 | | /// |
521 | | /// [`.slice()`]: ArrayRef::slice |
522 | | /// [`.slice_mut()`]: ArrayRef::slice_mut |
523 | | /// [`.slice_move()`]: Self::slice_move |
524 | | /// [`.slice_collapse()`]: LayoutRef::slice_collapse |
525 | | /// |
526 | | /// When slicing arrays with generic dimensionality, creating an instance of |
527 | | /// [`SliceInfo`] to pass to the multi-axis slicing methods like [`.slice()`] |
528 | | /// is awkward. In these cases, it's usually more convenient to use |
529 | | /// [`.slice_each_axis()`]/[`.slice_each_axis_mut()`]/[`.slice_each_axis_inplace()`] |
530 | | /// or to create a view and then slice individual axes of the view using |
531 | | /// methods such as [`.slice_axis_inplace()`] and [`.collapse_axis()`]. |
532 | | /// |
533 | | /// [`.slice_each_axis()`]: ArrayRef::slice_each_axis |
534 | | /// [`.slice_each_axis_mut()`]: ArrayRef::slice_each_axis_mut |
535 | | /// [`.slice_each_axis_inplace()`]: Self::slice_each_axis_inplace |
536 | | /// [`.slice_axis_inplace()`]: Self::slice_axis_inplace |
537 | | /// [`.collapse_axis()`]: LayoutRef::collapse_axis |
538 | | /// |
539 | | /// It's possible to take multiple simultaneous *mutable* slices with |
540 | | /// [`.multi_slice_mut()`] or (for [`ArrayViewMut`] only) |
541 | | /// [`.multi_slice_move()`]. |
542 | | /// |
543 | | /// [`.multi_slice_mut()`]: ArrayRef::multi_slice_mut |
544 | | /// [`.multi_slice_move()`]: ArrayViewMut#method.multi_slice_move |
545 | | /// |
546 | | /// ``` |
547 | | /// use ndarray::{arr2, arr3, s, ArrayBase, DataMut, Dimension, NewAxis, Slice}; |
548 | | /// |
549 | | /// // 2 submatrices of 2 rows with 3 elements per row, means a shape of `[2, 2, 3]`. |
550 | | /// |
551 | | /// let a = arr3(&[[[ 1, 2, 3], // -- 2 rows \_ |
552 | | /// [ 4, 5, 6]], // -- / |
553 | | /// [[ 7, 8, 9], // \_ 2 submatrices |
554 | | /// [10, 11, 12]]]); // / |
555 | | /// // 3 columns ..../.../.../ |
556 | | /// |
557 | | /// assert_eq!(a.shape(), &[2, 2, 3]); |
558 | | /// |
559 | | /// // Let’s create a slice with |
560 | | /// // |
561 | | /// // - Both of the submatrices of the greatest dimension: `..` |
562 | | /// // - Only the first row in each submatrix: `0..1` |
563 | | /// // - Every element in each row: `..` |
564 | | /// |
565 | | /// let b = a.slice(s![.., 0..1, ..]); |
566 | | /// let c = arr3(&[[[ 1, 2, 3]], |
567 | | /// [[ 7, 8, 9]]]); |
568 | | /// assert_eq!(b, c); |
569 | | /// assert_eq!(b.shape(), &[2, 1, 3]); |
570 | | /// |
571 | | /// // Let’s create a slice with |
572 | | /// // |
573 | | /// // - Both submatrices of the greatest dimension: `..` |
574 | | /// // - The last row in each submatrix: `-1..` |
575 | | /// // - Row elements in reverse order: `..;-1` |
576 | | /// let d = a.slice(s![.., -1.., ..;-1]); |
577 | | /// let e = arr3(&[[[ 6, 5, 4]], |
578 | | /// [[12, 11, 10]]]); |
579 | | /// assert_eq!(d, e); |
580 | | /// assert_eq!(d.shape(), &[2, 1, 3]); |
581 | | /// |
582 | | /// // Let’s create a slice while selecting a subview and inserting a new axis with |
583 | | /// // |
584 | | /// // - Both submatrices of the greatest dimension: `..` |
585 | | /// // - The last row in each submatrix, removing that axis: `-1` |
586 | | /// // - Row elements in reverse order: `..;-1` |
587 | | /// // - A new axis at the end. |
588 | | /// let f = a.slice(s![.., -1, ..;-1, NewAxis]); |
589 | | /// let g = arr3(&[[ [6], [5], [4]], |
590 | | /// [[12], [11], [10]]]); |
591 | | /// assert_eq!(f, g); |
592 | | /// assert_eq!(f.shape(), &[2, 3, 1]); |
593 | | /// |
594 | | /// // Let's take two disjoint, mutable slices of a matrix with |
595 | | /// // |
596 | | /// // - One containing all the even-index columns in the matrix |
597 | | /// // - One containing all the odd-index columns in the matrix |
598 | | /// let mut h = arr2(&[[0, 1, 2, 3], |
599 | | /// [4, 5, 6, 7]]); |
600 | | /// let (s0, s1) = h.multi_slice_mut((s![.., ..;2], s![.., 1..;2])); |
601 | | /// let i = arr2(&[[0, 2], |
602 | | /// [4, 6]]); |
603 | | /// let j = arr2(&[[1, 3], |
604 | | /// [5, 7]]); |
605 | | /// assert_eq!(s0, i); |
606 | | /// assert_eq!(s1, j); |
607 | | /// |
608 | | /// // Generic function which assigns the specified value to the elements which |
609 | | /// // have indices in the lower half along all axes. |
610 | | /// fn fill_lower<S, D>(arr: &mut ArrayBase<S, D>, x: S::Elem) |
611 | | /// where |
612 | | /// S: DataMut, |
613 | | /// S::Elem: Clone, |
614 | | /// D: Dimension, |
615 | | /// { |
616 | | /// arr.slice_each_axis_mut(|ax| Slice::from(0..ax.len / 2)).fill(x); |
617 | | /// } |
618 | | /// fill_lower(&mut h, 9); |
619 | | /// let k = arr2(&[[9, 9, 2, 3], |
620 | | /// [4, 5, 6, 7]]); |
621 | | /// assert_eq!(h, k); |
622 | | /// ``` |
623 | | /// |
624 | | /// ## Subviews |
625 | | /// |
626 | | /// Subview methods allow you to restrict the array view while removing one |
627 | | /// axis from the array. Methods for selecting individual subviews include |
628 | | /// [`.index_axis()`], [`.index_axis_mut()`], [`.index_axis_move()`], and |
629 | | /// [`.index_axis_inplace()`]. You can also select a subview by using a single |
630 | | /// index instead of a range when slicing. Some other methods, such as |
631 | | /// [`.fold_axis()`], [`.axis_iter()`], [`.axis_iter_mut()`], |
632 | | /// [`.outer_iter()`], and [`.outer_iter_mut()`] operate on all the subviews |
633 | | /// along an axis. |
634 | | /// |
635 | | /// A related method is [`.collapse_axis()`], which modifies the view in the |
636 | | /// same way as [`.index_axis()`] except for removing the collapsed axis, since |
637 | | /// it operates *in place*. The length of the axis becomes 1. |
638 | | /// |
639 | | /// Methods for selecting an individual subview take two arguments: `axis` and |
640 | | /// `index`. |
641 | | /// |
642 | | /// [`.axis_iter()`]: ArrayRef::axis_iter |
643 | | /// [`.axis_iter_mut()`]: ArrayRef::axis_iter_mut |
644 | | /// [`.fold_axis()`]: ArrayRef::fold_axis |
645 | | /// [`.index_axis()`]: ArrayRef::index_axis |
646 | | /// [`.index_axis_inplace()`]: LayoutRef::index_axis_inplace |
647 | | /// [`.index_axis_mut()`]: ArrayRef::index_axis_mut |
648 | | /// [`.index_axis_move()`]: Self::index_axis_move |
649 | | /// [`.collapse_axis()`]: LayoutRef::collapse_axis |
650 | | /// [`.outer_iter()`]: ArrayRef::outer_iter |
651 | | /// [`.outer_iter_mut()`]: ArrayRef::outer_iter_mut |
652 | | /// |
653 | | /// ``` |
654 | | /// |
655 | | /// use ndarray::{arr3, aview1, aview2, s, Axis}; |
656 | | /// |
657 | | /// |
658 | | /// // 2 submatrices of 2 rows with 3 elements per row, means a shape of `[2, 2, 3]`. |
659 | | /// |
660 | | /// let a = arr3(&[[[ 1, 2, 3], // \ axis 0, submatrix 0 |
661 | | /// [ 4, 5, 6]], // / |
662 | | /// [[ 7, 8, 9], // \ axis 0, submatrix 1 |
663 | | /// [10, 11, 12]]]); // / |
664 | | /// // \ |
665 | | /// // axis 2, column 0 |
666 | | /// |
667 | | /// assert_eq!(a.shape(), &[2, 2, 3]); |
668 | | /// |
669 | | /// // Let’s take a subview along the greatest dimension (axis 0), |
670 | | /// // taking submatrix 0, then submatrix 1 |
671 | | /// |
672 | | /// let sub_0 = a.index_axis(Axis(0), 0); |
673 | | /// let sub_1 = a.index_axis(Axis(0), 1); |
674 | | /// |
675 | | /// assert_eq!(sub_0, aview2(&[[ 1, 2, 3], |
676 | | /// [ 4, 5, 6]])); |
677 | | /// assert_eq!(sub_1, aview2(&[[ 7, 8, 9], |
678 | | /// [10, 11, 12]])); |
679 | | /// assert_eq!(sub_0.shape(), &[2, 3]); |
680 | | /// |
681 | | /// // This is the subview picking only axis 2, column 0 |
682 | | /// let sub_col = a.index_axis(Axis(2), 0); |
683 | | /// |
684 | | /// assert_eq!(sub_col, aview2(&[[ 1, 4], |
685 | | /// [ 7, 10]])); |
686 | | /// |
687 | | /// // You can take multiple subviews at once (and slice at the same time) |
688 | | /// let double_sub = a.slice(s![1, .., 0]); |
689 | | /// assert_eq!(double_sub, aview1(&[7, 10])); |
690 | | /// ``` |
691 | | /// |
692 | | /// ## Arithmetic Operations |
693 | | /// |
694 | | /// Arrays support all arithmetic operations the same way: they apply elementwise. |
695 | | /// |
696 | | /// Since the trait implementations are hard to overview, here is a summary. |
697 | | /// |
698 | | /// ### Binary Operators with Two Arrays |
699 | | /// |
700 | | /// Let `A` be an array or view of any kind. Let `B` be an array |
701 | | /// with owned storage (either `Array` or `ArcArray`). |
702 | | /// Let `C` be an array with mutable data (either `Array`, `ArcArray` |
703 | | /// or `ArrayViewMut`). |
704 | | /// The following combinations of operands |
705 | | /// are supported for an arbitrary binary operator denoted by `@` (it can be |
706 | | /// `+`, `-`, `*`, `/` and so on). |
707 | | /// |
708 | | /// - `&A @ &A` which produces a new `Array` |
709 | | /// - `B @ A` which consumes `B`, updates it with the result, and returns it |
710 | | /// - `B @ &A` which consumes `B`, updates it with the result, and returns it |
711 | | /// - `C @= &A` which performs an arithmetic operation in place |
712 | | /// |
713 | | /// Note that the element type needs to implement the operator trait and the |
714 | | /// `Clone` trait. |
715 | | /// |
716 | | /// ``` |
717 | | /// use ndarray::{array, ArrayView1}; |
718 | | /// |
719 | | /// let owned1 = array![1, 2]; |
720 | | /// let owned2 = array![3, 4]; |
721 | | /// let view1 = ArrayView1::from(&[5, 6]); |
722 | | /// let view2 = ArrayView1::from(&[7, 8]); |
723 | | /// let mut mutable = array![9, 10]; |
724 | | /// |
725 | | /// let sum1 = &view1 + &view2; // Allocates a new array. Note the explicit `&`. |
726 | | /// // let sum2 = view1 + &view2; // This doesn't work because `view1` is not an owned array. |
727 | | /// let sum3 = owned1 + view1; // Consumes `owned1`, updates it, and returns it. |
728 | | /// let sum4 = owned2 + &view2; // Consumes `owned2`, updates it, and returns it. |
729 | | /// mutable += &view2; // Updates `mutable` in-place. |
730 | | /// ``` |
731 | | /// |
732 | | /// ### Binary Operators with Array and Scalar |
733 | | /// |
734 | | /// The trait [`ScalarOperand`] marks types that can be used in arithmetic |
735 | | /// with arrays directly. For a scalar `K` the following combinations of operands |
736 | | /// are supported (scalar can be on either the left or right side, but |
737 | | /// `ScalarOperand` docs has the detailed conditions). |
738 | | /// |
739 | | /// - `&A @ K` or `K @ &A` which produces a new `Array` |
740 | | /// - `B @ K` or `K @ B` which consumes `B`, updates it with the result and returns it |
741 | | /// - `C @= K` which performs an arithmetic operation in place |
742 | | /// |
743 | | /// ### Unary Operators |
744 | | /// |
745 | | /// Let `A` be an array or view of any kind. Let `B` be an array with owned |
746 | | /// storage (either `Array` or `ArcArray`). The following operands are supported |
747 | | /// for an arbitrary unary operator denoted by `@` (it can be `-` or `!`). |
748 | | /// |
749 | | /// - `@&A` which produces a new `Array` |
750 | | /// - `@B` which consumes `B`, updates it with the result, and returns it |
751 | | /// |
752 | | /// ## Broadcasting |
753 | | /// |
754 | | /// Arrays support limited *broadcasting*, where arithmetic operations with |
755 | | /// array operands of different sizes can be carried out by repeating the |
756 | | /// elements of the smaller dimension array. See |
757 | | /// [`.broadcast()`](ArrayRef::broadcast) for a more detailed |
758 | | /// description. |
759 | | /// |
760 | | /// ``` |
761 | | /// use ndarray::arr2; |
762 | | /// |
763 | | /// let a = arr2(&[[1., 1.], |
764 | | /// [1., 2.], |
765 | | /// [0., 3.], |
766 | | /// [0., 4.]]); |
767 | | /// |
768 | | /// let b = arr2(&[[0., 1.]]); |
769 | | /// |
770 | | /// let c = arr2(&[[1., 2.], |
771 | | /// [1., 3.], |
772 | | /// [0., 4.], |
773 | | /// [0., 5.]]); |
774 | | /// // We can add because the shapes are compatible even if not equal. |
775 | | /// // The `b` array is shape 1 × 2 but acts like a 4 × 2 array. |
776 | | /// assert!( |
777 | | /// c == a + b |
778 | | /// ); |
779 | | /// ``` |
780 | | /// |
781 | | /// ## Conversions |
782 | | /// |
783 | | /// ### Conversions Between Array Types |
784 | | /// |
785 | | /// This table is a summary of the conversions between arrays of different |
786 | | /// ownership, dimensionality, and element type. All of the conversions in this |
787 | | /// table preserve the shape of the array. |
788 | | /// |
789 | | /// <table> |
790 | | /// <tr> |
791 | | /// <th rowspan="2">Output</th> |
792 | | /// <th colspan="5">Input</th> |
793 | | /// </tr> |
794 | | /// |
795 | | /// <tr> |
796 | | /// <td> |
797 | | /// |
798 | | /// `Array<A, D>` |
799 | | /// |
800 | | /// </td> |
801 | | /// <td> |
802 | | /// |
803 | | /// `ArcArray<A, D>` |
804 | | /// |
805 | | /// </td> |
806 | | /// <td> |
807 | | /// |
808 | | /// `CowArray<'a, A, D>` |
809 | | /// |
810 | | /// </td> |
811 | | /// <td> |
812 | | /// |
813 | | /// `ArrayView<'a, A, D>` |
814 | | /// |
815 | | /// </td> |
816 | | /// <td> |
817 | | /// |
818 | | /// `ArrayViewMut<'a, A, D>` |
819 | | /// |
820 | | /// </td> |
821 | | /// </tr> |
822 | | /// |
823 | | /// <!--Conversions to `Array<A, D>`--> |
824 | | /// |
825 | | /// <tr> |
826 | | /// <td> |
827 | | /// |
828 | | /// `Array<A, D>` |
829 | | /// |
830 | | /// </td> |
831 | | /// <td> |
832 | | /// |
833 | | /// no-op |
834 | | /// |
835 | | /// </td> |
836 | | /// <td> |
837 | | /// |
838 | | /// [`a.into_owned()`][.into_owned()] |
839 | | /// |
840 | | /// </td> |
841 | | /// <td> |
842 | | /// |
843 | | /// [`a.into_owned()`][.into_owned()] |
844 | | /// |
845 | | /// </td> |
846 | | /// <td> |
847 | | /// |
848 | | /// [`a.to_owned()`][.to_owned()] |
849 | | /// |
850 | | /// </td> |
851 | | /// <td> |
852 | | /// |
853 | | /// [`a.to_owned()`][.to_owned()] |
854 | | /// |
855 | | /// </td> |
856 | | /// </tr> |
857 | | /// |
858 | | /// <!--Conversions to `ArcArray<A, D>`--> |
859 | | /// |
860 | | /// <tr> |
861 | | /// <td> |
862 | | /// |
863 | | /// `ArcArray<A, D>` |
864 | | /// |
865 | | /// </td> |
866 | | /// <td> |
867 | | /// |
868 | | /// [`a.into_shared()`][.into_shared()] |
869 | | /// |
870 | | /// </td> |
871 | | /// <td> |
872 | | /// |
873 | | /// no-op |
874 | | /// |
875 | | /// </td> |
876 | | /// <td> |
877 | | /// |
878 | | /// [`a.into_owned().into_shared()`][.into_shared()] |
879 | | /// |
880 | | /// </td> |
881 | | /// <td> |
882 | | /// |
883 | | /// [`a.to_owned().into_shared()`][.into_shared()] |
884 | | /// |
885 | | /// </td> |
886 | | /// <td> |
887 | | /// |
888 | | /// [`a.to_owned().into_shared()`][.into_shared()] |
889 | | /// |
890 | | /// </td> |
891 | | /// </tr> |
892 | | /// |
893 | | /// <!--Conversions to `CowArray<'a, A, D>`--> |
894 | | /// |
895 | | /// <tr> |
896 | | /// <td> |
897 | | /// |
898 | | /// `CowArray<'a, A, D>` |
899 | | /// |
900 | | /// </td> |
901 | | /// <td> |
902 | | /// |
903 | | /// [`CowArray::from(a)`](CowArray#impl-From<ArrayBase<OwnedRepr<A>%2C%20D>>) |
904 | | /// |
905 | | /// </td> |
906 | | /// <td> |
907 | | /// |
908 | | /// [`CowArray::from(a.into_owned())`](CowArray#impl-From<ArrayBase<OwnedRepr<A>%2C%20D>>) |
909 | | /// |
910 | | /// </td> |
911 | | /// <td> |
912 | | /// |
913 | | /// no-op |
914 | | /// |
915 | | /// </td> |
916 | | /// <td> |
917 | | /// |
918 | | /// [`CowArray::from(a)`](CowArray#impl-From<ArrayBase<ViewRepr<%26%27a%20A>%2C%20D>>) |
919 | | /// |
920 | | /// </td> |
921 | | /// <td> |
922 | | /// |
923 | | /// [`CowArray::from(a.view())`](CowArray#impl-From<ArrayBase<ViewRepr<%26%27a%20A>%2C%20D>>) |
924 | | /// |
925 | | /// </td> |
926 | | /// </tr> |
927 | | /// |
928 | | /// <!--Conversions to `ArrayView<'b, A, D>`--> |
929 | | /// |
930 | | /// <tr> |
931 | | /// <td> |
932 | | /// |
933 | | /// `ArrayView<'b, A, D>` |
934 | | /// |
935 | | /// </td> |
936 | | /// <td> |
937 | | /// |
938 | | /// [`a.view()`][.view()] |
939 | | /// |
940 | | /// </td> |
941 | | /// <td> |
942 | | /// |
943 | | /// [`a.view()`][.view()] |
944 | | /// |
945 | | /// </td> |
946 | | /// <td> |
947 | | /// |
948 | | /// [`a.view()`][.view()] |
949 | | /// |
950 | | /// </td> |
951 | | /// <td> |
952 | | /// |
953 | | /// [`a.view()`][.view()] or [`a.reborrow()`][ArrayView::reborrow()] |
954 | | /// |
955 | | /// </td> |
956 | | /// <td> |
957 | | /// |
958 | | /// [`a.view()`][.view()] |
959 | | /// |
960 | | /// </td> |
961 | | /// </tr> |
962 | | /// |
963 | | /// <!--Conversions to `ArrayViewMut<'b, A, D>`--> |
964 | | /// |
965 | | /// <tr> |
966 | | /// <td> |
967 | | /// |
968 | | /// `ArrayViewMut<'b, A, D>` |
969 | | /// |
970 | | /// </td> |
971 | | /// <td> |
972 | | /// |
973 | | /// [`a.view_mut()`][.view_mut()] |
974 | | /// |
975 | | /// </td> |
976 | | /// <td> |
977 | | /// |
978 | | /// [`a.view_mut()`][.view_mut()] |
979 | | /// |
980 | | /// </td> |
981 | | /// <td> |
982 | | /// |
983 | | /// [`a.view_mut()`][.view_mut()] |
984 | | /// |
985 | | /// </td> |
986 | | /// <td> |
987 | | /// |
988 | | /// illegal |
989 | | /// |
990 | | /// </td> |
991 | | /// <td> |
992 | | /// |
993 | | /// [`a.view_mut()`][.view_mut()] or [`a.reborrow()`][ArrayViewMut::reborrow()] |
994 | | /// |
995 | | /// </td> |
996 | | /// </tr> |
997 | | /// |
998 | | /// <!--Conversions to equivalent with dim `D2`--> |
999 | | /// |
1000 | | /// <tr> |
1001 | | /// <td> |
1002 | | /// |
1003 | | /// equivalent with dim `D2` (e.g. converting from dynamic dim to const dim) |
1004 | | /// |
1005 | | /// </td> |
1006 | | /// <td colspan="5"> |
1007 | | /// |
1008 | | /// [`a.into_dimensionality::<D2>()`][.into_dimensionality()] |
1009 | | /// |
1010 | | /// </td> |
1011 | | /// </tr> |
1012 | | /// |
1013 | | /// <!--Conversions to equivalent with dim `IxDyn`--> |
1014 | | /// |
1015 | | /// <tr> |
1016 | | /// <td> |
1017 | | /// |
1018 | | /// equivalent with dim `IxDyn` |
1019 | | /// |
1020 | | /// </td> |
1021 | | /// <td colspan="5"> |
1022 | | /// |
1023 | | /// [`a.into_dyn()`][.into_dyn()] |
1024 | | /// |
1025 | | /// </td> |
1026 | | /// </tr> |
1027 | | /// |
1028 | | /// <!--Conversions to `Array<B, D>`--> |
1029 | | /// |
1030 | | /// <tr> |
1031 | | /// <td> |
1032 | | /// |
1033 | | /// `Array<B, D>` (new element type) |
1034 | | /// |
1035 | | /// </td> |
1036 | | /// <td colspan="5"> |
1037 | | /// |
1038 | | /// [`a.map(|x| x.do_your_conversion())`][.map()] |
1039 | | /// |
1040 | | /// </td> |
1041 | | /// </tr> |
1042 | | /// </table> |
1043 | | /// |
1044 | | /// ### Conversions Between Arrays and `Vec`s/Slices/Scalars |
1045 | | /// |
1046 | | /// This is a table of the safe conversions between arrays and |
1047 | | /// `Vec`s/slices/scalars. Note that some of the return values are actually |
1048 | | /// `Result`/`Option` wrappers around the indicated output types. |
1049 | | /// |
1050 | | /// Input | Output | Methods |
1051 | | /// ------|--------|-------- |
1052 | | /// `Vec<A>` | `ArrayBase<S: DataOwned, Ix1>` | [`::from_vec()`](Self::from_vec) |
1053 | | /// `Vec<A>` | `ArrayBase<S: DataOwned, D>` | [`::from_shape_vec()`](Self::from_shape_vec) |
1054 | | /// `&[A]` | `ArrayView1<A>` | [`::from()`](ArrayView#method.from) |
1055 | | /// `&[A]` | `ArrayView<A, D>` | [`::from_shape()`](ArrayView#method.from_shape) |
1056 | | /// `&mut [A]` | `ArrayViewMut1<A>` | [`::from()`](ArrayViewMut#method.from) |
1057 | | /// `&mut [A]` | `ArrayViewMut<A, D>` | [`::from_shape()`](ArrayViewMut#method.from_shape) |
1058 | | /// `&ArrayBase<S, Ix1>` | `Vec<A>` | [`.to_vec()`](ArrayRef::to_vec) |
1059 | | /// `Array<A, D>` | `Vec<A>` | [`.into_raw_vec()`](Array#method.into_raw_vec)<sup>[1](#into_raw_vec)</sup> |
1060 | | /// `&ArrayBase<S, D>` | `&[A]` | [`.as_slice()`](ArrayRef::as_slice)<sup>[2](#req_contig_std)</sup>, [`.as_slice_memory_order()`](ArrayRef::as_slice_memory_order)<sup>[3](#req_contig)</sup> |
1061 | | /// `&mut ArrayBase<S: DataMut, D>` | `&mut [A]` | [`.as_slice_mut()`](Self::as_slice_mut)<sup>[2](#req_contig_std)</sup>, [`.as_slice_memory_order_mut()`](Self::as_slice_memory_order_mut)<sup>[3](#req_contig)</sup> |
1062 | | /// `ArrayView<A, D>` | `&[A]` | [`.to_slice()`](ArrayView#method.to_slice)<sup>[2](#req_contig_std)</sup> |
1063 | | /// `ArrayViewMut<A, D>` | `&mut [A]` | [`.into_slice()`](ArrayViewMut#method.into_slice)<sup>[2](#req_contig_std)</sup> |
1064 | | /// `Array0<A>` | `A` | [`.into_scalar()`](Array#method.into_scalar) |
1065 | | /// |
1066 | | /// <sup><a name="into_raw_vec">1</a></sup>Returns the data in memory order. |
1067 | | /// |
1068 | | /// <sup><a name="req_contig_std">2</a></sup>Works only if the array is |
1069 | | /// contiguous and in standard order. |
1070 | | /// |
1071 | | /// <sup><a name="req_contig">3</a></sup>Works only if the array is contiguous. |
1072 | | /// |
1073 | | /// The table above does not include all the constructors; it only shows |
1074 | | /// conversions to/from `Vec`s/slices. See |
1075 | | /// [below](#constructor-methods-for-owned-arrays) for more constructors. |
1076 | | /// |
1077 | | /// [ArrayView::reborrow()]: ArrayView#method.reborrow |
1078 | | /// [ArrayViewMut::reborrow()]: ArrayViewMut#method.reborrow |
1079 | | /// [.into_dimensionality()]: Self::into_dimensionality |
1080 | | /// [.into_dyn()]: Self::into_dyn |
1081 | | /// [.into_owned()]: Self::into_owned |
1082 | | /// [.into_shared()]: Self::into_shared |
1083 | | /// [.to_owned()]: Self::to_owned |
1084 | | /// [.map()]: ArrayRef::map |
1085 | | /// [.view()]: ArrayRef::view |
1086 | | /// [.view_mut()]: ArrayRef::view_mut |
1087 | | /// |
1088 | | /// ### Conversions from Nested `Vec`s/`Array`s |
1089 | | /// |
1090 | | /// It's generally a good idea to avoid nested `Vec`/`Array` types, such as |
1091 | | /// `Vec<Vec<A>>` or `Vec<Array2<A>>` because: |
1092 | | /// |
1093 | | /// * they require extra heap allocations compared to a single `Array`, |
1094 | | /// |
1095 | | /// * they can scatter data all over memory (because of multiple allocations), |
1096 | | /// |
1097 | | /// * they cause unnecessary indirection (traversing multiple pointers to reach |
1098 | | /// the data), |
1099 | | /// |
1100 | | /// * they don't enforce consistent shape within the nested |
1101 | | /// `Vec`s/`ArrayBase`s, and |
1102 | | /// |
1103 | | /// * they are generally more difficult to work with. |
1104 | | /// |
1105 | | /// The most common case where users might consider using nested |
1106 | | /// `Vec`s/`Array`s is when creating an array by appending rows/subviews in a |
1107 | | /// loop, where the rows/subviews are computed within the loop. However, there |
1108 | | /// are better ways than using nested `Vec`s/`Array`s. |
1109 | | /// |
1110 | | /// If you know ahead-of-time the shape of the final array, the cleanest |
1111 | | /// solution is to allocate the final array before the loop, and then assign |
1112 | | /// the data to it within the loop, like this: |
1113 | | /// |
1114 | | /// ```rust |
1115 | | /// use ndarray::{array, Array2, Axis}; |
1116 | | /// |
1117 | | /// let mut arr = Array2::zeros((2, 3)); |
1118 | | /// for (i, mut row) in arr.axis_iter_mut(Axis(0)).enumerate() { |
1119 | | /// // Perform calculations and assign to `row`; this is a trivial example: |
1120 | | /// row.fill(i); |
1121 | | /// } |
1122 | | /// assert_eq!(arr, array![[0, 0, 0], [1, 1, 1]]); |
1123 | | /// ``` |
1124 | | /// |
1125 | | /// If you don't know ahead-of-time the shape of the final array, then the |
1126 | | /// cleanest solution is generally to append the data to a flat `Vec`, and then |
1127 | | /// convert it to an `Array` at the end with |
1128 | | /// [`::from_shape_vec()`](Self::from_shape_vec). You just have to be careful |
1129 | | /// that the layout of the data (the order of the elements in the flat `Vec`) |
1130 | | /// is correct. |
1131 | | /// |
1132 | | /// ```rust |
1133 | | /// use ndarray::{array, Array2}; |
1134 | | /// |
1135 | | /// let ncols = 3; |
1136 | | /// let mut data = Vec::new(); |
1137 | | /// let mut nrows = 0; |
1138 | | /// for i in 0..2 { |
1139 | | /// // Compute `row` and append it to `data`; this is a trivial example: |
1140 | | /// let row = vec![i; ncols]; |
1141 | | /// data.extend_from_slice(&row); |
1142 | | /// nrows += 1; |
1143 | | /// } |
1144 | | /// let arr = Array2::from_shape_vec((nrows, ncols), data)?; |
1145 | | /// assert_eq!(arr, array![[0, 0, 0], [1, 1, 1]]); |
1146 | | /// # Ok::<(), ndarray::ShapeError>(()) |
1147 | | /// ``` |
1148 | | /// |
1149 | | /// If neither of these options works for you, and you really need to convert |
1150 | | /// nested `Vec`/`Array` instances to an `Array`, the cleanest solution is |
1151 | | /// generally to use [`Iterator::flatten()`] |
1152 | | /// to get a flat `Vec`, and then convert the `Vec` to an `Array` with |
1153 | | /// [`::from_shape_vec()`](Self::from_shape_vec), like this: |
1154 | | /// |
1155 | | /// ```rust |
1156 | | /// use ndarray::{array, Array2, Array3}; |
1157 | | /// |
1158 | | /// let nested: Vec<Array2<i32>> = vec![ |
1159 | | /// array![[1, 2, 3], [4, 5, 6]], |
1160 | | /// array![[7, 8, 9], [10, 11, 12]], |
1161 | | /// ]; |
1162 | | /// let inner_shape = nested[0].dim(); |
1163 | | /// let shape = (nested.len(), inner_shape.0, inner_shape.1); |
1164 | | /// let flat: Vec<i32> = nested.iter().flatten().cloned().collect(); |
1165 | | /// let arr = Array3::from_shape_vec(shape, flat)?; |
1166 | | /// assert_eq!(arr, array![ |
1167 | | /// [[1, 2, 3], [4, 5, 6]], |
1168 | | /// [[7, 8, 9], [10, 11, 12]], |
1169 | | /// ]); |
1170 | | /// # Ok::<(), ndarray::ShapeError>(()) |
1171 | | /// ``` |
1172 | | /// |
1173 | | /// Note that this implementation assumes that the nested `Vec`s are all the |
1174 | | /// same shape and that the `Vec` is non-empty. Depending on your application, |
1175 | | /// it may be a good idea to add checks for these assumptions and possibly |
1176 | | /// choose a different way to handle the empty case. |
1177 | | /// |
1178 | | // # For implementors |
1179 | | // |
1180 | | // All methods must uphold the following constraints: |
1181 | | // |
1182 | | // 1. `data` must correctly represent the data buffer / ownership information, |
1183 | | // `ptr` must point into the data represented by `data`, and the `dim` and |
1184 | | // `strides` must be consistent with `data`. For example, |
1185 | | // |
1186 | | // * If `data` is `OwnedRepr<A>`, all elements represented by `ptr`, `dim`, |
1187 | | // and `strides` must be owned by the `Vec` and not aliased by multiple |
1188 | | // indices. |
1189 | | // |
1190 | | // * If `data` is `ViewRepr<&'a mut A>`, all elements represented by `ptr`, |
1191 | | // `dim`, and `strides` must be exclusively borrowed and not aliased by |
1192 | | // multiple indices. |
1193 | | // |
1194 | | // 2. If the type of `data` implements `Data`, then `ptr` must be aligned. |
1195 | | // |
1196 | | // 3. `ptr` must be non-null, and it must be safe to [`.offset()`] `ptr` by |
1197 | | // zero. |
1198 | | // |
1199 | | // 4. It must be safe to [`.offset()`] the pointer repeatedly along all axes |
1200 | | // and calculate the `count`s for the `.offset()` calls without overflow, |
1201 | | // even if the array is empty or the elements are zero-sized. |
1202 | | // |
1203 | | // More specifically, the set of all possible (signed) offset counts |
1204 | | // relative to `ptr` can be determined by the following (the casts and |
1205 | | // arithmetic must not overflow): |
1206 | | // |
1207 | | // ```rust |
1208 | | // /// Returns all the possible offset `count`s relative to `ptr`. |
1209 | | // fn all_offset_counts(shape: &[usize], strides: &[isize]) -> BTreeSet<isize> { |
1210 | | // assert_eq!(shape.len(), strides.len()); |
1211 | | // let mut all_offsets = BTreeSet::<isize>::new(); |
1212 | | // all_offsets.insert(0); |
1213 | | // for axis in 0..shape.len() { |
1214 | | // let old_offsets = all_offsets.clone(); |
1215 | | // for index in 0..shape[axis] { |
1216 | | // assert!(index <= isize::MAX as usize); |
1217 | | // let off = (index as isize).checked_mul(strides[axis]).unwrap(); |
1218 | | // for &old_offset in &old_offsets { |
1219 | | // all_offsets.insert(old_offset.checked_add(off).unwrap()); |
1220 | | // } |
1221 | | // } |
1222 | | // } |
1223 | | // all_offsets |
1224 | | // } |
1225 | | // ``` |
1226 | | // |
1227 | | // Note that it must be safe to offset the pointer *repeatedly* along all |
1228 | | // axes, so in addition for it being safe to offset `ptr` by each of these |
1229 | | // counts, the difference between the least and greatest address reachable |
1230 | | // by these offsets in units of `A` and in units of bytes must not be |
1231 | | // greater than `isize::MAX`. |
1232 | | // |
1233 | | // In other words, |
1234 | | // |
1235 | | // * All possible pointers generated by moving along all axes must be in |
1236 | | // bounds or one byte past the end of a single allocation with element |
1237 | | // type `A`. The only exceptions are if the array is empty or the element |
1238 | | // type is zero-sized. In these cases, `ptr` may be dangling, but it must |
1239 | | // still be safe to [`.offset()`] the pointer along the axes. |
1240 | | // |
1241 | | // * The offset in units of bytes between the least address and greatest |
1242 | | // address by moving along all axes must not exceed `isize::MAX`. This |
1243 | | // constraint prevents the computed offset, in bytes, from overflowing |
1244 | | // `isize` regardless of the starting point due to past offsets. |
1245 | | // |
1246 | | // * The offset in units of `A` between the least address and greatest |
1247 | | // address by moving along all axes must not exceed `isize::MAX`. This |
1248 | | // constraint prevents overflow when calculating the `count` parameter to |
1249 | | // [`.offset()`] regardless of the starting point due to past offsets. |
1250 | | // |
1251 | | // For example, if the shape is [2, 0, 3] and the strides are [3, 6, -1], |
1252 | | // the offsets of interest relative to `ptr` are -2, -1, 0, 1, 2, 3. So, |
1253 | | // `ptr.offset(-2)`, `ptr.offset(-1)`, …, `ptr.offset(3)` must be pointers |
1254 | | // within a single allocation with element type `A`; `(3 - (-2)) * |
1255 | | // size_of::<A>()` must not exceed `isize::MAX`, and `3 - (-2)` must not |
1256 | | // exceed `isize::MAX`. Note that this is a requirement even though the |
1257 | | // array is empty (axis 1 has length 0). |
1258 | | // |
1259 | | // A dangling pointer can be used when creating an empty array, but this |
1260 | | // usually means all the strides have to be zero. A dangling pointer that |
1261 | | // can safely be offset by zero bytes can be constructed with |
1262 | | // `::std::ptr::NonNull::<A>::dangling().as_ptr()`. (It isn't entirely clear |
1263 | | // from the documentation that a pointer created this way is safe to |
1264 | | // `.offset()` at all, even by zero bytes, but the implementation of |
1265 | | // `Vec<A>` does this, so we can too. See rust-lang/rust#54857 for details.) |
1266 | | // |
1267 | | // 5. The product of non-zero axis lengths must not exceed `isize::MAX`. (This |
1268 | | // also implies that the length of any individual axis must not exceed |
1269 | | // `isize::MAX`, and an array can contain at most `isize::MAX` elements.) |
1270 | | // This constraint makes various calculations easier because they don't have |
1271 | | // to worry about overflow and axis lengths can be freely cast to `isize`. |
1272 | | // |
1273 | | // Constraints 2–5 are carefully designed such that if they're upheld for the |
1274 | | // array, they're also upheld for any subset of axes of the array as well as |
1275 | | // slices/subviews/reshapes of the array. This is important for iterators that |
1276 | | // produce subviews (and other similar cases) to be safe without extra (easy to |
1277 | | // forget) checks for zero-length axes. Constraint 1 is similarly upheld for |
1278 | | // any subset of axes and slices/subviews/reshapes, except when removing a |
1279 | | // zero-length axis (since if the other axes are non-zero-length, that would |
1280 | | // allow accessing elements that should not be possible to access). |
1281 | | // |
1282 | | // Method/function implementations can rely on these constraints being upheld. |
1283 | | // The constraints can be temporarily violated within a method/function |
1284 | | // implementation since `ArrayBase` doesn't implement `Drop` and `&mut |
1285 | | // ArrayBase` is `!UnwindSafe`, but the implementation must not call |
1286 | | // methods/functions on the array while it violates the constraints. |
1287 | | // Critically, this includes calling `DerefMut`; as a result, methods/functions |
1288 | | // that temporarily violate these must not rely on the `DerefMut` implementation |
1289 | | // for access to the underlying `ptr`, `strides`, or `dim`. |
1290 | | // |
1291 | | // Users of the `ndarray` crate cannot rely on these constraints because they |
1292 | | // may change in the future. |
1293 | | // |
1294 | | // [`.offset()`]: https://doc.rust-lang.org/stable/std/primitive.pointer.html#method.offset-1 |
1295 | | pub struct ArrayBase<S, D, A = <S as RawData>::Elem> |
1296 | | where S: RawData<Elem = A> |
1297 | | { |
1298 | | /// Data buffer / ownership information. (If owned, contains the data |
1299 | | /// buffer; if borrowed, contains the lifetime and mutability.) |
1300 | | data: S, |
1301 | | /// The dimension, strides, and pointer to inside of `data` |
1302 | | parts: ArrayPartsSized<A, D>, |
1303 | | } |
1304 | | |
1305 | | /// A possibly-unsized container for array parts. |
1306 | | /// |
1307 | | /// This type only exists to enable holding the array parts in a single |
1308 | | /// type, which needs to be sized inside of `ArrayBase` and unsized inside |
1309 | | /// of the reference types. |
1310 | | #[derive(Debug)] |
1311 | | struct ArrayParts<A, D, T: ?Sized> |
1312 | | { |
1313 | | /// A non-null pointer into the buffer held by `data`; may point anywhere |
1314 | | /// in its range. If `S: Data`, this pointer must be aligned. |
1315 | | ptr: NonNull<A>, |
1316 | | /// The lengths of the axes. |
1317 | | dim: D, |
1318 | | /// The element count stride per axis. To be parsed as `isize`. |
1319 | | strides: D, |
1320 | | _dst_control: T, |
1321 | | } |
1322 | | |
1323 | | type ArrayPartsSized<A, D> = ArrayParts<A, D, [usize; 0]>; |
1324 | | type ArrayPartsUnsized<A, D> = ArrayParts<A, D, [usize]>; |
1325 | | |
1326 | | impl<A, D> ArrayPartsSized<A, D> |
1327 | | { |
1328 | 0 | const fn new(ptr: NonNull<A>, dim: D, strides: D) -> ArrayPartsSized<A, D> |
1329 | | { |
1330 | 0 | Self { |
1331 | 0 | ptr, |
1332 | 0 | dim, |
1333 | 0 | strides, |
1334 | 0 | _dst_control: [], |
1335 | 0 | } |
1336 | 0 | } Unexecuted instantiation: <ndarray::ArrayParts<core::mem::maybe_uninit::MaybeUninit<f64>, ndarray::dimension::dim::Dim<[usize; 1]>, [usize; 0]>>::new Unexecuted instantiation: <ndarray::ArrayParts<core::mem::maybe_uninit::MaybeUninit<f32>, ndarray::dimension::dim::Dim<[usize; 1]>, [usize; 0]>>::new Unexecuted instantiation: <ndarray::ArrayParts<f64, ndarray::dimension::dim::Dim<[usize; 0]>, [usize; 0]>>::new Unexecuted instantiation: <ndarray::ArrayParts<f64, ndarray::dimension::dim::Dim<ndarray::dimension::dynindeximpl::IxDynImpl>, [usize; 0]>>::new Unexecuted instantiation: <ndarray::ArrayParts<f32, ndarray::dimension::dim::Dim<[usize; 0]>, [usize; 0]>>::new Unexecuted instantiation: <ndarray::ArrayParts<f32, ndarray::dimension::dim::Dim<ndarray::dimension::dynindeximpl::IxDynImpl>, [usize; 0]>>::new Unexecuted instantiation: <ndarray::ArrayParts<i32, ndarray::dimension::dim::Dim<[usize; 0]>, [usize; 0]>>::new Unexecuted instantiation: <ndarray::ArrayParts<i32, ndarray::dimension::dim::Dim<[usize; 1]>, [usize; 0]>>::new Unexecuted instantiation: <ndarray::ArrayParts<i32, ndarray::dimension::dim::Dim<ndarray::dimension::dynindeximpl::IxDynImpl>, [usize; 0]>>::new Unexecuted instantiation: <ndarray::ArrayParts<i16, ndarray::dimension::dim::Dim<[usize; 0]>, [usize; 0]>>::new Unexecuted instantiation: <ndarray::ArrayParts<i16, ndarray::dimension::dim::Dim<[usize; 1]>, [usize; 0]>>::new Unexecuted instantiation: <ndarray::ArrayParts<i16, ndarray::dimension::dim::Dim<ndarray::dimension::dynindeximpl::IxDynImpl>, [usize; 0]>>::new Unexecuted instantiation: <ndarray::ArrayParts<i64, ndarray::dimension::dim::Dim<[usize; 0]>, [usize; 0]>>::new Unexecuted instantiation: <ndarray::ArrayParts<i64, ndarray::dimension::dim::Dim<[usize; 1]>, [usize; 0]>>::new Unexecuted instantiation: <ndarray::ArrayParts<i64, ndarray::dimension::dim::Dim<ndarray::dimension::dynindeximpl::IxDynImpl>, [usize; 0]>>::new Unexecuted instantiation: <ndarray::ArrayParts<noisy_float::NoisyFloat<f64, noisy_float::checkers::NumChecker>, ndarray::dimension::dim::Dim<[usize; 1]>, [usize; 0]>>::new Unexecuted instantiation: <ndarray::ArrayParts<noisy_float::NoisyFloat<f32, noisy_float::checkers::NumChecker>, ndarray::dimension::dim::Dim<[usize; 1]>, [usize; 0]>>::new Unexecuted instantiation: <ndarray::ArrayParts<core::option::Option<noisy_float::NoisyFloat<f64, noisy_float::checkers::NumChecker>>, ndarray::dimension::dim::Dim<[usize; 1]>, [usize; 0]>>::new Unexecuted instantiation: <ndarray::ArrayParts<core::option::Option<noisy_float::NoisyFloat<f32, noisy_float::checkers::NumChecker>>, ndarray::dimension::dim::Dim<[usize; 1]>, [usize; 0]>>::new Unexecuted instantiation: <ndarray::ArrayParts<core::option::Option<i8>, ndarray::dimension::dim::Dim<[usize; 1]>, [usize; 0]>>::new Unexecuted instantiation: <ndarray::ArrayParts<core::option::Option<u8>, ndarray::dimension::dim::Dim<[usize; 1]>, [usize; 0]>>::new Unexecuted instantiation: <ndarray::ArrayParts<core::option::Option<i32>, ndarray::dimension::dim::Dim<[usize; 1]>, [usize; 0]>>::new Unexecuted instantiation: <ndarray::ArrayParts<core::option::Option<u32>, ndarray::dimension::dim::Dim<[usize; 1]>, [usize; 0]>>::new Unexecuted instantiation: <ndarray::ArrayParts<core::option::Option<i128>, ndarray::dimension::dim::Dim<[usize; 1]>, [usize; 0]>>::new Unexecuted instantiation: <ndarray::ArrayParts<core::option::Option<u128>, ndarray::dimension::dim::Dim<[usize; 1]>, [usize; 0]>>::new Unexecuted instantiation: <ndarray::ArrayParts<core::option::Option<i16>, ndarray::dimension::dim::Dim<[usize; 1]>, [usize; 0]>>::new Unexecuted instantiation: <ndarray::ArrayParts<core::option::Option<u16>, ndarray::dimension::dim::Dim<[usize; 1]>, [usize; 0]>>::new Unexecuted instantiation: <ndarray::ArrayParts<core::option::Option<i64>, ndarray::dimension::dim::Dim<[usize; 1]>, [usize; 0]>>::new Unexecuted instantiation: <ndarray::ArrayParts<core::option::Option<u64>, ndarray::dimension::dim::Dim<[usize; 1]>, [usize; 0]>>::new Unexecuted instantiation: <ndarray::ArrayParts<ndarray_stats::maybe_nan::NotNone<noisy_float::NoisyFloat<f64, noisy_float::checkers::NumChecker>>, ndarray::dimension::dim::Dim<[usize; 1]>, [usize; 0]>>::new Unexecuted instantiation: <ndarray::ArrayParts<ndarray_stats::maybe_nan::NotNone<noisy_float::NoisyFloat<f32, noisy_float::checkers::NumChecker>>, ndarray::dimension::dim::Dim<[usize; 1]>, [usize; 0]>>::new Unexecuted instantiation: <ndarray::ArrayParts<ndarray_stats::maybe_nan::NotNone<i8>, ndarray::dimension::dim::Dim<[usize; 1]>, [usize; 0]>>::new Unexecuted instantiation: <ndarray::ArrayParts<ndarray_stats::maybe_nan::NotNone<u8>, ndarray::dimension::dim::Dim<[usize; 1]>, [usize; 0]>>::new Unexecuted instantiation: <ndarray::ArrayParts<ndarray_stats::maybe_nan::NotNone<i32>, ndarray::dimension::dim::Dim<[usize; 1]>, [usize; 0]>>::new Unexecuted instantiation: <ndarray::ArrayParts<ndarray_stats::maybe_nan::NotNone<u32>, ndarray::dimension::dim::Dim<[usize; 1]>, [usize; 0]>>::new Unexecuted instantiation: <ndarray::ArrayParts<ndarray_stats::maybe_nan::NotNone<i128>, ndarray::dimension::dim::Dim<[usize; 1]>, [usize; 0]>>::new Unexecuted instantiation: <ndarray::ArrayParts<ndarray_stats::maybe_nan::NotNone<u128>, ndarray::dimension::dim::Dim<[usize; 1]>, [usize; 0]>>::new Unexecuted instantiation: <ndarray::ArrayParts<ndarray_stats::maybe_nan::NotNone<i16>, ndarray::dimension::dim::Dim<[usize; 1]>, [usize; 0]>>::new Unexecuted instantiation: <ndarray::ArrayParts<ndarray_stats::maybe_nan::NotNone<u16>, ndarray::dimension::dim::Dim<[usize; 1]>, [usize; 0]>>::new Unexecuted instantiation: <ndarray::ArrayParts<ndarray_stats::maybe_nan::NotNone<i64>, ndarray::dimension::dim::Dim<[usize; 1]>, [usize; 0]>>::new Unexecuted instantiation: <ndarray::ArrayParts<ndarray_stats::maybe_nan::NotNone<u64>, ndarray::dimension::dim::Dim<[usize; 1]>, [usize; 0]>>::new Unexecuted instantiation: <ndarray::ArrayParts<f64, ndarray::dimension::dim::Dim<[usize; 1]>, [usize; 0]>>::new Unexecuted instantiation: <ndarray::ArrayParts<f32, ndarray::dimension::dim::Dim<[usize; 1]>, [usize; 0]>>::new Unexecuted instantiation: <ndarray::ArrayParts<_, _, [usize; 0]>>::new |
1337 | | } |
1338 | | |
1339 | | /// A reference to the layout of an *n*-dimensional array. |
1340 | | /// |
1341 | | /// This type can be used to read and write to the layout of an array; |
1342 | | /// that is to say, its shape and strides. It does not provide any read |
1343 | | /// or write access to the array's underlying data. It is generic on two |
1344 | | /// types: `D`, its dimensionality, and `A`, the element type of its data. |
1345 | | /// |
1346 | | /// ## Example |
1347 | | /// Say we wanted to write a function that provides the aspect ratio |
1348 | | /// of any 2D array: the ratio of its width (number of columns) to its |
1349 | | /// height (number of rows). We would write that as follows: |
1350 | | /// ```rust |
1351 | | /// use ndarray::{LayoutRef2, array}; |
1352 | | /// |
1353 | | /// fn aspect_ratio<T, A>(layout: &T) -> (usize, usize) |
1354 | | /// where T: AsRef<LayoutRef2<A>> + ?Sized |
1355 | | /// { |
1356 | | /// let layout = layout.as_ref(); |
1357 | | /// (layout.ncols(), layout.nrows()) |
1358 | | /// } |
1359 | | /// |
1360 | | /// let arr = array![[1, 2], [3, 4]]; |
1361 | | /// assert_eq!(aspect_ratio(&arr), (2, 2)); |
1362 | | /// ``` |
1363 | | /// Similarly, new traits that provide functions that only depend on |
1364 | | /// or alter the layout of an array should do so via a blanket |
1365 | | /// implementation. Lets write a trait that both provides the aspect ratio |
1366 | | /// and lets users cut down arrays to a desired aspect ratio. |
1367 | | /// For simplicity, we'll panic if the user provides an aspect ratio |
1368 | | /// where either element is larger than the array's size. |
1369 | | /// ```rust |
1370 | | /// use ndarray::{LayoutRef2, array, s}; |
1371 | | /// |
1372 | | /// trait Ratioable<A> { |
1373 | | /// fn aspect_ratio(&self) -> (usize, usize) |
1374 | | /// where Self: AsRef<LayoutRef2<A>>; |
1375 | | /// |
1376 | | /// fn cut_to_ratio(&mut self, ratio: (usize, usize)) |
1377 | | /// where Self: AsMut<LayoutRef2<A>>; |
1378 | | /// } |
1379 | | /// |
1380 | | /// impl<T, A> Ratioable<A> for T |
1381 | | /// where T: AsRef<LayoutRef2<A>> + AsMut<LayoutRef2<A>> + ?Sized |
1382 | | /// { |
1383 | | /// fn aspect_ratio(&self) -> (usize, usize) |
1384 | | /// { |
1385 | | /// let layout = self.as_ref(); |
1386 | | /// (layout.ncols(), layout.nrows()) |
1387 | | /// } |
1388 | | /// |
1389 | | /// fn cut_to_ratio(&mut self, ratio: (usize, usize)) |
1390 | | /// { |
1391 | | /// let layout = self.as_mut(); |
1392 | | /// layout.slice_collapse(s![..ratio.1, ..ratio.0]); |
1393 | | /// } |
1394 | | /// } |
1395 | | /// |
1396 | | /// let mut arr = array![[1, 2, 3], [4, 5, 6]]; |
1397 | | /// assert_eq!(arr.aspect_ratio(), (3, 2)); |
1398 | | /// arr.cut_to_ratio((2, 2)); |
1399 | | /// assert_eq!(arr, array![[1, 2], [4, 5]]); |
1400 | | /// ``` |
1401 | | /// Continue reading for why we use `AsRef` instead of taking `&LayoutRef` directly. |
1402 | | /// |
1403 | | /// ## Writing Functions |
1404 | | /// Writing functions that accept `LayoutRef` is not as simple as taking |
1405 | | /// a `&LayoutRef` argument, as the above examples show. This is because |
1406 | | /// `LayoutRef` can be obtained either cheaply or expensively, depending |
1407 | | /// on the method used. `LayoutRef` can be obtained from all kinds of arrays |
1408 | | /// -- [owned](Array), [shared](ArcArray), [viewed](ArrayView), [referenced](ArrayRef), |
1409 | | /// and [raw referenced](RawRef) -- via `.as_ref()`. Critically, this way of |
1410 | | /// obtaining a `LayoutRef` is cheap, as it does not guarantee that the |
1411 | | /// underlying data is uniquely held. |
1412 | | /// |
1413 | | /// However, `LayoutRef`s can be obtained a second way: they sit at the bottom |
1414 | | /// of a "deref chain" going from shared arrays, through `ArrayRef`, through |
1415 | | /// `RawRef`, and finally to `LayoutRef`. As a result, `LayoutRef`s can also |
1416 | | /// be obtained via auto-dereferencing. When requesting a mutable reference -- |
1417 | | /// `&mut LayoutRef` -- the `deref_mut` to `ArrayRef` triggers a (possibly |
1418 | | /// expensive) guarantee that the data is uniquely held (see [`ArrayRef`] |
1419 | | /// for more information). |
1420 | | /// |
1421 | | /// To help users avoid this cost, functions that operate on `LayoutRef`s |
1422 | | /// should take their parameters as a generic type `T: AsRef<LayoutRef<A, D>>`, |
1423 | | /// as the above examples show. This aids the caller in two ways: they can pass |
1424 | | /// their arrays by reference (`&arr`) instead of explicitly calling `as_ref`, |
1425 | | /// and they will avoid paying a performance penalty for mutating the shape. |
1426 | | // |
1427 | | // # Safety for Implementors |
1428 | | // |
1429 | | // Despite carrying around a `ptr`, maintainers of `LayoutRef` |
1430 | | // must *guarantee* that the pointer is *never* dereferenced. |
1431 | | // No read access can be used when handling a `LayoutRef`, and |
1432 | | // the `ptr` can *never* be exposed to the user. |
1433 | | // |
1434 | | // The reason the pointer is included here is because some methods |
1435 | | // which alter the layout / shape / strides of an array must also |
1436 | | // alter the offset of the pointer. This is allowed, as it does not |
1437 | | // cause a pointer deref. |
1438 | | #[repr(transparent)] |
1439 | | pub struct LayoutRef<A, D>(ArrayPartsUnsized<A, D>); |
1440 | | |
1441 | | impl<A, D> LayoutRef<A, D> |
1442 | | { |
1443 | | /// Get a reference to the data pointer. |
1444 | 0 | fn _ptr(&self) -> &NonNull<A> |
1445 | | { |
1446 | 0 | &self.0.ptr |
1447 | 0 | } Unexecuted instantiation: <ndarray::LayoutRef<core::mem::maybe_uninit::MaybeUninit<f64>, ndarray::dimension::dim::Dim<[usize; 1]>>>::_ptr Unexecuted instantiation: <ndarray::LayoutRef<core::mem::maybe_uninit::MaybeUninit<f32>, ndarray::dimension::dim::Dim<[usize; 1]>>>::_ptr Unexecuted instantiation: <ndarray::LayoutRef<f64, ndarray::dimension::dim::Dim<ndarray::dimension::dynindeximpl::IxDynImpl>>>::_ptr Unexecuted instantiation: <ndarray::LayoutRef<f32, ndarray::dimension::dim::Dim<ndarray::dimension::dynindeximpl::IxDynImpl>>>::_ptr Unexecuted instantiation: <ndarray::LayoutRef<i32, ndarray::dimension::dim::Dim<[usize; 1]>>>::_ptr Unexecuted instantiation: <ndarray::LayoutRef<i32, ndarray::dimension::dim::Dim<ndarray::dimension::dynindeximpl::IxDynImpl>>>::_ptr Unexecuted instantiation: <ndarray::LayoutRef<i16, ndarray::dimension::dim::Dim<[usize; 1]>>>::_ptr Unexecuted instantiation: <ndarray::LayoutRef<i16, ndarray::dimension::dim::Dim<ndarray::dimension::dynindeximpl::IxDynImpl>>>::_ptr Unexecuted instantiation: <ndarray::LayoutRef<i64, ndarray::dimension::dim::Dim<[usize; 1]>>>::_ptr Unexecuted instantiation: <ndarray::LayoutRef<i64, ndarray::dimension::dim::Dim<ndarray::dimension::dynindeximpl::IxDynImpl>>>::_ptr Unexecuted instantiation: <ndarray::LayoutRef<noisy_float::NoisyFloat<f64, noisy_float::checkers::NumChecker>, ndarray::dimension::dim::Dim<[usize; 1]>>>::_ptr Unexecuted instantiation: <ndarray::LayoutRef<noisy_float::NoisyFloat<f32, noisy_float::checkers::NumChecker>, ndarray::dimension::dim::Dim<[usize; 1]>>>::_ptr Unexecuted instantiation: <ndarray::LayoutRef<core::option::Option<noisy_float::NoisyFloat<f64, noisy_float::checkers::NumChecker>>, ndarray::dimension::dim::Dim<[usize; 1]>>>::_ptr Unexecuted instantiation: <ndarray::LayoutRef<core::option::Option<noisy_float::NoisyFloat<f32, noisy_float::checkers::NumChecker>>, ndarray::dimension::dim::Dim<[usize; 1]>>>::_ptr Unexecuted instantiation: <ndarray::LayoutRef<core::option::Option<i8>, ndarray::dimension::dim::Dim<[usize; 1]>>>::_ptr Unexecuted instantiation: <ndarray::LayoutRef<core::option::Option<u8>, ndarray::dimension::dim::Dim<[usize; 1]>>>::_ptr Unexecuted instantiation: <ndarray::LayoutRef<core::option::Option<i32>, ndarray::dimension::dim::Dim<[usize; 1]>>>::_ptr Unexecuted instantiation: <ndarray::LayoutRef<core::option::Option<u32>, ndarray::dimension::dim::Dim<[usize; 1]>>>::_ptr Unexecuted instantiation: <ndarray::LayoutRef<core::option::Option<i128>, ndarray::dimension::dim::Dim<[usize; 1]>>>::_ptr Unexecuted instantiation: <ndarray::LayoutRef<core::option::Option<u128>, ndarray::dimension::dim::Dim<[usize; 1]>>>::_ptr Unexecuted instantiation: <ndarray::LayoutRef<core::option::Option<i16>, ndarray::dimension::dim::Dim<[usize; 1]>>>::_ptr Unexecuted instantiation: <ndarray::LayoutRef<core::option::Option<u16>, ndarray::dimension::dim::Dim<[usize; 1]>>>::_ptr Unexecuted instantiation: <ndarray::LayoutRef<core::option::Option<i64>, ndarray::dimension::dim::Dim<[usize; 1]>>>::_ptr Unexecuted instantiation: <ndarray::LayoutRef<core::option::Option<u64>, ndarray::dimension::dim::Dim<[usize; 1]>>>::_ptr Unexecuted instantiation: <ndarray::LayoutRef<f64, ndarray::dimension::dim::Dim<[usize; 1]>>>::_ptr Unexecuted instantiation: <ndarray::LayoutRef<f32, ndarray::dimension::dim::Dim<[usize; 1]>>>::_ptr Unexecuted instantiation: <ndarray::LayoutRef<_, _>>::_ptr |
1448 | | |
1449 | | /// Get a reference to the array's dimension. |
1450 | 0 | fn _dim(&self) -> &D |
1451 | | { |
1452 | 0 | &self.0.dim |
1453 | 0 | } Unexecuted instantiation: <ndarray::LayoutRef<core::mem::maybe_uninit::MaybeUninit<f64>, ndarray::dimension::dim::Dim<[usize; 1]>>>::_dim Unexecuted instantiation: <ndarray::LayoutRef<core::mem::maybe_uninit::MaybeUninit<f32>, ndarray::dimension::dim::Dim<[usize; 1]>>>::_dim Unexecuted instantiation: <ndarray::LayoutRef<f64, ndarray::dimension::dim::Dim<ndarray::dimension::dynindeximpl::IxDynImpl>>>::_dim Unexecuted instantiation: <ndarray::LayoutRef<f32, ndarray::dimension::dim::Dim<ndarray::dimension::dynindeximpl::IxDynImpl>>>::_dim Unexecuted instantiation: <ndarray::LayoutRef<i32, ndarray::dimension::dim::Dim<[usize; 1]>>>::_dim Unexecuted instantiation: <ndarray::LayoutRef<i32, ndarray::dimension::dim::Dim<ndarray::dimension::dynindeximpl::IxDynImpl>>>::_dim Unexecuted instantiation: <ndarray::LayoutRef<i16, ndarray::dimension::dim::Dim<[usize; 1]>>>::_dim Unexecuted instantiation: <ndarray::LayoutRef<i16, ndarray::dimension::dim::Dim<ndarray::dimension::dynindeximpl::IxDynImpl>>>::_dim Unexecuted instantiation: <ndarray::LayoutRef<i64, ndarray::dimension::dim::Dim<[usize; 1]>>>::_dim Unexecuted instantiation: <ndarray::LayoutRef<i64, ndarray::dimension::dim::Dim<ndarray::dimension::dynindeximpl::IxDynImpl>>>::_dim Unexecuted instantiation: <ndarray::LayoutRef<noisy_float::NoisyFloat<f64, noisy_float::checkers::NumChecker>, ndarray::dimension::dim::Dim<[usize; 1]>>>::_dim Unexecuted instantiation: <ndarray::LayoutRef<noisy_float::NoisyFloat<f32, noisy_float::checkers::NumChecker>, ndarray::dimension::dim::Dim<[usize; 1]>>>::_dim Unexecuted instantiation: <ndarray::LayoutRef<core::option::Option<noisy_float::NoisyFloat<f64, noisy_float::checkers::NumChecker>>, ndarray::dimension::dim::Dim<[usize; 1]>>>::_dim Unexecuted instantiation: <ndarray::LayoutRef<core::option::Option<noisy_float::NoisyFloat<f32, noisy_float::checkers::NumChecker>>, ndarray::dimension::dim::Dim<[usize; 1]>>>::_dim Unexecuted instantiation: <ndarray::LayoutRef<core::option::Option<i8>, ndarray::dimension::dim::Dim<[usize; 1]>>>::_dim Unexecuted instantiation: <ndarray::LayoutRef<core::option::Option<u8>, ndarray::dimension::dim::Dim<[usize; 1]>>>::_dim Unexecuted instantiation: <ndarray::LayoutRef<core::option::Option<i32>, ndarray::dimension::dim::Dim<[usize; 1]>>>::_dim Unexecuted instantiation: <ndarray::LayoutRef<core::option::Option<u32>, ndarray::dimension::dim::Dim<[usize; 1]>>>::_dim Unexecuted instantiation: <ndarray::LayoutRef<core::option::Option<i128>, ndarray::dimension::dim::Dim<[usize; 1]>>>::_dim Unexecuted instantiation: <ndarray::LayoutRef<core::option::Option<u128>, ndarray::dimension::dim::Dim<[usize; 1]>>>::_dim Unexecuted instantiation: <ndarray::LayoutRef<core::option::Option<i16>, ndarray::dimension::dim::Dim<[usize; 1]>>>::_dim Unexecuted instantiation: <ndarray::LayoutRef<core::option::Option<u16>, ndarray::dimension::dim::Dim<[usize; 1]>>>::_dim Unexecuted instantiation: <ndarray::LayoutRef<core::option::Option<i64>, ndarray::dimension::dim::Dim<[usize; 1]>>>::_dim Unexecuted instantiation: <ndarray::LayoutRef<core::option::Option<u64>, ndarray::dimension::dim::Dim<[usize; 1]>>>::_dim Unexecuted instantiation: <ndarray::LayoutRef<f64, ndarray::dimension::dim::Dim<[usize; 1]>>>::_dim Unexecuted instantiation: <ndarray::LayoutRef<f32, ndarray::dimension::dim::Dim<[usize; 1]>>>::_dim Unexecuted instantiation: <ndarray::LayoutRef<_, _>>::_dim |
1454 | | |
1455 | | /// Get a reference to the array's strides. |
1456 | 0 | fn _strides(&self) -> &D |
1457 | | { |
1458 | 0 | &self.0.strides |
1459 | 0 | } Unexecuted instantiation: <ndarray::LayoutRef<core::mem::maybe_uninit::MaybeUninit<f64>, ndarray::dimension::dim::Dim<[usize; 1]>>>::_strides Unexecuted instantiation: <ndarray::LayoutRef<core::mem::maybe_uninit::MaybeUninit<f32>, ndarray::dimension::dim::Dim<[usize; 1]>>>::_strides Unexecuted instantiation: <ndarray::LayoutRef<f64, ndarray::dimension::dim::Dim<ndarray::dimension::dynindeximpl::IxDynImpl>>>::_strides Unexecuted instantiation: <ndarray::LayoutRef<f32, ndarray::dimension::dim::Dim<ndarray::dimension::dynindeximpl::IxDynImpl>>>::_strides Unexecuted instantiation: <ndarray::LayoutRef<i32, ndarray::dimension::dim::Dim<[usize; 1]>>>::_strides Unexecuted instantiation: <ndarray::LayoutRef<i32, ndarray::dimension::dim::Dim<ndarray::dimension::dynindeximpl::IxDynImpl>>>::_strides Unexecuted instantiation: <ndarray::LayoutRef<i16, ndarray::dimension::dim::Dim<[usize; 1]>>>::_strides Unexecuted instantiation: <ndarray::LayoutRef<i16, ndarray::dimension::dim::Dim<ndarray::dimension::dynindeximpl::IxDynImpl>>>::_strides Unexecuted instantiation: <ndarray::LayoutRef<i64, ndarray::dimension::dim::Dim<[usize; 1]>>>::_strides Unexecuted instantiation: <ndarray::LayoutRef<i64, ndarray::dimension::dim::Dim<ndarray::dimension::dynindeximpl::IxDynImpl>>>::_strides Unexecuted instantiation: <ndarray::LayoutRef<noisy_float::NoisyFloat<f64, noisy_float::checkers::NumChecker>, ndarray::dimension::dim::Dim<[usize; 1]>>>::_strides Unexecuted instantiation: <ndarray::LayoutRef<noisy_float::NoisyFloat<f32, noisy_float::checkers::NumChecker>, ndarray::dimension::dim::Dim<[usize; 1]>>>::_strides Unexecuted instantiation: <ndarray::LayoutRef<core::option::Option<noisy_float::NoisyFloat<f64, noisy_float::checkers::NumChecker>>, ndarray::dimension::dim::Dim<[usize; 1]>>>::_strides Unexecuted instantiation: <ndarray::LayoutRef<core::option::Option<noisy_float::NoisyFloat<f32, noisy_float::checkers::NumChecker>>, ndarray::dimension::dim::Dim<[usize; 1]>>>::_strides Unexecuted instantiation: <ndarray::LayoutRef<core::option::Option<i8>, ndarray::dimension::dim::Dim<[usize; 1]>>>::_strides Unexecuted instantiation: <ndarray::LayoutRef<core::option::Option<u8>, ndarray::dimension::dim::Dim<[usize; 1]>>>::_strides Unexecuted instantiation: <ndarray::LayoutRef<core::option::Option<i32>, ndarray::dimension::dim::Dim<[usize; 1]>>>::_strides Unexecuted instantiation: <ndarray::LayoutRef<core::option::Option<u32>, ndarray::dimension::dim::Dim<[usize; 1]>>>::_strides Unexecuted instantiation: <ndarray::LayoutRef<core::option::Option<i128>, ndarray::dimension::dim::Dim<[usize; 1]>>>::_strides Unexecuted instantiation: <ndarray::LayoutRef<core::option::Option<u128>, ndarray::dimension::dim::Dim<[usize; 1]>>>::_strides Unexecuted instantiation: <ndarray::LayoutRef<core::option::Option<i16>, ndarray::dimension::dim::Dim<[usize; 1]>>>::_strides Unexecuted instantiation: <ndarray::LayoutRef<core::option::Option<u16>, ndarray::dimension::dim::Dim<[usize; 1]>>>::_strides Unexecuted instantiation: <ndarray::LayoutRef<core::option::Option<i64>, ndarray::dimension::dim::Dim<[usize; 1]>>>::_strides Unexecuted instantiation: <ndarray::LayoutRef<core::option::Option<u64>, ndarray::dimension::dim::Dim<[usize; 1]>>>::_strides Unexecuted instantiation: <ndarray::LayoutRef<f64, ndarray::dimension::dim::Dim<[usize; 1]>>>::_strides Unexecuted instantiation: <ndarray::LayoutRef<f32, ndarray::dimension::dim::Dim<[usize; 1]>>>::_strides Unexecuted instantiation: <ndarray::LayoutRef<_, _>>::_strides |
1460 | | } |
1461 | | |
1462 | | /// A reference to an *n*-dimensional array whose data is safe to read and write. |
1463 | | /// |
1464 | | /// This type's relationship to [`ArrayBase`] can be thought of a bit like the |
1465 | | /// relationship between [`Vec`] and [`std::slice`]: it represents a look into the |
1466 | | /// array, and is the [`Deref`](std::ops::Deref) target for owned, shared, and viewed |
1467 | | /// arrays. Most functionality is implemented on `ArrayRef`, and most functions |
1468 | | /// should take `&ArrayRef` instead of `&ArrayBase`. |
1469 | | /// |
1470 | | /// ## Relationship to Views |
1471 | | /// `ArrayRef` and [`ArrayView`] are very similar types: they both represent a |
1472 | | /// "look" into an array. There is one key difference: views have their own |
1473 | | /// shape and strides, while `ArrayRef` just points to the shape and strides of |
1474 | | /// whatever array it came from. |
1475 | | /// |
1476 | | /// As an example, let's write a function that takes an array, trims it |
1477 | | /// down to a square in-place, and then returns the sum: |
1478 | | /// ```rust |
1479 | | /// use std::cmp; |
1480 | | /// use std::ops::Add; |
1481 | | /// |
1482 | | /// use ndarray::{ArrayRef2, array, s}; |
1483 | | /// use num_traits::Zero; |
1484 | | /// |
1485 | | /// fn square_and_sum<A>(arr: &mut ArrayRef2<A>) -> A |
1486 | | /// where A: Clone + Add<Output = A> + Zero |
1487 | | /// { |
1488 | | /// let side_len = cmp::min(arr.nrows(), arr.ncols()); |
1489 | | /// arr.slice_collapse(s![..side_len, ..side_len]); |
1490 | | /// arr.sum() |
1491 | | /// } |
1492 | | /// |
1493 | | /// let mut arr = array![ |
1494 | | /// [ 1, 2, 3], |
1495 | | /// [ 4, 5, 6], |
1496 | | /// [ 7, 8, 9], |
1497 | | /// [10, 11, 12] |
1498 | | /// ]; |
1499 | | /// // Take a view of the array, excluding the first column |
1500 | | /// let mut view = arr.slice_mut(s![.., 1..]); |
1501 | | /// let sum_view = square_and_sum(&mut view); |
1502 | | /// assert_eq!(sum_view, 16); |
1503 | | /// assert_eq!(view.ncols(), 2usize); // The view has changed shape... |
1504 | | /// assert_eq!(view.nrows(), 2usize); |
1505 | | /// assert_eq!(arr.ncols(), 3usize); // ... but the original array has not |
1506 | | /// assert_eq!(arr.nrows(), 4usize); |
1507 | | /// |
1508 | | /// let sum_all = square_and_sum(&mut arr); |
1509 | | /// assert_eq!(sum_all, 45); |
1510 | | /// assert_eq!(arr.ncols(), 3usize); // Now the original array has changed shape |
1511 | | /// assert_eq!(arr.nrows(), 3usize); // because we passed it directly to the function |
1512 | | /// ``` |
1513 | | /// Critically, we can call the same function on both the view and the array itself. |
1514 | | /// We can see that, because the view has its own shape and strides, "squaring" it does |
1515 | | /// not affect the shape of the original array. Those only change when we pass the array |
1516 | | /// itself into the function. |
1517 | | /// |
1518 | | /// Also notice that the output of `slice_mut` is a *view*, not an `ArrayRef`. |
1519 | | /// This is where the analogy to `Vec`/`slice` breaks down a bit: due to limitations of |
1520 | | /// the Rust language, `ArrayRef` *cannot* have a different shape / stride from the |
1521 | | /// array from which it is dereferenced. So slicing still produces an `ArrayView`, |
1522 | | /// not an `ArrayRef`. |
1523 | | /// |
1524 | | /// ## Uniqueness |
1525 | | /// `ndarray` has copy-on-write shared data; see [`ArcArray`], for example. |
1526 | | /// When a copy-on-write array is passed to a function that takes `ArrayRef` as mutable |
1527 | | /// (i.e., `&mut ArrayRef`, like above), that array will be un-shared when it is dereferenced |
1528 | | /// into `ArrayRef`. In other words, having a `&mut ArrayRef` guarantees that the underlying |
1529 | | /// data is un-shared and safe to write to. |
1530 | | #[repr(transparent)] |
1531 | | pub struct ArrayRef<A, D>(LayoutRef<A, D>); |
1532 | | |
1533 | | /// A reference to an *n*-dimensional array whose data is not safe to read or write. |
1534 | | /// |
1535 | | /// This type is similar to [`ArrayRef`] but does not guarantee that its data is safe |
1536 | | /// to read or write; i.e., the underlying data may come from a shared array or be otherwise |
1537 | | /// unsafe to dereference. This type should be used sparingly and with extreme caution; |
1538 | | /// most of its methods either provide pointers or return [`RawArrayView`], both of |
1539 | | /// which tend to be full of unsafety. |
1540 | | /// |
1541 | | /// For the few times when this type is appropriate, it has the same `AsRef` semantics |
1542 | | /// as [`LayoutRef`]; see [its documentation on writing functions](LayoutRef#writing-functions) |
1543 | | /// for information on how to properly handle functionality on this type. |
1544 | | #[repr(transparent)] |
1545 | | pub struct RawRef<A, D>(LayoutRef<A, D>); |
1546 | | |
1547 | | /// An array where the data has shared ownership and is copy on write. |
1548 | | /// |
1549 | | /// The `ArcArray<A, D>` is parameterized by `A` for the element type and `D` for |
1550 | | /// the dimensionality. |
1551 | | /// |
1552 | | /// It can act as both an owner as the data as well as a shared reference (view |
1553 | | /// like). |
1554 | | /// Calling a method for mutating elements on `ArcArray`, for example |
1555 | | /// [`view_mut()`](ArrayRef::view_mut) or |
1556 | | /// [`get_mut()`](ArrayRef::get_mut), will break sharing and |
1557 | | /// require a clone of the data (if it is not uniquely held). |
1558 | | /// |
1559 | | /// `ArcArray` uses atomic reference counting like `Arc`, so it is `Send` and |
1560 | | /// `Sync` (when allowed by the element type of the array too). |
1561 | | /// |
1562 | | /// **[`ArrayBase`]** is used to implement both the owned |
1563 | | /// arrays and the views; see its docs for an overview of all array features. |
1564 | | /// |
1565 | | /// See also: |
1566 | | /// |
1567 | | /// + [Constructor Methods for Owned Arrays](ArrayBase#constructor-methods-for-owned-arrays) |
1568 | | /// + [Methods For All Array Types](ArrayBase#methods-for-all-array-types) |
1569 | | pub type ArcArray<A, D> = ArrayBase<OwnedArcRepr<A>, D>; |
1570 | | |
1571 | | /// An array that owns its data uniquely. |
1572 | | /// |
1573 | | /// `Array` is the main n-dimensional array type, and it owns all its array |
1574 | | /// elements. |
1575 | | /// |
1576 | | /// The `Array<A, D>` is parameterized by `A` for the element type and `D` for |
1577 | | /// the dimensionality. |
1578 | | /// |
1579 | | /// **[`ArrayBase`]** is used to implement both the owned |
1580 | | /// arrays and the views; see its docs for an overview of all array features. |
1581 | | /// |
1582 | | /// See also: |
1583 | | /// |
1584 | | /// + [Constructor Methods for Owned Arrays](ArrayBase#constructor-methods-for-owned-arrays) |
1585 | | /// + [Methods For All Array Types](ArrayBase#methods-for-all-array-types) |
1586 | | /// + Dimensionality-specific type aliases |
1587 | | /// [`Array1`], |
1588 | | /// [`Array2`], |
1589 | | /// [`Array3`], ..., |
1590 | | /// [`ArrayD`], |
1591 | | /// and so on. |
1592 | | pub type Array<A, D> = ArrayBase<OwnedRepr<A>, D>; |
1593 | | |
1594 | | /// An array with copy-on-write behavior. |
1595 | | /// |
1596 | | /// An `CowArray` represents either a uniquely owned array or a view of an |
1597 | | /// array. The `'a` corresponds to the lifetime of the view variant. |
1598 | | /// |
1599 | | /// This type is analogous to [`std::borrow::Cow`]. |
1600 | | /// If a `CowArray` instance is the immutable view variant, then calling a |
1601 | | /// method for mutating elements in the array will cause it to be converted |
1602 | | /// into the owned variant (by cloning all the elements) before the |
1603 | | /// modification is performed. |
1604 | | /// |
1605 | | /// Array views have all the methods of an array (see [`ArrayBase`]). |
1606 | | /// |
1607 | | /// See also [`ArcArray`], which also provides |
1608 | | /// copy-on-write behavior but has a reference-counted pointer to the data |
1609 | | /// instead of either a view or a uniquely owned copy. |
1610 | | pub type CowArray<'a, A, D> = ArrayBase<CowRepr<'a, A>, D>; |
1611 | | |
1612 | | /// A read-only array view. |
1613 | | /// |
1614 | | /// An array view represents an array or a part of it, created from |
1615 | | /// an iterator, subview or slice of an array. |
1616 | | /// |
1617 | | /// The `ArrayView<'a, A, D>` is parameterized by `'a` for the scope of the |
1618 | | /// borrow, `A` for the element type and `D` for the dimensionality. |
1619 | | /// |
1620 | | /// Array views have all the methods of an array (see [`ArrayBase`]). |
1621 | | /// |
1622 | | /// See also [`ArrayViewMut`]. |
1623 | | pub type ArrayView<'a, A, D> = ArrayBase<ViewRepr<&'a A>, D>; |
1624 | | |
1625 | | /// A read-write array view. |
1626 | | /// |
1627 | | /// An array view represents an array or a part of it, created from |
1628 | | /// an iterator, subview or slice of an array. |
1629 | | /// |
1630 | | /// The `ArrayViewMut<'a, A, D>` is parameterized by `'a` for the scope of the |
1631 | | /// borrow, `A` for the element type and `D` for the dimensionality. |
1632 | | /// |
1633 | | /// Array views have all the methods of an array (see [`ArrayBase`]). |
1634 | | /// |
1635 | | /// See also [`ArrayView`]. |
1636 | | pub type ArrayViewMut<'a, A, D> = ArrayBase<ViewRepr<&'a mut A>, D>; |
1637 | | |
1638 | | /// A read-only array view without a lifetime. |
1639 | | /// |
1640 | | /// This is similar to [`ArrayView`] but does not carry any lifetime or |
1641 | | /// ownership information, and its data cannot be read without an unsafe |
1642 | | /// conversion into an [`ArrayView`]. The relationship between `RawArrayView` |
1643 | | /// and [`ArrayView`] is somewhat analogous to the relationship between `*const |
1644 | | /// T` and `&T`, but `RawArrayView` has additional requirements that `*const T` |
1645 | | /// does not, such as non-nullness. |
1646 | | /// |
1647 | | /// The `RawArrayView<A, D>` is parameterized by `A` for the element type and |
1648 | | /// `D` for the dimensionality. |
1649 | | /// |
1650 | | /// Raw array views have all the methods of an array (see |
1651 | | /// [`ArrayBase`]). |
1652 | | /// |
1653 | | /// See also [`RawArrayViewMut`]. |
1654 | | /// |
1655 | | /// # Warning |
1656 | | /// |
1657 | | /// You can't use this type with an arbitrary raw pointer; see |
1658 | | /// [`from_shape_ptr`](#method.from_shape_ptr) for details. |
1659 | | pub type RawArrayView<A, D> = ArrayBase<RawViewRepr<*const A>, D>; |
1660 | | |
1661 | | /// A mutable array view without a lifetime. |
1662 | | /// |
1663 | | /// This is similar to [`ArrayViewMut`] but does not carry any lifetime or |
1664 | | /// ownership information, and its data cannot be read/written without an |
1665 | | /// unsafe conversion into an [`ArrayViewMut`]. The relationship between |
1666 | | /// `RawArrayViewMut` and [`ArrayViewMut`] is somewhat analogous to the |
1667 | | /// relationship between `*mut T` and `&mut T`, but `RawArrayViewMut` has |
1668 | | /// additional requirements that `*mut T` does not, such as non-nullness. |
1669 | | /// |
1670 | | /// The `RawArrayViewMut<A, D>` is parameterized by `A` for the element type |
1671 | | /// and `D` for the dimensionality. |
1672 | | /// |
1673 | | /// Raw array views have all the methods of an array (see |
1674 | | /// [`ArrayBase`]). |
1675 | | /// |
1676 | | /// See also [`RawArrayView`]. |
1677 | | /// |
1678 | | /// # Warning |
1679 | | /// |
1680 | | /// You can't use this type with an arbitrary raw pointer; see |
1681 | | /// [`from_shape_ptr`](#method.from_shape_ptr) for details. |
1682 | | pub type RawArrayViewMut<A, D> = ArrayBase<RawViewRepr<*mut A>, D>; |
1683 | | |
1684 | | pub use data_repr::OwnedRepr; |
1685 | | |
1686 | | /// ArcArray's representation. |
1687 | | /// |
1688 | | /// *Don’t use this type directly—use the type alias |
1689 | | /// [`ArcArray`] for the array type!* |
1690 | | #[derive(Debug)] |
1691 | | pub struct OwnedArcRepr<A>(Arc<OwnedRepr<A>>); |
1692 | | |
1693 | | impl<A> Clone for OwnedArcRepr<A> |
1694 | | { |
1695 | 0 | fn clone(&self) -> Self |
1696 | | { |
1697 | 0 | OwnedArcRepr(self.0.clone()) |
1698 | 0 | } |
1699 | | } |
1700 | | |
1701 | | /// Array pointer’s representation. |
1702 | | /// |
1703 | | /// *Don’t use this type directly—use the type aliases |
1704 | | /// [`RawArrayView`] / [`RawArrayViewMut`] for the array type!* |
1705 | | #[derive(Copy, Clone)] |
1706 | | // This is just a marker type, to carry the mutability and element type. |
1707 | | pub struct RawViewRepr<A> |
1708 | | { |
1709 | | ptr: PhantomData<A>, |
1710 | | } |
1711 | | |
1712 | | impl<A> RawViewRepr<A> |
1713 | | { |
1714 | | #[inline(always)] |
1715 | 0 | const fn new() -> Self |
1716 | | { |
1717 | 0 | RawViewRepr { ptr: PhantomData } |
1718 | 0 | } Unexecuted instantiation: <ndarray::RawViewRepr<*mut core::mem::maybe_uninit::MaybeUninit<f64>>>::new Unexecuted instantiation: <ndarray::RawViewRepr<*mut core::mem::maybe_uninit::MaybeUninit<f32>>>::new Unexecuted instantiation: <ndarray::RawViewRepr<*mut f64>>::new Unexecuted instantiation: <ndarray::RawViewRepr<*mut f32>>::new Unexecuted instantiation: <ndarray::RawViewRepr<*mut noisy_float::NoisyFloat<f64, noisy_float::checkers::NumChecker>>>::new Unexecuted instantiation: <ndarray::RawViewRepr<*mut noisy_float::NoisyFloat<f32, noisy_float::checkers::NumChecker>>>::new Unexecuted instantiation: <ndarray::RawViewRepr<*mut ndarray_stats::maybe_nan::NotNone<noisy_float::NoisyFloat<f64, noisy_float::checkers::NumChecker>>>>::new Unexecuted instantiation: <ndarray::RawViewRepr<*mut ndarray_stats::maybe_nan::NotNone<noisy_float::NoisyFloat<f32, noisy_float::checkers::NumChecker>>>>::new Unexecuted instantiation: <ndarray::RawViewRepr<*mut ndarray_stats::maybe_nan::NotNone<i8>>>::new Unexecuted instantiation: <ndarray::RawViewRepr<*mut ndarray_stats::maybe_nan::NotNone<u8>>>::new Unexecuted instantiation: <ndarray::RawViewRepr<*mut ndarray_stats::maybe_nan::NotNone<i32>>>::new Unexecuted instantiation: <ndarray::RawViewRepr<*mut ndarray_stats::maybe_nan::NotNone<u32>>>::new Unexecuted instantiation: <ndarray::RawViewRepr<*mut ndarray_stats::maybe_nan::NotNone<i128>>>::new Unexecuted instantiation: <ndarray::RawViewRepr<*mut ndarray_stats::maybe_nan::NotNone<u128>>>::new Unexecuted instantiation: <ndarray::RawViewRepr<*mut ndarray_stats::maybe_nan::NotNone<i16>>>::new Unexecuted instantiation: <ndarray::RawViewRepr<*mut ndarray_stats::maybe_nan::NotNone<u16>>>::new Unexecuted instantiation: <ndarray::RawViewRepr<*mut ndarray_stats::maybe_nan::NotNone<i64>>>::new Unexecuted instantiation: <ndarray::RawViewRepr<*mut ndarray_stats::maybe_nan::NotNone<u64>>>::new Unexecuted instantiation: <ndarray::RawViewRepr<_>>::new |
1719 | | } |
1720 | | |
1721 | | /// Array view’s representation. |
1722 | | /// |
1723 | | /// *Don’t use this type directly—use the type aliases |
1724 | | /// [`ArrayView`] / [`ArrayViewMut`] for the array type!* |
1725 | | #[derive(Copy, Clone)] |
1726 | | // This is just a marker type, to carry the lifetime parameter. |
1727 | | pub struct ViewRepr<A> |
1728 | | { |
1729 | | life: PhantomData<A>, |
1730 | | } |
1731 | | |
1732 | | impl<A> ViewRepr<A> |
1733 | | { |
1734 | | #[inline(always)] |
1735 | 0 | const fn new() -> Self |
1736 | | { |
1737 | 0 | ViewRepr { life: PhantomData } |
1738 | 0 | } Unexecuted instantiation: <ndarray::ViewRepr<&mut core::mem::maybe_uninit::MaybeUninit<f64>>>::new Unexecuted instantiation: <ndarray::ViewRepr<&mut core::mem::maybe_uninit::MaybeUninit<f32>>>::new Unexecuted instantiation: <ndarray::ViewRepr<&f64>>::new Unexecuted instantiation: <ndarray::ViewRepr<&f32>>::new Unexecuted instantiation: <ndarray::ViewRepr<&i32>>::new Unexecuted instantiation: <ndarray::ViewRepr<&i16>>::new Unexecuted instantiation: <ndarray::ViewRepr<&i64>>::new Unexecuted instantiation: <ndarray::ViewRepr<&mut noisy_float::NoisyFloat<f64, noisy_float::checkers::NumChecker>>>::new Unexecuted instantiation: <ndarray::ViewRepr<&mut noisy_float::NoisyFloat<f32, noisy_float::checkers::NumChecker>>>::new Unexecuted instantiation: <ndarray::ViewRepr<&mut ndarray_stats::maybe_nan::NotNone<noisy_float::NoisyFloat<f64, noisy_float::checkers::NumChecker>>>>::new Unexecuted instantiation: <ndarray::ViewRepr<&mut ndarray_stats::maybe_nan::NotNone<noisy_float::NoisyFloat<f32, noisy_float::checkers::NumChecker>>>>::new Unexecuted instantiation: <ndarray::ViewRepr<&mut ndarray_stats::maybe_nan::NotNone<i8>>>::new Unexecuted instantiation: <ndarray::ViewRepr<&mut ndarray_stats::maybe_nan::NotNone<u8>>>::new Unexecuted instantiation: <ndarray::ViewRepr<&mut ndarray_stats::maybe_nan::NotNone<i32>>>::new Unexecuted instantiation: <ndarray::ViewRepr<&mut ndarray_stats::maybe_nan::NotNone<u32>>>::new Unexecuted instantiation: <ndarray::ViewRepr<&mut ndarray_stats::maybe_nan::NotNone<i128>>>::new Unexecuted instantiation: <ndarray::ViewRepr<&mut ndarray_stats::maybe_nan::NotNone<u128>>>::new Unexecuted instantiation: <ndarray::ViewRepr<&mut ndarray_stats::maybe_nan::NotNone<i16>>>::new Unexecuted instantiation: <ndarray::ViewRepr<&mut ndarray_stats::maybe_nan::NotNone<u16>>>::new Unexecuted instantiation: <ndarray::ViewRepr<&mut ndarray_stats::maybe_nan::NotNone<i64>>>::new Unexecuted instantiation: <ndarray::ViewRepr<&mut ndarray_stats::maybe_nan::NotNone<u64>>>::new Unexecuted instantiation: <ndarray::ViewRepr<_>>::new |
1739 | | } |
1740 | | |
1741 | | /// CowArray's representation. |
1742 | | /// |
1743 | | /// *Don't use this type directly—use the type alias |
1744 | | /// [`CowArray`] for the array type!* |
1745 | | pub enum CowRepr<'a, A> |
1746 | | { |
1747 | | /// Borrowed data. |
1748 | | View(ViewRepr<&'a A>), |
1749 | | /// Owned data. |
1750 | | Owned(OwnedRepr<A>), |
1751 | | } |
1752 | | |
1753 | | impl<A> CowRepr<'_, A> |
1754 | | { |
1755 | | /// Returns `true` iff the data is the `View` variant. |
1756 | 0 | pub fn is_view(&self) -> bool |
1757 | | { |
1758 | 0 | match self { |
1759 | 0 | CowRepr::View(_) => true, |
1760 | 0 | CowRepr::Owned(_) => false, |
1761 | | } |
1762 | 0 | } |
1763 | | |
1764 | | /// Returns `true` iff the data is the `Owned` variant. |
1765 | 0 | pub fn is_owned(&self) -> bool |
1766 | | { |
1767 | 0 | match self { |
1768 | 0 | CowRepr::View(_) => false, |
1769 | 0 | CowRepr::Owned(_) => true, |
1770 | | } |
1771 | 0 | } |
1772 | | } |
1773 | | |
1774 | | // NOTE: The order of modules decides in which order methods on the type ArrayBase |
1775 | | // (mainly mentioning that as the most relevant type) show up in the documentation. |
1776 | | // Consider the doc effect of ordering modules here. |
1777 | | mod impl_clone; |
1778 | | |
1779 | | mod impl_internal_constructors; |
1780 | | mod impl_constructors; |
1781 | | |
1782 | | mod impl_methods; |
1783 | | mod alias_asref; |
1784 | | mod impl_owned_array; |
1785 | | mod impl_special_element_types; |
1786 | | |
1787 | | /// Private Methods |
1788 | | impl<A, D: Dimension> ArrayRef<A, D> |
1789 | | { |
1790 | | #[inline] |
1791 | 0 | fn broadcast_unwrap<E>(&self, dim: E) -> ArrayView<'_, A, E> |
1792 | 0 | where E: Dimension |
1793 | | { |
1794 | | #[cold] |
1795 | | #[inline(never)] |
1796 | 0 | fn broadcast_panic<D, E>(from: &D, to: &E) -> ! |
1797 | 0 | where |
1798 | 0 | D: Dimension, |
1799 | 0 | E: Dimension, |
1800 | | { |
1801 | 0 | panic!("ndarray: could not broadcast array from shape: {:?} to: {:?}", from.slice(), to.slice()) |
1802 | | } |
1803 | | |
1804 | 0 | match self.broadcast(dim.clone()) { |
1805 | 0 | Some(it) => it, |
1806 | 0 | None => broadcast_panic(self._dim(), &dim), |
1807 | | } |
1808 | 0 | } |
1809 | | |
1810 | | // Broadcast to dimension `E`, without checking that the dimensions match |
1811 | | // (Checked in debug assertions). |
1812 | | #[inline] |
1813 | 0 | fn broadcast_assume<E>(&self, dim: E) -> ArrayView<'_, A, E> |
1814 | 0 | where E: Dimension |
1815 | | { |
1816 | 0 | let dim = dim.into_dimension(); |
1817 | 0 | debug_assert_eq!(self.shape(), dim.slice()); |
1818 | 0 | let ptr = self._ptr(); |
1819 | 0 | let mut strides = dim.clone(); |
1820 | 0 | strides.slice_mut().copy_from_slice(self._strides().slice()); |
1821 | 0 | unsafe { ArrayView::new(*ptr, dim, strides) } |
1822 | 0 | } |
1823 | | } |
1824 | | |
1825 | | impl<A, S, D> ArrayBase<S, D> |
1826 | | where |
1827 | | S: Data<Elem = A>, |
1828 | | D: Dimension, |
1829 | | { |
1830 | | /// Remove array axis `axis` and return the result. |
1831 | 0 | fn try_remove_axis(self, axis: Axis) -> ArrayBase<S, D::Smaller> |
1832 | | { |
1833 | 0 | let d = self.parts.dim.try_remove_axis(axis); |
1834 | 0 | let s = self.parts.strides.try_remove_axis(axis); |
1835 | | // safe because new dimension, strides allow access to a subset of old data |
1836 | 0 | unsafe { self.with_strides_dim(s, d) } |
1837 | 0 | } Unexecuted instantiation: <ndarray::ArrayBase<ndarray::ViewRepr<&f64>, ndarray::dimension::dim::Dim<[usize; 1]>, f64>>::try_remove_axis Unexecuted instantiation: <ndarray::ArrayBase<ndarray::ViewRepr<&f32>, ndarray::dimension::dim::Dim<[usize; 1]>, f32>>::try_remove_axis Unexecuted instantiation: <ndarray::ArrayBase<ndarray::ViewRepr<&i32>, ndarray::dimension::dim::Dim<[usize; 1]>, i32>>::try_remove_axis Unexecuted instantiation: <ndarray::ArrayBase<ndarray::ViewRepr<&i16>, ndarray::dimension::dim::Dim<[usize; 1]>, i16>>::try_remove_axis Unexecuted instantiation: <ndarray::ArrayBase<ndarray::ViewRepr<&i64>, ndarray::dimension::dim::Dim<[usize; 1]>, i64>>::try_remove_axis Unexecuted instantiation: <ndarray::ArrayBase<_, _, _>>::try_remove_axis |
1838 | | } |
1839 | | |
1840 | | // parallel methods |
1841 | | #[cfg(feature = "rayon")] |
1842 | | pub mod parallel; |
1843 | | |
1844 | | mod impl_1d; |
1845 | | mod impl_2d; |
1846 | | mod impl_dyn; |
1847 | | |
1848 | | mod numeric; |
1849 | | |
1850 | | pub mod linalg; |
1851 | | |
1852 | | mod impl_ops; |
1853 | | pub use crate::impl_ops::ScalarOperand; |
1854 | | |
1855 | | #[cfg(feature = "approx")] |
1856 | | mod array_approx; |
1857 | | |
1858 | | // Array view methods |
1859 | | mod impl_views; |
1860 | | |
1861 | | // Array raw view methods |
1862 | | mod impl_raw_views; |
1863 | | |
1864 | | // Copy-on-write array methods |
1865 | | mod impl_cow; |
1866 | | |
1867 | | // Arc array methods |
1868 | | mod impl_arc_array; |
1869 | | |
1870 | | /// Returns `true` if the pointer is aligned. |
1871 | 0 | pub(crate) fn is_aligned<T>(ptr: *const T) -> bool |
1872 | | { |
1873 | 0 | (ptr as usize) % ::std::mem::align_of::<T>() == 0 |
1874 | 0 | } |
1875 | | |
1876 | | // Triangular constructors |
1877 | | mod tri; |