* * *

Author Topic: What happened to the built in CARD() function?  (Read 5578 times)

meteoricshipyards

  • Newbie
  • Posts: 2
What happened to the built in CARD() function?
« on: January 12, 2016, 11:29:59 pm »
Way back in the late 70's and early 80's I worked with Pascal on a CDC NOS machine.  This past Summer I recently found a listing of an Adventure game that I played way back then.  I researched, found Lazarus and Free Pascal, and started typing it in.  One thing that didn't work was the CARD() function.  For those of you who don't know it, it returns the number of items in a set variable.  (For really obscure trivia, it was implemented as a single instruction on the CDC 60 bit architecture). 

As I only had one type of set that I needed the function for, I coded up my own.  But I was wondering when and why it disappeared, and if I should be aware of other items that may have gone away.

Tom A.
Planning on "publishing" the game on an Interactive Fiction site in within a month.

molly

  • Hero Member
  • *****
  • Posts: 2345
Re: What happened to the built in CARD() function?
« Reply #1 on: January 13, 2016, 03:25:58 am »
One thing that didn't work was the CARD() function.
Perhaps you might find this thread interesting.

marcov

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 6161
Re: What happened to the built in CARD() function?
« Reply #2 on: January 13, 2016, 09:17:01 am »
It never was in Turbo Pascal, so if it was standard, it already fell off before.

It is also possible it was just some intrinsic for a CDC instruction and not standard.  As Molly correctly pointed out, FPC has popcount, but it is only for integers, so only works for sets the size of a register.

Thaddy

  • Hero Member
  • *****
  • Posts: 5974
Re: What happened to the built in CARD() function?
« Reply #3 on: January 13, 2016, 12:21:48 pm »
@Marco: You yourself suggested PopCnt sometime ago.... ;)
http://stackoverflow.com/questions/12934017/knowing-how-many-elements-a-set-have

If that is correct and there are already compiler iintrinsics, it shouldn't be too hard to massage the compiler into having a card().
« Last Edit: January 13, 2016, 12:25:27 pm by Thaddy »
recommends {$macro on}{$define Silly:=ObjFpc}

marcov

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 6161
Re: What happened to the built in CARD() function?
« Reply #4 on: January 13, 2016, 12:46:37 pm »
My point is mainly that if an ancient compiler had it, it is not necessarily standard.

But I guess nothing stops you from submitting a patch if it is easy.

meteoricshipyards

  • Newbie
  • Posts: 2
Re: What happened to the built in CARD() function?
« Reply #5 on: January 13, 2016, 08:01:14 pm »
It was in the User Manual and Report at the time, and was the first or second implementation of Pascal, so it was pretty standard :-)

But it is not a function that is used often, or needs to be part of the standard, as far as I'm concerned.  Other functions that are gone (and were definitely implementation specific) are the eos(file) (end of segment) and linelimit(text) functions.

But I'm just glad I found this.  I consider Pascal my native language (even though I learned BASIC and FORTRAN before it).

Tom A.
Now to figure out objects in Pascal....

ArtLogi

  • Full Member
  • ***
  • Posts: 132
Re: What happened to the built in CARD() function?
« Reply #6 on: January 17, 2016, 02:18:33 am »
Well it seems to be in the ISO/IEC 10206:1 Page X, under "Set Extensions"
Quote
The function card yields the number of members in a set.

http://pascal-central.com/docs/iso10206.pdf
http://pascal-central.com/standards.html 
8)

Interesting I had an image that there were only one standard along the years considering pascal language. 1982 and no further updates and standardization work.

marcov

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 6161
Re: What happened to the built in CARD() function?
« Reply #7 on: January 17, 2016, 04:55:39 pm »
Don't get me wrong, CARD() would be fine, as would other work on sets

- like lifting the upper limit of 256 elements. (this makes using enums and sets difficult since it bounds itsscaling)

- respecting the lower limit (too often, elements are allocated starting with 0, even if the lower bound is not 0 or close to it)

- not even talking of the sparse sets in some Pascal dialects etc.

Bart

  • Hero Member
  • *****
  • Posts: 2956
    • Bart en Mariska's Webstek
Re: What happened to the built in CARD() function?
« Reply #8 on: January 17, 2016, 05:09:06 pm »
Extending Length() to handle sets would, with regard to the name of the function, make more sense to me.

Bart

Thaddy

  • Hero Member
  • *****
  • Posts: 5974
Re: What happened to the built in CARD() function?
« Reply #9 on: February 10, 2018, 09:36:45 am »
Old thread but not much has happened.
Summary:
For small sets (max 32 members) you can use PopCnt
For large sets (max 256 members you can also use PopCnt, but over an array.
I dreamed up this today because I only needed it now.
Code: Pascal  [Select]
  1. function Card(const s;SmallSet:boolean =true):word;inline;
  2. var
  3.   t:packed array [0..3] of qword absolute s;
  4. begin
  5.   if SmallSet then
  6.     Result := PopCnt(Dword(s))
  7.   else
  8.     Result := PopCnt(T[0])+PopCnt(T[1])+PopCnt(T[2])+PopCnt(T[3]);
  9. end;

Now if somebody knows a nifty trick to obtain the set size from an untyped const, I can get rid of the second parameter.
In extended ISO Pascal this is solved by an any_set intrinsic 

recommends {$macro on}{$define Silly:=ObjFpc}

taazz

  • Hero Member
  • *****
  • Posts: 5048
Re: What happened to the built in CARD() function?
« Reply #10 on: February 10, 2018, 10:19:04 am »
Now if somebody knows a nifty trick to obtain the set size from an untyped const, I can get rid of the second parameter.
how about making the second parameter the size of the set instead of a boolean.
Good judgement is the result of experience … Experience is the result of bad judgement.

OS : Windows 7 64 bit
Laz: Lazarus 1.4.4 FPC 2.6.4 i386-win32-win32/win64

Thaddy

  • Hero Member
  • *****
  • Posts: 5974
Re: What happened to the built in CARD() function?
« Reply #11 on: February 10, 2018, 11:11:43 am »
how about making the second parameter the size of the set instead of a boolean.
That's what I had first but I want to get rid of the parameter altogether. Another option was two separate functions. (Can't overload them). I tried rtti but that fails on tkUnKnown/$formal
« Last Edit: February 10, 2018, 11:41:53 am by Thaddy »
recommends {$macro on}{$define Silly:=ObjFpc}

marcov

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 6161
Re: What happened to the built in CARD() function?
« Reply #12 on: February 10, 2018, 02:07:03 pm »
Now if somebody knows a nifty trick to obtain the set size from an untyped const, I can get rid of the second parameter.

Well, there is also a problem that you need to mask out unused bits. They are probably zero, but I don't know how reliable that is. And sets are multiples of bytes, not qwords.

Thaddy

  • Hero Member
  • *****
  • Posts: 5974
Re: What happened to the built in CARD() function?
« Reply #13 on: February 10, 2018, 03:33:53 pm »
@marcov
The unused bits in sets < 33 bits are predictably zero, as are the unused bytes in a large up-to-32 byte set (this is also documented)
I can not use, however, just the function body for large sets for any set because that fails on stack-allocated space. And I tested that that will fail. (of course, but I tested it)
The use of qwords is an internal and legal for any bit set > 32 bits. It merely uses the most efficient available PopCnt overload.
« Last Edit: February 10, 2018, 03:40:06 pm by Thaddy »
recommends {$macro on}{$define Silly:=ObjFpc}

howardpc

  • Hero Member
  • *****
  • Posts: 2669
Re: What happened to the built in CARD() function?
« Reply #14 on: February 10, 2018, 04:16:17 pm »
Now if somebody knows a nifty trick to obtain the set size from an untyped const, I can get rid of the second parameter.

An untyped const parameter has no type information (SizeOf() = 0, TTypeKind = tkUnknown), which is logical since it is untyped.
You can, however, determine the size predicated on the unused bits being zero. Where is this documented?
The following routine may not be very efficient, but it expresses the cardinality of any set passed as an untyped parameter to the Card() function.

Code: Pascal  [Select]
  1. program Cardinality;
  2.  
  3. {$Mode objfpc}{$H+}
  4.  
  5. type
  6.   T4ByteRange      = Byte(0)..Byte(3);
  7.   T32ByteRange     = Byte(0)..Byte(31);
  8.   TMediumSetQWords = array[T4ByteRange] of QWord;
  9.  
  10. function Card(const aSet): Integer;
  11. var
  12.   msqw: TMediumSetQWords absolute aSet;
  13.   w: Word = 0;
  14.   b: Byte;
  15. begin
  16.   for b := Low(T4ByteRange) to High(T4ByteRange) do
  17.     Inc(w, PopCnt(msqw[b]));
  18.   if (w = 0) then
  19.     Exit(0);
  20.   Result := 0;
  21.   for b:= 1 to High(T4ByteRange) do
  22.     Inc(Result);
  23.   if (Result = 0) then
  24.     Exit(PopCnt(DWord(aSet)))
  25.   else Exit(w);
  26. end;
  27.  
  28. var
  29.   smallSet:  set of T32ByteRange;
  30.   mediumSet: set of Char;
  31.   c:         Char;
  32.   b:         T32ByteRange;
  33.  
  34. begin
  35.   smallSet := [];
  36.     WriteLn('smallSet: Card([]) = ', Card(smallSet));
  37.   smallSet := [31];
  38.     WriteLn('smallSet: Card([31]) = ', Card(smallSet));
  39.   smallSet := [1,3,5,7,31];
  40.     WriteLn('smallSet: Card([1,3,5,7,31]) = ', Card(smallSet));
  41.   for b := Low(T32ByteRange) to High(T32ByteRange) do
  42.     Include(smallSet, b);
  43.     WriteLn('smallSet: Card([full small set]) = ', Card(smallSet));
  44.   WriteLn;
  45.  
  46.   mediumSet := [];
  47.     WriteLn('mediumSet: Card([]) = ',Card(mediumSet));
  48.   mediumSet := ['?'];
  49.     WriteLn('mediumSet: Card([''?'']) = ',Card(mediumSet));
  50.   mediumSet := ['!','f','%','D'];
  51.     WriteLn('mediumSet: Card([''!'',''f'',''%'',''D'']) = ',Card(mediumSet));
  52.   Exclude(mediumSet, 'f');
  53.     WriteLn('mediumSet: after Exclude(mediumSet,''f''), Card(mediumSet) = ',Card(mediumSet));
  54.   for c in Char do
  55.     Include(mediumSet, c);
  56.   WriteLn('Card([full medium set]) = ',Card(mediumSet));
  57.  
  58.   ReadLn;
  59. end.    
« Last Edit: February 10, 2018, 11:34:24 pm by howardpc »

 

Recent

Get Lazarus at SourceForge.net. Fast, secure and Free Open Source software downloads Open Hub project report for Lazarus