I have some reports that use For loop with condition of value between 2 numbers like this:
for i := 1 to n do
if (Data[i].ProjId >= X) and (Data[i].ProjId <= Y) then
So, to refactor and simplify code, I looked into InRange function in System.Math unit, but why is it designed this way:
function InRange(const AValue, AMin, AMax: Integer): Boolean;
var
A, B: Boolean;
begin
A := (AValue >= AMin);
B := (AValue <= AMax);
Result := B and A;
end;
Why does it need 2 variables, if simple Result := (AValue >= AMin) and (AValue <= AMax); is all that is needed.
So, I measured the performance difference with function without variables:
function IsInRange(const AValue, AMin, AMax: Integer): Boolean; inline;
begin
Result := (AValue >= AMin) and (AValue <= AMax);
end;
And is a little faster. But they are both still 100% slower than just If statement:
32bit:
and once again we see how 64bit is so much worse than 32 bit, while single line function is almost 20% faster than Math.InRange:
Why would they design function with 2 variables, if they are useless? Is it just readability or am missing something obvious?
and code:
program Project1;
{$APPTYPE CONSOLE}
{$R *.res}
uses
System.SysUtils, System.Math, System.Diagnostics;
const cLoop: integer = 10000000000;
var
vSW: TStopWatch;
// Single line function replacing System.Math.InRange
function IsInRange(const AValue, AMin, AMax: Integer): Boolean; inline;
begin
Result := (AValue >= AMin) and (AValue <= AMax);
end;
procedure Test1;
var i, a, b: integer;
begin
a := 999;
b := 999999;
vSW := TStopwatch.StartNew;
for i := 1 to cLoop do
if System.Math.InRange(i, a, b) then;
writeln('Math.InRange: '+vSW.ElapsedMilliseconds.ToString);
end;
procedure Test2;
var i, a, b: integer;
begin
a := 999;
b := 999999;
vSW := TStopwatch.StartNew;
for i := 1 to cLoop do
if IsInRange(i, a, b) then;
writeln('IsInRange: ' + vSW.ElapsedMilliseconds.ToString);
end;
procedure Test3;
var i, a, b: integer;
begin
a := 999;
b := 999999;
vSW := TStopwatch.StartNew;
for i := 1 to cLoop do
if (i >= a) and (i<=b) then;
writeln('If: ' + vSW.ElapsedMilliseconds.ToString);
end;
begin
Test1;
Test2;
Test3;
Readln;
end.