www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Multidimensional foreach

reply "Simen kjaeraas" <simen.kjaras gmail.com> writes:
I have a function that returns an N-dimensional array, where N is a
template parameter. Now I want to run a foreach loop through each
element of this array. Is there a known and tested way to do this,
or should I write my own templates to do it?

-- 
Simen
Dec 17 2009
parent reply "Simen kjaeraas" <simen.kjaras gmail.com> writes:
Simen kjaeraas <simen.kjaras gmail.com> wrote:

 I have a function that returns an N-dimensional array, where N is a
 template parameter. Now I want to run a foreach loop through each
 element of this array. Is there a known and tested way to do this,
 or should I write my own templates to do it?
I wrote this implementation. Now, to get some meaningful indices out of it. Do D2's ranges even support that? Oh, and I probably need to rewrite it in terms of an index instead of slices to get that working. Bah. Ideas? Comments? Death threats? template ArrayBaseType( T ) { alias T ArrayBaseType; } template ArrayBaseType( T : U[], U ) { alias ArrayBaseType!( U ) ArrayBaseType; } template MultiDimRange( T ) { alias T MultiDimRange; } struct MultiDimRange( T : U[][], U ) { T arr; MultiDimRange!( U[] ) subRange; this( T arg ) { arr = arg; subRange = arg[ 0 ]; } void opAssign( T arg ) { arr = arg; subRange = arg[ 0 ]; } bool empty( ) { return ( arr.length <= 1 ) && subRange.empty; } ArrayBaseType!( T ) front( ) { assert( !empty, "Called front on empty range." ); if ( subRange.empty ) { typeof( subRange ) tmp = arr[ 1 ]; return tmp.front( ); } else { return subRange.front( ); } } ArrayBaseType!( T ) popFront( ) { assert( !empty, "Called popFront on empty range." ); ArrayBaseType!( T ) result; if ( subRange.empty ) { if ( arr.length <= 1 ) { throw new Exception( "Argh!" ); } arr = arr[ 1..$ ]; subRange = arr[0]; } result = front( ); subRange.popFront( ); return result; } } MultiDimRange!( T ) multiDimRange( T )( T args ) { return MultiDimRange!( T )( args ); } -- Simen
Dec 18 2009
parent reply Bill Baxter <wbaxter gmail.com> writes:
On Fri, Dec 18, 2009 at 5:17 AM, Simen kjaeraas <simen.kjaras gmail.com> wrote:
 Simen kjaeraas <simen.kjaras gmail.com> wrote:

 I have a function that returns an N-dimensional array, where N is a
 template parameter. Now I want to run a foreach loop through each
 element of this array. Is there a known and tested way to do this,
 or should I write my own templates to do it?
I wrote this implementation. Now, to get some meaningful indices out of it. Do D2's ranges even support that? Oh, and I probably need to rewrite it in terms of an index instead of slices to get that working. Bah. Ideas? Comments? Death threats?
I think you need to explain more what you are hoping to accomplish. In general there are two ways to store multidimensional data: 1) jagged - with arrays of arrays. This is the method directly supported by D arrays. With this accessing each element requires as many indirections as there are dimensions. But for large arrays, this is more friendly to memory use because the data doesn't have to be in one huge contiguous chunk 2) rectangular - with indexing into a chunk of memory. This method is directly supported by some languages like C#, but not D. Accessing each element requires just one indirection but a bit of offset computation. Very large arrays may have trouble fitting in available memory. (See this very old proposal for adding them to D: http://homepages.uni-regensburg.de/~nen10015/documents/D-multidimarray.html) Generally if your plan is to do math on these arrays, method 2 is better supported by existing math libraries. So what do you plan to do with these? You may be better off implementing a rectangular style multi-dim array type than trying to use D's built-in. Or look at the multi-dim array types written by Fawzi or myself. --bb
Dec 18 2009
parent "Simen kjaeraas" <simen.kjaras gmail.com> writes:
On Fri, 18 Dec 2009 19:49:31 +0100, Bill Baxter <wbaxter gmail.com> wrote:

 On Fri, Dec 18, 2009 at 5:17 AM, Simen kjaeraas <simen.kjaras gmail.com>  
 wrote:
 Simen kjaeraas <simen.kjaras gmail.com> wrote:

 I have a function that returns an N-dimensional array, where N is a
 template parameter. Now I want to run a foreach loop through each
 element of this array. Is there a known and tested way to do this,
 or should I write my own templates to do it?
I wrote this implementation. Now, to get some meaningful indices out of it. Do D2's ranges even support that? Oh, and I probably need to rewrite it in terms of an index instead of slices to get that working. Bah. Ideas? Comments? Death threats?
I think you need to explain more what you are hoping to accomplish. In general there are two ways to store multidimensional data: 1) jagged - with arrays of arrays. This is the method directly supported by D arrays. With this accessing each element requires as many indirections as there are dimensions. But for large arrays, this is more friendly to memory use because the data doesn't have to be in one huge contiguous chunk 2) rectangular - with indexing into a chunk of memory. This method is directly supported by some languages like C#, but not D. Accessing each element requires just one indirection but a bit of offset computation. Very large arrays may have trouble fitting in available memory. (See this very old proposal for adding them to D: http://homepages.uni-regensburg.de/~nen10015/documents/D-multidimarray.html) Generally if your plan is to do math on these arrays, method 2 is better supported by existing math libraries. So what do you plan to do with these? You may be better off implementing a rectangular style multi-dim array type than trying to use D's built-in. Or look at the multi-dim array types written by Fawzi or myself. --bb
I started out with no particular plan to this, but have arrived at wanting to make a range that facilitates "deep foreach" - that is, enumerate all ranges recursively. This way, it doesn't matter whether one wants to use a jagged or rectangular array. (except of course possibly for speed) btw, is there currently a way to support foreach( index, element; range ){} syntax for ranges? I can't seem to find any documentation on how to get the index. -- Simen
Dec 18 2009