Recent

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

jamie

  • Hero Member
  • *****
  • Posts: 6130
Re: Copy the contents of a 2D dynamic array to another one
« Reply #30 on: January 21, 2018, 07:47:32 pm »
Using a table 0..7 is much much faster.

 Create an array table that has the 0..7 bit address needed to do the logical masking and
simply index it for the masking value..
The only true wisdom is knowing you know nothing

Bart

  • Hero Member
  • *****
  • Posts: 5289
    • Bart en Mariska's Webstek
Re: Copy the contents of a 2D dynamic array to another one
« Reply #31 on: January 21, 2018, 10:54:52 pm »
OK, in the real world of my program I opted for the B := Copy(A) method, only to fins out that writeng to B now also wrote to A:

Code: Pascal  [Select][+][-]
  1.   A[R,C] := 0;
  2.   B := Copy(A); //or Copy(A, 0, total number of elements)
  3.   B[R,C] := 1;
  4.   writeln(A[R,C]); //gives 1, instead of 0
  5.  

Copying each row seperately did work however.
(fpc 3.0.4 on win32)

Bart

Mr.Madguy

  • Hero Member
  • *****
  • Posts: 844
Re: Copy the contents of a 2D dynamic array to another one
« Reply #32 on: January 22, 2018, 02:58:51 pm »
Each dynamic array variable is pointer to structure like this:
Code: Pascal  [Select][+][-]
  1. TDynamicArray<T> = record
  2.   Length:Integer;
  3.   Data:array[0..Length-1] of T;
  4. end;
  5. PDynamicArray = ^TDynamicArray;
  6.  
i.e.
Code: Pascal  [Select][+][-]
  1. A, B:PDynamicArray;
  2.  
2D array - is just array of dynamic arrays, i.e. array of pointers to nested structures.

B := A simply copies pointer, so they both reference to the same data.

B := Copy(A) allocates new pointer for B, but copies the same pointers of A[n], i.e. result will still reference to same data.

Only B[n] := Copy(A[n]) works properly.
« Last Edit: January 23, 2018, 09:11:24 am by Mr.Madguy »
Is it healthy for project not to have regular stable releases?
Just for fun: Code::Blocks, GCC 13 and DOS - is it possible?

Bart

  • Hero Member
  • *****
  • Posts: 5289
    • Bart en Mariska's Webstek
Re: Copy the contents of a 2D dynamic array to another one
« Reply #33 on: January 22, 2018, 08:54:48 pm »
Thanks for explaining.

Bart

han

  • Jr. Member
  • **
  • Posts: 96
Re: Copy the contents of a 2D dynamic array to another one
« Reply #34 on: January 27, 2019, 09:24:53 pm »
This is an old topic but none of the methods worked well for for multidimensional dynamic arrays. This one worked for me and hasn't been mentioned:

For a 3D array:
Code: [Select]
 
    B:=A;
    setlength(B,colors,width2,height2);{this forces a duplication}

   {In dynamic arrays, the assignment statement duplicates only the reference to the array, while SetLength does the job of }
    {physically copying/duplicating it, leaving two separate, independent dynamic arrays.}


For 1D array:

Code: [Select]

    B:= A;
    SetLength(B,Length(A));{this forces a duplication}


See: https://stackoverflow.com/questions/3545449/is-there-way-of-copying-the-whole-array-into-another-array-other-than-using-a/3545758#3545758

And the width of 2D array:
Code: [Select]

   width2:=length(A[length(A)-1]);

   width2:=length(A[0]);didn't work in all cases.







Kays

  • Hero Member
  • *****
  • Posts: 575
  • Whasup!?
    • KaiBurghardt.de
Re: Copy the contents of a 2D dynamic array to another one
« Reply #35 on: January 28, 2019, 03:31:30 am »
[…] This one worked for me and hasn't been mentioned:

[…]
Code: [Select]
 
   […]
   { […] while SetLength does the job of  […] physically copying/duplicating it, leaving two separate, independent dynamic arrays.}
   […]
  […]

I put this in the wiki just a couple months ago. However, care must be taken with multi-dimensional arrays. Copying with setLength only works well for rectangular matrices.

I don't know how to do (a convenient) deep copy preserving varying lengths of the inner array. You must see that
Code: Pascal  [Select][+][-]
  1. array of array of boolean
is better (in your mind) regarded as two separate types
Code: Pascal  [Select][+][-]
  1. booleanSequence = array of boolean;
  2. booleanLists = array of booleanSequence;
So, since booleanLists is an array of pointers, you can't just do a memory copy starting at the address n[0, 0]. You're with nothing left but iterating over the arrays again, yikes:
Code: Pascal  [Select][+][-]
  1. program multidimensionalDynamicArrayCopy(input, output, stderr);
  2. type
  3.         booleanSequence = array of boolean;
  4.         booleanLists = array of booleanSequence;
  5. var
  6.         m, n: booleanLists;
  7.         i: int64;
  8. begin
  9.         m := booleanLists.create(
  10.                         booleanSequence.create(false),
  11.                         booleanSequence.create(false, false)
  12.                 );
  13.         // copy reference
  14.         n := m;
  15.         // copy data
  16.         setLength(n, length(n));
  17.        
  18.         // alter data via original array
  19.         m[0, 0] := true;
  20.         // we will read altered data
  21.         writeLn(n[0, 0]);
  22.        
  23.         // ensure we really copy _everything_
  24.         for i := low(n) to high(n) do
  25.         begin
  26.                 setLength(n[i], length(n[i]));
  27.         end;
  28.        
  29.         // only _then_ modifying data via original reference doesn't harm
  30.         m[0, 0] := false;
  31.         writeLn(n[0, 0]);
  32. end.
« Last Edit: January 28, 2019, 04:34:09 pm by Kays »
Yours Sincerely
Kai Burghardt

Mr.Madguy

  • Hero Member
  • *****
  • Posts: 844
Re: Copy the contents of a 2D dynamic array to another one
« Reply #36 on: January 28, 2019, 10:32:08 am »
Is this behavior Delphi-compatible? I don't like it, cuz it isn't intuitive. I think, SetLength is expected to work the same way, as ReallocMem, i.e. to minimize amount of data copying for optimization purposes. Are you sure, it works this way on all platforms? Have you checked it's source code? Cuz may be it's certain memory manager's behavior. May be it's better to add new function for that purpose, that will have this behavior explicitly?
Is it healthy for project not to have regular stable releases?
Just for fun: Code::Blocks, GCC 13 and DOS - is it possible?

User137

  • Hero Member
  • *****
  • Posts: 1791
    • Nxpascal home
Re: Copy the contents of a 2D dynamic array to another one
« Reply #37 on: January 28, 2019, 11:16:56 am »
Anything performance demanding such as pixel data of a 2D image is always defined in 1-dimensional array. You can straight up copy the values with a single call, or go through each data index by incrementing the pointer.

Mr.Madguy

  • Hero Member
  • *****
  • Posts: 844
Re: Copy the contents of a 2D dynamic array to another one
« Reply #38 on: January 28, 2019, 03:15:12 pm »
Due to some reasons I currently don't have access to official Embarcadero docs, but, as I remember, strings are always copied and dynamic arrays are never copied. Even if they should be, it should happen, when RefCount > 1 and size changes, but not always. Dunno. I've been always relying on "no size change -> no dyn array change" behaviour. If it's not the case, then I should review my code.
Is it healthy for project not to have regular stable releases?
Just for fun: Code::Blocks, GCC 13 and DOS - is it possible?

ASerge

  • Hero Member
  • *****
  • Posts: 2241
Re: Copy the contents of a 2D dynamic array to another one
« Reply #39 on: January 28, 2019, 04:25:31 pm »
Is this behavior Delphi-compatible? I don't like it, cuz it isn't intuitive. I think, SetLength is expected to work the same way, as ReallocMem, i.e. to minimize amount of data copying for optimization purposes.
On the contrary, it is intuitively clear that if there is a reference counting then before the change it is necessary to ensure the uniqueness of the reference, i.e. in fact there will be deep copy. What is also indicated in the FPC documentation SetLength.

Due to some reasons I currently don't have access to official Embarcadero docs, but, as I remember, strings are always copied and dynamic arrays are never copied.
Embarcadero documentation is open. From SetLength: For multidimensional dynamic arrays, SetLength may take more than one-length parameter (up to the number of array dimensions)...Following a call to SetLength, S is guaranteed to reference a unique string or array. This is also true for FPC
There are only two fundamental differences between dynamic strings and dynamic arrays: support for code pages, and copy-on-write when replacing an individual string element (which is backward compatible with old strings).

han

  • Jr. Member
  • **
  • Posts: 96
Re: Copy the contents of a 2D dynamic array to another one
« Reply #40 on: January 28, 2019, 09:32:23 pm »
I would suggest to improve the compiler behavior. E.g.:

B:=A; {copies the pointer}
B:=copy(A); {make a physical copy of the 2D, 3D array (proposed)}

jamie

  • Hero Member
  • *****
  • Posts: 6130
Re: Copy the contents of a 2D dynamic array to another one
« Reply #41 on: January 28, 2019, 11:06:34 pm »
The issue is how the multi dimension arrays are built using jump tables in the array via absolute values.

 This is why you can't do a standard memory move/copy because the abs addresses will still be pointing to the
source array and if you delete the source array, there goes your memory and most likely and access violation.

 So currently you would need to do a memory move on each row of the array since getting the address from
these points will return the entry point.

 This all makes it so the array is fixed into one location of memory, its not a relative addressed multi array.

 The simple fix for this would be to instead of absolute addressing, use OFFSET/Relative addressing in these
tables, the compiler would simply ADD these values to the base address of the array to get to the desired slot.

 Doing so would allow a bulk copy of the array from one to another of the same configuration and it would also
allow a common entry point to the bulk of the data.
The only true wisdom is knowing you know nothing

User137

  • Hero Member
  • *****
  • Posts: 1791
    • Nxpascal home
Re: Copy the contents of a 2D dynamic array to another one
« Reply #42 on: January 28, 2019, 11:23:48 pm »
It's not a simple fix. Having 2-dimensional array's data to be continuous would break 2 things, first the definition that each row can have different length, and secondly it would make performance a lot worse if you added 1 column to first row. It would resize the entire array instead of just the row.

jamie

  • Hero Member
  • *****
  • Posts: 6130
Re: Copy the contents of a 2D dynamic array to another one
« Reply #43 on: January 28, 2019, 11:40:32 pm »
What?

 I don't think you understood what I said or maybe don't understand how the underlayer if for a two dim array

 There is no Resizing taking place..

 You can use the standard memory features and create a Array dynamically and the compiler then just
knows where everything is.. , A bulk of memory.

 But using a managed array is a different story, the short story is, use OFFSET values instead of absolute
in the table.
 
 We are not talking about changing the size of any element in the multi dim array, just the way it knows where
all the starting rows are and they should be OFFSETS not absolutes..

 If you really think that is going to make a basket case out of it then I think you are on the wrong track..

Oh well, That is all I'll say about that one..

The only true wisdom is knowing you know nothing

PascalDragon

  • Hero Member
  • *****
  • Posts: 5469
  • Compiler Developer
Re: Copy the contents of a 2D dynamic array to another one
« Reply #44 on: January 30, 2019, 10:55:55 am »
No, User137 understood it correctly: a dynamic array of dynamic arrays is essentially an array of Pointers. Each of these pointers points to another dynamic array which all can have different lengths. The compiler has absolutely no knowledge about the memory layout. One of those sub elements could reside at the start of the heap, another at the end, a third somewhere in between. This is by design.
If you want a consecutive memory layout for multi dimensional arrays use a static array or write your own type that handles that based on a single junk of memory plus array properties for access.

 

TinyPortal © 2005-2018