Jump to page: 1 2
Thread overview
to! converting 1D to 2D array
Mar 12, 2014
ed
Mar 12, 2014
bearophile
Mar 12, 2014
ed
Mar 12, 2014
monarch_dodra
Mar 12, 2014
bearophile
Mar 12, 2014
monarch_dodra
Mar 13, 2014
ed
Mar 13, 2014
Marc Schütz
Mar 13, 2014
Chris Williams
Mar 13, 2014
ed
Mar 13, 2014
Chris Williams
Mar 14, 2014
ed
Mar 14, 2014
ed
Mar 14, 2014
Chris Williams
Mar 14, 2014
ed
Mar 14, 2014
ed
Mar 22, 2014
Marc Schütz
March 12, 2014
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
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
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
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
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
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
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
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
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
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.
« First   ‹ Prev
1 2