Jump to content
shineworld

Compare two TIntegerDynArray

Recommended Posts

Hi all,

 

what is the fastest way to compare two vars of the TIntegerDynArray type?
 

Thank you in advance for your suggestions.

 

 

Share this post


Link to post

That is what I've used....

procedure TGCodeEditor.SetGCodeLinePoints(Value: TIntegerDynArray);
var
  F: Boolean;
  L: Integer;
begin
  F := False;
  L := Length(Value);
  if (Length(FGCodeLinePoints) > 0) and (Length(FGCodeLinePoints) = L) then
    F := CompareMem(@FGCodeLinePoints[0], @Value[0], Sizeof(Integer) * L);
  FGCodeLinePoints := Value;
  if not F then
    Invalidate;
end;

 

Share this post


Link to post
9 minutes ago, shineworld said:

That is what I've used....


procedure TGCodeEditor.SetGCodeLinePoints(Value: TIntegerDynArray);
var
  F: Boolean;
  L: Integer;
begin
  F := False;
  L := Length(Value);
  if (Length(FGCodeLinePoints) > 0) and (Length(FGCodeLinePoints) = L) then
    F := CompareMem(@FGCodeLinePoints[0], @Value[0], Sizeof(Integer) * L);
  FGCodeLinePoints := Value;
  if not F then
    Invalidate;
end;

 

Not much point having three calls to Length and in fact the zero length check can be skipped and rely on CompareMem to know what to do when passed a size of zero. 

Share this post


Link to post

Some type like this? 

PS: IsEqualIntegerDynArray placed in method just to test.

procedure TGCodeEditor.SetGCodeLinePoints(Value: TIntegerDynArray);

  function IsEqualIntegerDynArray(const A, B: TIntegerDynArray): Boolean;
  begin
    if Length(A) <> Length(B) then Exit(False);
    Result := CompareMem(@A[0], @B[0], Sizeof(Integer) * Length(A));
  end;

begin
  if not IsEqualIntegerDynArray(FGCodeLinePoints, Value) then
  begin
    FGCodeLinePoints := Value;
    Invalidate;
  end;
end;

 

Share this post


Link to post
1 minute ago, shineworld said:

Result := CompareMem(@A[0], @B[0], Sizeof(Integer) * Length(A));

This risks range check errors so I'd use Pointer(A)^ and similar for B. You could still save one of the lengths to a local to avoid getting it twice. 

Share this post


Link to post

Sincerely no reason.
I just thought that TIntegerDynArray is more performant than a generic.

In my defense or fault, I have not been a big user of generics until now.

Edited by shineworld

Share this post


Link to post
10 minutes ago, shineworld said:

Sincerely no reason.
I just thought that TIntegerDynArray is more performant than a generic.

In my defense or fault, I have not been a big user of generics until now.

Don't think performance is an issue with TArray<T> and using it makes you code better able to work with other generic code. 

  • Like 1

Share this post


Link to post
5 hours ago, shineworld said:

Some type like this? 

PS: IsEqualIntegerDynArray placed in method just to test.

If there is any possibility that FGCodeLinePoints could be passed in to SetGCodeLinePoints() (eg: GCodeEditor1.GCodeLinePoints := GCodeEditor1.GCodeLinePoints;), then I would also add a pointer equality check as well, since dynamic arrays are implemented as ref-counted pinters, eg:

procedure TGCodeEditor.SetGCodeLinePoints(Value: TIntegerDynArray);

  function IsEqualIntegerDynArray(const A, B: TIntegerDynArray): Boolean;
  var
    L: Integer;
  begin
    if Pointer(A) = Pointer(B) then Exit(True); // <-- HERE
    L := Length(A);
    if L <> Length(B) then Exit(False);
    Result := CompareMem(PInteger(A)^, PInteger(B)^, Sizeof(Integer) * L);
  end;

begin
  if not IsEqualIntegerDynArray(FGCodeLinePoints, Value) then
  begin
    FGCodeLinePoints := Value;
    Invalidate;
  end;
end;
Edited by Remy Lebeau
  • Like 1

Share this post


Link to post
6 hours ago, Remy Lebeau said:

If there is any possibility that FGCodeLinePoints could be passed in to SetGCodeLinePoints() (eg: GCodeEditor1.GCodeLinePoints := GCodeEditor1.GCodeLinePoints;), then I would also add a pointer equality check as well, since dynamic arrays are implemented as ref-counted pinters, eg:

I'd definitely remove the pointer check you just added. Surely that's just going to make things slower. 

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×