-
Notifications
You must be signed in to change notification settings - Fork 307
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
Implement real/imag splitting of arrays #1107
Conversation
These methods make it possible to obtain views of the real and imaginary components of elements in an array of complex elements.
Will you please add a "Co-authored-by" line to the commit message for attribution of my changes? Or, if you'd prefer, you could use separate commits (with the correct authors). Regarding testing, the following cases tend to be where most bugs occur, so, as a general rule, it's good to test them in particular:
Depending on the functionality being tested, it may not be necessary to have tests for all of these edge cases. Another edge case which isn't applicable here is: owned arrays where all the strides are positive but the first visible element is not the first element in the underlying allocation (due to slicing). |
d91b2bd
to
f2f3a44
Compare
We should probably adopt quickcheck more to be a bit more efficient and principled about testing "known tricky cases". It's a topic for another day, but would be very welcome. I'm looking at updating us to quickcheck 1.0. |
Yes of course sorry! I normally use a squash on merge flow, so I figured you'd get attribution there anyway. I've redone things with your commits so you get proper attribution.
Thank you for the recommendations, I have a few more tests that I've added locally and will push. I have found one edge case where things currently panic: #[test]
fn test_split_re_im_invert_axis() {
let s_re: Vec<Complex<f64>> = vec![Complex::one(); 12];
// negative strides
let a = ArrayView::from_shape((2, 3, 2).strides((6, (-2isize) as usize, 1)), &s_re).unwrap();
// panics because the stride doubled overflows usize
let Complex { re, im } = a.split_re_im();
} Perhaps when doubling the strides I should use |
@ethanhs Good find. All stride arithmetic needs to be done as |
Okay pushed the test and fix for that, as well as a few other tests. Let me know if there are other cases I should consider and I'll add tests. |
thanks. Should be good. I pushed in an edit to the test just to add more assertions |
Ok thank you! Good to go. I'm fine with names either split_complex, split_real_imag, split_re_im, so we can think of that until the next patch release. |
Yeah I personally named it |
I would vote split_complex here I think. I see the consistency of using re/im seeing that's what num_complex does, but split complex seems easier to understand. I have (messy) patches for the related but a bit different [T; 4] -> new dimension and have a working name of "expand" right now, in the sense of expanding the element into new axis. But since it works with axes the name isn't really related. Either way, in that patch it's likely that complex will show up again, allowing one to expand Complex into a new axis just like [T; 2] is allowed to. Expand unfortunately is not allowed with regular owned arrays, because it's not legal to change the alignment/element type of an allocation (we could save it in metadata, but we don't have a location for that right now). |
Fwiw, I chose the name
That said, I think
That would be useful functionality, and that's a good point regarding the complex case. "expand" is a reasonable term for this. My first thought was something related to "flattening" the types, but that could easily be confused with flattening/merging axes. Another thought would be a name like |
I made some experiments and I think I went overboard with the possibilities, including allowing expand u128 => 16 x u8 or u128 => 4 x u32 (When these are signed, then it's harder to know that the expand should really mean, even if it's easy to implement). Multiple expand calls might as well be used, at least in the shape of the API where we ask the user to specify where the new axis is going to be, since that's actually arbitrary. Even though for common cases, it would of course be possible to guess if it should be the first or last, but it's technically arbitrary. |
For points (2) and (3) that makes sense, but I think convention is quite strong, those should be the almost obvious choices. |
I agree the convention is pretty strong, I would in fact be quite surprised if Also, after this was merged I was looking at how pytorch does this (See accessing real and imag). >>> y.real
tensor([ 0.6125, -0.3773, -0.0861])
>>> y.imag
tensor([-0.1681, 1.3487, -0.7981])
>>> y.real.mul_(2)
tensor([ 1.2250, -0.7546, -0.1722])
>>> y
tensor([ 1.2250-0.1681j, -0.7546+1.3487j, -0.1722-0.7981j])
>>> y.real.stride()
(2,) It might be nice to provide these as utilities on top of whichever I'm happy to make a PR with the name change and add these. |
All of those conveniences are already there by virtue of Let's go for the name change to split_complex |
oh, is that about more convenient access to real/imag? It was last discussed here #1029 (comment) |
Oh, I just took another look at the implementation, and realized that
Yeah, I don't think we should provide those conversions directly. Instead, I'd suggest adding a |
We already have .cast() for raw views fortunately 🙂 (#734) I guess I'm thinking about if we eventually want some conveniences to make it easy in safe code to translate between different equivalent representations, thinking of It's strange that we have gone so far without addressing ergonomics of wrapping computations yet, but maybe easy translation <=> Wrapping elements is a way to go? |
Oh, yeah, I forgot about that. :)
Yeah, I think the best solution is a trait like the
Here are some options:
Option 4 would provide the most convenience for the user, but I like the simplicity of option 1. |
Picking things up from #1029
It seems the main thing is that tests were needed looking at the discussion. I've added a few to test mutation, reading the views, etc. I don't have a lot of experience testing matrix libraries so let me know if you have other suggestions for tests.
Closes #1029