- Notifications
You must be signed in to change notification settings - Fork 35
Add byDim function #79
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
Conversation
Codecov Report
@@ Coverage Diff @@ ## master #79 +/- ## ========================================== + Coverage 96.32% 96.56% +0.24% ========================================== Files 29 29 Lines 4761 5096 +335 ========================================== + Hits 4586 4921 +335 Misses 175 175
Continue to review full report at Codecov.
|
source/mir/ndslice/topology.d Outdated
| | ||
| auto adjTransposed(SliceKind kind, size_t[] packs, Iterator)(Slice!(kind, packs, Iterator) slice) | ||
| { | ||
| static assert (packs != [1], "1-dimensional slice not accepted"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this can be removed and generalised for vectors
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@9il I had only included that initially because transposed does not work properly on vectors, i.e.
auto slice = iota(3); auto x = slice.transposed!1; //does not work but with the adjustment for packs, then one can only pass dim=0 for a 1-dimensional vector and there is no error.
source/mir/ndslice/topology.d Outdated
| { | ||
| import mir.ndslice : Slice, SliceKind; | ||
| | ||
| auto adjTransposed(SliceKind kind, size_t[] packs, Iterator)(Slice!(kind, packs, Iterator) slice) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
please add ///
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@9il Do I also need to add the /// before byDim?
| import mir.ndslice : Slice, SliceKind; | ||
| | ||
| auto adjTransposed(SliceKind kind, size_t[] packs, Iterator)(Slice!(kind, packs, Iterator) slice) | ||
| { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if (dim < packs[0]) | { | ||
| return slice; | ||
| } | ||
| else |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
... else static if (dim + 1 < packs[0] || packs.length > 1) { import mir.ndslice : canonical, transposed; return slice.canonical.transposed!dim; } ...please cover this in unittest
source/mir/ndslice/topology.d Outdated
| | ||
| auto slice = iota(3, 4); | ||
| | ||
| static immutable shape34 = [3, 4]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please change to fixed size arrays (like size_t[2] = shape34 = [3, 4]; ) for all unittests
source/mir/ndslice/package.d Outdated
| $(TD | ||
| $(SUBREF topology, as) | ||
| $(SUBREF topology, apply) | ||
| $(SUBREF topology, as) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
tabs -> spaces
source/mir/ndslice/topology.d Outdated
| auto adjTransposed(SliceKind kind, size_t[] packs, Iterator)(Slice!(kind, packs, Iterator) slice) | ||
| { | ||
| static assert (packs != [1], "1-dimensional slice not accepted"); | ||
| |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please remove trailing tabs and spaces
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
in all edited files
source/mir/ndslice/topology.d Outdated
| $(LREF ipack), | ||
| $(LREF transposed). | ||
| +/ | ||
| template byDim(size_t dim = 0) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please generalize it for multiple dimensions like it was done for transposed:
template transposed(Dimensions...) if (Dimensions.length) { static if (!allSatisfy!(isSize_t, Dimensions)) alias transposed = .transposed!(staticMap!(toSize_t, Dimensions)); else .... source/mir/ndslice/topology.d Outdated
| $(T2 ipack , Returns slice of slices.) | ||
| $(T2 unpack , Merges all dimension packs.) | ||
| $(T2 evertPack, Reverses dimension packs.) | ||
| $(T2 byDim , Convenience function to return a slice that can be iterated by dimension.) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please also add a note what actually this function do: transposes dimensions on top and packs them.
source/mir/ndslice/topology.d Outdated
| $(LREF map), | ||
| $(HTTP https://stat.ethz.ch/R-manual/R-devel/library/base/html/apply.html, apply) | ||
| +/ | ||
| template apply(alias f, size_t dim = 0) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I do not think we need this function. slice.byDim!dim.map!f is well enough. Also issue with apply name: apply is a verb in infinitive form, which is good for actual computations but not for lazy data type construction.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fair point on the naming, R's apply would really be more like slice.byDim!dim.each!f
| ping @wilzbach : what do you think? |
source/mir/ndslice/topology.d Outdated
| import mir.ndslice.slice : Slice, SliceKind; | ||
| | ||
| /// | ||
| auto adjTransposed(SliceKind kind, size_t[] packs, Iterator)(Slice!(kind, packs, Iterator) slice) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please add @fastmath flag for all inner functions
| @9il I think I have made all of the requested changes. Let me know if additional changes are required, or if you want me to rebase the three commits into one final one before merging (I already compressed a bunch into the two additional ones). |
source/mir/ndslice/topology.d Outdated
| alias byDim = .byDim!(staticMap!(toSize_t, Dimensions)); | ||
| else | ||
| /// | ||
| auto byDim(SliceKind kind, size_t[] packs, Iterator) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@fastmath
source/mir/ndslice/topology.d Outdated
| } | ||
| | ||
| /// | ||
| @fastmath private auto adjTransposed(SliceKind kind, size_t[] packs, Iterator) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no need @fastmath here because it is global for the module
source/mir/ndslice/topology.d Outdated
| } | ||
| | ||
| /// Transposed adjusted to ignore dim=0 and include universal | ||
| @fastmath private template adjTransposed(Dimensions...) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no need @fastmath here because it is global for the module
source/mir/ndslice/topology.d Outdated
| alias adjTransposed = .adjTransposed!(staticMap!(toSize_t, Dimensions)); | ||
| else | ||
| /// | ||
| auto adjTransposed(SliceKind kind, size_t[] packs, Iterator)(Slice!(kind, packs, Iterator) slice) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@fastmath is required here because global fastmath does not affect internal template content
| { | ||
| return slice; | ||
| } | ||
| else |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please add specialization for canonical case. Canonical case is valid when the last (last of unpacked slice) dimension of contiguous slice is not moved upper. The code example for single dimension is below. Please generalize it for multiple dimensions.
... else static if (dim + 1 < packs[0] || packs.length > 1) { import mir.ndslice : canonical, transposed; return slice.canonical.transposed!dim; } ...please cover this in unittest (contiguous -> canonical) . Existing unittests should be enough, just extend them
source/mir/ndslice/topology.d Outdated
| | ||
| mixin DimensionsCountCTError; | ||
| | ||
| static if (Dimensions.length == 1 && Dimensions[0] == 0) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
static if ([Dimensions] == [Iota!(Dimensions.length)])
or
static if (Dimensions == Iota!(Dimensions.length)) but not sure if the last variant works
| @9il I have fixed some of the issues...I definitely didn't understand your point on the canonical the first time you mentioned it. This second time I've at least added the code and adjusted it for multiple dimensions (though perhaps incorrectly). I still don't really understand the case, so I'm not really sure what I'm supposed to be testing for. So I didn't add any more tests and thus can't really be sure that it's currently right for multiple dimensions. |
| @9il I've tried adding some more unittests (and some other small changes). Hopefully moving in the right direction. As an aside, I have done some working with a function that formats an ndslice into a string (same format as the pretty versions I added here). At present I am making use of some features of the standard library and there is some use of the @gc. Does it have a place in mir-algorithm? Perhaps numir? |
source/mir/ndslice/topology.d Outdated
| import mir.ndslice.internal : DimensionsCountCTError, DimensionCTError; | ||
| | ||
| mixin DimensionsCountCTError; | ||
| |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
just return slice.adjTransposed!Dimensions.ipack!(Dimensions.length);
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
please add a small unittest to cover Dimensions.length > 1
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I had actually included a two-dimensional unittest on line 4412.
source/mir/ndslice/topology.d Outdated
| } | ||
| | ||
| /// | ||
| auto byDim(SliceKind kind, size_t[] packs, Iterator) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I do not think we need this overload, because it is equal to ipack!0
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This was to allow writing the default x.byDim instead of x.byDim!0
Mir Algorithms need formatting, and it may be based on 100% generic @nogc code from Phobos. GC usage is allowed by user, but @nogc allocators should be supported by API. For GC based code numic seems to be a good front-end library. Thank you for byDim PR, good addition! |
If you have ability to fix #48 this would be awesome! Phobos appender allocates GC struct on the heep. So it behaves as it is an object. Other approach is RefCounted appender. Third approach is an appender with disabled With allocator based appender we have the following API issue: The last variant is valid only for some allocators like Mallocator and GCAllocator. The first may not be valid for some allocators (it is not specified yet, I just realize this issue, that allocators should have disabled This is draft: For now simple extend logic for Also, we need our |
| @9il I'm not sure that I have the skills to get appender working properly (was just saying that if it did work, then I could do a @nogc format for slices). I'd say as a first step, I would need to re-write it to rely less on strings and more on ndslices. Then I would need to change use of std.format.format to std.format.sformat. I think only then would I check to see if I can get the appender working. |
|
|
| Gotcha. |
Adds convenience functions byDim and apply. byDim provides iteration of a slice by dimension, while apply combines byDim and map to apply a function by dimension.
Functionality discussed in issue #58.