Recent

Author Topic: Trying to copy part of an array  (Read 542 times)

imekon

  • New Member
  • *
  • Posts: 11
Trying to copy part of an array
« on: August 18, 2019, 03:28:29 pm »
Why does this return a substring:

Code: Pascal  [Select]
  1. procedure TGraphic.AddTriangles(points: array of single);
  2. var
  3.   i: integer;
  4.   triangle: TTriangle;
  5.   chunk: array of single;
  6.  
  7. begin
  8.   i := 0;
  9.   while i < Length(points) - 1 do
  10.   begin
  11.     triangle := TTriangle.Create;
  12.     chunk := Copy(points, i, 9);     // HERE!
  13.     triangle.SetPoints(chunk);
  14.     inc(i, 9)
  15.   end;
  16. end;
  17.  

The error I get is:

Error: Incompatible types: got "ShortString" expected "{Dynamic} Array Of Single"

triangle.SetPoints expects array of single, why does Copy convert an array of single to shortstring?
« Last Edit: August 18, 2019, 03:34:09 pm by imekon »

imekon

  • New Member
  • *
  • Posts: 11
Re: Trying to copy part of an array
« Reply #1 on: August 18, 2019, 03:33:25 pm »
Here's a complete program showing the issue:

Code: Pascal  [Select]
  1. program test;
  2.  
  3. var
  4.   i: integer;
  5.   thing: array [1..9] of single;
  6.   slice1: array of single;
  7.  
  8. begin
  9.   for i := 1 to 9 do
  10.     thing[i] := i * 2.1;
  11.  
  12.   slice1 := Copy(thing, 1, 3);
  13. end.
  14.  

test.lpr(12,13) Error: Incompatible types: got "ShortString" expected "{Dynamic} Array Of Single"

Thaddy

  • Hero Member
  • *****
  • Posts: 8664
Re: Trying to copy part of an array
« Reply #2 on: August 18, 2019, 03:45:51 pm »
The syntax is here: https://www.freepascal.org/docs-html/rtl/system/slice.html
simple example:
Code: Pascal  [Select]
  1. procedure ShowArray(const A: array of single);
  2. var
  3.   i: single;
  4. begin
  5.   for i in a do
  6.     WriteLn(i:2:2);
  7. end;
  8.  
  9. begin
  10.   ShowArray(Slice([1,2,3,4],2));
  11. end.


« Last Edit: August 18, 2019, 03:59:18 pm by Thaddy »
Most people that want to use threading should learn to patch their jeans first: use a needle.

julkas

  • Sr. Member
  • ****
  • Posts: 348
  • KISS principle / Lazarus 2.0.0 / FPC 3.0.4
Re: Trying to copy part of an array
« Reply #3 on: August 18, 2019, 04:19:05 pm »
Code: Pascal  [Select]
  1. program test;
  2. {$mode delphi}
  3. var
  4.   i: integer;
  5.   thing: array [1..9] of single;
  6.   slice: array of single;
  7. begin
  8.   for i := 1 to 9 do
  9.     thing[i] := i;
  10.   SetLength(slice, 9);
  11.   Move(thing[1], slice[0], 9*SizeOf(single));
  12.   for i := 1 to 9 do
  13.     WriteLn(slice[i-1])
  14. end.
  15.  
procedure mulu64(a, b: QWORD; out clo, chi: QWORD); assembler;
asm
  mov rax, a
  mov rdx, b
  mul rdx
  mov [clo], rax
  mov [chi], rdx
end;
(* Pointer game *) Inc(ptr, 1); (* vs *) ptr := ptr + 1;

Thaddy

  • Hero Member
  • *****
  • Posts: 8664
Re: Trying to copy part of an array
« Reply #4 on: August 18, 2019, 04:33:01 pm »
Code: Pascal  [Select]
  1. program test;
  2. {$mode delphi}
  3. var
  4.   i: integer;
  5.   thing: array [1..9] of single;
  6.   slice: array of single;
  7. begin
  8.   for i := 1 to 9 do
  9.     thing[i] := i;
  10.   SetLength(slice, 9);
  11.   Move(thing[1], slice[0], 9*SizeOf(single));
  12.   for i := 1 to 9 do
  13.     WriteLn(slice[i-1])
  14. end.
  15.  
Sigh. we have Slice() as I demonstrated. It is also more efficient. It is built-in. No need to jump through hoops.
First check, then answer.
Most people that want to use threading should learn to patch their jeans first: use a needle.

julkas

  • Sr. Member
  • ****
  • Posts: 348
  • KISS principle / Lazarus 2.0.0 / FPC 3.0.4
Re: Trying to copy part of an array
« Reply #5 on: August 18, 2019, 04:55:09 pm »
Code: Pascal  [Select]
  1. program test;
  2. {$mode delphi}
  3. var
  4.   i: integer;
  5.   thing: array [1..9] of single;
  6.   slice: array of single;
  7. begin
  8.   for i := 1 to 9 do
  9.     thing[i] := i;
  10.   SetLength(slice, 9);
  11.   Move(thing[1], slice[0], 9*SizeOf(single));
  12.   for i := 1 to 9 do
  13.     WriteLn(slice[i-1])
  14. end.
  15.  
Sigh. we have Slice() as I demonstrated. It is also more efficient. It is built-in. No need to jump through hoops.
First check, then answer.
It's just my working solution.
BTW. Move() must be fast and host, OS optimized just as C memmove().
procedure mulu64(a, b: QWORD; out clo, chi: QWORD); assembler;
asm
  mov rax, a
  mov rdx, b
  mul rdx
  mov [clo], rax
  mov [chi], rdx
end;
(* Pointer game *) Inc(ptr, 1); (* vs *) ptr := ptr + 1;

Thaddy

  • Hero Member
  • *****
  • Posts: 8664
Re: Trying to copy part of an array
« Reply #6 on: August 18, 2019, 05:21:46 pm »
It's just my working solution.
BTW. Move() must be fast and host, OS optimized just as C memmove().
Fine with me but Slice() is a compiler intrinsic and therefor should be faster.
Also note Slice() has been part of the Pascal language for *a*very*long*time* ...(.although the implementation in FPC is rather recent, give a couple of 10 years, I mean)

Note slice() still needs an open array parameter, in all other cases use copy. (But that was not the case here...)
« Last Edit: August 18, 2019, 05:36:30 pm by Thaddy »
Most people that want to use threading should learn to patch their jeans first: use a needle.

avk

  • Full Member
  • ***
  • Posts: 102
    • my self-education project
Re: Trying to copy part of an array
« Reply #7 on: August 18, 2019, 05:41:36 pm »
It seems that if triangle.SetPoints could accept an open array, then copying could be completely avoided:
Code: Pascal  [Select]
  1. procedure AddTriangles(points: array of single);
  2. var
  3.   i: integer;
  4.   triangle: TTriangle;
  5. begin
  6.   i := 0;
  7.   while i <= Length(points) - 9 do
  8.     begin
  9.       triangle := TTriangle.Create;
  10.       triangle.SetPoints(points[I..I+8]);
  11.       inc(i, 9)
  12.     end;
  13. end;  
  14.  

jamie

  • Hero Member
  • *****
  • Posts: 1893
Re: Trying to copy part of an array
« Reply #8 on: August 18, 2019, 05:46:02 pm »
Or you could simply write yourself a Copy Function that works the same way as the string Copy does.

Code: Pascal  [Select]
  1. function Copy(Const A:Array of Single;aStart:Integer;ACount:Integer=1):TSingleArray;
  2. var
  3.   I:Integer;
  4. Begin
  5.   SetLength(result, 0);
  6.   If (Not AStart in [0..High(A)])or(Acount <= 0) then Exit;
  7.   If ACount+AStart > Length(A) Then ACount := Length(A)-AStart;
  8.   SetLength(Result, ACount);
  9.   For I:= 0 To ACount-1 do Result[I] := A[AStart+I];
  10. End;                                                    
  11.  

That will start you in any location within the Array and then you specify the number of elements from that point on.
 it returns an array created to the resolving size..

This will also test for limit control and not exceed the given array and simply return the remainder or nothing if it's outside the limits.


Thaddy

  • Hero Member
  • *****
  • Posts: 8664
Re: Trying to copy part of an array
« Reply #9 on: August 18, 2019, 07:35:16 pm »
Or you could simply write yourself a Copy Function that works the same way as the string Copy does.
Jamie! slice()! >:D
Is that feature so obscure everybody fails to comprehend it.... <sigh> and that goes for all of you...
« Last Edit: August 18, 2019, 07:37:41 pm by Thaddy »
Most people that want to use threading should learn to patch their jeans first: use a needle.

jamie

  • Hero Member
  • *****
  • Posts: 1893
Re: Trying to copy part of an array
« Reply #10 on: August 18, 2019, 07:40:38 pm »
Or you could simply write yourself a Copy Function that works the same way as the string Copy does.
Jamie! slice()! >:D
Is that feature so obscure everybody fails to comprehend it.... <sigh> and that goes for all of you...

Please show me how you use Slice with a starting index and count?

from what I see, it's only starts at 0 and count is all you can specify..

The user was looking for a start index and count.

Abelisto

  • Jr. Member
  • **
  • Posts: 80
Re: Trying to copy part of an array
« Reply #11 on: August 18, 2019, 07:47:34 pm »
Or you could simply write yourself a Copy Function that works the same way as the string Copy does.
Jamie! slice()! >:D
Is that feature so obscure everybody fails to comprehend it.... <sigh> and that goes for all of you...

Additionally, citation from your link: "but this array is not assignment compatible to any other array, and can therefor only be used in open array arguments to functions."
So it is impossible to use slice() function in a construction like
Code: Pascal  [Select]
  1. a := slice(b, c);
OS: Linux Mint + MATE, Compiler: FPC trunk (yes, I am risky!), IDE: Lazarus trunk

Thaddy

  • Hero Member
  • *****
  • Posts: 8664
Re: Trying to copy part of an array
« Reply #12 on: August 18, 2019, 08:17:04 pm »
Additionally, citation from your link: "but this array is not assignment compatible to any other array, and can therefor only be used in open array arguments to functions."
So it is impossible to use slice() function in a construction like
Code: Pascal  [Select]
  1. a := slice(b, c);
Can you explain what you mean? Of course that is possible. That's part of my demo .The devil is in the detail.
Most people that want to use threading should learn to patch their jeans first: use a needle.

imekon

  • New Member
  • *
  • Posts: 11
Re: Trying to copy part of an array
« Reply #13 on: August 18, 2019, 08:36:24 pm »
Or you could simply write yourself a Copy Function that works the same way as the string Copy does.

Code: Pascal  [Select]
  1. function Copy(Const A:Array of Single;aStart:Integer;ACount:Integer=1):TSingleArray;
  2. var
  3.   I:Integer;
  4. Begin
  5.   SetLength(result, 0);
  6.   If (Not AStart in [0..High(A)])or(Acount <= 0) then Exit;
  7.   If ACount+AStart > Length(A) Then ACount := Length(A)-AStart;
  8.   SetLength(Result, ACount);
  9.   For I:= 0 To ACount-1 do Result[I] := A[AStart+I];
  10. End;                                                    
  11.  

That will start you in any location within the Array and then you specify the number of elements from that point on.
 it returns an array created to the resolving size..

This will also test for limit control and not exceed the given array and simply return the remainder or nothing if it's outside the limits.

This looks like what I'm looking for, thanks!

avk

  • Full Member
  • ***
  • Posts: 102
    • my self-education project
Re: Trying to copy part of an array
« Reply #14 on: August 18, 2019, 08:50:57 pm »
Or you could simply write yourself a Copy Function that works the same way as the string Copy does...
Hmm, I can only envy the Delphi programmers, for some reason they always have the fastest processors, unlimited memory and the most understandable code.