[fpc-devel] Little feature teaser
Sven Barth
pascaldragon at googlemail.com
Fri Aug 2 17:34:24 CEST 2013
On 02.08.2013 17:01, Mattias Gaertner wrote:
> On Fri, 02 Aug 2013 13:18:53 +0200
> Sven Barth <pascaldragon at googlemail.com> wrote:
>
>> [...]
>> === source begin ===
>>
>> program tgenfuncs;
>>
>> {$modeswitch result}
>>
>> generic function IsIn<T>(aElement: T; const aArray: array of T): Boolean;
>> var
>> elem: T;
>> begin
>> for elem in aArray do
>> if elem = aElement then
>> Exit(True);
>> Result := False;
>> end;
>>
>> begin
>> Writeln(specialize IsIn<LongInt>(42, [21, 42, 84]));
>> Writeln(specialize IsIn<LongInt>(5, [21, 42, 84]));
>
> What is the speed?
> Is it much slower compared to a line of "if
> (aElement=val) or (..)... then" or a "case" statement?
You can do the comparison yourself, as a "specialize IsIn<LongInt>" will
generate a version of "IsIn<T>" where each "T" is replaced by "LongInt"
and be completely reparsed. So it's the same as if you wrote the
following from the beginning:
=== code begin ===
function IsIn(aElement: LongInt; const aArray: array of LongInt): Boolean;
var
elem: LongInt;
begin
for elem in aArray do
if elem = aElement then
Exit(True);
Result := False;
end;
=== code end ===
AFAIK the compiler implements the for-in for arrays as a normal for-loop
and thus I'd suspect that the "IsIn<T>" function is faster for a larger
amount of elements (=> less jumps). Your approach with ifs is basically
a loop unrolling which is better with fewer iterations.
If you'd declare the "IsIn<T>" function as "inline" and the compiler
would correctly handle this(*1) the compiler could in theory be able to
fold the complete for-loop together in the example I gave (because only
constants are used there). I don't know though whether the compiler is
currently able to deduce this (I'll need to test that ^^).
(*1) The problem currently is that the implementation needs to be
available when the call is parsed, but specializations are created at
the end of parsing a unit. So this would need to be adjusted to allow
inline generic functions to work correctly (I plan this, but not now).
> What about code size?
The code size for one unit is the same as if you had (in that example)
declared a variant of "IsIn" for each "LongInt" and "String". So for
each "IsIn<T>" specialization with different types new code is generated
if it does not yet exist in that unit. This means that if you call
"IsIn<LongInt>" in different units you'll have a "IsIn<LongInt>"
implementation in each unit. This is the same as for generic types btw.
Regards,
Sven
More information about the fpc-devel
mailing list