### Bookstore

 Computer Math and Games in Pascal (preview) Lazarus Handbook (preview only)

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

#### imekon

• New Member
• Posts: 12
##### 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: 12
##### 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"

• Hero Member
• Posts: 9436
##### 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 »
also related to equus asinus.

#### julkas

• Hero Member
• Posts: 523
• KISS principle / Lazarus 2.0.6 / 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;

• Hero Member
• Posts: 9436
##### 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.
also related to equus asinus.

#### julkas

• Hero Member
• Posts: 523
• KISS principle / Lazarus 2.0.6 / 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.
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;

• Hero Member
• Posts: 9436
##### 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 »
also related to equus asinus.

#### avk

• Full Member
• Posts: 192
##### 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: 2262
##### 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.

Number 1 at blue screen app creations!

• Hero Member
• Posts: 9436
##### 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()!
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 »
also related to equus asinus.

#### jamie

• Hero Member
• Posts: 2262
##### 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()!
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.
Number 1 at blue screen app creations!

#### Abelisto

• Jr. Member
• Posts: 82
##### 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()!
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

• Hero Member
• Posts: 9436
##### 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.
also related to equus asinus.

#### imekon

• New Member
• Posts: 12
##### 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: 192
##### 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.