One thing that didn't work was the CARD() function.Perhaps you might find this thread (http://forum.lazarus.freepascal.org/index.php?topic=27629.0) interesting.
The function card yields the number of members in a set.
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.
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
Now if somebody knows a nifty trick to obtain the set size from an untyped const, I can get rid of the second parameter.
Now if somebody knows a nifty trick to obtain the set size from an untyped const, I can get rid of the second parameter.
The use of qwords is an internal and legal for any bit set > 32 bits. It merely uses the most efficient available PopCnt overload.
Prints 31.https://www.freepascal.org/docs-html/ref/refsu16.html#x40-580003.3.3
https://www.freepascal.org/docs-html/ref/refsu16.html#x40-580003.3.3
" The compiler stores small sets (less than 32 elements) in a Longint, if the type range allows it. This allows for faster processing and decreases program size. Otherwise, sets are stored in 32 bytes."
" The compiler stores small sets (less than 32 elements) in a Longint, if the type range allows it. This allows for faster processing and decreases program size. Otherwise, sets are stored in 32 bytes."I think the documentation is inaccurate and most likely in FPC, as in Delphi: Max div 8 - Min div 8 + 1 (http://docwiki.embarcadero.com/RADStudio/Tokyo/en/Internal_Data_Formats_(Delphi)#Set_Types).
After a bit more thought, a simplified Card() is this:- That code is less efficient on modern processors since PopCnt has a qword option (like I used)
Sadly the "Unreachable code" warning can not be suppressed :'(1. This is compiled only in the development version.
So? A potential Card() function or intrinsic would also only be part of trunk.Sadly the "Unreachable code" warning can not be suppressed :'(1. This is compiled only in the development version.
2. With {$mode objfpc} only two set sizes: 4 and 32. Thus, either one or the other part of "if" is an unreachable code.Yes, I know, but I'm more complaining about that even with {$warn off 6018} around the generic function the compiler doesn't remember that setting when specializing the function which is quite irritating, cause I thought that this should work. Probably a bug I'll have to look at... *sigh*
3. With {$mode delphi} this code, with little modification, is wrong, because, as @Thaddy say "The unused bytes are undefined, i.e. also dirty".Yes, that definitely simplifies that affair without any unreachable code warning. I was much too focused on the difference between small and large sets plus I wasn't aware that PopCnt had an overload for Byte as I had no need to use that function before. :-[
program Project1; {$APPTYPE CONSOLE} {-$mode delphi} {$mode objfpc} {$IFDEF FPC_OBJFPC}generic{$ENDIF} function Card<T>(const aSetValue: T): Integer; var i: Integer; begin Result := 0; for i := 0 to SizeOf(T) - 1 do Inc(Result, PopCnt(PByte(@aSetValue)[i])); end; type TSet1 = set of 0..3; TSet2 = set of 0..40; var set1: TSet1 = [2]; set2: TSet2 = [4, 9, 23, 40]; begin set1 := [2]; set2 := [4, 9, 23, 40]; Writeln(SizeOf(TSet1)); Writeln(SizeOf(TSet2)); Writeln({$IFDEF FPC_OBJFPC}specialize {$ENDIF}Card<TSet1>(set1)); Writeln({$IFDEF FPC_OBJFPC}specialize {$ENDIF}Card<TSet2>(set2)); Readln; end.