Skip to content

Implement owning constructors taking dimensions and strides #60

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 13 commits into from
Jan 25, 2016

Conversation

vbarrielle
Copy link
Contributor

Fixes #59.

This is a first draft of constructors taking strides into account. Tests are required, and I need to think it through a bit more to see if the checks are ok.

@bluss
Copy link
Member

bluss commented Jan 19, 2016

Seems nice. We need a simpler way than this to create f-order arrays too, later. I was thinking you maybe know how to handle that best.

Can we use a Result based API here?

@vbarrielle
Copy link
Contributor Author

We need a simpler way than this to create f-order arrays too, later. I was
thinking you maybe know how to handle that best.

I think a nice API for this could be to have fn arr1_f and similar to create
f-order arrays easily.

Can we use a Result based API here?

Yes it's probably better.

I think my current tests may not be enough. Some strides may enable a same
element to be referenced by different indices, and I don't think this should be
allowed (probably could break some unsafe code). I'll try and add checking for
that as well.

@bluss
Copy link
Member

bluss commented Jan 19, 2016

Right, accessing the same element under multiple indices is the way broadcasting is implemented, and it can only be allowed for read only array views, so not for these constructors.

@bluss
Copy link
Member

bluss commented Jan 21, 2016

Cool stuff happening here. Say something here if you want me to look at it. I don't think we want to expose the helper functions in src/dimension.rs.

@vbarrielle
Copy link
Contributor Author

I don't think we want to expose the helper functions in src/dimension.rs.

Yeah I wasn't sure about exposing those either. Once thing that made me think they had to be exposed was that it allowed documenting clearly what kind of strides are allowed.

Otherwise I think this is in a pretty good shape now, so you can review it. Depending on what you prefer I can un-expose the helper functions before a merge.

@vbarrielle vbarrielle changed the title WIP implement owning constructors taking dimensions and strides Implement owning constructors taking dimensions and strides Jan 21, 2016
#[derive(Clone, Debug, PartialEq)]
pub enum StrideError {
/// stride leads to out of bounds indexing
OutOfBoundsStride,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Error looks good. I'd like to remove Stride from all the variant names.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we combine Aliasing and Negative? I don't know if we need the details.

@bluss
Copy link
Member

bluss commented Jan 21, 2016

One thing for info: In the long run I hope to switch all dimension impls to be on fixed size arrays, so [Ix; 2] instead of (Ix, Ix) for example.

It would mean that in the future, arguments like dimension and stride will be provided as arrays. But I'm hopeful that we can bridge the transition with associated types and a trait, just like how NdIndex works today to accept (i, j) and [i, j] the same way.

One thing I'm thinking about is if we ever want to accept signed strides. Maybe not. Maybe that's mostly relevant "for raw parts"

@bluss
Copy link
Member

bluss commented Jan 21, 2016

Let's skip exporting the helper functions. I want the least API liability :D

@bluss
Copy link
Member

bluss commented Jan 21, 2016

Note to anyone following, we optimize for c-order arrays in arithmetic right now, but we will fix that down the line (and add fast cases for f-order too).

@vbarrielle
Copy link
Contributor Author

The latest changes rewrites the StrideError variants and no longer exposes the
stride check methods at the API level.

@vbarrielle
Copy link
Contributor Author

One thing I'm thinking about is if we ever want to accept signed strides. Maybe not. Maybe that's mostly relevant "for raw parts"

Negative strides look useful if you want to reverse iteration on some axis (at least that's what I use them for in numpy).
At the type level I would see some benefits having the strides as signed integers, it would make it impossible to use a strides data in place of a dim.

@bluss
Copy link
Member

bluss commented Jan 22, 2016

The Dimension design that uses the signed strides in unsigned integers predates associated types! So it's def something that will be fixed at some point.

sorted.slice_mut().sort();
let mut res = strides.clone();
for (ind, val) in strides.slice().iter().enumerate() {
// cannot binary search in unsorted...
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It should probably just be a linear search. Linear search is faster than binary search anway, for slices surprisingly long, up to 32 or more elements.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd use .unwrap() since it's expected to never be None. No reason to insert a panic with formatting here, that's just awful in the generated code unfortunately.

Compare asm in release mode here: http://is.gd/UFzf2y

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right, I originally thought .expect() would document the fact that it should never be None but it's better to not have dead formatting code.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's an inspiration to finally fix this issue at least 😄 rust-lang/rust/pull/31116

Linear search should be more performant than binary search for all
reasonable use cases (never more than 30 dimensions).
Removed the expect() because it will add dedicated panic and printing
code that should never execute.
.iter()
.enumerate()
.find(|&(_, &x)| x == val)
.unwrap().0; // cannot panic by construction
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is actually shorter with the iterator method position.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh nice I didn't know about that method.

@bluss
Copy link
Member

bluss commented Jan 22, 2016

Ok everything looks good. I think we want to scrap the abbreviation "uchk", I want to remove that from ndarray (the other use is deprecated)!

No worries, at this point I can do any adjustments after merge as well.

I would probably rename StrideError::Aliased to something more generic too.

@vbarrielle
Copy link
Contributor Author

Ok I'll leave the renames to you after the merge since you probably know better which names are more consistent with the rest of the API :)

@bluss
Copy link
Member

bluss commented Jan 25, 2016

Thank you

Rust 1.7 is adding .sort_by_key() to slices, which can be used in the stride sort scenario, in the future.

bluss added a commit that referenced this pull request Jan 25, 2016
Implement owning constructors taking dimensions and strides
@bluss bluss merged commit 6d960a4 into rust-ndarray:master Jan 25, 2016
@vbarrielle vbarrielle deleted the stride_constructor branch January 26, 2016 12:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants