|
@@ -0,0 +1,1800 @@
|
|
|
+program bfloatfunc;
|
|
|
+
|
|
|
+{$mode objfpc}{$H+}
|
|
|
+
|
|
|
+uses
|
|
|
+ SysUtils, Math;
|
|
|
+
|
|
|
+{ Utility functions }
|
|
|
+function GetRealTime(const st: TSystemTime): Real;
|
|
|
+ begin
|
|
|
+ Result := st.Hour*3600.0 + st.Minute*60.0 + st.Second + st.MilliSecond/1000.0;
|
|
|
+ end;
|
|
|
+
|
|
|
+{$push}
|
|
|
+{$warn 5057 off}
|
|
|
+function GetRealTime : Real;
|
|
|
+ var
|
|
|
+ st:TSystemTime;
|
|
|
+ begin
|
|
|
+ GetLocalTime(st);
|
|
|
+ result:=GetRealTime(st);
|
|
|
+ end;
|
|
|
+{$pop}
|
|
|
+
|
|
|
+function IIf(Condition: Boolean; TrueRes, FalseRes: Integer): Integer; inline;
|
|
|
+ begin
|
|
|
+ if Condition then
|
|
|
+ Result := TrueRes
|
|
|
+ else
|
|
|
+ Result := FalseRes;
|
|
|
+ end;
|
|
|
+
|
|
|
+const
|
|
|
+ ITERATIONS = 33554432;
|
|
|
+
|
|
|
+{ TTestAncestor }
|
|
|
+type
|
|
|
+ TTestAncestor = class
|
|
|
+ private
|
|
|
+ FStartTime: Real;
|
|
|
+ FEndTime: Real;
|
|
|
+ FAvgTime: Real;
|
|
|
+ procedure SetStartTime;
|
|
|
+ procedure SetEndTime;
|
|
|
+ protected
|
|
|
+ procedure DoTestIteration(Iteration: Integer); virtual; abstract;
|
|
|
+ public
|
|
|
+ constructor Create; virtual;
|
|
|
+ destructor Destroy; override;
|
|
|
+ procedure Run;
|
|
|
+ function TestTitle: shortstring; virtual; abstract;
|
|
|
+ function WriteResults: Boolean; virtual; abstract;
|
|
|
+ property RunTime: Real read FAvgTime;
|
|
|
+ end;
|
|
|
+
|
|
|
+ TTestClass = class of TTestAncestor;
|
|
|
+
|
|
|
+ TFloat32Test = class(TTestAncestor)
|
|
|
+ protected
|
|
|
+ FResultStorage: array[0..7] of Single;
|
|
|
+ FExpected: array[0..7] of Single;
|
|
|
+ class function IsEqual(Value, Reference: Single): Boolean; static;
|
|
|
+ public
|
|
|
+ function WriteResults: Boolean; override;
|
|
|
+ end;
|
|
|
+
|
|
|
+ TFloat32OneInputTest = class(TFloat32Test)
|
|
|
+ protected
|
|
|
+ FInputs: array[0..7] of Single;
|
|
|
+ procedure DoTestIteration(Iteration: Integer); override;
|
|
|
+ function DoFunc(Input: Single): Single; virtual; abstract;
|
|
|
+ end;
|
|
|
+
|
|
|
+ TFloat32TwoInputTest = class(TFloat32Test)
|
|
|
+ protected
|
|
|
+ FInputs: array[0..7] of array[0..1] of Single;
|
|
|
+ procedure DoTestIteration(Iteration: Integer); override;
|
|
|
+ function DoFunc(Input1, Input2: Single): Single; virtual; abstract;
|
|
|
+ end;
|
|
|
+
|
|
|
+ TSingleIntPair = record
|
|
|
+ S: Single;
|
|
|
+ N: Integer;
|
|
|
+ end;
|
|
|
+
|
|
|
+ TFloat32FloatIntTest = class(TFloat32Test)
|
|
|
+ protected
|
|
|
+ FInputs: array[0..7] of TSingleIntPair;
|
|
|
+ procedure DoTestIteration(Iteration: Integer); override;
|
|
|
+ function DoFunc(Float: Single; N: Integer): Single; virtual; abstract;
|
|
|
+ end;
|
|
|
+
|
|
|
+ TFloat64Test = class(TTestAncestor)
|
|
|
+ protected
|
|
|
+ FResultStorage: array[0..7] of Double;
|
|
|
+ FExpected: array[0..7] of Double;
|
|
|
+ class function IsEqual(Value, Reference: Double): Boolean; static;
|
|
|
+ public
|
|
|
+ function WriteResults: Boolean; override;
|
|
|
+ end;
|
|
|
+
|
|
|
+ TFloat64OneInputTest = class(TFloat64Test)
|
|
|
+ protected
|
|
|
+ FInputs: array[0..7] of Double;
|
|
|
+ procedure DoTestIteration(Iteration: Integer); override;
|
|
|
+ function DoFunc(Input: Double): Double; virtual; abstract;
|
|
|
+ end;
|
|
|
+
|
|
|
+ TFloat64TwoInputTest = class(TFloat64Test)
|
|
|
+ protected
|
|
|
+ FInputs: array[0..7] of array[0..1] of Double;
|
|
|
+ procedure DoTestIteration(Iteration: Integer); override;
|
|
|
+ function DoFunc(Input1, Input2: Double): Double; virtual; abstract;
|
|
|
+ end;
|
|
|
+
|
|
|
+ TDoubleIntPair = record
|
|
|
+ D: Double;
|
|
|
+ N: Integer;
|
|
|
+ end;
|
|
|
+
|
|
|
+ TFloat64FloatIntTest = class(TFloat64Test)
|
|
|
+ protected
|
|
|
+ FInputs: array[0..7] of TDoubleIntPair;
|
|
|
+ procedure DoTestIteration(Iteration: Integer); override;
|
|
|
+ function DoFunc(Float: Double; N: Integer): Double; virtual; abstract;
|
|
|
+ end;
|
|
|
+
|
|
|
+ { Test classes for actual tests }
|
|
|
+
|
|
|
+ { 32-bit floating-point }
|
|
|
+ TFloat32MinTest = class(TFloat32TwoInputTest)
|
|
|
+ protected
|
|
|
+ function DoFunc(Input1, Input2: Single): Single; override;
|
|
|
+ public
|
|
|
+ constructor Create; override;
|
|
|
+ function TestTitle: shortstring; override;
|
|
|
+ end;
|
|
|
+
|
|
|
+ TFloat32ImplicitMinTest = class(TFloat32MinTest)
|
|
|
+ protected
|
|
|
+ function DoFunc(Input1, Input2: Single): Single; override;
|
|
|
+ public
|
|
|
+ function TestTitle: shortstring; override;
|
|
|
+ end;
|
|
|
+
|
|
|
+ TFloat32MinSpecialTest = class(TFloat32MinTest)
|
|
|
+ public
|
|
|
+ constructor Create; override;
|
|
|
+ function TestTitle: shortstring; override;
|
|
|
+ end;
|
|
|
+
|
|
|
+ TFloat32ImplicitMinSpecialTest = class(TFloat32MinSpecialTest)
|
|
|
+ protected
|
|
|
+ function DoFunc(Input1, Input2: Single): Single; override;
|
|
|
+ public
|
|
|
+ function TestTitle: shortstring; override;
|
|
|
+ end;
|
|
|
+
|
|
|
+ TFloat32MaxTest = class(TFloat32TwoInputTest)
|
|
|
+ protected
|
|
|
+ function DoFunc(Input1, Input2: Single): Single; override;
|
|
|
+ public
|
|
|
+ constructor Create; override;
|
|
|
+ function TestTitle: shortstring; override;
|
|
|
+ end;
|
|
|
+
|
|
|
+ TFloat32ImplicitMaxTest = class(TFloat32MaxTest)
|
|
|
+ protected
|
|
|
+ function DoFunc(Input1, Input2: Single): Single; override;
|
|
|
+ public
|
|
|
+ function TestTitle: shortstring; override;
|
|
|
+ end;
|
|
|
+
|
|
|
+ TFloat32MaxSpecialTest = class(TFloat32MaxTest)
|
|
|
+ public
|
|
|
+ constructor Create; override;
|
|
|
+ function TestTitle: shortstring; override;
|
|
|
+ end;
|
|
|
+
|
|
|
+ TFloat32ImplicitMaxSpecialTest = class(TFloat32MaxSpecialTest)
|
|
|
+ protected
|
|
|
+ function DoFunc(Input1, Input2: Single): Single; override;
|
|
|
+ public
|
|
|
+ function TestTitle: shortstring; override;
|
|
|
+ end;
|
|
|
+
|
|
|
+ TFloat32SqrtTest = class(TFloat32OneInputTest)
|
|
|
+ protected
|
|
|
+ function DoFunc(Input: Single): Single; override;
|
|
|
+ public
|
|
|
+ constructor Create; override;
|
|
|
+ function TestTitle: shortstring; override;
|
|
|
+ end;
|
|
|
+
|
|
|
+ TFloat32SqrtSpecialTest = class(TFloat32SqrtTest)
|
|
|
+ public
|
|
|
+ constructor Create; override;
|
|
|
+ function TestTitle: shortstring; override;
|
|
|
+ end;
|
|
|
+
|
|
|
+ TFloat32LnTest = class(TFloat32OneInputTest)
|
|
|
+ protected
|
|
|
+ function DoFunc(Input: Single): Single; override;
|
|
|
+ public
|
|
|
+ constructor Create; override;
|
|
|
+ function TestTitle: shortstring; override;
|
|
|
+ end;
|
|
|
+
|
|
|
+ TFloat32LnSpecialTest = class(TFloat32LnTest)
|
|
|
+ public
|
|
|
+ constructor Create; override;
|
|
|
+ function TestTitle: shortstring; override;
|
|
|
+ end;
|
|
|
+
|
|
|
+ TFloat32ExpTest = class(TFloat32OneInputTest)
|
|
|
+ protected
|
|
|
+ function DoFunc(Input: Single): Single; override;
|
|
|
+ public
|
|
|
+ constructor Create; override;
|
|
|
+ function TestTitle: shortstring; override;
|
|
|
+ end;
|
|
|
+
|
|
|
+ TFloat32ExpSpecialTest = class(TFloat32ExpTest)
|
|
|
+ public
|
|
|
+ constructor Create; override;
|
|
|
+ function TestTitle: shortstring; override;
|
|
|
+ end;
|
|
|
+
|
|
|
+ TFloat32SinTest = class(TFloat32OneInputTest)
|
|
|
+ protected
|
|
|
+ function DoFunc(Input: Single): Single; override;
|
|
|
+ public
|
|
|
+ constructor Create; override;
|
|
|
+ function TestTitle: shortstring; override;
|
|
|
+ end;
|
|
|
+
|
|
|
+ TFloat32SinSpecialTest = class(TFloat32SinTest)
|
|
|
+ public
|
|
|
+ constructor Create; override;
|
|
|
+ function TestTitle: shortstring; override;
|
|
|
+ end;
|
|
|
+
|
|
|
+ TFloat32CosTest = class(TFloat32OneInputTest)
|
|
|
+ protected
|
|
|
+ function DoFunc(Input: Single): Single; override;
|
|
|
+ public
|
|
|
+ constructor Create; override;
|
|
|
+ function TestTitle: shortstring; override;
|
|
|
+ end;
|
|
|
+
|
|
|
+ TFloat32CosSpecialTest = class(TFloat32CosTest)
|
|
|
+ public
|
|
|
+ constructor Create; override;
|
|
|
+ function TestTitle: shortstring; override;
|
|
|
+ end;
|
|
|
+
|
|
|
+ TFloat32LdexpTest = class(TFloat32FloatIntTest)
|
|
|
+ protected
|
|
|
+ function DoFunc(Float: Single; N: Integer): Single; override;
|
|
|
+ public
|
|
|
+ constructor Create; override;
|
|
|
+ function TestTitle: shortstring; override;
|
|
|
+ end;
|
|
|
+
|
|
|
+ TFloat32LdexpSpecialTest = class(TFloat32LdexpTest)
|
|
|
+ public
|
|
|
+ constructor Create; override;
|
|
|
+ function TestTitle: shortstring; override;
|
|
|
+ end;
|
|
|
+
|
|
|
+ { 64-bit floating-point }
|
|
|
+ TFloat64MinTest = class(TFloat64TwoInputTest)
|
|
|
+ protected
|
|
|
+ function DoFunc(Input1, Input2: Double): Double; override;
|
|
|
+ public
|
|
|
+ constructor Create; override;
|
|
|
+ function TestTitle: shortstring; override;
|
|
|
+ end;
|
|
|
+
|
|
|
+ TFloat64ImplicitMinTest = class(TFloat64MinTest)
|
|
|
+ protected
|
|
|
+ function DoFunc(Input1, Input2: Double): Double; override;
|
|
|
+ public
|
|
|
+ function TestTitle: shortstring; override;
|
|
|
+ end;
|
|
|
+
|
|
|
+ TFloat64MinSpecialTest = class(TFloat64MinTest)
|
|
|
+ public
|
|
|
+ constructor Create; override;
|
|
|
+ function TestTitle: shortstring; override;
|
|
|
+ end;
|
|
|
+
|
|
|
+ TFloat64ImplicitMinSpecialTest = class(TFloat64MinSpecialTest)
|
|
|
+ protected
|
|
|
+ function DoFunc(Input1, Input2: Double): Double; override;
|
|
|
+ public
|
|
|
+ function TestTitle: shortstring; override;
|
|
|
+ end;
|
|
|
+
|
|
|
+ TFloat64MaxTest = class(TFloat64TwoInputTest)
|
|
|
+ protected
|
|
|
+ function DoFunc(Input1, Input2: Double): Double; override;
|
|
|
+ public
|
|
|
+ constructor Create; override;
|
|
|
+ function TestTitle: shortstring; override;
|
|
|
+ end;
|
|
|
+
|
|
|
+ TFloat64ImplicitMaxTest = class(TFloat64MaxTest)
|
|
|
+ protected
|
|
|
+ function DoFunc(Input1, Input2: Double): Double; override;
|
|
|
+ public
|
|
|
+ function TestTitle: shortstring; override;
|
|
|
+ end;
|
|
|
+
|
|
|
+ TFloat64MaxSpecialTest = class(TFloat64MaxTest)
|
|
|
+ public
|
|
|
+ constructor Create; override;
|
|
|
+ function TestTitle: shortstring; override;
|
|
|
+ end;
|
|
|
+
|
|
|
+ TFloat64ImplicitMaxSpecialTest = class(TFloat64MaxSpecialTest)
|
|
|
+ protected
|
|
|
+ function DoFunc(Input1, Input2: Double): Double; override;
|
|
|
+ public
|
|
|
+ function TestTitle: shortstring; override;
|
|
|
+ end;
|
|
|
+
|
|
|
+ TFloat64SqrtTest = class(TFloat64OneInputTest)
|
|
|
+ protected
|
|
|
+ function DoFunc(Input: Double): Double; override;
|
|
|
+ public
|
|
|
+ constructor Create; override;
|
|
|
+ function TestTitle: shortstring; override;
|
|
|
+ end;
|
|
|
+
|
|
|
+ TFloat64SqrtSpecialTest = class(TFloat64SqrtTest)
|
|
|
+ public
|
|
|
+ constructor Create; override;
|
|
|
+ function TestTitle: shortstring; override;
|
|
|
+ end;
|
|
|
+
|
|
|
+ TFloat64LnTest = class(TFloat64OneInputTest)
|
|
|
+ protected
|
|
|
+ function DoFunc(Input: Double): Double; override;
|
|
|
+ public
|
|
|
+ constructor Create; override;
|
|
|
+ function TestTitle: shortstring; override;
|
|
|
+ end;
|
|
|
+
|
|
|
+ TFloat64LnSpecialTest = class(TFloat64LnTest)
|
|
|
+ public
|
|
|
+ constructor Create; override;
|
|
|
+ function TestTitle: shortstring; override;
|
|
|
+ end;
|
|
|
+
|
|
|
+ TFloat64ExpTest = class(TFloat64OneInputTest)
|
|
|
+ protected
|
|
|
+ function DoFunc(Input: Double): Double; override;
|
|
|
+ public
|
|
|
+ constructor Create; override;
|
|
|
+ function TestTitle: shortstring; override;
|
|
|
+ end;
|
|
|
+
|
|
|
+ TFloat64ExpSpecialTest = class(TFloat64ExpTest)
|
|
|
+ public
|
|
|
+ constructor Create; override;
|
|
|
+ function TestTitle: shortstring; override;
|
|
|
+ end;
|
|
|
+
|
|
|
+ TFloat64SinTest = class(TFloat64OneInputTest)
|
|
|
+ protected
|
|
|
+ function DoFunc(Input: Double): Double; override;
|
|
|
+ public
|
|
|
+ constructor Create; override;
|
|
|
+ function TestTitle: shortstring; override;
|
|
|
+ end;
|
|
|
+
|
|
|
+ TFloat64SinSpecialTest = class(TFloat64SinTest)
|
|
|
+ public
|
|
|
+ constructor Create; override;
|
|
|
+ function TestTitle: shortstring; override;
|
|
|
+ end;
|
|
|
+
|
|
|
+ TFloat64CosTest = class(TFloat64OneInputTest)
|
|
|
+ protected
|
|
|
+ function DoFunc(Input: Double): Double; override;
|
|
|
+ public
|
|
|
+ constructor Create; override;
|
|
|
+ function TestTitle: shortstring; override;
|
|
|
+ end;
|
|
|
+
|
|
|
+ TFloat64CosSpecialTest = class(TFloat64CosTest)
|
|
|
+ public
|
|
|
+ constructor Create; override;
|
|
|
+ function TestTitle: shortstring; override;
|
|
|
+ end;
|
|
|
+
|
|
|
+ TFloat64LdexpTest = class(TFloat64FloatIntTest)
|
|
|
+ protected
|
|
|
+ function DoFunc(Float: Double; N: Integer): Double; override;
|
|
|
+ public
|
|
|
+ constructor Create; override;
|
|
|
+ function TestTitle: shortstring; override;
|
|
|
+ end;
|
|
|
+
|
|
|
+ TFloat64LdexpSpecialTest = class(TFloat64LdexpTest)
|
|
|
+ public
|
|
|
+ constructor Create; override;
|
|
|
+ function TestTitle: shortstring; override;
|
|
|
+ end;
|
|
|
+
|
|
|
+{ TTestAncestor }
|
|
|
+constructor TTestAncestor.Create;
|
|
|
+ begin
|
|
|
+ FStartTime := 0;
|
|
|
+ FEndTime := 0;
|
|
|
+ FAvgTime := 0;
|
|
|
+ end;
|
|
|
+
|
|
|
+destructor TTestAncestor.Destroy;
|
|
|
+ begin
|
|
|
+ inherited Destroy;
|
|
|
+ end;
|
|
|
+
|
|
|
+procedure TTestAncestor.SetStartTime;
|
|
|
+ begin
|
|
|
+ FStartTime := GetRealTime();
|
|
|
+ end;
|
|
|
+
|
|
|
+procedure TTestAncestor.SetEndTime;
|
|
|
+ begin
|
|
|
+ FEndTime := GetRealTime();
|
|
|
+ if FEndTime < FStartTime then { Happens if the test runs past midnight }
|
|
|
+ FEndTime := FEndTime + 86400.0;
|
|
|
+ end;
|
|
|
+
|
|
|
+procedure TTestAncestor.Run;
|
|
|
+ var
|
|
|
+ X: Integer;
|
|
|
+ begin
|
|
|
+ SetStartTime;
|
|
|
+ for X := 0 to ITERATIONS - 1 do
|
|
|
+ DoTestIteration(X);
|
|
|
+
|
|
|
+ SetEndTime;
|
|
|
+
|
|
|
+ FAvgTime := FEndTime - FStartTime;
|
|
|
+ end;
|
|
|
+
|
|
|
+{ TFloat32Test }
|
|
|
+
|
|
|
+class function TFloat32Test.IsEqual(Value, Reference: Single): Boolean;
|
|
|
+ var
|
|
|
+ Epsilon: Single;
|
|
|
+ begin
|
|
|
+ if IsNan(Reference) then
|
|
|
+ Exit(IsNan(Value))
|
|
|
+ else if IsInfinite(Reference) then
|
|
|
+ Exit(Value = Reference) { Must be the same infinity }
|
|
|
+ else if Abs(Reference) < 0.25 then
|
|
|
+ Epsilon := 0.00000095367431640625 { 2^-20 ~ 10^-6 }
|
|
|
+ else
|
|
|
+ Epsilon := Power(2, Floor(Ln(Reference) / Ln(2)) - 18);
|
|
|
+
|
|
|
+ Result := Abs(Value - Reference) <= Epsilon; { If Value is NaN, Result will be set to False }
|
|
|
+ end;
|
|
|
+
|
|
|
+function TFloat32Test.WriteResults: Boolean;
|
|
|
+ var
|
|
|
+ X: Byte;
|
|
|
+ begin
|
|
|
+ Result := True;
|
|
|
+
|
|
|
+ for X := 0 to High(FResultStorage) do
|
|
|
+ if not IsEqual(FResultStorage[X], FExpected[X]) then
|
|
|
+ begin
|
|
|
+ WriteLn('FAIL - index ', X, '; expected ', FExpected[X], ' got ', FResultStorage[X]);
|
|
|
+ Result := False;
|
|
|
+ Exit;
|
|
|
+ end;
|
|
|
+ end;
|
|
|
+
|
|
|
+{ TFloat32OneInputTest }
|
|
|
+
|
|
|
+procedure TFloat32OneInputTest.DoTestIteration(Iteration: Integer);
|
|
|
+ begin
|
|
|
+ Iteration := Iteration and $7;
|
|
|
+ FResultStorage[Iteration] := DoFunc(FInputs[Iteration]);
|
|
|
+ end;
|
|
|
+
|
|
|
+{ TFloat32TwoInputTest }
|
|
|
+
|
|
|
+procedure TFloat32TwoInputTest.DoTestIteration(Iteration: Integer);
|
|
|
+ begin
|
|
|
+ Iteration := Iteration and $7;
|
|
|
+ FResultStorage[Iteration] := DoFunc(FInputs[Iteration][0], FInputs[Iteration][1]);
|
|
|
+ end;
|
|
|
+
|
|
|
+{ TFloat32FloatIntTest }
|
|
|
+
|
|
|
+procedure TFloat32FloatIntTest.DoTestIteration(Iteration: Integer);
|
|
|
+ begin
|
|
|
+ Iteration := Iteration and $7;
|
|
|
+ FResultStorage[Iteration] := DoFunc(FInputs[Iteration].S, FInputs[Iteration].N);
|
|
|
+ end;
|
|
|
+
|
|
|
+{ TFloat32MinTest }
|
|
|
+const
|
|
|
+ MINMAX_INPUTS: array[0..7] of array[0..1] of Single = (
|
|
|
+ (-0.5, 0.5),
|
|
|
+ (1048576.0, 1048577.0),
|
|
|
+ (-1048576.0, -1048577.0),
|
|
|
+ (0.0, -0.0),
|
|
|
+ (0.0, 1E4),
|
|
|
+ (0.0, -1E4),
|
|
|
+ (0.0, 1E-4),
|
|
|
+ (0.0, -1E-4)
|
|
|
+ );
|
|
|
+
|
|
|
+ MIN_EXPECTED: array[0..7] of Single = (
|
|
|
+ -0.5,
|
|
|
+ 1048576.0,
|
|
|
+ -1048577.0,
|
|
|
+ -0.0,
|
|
|
+ 0.0,
|
|
|
+ -1E4,
|
|
|
+ 0.0,
|
|
|
+ -1E-4
|
|
|
+ );
|
|
|
+
|
|
|
+ MAX_EXPECTED: array[0..7] of Single = (
|
|
|
+ 0.5,
|
|
|
+ 1048577.0,
|
|
|
+ -1048576.0,
|
|
|
+ -0.0,
|
|
|
+ 1E4,
|
|
|
+ 0.0,
|
|
|
+ 1E-4,
|
|
|
+ 0.0
|
|
|
+ );
|
|
|
+
|
|
|
+constructor TFloat32MinTest.Create;
|
|
|
+begin
|
|
|
+ inherited Create;
|
|
|
+ Move(MINMAX_INPUTS, FInputs, SizeOf(FInputs));
|
|
|
+ Move(MIN_EXPECTED, FExpected, SizeOf(FExpected));
|
|
|
+end;
|
|
|
+
|
|
|
+function TFloat32MinTest.DoFunc(Input1, Input2: Single): Single;
|
|
|
+ begin
|
|
|
+ Result := Min(Input1, Input2);
|
|
|
+ end;
|
|
|
+
|
|
|
+function TFloat32MinTest.TestTitle: shortstring;
|
|
|
+ begin
|
|
|
+ Result := 'Min (single-precision)';
|
|
|
+ end;
|
|
|
+
|
|
|
+function TFloat32ImplicitMinTest.DoFunc(Input1, Input2: Single): Single;
|
|
|
+ begin
|
|
|
+ if Input1 < Input2 then
|
|
|
+ Result := Input1
|
|
|
+ else
|
|
|
+ Result := Input2;
|
|
|
+ end;
|
|
|
+
|
|
|
+function TFloat32ImplicitMinTest.TestTitle: shortstring;
|
|
|
+ begin
|
|
|
+ Result := 'Implicit Min (single-precision)';
|
|
|
+ end;
|
|
|
+
|
|
|
+{ TFloat32MaxTest }
|
|
|
+
|
|
|
+constructor TFloat32MaxTest.Create;
|
|
|
+begin
|
|
|
+ inherited Create;
|
|
|
+ Move(MINMAX_INPUTS, FInputs, SizeOf(FInputs));
|
|
|
+ Move(MAX_EXPECTED, FExpected, SizeOf(FExpected));
|
|
|
+end;
|
|
|
+
|
|
|
+function TFloat32MaxTest.DoFunc(Input1, Input2: Single): Single;
|
|
|
+ begin
|
|
|
+ Result := Max(Input1, Input2);
|
|
|
+ end;
|
|
|
+
|
|
|
+function TFloat32MaxTest.TestTitle: shortstring;
|
|
|
+ begin
|
|
|
+ Result := 'Max (single-precision)';
|
|
|
+ end;
|
|
|
+
|
|
|
+function TFloat32ImplicitMaxTest.DoFunc(Input1, Input2: Single): Single;
|
|
|
+ begin
|
|
|
+ if Input1 > Input2 then
|
|
|
+ Result := Input1
|
|
|
+ else
|
|
|
+ Result := Input2;
|
|
|
+ end;
|
|
|
+
|
|
|
+function TFloat32ImplicitMaxTest.TestTitle: shortstring;
|
|
|
+ begin
|
|
|
+ Result := 'Implicit Max (single-precision)';
|
|
|
+ end;
|
|
|
+
|
|
|
+{ TFloat32MinTest }
|
|
|
+const
|
|
|
+ MINMAX_SPECIAL_INPUTS: array[0..7] of array[0..1] of Single = (
|
|
|
+ (NaN, 0.0),
|
|
|
+ (0.0, NaN),
|
|
|
+ (0.0, Infinity),
|
|
|
+ (Infinity, 0.0),
|
|
|
+ (0.0, NegInfinity),
|
|
|
+ (NegInfinity, 0.0),
|
|
|
+ (Infinity, NegInfinity),
|
|
|
+ (NegInfinity, Infinity)
|
|
|
+ );
|
|
|
+
|
|
|
+ MIN_SPECIAL_EXPECTED: array[0..7] of Single = (
|
|
|
+ 0.0,
|
|
|
+ NaN,
|
|
|
+ 0.0,
|
|
|
+ 0.0,
|
|
|
+ NegInfinity,
|
|
|
+ NegInfinity,
|
|
|
+ NegInfinity,
|
|
|
+ NegInfinity
|
|
|
+ );
|
|
|
+
|
|
|
+ MAX_SPECIAL_EXPECTED: array[0..7] of Single = (
|
|
|
+ 0.0,
|
|
|
+ NaN,
|
|
|
+ Infinity,
|
|
|
+ Infinity,
|
|
|
+ 0.0,
|
|
|
+ 0.0,
|
|
|
+ Infinity,
|
|
|
+ Infinity
|
|
|
+ );
|
|
|
+
|
|
|
+constructor TFloat32MinSpecialTest.Create;
|
|
|
+begin
|
|
|
+ inherited Create;
|
|
|
+ Move(MINMAX_SPECIAL_INPUTS, FInputs, SizeOf(FInputs));
|
|
|
+ Move(MIN_SPECIAL_EXPECTED, FExpected, SizeOf(FExpected));
|
|
|
+end;
|
|
|
+
|
|
|
+function TFloat32MinSpecialTest.TestTitle: shortstring;
|
|
|
+ begin
|
|
|
+ Result := 'Min (special single-precision)';
|
|
|
+ end;
|
|
|
+
|
|
|
+function TFloat32ImplicitMinSpecialTest.DoFunc(Input1, Input2: Single): Single;
|
|
|
+ begin
|
|
|
+ if Input1 < Input2 then
|
|
|
+ Result := Input1
|
|
|
+ else
|
|
|
+ Result := Input2;
|
|
|
+ end;
|
|
|
+
|
|
|
+function TFloat32ImplicitMinSpecialTest.TestTitle: shortstring;
|
|
|
+ begin
|
|
|
+ Result := 'Implicit Min (special single-precision)';
|
|
|
+ end;
|
|
|
+
|
|
|
+{ TFloat32MaxTest }
|
|
|
+
|
|
|
+constructor TFloat32MaxSpecialTest.Create;
|
|
|
+begin
|
|
|
+ inherited Create;
|
|
|
+ Move(MINMAX_SPECIAL_INPUTS, FInputs, SizeOf(FInputs));
|
|
|
+ Move(MAX_SPECIAL_EXPECTED, FExpected, SizeOf(FExpected));
|
|
|
+end;
|
|
|
+
|
|
|
+function TFloat32MaxSpecialTest.TestTitle: shortstring;
|
|
|
+ begin
|
|
|
+ Result := 'Max (special single-precision)';
|
|
|
+ end;
|
|
|
+
|
|
|
+function TFloat32ImplicitMaxSpecialTest.DoFunc(Input1, Input2: Single): Single;
|
|
|
+ begin
|
|
|
+ if Input1 > Input2 then
|
|
|
+ Result := Input1
|
|
|
+ else
|
|
|
+ Result := Input2;
|
|
|
+ end;
|
|
|
+
|
|
|
+function TFloat32ImplicitMaxSpecialTest.TestTitle: shortstring;
|
|
|
+ begin
|
|
|
+ Result := 'Implicit Max (special single-precision)';
|
|
|
+ end;
|
|
|
+
|
|
|
+{ TFloat32SqrtTest }
|
|
|
+const
|
|
|
+ SQRT_INPUTS: array[0..7] of Single = (
|
|
|
+ 4.0,
|
|
|
+ 1.0,
|
|
|
+ 256.0,
|
|
|
+ 2.0,
|
|
|
+ 100.0,
|
|
|
+ 0.5,
|
|
|
+ 3.1415926535897932384626433832795, { Pi }
|
|
|
+ 1.5707963267948966192313216916398 { Pi / 2 }
|
|
|
+ );
|
|
|
+
|
|
|
+ SQRT_EXPECTED: array[0..7] of Single = (
|
|
|
+ 2.0,
|
|
|
+ 1.0,
|
|
|
+ 16.0,
|
|
|
+ 1.414213562373095,
|
|
|
+ 10.0,
|
|
|
+ 0.707106781186548,
|
|
|
+ 1.772453850905516,
|
|
|
+ 1.253314137315500
|
|
|
+ );
|
|
|
+
|
|
|
+constructor TFloat32SqrtTest.Create;
|
|
|
+begin
|
|
|
+ inherited Create;
|
|
|
+ Move(SQRT_INPUTS, FInputs, SizeOf(FInputs));
|
|
|
+ Move(SQRT_EXPECTED, FExpected, SizeOf(FExpected));
|
|
|
+end;
|
|
|
+
|
|
|
+function TFloat32SqrtTest.DoFunc(Input: Single): Single;
|
|
|
+ begin
|
|
|
+ Result := Sqrt(Input);
|
|
|
+ end;
|
|
|
+
|
|
|
+function TFloat32SqrtTest.TestTitle: shortstring;
|
|
|
+ begin
|
|
|
+ Result := 'sqrt(x) (single-precision)';
|
|
|
+ end;
|
|
|
+
|
|
|
+{ TFloat32SqrtSpecialTest }
|
|
|
+const
|
|
|
+ SQRT_SPECIAL_INPUTS: array[0..7] of Single = (
|
|
|
+ 0.0,
|
|
|
+ Infinity,
|
|
|
+ NegInfinity,
|
|
|
+ NaN,
|
|
|
+ -0.0,
|
|
|
+ -1.0,
|
|
|
+ 1E6,
|
|
|
+ NaN
|
|
|
+ );
|
|
|
+
|
|
|
+ SQRT_SPECIAL_EXPECTED: array[0..7] of Single = (
|
|
|
+ 0.0,
|
|
|
+ Infinity,
|
|
|
+ NaN,
|
|
|
+ NaN,
|
|
|
+ 0.0,
|
|
|
+ NaN,
|
|
|
+ 1E3,
|
|
|
+ NaN
|
|
|
+ );
|
|
|
+
|
|
|
+constructor TFloat32SqrtSpecialTest.Create;
|
|
|
+begin
|
|
|
+ inherited Create;
|
|
|
+ Move(SQRT_SPECIAL_INPUTS, FInputs, SizeOf(FInputs));
|
|
|
+ Move(SQRT_SPECIAL_EXPECTED, FExpected, SizeOf(FExpected));
|
|
|
+end;
|
|
|
+
|
|
|
+function TFloat32SqrtSpecialTest.TestTitle: shortstring;
|
|
|
+ begin
|
|
|
+ Result := 'sqrt(x) (special single-precision)';
|
|
|
+ end;
|
|
|
+
|
|
|
+{ TFloat32LnTest }
|
|
|
+
|
|
|
+const
|
|
|
+ LN_EXPECTED: array[0..7] of Single = (
|
|
|
+ 1.386294361119891,
|
|
|
+ 0.0,
|
|
|
+ 5.545177444479562,
|
|
|
+ 0.693147180559945,
|
|
|
+ 4.605170185988091,
|
|
|
+ -0.693147180559945,
|
|
|
+ 1.1447298858494002,
|
|
|
+ 0.4515827052894549
|
|
|
+ );
|
|
|
+
|
|
|
+constructor TFloat32LnTest.Create;
|
|
|
+begin
|
|
|
+ inherited Create;
|
|
|
+ Move(SQRT_INPUTS, FInputs, SizeOf(FInputs)); { Reuse the sqrt inputs }
|
|
|
+ Move(LN_EXPECTED, FExpected, SizeOf(FExpected));
|
|
|
+end;
|
|
|
+
|
|
|
+function TFloat32LnTest.DoFunc(Input: Single): Single;
|
|
|
+ begin
|
|
|
+ Result := Ln(Input);
|
|
|
+ end;
|
|
|
+
|
|
|
+function TFloat32LnTest.TestTitle: shortstring;
|
|
|
+ begin
|
|
|
+ Result := 'ln x (single-precision)';
|
|
|
+ end;
|
|
|
+
|
|
|
+{ TFloat32LnSpecialTest }
|
|
|
+
|
|
|
+const
|
|
|
+ LN_SPECIAL_EXPECTED: array[0..7] of Single = (
|
|
|
+ NegInfinity,
|
|
|
+ Infinity,
|
|
|
+ NaN,
|
|
|
+ NaN,
|
|
|
+ NegInfinity,
|
|
|
+ NaN,
|
|
|
+ 13.815510557964274,
|
|
|
+ NaN
|
|
|
+ );
|
|
|
+
|
|
|
+constructor TFloat32LnSpecialTest.Create;
|
|
|
+begin
|
|
|
+ inherited Create;
|
|
|
+ Move(SQRT_SPECIAL_INPUTS, FInputs, SizeOf(FInputs)); { Reuse the sqrt inputs }
|
|
|
+ Move(LN_SPECIAL_EXPECTED, FExpected, SizeOf(FExpected));
|
|
|
+end;
|
|
|
+
|
|
|
+function TFloat32LnSpecialTest.TestTitle: shortstring;
|
|
|
+ begin
|
|
|
+ Result := 'ln x (special single-precision)';
|
|
|
+ end;
|
|
|
+
|
|
|
+{ TFloat32ExpTest }
|
|
|
+const
|
|
|
+ EXP_EXPECTED: array[0..7] of Single = (
|
|
|
+ 54.598150033144239,
|
|
|
+ 2.718281828459045,
|
|
|
+ 1.5114276650041035e+111,
|
|
|
+ 7.3890560989306502,
|
|
|
+ 2.6881171418161354e+43,
|
|
|
+ 1.6487212707001281,
|
|
|
+ 23.1406926327792690,
|
|
|
+ 4.8104773809653517
|
|
|
+ );
|
|
|
+
|
|
|
+constructor TFloat32ExpTest.Create;
|
|
|
+begin
|
|
|
+ inherited Create;
|
|
|
+ Move(SQRT_INPUTS, FInputs, SizeOf(FInputs)); { Reuse the sqrt inputs }
|
|
|
+ Move(EXP_EXPECTED, FExpected, SizeOf(FExpected));
|
|
|
+end;
|
|
|
+
|
|
|
+function TFloat32ExpTest.DoFunc(Input: Single): Single;
|
|
|
+ begin
|
|
|
+ Result := Exp(Input);
|
|
|
+ end;
|
|
|
+
|
|
|
+function TFloat32ExpTest.TestTitle: shortstring;
|
|
|
+ begin
|
|
|
+ Result := 'e^x (single-precision)';
|
|
|
+ end;
|
|
|
+
|
|
|
+{ TFloat32ExpSpecialTest }
|
|
|
+const
|
|
|
+ EXP_SPECIAL_EXPECTED: array[0..7] of Single = (
|
|
|
+ 1.0,
|
|
|
+ Infinity,
|
|
|
+ 0,
|
|
|
+ NaN,
|
|
|
+ 1.0,
|
|
|
+ 0.3678794411714423,
|
|
|
+ Infinity,
|
|
|
+ NaN
|
|
|
+ );
|
|
|
+
|
|
|
+constructor TFloat32ExpSpecialTest.Create;
|
|
|
+begin
|
|
|
+ inherited Create;
|
|
|
+ Move(SQRT_SPECIAL_INPUTS, FInputs, SizeOf(FInputs)); { Reuse the sqrt inputs }
|
|
|
+ Move(EXP_SPECIAL_EXPECTED, FExpected, SizeOf(FExpected));
|
|
|
+end;
|
|
|
+
|
|
|
+function TFloat32ExpSpecialTest.TestTitle: shortstring;
|
|
|
+ begin
|
|
|
+ Result := 'e^x (special single-precision)';
|
|
|
+ end;
|
|
|
+
|
|
|
+{ TFloat32SinTest }
|
|
|
+const
|
|
|
+ SIN_EXPECTED: array[0..7] of Single = (
|
|
|
+ -0.756802495307928,
|
|
|
+ 0.841470984807897,
|
|
|
+ -0.999208034107063,
|
|
|
+ 0.9092974268256817,
|
|
|
+ -0.5063656411097588,
|
|
|
+ 0.4794255386042030,
|
|
|
+ 0.0,
|
|
|
+ 1.0
|
|
|
+ );
|
|
|
+
|
|
|
+constructor TFloat32SinTest.Create;
|
|
|
+begin
|
|
|
+ inherited Create;
|
|
|
+ Move(SQRT_INPUTS, FInputs, SizeOf(FInputs)); { Reuse the sqrt inputs }
|
|
|
+ Move(SIN_EXPECTED, FExpected, SizeOf(FExpected));
|
|
|
+end;
|
|
|
+
|
|
|
+function TFloat32SinTest.DoFunc(Input: Single): Single;
|
|
|
+ begin
|
|
|
+ Result := Sin(Input);
|
|
|
+ end;
|
|
|
+
|
|
|
+function TFloat32SinTest.TestTitle: shortstring;
|
|
|
+ begin
|
|
|
+ Result := 'sin x (single-precision)';
|
|
|
+ end;
|
|
|
+
|
|
|
+{ TFloat32SinSpecialTest }
|
|
|
+const
|
|
|
+ SIN_SPECIAL_INPUTS: array[0..7] of Single = ( { Using different inputs as infinities are invalid }
|
|
|
+ 0.0,
|
|
|
+ -1.0,
|
|
|
+ 1E6,
|
|
|
+ NaN,
|
|
|
+ -0.0,
|
|
|
+ -1.0,
|
|
|
+ 1E6,
|
|
|
+ NaN
|
|
|
+ );
|
|
|
+
|
|
|
+ SIN_SPECIAL_EXPECTED: array[0..7] of Single = (
|
|
|
+ 0.0,
|
|
|
+ -0.8414709848078965,
|
|
|
+ -0.3499935021712930,
|
|
|
+ NaN,
|
|
|
+ -0.0,
|
|
|
+ -0.8414709848078965,
|
|
|
+ -0.3499935021712930,
|
|
|
+ NaN
|
|
|
+ );
|
|
|
+
|
|
|
+constructor TFloat32SinSpecialTest.Create;
|
|
|
+begin
|
|
|
+ inherited Create;
|
|
|
+ Move(SIN_SPECIAL_INPUTS, FInputs, SizeOf(FInputs));
|
|
|
+ Move(SIN_SPECIAL_EXPECTED, FExpected, SizeOf(FExpected));
|
|
|
+end;
|
|
|
+
|
|
|
+function TFloat32SinSpecialTest.TestTitle: shortstring;
|
|
|
+ begin
|
|
|
+ Result := 'sin x (special single-precision)';
|
|
|
+ end;
|
|
|
+
|
|
|
+{ TFloat32CosTest }
|
|
|
+const
|
|
|
+ COS_EXPECTED: array[0..7] of Single = (
|
|
|
+ -0.6536436208636119,
|
|
|
+ 0.5403023058681397,
|
|
|
+ -0.0397907599311577,
|
|
|
+ -0.4161468365471424,
|
|
|
+ 0.8623188722876839,
|
|
|
+ 0.8775825618903727,
|
|
|
+ -1.0, { Pi }
|
|
|
+ 0.0
|
|
|
+ );
|
|
|
+
|
|
|
+constructor TFloat32CosTest.Create;
|
|
|
+begin
|
|
|
+ inherited Create;
|
|
|
+ Move(SQRT_INPUTS, FInputs, SizeOf(FInputs)); { Reuse the sqrt inputs }
|
|
|
+ Move(COS_EXPECTED, FExpected, SizeOf(FExpected));
|
|
|
+end;
|
|
|
+
|
|
|
+function TFloat32CosTest.DoFunc(Input: Single): Single;
|
|
|
+ begin
|
|
|
+ Result := Cos(Input);
|
|
|
+ end;
|
|
|
+
|
|
|
+function TFloat32CosTest.TestTitle: shortstring;
|
|
|
+ begin
|
|
|
+ Result := 'cos x (single-precision)';
|
|
|
+ end;
|
|
|
+
|
|
|
+{ TFloat32SinSpecialTest }
|
|
|
+const
|
|
|
+ COS_SPECIAL_EXPECTED: array[0..7] of Single = (
|
|
|
+ 1.0,
|
|
|
+ 0.5403023058681397,
|
|
|
+ 0.9367521275331448,
|
|
|
+ NaN,
|
|
|
+ 1.0,
|
|
|
+ 0.5403023058681397,
|
|
|
+ 0.9367521275331448,
|
|
|
+ NaN
|
|
|
+ );
|
|
|
+
|
|
|
+constructor TFloat32CosSpecialTest.Create;
|
|
|
+begin
|
|
|
+ inherited Create;
|
|
|
+ Move(SIN_SPECIAL_INPUTS, FInputs, SizeOf(FInputs));
|
|
|
+ Move(COS_SPECIAL_EXPECTED, FExpected, SizeOf(FExpected));
|
|
|
+end;
|
|
|
+
|
|
|
+function TFloat32CosSpecialTest.TestTitle: shortstring;
|
|
|
+ begin
|
|
|
+ Result := 'cos x (special single-precision)';
|
|
|
+ end;
|
|
|
+
|
|
|
+{ TFloat32LdexpTest }
|
|
|
+const
|
|
|
+ LDEXP_INPUTS: array[0..7] of TSingleIntPair = (
|
|
|
+ (S: 1.0; N: 0),
|
|
|
+ (S: 2.7182818284590452353602874713527; N: -1),
|
|
|
+ (S: 0.85309609426787873559547283129472; N: 6),
|
|
|
+ (S: 0.1; N: 1),
|
|
|
+ (S: 0.2; N: 2),
|
|
|
+ (S: 0.3; N: 3),
|
|
|
+ (S: 0.4; N: 4),
|
|
|
+ (S: 0.5; N: 5)
|
|
|
+ );
|
|
|
+
|
|
|
+ LDEXP_EXPECTED: array[0..7] of Single = (
|
|
|
+ 1.0,
|
|
|
+ 1.3591409142295226176801437356763,
|
|
|
+ 54.598150033144239078110261202862,
|
|
|
+ 0.2,
|
|
|
+ 0.8,
|
|
|
+ 2.4,
|
|
|
+ 6.4,
|
|
|
+ 16.0
|
|
|
+ );
|
|
|
+
|
|
|
+constructor TFloat32LdexpTest.Create;
|
|
|
+begin
|
|
|
+ inherited Create;
|
|
|
+ Move(LDEXP_INPUTS, FInputs, SizeOf(FInputs));
|
|
|
+ Move(LDEXP_EXPECTED, FExpected, SizeOf(FExpected));
|
|
|
+end;
|
|
|
+
|
|
|
+function TFloat32LdexpTest.DoFunc(Float: Single; N: Integer): Single;
|
|
|
+ begin
|
|
|
+ Result := LdExp(Float, N);
|
|
|
+ end;
|
|
|
+
|
|
|
+function TFloat32LdexpTest.TestTitle: shortstring;
|
|
|
+ begin
|
|
|
+ Result := 'ldexp(x, n) (single-precision)';
|
|
|
+ end;
|
|
|
+
|
|
|
+{ TFloat32SpecialLdexpTest }
|
|
|
+const
|
|
|
+ LDEXP_SPECIAL_INPUTS: array[0..7] of TSingleIntPair = (
|
|
|
+ (S: Infinity; N: 0),
|
|
|
+ (S: NegInfinity; N: 0),
|
|
|
+ (S: 2.0; N: -128),
|
|
|
+ (S: 2.0; N: 127),
|
|
|
+ (S: NaN; N: 1),
|
|
|
+ (S: 0.0; N: 16384),
|
|
|
+ (S: 1.7014118346046923173168730371588e+38; N: -128),
|
|
|
+ (S: 2.9387358770557187699218413430556e-39; N: 127)
|
|
|
+ );
|
|
|
+
|
|
|
+ LDEXP_SPECIAL_EXPECTED: array[0..7] of Single = (
|
|
|
+ Infinity,
|
|
|
+ NegInfinity,
|
|
|
+ 2.9387358770557187699218413430556e-39,
|
|
|
+ Infinity,
|
|
|
+ Nan,
|
|
|
+ 0.0,
|
|
|
+ 0.5,
|
|
|
+ 0.5
|
|
|
+ );
|
|
|
+
|
|
|
+constructor TFloat32LdexpSpecialTest.Create;
|
|
|
+begin
|
|
|
+ inherited Create;
|
|
|
+ Move(LDEXP_SPECIAL_INPUTS, FInputs, SizeOf(FInputs));
|
|
|
+ Move(LDEXP_SPECIAL_EXPECTED, FExpected, SizeOf(FExpected));
|
|
|
+end;
|
|
|
+
|
|
|
+function TFloat32LdexpSpecialTest.TestTitle: shortstring;
|
|
|
+ begin
|
|
|
+ Result := 'ldexp(x, n) (special single-precision)';
|
|
|
+ end;
|
|
|
+
|
|
|
+{ TFloat64Test }
|
|
|
+
|
|
|
+class function TFloat64Test.IsEqual(Value, Reference: Double): Boolean;
|
|
|
+ var
|
|
|
+ Epsilon: Double;
|
|
|
+ begin
|
|
|
+ if IsNan(Reference) then
|
|
|
+ Exit(IsNan(Value))
|
|
|
+ else if IsInfinite(Reference) then
|
|
|
+ Exit(Value = Reference)
|
|
|
+ else if Abs(Reference) < 0.25 then
|
|
|
+ Epsilon := 9.094947017729282379150390625e-13 { 2^-40 ~ 10^-12 }
|
|
|
+ else
|
|
|
+ Epsilon := Power(2, Floor(Ln(Reference) / Ln(2)) - 18);
|
|
|
+
|
|
|
+ Result := Abs(Value - Reference) <= Epsilon;
|
|
|
+ end;
|
|
|
+
|
|
|
+function TFloat64Test.WriteResults: Boolean;
|
|
|
+ var
|
|
|
+ X: Byte;
|
|
|
+ begin
|
|
|
+ Result := True;
|
|
|
+
|
|
|
+ for X := 0 to High(FResultStorage) do
|
|
|
+ if not IsEqual(FResultStorage[X], FExpected[X]) then
|
|
|
+ begin
|
|
|
+ WriteLn('FAIL - index ', X, '; expected ', FExpected[X], ' got ', FResultStorage[X]);
|
|
|
+ Result := False;
|
|
|
+ Exit;
|
|
|
+ end;
|
|
|
+ end;
|
|
|
+
|
|
|
+{ TFloat64OneInputTest }
|
|
|
+
|
|
|
+procedure TFloat64OneInputTest.DoTestIteration(Iteration: Integer);
|
|
|
+ begin
|
|
|
+ Iteration := Iteration and $7;
|
|
|
+ FResultStorage[Iteration] := DoFunc(FInputs[Iteration]);
|
|
|
+ end;
|
|
|
+
|
|
|
+{ TFloat64TwoInputTest }
|
|
|
+
|
|
|
+procedure TFloat64TwoInputTest.DoTestIteration(Iteration: Integer);
|
|
|
+ begin
|
|
|
+ Iteration := Iteration and $7;
|
|
|
+ FResultStorage[Iteration] := DoFunc(FInputs[Iteration][0], FInputs[Iteration][1]);
|
|
|
+ end;
|
|
|
+
|
|
|
+{ TFloat64FloatIntTest }
|
|
|
+
|
|
|
+procedure TFloat64FloatIntTest.DoTestIteration(Iteration: Integer);
|
|
|
+ begin
|
|
|
+ Iteration := Iteration and $7;
|
|
|
+ FResultStorage[Iteration] := DoFunc(FInputs[Iteration].D, FInputs[Iteration].N);
|
|
|
+ end;
|
|
|
+
|
|
|
+{ TFloat64MinTest }
|
|
|
+const
|
|
|
+ MINMAX_64_INPUTS: array[0..7] of array[0..1] of Double = (
|
|
|
+ (-0.5, 0.5),
|
|
|
+ (1048576.0, 1048577.0),
|
|
|
+ (-1048576.0, -1048577.0),
|
|
|
+ (0.0, -0.0),
|
|
|
+ (0.0, 1E4),
|
|
|
+ (0.0, -1E4),
|
|
|
+ (0.0, 1E-4),
|
|
|
+ (0.0, -1E-4)
|
|
|
+ );
|
|
|
+
|
|
|
+ MIN_64_EXPECTED: array[0..7] of Double = (
|
|
|
+ -0.5,
|
|
|
+ 1048576.0,
|
|
|
+ -1048577.0,
|
|
|
+ -0.0,
|
|
|
+ 0.0,
|
|
|
+ -1E4,
|
|
|
+ 0.0,
|
|
|
+ -1E-4
|
|
|
+ );
|
|
|
+
|
|
|
+ MAX_64_EXPECTED: array[0..7] of Double = (
|
|
|
+ 0.5,
|
|
|
+ 1048577.0,
|
|
|
+ -1048576.0,
|
|
|
+ -0.0,
|
|
|
+ 1E4,
|
|
|
+ 0.0,
|
|
|
+ 1E-4,
|
|
|
+ 0.0
|
|
|
+ );
|
|
|
+
|
|
|
+constructor TFloat64MinTest.Create;
|
|
|
+begin
|
|
|
+ inherited Create;
|
|
|
+ Move(MINMAX_64_INPUTS, FInputs, SizeOf(FInputs));
|
|
|
+ Move(MIN_64_EXPECTED, FExpected, SizeOf(FExpected));
|
|
|
+end;
|
|
|
+
|
|
|
+function TFloat64MinTest.DoFunc(Input1, Input2: Double): Double;
|
|
|
+ begin
|
|
|
+ Result := Min(Input1, Input2);
|
|
|
+ end;
|
|
|
+
|
|
|
+function TFloat64MinTest.TestTitle: shortstring;
|
|
|
+ begin
|
|
|
+ Result := 'Min (double-precision)';
|
|
|
+ end;
|
|
|
+
|
|
|
+function TFloat64ImplicitMinTest.DoFunc(Input1, Input2: Double): Double;
|
|
|
+ begin
|
|
|
+ if Input1 < Input2 then
|
|
|
+ Result := Input1
|
|
|
+ else
|
|
|
+ Result := Input2;
|
|
|
+ end;
|
|
|
+
|
|
|
+function TFloat64ImplicitMinTest.TestTitle: shortstring;
|
|
|
+ begin
|
|
|
+ Result := 'Implicit Min (double-precision)';
|
|
|
+ end;
|
|
|
+
|
|
|
+{ TFloat64MaxTest }
|
|
|
+
|
|
|
+constructor TFloat64MaxTest.Create;
|
|
|
+begin
|
|
|
+ inherited Create;
|
|
|
+ Move(MINMAX_64_INPUTS, FInputs, SizeOf(FInputs));
|
|
|
+ Move(MAX_64_EXPECTED, FExpected, SizeOf(FExpected));
|
|
|
+end;
|
|
|
+
|
|
|
+function TFloat64MaxTest.DoFunc(Input1, Input2: Double): Double;
|
|
|
+ begin
|
|
|
+ Result := Max(Input1, Input2);
|
|
|
+ end;
|
|
|
+
|
|
|
+function TFloat64MaxTest.TestTitle: shortstring;
|
|
|
+ begin
|
|
|
+ Result := 'Max (double-precision)';
|
|
|
+ end;
|
|
|
+
|
|
|
+function TFloat64ImplicitMaxTest.DoFunc(Input1, Input2: Double): Double;
|
|
|
+ begin
|
|
|
+ if Input1 > Input2 then
|
|
|
+ Result := Input1
|
|
|
+ else
|
|
|
+ Result := Input2;
|
|
|
+ end;
|
|
|
+
|
|
|
+function TFloat64ImplicitMaxTest.TestTitle: shortstring;
|
|
|
+ begin
|
|
|
+ Result := 'Implicit Max (double-precision)';
|
|
|
+ end;
|
|
|
+
|
|
|
+{ TFloat64MinTest }
|
|
|
+const
|
|
|
+ MINMAX_64_SPECIAL_INPUTS: array[0..7] of array[0..1] of Double = (
|
|
|
+ (NaN, 0.0),
|
|
|
+ (0.0, NaN),
|
|
|
+ (0.0, Infinity),
|
|
|
+ (Infinity, 0.0),
|
|
|
+ (0.0, NegInfinity),
|
|
|
+ (NegInfinity, 0.0),
|
|
|
+ (Infinity, NegInfinity),
|
|
|
+ (NegInfinity, Infinity)
|
|
|
+ );
|
|
|
+
|
|
|
+ MIN_64_SPECIAL_EXPECTED: array[0..7] of Double = (
|
|
|
+ 0.0,
|
|
|
+ NaN,
|
|
|
+ 0.0,
|
|
|
+ 0.0,
|
|
|
+ NegInfinity,
|
|
|
+ NegInfinity,
|
|
|
+ NegInfinity,
|
|
|
+ NegInfinity
|
|
|
+ );
|
|
|
+
|
|
|
+ MAX_64_SPECIAL_EXPECTED: array[0..7] of Double = (
|
|
|
+ 0.0,
|
|
|
+ NaN,
|
|
|
+ Infinity,
|
|
|
+ Infinity,
|
|
|
+ 0.0,
|
|
|
+ 0.0,
|
|
|
+ Infinity,
|
|
|
+ Infinity
|
|
|
+ );
|
|
|
+
|
|
|
+constructor TFloat64MinSpecialTest.Create;
|
|
|
+begin
|
|
|
+ inherited Create;
|
|
|
+ Move(MINMAX_64_SPECIAL_INPUTS, FInputs, SizeOf(FInputs));
|
|
|
+ Move(MIN_64_SPECIAL_EXPECTED, FExpected, SizeOf(FExpected));
|
|
|
+end;
|
|
|
+
|
|
|
+function TFloat64MinSpecialTest.TestTitle: shortstring;
|
|
|
+ begin
|
|
|
+ Result := 'Min (special double-precision)';
|
|
|
+ end;
|
|
|
+
|
|
|
+function TFloat64ImplicitMinSpecialTest.DoFunc(Input1, Input2: Double): Double;
|
|
|
+ begin
|
|
|
+ if Input1 < Input2 then
|
|
|
+ Result := Input1
|
|
|
+ else
|
|
|
+ Result := Input2;
|
|
|
+ end;
|
|
|
+
|
|
|
+function TFloat64ImplicitMinSpecialTest.TestTitle: shortstring;
|
|
|
+ begin
|
|
|
+ Result := 'Implicit Min (special double-precision)';
|
|
|
+ end;
|
|
|
+
|
|
|
+{ TFloat64MaxTest }
|
|
|
+
|
|
|
+constructor TFloat64MaxSpecialTest.Create;
|
|
|
+begin
|
|
|
+ inherited Create;
|
|
|
+ Move(MINMAX_64_SPECIAL_INPUTS, FInputs, SizeOf(FInputs));
|
|
|
+ Move(MAX_64_SPECIAL_EXPECTED, FExpected, SizeOf(FExpected));
|
|
|
+end;
|
|
|
+
|
|
|
+function TFloat64MaxSpecialTest.TestTitle: shortstring;
|
|
|
+ begin
|
|
|
+ Result := 'Max (special double-precision)';
|
|
|
+ end;
|
|
|
+
|
|
|
+function TFloat64ImplicitMaxSpecialTest.DoFunc(Input1, Input2: Double): Double;
|
|
|
+ begin
|
|
|
+ if Input1 > Input2 then
|
|
|
+ Result := Input1
|
|
|
+ else
|
|
|
+ Result := Input2;
|
|
|
+ end;
|
|
|
+
|
|
|
+function TFloat64ImplicitMaxSpecialTest.TestTitle: shortstring;
|
|
|
+ begin
|
|
|
+ Result := 'Implicit Max (special double-precision)';
|
|
|
+ end;
|
|
|
+
|
|
|
+{ TFloat64SqrtTest }
|
|
|
+const
|
|
|
+ SQRT_64_INPUTS: array[0..7] of Double = (
|
|
|
+ 4.0,
|
|
|
+ 1.0,
|
|
|
+ 256.0,
|
|
|
+ 2.0,
|
|
|
+ 100.0,
|
|
|
+ 0.5,
|
|
|
+ 3.1415926535897932384626433832795, { Pi }
|
|
|
+ 1.5707963267948966192313216916398 { Pi / 2 }
|
|
|
+ );
|
|
|
+
|
|
|
+ SQRT_64_EXPECTED: array[0..7] of Double = (
|
|
|
+ 2.0,
|
|
|
+ 1.0,
|
|
|
+ 16.0,
|
|
|
+ 1.4142135623730950488016887242097,
|
|
|
+ 10.0,
|
|
|
+ 0.70710678118654752440084436210485,
|
|
|
+ 1.7724538509055160272981674833411,
|
|
|
+ 1.2533141373155002512078826424055
|
|
|
+ );
|
|
|
+
|
|
|
+constructor TFloat64SqrtTest.Create;
|
|
|
+begin
|
|
|
+ inherited Create;
|
|
|
+ Move(SQRT_64_INPUTS, FInputs, SizeOf(FInputs));
|
|
|
+ Move(SQRT_64_EXPECTED, FExpected, SizeOf(FExpected));
|
|
|
+end;
|
|
|
+
|
|
|
+function TFloat64SqrtTest.DoFunc(Input: Double): Double;
|
|
|
+ begin
|
|
|
+ Result := Sqrt(Input);
|
|
|
+ end;
|
|
|
+
|
|
|
+function TFloat64SqrtTest.TestTitle: shortstring;
|
|
|
+ begin
|
|
|
+ Result := 'sqrt(x) (double-precision)';
|
|
|
+ end;
|
|
|
+
|
|
|
+{ TFloat64SqrtSpecialTest }
|
|
|
+const
|
|
|
+ SQRT_64_SPECIAL_INPUTS: array[0..7] of Double = (
|
|
|
+ 0.0,
|
|
|
+ Infinity,
|
|
|
+ NegInfinity,
|
|
|
+ NaN,
|
|
|
+ -0.0,
|
|
|
+ -1.0,
|
|
|
+ 1E6,
|
|
|
+ NaN
|
|
|
+ );
|
|
|
+
|
|
|
+ SQRT_64_SPECIAL_EXPECTED: array[0..7] of Double = (
|
|
|
+ 0.0,
|
|
|
+ Infinity,
|
|
|
+ NaN,
|
|
|
+ NaN,
|
|
|
+ 0.0,
|
|
|
+ NaN,
|
|
|
+ 1E3,
|
|
|
+ NaN
|
|
|
+ );
|
|
|
+
|
|
|
+constructor TFloat64SqrtSpecialTest.Create;
|
|
|
+begin
|
|
|
+ inherited Create;
|
|
|
+ Move(SQRT_64_SPECIAL_INPUTS, FInputs, SizeOf(FInputs));
|
|
|
+ Move(SQRT_64_SPECIAL_EXPECTED, FExpected, SizeOf(FExpected));
|
|
|
+end;
|
|
|
+
|
|
|
+function TFloat64SqrtSpecialTest.TestTitle: shortstring;
|
|
|
+ begin
|
|
|
+ Result := 'sqrt(x) (special double-precision)';
|
|
|
+ end;
|
|
|
+
|
|
|
+{ TFloat64LnTest }
|
|
|
+
|
|
|
+const
|
|
|
+ LN_64_EXPECTED: array[0..7] of Double = (
|
|
|
+ 1.3862943611198906188344642429164,
|
|
|
+ 0.0,
|
|
|
+ 5.5451774444795624753378569716654,
|
|
|
+ 0.69314718055994530941723212145818,
|
|
|
+ 4.6051701859880913680359829093687,
|
|
|
+ -0.69314718055994530941723212145818,
|
|
|
+ 1.1447298858494001741434273513531,
|
|
|
+ 0.45158270528945486472619522989488
|
|
|
+ );
|
|
|
+
|
|
|
+constructor TFloat64LnTest.Create;
|
|
|
+begin
|
|
|
+ inherited Create;
|
|
|
+ Move(SQRT_64_INPUTS, FInputs, SizeOf(FInputs)); { Reuse the sqrt inputs }
|
|
|
+ Move(LN_64_EXPECTED, FExpected, SizeOf(FExpected));
|
|
|
+end;
|
|
|
+
|
|
|
+function TFloat64LnTest.DoFunc(Input: Double): Double;
|
|
|
+ begin
|
|
|
+ Result := Ln(Input);
|
|
|
+ end;
|
|
|
+
|
|
|
+function TFloat64LnTest.TestTitle: shortstring;
|
|
|
+ begin
|
|
|
+ Result := 'ln x (double-precision)';
|
|
|
+ end;
|
|
|
+
|
|
|
+{ TFloat64LnSpecialTest }
|
|
|
+
|
|
|
+const
|
|
|
+ LN_64_SPECIAL_EXPECTED: array[0..7] of Double = (
|
|
|
+ NegInfinity,
|
|
|
+ Infinity,
|
|
|
+ NaN,
|
|
|
+ NaN,
|
|
|
+ NegInfinity,
|
|
|
+ NaN,
|
|
|
+ 13.815510557964274104107948728106,
|
|
|
+ NaN
|
|
|
+ );
|
|
|
+
|
|
|
+constructor TFloat64LnSpecialTest.Create;
|
|
|
+begin
|
|
|
+ inherited Create;
|
|
|
+ Move(SQRT_64_SPECIAL_INPUTS, FInputs, SizeOf(FInputs)); { Reuse the sqrt inputs }
|
|
|
+ Move(LN_64_SPECIAL_EXPECTED, FExpected, SizeOf(FExpected));
|
|
|
+end;
|
|
|
+
|
|
|
+function TFloat64LnSpecialTest.TestTitle: shortstring;
|
|
|
+ begin
|
|
|
+ Result := 'ln x (special double-precision)';
|
|
|
+ end;
|
|
|
+
|
|
|
+{ TFloat64ExpTest }
|
|
|
+const
|
|
|
+ EXP_64_EXPECTED: array[0..7] of Double = (
|
|
|
+ 54.598150033144239078110261202861,
|
|
|
+ 2.7182818284590455, // remove the last 5 and append 2353602874713527 (too precise),
|
|
|
+ 1.5114276650041035425200896657073e+111,
|
|
|
+ 7.389056098930650227230427460575,
|
|
|
+ 2.68811714181613544841262555158e+43,
|
|
|
+ 1.6487212707001281468486507878142,
|
|
|
+ 23.140692632779269005729086367949,
|
|
|
+ 4.8104773809653516554730356667038
|
|
|
+ );
|
|
|
+
|
|
|
+constructor TFloat64ExpTest.Create;
|
|
|
+begin
|
|
|
+ inherited Create;
|
|
|
+ Move(SQRT_64_INPUTS, FInputs, SizeOf(FInputs)); { Reuse the sqrt inputs }
|
|
|
+ Move(EXP_64_EXPECTED, FExpected, SizeOf(FExpected));
|
|
|
+end;
|
|
|
+
|
|
|
+function TFloat64ExpTest.DoFunc(Input: Double): Double;
|
|
|
+ begin
|
|
|
+ Result := Exp(Input);
|
|
|
+ end;
|
|
|
+
|
|
|
+function TFloat64ExpTest.TestTitle: shortstring;
|
|
|
+ begin
|
|
|
+ Result := 'e^x (double-precision)';
|
|
|
+ end;
|
|
|
+
|
|
|
+{ TFloat64ExpSpecialTest }
|
|
|
+const
|
|
|
+ EXP_64_SPECIAL_EXPECTED: array[0..7] of Double = (
|
|
|
+ 1.0,
|
|
|
+ Infinity,
|
|
|
+ 0,
|
|
|
+ NaN,
|
|
|
+ 1.0,
|
|
|
+ 0.36787944117144232159552377016146,
|
|
|
+ Infinity,
|
|
|
+ NaN
|
|
|
+ );
|
|
|
+
|
|
|
+constructor TFloat64ExpSpecialTest.Create;
|
|
|
+begin
|
|
|
+ inherited Create;
|
|
|
+ Move(SQRT_64_SPECIAL_INPUTS, FInputs, SizeOf(FInputs)); { Reuse the sqrt inputs }
|
|
|
+ Move(EXP_64_SPECIAL_EXPECTED, FExpected, SizeOf(FExpected));
|
|
|
+end;
|
|
|
+
|
|
|
+function TFloat64ExpSpecialTest.TestTitle: shortstring;
|
|
|
+ begin
|
|
|
+ Result := 'e^x (special double-precision)';
|
|
|
+ end;
|
|
|
+
|
|
|
+{ TFloat64SinTest }
|
|
|
+const
|
|
|
+ SIN_64_EXPECTED: array[0..7] of Double = (
|
|
|
+ -0.75680249530792825137263909451183,
|
|
|
+ 0.8414709848078965066525023216303,
|
|
|
+ -0.99920803410706269906759056238387,
|
|
|
+ 0.90929742682568169539601986591174,
|
|
|
+ -0.50636564110975879365655761045979,
|
|
|
+ 0.47942553860420300027328793521557,
|
|
|
+ 0.0,
|
|
|
+ 1.0
|
|
|
+ );
|
|
|
+
|
|
|
+constructor TFloat64SinTest.Create;
|
|
|
+begin
|
|
|
+ inherited Create;
|
|
|
+ Move(SQRT_64_INPUTS, FInputs, SizeOf(FInputs)); { Reuse the sqrt inputs }
|
|
|
+ Move(SIN_64_EXPECTED, FExpected, SizeOf(FExpected));
|
|
|
+end;
|
|
|
+
|
|
|
+function TFloat64SinTest.DoFunc(Input: Double): Double;
|
|
|
+ begin
|
|
|
+ Result := Sin(Input);
|
|
|
+ end;
|
|
|
+
|
|
|
+function TFloat64SinTest.TestTitle: shortstring;
|
|
|
+ begin
|
|
|
+ Result := 'sin x (single-precision)';
|
|
|
+ end;
|
|
|
+
|
|
|
+{ TFloat64SinSpecialTest }
|
|
|
+const
|
|
|
+ SIN_64_SPECIAL_INPUTS: array[0..7] of Double = ( { Using different inputs as infinities are invalid }
|
|
|
+ 0.0,
|
|
|
+ -1.0,
|
|
|
+ 1E6,
|
|
|
+ NaN,
|
|
|
+ -0.0,
|
|
|
+ -1.0,
|
|
|
+ 1E6,
|
|
|
+ NaN
|
|
|
+ );
|
|
|
+
|
|
|
+ SIN_64_SPECIAL_EXPECTED: array[0..7] of Double = (
|
|
|
+ 0.0,
|
|
|
+ -0.8414709848078965066525023216303,
|
|
|
+ -0.34999350217129295211765248678077,
|
|
|
+ NaN,
|
|
|
+ -0.0,
|
|
|
+ -0.8414709848078965066525023216303,
|
|
|
+ -0.34999350217129295211765248678077,
|
|
|
+ NaN
|
|
|
+ );
|
|
|
+
|
|
|
+constructor TFloat64SinSpecialTest.Create;
|
|
|
+begin
|
|
|
+ inherited Create;
|
|
|
+ Move(SIN_64_SPECIAL_INPUTS, FInputs, SizeOf(FInputs));
|
|
|
+ Move(SIN_64_SPECIAL_EXPECTED, FExpected, SizeOf(FExpected));
|
|
|
+end;
|
|
|
+
|
|
|
+function TFloat64SinSpecialTest.TestTitle: shortstring;
|
|
|
+ begin
|
|
|
+ Result := 'sin x (double single-precision)';
|
|
|
+ end;
|
|
|
+
|
|
|
+{ TFloat64CosTest }
|
|
|
+const
|
|
|
+ COS_64_EXPECTED: array[0..7] of Double = (
|
|
|
+ -0.65364362086361191463916818309775,
|
|
|
+ 0.54030230586813971740093660744298,
|
|
|
+ -0.03979075993115770952448155799687,
|
|
|
+ -0.41614683654714238699756822950076,
|
|
|
+ 0.86231887228768393410193851395084,
|
|
|
+ 0.87758256189037271611628158260383,
|
|
|
+ -1.0, { Pi }
|
|
|
+ 0.0
|
|
|
+ );
|
|
|
+
|
|
|
+constructor TFloat64CosTest.Create;
|
|
|
+begin
|
|
|
+ inherited Create;
|
|
|
+ Move(SQRT_64_INPUTS, FInputs, SizeOf(FInputs)); { Reuse the sqrt inputs }
|
|
|
+ Move(COS_64_EXPECTED, FExpected, SizeOf(FExpected));
|
|
|
+end;
|
|
|
+
|
|
|
+function TFloat64CosTest.DoFunc(Input: Double): Double;
|
|
|
+ begin
|
|
|
+ Result := Cos(Input);
|
|
|
+ end;
|
|
|
+
|
|
|
+function TFloat64CosTest.TestTitle: shortstring;
|
|
|
+ begin
|
|
|
+ Result := 'cos x (double-precision)';
|
|
|
+ end;
|
|
|
+
|
|
|
+{ TFloat64CosSpecialTest }
|
|
|
+const
|
|
|
+ COS_64_SPECIAL_EXPECTED: array[0..7] of Double = (
|
|
|
+ 1.0,
|
|
|
+ 0.54030230586813971740093660744298,
|
|
|
+ 0.93675212753314478693853253507492,
|
|
|
+ NaN,
|
|
|
+ 1.0,
|
|
|
+ 0.54030230586813971740093660744298,
|
|
|
+ 0.93675212753314478693853253507492,
|
|
|
+ NaN
|
|
|
+ );
|
|
|
+
|
|
|
+constructor TFloat64CosSpecialTest.Create;
|
|
|
+begin
|
|
|
+ inherited Create;
|
|
|
+ Move(SIN_64_SPECIAL_INPUTS, FInputs, SizeOf(FInputs));
|
|
|
+ Move(COS_64_SPECIAL_EXPECTED, FExpected, SizeOf(FExpected));
|
|
|
+end;
|
|
|
+
|
|
|
+function TFloat64CosSpecialTest.TestTitle: shortstring;
|
|
|
+ begin
|
|
|
+ Result := 'cos x (special double-precision)';
|
|
|
+ end;
|
|
|
+
|
|
|
+{ TFloat64LdexpTest }
|
|
|
+const
|
|
|
+ LDEXP_64_INPUTS: array[0..7] of TDoubleIntPair = (
|
|
|
+ (D: 1.0; N: 0),
|
|
|
+ (D: 2.7182818284590452353602874713527; N: -1),
|
|
|
+ (D: 0.85309609426787873559547283129472; N: 6),
|
|
|
+ (D: 0.1; N: 1),
|
|
|
+ (D: 0.2; N: 2),
|
|
|
+ (D: 0.3; N: 3),
|
|
|
+ (D: 0.4; N: 4),
|
|
|
+ (D: 0.5; N: 5)
|
|
|
+ );
|
|
|
+
|
|
|
+ LDEXP_64_EXPECTED: array[0..7] of Double = (
|
|
|
+ 1.0,
|
|
|
+ 1.3591409142295226176801437356763,
|
|
|
+ 54.598150033144239078110261202862,
|
|
|
+ 0.2,
|
|
|
+ 0.8,
|
|
|
+ 2.4,
|
|
|
+ 6.4,
|
|
|
+ 16.0
|
|
|
+ );
|
|
|
+
|
|
|
+constructor TFloat64LdexpTest.Create;
|
|
|
+begin
|
|
|
+ inherited Create;
|
|
|
+ Move(LDEXP_64_INPUTS, FInputs, SizeOf(FInputs));
|
|
|
+ Move(LDEXP_64_EXPECTED, FExpected, SizeOf(FExpected));
|
|
|
+end;
|
|
|
+
|
|
|
+function TFloat64LdexpTest.DoFunc(Float: Double; N: Integer): Double;
|
|
|
+ begin
|
|
|
+ Result := LdExp(Float, N);
|
|
|
+ end;
|
|
|
+
|
|
|
+function TFloat64LdexpTest.TestTitle: shortstring;
|
|
|
+ begin
|
|
|
+ Result := 'ldexp(x, n) (double-precision)';
|
|
|
+ end;
|
|
|
+
|
|
|
+{ TFloat32SpecialLdexpTest }
|
|
|
+const
|
|
|
+ LDEXP_64_SPECIAL_INPUTS: array[0..7] of TDoubleIntPair = (
|
|
|
+ (D: Infinity; N: 0),
|
|
|
+ (D: NegInfinity; N: 0),
|
|
|
+ (D: 2.0; N: -1024),
|
|
|
+ (D: 2.0; N: 1023),
|
|
|
+ (D: NaN; N: 1),
|
|
|
+ (D: 0.0; N: 16384),
|
|
|
+ (D: 8.9884656743115795386465259539451e+307; N: -1024),
|
|
|
+ (D: 5.562684646268003457725581793331e-309; N: 1023)
|
|
|
+ );
|
|
|
+
|
|
|
+ LDEXP_64_SPECIAL_EXPECTED: array[0..7] of Double = (
|
|
|
+ Infinity,
|
|
|
+ NegInfinity,
|
|
|
+ 5.562684646268003457725581793331e-309,
|
|
|
+ Infinity,
|
|
|
+ Nan,
|
|
|
+ 0.0,
|
|
|
+ 0.5,
|
|
|
+ 0.5
|
|
|
+ );
|
|
|
+
|
|
|
+constructor TFloat64LdexpSpecialTest.Create;
|
|
|
+begin
|
|
|
+ inherited Create;
|
|
|
+ Move(LDEXP_64_SPECIAL_INPUTS, FInputs, SizeOf(FInputs));
|
|
|
+ Move(LDEXP_64_SPECIAL_EXPECTED, FExpected, SizeOf(FExpected));
|
|
|
+end;
|
|
|
+
|
|
|
+function TFloat64LdexpSpecialTest.TestTitle: shortstring;
|
|
|
+ begin
|
|
|
+ Result := 'ldexp(x, n) (special double-precision)';
|
|
|
+ end;
|
|
|
+
|
|
|
+{ Main function }
|
|
|
+const
|
|
|
+ { TCompleteByteRange and descendants }
|
|
|
+
|
|
|
+ TestClasses: array[0..39] of TTestClass = (
|
|
|
+ TFloat32MinTest,
|
|
|
+ TFloat32MaxTest,
|
|
|
+ TFloat32ImplicitMinTest,
|
|
|
+ TFloat32ImplicitMaxTest,
|
|
|
+ TFloat32MinSpecialTest,
|
|
|
+ TFloat32MaxSpecialTest,
|
|
|
+ TFloat32ImplicitMinSpecialTest,
|
|
|
+ TFloat32ImplicitMaxSpecialTest,
|
|
|
+ TFloat32SqrtTest,
|
|
|
+ TFloat32SqrtSpecialTest,
|
|
|
+ TFloat32LnTest,
|
|
|
+ TFloat32LnSpecialTest,
|
|
|
+ TFloat32ExpTest,
|
|
|
+ TFloat32ExpSpecialTest,
|
|
|
+ TFloat32SinTest,
|
|
|
+ TFloat32SinSpecialTest,
|
|
|
+ TFloat32CosTest,
|
|
|
+ TFloat32CosSpecialTest,
|
|
|
+ TFloat32LdexpTest,
|
|
|
+ TFloat32LdexpSpecialTest,
|
|
|
+ TFloat64MinTest,
|
|
|
+ TFloat64MaxTest,
|
|
|
+ TFloat64ImplicitMinTest,
|
|
|
+ TFloat64ImplicitMaxTest,
|
|
|
+ TFloat64MinSpecialTest,
|
|
|
+ TFloat64MaxSpecialTest,
|
|
|
+ TFloat64ImplicitMinSpecialTest,
|
|
|
+ TFloat64ImplicitMaxSpecialTest,
|
|
|
+ TFloat64SqrtTest,
|
|
|
+ TFloat64SqrtSpecialTest,
|
|
|
+ TFloat64LnTest,
|
|
|
+ TFloat64LnSpecialTest,
|
|
|
+ TFloat64ExpTest,
|
|
|
+ TFloat64ExpSpecialTest,
|
|
|
+ TFloat64SinTest,
|
|
|
+ TFloat64SinSpecialTest,
|
|
|
+ TFloat64CosTest,
|
|
|
+ TFloat64CosSpecialTest,
|
|
|
+ TFloat64LdexpTest,
|
|
|
+ TFloat64LdexpSpecialTest
|
|
|
+ );
|
|
|
+
|
|
|
+var
|
|
|
+ CurrentObject: TTestAncestor;
|
|
|
+ Failed: Boolean;
|
|
|
+ X: Integer;
|
|
|
+ SummedUpAverageDuration, AverageDuration : Double;
|
|
|
+begin
|
|
|
+ SetExceptionMask(GetExceptionMask + [exOverflow, exZeroDivide, exInvalidOp]);
|
|
|
+ SummedUpAverageDuration := 0.0;
|
|
|
+ Failed := False;
|
|
|
+ WriteLn('Floating-point compilation and timing test');
|
|
|
+ WriteLn('------------------------------------------');
|
|
|
+ for X := low(TestClasses) to High(TestClasses) do
|
|
|
+ begin
|
|
|
+ try
|
|
|
+ CurrentObject := TestClasses[X].Create;
|
|
|
+ try
|
|
|
+ Write(CurrentObject.TestTitle:40, ' - ');
|
|
|
+ CurrentObject.Run;
|
|
|
+
|
|
|
+ if CurrentObject.WriteResults then
|
|
|
+ begin
|
|
|
+ AverageDuration := ((CurrentObject.RunTime * 1000000000.0) / ITERATIONS);
|
|
|
+ WriteLn('Pass - average iteration duration: ', AverageDuration:1:3, ' ns');
|
|
|
+ SummedUpAverageDuration := SummedUpAverageDuration + AverageDuration;
|
|
|
+ end
|
|
|
+ else
|
|
|
+ { Final average isn't processed if a test failed, so there's no need
|
|
|
+ to calculate and add the average duration to it }
|
|
|
+ Failed := True;
|
|
|
+
|
|
|
+ finally
|
|
|
+ CurrentObject.Free;
|
|
|
+ end;
|
|
|
+ except on E: Exception do
|
|
|
+ begin
|
|
|
+ WriteLn('Exception "', E.ClassName, '" raised while running test object of class "', TestClasses[X].ClassName, '"');
|
|
|
+ Failed := True;
|
|
|
+ end;
|
|
|
+ end;
|
|
|
+ end;
|
|
|
+
|
|
|
+ if Failed then
|
|
|
+ Halt(1);
|
|
|
+
|
|
|
+ WriteLn(#10'ok');
|
|
|
+ WriteLn('- Sum of average durations: ', SummedUpAverageDuration:1:3, ' ns');
|
|
|
+ WriteLn('- Overall average duration: ', (SummedUpAverageDuration / Length(TestClasses)):1:3, ' ns');
|
|
|
+end.
|