Thread overview | |||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
February 24, 2008 Difficulty copying multi dimensional static array to dynamic array. | ||||
---|---|---|---|---|
| ||||
I have more than one problem in this class (errors below), but my focus it to return a dynamic array of float[4][4] which is copied from a static array of float[4][4]. I am having trouble finding how to do this. class Matrix { float[][] toFloatArray4x4() { float f[4][4] = matrix.dup; return f; } void toFloatArray16(float flat[16]) { flat[]=matrix_flat[]; } private: union { float matrix[4][4]; float matrix_flat[16]; } } matrix.d(74): Error: cannot implicitly convert expression (_adDupT(&_D14TypeInfo_G4G4f6__initZ,cast(float[4u][])(this.matrix))) of type float[4u][] to float[] matrix.d(75): Error: cannot implicitly convert expression (f) of type float[4u][4u] to float[][] matrix.d(75): Error: escaping reference to local f |
February 25, 2008 Re: Difficulty copying multi dimensional static array to dynamic array. | ||||
---|---|---|---|---|
| ||||
Posted in reply to Spacen Jasset | Spacen Jasset wrote: > I have more than one problem in this class (errors below), but my focus it to return a dynamic array of float[4][4] which is copied from a static array of float[4][4]. I am having trouble finding how to do this. > > class Matrix > { > float[][] toFloatArray4x4() > { > float f[4][4] = matrix.dup; > return f; > } > void toFloatArray16(float flat[16]) > { > flat[]=matrix_flat[]; > } > private: > union > { > float matrix[4][4]; > float matrix_flat[16]; > } > } > > matrix.d(74): Error: cannot implicitly convert expression (_adDupT(&_D14TypeInfo_G4G4f6__initZ,cast(float[4u][])(this.matrix))) of type float[4u][] to float[] > matrix.d(75): Error: cannot implicitly convert expression (f) of type float[4u][4u] to float[][] > matrix.d(75): Error: escaping reference to local f matrix.dup is going to only copy the pointers to the 4 sub-arrays. Those sub-arrays are float[4u] static arrays. So you get back a dynamic array of static arrays. float[4u][] just like the compiler is telling you. I think if you really want to make a dynamic array of dynamic arrays that still points to the same memory as the original you're going to have to do something like: float f[][] ret; ret.length = 4; foreach(i,ref v; matrix) { ret[i] = matrix[i][0..4]; } return ret; If you intend that to be a copy, then make it matrix[i].dup But is it something you really need to be able to do? You will get back a dynamic array that isn't really dynamic. Resizing it will cause it to become distinct from the original static array's memory. Double indexed arrays aren't really a great representation for matrices anyway, since every access requires a double indirection. Furthermore, the float[][] interface allows you to make ragged arrays, that is, if you have a "float[][] M" you can't really be sure if every row has the same length as M[0] unless you check them all because some silly user might have changed the length of just the 3rd row or something. Finally, for many purposes (OpenGL and and calling Fortran numeric routines) column-major ordering is needed. With column major ordering M[i][j] is the i'th column, j'th row, which just looks wrong to anyone who's done much linear algebra. If you're interested I can point you to two other matrix classes where you can probably find answers most other issues you'll run across: http://www.dsource.org/projects/openmeshd/browser/trunk/Helix/helix/linalgebra.d http://www.dsource.org/projects/openmeshd/browser/trunk/OpenMeshD/OpenMesh/Core/Geometry/MatrixT.d And here are some others I found but can't vouch for because I've never used 'em: http://www.dsource.org/projects/arclib/browser/trunk/arclib/arc/math/matrix.d http://www.dsource.org/projects/yage/browser/trunk/src/yage/core/matrix.d http://www.dsource.org/projects/mathematics/browser/trunk/mathematics/numerical/Matrix.d --bb |
February 25, 2008 Re: Difficulty copying multi dimensional static array to dynamic array. | ||||
---|---|---|---|---|
| ||||
Posted in reply to Bill Baxter | Bill Baxter wrote:
> Spacen Jasset wrote:
>> I have more than one problem in this class (errors below), but my focus it to return a dynamic array of float[4][4] which is copied from a static array of float[4][4]. I am having trouble finding how to do this.
>>
>> class Matrix
>> {
>> float[][] toFloatArray4x4()
>> {
>> float f[4][4] = matrix.dup;
>> return f;
>> }
>> void toFloatArray16(float flat[16])
>> {
>> flat[]=matrix_flat[];
>> }
>> private:
>> union
>> {
>> float matrix[4][4];
>> float matrix_flat[16];
>> }
>> }
>>
>> matrix.d(74): Error: cannot implicitly convert expression (_adDupT(&_D14TypeInfo_G4G4f6__initZ,cast(float[4u][])(this.matrix))) of type float[4u][] to float[]
>> matrix.d(75): Error: cannot implicitly convert expression (f) of type float[4u][4u] to float[][]
>> matrix.d(75): Error: escaping reference to local f
>
>
> matrix.dup is going to only copy the pointers to the 4 sub-arrays. Those sub-arrays are float[4u] static arrays.
> So you get back a dynamic array of static arrays.
> float[4u][] just like the compiler is telling you.
>
> I think if you really want to make a dynamic array of dynamic arrays that still points to the same memory as the original you're going to have to do something like:
>
> float f[][] ret;
> ret.length = 4;
> foreach(i,ref v; matrix) {
> ret[i] = matrix[i][0..4];
> }
> return ret;
>
> If you intend that to be a copy, then make it matrix[i].dup
>
> But is it something you really need to be able to do?
> You will get back a dynamic array that isn't really dynamic. Resizing it will cause it to become distinct from the original static array's memory. Double indexed arrays aren't really a great representation for matrices anyway, since every access requires a double indirection. Furthermore, the float[][] interface allows you to make ragged arrays, that is, if you have a "float[][] M" you can't really be sure if every row has the same length as M[0] unless you check them all because some silly user might have changed the length of just the 3rd row or something. Finally, for many purposes (OpenGL and and calling Fortran numeric routines) column-major ordering is needed. With column major ordering M[i][j] is the i'th column, j'th row, which just looks wrong to anyone who's done much linear algebra.
>
> If you're interested I can point you to two other matrix classes where you can probably find answers most other issues you'll run across:
>
> http://www.dsource.org/projects/openmeshd/browser/trunk/Helix/helix/linalgebra.d
>
> http://www.dsource.org/projects/openmeshd/browser/trunk/OpenMeshD/OpenMesh/Core/Geometry/MatrixT.d
>
> And here are some others I found but can't vouch for because I've never used 'em:
> http://www.dsource.org/projects/arclib/browser/trunk/arclib/arc/math/matrix.d
>
> http://www.dsource.org/projects/yage/browser/trunk/src/yage/core/matrix.d
> http://www.dsource.org/projects/mathematics/browser/trunk/mathematics/numerical/Matrix.d
>
> --bb
I see what you mean. I will look though helix, perhaps I should be using that anway.
All I am trying to do is 'return' an array so that toFloatArray4x4() can be called to fill in a static array. Something like this:
float [4][4] m1;
m1 = obj.toFloatArray4x4();
I realize I can pass the array in an have it set as in toFloatArray16(float flat[16]) but I was hoping I could return an array too.
|
February 25, 2008 Re: Difficulty copying multi dimensional static array to dynamic array. | ||||
---|---|---|---|---|
| ||||
Posted in reply to Spacen Jasset | On Mon, 25 Feb 2008 15:13:45 +0000, Spacen Jasset wrote: > All I am trying to do is 'return' an array so that toFloatArray4x4() can be called to fill in a static array. Because for some mysterious reason, one can't pass the static array by reference you probably need to do it the old fashioned way ... void fillArray(float *d, int len) { while (len > 0) { *data = somevalue; data++; len--; } } float[4][4] m1; fillArrary( &m1[0][0], 4 * 4 ); -- Derek Parnell Melbourne, Australia skype: derek.j.parnell |
February 25, 2008 Re: Difficulty copying multi dimensional static array to dynamic array. | ||||
---|---|---|---|---|
| ||||
Posted in reply to Derek Parnell | Using ref should do the trick without pointers.
>
>> All I am trying to do is 'return' an array so that toFloatArray4x4() can be called to fill in a static array.
>
> Because for some mysterious reason, one can't pass the static array by reference you probably need to do it the old fashioned way ...
>
> void fillArray(float *d, int len)
> {
> while (len > 0)
> {
> *data = somevalue;
> data++;
> len--;
> }
> }
>
> float[4][4] m1;
> fillArrary( &m1[0][0], 4 * 4 );
>
> --
> Derek Parnell
> Melbourne, Australia
> skype: derek.j.parnell
|
February 25, 2008 Re: Difficulty copying multi dimensional static array to dynamic array. | ||||
---|---|---|---|---|
| ||||
Posted in reply to Saaa | On Mon, 25 Feb 2008 23:11:11 +0100, Saaa wrote: > Using ref should do the trick without pointers. I agree, but the compiler explicitly disallows using ref with static arrays. Try it yourself. Seems unreasonable to me and no one has explained it to me why this must be so. void fillArray(ref float[4][4] data) { for (int i = 0; i < 4; i++) for (int j = 0; j < 4; j++) data[i][j] = 0.0; } void main() { float[4][4] m1; fillArrary( m1 ); } I get the message "Error: cannot have out or ref parameter of type float[4u][4u]" -- Derek (skype: derek.j.parnell) Melbourne, Australia 26/02/2008 9:33:53 AM |
February 25, 2008 Re: Difficulty copying multi dimensional static array to dynamic array. | ||||
---|---|---|---|---|
| ||||
Posted in reply to Derek Parnell | On Tue, 26 Feb 2008 09:39:49 +1100, Derek Parnell wrote: > On Mon, 25 Feb 2008 23:11:11 +0100, Saaa wrote: > >> Using ref should do the trick without pointers. Oh and if it's "tricks" you want ;-) this works ... import std.stdio; struct nastytrick(T) { T m; } alias float[3][5] a2D; alias nastytrick!(a2D) sa2D; void fillArray(ref sa2D data) { invariant int maxi = data.m.length; invariant int maxj = data.m[0].length; for (int i = 0; i < maxi; i++) for (int j = 0; j < maxj; j++) data.m[i][j] = i*maxj + j; } void main() { sa2D x; // declare static array inside its struct wrapper. fillArray( x ); std.stdio.writefln("%s", x.m); } It seems very odd that a struct can be passed using 'ref' but a fixed length array can't be. -- Derek (skype: derek.j.parnell) Melbourne, Australia 26/02/2008 10:27:35 AM |
February 26, 2008 Re: Difficulty copying multi dimensional static array to dynamic array. | ||||
---|---|---|---|---|
| ||||
Posted in reply to Derek Parnell | Derek Parnell wrote:
> On Tue, 26 Feb 2008 09:39:49 +1100, Derek Parnell wrote:
>
>> On Mon, 25 Feb 2008 23:11:11 +0100, Saaa wrote:
>>
>>> Using ref should do the trick without pointers.
>
> Oh and if it's "tricks" you want ;-) this works ...
>
> import std.stdio;
> struct nastytrick(T)
> {
> T m;
> }
>
> alias float[3][5] a2D;
> alias nastytrick!(a2D) sa2D;
>
> void fillArray(ref sa2D data)
> {
> invariant int maxi = data.m.length;
> invariant int maxj = data.m[0].length;
> for (int i = 0; i < maxi; i++)
> for (int j = 0; j < maxj; j++)
> data.m[i][j] = i*maxj + j;
> }
> void main()
> {
> sa2D x; // declare static array inside its struct wrapper.
> fillArray( x );
> std.stdio.writefln("%s", x.m);
> }
>
> It seems very odd that a struct can be passed using 'ref' but a fixed
> length array can't be.
>
I don't see the mystery. Arrays are *always* passed by reference. You can't use ref because can't change a ref to a static array (becuase it's static?) so it doesn't actually make sense, you can [I think] with a class object -- Chanage it's ref using "ref" keyword so that it points to a new object) So that is all fine and makes sense as far as I can see.
My beef is returning static arrays which you can't do. You can return dynamic ones only.
It makes this impossible:
glMatrixMultiply( mymatrix.toFloatArray16() );
Instead you have to do something like this:
float[4][4] temp;
mymatrix.toFloatArray16ByRef( temp );
glMatrixMultiply( temp );
Or
glMatrixMultiply( *temp.toFloatArrayPointer() );
toFloatArrayPointer is:
float[16] * toFloatArrayPointer()
{
static float[16] matrix;
return &matrix;
}
...and then you can use a wrapping structure and so on. But this isn't 'right' is it? or is it? Can why can I not use something like:
glMatrixMultiply( mymatrix.toFloatArray16() );
where toFloatArray16 is:
float[4][4] toFloatArray()
{
float[4][4] a;
return a; // a is returned like a struct would be. (i.e. copied onto the stack and copied off on return. (or usually optimsed via a pointer on the stack to the callers object perhaps - whatever dmd currently does)
}
|
February 26, 2008 Re: Difficulty copying multi dimensional static array to dynamic array. | ||||
---|---|---|---|---|
| ||||
Posted in reply to Spacen Jasset | Spacen Jasset wrote:
> Derek Parnell wrote:
>> On Tue, 26 Feb 2008 09:39:49 +1100, Derek Parnell wrote:
>>
>>> On Mon, 25 Feb 2008 23:11:11 +0100, Saaa wrote:
>>>
>>>> Using ref should do the trick without pointers.
>>
>> Oh and if it's "tricks" you want ;-) this works ...
>>
>> import std.stdio;
>> struct nastytrick(T)
>> {
>> T m;
>> }
>>
>> alias float[3][5] a2D;
>> alias nastytrick!(a2D) sa2D;
>>
>> void fillArray(ref sa2D data)
>> {
>> invariant int maxi = data.m.length;
>> invariant int maxj = data.m[0].length;
>> for (int i = 0; i < maxi; i++)
>> for (int j = 0; j < maxj; j++)
>> data.m[i][j] = i*maxj + j;
>> }
>> void main()
>> {
>> sa2D x; // declare static array inside its struct wrapper.
>> fillArray( x );
>> std.stdio.writefln("%s", x.m);
>> }
>>
>> It seems very odd that a struct can be passed using 'ref' but a fixed
>> length array can't be.
> I don't see the mystery. Arrays are *always* passed by reference. You can't use ref because can't change a ref to a static array (becuase it's static?) so it doesn't actually make sense, you can [I think] with a class object -- Chanage it's ref using "ref" keyword so that it points to a new object) So that is all fine and makes sense as far as I can see.
>
> My beef is returning static arrays which you can't do. You can return dynamic ones only.
>
> It makes this impossible:
>
> glMatrixMultiply( mymatrix.toFloatArray16() );
>
> Instead you have to do something like this:
>
> float[4][4] temp;
> mymatrix.toFloatArray16ByRef( temp );
> glMatrixMultiply( temp );
>
> Or
>
> glMatrixMultiply( *temp.toFloatArrayPointer() );
>
> toFloatArrayPointer is:
>
> float[16] * toFloatArrayPointer()
> {
> static float[16] matrix;
> return &matrix;
> }
>
>
> ...and then you can use a wrapping structure and so on. But this isn't 'right' is it? or is it? Can why can I not use something like:
>
> glMatrixMultiply( mymatrix.toFloatArray16() );
>
> where toFloatArray16 is:
>
> float[4][4] toFloatArray()
> {
> float[4][4] a;
> return a; // a is returned like a struct would be. (i.e. copied onto the stack and copied off on return. (or usually optimsed via a pointer on the stack to the callers object perhaps - whatever dmd currently does)
> }
You could just store your matrix in the order GL wants, and then do:
glMultMatrixf( mymatrix.ptr );
Where .ptr returns a float* pointing to the first element.
That's going to be hella more efficient than passing around big 16-element float arrays by value.
--bb
|
February 26, 2008 Re: Difficulty copying multi dimensional static array to dynamic array. | ||||
---|---|---|---|---|
| ||||
Posted in reply to Spacen Jasset | On Tue, 26 Feb 2008 00:17:10 +0000, Spacen Jasset wrote: > I don't see the mystery. Arrays are *always* passed by reference. Thanks. I was still under the illusion that fixed length arrays were passed by value. Maybe this will stick in my head now ;-) On the question of returning fixed-length arrays, it does seem like its something that the compiler should be able to do. Good luck with that one. -- Derek (skype: derek.j.parnell) Melbourne, Australia 26/02/2008 12:58:31 PM |
Copyright © 1999-2021 by the D Language Foundation