Scalar operators

This commit is contained in:
Michael Schimmel
2025-09-15 16:10:01 +02:00
parent 3ad004a895
commit 101dbec760
2 changed files with 794 additions and 0 deletions
+76
View File
@@ -20,6 +20,13 @@ type
class operator Equal(const A, B: TDecimal): Boolean; inline;
class operator NotEqual(const A, B: TDecimal): Boolean; inline;
class operator GreaterThan(const A, B: TDecimal): Boolean; inline;
class operator GreaterThanOrEqual(const A, B: TDecimal): Boolean; inline;
class operator LessThan(const A, B: TDecimal): Boolean; inline;
class operator LessThanOrEqual(const A, B: TDecimal): Boolean; inline;
class operator Negative(const A: TDecimal): TDecimal; inline;
class operator Round(const A: TDecimal): TDecimal;
class operator Trunc(const A: TDecimal): TDecimal;
class operator Implicit(const A: Int64): TDecimal; inline;
class operator Explicit(const A: TDecimal): Double;
@@ -246,6 +253,75 @@ begin
Result := not (A = B);
end;
class operator TDecimal.GreaterThan(const A, B: TDecimal): Boolean;
begin
var aScale := A.GetScale;
var bScale := B.GetScale;
// Fast path for identical scales
if aScale = bScale then
begin
Result := (A.GetValue > B.GetValue);
exit;
end;
// Slower path: align scales before comparing values
if aScale > bScale then
begin
var scaledB := TDecimal.Create(B, aScale);
Result := (A.GetValue > scaledB.GetValue);
end
else // bScale > aScale
begin
var scaledA := TDecimal.Create(A, bScale);
Result := (scaledA.GetValue > B.GetValue);
end;
end;
class operator TDecimal.GreaterThanOrEqual(const A, B: TDecimal): Boolean;
begin
// Reuse existing operators for consistency
Result := not (A < B);
end;
class operator TDecimal.LessThan(const A, B: TDecimal): Boolean;
begin
// Reuse existing operators for consistency
Result := (B > A);
end;
class operator TDecimal.LessThanOrEqual(const A, B: TDecimal): Boolean;
begin
// Reuse existing operators for consistency
Result := not (A > B);
end;
class operator TDecimal.Negative(const A: TDecimal): TDecimal;
begin
// Negate the value, keep the scale
Result := TDecimal.Create(-A.GetValue, A.GetScale);
end;
class operator TDecimal.Round(const A: TDecimal): TDecimal;
var
value: Int64;
divisor: Int64;
begin
// Rounds to the nearest whole number (scale 0) using arithmetic rounding.
value := A.GetValue;
divisor := PowersOf10[A.GetScale];
if value >= 0 then
Result := TDecimal.Create((value + divisor div 2) div divisor, 0)
else
Result := TDecimal.Create((value - divisor div 2) div divisor, 0);
end;
class operator TDecimal.Trunc(const A: TDecimal): TDecimal;
begin
// Truncates the fractional part, resulting in a decimal with scale 0
Result := TDecimal.Create(A.GetValue div PowersOf10[A.GetScale], 0);
end;
class operator TDecimal.Implicit(const A: Int64): TDecimal;
begin
// Correctly create a TDecimal with scale 0