www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - foreach(i,ref val; ndim_arr)??

reply Jay Norwood <jayn prismnet.com> writes:
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
next sibling parent reply ZombineDev <petar.p.kirov gmail.com> writes:
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-iteration
I 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 ice.html#.makeSlice and http://dlang.org/phobos-prerelease/std_experimental_ndslice_slice.html#.Slice.opIndex 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
next sibling parent reply ag0aep6g <anonymous example.com> writes:
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
parent ZombineDev <petar.p.kirov gmail.com> writes:
On Tuesday, 10 May 2016 at 13:52:27 UTC, ag0aep6g wrote:
 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.
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.
May 10 2016
prev sibling parent reply ZombineDev <petar.p.kirov gmail.com> writes:
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:
 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
I 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 ice.html#.makeSlice and http://dlang.org/phobos-prerelease/std_experimental_ndslice_slice.html#.Slice.opIndex 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);
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] = 24
May 10 2016
parent 9il <ilyayaroshenko gmail.com> writes:
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
prev sibling parent 9il <ilyayaroshenko gmail.com> writes:
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-iteration
This example is form documentation: http://dlang.org/phobos/std_experimental_ndslice_selection.html#.byElement 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