Extended math RTL

This commit is contained in:
Michael Schimmel
2026-01-13 18:08:52 +01:00
parent 1c6a6fe5a0
commit 629dbc97ca
6 changed files with 457 additions and 90 deletions
+41 -36
View File
@@ -14,9 +14,17 @@ type
public
// --- Constants ---
[TRtlConst('false')]
[AstDoc('Boolean false.')]
class function CFalse: Boolean; static;
[TRtlConst('true')]
[AstDoc('Boolean true.')]
class function CTrue: Boolean; static;
[TRtlConst('NaN')]
[AstDoc('Not a Number (IEEE 754).')]
class function Const_NaN: Double; static;
class function CNaN: Double; static;
// --- Arithmetic Operators ---
@@ -38,17 +46,17 @@ type
class function Multiply(const Args: TArray<TDataValue>): TDataValue; static;
[TRtlExport('/', Pure)]
[AstDoc('Divides A by B. Always returns a floating point number.')]
[AstDoc('Divides A by B. Returns NaN on division by zero.')]
[AstSignature('(number, number) -> number')]
class function Divide(const Args: TArray<TDataValue>): TDataValue; static;
[TRtlExport('div', Pure)]
[AstDoc('Performs integer division.')]
[AstDoc('Performs integer division. Returns NaN on division by zero.')]
[AstSignature('(number, number) -> number')]
class function IntDivide(const Args: TArray<TDataValue>): TDataValue; static;
[TRtlExport('mod', Pure)]
[AstDoc('Returns the remainder of integer division.')]
[AstDoc('Returns the remainder of integer division. Returns NaN on division by zero.')]
[AstSignature('(number, number) -> number')]
class function Modulus(const Args: TArray<TDataValue>): TDataValue; static;
@@ -160,11 +168,6 @@ type
[TRtlExport('/', Pure)]
class function Divide_Float_Ordinal_Float(A: Double; B: Int64): Double; static;
[TRtlExport('div', Pure)]
class function Div_Ordinal_Ordinal_Ordinal(A, B: Int64): Int64; static;
[TRtlExport('mod', Pure)]
class function Mod_Ordinal_Ordinal_Ordinal(A, B: Int64): Int64; static;
[TRtlExport('=', Pure)]
class function Equal_Ordinal_Ordinal_Ordinal(A, B: Int64): Int64; static;
[TRtlExport('=', Pure)]
@@ -246,7 +249,7 @@ implementation
{ TRtlCoreFunctions - Constants }
class function TRtlCoreFunctions.Const_NaN: Double;
class function TRtlCoreFunctions.CNaN: Double;
begin
Result := System.Math.NaN;
end;
@@ -284,6 +287,7 @@ class function TRtlCoreFunctions.Divide(const Args: TArray<TDataValue>): TDataVa
begin
if Length(Args) <> 2 then
raise EArgumentException.Create('Operator / requires 2 arguments.');
Result := Args[0].AsScalar / Args[1].AsScalar;
end;
@@ -291,6 +295,7 @@ class function TRtlCoreFunctions.IntDivide(const Args: TArray<TDataValue>): TDat
begin
if Length(Args) <> 2 then
raise EArgumentException.Create('Operator div requires 2 arguments.');
Result := Args[0].AsScalar div Args[1].AsScalar;
end;
@@ -298,7 +303,8 @@ class function TRtlCoreFunctions.Modulus(const Args: TArray<TDataValue>): TDataV
begin
if Length(Args) <> 2 then
raise EArgumentException.Create('Operator mod requires 2 arguments.');
Result := Args[0].AsScalar mod Args[1].AsScalar;
Result := TScalar.FromInt64(Int64(Args[0].AsScalar) mod Args[1].AsScalar);
end;
class function TRtlCoreFunctions.Equal(const Args: TArray<TDataValue>): TDataValue;
@@ -447,42 +453,30 @@ begin
Result := A * B;
end;
// Divide
// Divide - Updated to return NaN on div0
class function TRtlCoreFunctions.Divide_Ordinal_Ordinal_Float(A, B: Int64): Double;
begin
if B = 0 then
raise EDivByZero.Create('Division by zero.');
Result := A / B;
end;
class function TRtlCoreFunctions.Divide_Float_Float_Float(A, B: Double): Double;
begin
if B = 0.0 then
raise EDivByZero.Create('Division by zero.');
Result := A / B;
Result := NaN
else
Result := A / B;
end;
class function TRtlCoreFunctions.Divide_Ordinal_Float_Float(A: Int64; B: Double): Double;
begin
if B = 0.0 then
raise EDivByZero.Create('Division by zero.');
Result := A / B;
Result := NaN
else
Result := A / B;
end;
class function TRtlCoreFunctions.Divide_Float_Ordinal_Float(A: Double; B: Int64): Double;
begin
if B = 0 then
raise EDivByZero.Create('Division by zero.');
Result := A / B;
end;
// Integer Math
class function TRtlCoreFunctions.Div_Ordinal_Ordinal_Ordinal(A, B: Int64): Int64;
begin
Result := A div B;
end;
class function TRtlCoreFunctions.Mod_Ordinal_Ordinal_Ordinal(A, B: Int64): Int64;
begin
Result := A mod B;
end;
// Comparisons
class function TRtlCoreFunctions.Equal_Ordinal_Ordinal_Ordinal(A, B: Int64): Int64;
begin
@@ -490,15 +484,15 @@ begin
end;
class function TRtlCoreFunctions.Equal_Float_Float_Ordinal(A, B: Double): Int64;
begin
Result := Ord(SameValue(A, B));
Result := Ord(A = B);
end;
class function TRtlCoreFunctions.Equal_Ordinal_Float_Ordinal(A: Int64; B: Double): Int64;
begin
Result := Ord(SameValue(A, B));
Result := Ord(A = B);
end;
class function TRtlCoreFunctions.Equal_Float_Ordinal_Ordinal(A: Double; B: Int64): Int64;
begin
Result := Ord(SameValue(A, B));
Result := Ord(A = B);
end;
class function TRtlCoreFunctions.Equal_Keyword_Keyword_Ordinal(A, B: Int64): Int64;
begin
@@ -511,15 +505,15 @@ begin
end;
class function TRtlCoreFunctions.NotEqual_Float_Float_Ordinal(A, B: Double): Int64;
begin
Result := Ord(not SameValue(A, B));
Result := Ord(A <> B);
end;
class function TRtlCoreFunctions.NotEqual_Ordinal_Float_Ordinal(A: Int64; B: Double): Int64;
begin
Result := Ord(not SameValue(A, B));
Result := Ord(A <> B);
end;
class function TRtlCoreFunctions.NotEqual_Float_Ordinal_Ordinal(A: Double; B: Int64): Int64;
begin
Result := Ord(not SameValue(A, B));
Result := Ord(A <> B);
end;
class function TRtlCoreFunctions.NotEqual_Keyword_Keyword_Ordinal(A, B: Int64): Int64;
begin
@@ -599,6 +593,17 @@ class function TRtlCoreFunctions.And_Ordinal_Ordinal_Ordinal(A, B: Int64): Int64
begin
Result := A and B;
end;
class function TRtlCoreFunctions.CFalse: Boolean;
begin
Result := false;
end;
class function TRtlCoreFunctions.CTrue: Boolean;
begin
Result := true;
end;
class function TRtlCoreFunctions.Or_Ordinal_Ordinal_Ordinal(A, B: Int64): Int64;
begin
Result := A or B;