digitalmars.D.learn - foreach(i,ref val; ndim_arr)??
- Jay Norwood (7/7) May 09 2016 I noticed some discussion of Cartesian indexes in Julia, where
- ZombineDev (17/24) May 10 2016 I guess you are talking about ndslice
- ag0aep6g (3/4) May 10 2016 Tiny nitpick: lockstep doesn't return a range. It uses opApply to
- ZombineDev (5/9) May 10 2016 Yes I know and I chose it in purpose, because it allows ref
- ZombineDev (48/75) May 10 2016 Oops, this is not entirely correct. Sorry, I was on the phone and
- 9il (18/37) May 10 2016 The code above is slow because it calculates index using multiple
- 9il (23/30) May 10 2016 This example is form documentation:
I noticed some discussion of Cartesian indexes in Julia, where the index is a tuple, along with some discussion of optimizing the index created for cache efficiency. I could find foreach(ref val, m.byElement()), but didn't find an example that returned a tuple index. Is that supported? http://julialang.org/blog/2016/02/iteration http://julialang.org/blog/2016/03/arrays-iteration
May 09 2016
On Monday, 9 May 2016 at 18:50:32 UTC, Jay Norwood wrote:I noticed some discussion of Cartesian indexes in Julia, where the index is a tuple, along with some discussion of optimizing the index created for cache efficiency. I could find foreach(ref val, m.byElement()), but didn't find an example that returned a tuple index. Is that supported? http://julialang.org/blog/2016/02/iteration http://julialang.org/blog/2016/03/arrays-iterationI guess you are talking about ndslice (http://dlang.org/phobos/std_experimental_ndslice). There are various functions that can take static arrays, as well as tuples as parameters that are both cache-efficient. For example: http://dlang.org/phobos-prerelease/std_experimental_ndslice_s I also found the need for a byElement function that also provides the index. I guess it is a good idea for a pull request. In the mean time, you can use the following: auto indexed_range = lockstep( ndslice.byElement, ndslice.shape.indexSlice ); foreach (ref elem; indexes; indexed_range) writefln("Element at %s = %s", indexes, elem);
May 10 2016
Am 10.05.2016 um 12:21 schrieb ZombineDev:auto indexed_range = lockstep(Tiny nitpick: lockstep doesn't return a range. It uses opApply to support foreach.
May 10 2016
On Tuesday, 10 May 2016 at 13:52:27 UTC, ag0aep6g wrote:Am 10.05.2016 um 12:21 schrieb ZombineDev:Yes I know and I chose it in purpose, because it allows ref access to individual elements (zip returns a tuple which doesn't provide ref access). Otherwise my translation of OP wouldn't be accurate.auto indexed_range = lockstep(Tiny nitpick: lockstep doesn't return a range. It uses opApply to support foreach.
May 10 2016
On Tuesday, 10 May 2016 at 10:21:30 UTC, ZombineDev wrote:On Monday, 9 May 2016 at 18:50:32 UTC, Jay Norwood wrote:Oops, this is not entirely correct. Sorry, I was on the phone and I couldn't verify it. Here's a working example: (You can try it at: https://dpaste.dzfl.pl/c0327f067fca) import std.array : array; import std.experimental.ndslice : byElement, indexSlice, sliced; import std.range : iota, lockstep, zip; import std.stdio : writefln; void main() { // needs .array for ref (lvalue) access // (iota offers only rvalues) auto slice = iota(2 * 3 * 4).array.sliced(2, 3, 4); auto indexed_range = lockstep( slice.shape.indexSlice.byElement(), slice.byElement() ); writefln("%s", slice); foreach (idx, ref elem; indexed_range) writefln("Element at %s = %s", idx, ++elem); } [[[0, 1, 2, 3], [4, 5, 6, 7], [8, 9, 10, 11]], [[12, 13, 14, 15], [16, 17, 18, 19], [20, 21, 22, 23]]] Element at [0, 0, 0] = 1 Element at [0, 0, 1] = 2 Element at [0, 0, 2] = 3 Element at [0, 0, 3] = 4 Element at [0, 1, 0] = 5 Element at [0, 1, 1] = 6 Element at [0, 1, 2] = 7 Element at [0, 1, 3] = 8 Element at [0, 2, 0] = 9 Element at [0, 2, 1] = 10 Element at [0, 2, 2] = 11 Element at [0, 2, 3] = 12 Element at [1, 0, 0] = 13 Element at [1, 0, 1] = 14 Element at [1, 0, 2] = 15 Element at [1, 0, 3] = 16 Element at [1, 1, 0] = 17 Element at [1, 1, 1] = 18 Element at [1, 1, 2] = 19 Element at [1, 1, 3] = 20 Element at [1, 2, 0] = 21 Element at [1, 2, 1] = 22 Element at [1, 2, 2] = 23 Element at [1, 2, 3] = 24I noticed some discussion of Cartesian indexes in Julia, where the index is a tuple, along with some discussion of optimizing the index created for cache efficiency. I could find foreach(ref val, m.byElement()), but didn't find an example that returned a tuple index. Is that supported? http://julialang.org/blog/2016/02/iteration http://julialang.org/blog/2016/03/arrays-iterationI guess you are talking about ndslice (http://dlang.org/phobos/std_experimental_ndslice). There are various functions that can take static arrays, as well as tuples as parameters that are both cache-efficient. For example: http://dlang.org/phobos-prerelease/std_experimental_ndslice_s I also found the need for a byElement function that also provides the index. I guess it is a good idea for a pull request. In the mean time, you can use the following: auto indexed_range = lockstep( ndslice.byElement, ndslice.shape.indexSlice ); foreach (ref elem; indexes; indexed_range) writefln("Element at %s = %s", indexes, elem);
May 10 2016
On Tuesday, 10 May 2016 at 15:18:50 UTC, ZombineDev wrote:On Tuesday, 10 May 2016 at 10:21:30 UTC, ZombineDev wrote: (You can try it at: https://dpaste.dzfl.pl/c0327f067fca) import std.array : array; import std.experimental.ndslice : byElement, indexSlice, sliced; import std.range : iota, lockstep, zip; import std.stdio : writefln; void main() { // needs .array for ref (lvalue) access // (iota offers only rvalues) auto slice = iota(2 * 3 * 4).array.sliced(2, 3, 4); auto indexed_range = lockstep( slice.shape.indexSlice.byElement(), slice.byElement() ); writefln("%s", slice); foreach (idx, ref elem; indexed_range) writefln("Element at %s = %s", idx, ++elem); }The code above is slow because it calculates index using multiple assembler ops. Following would be faster: for(auto elems = slice.byElement; !elems.empty; elems.popFront) { size_t[2] index = elems.index; elems.front = index[0] * 10 + index[1] * 3; } For really fast code just use multiple foreach loops: foreach(i; matrix.length) { auto row = matrix[i]; // optional foreach(j; matrix.length!1) { ... } }
May 10 2016
On Monday, 9 May 2016 at 18:50:32 UTC, Jay Norwood wrote:I noticed some discussion of Cartesian indexes in Julia, where the index is a tuple, along with some discussion of optimizing the index created for cache efficiency. I could find foreach(ref val, m.byElement()), but didn't find an example that returned a tuple index. Is that supported? http://julialang.org/blog/2016/02/iteration http://julialang.org/blog/2016/03/arrays-iterationThis example is form documentation: import std.experimental.ndslice.slice; auto slice = new long[20].sliced(5, 4); for(auto elems = slice.byElement; !elems.empty; elems.popFront) { size_t[2] index = elems.index; elems.front = index[0] * 10 + index[1] * 3; } assert(slice == [[ 0, 3, 6, 9], [10, 13, 16, 19], [20, 23, 26, 29], [30, 33, 36, 39], [40, 43, 46, 49]]); ndslice does not have opApply, because it overrides range primitives. Iteration with byElement may be a little bit slower then iteration with common foreach loops. A method, say, `forElement` for `foreach` loops may be added, thought. Best regards, llya
May 10 2016