Recent

Author Topic: Copy the contents of a 2D dynamic array to another one  (Read 23110 times)

Bart

  • Hero Member
  • *****
  • Posts: 5290
    • Bart en Mariska's Webstek
Copy the contents of a 2D dynamic array to another one
« on: January 20, 2018, 07:02:24 pm »
Hi,

Is there a more efficient way of copying the data from one 2D dynamic array to another one (both have the same size) than using a nested for loop?
The datatype of the array is guaranteed to be NOT managed.

(Untested code, too lazy to see if it compiles without error)
Code: [Select]
type
  T2DArr = array of array of Boolean;
var
  A, B: T2DArr;
  R, C: Integer;
begin
  SetLength(A, 20, 10);
  SetLength(B, 20, 10);
  ... //code that fills A
  ...
  //Lazy solution
  for R := Low(A) to Hig(B) do
    for C := Low(A[0]) to High(A[0]) do
      B[R,C] := A[R,C];
end.

Bart

jamie

  • Hero Member
  • *****
  • Posts: 6130
Re: Copy the contents of a 2D dynamic array to another one
« Reply #1 on: January 20, 2018, 07:19:42 pm »
Hmm.

 Have you tried the old standard ?

  CopyMemory(A,B,SizeOf(Boolean)*(20*10)); 

 Dynamic arrays are pointers so....

 
The only true wisdom is knowing you know nothing

Bart

  • Hero Member
  • *****
  • Posts: 5290
    • Bart en Mariska's Webstek
Re: Copy the contents of a 2D dynamic array to another one
« Reply #2 on: January 20, 2018, 07:24:35 pm »
Are multidemnsional dynamic arrays guaranteed to be one contiguous memory block then?
(I know 1 dimensional dynamic arrays are)

Bart

jamie

  • Hero Member
  • *****
  • Posts: 6130
Re: Copy the contents of a 2D dynamic array to another one
« Reply #3 on: January 20, 2018, 07:31:43 pm »
They should be, its a single pointer to the whole pile..
when you do mlti arrays it should be one block of memory partition to fit your
request.
The only true wisdom is knowing you know nothing

Nitorami

  • Sr. Member
  • ****
  • Posts: 496
Re: Copy the contents of a 2D dynamic array to another one
« Reply #4 on: January 20, 2018, 08:50:24 pm »
No, you cannot rely on multidemensional arrays to form a continuous memory block. Mind, the lengths of the vectors can be different, and they can change anytime. E.g. instead of 10x20 your array content could be something like this

0 1 1 1
0 1 0
0
0
1 0 1 1 1...
and this will certainly not be a continuous block.

Why dont'you

Code: Pascal  [Select][+][-]
  1.   for R := Low(A) to High(A) do B[R] := copy (A[R]);
  2.  

Bart

  • Hero Member
  • *****
  • Posts: 5290
    • Bart en Mariska's Webstek
Re: Copy the contents of a 2D dynamic array to another one
« Reply #5 on: January 20, 2018, 09:03:17 pm »
No, you cannot rely on multidemensional arrays to form a continuous memory block. Mind, the lengths of the vectors can be different, and they can change anytime. E.g. instead of 10x20 your array content could be something like this

0 1 1 1
0 1 0
0
0
1 0 1 1 1...

Does that also apply if my code guarantees that the array is always rectangular?

Code: Pascal  [Select][+][-]
  1.   for R := Low(A) to High(A) do B[R] := copy (A[R]);
  2.  

That would re-create (possibly re-allocate) each and every "row" in the target array?

Bart

Nitorami

  • Sr. Member
  • ****
  • Posts: 496
Re: Copy the contents of a 2D dynamic array to another one
« Reply #6 on: January 20, 2018, 09:09:28 pm »
Quote
Does that also apply if my code guarantees that the array is always rectangular?

I would think so, that is how dynamic arrays work. If you want a fixed memory structure, you got to use static arrays e.g. array [0..9,0..19] of boolean.

A one-dimensional dynamic vector (or "row", e.g. "array of boolean") always forms a continous block. But if you make it two-dimensional, the compiler may store the individual vectors wherever it sees fit.

Quote
That would re-create (possibly re-allocate) each and every "row" in the target array?
Yes.

Bart

  • Hero Member
  • *****
  • Posts: 5290
    • Bart en Mariska's Webstek
Re: Copy the contents of a 2D dynamic array to another one
« Reply #7 on: January 20, 2018, 09:19:17 pm »
So, then possibly it would be more efficient to use the CopyMemory (or system.move) on each row?

Bart

Nitorami

  • Sr. Member
  • ****
  • Posts: 496
Re: Copy the contents of a 2D dynamic array to another one
« Reply #8 on: January 20, 2018, 09:25:43 pm »
Quote
So, then possibly it would be more efficient to use the CopyMemory (or system.move) on each row?

Uh... why would you do that ? B := copy(A) is the proper way to copy a one-dimensional array. When using move-

move (A,B, size) will give you an access violation, because the compiler does not only store your data in the array but also some management information at a negative offset. The move would overwrite that. The least you would have to do is
move (A[0], B[0], size)

But that requires that you have allocated the required space for B beforehand manually, and I can't see a reason to to so. If your want to do that, use pointers.

Bart

  • Hero Member
  • *****
  • Posts: 5290
    • Bart en Mariska's Webstek
Re: Copy the contents of a 2D dynamic array to another one
« Reply #9 on: January 20, 2018, 09:49:42 pm »
Move(A, B, Length(A)*SizeOf(DataType)) is what I had in mind.

But that requires that you have allocated the required space for B beforehand manually, and I can't see a reason to to so. If your want to do that, use pointers.

Not sure what you mean here.
In the scenario I have in mind A and B are already allocated.
I need to copy the content of A to B, in order to calculate the new values for A (e.g. to calculate the new value of A[5,5] I need the old value of A[4,5] (amd more) and this contnues while I'm iterating over the cells, so I need a copy (on my "scratch pad" B) of the of the original values of A.

Pseudo code:
Code: [Select]
Allocate A
 Allocate B
 SetUp A
 repeat
  Copy A to B
  Use B to calculate new values for A
 until I want to stop

The size of A can be changed, but this will also trigger a re-allocation of B.
And the repeat loop can start again.

Bart

howardpc

  • Hero Member
  • *****
  • Posts: 4144
Re: Copy the contents of a 2D dynamic array to another one
« Reply #10 on: January 20, 2018, 09:51:39 pm »
If the array is rectangular you can do
Code: Pascal  [Select][+][-]
  1. var
  2.   A, B: T2DArr;
  3.   r, c: Integer;
  4. const
  5.   dimR = 20;
  6.   dimC = 10;
  7. begin
  8.   SetLength(A, dimR, dimC);
  9.   //
  10.   // initialize A
  11.   //
  12.   SetLength(B, dimR, dimC);
  13.   B:=Copy(A, 0, dimR*dimC*Sizeof(Boolean));
« Last Edit: January 20, 2018, 10:01:07 pm by howardpc »

Nitorami

  • Sr. Member
  • ****
  • Posts: 496
Re: Copy the contents of a 2D dynamic array to another one
« Reply #11 on: January 20, 2018, 09:57:32 pm »
Bart: You may do it like that if you handle the move correctly, but I understand your "scratch pad" B is for temporary use anyway, so why would you allocate it beforehand ?

howardpc: Copying dynamic arrays using copy() does not require separate memory allocation, neither manual calculation of element size. I don't think that would work.

Thaddy

  • Hero Member
  • *****
  • Posts: 14373
  • Sensorship about opinions does not belong here.
Re: Copy the contents of a 2D dynamic array to another one
« Reply #12 on: January 20, 2018, 10:17:13 pm »
If the array is rectangular you can do
You can do that with any dimension as long as the array is planar in all dimensions (any dimension) and given memory boundary limitations. You can flatten the array given x,(((y z),y)(z,v)),z,v) order.
You can even declare an array type of different dimensions as absolute on any other planar array. Given memory limitations. e.g. 8086 --> 64K

In Bart's case I would declare twice the array at the same location using absolute.
Code: Pascal  [Select][+][-]
  1. var
  2.   a:array[0..9,0..9] of integer;
  3.   b:array[0..99] of integer absolute a;

Proof:
Code: Pascal  [Select][+][-]
  1. program arrayfun;
  2. {$ifdef fpc}{$mode delphi}{$H+}{$I-}{$endif}
  3. var
  4.   a:array[0..2,0..2,0..2] of integer;      //3 dimensions
  5.   b:array[0..26] of integer absolute a;//1 dimension
  6.   i,j,k:integer;  
  7. begin
  8.   for i := 0 to 26 do b[i] := i;
  9.   for i := 0 to 2 do
  10.     for j:= 0 to 2 do
  11.       for k := 0 to 2 do
  12.         writeln(a[i,j,k]);  // the cumbersome way to write out b[]
  13. end.

In principle this goes for any array that is planar with any dimension. e.g 0..x,0..y, depth, time.. etc

Note this is NOT implementation detail. It is how arrays work. Mathematically too, they are symmetrical functions of each other  a=f(b) and b=f(a) representing the same data in any order. The compiler may have to work around this given memory limitations, as explained. Planar, because the dimensions need to be related by a power function.  It does not need to be square, but needs to be a rectangle (of possibly different size ) in all directions. E.g:
Code: Pascal  [Select][+][-]
  1. program arrayfun2;
  2. {$ifdef fpc}{$mode delphi}{$H+}{$I-}{$endif}
  3. var
  4.   a:array[0..1,0..7,0..3] of integer;
  5.   b:array[0..63] of integer absolute a;
  6.   i,j,k:integer;  
  7. begin
  8.   for i := 0 to 63 do b[i] := i;
  9.   for i := 0 to 1 do
  10.     for j:= 0 to 7 do
  11.       for k := 0 to 3 do
  12.         writeln(a[i,j,k]);
  13. end.

Oh and the answer:
Code: Pascal  [Select][+][-]
  1. type
  2.   T2DArr = array of array of Boolean;
  3. var
  4.   A, B: T2DArr;
  5. begin
  6.   SetLength(A, 20, 10);
  7.   B:= A;
  8. end.
« Last Edit: January 20, 2018, 11:16:30 pm by Thaddy »
Object Pascal programmers should get rid of their "component fetish" especially with the non-visuals.

Thaddy

  • Hero Member
  • *****
  • Posts: 14373
  • Sensorship about opinions does not belong here.
Re: Copy the contents of a 2D dynamic array to another one
« Reply #13 on: January 20, 2018, 11:19:57 pm »
The datatype of the array is guaranteed to be NOT managed.
A dynamic array is by definition a managed type ,Bart. What do you mean? Otherwise give it dimensions and declare it bitpacked. (much more efficient. Assignment copy stays too (last example)
Nitorami put you in the wrong direction.  The assignment will do the copy.

E.g:
Code: Pascal  [Select][+][-]
  1. program arrayfun3;
  2. {$ifdef fpc}{$mode delphi}{$H+}{$I-}{$endif}
  3. type
  4.   T2DArr = bitpacked array[0..3] of bitpacked array[0..3] of Boolean;
  5. var
  6.   A, B: T2DArr;
  7.   R, C: Integer;
  8. begin
  9.  for R:= 0 to 3 do
  10.    for C := 0 to 3 do
  11.    if Odd(R) then A[R,C] := true else  a[R,C] := false;
  12.  B:=A; // simply assign
  13.  for R := 0 to 3 do
  14.    for C := 0 to 3 do
  15.    writeln(b[r,c]);
  16. end.
« Last Edit: January 20, 2018, 11:33:06 pm by Thaddy »
Object Pascal programmers should get rid of their "component fetish" especially with the non-visuals.

Bart

  • Hero Member
  • *****
  • Posts: 5290
    • Bart en Mariska's Webstek
Re: Copy the contents of a 2D dynamic array to another one
« Reply #14 on: January 20, 2018, 11:26:20 pm »
@Nitorami: The "scratchpad" is needed during the complete time of the program (that is, until the user changes the dimensions of the array, at which point I recreate both arrays).

@Thaddy: I can't use absolute. As I described I need the "old" contents of A to calculate the new one, in such a way that, just iterationg over A and changing the "cells" along, is not going to work, because I wille need the old value of "cell" I have changed, after I have moved to the next one.

And:
Code: Pascal  [Select][+][-]
  1.   A := B;
  2.  

AFAIK, this will make B now point to A, and if I change B, in essence I change A.
See the example in https://www.freepascal.org/docs-html/ref/refsu14.html#x38-510003.3.1.

Bart
« Last Edit: January 20, 2018, 11:35:26 pm by Bart »

 

TinyPortal © 2005-2018