copy a 2d array to another - Programmers Heaven

Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Categories

Welcome to the new platform of Programmer's Heaven! We apologize for the inconvenience caused, if you visited us from a broken link of the previous version. The main reason to move to a new platform is to provide more effective and collaborative experience to you all. Please feel free to experience the new platform and use its exciting features. Contact us for any issue that you need to get clarified. We are more than happy to help you.

copy a 2d array to another

MalekovitsMalekovits Posts: 24Member
Hi! I know that there are some ways for copying (2d)arrays in pascal (I use borland pascal). One is to use for-loops and the other one is to use something like array1:=array2. That's what i know so far. Of course i know that there is the fillchar that fills an array with a specified character. I wonder how to do this without for-loops:

copy an array into another but only some elements. To be more specific, the array i want to copy is char type, and it has empty elements(even if you don't put something, the space itself is a character.)that i dont want to be copied to the other array. Until now I did this with for-loops:

for i:=1 to 10 do
for j:=1 to 10 do
if array1[i,j] <> ' ' do array2[i,j]:=array1[i,j];

Is there any way that i can do the same thing without for loops? With for loops its very very slow, but when use something like array1:=array2
its blazingly faster, but then you copy everything that array2 has, and I want NOT to copy the "empty" or " " characters (or any one else character that might be specified). Hope you understand what I am saying...

Comments

  • _Atex__Atex_ Posts: 163Member
    : Is there any way that i can do the same thing without for loops?
    : With for loops its very very slow, but when use something like
    : array1:=array2
    : its blazingly faster, but then you copy everything that array2 has,
    : and I want NOT to copy the "empty" or " " characters (or any one
    : else character that might be specified). Hope you understand what I
    : am saying...

    The only way I know is to do it in assembly, optimize it as much as possible and see if is there any speed improvement, but you have to have loops no matter what. Even a simple assumption like: array1:=array2 involves a loop on machine level. Including an example here, see if it helps:[code][blue]{ Copy from "source" to "dest", "count" number of bytes }
    { "source" and "dest" should NOT overlap in memory }
    procedure copyfast(source,dest:pointer;count:word);assembler;
    asm
    mov dx,ds { save data segment in dx }
    mov cx,count { get count in cx }
    les di,dest { es:di <-- dest }
    lds si,source { ds:si <-- source }
    shr cx,1 { cx:=cx div 2 }
    cld { clear direction flag }
    rep movsw { loop: copy one word fron source to dest }
    adc cx,cx { leftover byte ? }
    rep movsb
    mov ds,dx { restore data segment }
    end;


    { Selective copy from "source" to "dest", "count" number of bytes }
    { Will not copy the exemption values specified in "exempt" }
    { "source" and "dest" should NOT overlap in memory }
    { Returns the actual number of bytes copied }
    function copyselective(source,dest:pointer;count:word;exempt:byte):word;assembler;
    asm
    mov dx,ds { save data segment in dx }
    mov bl,exempt { get exemt in bl }
    mov cx,count { get count in cx }
    les di,dest { es:di <-- dest }
    lds si,source { ds:si <-- source }
    push dx { save dx in stack }
    sub dx,dx { dx:=0 }
    @1:
    mov al,ds:[si] { get a byte from source }
    inc si { increase source index }
    cmp al,bl { compare byte with exempt }
    je @2 { equal ? jump to @2 }
    mov es:[di],al { not equal --> copy to dest }
    inc di { increase destination index }
    inc dx { dx:=dx+1 }
    @2:
    loop @1 { decrease cx, jump to @1 }
    mov ax,dx { return no. of bytes copied }
    pop dx { restore dx from stack }
    mov ds,dx { restore data segment }
    end;


    type _array_=array[1..20] of byte;

    var a1,a2:^_array_;
    i:byte;

    begin
    new(a1);new(a2);

    fillchar(a1^,sizeof(a1^),1); { fill a1 with 1's }
    fillchar(a2^,sizeof(a2^),0); { fill a2 with 0's }
    write('a1= ');for i:=1 to 19 do write(a1^[i],',');writeln(a1^[20]);
    write('a2= ');for i:=1 to 19 do write(a2^[i],',');writeln(a2^[20]);
    copyfast(a1,a2,20);
    write('a2= ');for i:=1 to 19 do write(a2^[i],',');writeln(a2^[20],#13#10);
    readln;

    for i:=1 to 20 do a1^[i]:=i;
    fillchar(a2^,sizeof(a2^),0); { fill a2 with 0's }
    write('a1= ');for i:=1 to 19 do write(a1^[i],',');writeln(a1^[20]);
    write('a2= ');for i:=1 to 19 do write(a2^[i],',');writeln(a2^[20]);
    writeln(copyselective(a1,a2,20,5),' bytes copied'); { copy all, except value: 5}
    write('a2= ');for i:=1 to 19 do write(a2^[i],',');writeln(a2^[20]);
    readln;

    dispose(a2);dispose(a1);
    end.[/blue][/code]
  • MalekovitsMalekovits Posts: 24Member
    Thanks a lot, but I can't understand it, because I know nothing about assembly.. Of course the simple assumption you said has a loop inside it, but as I can understand, its something like this:

    in the for-loop its going to start something and end it, about 10 x 10 = 100 times (start 100 times, stop 100 times):

    for i:=1 to 10 do
    for j:=1 to 10 do

    but the simple assumption I thing its something like start something and end it, only for once, as I imagine, because it treats the array like a chain, so its way faster.

    All these years that i know some pascal, I always used the for loops for arrays and just about 2 days ago I saw in the net the simple assumption :-O!!! ant the fillchar function that can "erase" an array blazingly fast!!! Yes, something very very simple and I didn't thought it before!!!

    I was hoping for something like a function to copy arrays that might have parametres to set, statements.. Unfortunately, I don't have any idea about assembly code..
  • _Atex__Atex_ Posts: 163Member
    :
    : but the simple assumption I thing its something like start something
    : and end it, only for once, as I imagine, because it treats the array
    : like a chain, so its way faster.

    The code I posted treats an array like a chain, and it's fast as 16bit code can be. It's possible to make it almost 2x faster by upgrading it to 32bit.

    : I was hoping for something like a function to copy arrays that might
    : have parametres to set, statements.. Unfortunately, I don't have any
    : idea about assembly code..

    Well, that's what it does, but it would be way too complex to handle all kinds of arrays (including data types, dimensional structures etc.), instead works directly with the memory so it could handle everything you pass down to it while being simple thus fast. The only issue is that you have to use dynamic variables (pointers) instead, you don't have to worry about the asm code just observe the main part of my example which shows how to use those assembly routines. Also, it's a good idea to befriend dynamic data types if you want to move past the 64 kByte limit of the data segment. Anyway, for a 100 element array there is no substantial speed gain using assembly vs. plain pascal code...


  • MalekovitsMalekovits Posts: 24Member
    Ok, I am going to give it a try! Unfortunately I haven't still work with dynamic variables (pointers), and this and assembly code is difficult for me to understand... By the way, what do you mean that its going to be 2x faster in 32bit?? How to do this (if use a 32bit pascal, right?) ? Anyway, thanks man! Once I put it in my program I am making,I am going to post again!
  • _Atex__Atex_ Posts: 163Member
    : Ok, I am going to give it a try! Unfortunately I haven't still work
    : with dynamic variables (pointers), and this and assembly code is
    : difficult for me to understand...

    That's OK if you don't understand those assembly routines, just use them as any other procedure on function, all pascal routines are written in asm by the way.

    : its going to be 2x faster in 32bit?? How to do this (if use a 32bit
    : pascal, right?) ? Anyway, thanks man! Once I put it in my program I
    : am making,I am going to post again!

    Borland Pascal is 16bit, if you use Free Pascal that's either 32 or 64bit. Like all Dos era programs BP is running on a virtual machine under Windows, because is emulated tends to run way slower than it would on a Dos machine. If you really looking for speed than upgrade to FP and watch the difference. How 32bit is faster, here's an example: for a 100 element array if you van to copy byte by byte to another array the it would loop 100 times. One byte is 8bit therefore if you do the copying by using words instead (16 bit) then it would loop 50 times (2 bytes at a time), so is 2x faster. Going up to 32bit you'd copy longwords so it would loop 25 times (4 bytes at a time), that's 2x faster than 16bit, 4x faster than the original 8bit operation. Is possible to do this with BP, using assembly:[code][color=Blue]procedure copyfaster(source,dest:pointer;count:word);assembler;
    asm
    mov dx,ds { save data segment in dx }
    mov cx,count { get count in cx }
    les di,dest { es:di <-- dest }
    lds si,source { ds:si <-- source }
    mov bl,cl { bl:=cl; }
    and bl,3 { bl:=bl mod 4 }
    shr cx,2 { cx:=cx div 4 }
    cld { clear direction flag }
    db $66;rep movsw { loop: copy one dword (32bit) from source to dest }
    mov cl,bl { cl:=bl; }
    rep movsb { leftover bytes ? 0..3 }
    mov ds,dx { restore data segment }
    end;[/color][/code]


  • MalekovitsMalekovits Posts: 24Member
    OK!! I didn't knew that dos in windows(xp) is like java! (virtual machine):-o! Of course I run my program using dos box! Well, I know its not the best way to make a program and run it, but I know good pascal, that's why I use it. Also I use BP because I like the environment (the editor), free pascal is not so pleasant environment to work... I am trying to make a 3d renderer (not raytracer). Until now, I've made a 2d rotating triangle, and I have made a framebuffer-like effect (motion-blur) as the triangle rotates, and this has 5 arrays that one is copied to another, that's why I need a the copyselective function of yours.

    here is the first image ever:
    [img=http://img.photobucket.com/albums/v327/Malekovits/5c1b8b60.jpg]
    and here is using graph and a fill code I made to fill the triangle! (I am using graph only to have a pixel output):
    [img=http://img.photobucket.com/albums/v327/Malekovits/trid.jpg]

    (The frame-buffer effect in not in these images, I haven't post any image with the effect)

    One thing I noticed, (maybe it's stupid what I am saying but I don't know what to do) is that the function(s) you wrote are being used in a single-dimension array

    copyselective(a1,a2,[u]20[/u],5)

    The 20 is for the count, right? But what if I want to use it in a 2d array???
  • _Atex__Atex_ Posts: 163Member
    : I am trying to make a 3d renderer (not raytracer). Until now, I've
    : made a 2d rotating triangle, and I have made a framebuffer-like effect
    : (motion-blur) as the triangle rotates, and this has 5 arrays that one
    : is copied to another...

    Post your code when ready, someone might find it useful.

    : Also I use BP because I like the
    : environment (the editor), free pascal is not so pleasant environment
    : to work...

    It has almost the same IDE

    : One thing I noticed, (maybe it's stupid what I am saying but I don't
    : know what to do) is that the function(s) you wrote are being used in
    : a single-dimension array
    :
    : copyselective(a1,a2,[u]20[/u],5)
    :
    : The 20 is for the count, right? But what if I want to use it in a 2d
    : array???

    It can be used for any type of array or data type ( hence the importance of the pointers ) because treats everything as a chain of bytes in the memory. So, for a 2D array would be for example:[code]type 2d_array=array[1..10,1..10] of byte; { size => 10 * 10 = 100 bytes }

    var a,b:^2d_array;

    {...}
    copyselective(a,b,[b]100[/b],0); { <-- copies a to b, omitting 0's }
    {...}
    [/code]




  • MalekovitsMalekovits Posts: 24Member
    I tried to put it in my code, but it doesn't work... I thing because the arrays I use are char type. Also the arrays are records etc
    a[i].mat[j,k].

    If I use SizeOf() for the count, is it going to work???
  • _Atex__Atex_ Posts: 163Member
    : I tried to put it in my code, but it doesn't work... I thing because
    : the arrays I use are char type. Also the arrays are records etc
    : a[i].mat[j,k].

    It will work with anything just have to use pointers for arguments.Ex:[code]type d=record
    x:array[1..20] of byte;
    y:array[1..20] of real;
    ch:array[1..20] of char;
    s:string[20];
    end;

    type c=array[1..10,1..10] of d;

    var a:^c; { <-- pointer to "c" }[/code]
    :
    : If I use SizeOf() for the count, is it going to work???

    Yes, Ex: [b]sizeof(a^)[/b]

Sign In or Register to comment.