The following code to compare two Real48's (6-byte float) compiles and runs, but either generates non-nonsensical results or generates a AV.
program Project44;
{$APPTYPE CONSOLE}
uses
System.SysUtils,
System.Generics.Defaults;
begin
try
WriteLn(System.Generics.Defaults.TComparer<Real48>.Default.Compare(100.0,100.0));
WriteLn('all ok, press space');
except on E:exception do
WriteLn(e.Message);
end;
ReadLn
end.
It should output 0, but if it does not bomb first it outputs -92 or some other incorrect value.
Is this bug still present in the lastest XE8?
And if so, has it been reported before, I cannot find anything on the https://quality.embarcadero.com, but if there's an older QC I would like to refer to that.
Finally....
How do I compare two REAL48 types using TComparer<something>?
EDIT :
this was the fix I settled upon:
interface
...snip...
[Test]
procedure TestReal48;
...snip...
TTest<T> = record
private
class var Def: System.Generics.Defaults.IComparer<T>;
class var F: FastDefaults.TComparison<T>;
public
class function Real48Comparison(const Left, Right: T): Integer; static;
implementation
procedure TestDefault.TestReal48;
var
OldDef: System.Generics.Defaults.IComparer<Real48>;
begin
OldDef:= TTest<Real48>.Def;
TTest<Real48>.Def:= System.Generics.Defaults.TComparer<Real48>.Construct(TTest<Real48>.Real48Comparison);
TTest<Real48>.Test(100.0,100.0);
TTest<Real48>.Test(100000.0,-10000.0);
TTest<Real48>.Test(0.0,-10000.0);
TTest<Real48>.Test(100000.0,0.0);
TTest<Real48>.Test(0.0,0.0);
TTest<Real48>.Def:= OldDef;
end;
This defect is present in all versions of the compiler. Since
Real48was deprecated more than a decade ago I would expect that Embarcadero would not change the behaviour, even if you submitted a bug report. Of course, you should still submit a bug report, but I would not hold your breath when waiting for a fix!You'll have to construct a comparer rather than relying on the default:
Why does the default
Real48comparer fail so hard. Well, it starts here:It transpires that
TypeInfo(Real48)yieldsnil. There would appear to be no type info available forReal48. Probably not a great surprise.Then we reach here:
We take the
elsebranch and callComparer_Selector_Binary. So we end up performing a binary comparison. The comparison is actually performed by this function:which calls:
Not going to be useful for a real valued type.
As for the runtime error that relates to the ABI for
Real48. It seems thatReal48parameters are always passed on the stack. That is just not compatible with the use of untyped parameters inCompare_Binary.