Thread overview | |||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
March 12, 2014 to! converting 1D to 2D array | ||||
---|---|---|---|---|
| ||||
Hi All, I am trying to convert a 1D array to a 2D array using to! and was wondering if someone could explain to me why this first example works but the second example does not compile: Example 1: ~~~ import std.conv; long[4] a=[1,2,3,4]; int[2][2] b = to!(int[])(a); assert(b == [[1,2],[3,4]]); ~~~~ Example 2: ~~~ import std.conv; long[4] a=[1,2,3,4]; int[2][2] b; b = to!(int[])(a); assert(b == [[1,2],[3,4]]); ~~~~ Error: cannot implicitly convert expression (to(a[])) of type int[][] to int[2][]. It's like the ReturnType in to!()() for Example 1 and Example 2 is different. Is this the case and why would it be so? If not, what is happening here? Thanks, ed |
March 12, 2014 Re: to! converting 1D to 2D array | ||||
---|---|---|---|---|
| ||||
Posted in reply to ed | ed:
> I am trying to convert a 1D array to a 2D array
If you have a dynamic array (1D), you can convert it to a dynamic array of dynamic arrays (2D) using chunks:
void main() {
import std.stdio, std.range, std.algorithm;
int[] a = [1, 2, 3, 4, 5, 6];
int[][] b = a.chunks(2).array;
b.writeln;
}
Output:
[[1, 2], [3, 4], [5, 6]]
Your problems are caused by mixing fixed-size arrays (that are values, allocated in-place), with dynamic arrays (that are little length+pointer structs that often point to heap-allocated memory).
Bye,
bearophile
|
March 12, 2014 Re: to! converting 1D to 2D array | ||||
---|---|---|---|---|
| ||||
Posted in reply to bearophile | On Wednesday, 12 March 2014 at 02:14:45 UTC, bearophile wrote:
> ed:
>
>> I am trying to convert a 1D array to a 2D array
>
> If you have a dynamic array (1D), you can convert it to a dynamic array of dynamic arrays (2D) using chunks:
>
>
> void main() {
> import std.stdio, std.range, std.algorithm;
>
> int[] a = [1, 2, 3, 4, 5, 6];
> int[][] b = a.chunks(2).array;
> b.writeln;
> }
>
>
> Output:
>
> [[1, 2], [3, 4], [5, 6]]
>
> Your problems are caused by mixing fixed-size arrays (that are values, allocated in-place), with dynamic arrays (that are little length+pointer structs that often point to heap-allocated memory).
>
> Bye,
> bearophile
Thanks for explaining this, it makes sense what you said. But I'm still not sure why my original Example 1 worked.
~~~
// This works OK and converts long[4] to int[] then implicitly to int[2][2]
long[4] a=[1,2,3,4];
int[2][2] b = to!(int[])(a);
// Why does this not work the same way?
long[4] a=[1,2,3,4];
int[2][2] b;
b = to!(int[])(a);
~~~
My understanding of your explanation is that it shouldn't work.
Cheers,
ed
|
March 12, 2014 Re: to! converting 1D to 2D array | ||||
---|---|---|---|---|
| ||||
Posted in reply to ed | On Wednesday, 12 March 2014 at 03:37:49 UTC, ed wrote:
> Thanks for explaining this, it makes sense what you said. But I'm still not sure why my original Example 1 worked.
>
> ~~~
> // This works OK and converts long[4] to int[] then implicitly to int[2][2]
> long[4] a=[1,2,3,4];
> int[2][2] b = to!(int[])(a);
>
> // Why does this not work the same way?
> long[4] a=[1,2,3,4];
> int[2][2] b;
> b = to!(int[])(a);
> ~~~
>
> My understanding of your explanation is that it shouldn't work.
>
>
> Cheers,
> ed
I *believe* it's really just that you are allowed to *initialize* a static array (of any depth) from a dynamic array.
However, for assignment, it doesn't work that way:
int[] a = [0, 1, 2, 3];
int[2][1][2][1] b = a; //OK!
b = a; //ERROR
If you want do want to do the assignment, you'll have to re-interpret your array's layout:
int[] a = [0, 1, 2, 3];
int[2][1][2][1] b;
*cast(int[4]*)&b = a;
assert(b == [[[[0, 1]], [[2, 3]]]]);
|
March 12, 2014 Re: to! converting 1D to 2D array | ||||
---|---|---|---|---|
| ||||
Posted in reply to monarch_dodra | monarch_dodra:
> int[] a = [0, 1, 2, 3];
> int[2][1][2][1] b;
> *cast(int[4]*)&b = a;
> assert(b == [[[[0, 1]], [[2, 3]]]]);
Those pointers are not needed:
cast(int[4])b = a;
Bye,
bearoophile
|
March 12, 2014 Re: to! converting 1D to 2D array | ||||
---|---|---|---|---|
| ||||
Posted in reply to bearophile | On Wednesday, 12 March 2014 at 07:43:46 UTC, bearophile wrote:
> monarch_dodra:
>
>> int[] a = [0, 1, 2, 3];
>> int[2][1][2][1] b;
>> *cast(int[4]*)&b = a;
>> assert(b == [[[[0, 1]], [[2, 3]]]]);
>
> Those pointers are not needed:
>
> cast(int[4])b = a;
>
> Bye,
> bearoophile
I'm *never* actually sure if these kinds of casts are value casts, or re-interpreting casts.
Thanks.
|
March 13, 2014 Re: to! converting 1D to 2D array | ||||
---|---|---|---|---|
| ||||
Posted in reply to ed | On Wednesday, 12 March 2014 at 03:37:49 UTC, ed wrote:
> My understanding of your explanation is that it shouldn't work.
It shouldn't and probably isn't working. If nothing else, when you use to!(x)(y), "x" should be the type that you're trying to convert into. So I would expect your code to be to!(int[2][2])(a). I would still be impressed if that worked, since std.conv is intended more for parsing strings into ints and stuff, not for splitting and grouping arrays.
Your assertion probably succeeds because in memory a two dimensional array is arranged with the first row followed by the second row. So a flat array of four items and a 2-D array of two arrays of two items end up laying out the same in memory. Some how it's going straight to memory and comparing them that way (maybe).
|
March 13, 2014 Re: to! converting 1D to 2D array | ||||
---|---|---|---|---|
| ||||
Posted in reply to Chris Williams | On Thursday, 13 March 2014 at 00:15:19 UTC, Chris Williams wrote: [snip] > It shouldn't and probably isn't working. It is working and in fact it is in a "const pure @safe" function. So I will trust it :-) > If nothing else, when you use to!(x)(y), "x" should be the type that you're trying to convert into. So I would expect your code to be to!(int[2][2])(a). Yes, I'm aware of this, the conversion I was doing is as follows: long[4] -> to! -> int[] ->implicit conv. -> int[2][2]. it is the implicit conversion that was failing, not the to! function. I didn't realise this until after bearophile's reply :D Thanks, ed |
March 13, 2014 Re: to! converting 1D to 2D array | ||||
---|---|---|---|---|
| ||||
Posted in reply to bearophile | On Wednesday, 12 March 2014 at 07:43:46 UTC, bearophile wrote:
> monarch_dodra:
>
>> int[] a = [0, 1, 2, 3];
>> int[2][1][2][1] b;
>> *cast(int[4]*)&b = a;
>> assert(b == [[[[0, 1]], [[2, 3]]]]);
>
> Those pointers are not needed:
>
> cast(int[4])b = a;
>
> Bye,
> bearoophile
Thanks for this, the casts work perfectly albeit a little ugly :D
Cheers,
ed
|
March 13, 2014 Re: to! converting 1D to 2D array | ||||
---|---|---|---|---|
| ||||
Posted in reply to ed | On Thursday, 13 March 2014 at 03:31:09 UTC, ed wrote:
> On Thursday, 13 March 2014 at 00:15:19 UTC, Chris Williams wrote:
> [snip]
>> It shouldn't and probably isn't working.
>
> It is working and in fact it is in a "const pure @safe" function. So I will trust it :-)
Well it's like a broken watch being correct twice a day. The correct result doesn't mean that something is working.
I'm glad you've found a solution though.
|
Copyright © 1999-2021 by the D Language Foundation