### Bookstore

 Computer Math and Games in Pascal (preview) Lazarus Handbook

### Author Topic: [CLOSED] type conversion : routine to convert a "set of" into an integer type  (Read 925 times)

#### devEric69

• Sr. Member
• Posts: 363
##### [CLOSED] type conversion : routine to convert a "set of" into an integer type
« on: January 21, 2020, 06:22:10 pm »
I searched the Free Pascal documentation without finding anything.

On the web, I found this which works:

Code: Pascal  [Select][+][-]
1. procedure TForm1.Button1Click(Sender: TObject);
2. type
3.   TmySetof = Set of (so0=0, so1, so2, so3, so4, so5, so6, so7, so8, so9, so10);
4. var
5.   aSetof, anotherSetof: TmySetof;
6.   iResult: integer;
7.   sDebug: string;
8.
9.         function SetofToInt(const aSetOf; const iSize: integer): integer;
10.         begin
11.             result:= 0;
12.             Move(aSetOf, result, iSize);
13.         end;
14.
15.         procedure InToSetof(const aValue: integer; var aSetOf; const iSize: integer);
16.         begin
17.             Move(aValue, aSetOf, iSize);
18.         end;
19.
20. begin
21.     aSetof:= [so0, so1, so9];
22.     iResult:= SetofToInt(aSetof, SizeOf(aSetof));
23.     ShowMessage('iResult=' + IntToStr(iResult));
24.     // for me, it displays 515;
25.     // now, test if the above hard-coded displayed result is ok:
26.     InToSetof(515, anotherSetof, SizeOf(aSetof));
27.     sDebug:= '';
28.     if anotherSetof * [so0] <> [] then sDebug:= sDebug+',so0';
29.     if anotherSetof * [so1] <> [] then sDebug:= sDebug+',so1';
30.     if anotherSetof * [so2] <> [] then sDebug:= sDebug+',so2';
31.     if anotherSetof * [so3] <> [] then sDebug:= sDebug+',so3';
32.     if anotherSetof * [so4] <> [] then sDebug:= sDebug+',so4';
33.     if anotherSetof * [so5] <> [] then sDebug:= sDebug+',so5';
34.     if anotherSetof * [so6] <> [] then sDebug:= sDebug+',so6';
35.     if anotherSetof * [so7] <> [] then sDebug:= sDebug+',so7';
36.     if anotherSetof * [so8] <> [] then sDebug:= sDebug+',so8';
37.     if anotherSetof * [so9] <> [] then sDebug:= sDebug+',so9';
38.     if anotherSetof * [so10] <> [] then sDebug:= sDebug+',so10';
39.     ShowMessage('[setOf]=' + sDebug);
40. end;

a) is it optimal?
b) if yes, couldn't it be added in an inter-types conversion routine (e.g. useful: passing a "Set of" via a TStream with ReadBuffer)?

Otherwise, if it can help others...
« Last Edit: January 22, 2020, 12:02:30 pm by devEric69 »
use: Linux 64 bits (Ubuntu 20.04 LTS).
Lazarus version: 2.0.4 (svn revision: 62502M) compiled with fpc 3.0.4 - fpDebug \ Dwarf3.

#### wp

• Hero Member
• Posts: 7636
##### Re: type conversion : routine to convert a "set of" into an integer type
« Reply #1 on: January 21, 2020, 07:39:19 pm »
Use type casts to/from integer und SetToString/StringToSet from unit typinfo instead:
Code: Pascal  [Select][+][-]
1. uses
2.   TypInfo;
3.
4. procedure TForm1.Button3Click(Sender: TObject);
5. type
6.   TmySetof = Set of (so0=0, so1, so2, so3, so4, so5, so6, so7, so8, so9, so10);
7. var
8.   aSetOf: TmySetOf = [so0, so1, so9];
9.   anotherSetOf: TmySetOf;
10.   iResult: Integer;
11. begin
12.   iResult := Integer(aSetOf);
13.   anotherSetOf := TmySetof(iResult);
14.
15.   ShowMessage(
16.     IntToStr(iResult) + LineEnding +
17.     SetToString(PTypeInfo(TypeInfo(TmySetOf)), Integer(aSetOf), true) + LineEnding +
18.     SetToString(PTypeInfo(TypeInfo(TmySetOf)), Integer(anotherSetOf), true) + LineEnding
19.   );
20. end;
Mainly Lazarus trunk / fpc 3.2.0 / all 32-bit on Win-10, but many more...

#### PascalDragon

• Hero Member
• Posts: 2264
• Compiler Developer
##### Re: type conversion : routine to convert a "set of" into an integer type
« Reply #2 on: January 21, 2020, 11:18:49 pm »
a) is it optimal?

In addition/as an explanation to what wp wrote: a set with a size <= 8 Byte can be cast to an integer type of the same size and vice versa (the size of a set depends on the number of elements and the \$PackSet directive).

#### devEric69

• Sr. Member
• Posts: 363
##### Re: type conversion : routine to convert a "set of" into an integer type
« Reply #3 on: January 22, 2020, 12:01:37 pm »
Quote
In addition/as an explanation to what wp wrote: a set with a size <= 8 Byte can be cast to an integer type of the same size and vice versa (the size of a set depends on the number of elements and the \$PackSet directive)

Thank you @wp and @PascalDragon.
Inspired by this post too, https://forum.lazarus.freepascal.org/index.php/topic,40761.msg281747.html#msg281747, then, in pseudo-code, I have to test the number of elements in the set, (to know in which "abacus" the number of elements of the "set of" falls, ie to know for example if the set goes over 32 elements "abacus"):

Code: Pascal  [Select][+][-]
1.         iResultInt := Integer(aSetOf);
2.         .../...
3.     else if Ord(High(TmySetOf)) > 32 then begin
4.         {\$PACKSET 4}
5.         iResult64 := Int64(aSetOf);
6.         .../...
« Last Edit: January 22, 2020, 12:15:17 pm by devEric69 »
use: Linux 64 bits (Ubuntu 20.04 LTS).
Lazarus version: 2.0.4 (svn revision: 62502M) compiled with fpc 3.0.4 - fpDebug \ Dwarf3.

#### lucamar

• Hero Member
• Posts: 3079
##### Re: [CLOSED] type conversion : routine to convert a "set of" into an integer type
« Reply #4 on: January 22, 2020, 12:38:34 pm »
The directive {\$PACKSET 4} only affects subsequent declarations so it should be before the declaration of aSetOf. Otherwise the compiler will assume the set uses whatever packing was in effect at the time it's declared.

Anyway, it's much easier to use SizeOf(), as in:

Code: Pascal  [Select][+][-]
1. if SizeOf(TmySetOf) = SizeOf(Int64) then ...
Turbo Pascal 3 CP/M - Amstrad PCW 8256 (512 KB !!!)
Lazarus 2.0.8/FPC 3.0.4 - 32/64 bits on:
(K|L|X)Ubuntu 12..18, Windows XP, 7, 10 and various DOSes.

#### howardpc

• Hero Member
• Posts: 3553
##### Re: [CLOSED] type conversion : routine to convert a "set of" into an integer type
« Reply #5 on: January 22, 2020, 12:45:02 pm »
And, strictly speaking, should the cast not be QWord() rather than Int64() ?

#### PascalDragon

• Hero Member
• Posts: 2264
• Compiler Developer
##### Re: [CLOSED] type conversion : routine to convert a "set of" into an integer type
« Reply #6 on: January 23, 2020, 09:26:52 am »
And, strictly speaking, should the cast not be QWord() rather than Int64() ?

Pascal prefers signed types, so that's what most code uses (e.g. TypInfo.SetToString takes a Integer as well). In the end, as long as the size fits, the compiler doesn't care whether it's signed or unsigned...