Finally, it looks like intrinsic functions are implemented in a special way and often inlined, so, approach of lucamar is slow.
Indeed, following program
program testcalls;
{$mode objfpc}{$H+}{$inline on}
uses SysUtils, DateUtils, Math;
type
Float = single;
TVector = array of Float;
TTransformFunc = function(X:float):float;
function Seq(Lb, Ub : integer; first, increment:Float; Vector:TVector = nil):TVector;
var
I:integer;
begin
if Vector = nil then
SetLength(Vector, Ub+1)
else
Ub := Max(Ub,High(Vector));
if Lb <= Ub then
Vector[Lb] := 0
else
Exit;
for I := Lb+1 to Ub do // 2 cycles to avoid rounding error if
Vector[I] := Vector[I-1]+increment; //First is very large and increment small
for I := Lb to Ub do
Vector[I] := Vector[I]+first;
Result := Vector;
end;
procedure Apply(V: TVector; Lb, Ub: integer; Func: TTransformFunc);
var
I:integer;
begin
Ub := max(High(V),Ub);
for I := Lb to Ub do
V[I] := Func(V[I]);
end;
function EAbs(X:float):float; inline;
begin
result := abs(X);
end;
procedure AbsArray(V:TVector; Lb, Ub: integer);
var
I:integer;
begin
Ub := max(High(V),Ub);
for I := Lb to Ub do
V[I] := abs(V[I]);
end;
var
Vec:TVector; // TVector = array of Float; Float = double
I:integer;
time1,time2:tdatetime;
begin
Vec := Seq(0,256000,-3000,2); // creates array with maximal index 128000
time1 := time; // and initializes with sequence -3000, -2998 etc
for I := 0 to 20 do
AbsArray(Vec,0,High(Vec));
time2 := time;
writeln('it takes ',inttostr(millisecondsbetween(time2, time1)), ' ms. for direct call of Abs.');
time1 := time;
for I := 0 to 20 do
Apply(Vec,0,High(Vec),@EAbs);
time2 := time;
writeln('it takes ',inttostr(millisecondsbetween(time2, time1)), ' ms. Apply of indirect call.');
readln;
end.
prints:
it takes 6 ms. for direct call of Abs.
it takes 21 ms. Apply of indirect call.
If Float = double thendifference is much bigger:
it takes 7 ms. for direct call of Abs.
it takes 63 ms. Apply of indirect call.
and if Float = extended then
it takes 20 ms. for direct call of Abs.
it takes 81 ms. Apply of indirect call.
So, it looks like Apply for intrunsic functions is not a good idea.