-
Notifications
You must be signed in to change notification settings - Fork 308
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
NdArray
trait
#339
Comments
I agree to introduce such trait. My current generic code typically has the following form: pub fn func<A, S1, S2>(a: &mut ArrayBase<S1, Ix2>, b: &ArrayBase<S2, Ix2>)
where
A: LinalgScalar,
S1: DataMut<Elem=A>,
S2: Data<Elem=A>,
{
...
} In my understanding, pub fn func<K, A1, A2>(a: &mut A1, b: &A2)
where
K: LinalgScalar,
A1: NdArrayMut<K, Ix2>,
A2: NdArray<K, Ix2>,
{
...
} I think |
Good idea there too: maybe a type parameter for element and dimension is better than associated types. Best to try both.. |
Logically they are associated types: A specific type like |
Here are some tantalizing examples of what Instead of dynamic typing, we get abstract types, and we can pick and choose which of the associated types of the array should be abstract for each time we use the trait. (It will make sense when you look at these examples.) Written for playground which as of this writing uses ndarray 0.12. (playground link) use ndarray::prelude::*;
use ndarray::Data;
use ndarray::Zip;
use num::{Zero, One};
// Usage examples
pub fn example_longest_axis(array: impl NdArray) -> Option<Axis> {
array.as_array().axes().max_by_key(|ax| ax.len()).map(|ax| ax.axis())
}
pub fn example_sum(array: impl NdArray<Item=f64>) -> f64 {
array.as_array().sum()
}
pub fn example_generic_sum<T>(array: impl NdArray<Item=T>) -> T
where T: Clone + Zero + One
{
array.as_array().sum()
}
pub fn example_index_2d(array: impl NdArray<Dim=Ix2, Item=f64>) {
Zip::indexed(array.as_array()).apply(|(_i, _j), _elt| {
});
}
// The NdArray trait has associated types for
// Dimension,
// Data storage,
// Item (Element type)
// But each usage can pick which of these should be abstracted or explicit
pub trait NdArray {
type Dim: Dimension;
type Data: Data<Elem=Self::Item>;
type Item;
// It is not at all certain, that these are the methods
// that should be on such a trait. But it's representative
// of what kind of access we have.
fn as_array(&self) -> &ArrayBase<Self::Data, Self::Dim>;
fn view(&self) -> ArrayView<Self::Item, Self::Dim>;
}
pub trait NdArrayMut : NdArray {
fn as_array_mut(&mut self) -> &mut ArrayBase<Self::Data, Self::Dim>;
fn view_mut(&mut self) -> ArrayViewMut<Self::Item, Self::Dim>;
}
pub trait NdArrayOwned : NdArrayMut {
/* methods */
}
impl<S, D> NdArray for ArrayBase<S, D>
where S: Data,
D: Dimension,
{
type Dim = D;
type Data = S;
type Item = S::Elem;
fn as_array(&self) -> &Self { self }
fn view(&self) -> ArrayView<Self::Item, Self::Dim> { self.view() }
}
impl<'a, T> NdArray for &'a T
where T: NdArray,
{
type Dim = T::Dim;
type Data = T::Data;
type Item = T::Item;
fn as_array(&self) -> &ArrayBase<Self::Data, Self::Dim> { (**self).as_array() }
fn view(&self) -> ArrayView<Self::Item, Self::Dim> { (**self).view() }
}
fn main() {
type A = Array2<f64>;
let a = A::from_shape_fn((5, 10), |(i, j)| i as f64 / (j + 1) as f64);
println!("longest axis={:?}", example_longest_axis(&a));
println!("sum={:.3}", example_sum(&a));
println!("sum={:.3}", example_generic_sum(&a));
example_index_2d(&a);
} If this is done, I'd think it should not just be a convenient trait - it should really be an overhaul of the whole crate, so that it is all usable, using the traits as starting point instead of the inherent methods. I don't have a plan or a PoC that can show that it works. |
@bluss do you have any thoughts about how this kind of trait might interact with the My understanding is that the advantage of this trait over |
We need to traitify the array types, so that we shift from using
ArrayBase
for generic programming to something more flexible.Imagine a sketch:
Foreseen problems: How do we conditionalize methods?
The text was updated successfully, but these errors were encountered: