-
Notifications
You must be signed in to change notification settings - Fork 329
Adds an array reference type #1440
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
34 commits
Select commit
Hold shift + click to select a range
e1ba6ca
Adds an array reference type.
akern40 cdf5012
Adds some documentation
akern40 5a5a39c
Fixes some CI/CD issues
akern40 1acf0e1
More CI/CD fixes
akern40 09800eb
Last CI/CD fix?
akern40 0d0a96a
Switches to the "same-repr" approach to allow array views to still be…
akern40 0f3f8d9
Changes back to Copy-capable ArrayBase and unchanged ArrayBase internals
akern40 fbafbb2
Removes unused import
akern40 52b276e
Introduces LayoutRef and starts to move functionality from ArrayBase …
akern40 a504217
Working version of the conversion to reference types
akern40 aa58113
Uses a new design with two reference types
akern40 9a2edb1
Satisfying CI/CD
akern40 e739d04
Adds Index, equality, IntoIterator, and Hash traits, plus approximates
akern40 fb7d87c
Finishes conversions of all possible ArrayBase impls to ArrayRef
akern40 fb24680
Satisfying CI/CD
akern40 bdc24bd
Adds some aliases to avoid breaking changes, and adds an example of h…
akern40 c72bf8f
Adds Borrow and ToOwned
akern40 2cce543
Tests that the *Assign operators work for slices via deref
akern40 7f70e9e
Somehow missed a `use` for `ToOwned`
akern40 c835680
Implicitly use deref
akern40 03fda7f
Adds documentation and aliases for `LayoutRef`
akern40 407b6c4
Fixes doc links
akern40 a9b5c37
Adds formatting for ArrayRef
akern40 8a26c34
Change some examples over to ArrayRef
akern40 8bb8f39
Adds missed #[repr(transparent)] for RawRef
akern40 775f06b
Simplifies deref logic and avoids null check
akern40 6eed17d
Adds documentation to ArrayRef
akern40 9c9d8c2
Adds missing aliases to ArrayBase from RawRef and LayoutRef
akern40 4e0bcc1
Adds a short snippet of documentation for `RawRef` and some top-level…
akern40 1bb06e7
Makes as_ref more explicit through methods on ArrayBase
akern40 435a9e7
Restore remove_index to DataOwned
akern40 6fd61c1
Fixes unused imports
akern40 0dedc3e
Re-fixes the covariant arrayview with the new reference structure
akern40 a71b509
Fixes the clippy lint and docs broken link
akern40 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,3 +4,6 @@ target/ | |
# Editor settings | ||
.vscode | ||
.idea | ||
|
||
# Apple details | ||
**/.DS_Store |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,178 @@ | ||
//! Examples of how to write functions and traits that operate on `ndarray` types. | ||
nilgoyette marked this conversation as resolved.
Show resolved
Hide resolved
|
||
//! | ||
//! `ndarray` has four kinds of array types that users may interact with: | ||
//! 1. [`ArrayBase`], the owner of the layout that describes an array in memory; | ||
//! this includes [`ndarray::Array`], [`ndarray::ArcArray`], [`ndarray::ArrayView`], | ||
//! [`ndarray::RawArrayView`], and other variants. | ||
//! 2. [`ArrayRef`], which represents a read-safe, uniquely-owned look at an array. | ||
//! 3. [`RawRef`], which represents a read-unsafe, possibly-shared look at an array. | ||
//! 4. [`LayoutRef`], which represents a look at an array's underlying structure, | ||
//! but does not allow data reading of any kind. | ||
//! | ||
//! Below, we illustrate how to write functions and traits for most variants of these types. | ||
|
||
use ndarray::{ArrayBase, ArrayRef, Data, DataMut, Dimension, LayoutRef, RawData, RawDataMut, RawRef}; | ||
|
||
/// Take an array with the most basic requirements. | ||
/// | ||
/// This function takes its data as owning. It is very rare that a user will need to specifically | ||
/// take a reference to an `ArrayBase`, rather than to one of the other four types. | ||
#[rustfmt::skip] | ||
fn takes_base_raw<S: RawData, D>(arr: ArrayBase<S, D>) -> ArrayBase<S, D> | ||
{ | ||
// These skip from a possibly-raw array to `RawRef` and `LayoutRef`, and so must go through `AsRef` | ||
takes_rawref(arr.as_ref()); // Caller uses `.as_ref` | ||
takes_rawref_asref(&arr); // Implementor uses `.as_ref` | ||
takes_layout(arr.as_ref()); // Caller uses `.as_ref` | ||
takes_layout_asref(&arr); // Implementor uses `.as_ref` | ||
|
||
arr | ||
} | ||
|
||
/// Similar to above, but allow us to read the underlying data. | ||
#[rustfmt::skip] | ||
fn takes_base_raw_mut<S: RawDataMut, D>(mut arr: ArrayBase<S, D>) -> ArrayBase<S, D> | ||
{ | ||
// These skip from a possibly-raw array to `RawRef` and `LayoutRef`, and so must go through `AsMut` | ||
takes_rawref_mut(arr.as_mut()); // Caller uses `.as_mut` | ||
takes_rawref_asmut(&mut arr); // Implementor uses `.as_mut` | ||
takes_layout_mut(arr.as_mut()); // Caller uses `.as_mut` | ||
takes_layout_asmut(&mut arr); // Implementor uses `.as_mut` | ||
|
||
arr | ||
} | ||
|
||
/// Now take an array whose data is safe to read. | ||
#[allow(dead_code)] | ||
fn takes_base<S: Data, D>(mut arr: ArrayBase<S, D>) -> ArrayBase<S, D> | ||
{ | ||
// Raw call | ||
arr = takes_base_raw(arr); | ||
|
||
// No need for AsRef, since data is safe | ||
takes_arrref(&arr); | ||
takes_rawref(&arr); | ||
takes_rawref_asref(&arr); | ||
takes_layout(&arr); | ||
takes_layout_asref(&arr); | ||
|
||
arr | ||
} | ||
|
||
/// Now, an array whose data is safe to read and that we can mutate. | ||
/// | ||
/// Notice that we include now a trait bound on `D: Dimension`; this is necessary in order | ||
/// for the `ArrayBase` to dereference to an `ArrayRef` (or to any of the other types). | ||
#[allow(dead_code)] | ||
fn takes_base_mut<S: DataMut, D: Dimension>(mut arr: ArrayBase<S, D>) -> ArrayBase<S, D> | ||
{ | ||
// Raw call | ||
arr = takes_base_raw_mut(arr); | ||
|
||
// No need for AsMut, since data is safe | ||
takes_arrref_mut(&mut arr); | ||
takes_rawref_mut(&mut arr); | ||
takes_rawref_asmut(&mut arr); | ||
takes_layout_mut(&mut arr); | ||
takes_layout_asmut(&mut arr); | ||
|
||
arr | ||
} | ||
|
||
/// Now for new stuff: we want to read (but not alter) any array whose data is safe to read. | ||
/// | ||
/// This is probably the most common functionality that one would want to write. | ||
/// As we'll see below, calling this function is very simple for `ArrayBase<S: Data, D>`. | ||
fn takes_arrref<A, D>(arr: &ArrayRef<A, D>) | ||
{ | ||
// No need for AsRef, since data is safe | ||
takes_rawref(arr); | ||
takes_rawref_asref(arr); | ||
takes_layout(arr); | ||
takes_layout_asref(arr); | ||
} | ||
|
||
/// Now we want any array whose data is safe to mutate. | ||
/// | ||
/// **Importantly**, any array passed to this function is guaranteed to uniquely point to its data. | ||
/// As a result, passing a shared array to this function will **silently** un-share the array. | ||
#[allow(dead_code)] | ||
fn takes_arrref_mut<A, D>(arr: &mut ArrayRef<A, D>) | ||
{ | ||
// Immutable call | ||
takes_arrref(arr); | ||
|
||
// No need for AsMut, since data is safe | ||
takes_rawref_mut(arr); | ||
takes_rawref_asmut(arr); | ||
takes_layout_mut(arr); | ||
takes_rawref_asmut(arr); | ||
} | ||
|
||
/// Now, we no longer care about whether we can safely read data. | ||
/// | ||
/// This is probably the rarest type to deal with, since `LayoutRef` can access and modify an array's | ||
/// shape and strides, and even do in-place slicing. As a result, `RawRef` is only for functionality | ||
/// that requires unsafe data access, something that `LayoutRef` can't do. | ||
/// | ||
/// Writing functions and traits that deal with `RawRef`s and `LayoutRef`s can be done two ways: | ||
/// 1. Directly on the types; calling these functions on arrays whose data are not known to be safe | ||
/// to dereference (i.e., raw array views or `ArrayBase<S: RawData, D>`) must explicitly call `.as_ref()`. | ||
/// 2. Via a generic with `: AsRef<RawRef<A, D>>`; doing this will allow direct calling for all `ArrayBase` and | ||
/// `ArrayRef` instances. | ||
/// We'll demonstrate #1 here for both immutable and mutable references, then #2 directly below. | ||
#[allow(dead_code)] | ||
fn takes_rawref<A, D>(arr: &RawRef<A, D>) | ||
{ | ||
takes_layout(arr); | ||
takes_layout_asref(arr); | ||
} | ||
|
||
/// Mutable, directly take `RawRef` | ||
#[allow(dead_code)] | ||
fn takes_rawref_mut<A, D>(arr: &mut RawRef<A, D>) | ||
{ | ||
takes_layout(arr); | ||
takes_layout_asmut(arr); | ||
} | ||
|
||
/// Immutable, take a generic that implements `AsRef` to `RawRef` | ||
#[allow(dead_code)] | ||
fn takes_rawref_asref<T, A, D>(_arr: &T) | ||
where T: AsRef<RawRef<A, D>> | ||
{ | ||
takes_layout(_arr.as_ref()); | ||
takes_layout_asref(_arr.as_ref()); | ||
} | ||
|
||
/// Mutable, take a generic that implements `AsMut` to `RawRef` | ||
#[allow(dead_code)] | ||
fn takes_rawref_asmut<T, A, D>(_arr: &mut T) | ||
where T: AsMut<RawRef<A, D>> | ||
{ | ||
takes_layout_mut(_arr.as_mut()); | ||
takes_layout_asmut(_arr.as_mut()); | ||
} | ||
|
||
/// Finally, there's `LayoutRef`: this type provides read and write access to an array's *structure*, but not its *data*. | ||
/// | ||
/// Practically, this means that functions that only read/modify an array's shape or strides, | ||
/// such as checking dimensionality or slicing, should take `LayoutRef`. | ||
/// | ||
/// Like `RawRef`, functions can be written either directly on `LayoutRef` or as generics with `: AsRef<LayoutRef<A, D>>>`. | ||
#[allow(dead_code)] | ||
fn takes_layout<A, D>(_arr: &LayoutRef<A, D>) {} | ||
|
||
/// Mutable, directly take `LayoutRef` | ||
#[allow(dead_code)] | ||
fn takes_layout_mut<A, D>(_arr: &mut LayoutRef<A, D>) {} | ||
|
||
/// Immutable, take a generic that implements `AsRef` to `LayoutRef` | ||
#[allow(dead_code)] | ||
fn takes_layout_asref<T: AsRef<LayoutRef<A, D>>, A, D>(_arr: &T) {} | ||
|
||
/// Mutable, take a generic that implements `AsMut` to `LayoutRef` | ||
#[allow(dead_code)] | ||
fn takes_layout_asmut<T: AsMut<LayoutRef<A, D>>, A, D>(_arr: &mut T) {} | ||
|
||
fn main() {} |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.