You've already forked lazarus-ccr
fpspreadsheet: Implement fpn formula calculation of all math functions available in fps. Test cases passed.
git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@3255 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
@ -64,7 +64,33 @@ function fpsGreaterEqual(Args: TsArgumentStack; NumArgs: Integer): TsArgument;
|
||||
function fpsLess (Args: TsArgumentStack; NumArgs: Integer): TsArgument;
|
||||
function fpsLessEqual (Args: TsArgumentStack; NumArgs: Integer): TsArgument;
|
||||
function fpsNotEqual (Args: TsArgumentStack; NumArgs: Integer): TsArgument;
|
||||
|
||||
{ Math }
|
||||
function fpsABS (Args: TsArgumentStack; NumArgs: Integer): TsArgument;
|
||||
function fpsACOS (Args: TsArgumentStack; NumArgs: Integer): TsArgument;
|
||||
function fpsACOSH (Args: TsArgumentStack; NumArgs: Integer): TsArgument;
|
||||
function fpsASIN (Args: TsArgumentStack; NumArgs: Integer): TsArgument;
|
||||
function fpsASINH (Args: TsArgumentStack; NumArgs: Integer): TsArgument;
|
||||
function fpsATAN (Args: TsArgumentStack; NumArgs: Integer): TsArgument;
|
||||
function fpsATANH (Args: TsArgumentStack; NumArgs: Integer): TsArgument;
|
||||
function fpsCOS (Args: TsArgumentStack; NumArgs: Integer): TsArgument;
|
||||
function fpsCOSH (Args: TsArgumentStack; NumArgs: Integer): TsArgument;
|
||||
function fpsDEGREES (Args: TsArgumentStack; NumArgs: Integer): TsArgument;
|
||||
function fpsEXP (Args: TsArgumentStack; NumArgs: Integer): TsArgument;
|
||||
function fpsINT (Args: TsArgumentStack; NumArgs: Integer): TsArgument;
|
||||
function fpsLN (Args: TsArgumentStack; NumArgs: Integer): TsArgument;
|
||||
function fpsLOG (Args: TsArgumentStack; NumArgs: Integer): TsArgument;
|
||||
function fpsLOG10 (Args: TsArgumentStack; NumArgs: Integer): TsArgument;
|
||||
function fpsPI (Args: TsArgumentStack; NumArgs: Integer): TsArgument;
|
||||
function fpsRADIANS (Args: TsArgumentStack; NumArgs: Integer): TsArgument;
|
||||
function fpsRAND (Args: TsArgumentStack; NumArgs: Integer): TsArgument;
|
||||
function fpsROUND (Args: TsArgumentStack; NumArgs: Integer): TsArgument;
|
||||
function fpsSIGN (Args: TsArgumentStack; NumArgs: Integer): TsArgument;
|
||||
function fpsSIN (Args: TsArgumentStack; NumArgs: Integer): TsArgument;
|
||||
function fpsSINH (Args: TsArgumentStack; NumArgs: Integer): TsArgument;
|
||||
function fpsSQRT (Args: TsArgumentStack; NumArgs: Integer): TsArgument;
|
||||
function fpsTAN (Args: TsArgumentStack; NumArgs: Integer): TsArgument;
|
||||
function fpsTANH (Args: TsArgumentStack; NumArgs: Integer): TsArgument;
|
||||
{ Logic }
|
||||
function fpsAND (Args: TsArgumentStack; NumArgs: Integer): TsArgument;
|
||||
function fpsFALSE (Args: TsArgumentStack; NumArgs: Integer): TsArgument;
|
||||
function fpsIF (Args: TsArgumentStack; NumArgs: Integer): TsArgument;
|
||||
@ -527,7 +553,6 @@ begin
|
||||
Result := CreateBool(false);
|
||||
end;
|
||||
|
||||
|
||||
function fpsNotEqual(Args: TsArgumentStack; NumArgs: Integer): TsArgument;
|
||||
var
|
||||
arg1, arg2: TsArgument;
|
||||
@ -544,6 +569,265 @@ begin
|
||||
Result := CreateBool(false);
|
||||
end;
|
||||
|
||||
|
||||
{ Math functions }
|
||||
|
||||
function fpsABS(Args: TsArgumentStack; NumArgs: Integer): TsArgument;
|
||||
var
|
||||
data: TFloatArray;
|
||||
begin
|
||||
if PopFloatValues(Args, 1, data, Result) then
|
||||
Result := CreateNumber(abs(data[0]));
|
||||
end;
|
||||
|
||||
function fpsACOS(Args: TsArgumentStack; NumArgs: Integer): TsArgument;
|
||||
var
|
||||
data: TFloatArray;
|
||||
begin
|
||||
if PopFloatValues(Args, 1, data, Result) then begin
|
||||
if InRange(data[0], -1, +1) then
|
||||
Result := CreateNumber(arccos(data[0]))
|
||||
else
|
||||
Result := CreateError(errOverflow); // #NUM!
|
||||
end;
|
||||
end;
|
||||
|
||||
function fpsACOSH(Args: TsArgumentStack; NumArgs: Integer): TsArgument;
|
||||
var
|
||||
data: TFloatArray;
|
||||
begin
|
||||
if PopFloatValues(Args, 1, data, Result) then begin
|
||||
if data[0] >= 1 then
|
||||
Result := CreateNumber(arccosh(data[0]))
|
||||
else
|
||||
Result := CreateError(errOverflow); // #NUM!
|
||||
end;
|
||||
end;
|
||||
|
||||
function fpsASIN(Args: TsArgumentStack; NumArgs: Integer): TsArgument;
|
||||
var
|
||||
data: TFloatArray;
|
||||
begin
|
||||
if PopFloatValues(Args, 1, data, Result) then begin
|
||||
if InRange(data[0], -1, +1) then
|
||||
Result := CreateNumber(arcsin(data[0]))
|
||||
else
|
||||
Result := CreateError(errOverflow); // #NUM!
|
||||
end;
|
||||
end;
|
||||
|
||||
function fpsASINH(Args: TsArgumentStack; NumArgs: Integer): TsArgument;
|
||||
var
|
||||
data: TFloatArray;
|
||||
begin
|
||||
if PopFloatValues(Args, 1, data, Result) then
|
||||
Result := CreateNumber(arcsinh(data[0]));
|
||||
end;
|
||||
|
||||
function fpsATAN(Args: TsArgumentStack; NumArgs: Integer): TsArgument;
|
||||
var
|
||||
data: TFloatArray;
|
||||
begin
|
||||
if PopFloatValues(Args, 1, data, Result) then
|
||||
Result := CreateNumber(arctan(data[0]));
|
||||
end;
|
||||
|
||||
function fpsATANH(Args: TsArgumentStack; NumArgs: Integer): TsArgument;
|
||||
var
|
||||
data: TFloatArray;
|
||||
begin
|
||||
if PopFloatValues(Args, 1, data, Result) then begin
|
||||
if (data[0] > -1) and (data[0] < +1) then
|
||||
Result := CreateNumber(arctanh(data[0]))
|
||||
else
|
||||
Result := CreateError(errOverflow); // #NUM!
|
||||
end;
|
||||
end;
|
||||
|
||||
function fpsCOS(Args: TsArgumentStack; NumArgs: Integer): TsArgument;
|
||||
var
|
||||
data: TFloatArray;
|
||||
begin
|
||||
if PopFloatValues(Args, 1, data, Result) then
|
||||
Result := CreateNumber(cos(data[0]));
|
||||
end;
|
||||
|
||||
function fpsCOSH(Args: TsArgumentStack; NumArgs: Integer): TsArgument;
|
||||
var
|
||||
data: TFloatArray;
|
||||
begin
|
||||
if PopFloatValues(Args, 1, data, Result) then
|
||||
Result := CreateNumber(cosh(data[0]));
|
||||
end;
|
||||
|
||||
function fpsDEGREES(Args: TsArgumentStack; NumArgs: Integer): TsArgument;
|
||||
var
|
||||
data: TFloatArray;
|
||||
begin
|
||||
if PopFloatValues(Args, 1, data, Result) then
|
||||
Result := CreateNumber(RadToDeg(data[0]));
|
||||
end;
|
||||
|
||||
function fpsEXP(Args: TsArgumentStack; NumArgs: Integer): TsArgument;
|
||||
var
|
||||
data: TFloatArray;
|
||||
begin
|
||||
if PopFloatValues(Args, 1, data, Result) then
|
||||
Result := CreateNumber(exp(data[0]));
|
||||
end;
|
||||
|
||||
function fpsINT(Args: TsArgumentStack; NumArgs: Integer): TsArgument;
|
||||
var
|
||||
data: TFloatArray;
|
||||
begin
|
||||
if PopFloatValues(Args, 1, data, Result) then
|
||||
Result := CreateNumber(floor(data[0]));
|
||||
end;
|
||||
|
||||
function fpsLN(Args: TsArgumentStack; NumArgs: Integer): TsArgument;
|
||||
var
|
||||
data: TFloatArray;
|
||||
begin
|
||||
if PopFloatValues(Args, 1, data, Result) then begin
|
||||
if (data[0] > 0) then
|
||||
Result := CreateNumber(ln(data[0]))
|
||||
else
|
||||
Result := CreateError(errOverflow); // #NUM!
|
||||
end;
|
||||
end;
|
||||
|
||||
function fpsLOG(Args: TsArgumentStack; NumArgs: Integer): TsArgument;
|
||||
var
|
||||
arg_base, arg_number: TsArgument;
|
||||
data: TFloatArray;
|
||||
base: Double;
|
||||
begin
|
||||
base := 10;
|
||||
if NumArgs = 2 then begin
|
||||
arg_base := Args.Pop;
|
||||
if not arg_base.IsMissing then begin
|
||||
if arg_base.ArgumentType <> atNumber then begin
|
||||
Result := CreateError(errWrongType);
|
||||
exit;
|
||||
end;
|
||||
base := arg_base.NumberValue;
|
||||
end;
|
||||
end;
|
||||
|
||||
if base < 0 then begin
|
||||
Result := CreateError(errOverflow);
|
||||
exit;
|
||||
end;
|
||||
|
||||
arg_number := Args.Pop;
|
||||
if arg_number.ArgumentType <> atNumber then begin
|
||||
Result := CreateError(errWrongType);
|
||||
exit;
|
||||
end;
|
||||
|
||||
if arg_number.NumberValue > 0 then
|
||||
Result := CreateNumber(logn(base, arg_number.NumberValue))
|
||||
else
|
||||
Result := CreateError(errOverflow);
|
||||
end;
|
||||
|
||||
function fpsLOG10(Args: TsArgumentStack; NumArgs: Integer): TsArgument;
|
||||
var
|
||||
data: TFloatArray;
|
||||
begin
|
||||
if PopFloatValues(Args, 1, data, Result) then begin
|
||||
if (data[0] > 0) then
|
||||
Result := CreateNumber(log10(data[0]))
|
||||
else
|
||||
Result := CreateError(errOverflow); // #NUM!
|
||||
end;
|
||||
end;
|
||||
|
||||
function fpsPI(Args: TsArgumentStack; NumArgs: Integer): TsArgument;
|
||||
begin
|
||||
Result := CreateNumber(pi);
|
||||
end;
|
||||
|
||||
function fpsRADIANS(Args: TsArgumentStack; NumArgs: Integer): TsArgument;
|
||||
var
|
||||
data: TFloatArray;
|
||||
begin
|
||||
if PopFloatValues(Args, 1, data, Result) then
|
||||
Result := CreateNumber(degtorad(data[0]))
|
||||
end;
|
||||
|
||||
function fpsRAND(Args: TsArgumentStack; NumArgs: Integer): TsArgument;
|
||||
begin
|
||||
Result := CreateNumber(random);
|
||||
end;
|
||||
|
||||
function fpsROUND(Args: TsArgumentStack; NumArgs: Integer): TsArgument;
|
||||
var
|
||||
data: TFloatArray;
|
||||
begin
|
||||
if PopFloatValues(Args, 2, data, Result) then
|
||||
Result := CreateNumber(RoundTo(data[0], round(data[1])))
|
||||
end;
|
||||
|
||||
function fpsSIGN(Args: TsArgumentStack; NumArgs: Integer): TsArgument;
|
||||
var
|
||||
data: TFloatArray;
|
||||
begin
|
||||
if PopFloatValues(Args, 1, data, Result) then
|
||||
Result := CreateNumber(sign(data[0]))
|
||||
end;
|
||||
|
||||
function fpsSIN(Args: TsArgumentStack; NumArgs: Integer): TsArgument;
|
||||
var
|
||||
data: TFloatArray;
|
||||
begin
|
||||
if PopFloatValues(Args, 1, data, Result) then
|
||||
Result := CreateNumber(sin(data[0]))
|
||||
end;
|
||||
|
||||
function fpsSINH(Args: TsArgumentStack; NumArgs: Integer): TsArgument;
|
||||
var
|
||||
data: TFloatArray;
|
||||
begin
|
||||
if PopFloatValues(Args, 1, data, Result) then
|
||||
Result := CreateNumber(sinh(data[0]))
|
||||
end;
|
||||
|
||||
function fpsSQRT(Args: TsArgumentStack; NumArgs: Integer): TsArgument;
|
||||
var
|
||||
data: TFloatArray;
|
||||
begin
|
||||
if PopFloatValues(Args, 1, data, Result) then begin
|
||||
if data[0] >= 0.0 then
|
||||
Result := CreateNumber(sqrt(data[0]))
|
||||
else
|
||||
Result := CreateError(errOverflow);
|
||||
end;
|
||||
end;
|
||||
|
||||
function fpsTAN(Args: TsArgumentStack; NumArgs: Integer): TsArgument;
|
||||
var
|
||||
data: TFloatArray;
|
||||
begin
|
||||
if PopFloatValues(Args, 1, data, Result) then begin
|
||||
if frac(data[0] / (pi*0.5)) = 0 then
|
||||
Result := CreateError(errOverflow)
|
||||
else
|
||||
Result := CreateNumber(tan(data[0]))
|
||||
end;
|
||||
end;
|
||||
|
||||
function fpsTANH(Args: TsArgumentStack; NumArgs: Integer): TsArgument;
|
||||
var
|
||||
data: TFloatArray;
|
||||
begin
|
||||
if PopFloatValues(Args, 1, data, Result) then
|
||||
Result := CreateNumber(tanh(data[0]))
|
||||
end;
|
||||
|
||||
|
||||
{ Logical functions }
|
||||
|
||||
function fpsAND(Args: TsArgumentStack; NumArgs: Integer): TsArgument;
|
||||
var
|
||||
data: TBoolArray;
|
||||
|
@ -1123,31 +1123,31 @@ const
|
||||
(Symbol:'<>'; MinParams:2; MaxParams:2; Func:fpsNotEqual), // fekNotEqual
|
||||
(Symbol:''; MinParams:1; MaxParams:1; Func:nil), // fekParen
|
||||
{ math }
|
||||
(Symbol:'ABS'; MinParams:1; MaxParams:1; Func:nil), // fekABS
|
||||
(Symbol:'ACOS'; MinParams:1; MaxParams:1; Func:nil), // fekACOS
|
||||
(Symbol:'ACOSH'; MinParams:1; MaxParams:1; Func:nil), // fekACOSH
|
||||
(Symbol:'ASIN'; MinParams:1; MaxParams:1; Func:nil), // fekASIN
|
||||
(Symbol:'ASINH'; MinParams:1; MaxParams:1; Func:nil), // fekASINH
|
||||
(Symbol:'ATAN'; MinParams:1; MaxParams:1; Func:nil), // fekATAN
|
||||
(Symbol:'ATANH'; MinParams:1; MaxParams:1; Func:nil), // fekATANH,
|
||||
(Symbol:'COS'; MinParams:1; MaxParams:1; Func:nil), // fekCOS
|
||||
(Symbol:'COSH'; MinParams:1; MaxParams:1; Func:nil), // fekCOSH
|
||||
(Symbol:'DEGREES'; MinParams:1; MaxParams:1; Func:nil), // fekDEGREES
|
||||
(Symbol:'EXP'; MinParams:1; MaxParams:1; Func:nil), // fekEXP
|
||||
(Symbol:'INT'; MinParams:1; MaxParams:1; Func:nil), // fekINT
|
||||
(Symbol:'LN'; MinParams:1; MaxParams:1; Func:nil), // fekLN
|
||||
(Symbol:'LOG'; MinParams:1; MaxParams:2; Func:nil), // fekLOG,
|
||||
(Symbol:'LOG10'; MinParams:1; MaxParams:1; Func:nil), // fekLOG10
|
||||
(Symbol:'PI'; MinParams:0; MaxParams:0; Func:nil), // fekPI
|
||||
(Symbol:'RADIANS'; MinParams:1; MaxParams:1; Func:nil), // fekRADIANS
|
||||
(Symbol:'RAND'; MinParams:0; MaxParams:0; Func:nil), // fekRAND
|
||||
(Symbol:'ROUND'; MinParams:2; MaxParams:2; Func:nil), // fekROUND,
|
||||
(Symbol:'SIGN'; MinParams:1; MaxParams:1; Func:nil), // fekSIGN
|
||||
(Symbol:'SIN'; MinParams:1; MaxParams:1; Func:nil), // fekSIN
|
||||
(Symbol:'SINH'; MinParams:1; MaxParams:1; Func:nil), // fekSINH
|
||||
(Symbol:'SQRT'; MinParams:1; MaxParams:1; Func:nil), // fekSQRT,
|
||||
(Symbol:'TAN'; MinParams:1; MaxParams:1; Func:nil), // fekTAN
|
||||
(Symbol:'TANH'; MinParams:1; MaxParams:1; Func:nil), // fekTANH,
|
||||
(Symbol:'ABS'; MinParams:1; MaxParams:1; Func:fpsABS), // fekABS
|
||||
(Symbol:'ACOS'; MinParams:1; MaxParams:1; Func:fpsACOS), // fekACOS
|
||||
(Symbol:'ACOSH'; MinParams:1; MaxParams:1; Func:fpsACOSH), // fekACOSH
|
||||
(Symbol:'ASIN'; MinParams:1; MaxParams:1; Func:fpsASIN), // fekASIN
|
||||
(Symbol:'ASINH'; MinParams:1; MaxParams:1; Func:fpsASINH), // fekASINH
|
||||
(Symbol:'ATAN'; MinParams:1; MaxParams:1; Func:fpsATAN), // fekATAN
|
||||
(Symbol:'ATANH'; MinParams:1; MaxParams:1; Func:fpsATANH), // fekATANH,
|
||||
(Symbol:'COS'; MinParams:1; MaxParams:1; Func:fpsCOS), // fekCOS
|
||||
(Symbol:'COSH'; MinParams:1; MaxParams:1; Func:fpsCOSH), // fekCOSH
|
||||
(Symbol:'DEGREES'; MinParams:1; MaxParams:1; Func:fpsDEGREES), // fekDEGREES
|
||||
(Symbol:'EXP'; MinParams:1; MaxParams:1; Func:fpsEXP), // fekEXP
|
||||
(Symbol:'INT'; MinParams:1; MaxParams:1; Func:fpsINT), // fekINT
|
||||
(Symbol:'LN'; MinParams:1; MaxParams:1; Func:fpsLN), // fekLN
|
||||
(Symbol:'LOG'; MinParams:1; MaxParams:2; Func:fpsLOG), // fekLOG,
|
||||
(Symbol:'LOG10'; MinParams:1; MaxParams:1; Func:fpsLOG10), // fekLOG10
|
||||
(Symbol:'PI'; MinParams:0; MaxParams:0; Func:fpsPI), // fekPI
|
||||
(Symbol:'RADIANS'; MinParams:1; MaxParams:1; Func:fpsRADIANS), // fekRADIANS
|
||||
(Symbol:'RAND'; MinParams:0; MaxParams:0; Func:fpsRAND), // fekRAND
|
||||
(Symbol:'ROUND'; MinParams:2; MaxParams:2; Func:fpsROUND), // fekROUND,
|
||||
(Symbol:'SIGN'; MinParams:1; MaxParams:1; Func:fpsSIGN), // fekSIGN
|
||||
(Symbol:'SIN'; MinParams:1; MaxParams:1; Func:fpsSIN), // fekSIN
|
||||
(Symbol:'SINH'; MinParams:1; MaxParams:1; Func:fpsSINH), // fekSINH
|
||||
(Symbol:'SQRT'; MinParams:1; MaxParams:1; Func:fpsSQRT), // fekSQRT,
|
||||
(Symbol:'TAN'; MinParams:1; MaxParams:1; Func:fpsTAN), // fekTAN
|
||||
(Symbol:'TANH'; MinParams:1; MaxParams:1; Func:fpsTANH), // fekTANH,
|
||||
{ date/time }
|
||||
(Symbol:'DATE'; MinParams:3; MaxParams:3; Func:nil), // fekDATE
|
||||
(Symbol:'DATEDIF'; MinParams:3; MaxParams:3; Func:nil), // fekDATEDIF
|
||||
|
@ -142,7 +142,7 @@ var
|
||||
expected: TsArgument;
|
||||
cell: PCell;
|
||||
sollValues: array of TsArgument;
|
||||
a, b: Double;
|
||||
formula: String;
|
||||
begin
|
||||
TempFile := GetTempFileName;
|
||||
|
||||
@ -174,6 +174,7 @@ begin
|
||||
fail('Error in test code. Failed to get named worksheet');
|
||||
|
||||
for Row := 0 to MyWorksheet.GetLastRowIndex do begin
|
||||
formula := MyWorksheet.ReadAsUTF8Text(Row, 0);
|
||||
cell := MyWorksheet.FindCell(Row, 1);
|
||||
if (cell = nil) then
|
||||
fail('Error in test code: Failed to get cell ' + CellNotation(MyWorksheet, Row, 1));
|
||||
@ -186,22 +187,27 @@ begin
|
||||
end;
|
||||
expected := SollValues[row];
|
||||
CheckEquals(ord(expected.ArgumentType), ord(actual.ArgumentType),
|
||||
'Test read calculated formula data type mismatch, cell '+CellNotation(MyWorkSheet,Row,1));
|
||||
'Test read calculated formula data type mismatch, formula "' + formula +
|
||||
'", cell '+CellNotation(MyWorkSheet,Row,1));
|
||||
case actual.ArgumentType of
|
||||
atBool:
|
||||
CheckEquals(BoolToStr(expected.BoolValue), BoolToStr(actual.BoolValue),
|
||||
'Test read calculated formula result mismatch, cell '+CellNotation(MyWorkSheet,Row,1));
|
||||
'Test read calculated formula result mismatch, formula "' + formula +
|
||||
'", cell '+CellNotation(MyWorkSheet,Row,1));
|
||||
atNumber:
|
||||
CheckEquals(expected.NumberValue, actual.NumberValue,
|
||||
'Test read calculated formula result mismatch, cell '+CellNotation(MyWorkSheet,Row,1));
|
||||
'Test read calculated formula result mismatch, formula "' + formula +
|
||||
'", cell '+CellNotation(MyWorkSheet,Row,1));
|
||||
atString:
|
||||
CheckEquals(expected.StringValue, actual.StringValue,
|
||||
'Test read calculated formula result mismatch, cell '+CellNotation(MyWorkSheet,Row,1));
|
||||
'Test read calculated formula result mismatch, formula "' + formula +
|
||||
'", cell '+CellNotation(MyWorkSheet,Row,1));
|
||||
atError:
|
||||
CheckEquals(
|
||||
GetEnumName(TypeInfo(TsErrorValue), ord(expected.ErrorValue)),
|
||||
GetEnumname(TypeInfo(TsErrorValue), ord(actual.ErrorValue)),
|
||||
'Test read calculated formula error value mismatch, cell '+CellNotation(MyWorkSheet,Row,1));
|
||||
'Test read calculated formula error value mismatch, formula ' + formula +
|
||||
', cell '+CellNotation(MyWorkSheet,Row,1));
|
||||
end;
|
||||
end;
|
||||
|
||||
|
@ -47,6 +47,9 @@
|
||||
<UseExternalDbgSyms Value="True"/>
|
||||
</Debugging>
|
||||
</Linking>
|
||||
<Other>
|
||||
<CompilerPath Value="$(CompPath)"/>
|
||||
</Other>
|
||||
</CompilerOptions>
|
||||
</Item2>
|
||||
</BuildModes>
|
||||
@ -156,6 +159,9 @@
|
||||
<OptimizationLevel Value="0"/>
|
||||
</Optimizations>
|
||||
</CodeGeneration>
|
||||
<Other>
|
||||
<CompilerPath Value="$(CompPath)"/>
|
||||
</Other>
|
||||
</CompilerOptions>
|
||||
<Debugging>
|
||||
<Exceptions Count="6">
|
||||
|
@ -321,6 +321,369 @@
|
||||
SetLength(sollValues, Row+1);
|
||||
sollValues[Row] := CreateBool(1<>1);
|
||||
|
||||
|
||||
|
||||
{------------------------------------------------------------------------------}
|
||||
{ Math }
|
||||
{------------------------------------------------------------------------------}
|
||||
|
||||
// ABS
|
||||
inc(Row);
|
||||
MyWorksheet.WriteUTF8Text(Row, 0, '=abs(-1)');
|
||||
MyWorksheet.WriteRPNFormula(Row, 1, CreateRPNFormula(
|
||||
RPNNumber(-1,
|
||||
RPNFunc(fekABS, nil))));
|
||||
SetLength(sollValues, Row+1);
|
||||
sollValues[Row] := CreateNumber(abs(-1));
|
||||
|
||||
// ARCCOS - valid result
|
||||
inc(Row);
|
||||
MyWorksheet.WriteUTF8Text(Row, 0, '=acos(0.1)');
|
||||
MyWorksheet.WriteRPNFormula(Row, 1, CreateRPNFormula(
|
||||
RPNNumber(0.1,
|
||||
RPNFunc(fekACOS, nil))));
|
||||
SetLength(sollValues, Row+1);
|
||||
sollValues[Row] := CreateNumber(arccos(0.1));
|
||||
|
||||
// ACOS - error result (arccos is not defined outside the interval [-1..1]
|
||||
inc(Row);
|
||||
MyWorksheet.WriteUTF8Text(Row, 0, '=acos(-2)');
|
||||
MyWorksheet.WriteRPNFormula(Row, 1, CreateRPNFormula(
|
||||
RPNNumber(-2,
|
||||
RPNFunc(fekACOS, nil))));
|
||||
SetLength(sollValues, Row+1);
|
||||
sollValues[Row] := CreateError(errOverFlow);
|
||||
|
||||
// ARCCOSH - valid result
|
||||
inc(Row);
|
||||
MyWorksheet.WriteUTF8Text(Row, 0, '=acosh(1.1)');
|
||||
MyWorksheet.WriteRPNFormula(Row, 1, CreateRPNFormula(
|
||||
RPNNumber(1.1,
|
||||
RPNFunc(fekACOSH, nil))));
|
||||
SetLength(sollValues, Row+1);
|
||||
sollValues[Row] := CreateNumber(arccosh(1.1));
|
||||
|
||||
// ACOSH - error result (arccos is not defined below 1
|
||||
inc(Row);
|
||||
MyWorksheet.WriteUTF8Text(Row, 0, '=acosh(0.9)');
|
||||
MyWorksheet.WriteRPNFormula(Row, 1, CreateRPNFormula(
|
||||
RPNNumber(0.9,
|
||||
RPNFunc(fekACOSH, nil))));
|
||||
SetLength(sollValues, Row+1);
|
||||
sollValues[Row] := CreateError(errOverFlow);
|
||||
|
||||
// ASIN
|
||||
inc(Row);
|
||||
MyWorksheet.WriteUTF8Text(Row, 0, '=asin(0.1)');
|
||||
MyWorksheet.WriteRPNFormula(Row, 1, CreateRPNFormula(
|
||||
RPNNumber(0.1,
|
||||
RPNFunc(fekASIN, nil))));
|
||||
SetLength(sollValues, Row+1);
|
||||
sollValues[Row] := CreateNumber(arcsin(0.1));
|
||||
|
||||
// ASIN - error result (arcsin is not defined outside the interval [-1..1]
|
||||
inc(Row);
|
||||
MyWorksheet.WriteUTF8Text(Row, 0, '=asin(-2)');
|
||||
MyWorksheet.WriteRPNFormula(Row, 1, CreateRPNFormula(
|
||||
RPNNumber(-2,
|
||||
RPNFunc(fekASIN, nil))));
|
||||
SetLength(sollValues, Row+1);
|
||||
sollValues[Row] := CreateError(errOverFlow);
|
||||
|
||||
// ARCSINH
|
||||
inc(Row);
|
||||
MyWorksheet.WriteUTF8Text(Row, 0, '=asinh(1.1)');
|
||||
MyWorksheet.WriteRPNFormula(Row, 1, CreateRPNFormula(
|
||||
RPNNumber(1.1,
|
||||
RPNFunc(fekASINH, nil))));
|
||||
SetLength(sollValues, Row+1);
|
||||
sollValues[Row] := CreateNumber(arcsinh(1.1));
|
||||
|
||||
// ATAN
|
||||
inc(Row);
|
||||
MyWorksheet.WriteUTF8Text(Row, 0, '=atan(0.1)');
|
||||
MyWorksheet.WriteRPNFormula(Row, 1, CreateRPNFormula(
|
||||
RPNNumber(0.1,
|
||||
RPNFunc(fekATAN, nil))));
|
||||
SetLength(sollValues, Row+1);
|
||||
sollValues[Row] := CreateNumber(arctan(0.1));
|
||||
|
||||
// ATANH - valid result
|
||||
inc(Row);
|
||||
MyWorksheet.WriteUTF8Text(Row, 0, '=atanh(0.1)');
|
||||
MyWorksheet.WriteRPNFormula(Row, 1, CreateRPNFormula(
|
||||
RPNNumber(0.1,
|
||||
RPNFunc(fekATANH, nil))));
|
||||
SetLength(sollValues, Row+1);
|
||||
sollValues[Row] := CreateNumber(arctanh(0.1));
|
||||
|
||||
// ATANH - error result (arctan is only defined within ]-1,1[
|
||||
inc(Row);
|
||||
MyWorksheet.WriteUTF8Text(Row, 0, '=atanh(1.0)');
|
||||
MyWorksheet.WriteRPNFormula(Row, 1, CreateRPNFormula(
|
||||
RPNNumber(1.0,
|
||||
RPNFunc(fekATANH, nil))));
|
||||
SetLength(sollValues, Row+1);
|
||||
sollValues[Row] := CreateError(errOverFlow);
|
||||
|
||||
// COS
|
||||
inc(Row);
|
||||
MyWorksheet.WriteUTF8Text(Row, 0, '=cos(0.1)');
|
||||
MyWorksheet.WriteRPNFormula(Row, 1, CreateRPNFormula(
|
||||
RPNNumber(0.1,
|
||||
RPNFunc(fekCOS, nil))));
|
||||
SetLength(sollValues, Row+1);
|
||||
sollValues[Row] := CreateNumber(cos(0.1));
|
||||
|
||||
// COSH
|
||||
inc(Row);
|
||||
MyWorksheet.WriteUTF8Text(Row, 0, '=cosh(0.1)');
|
||||
MyWorksheet.WriteRPNFormula(Row, 1, CreateRPNFormula(
|
||||
RPNNumber(0.1,
|
||||
RPNFunc(fekCOSH, nil))));
|
||||
SetLength(sollValues, Row+1);
|
||||
sollValues[Row] := CreateNumber(cosh(0.1));
|
||||
|
||||
// DEGREES
|
||||
inc(Row);
|
||||
MyWorksheet.WriteUTF8Text(Row, 0, '=degrees(1.0)');
|
||||
MyWorksheet.WriteRPNFormula(Row, 1, CreateRPNFormula(
|
||||
RPNNumber(1.0,
|
||||
RPNFunc(fekDEGREES, nil))));
|
||||
SetLength(sollValues, Row+1);
|
||||
sollValues[Row] := CreateNumber(radToDeg(1.0));
|
||||
|
||||
// EXP
|
||||
inc(Row);
|
||||
MyWorksheet.WriteUTF8Text(Row, 0, '=exp(0.1)');
|
||||
MyWorksheet.WriteRPNFormula(Row, 1, CreateRPNFormula(
|
||||
RPNNumber(0.1,
|
||||
RPNFunc(fekEXP, nil))));
|
||||
SetLength(sollValues, Row+1);
|
||||
sollValues[Row] := CreateNumber(exp(0.1));
|
||||
|
||||
// INT (positive argument)
|
||||
inc(Row);
|
||||
MyWorksheet.WriteUTF8Text(Row, 0, '=int(0.1)');
|
||||
MyWorksheet.WriteRPNFormula(Row, 1, CreateRPNFormula(
|
||||
RPNNumber(0.1,
|
||||
RPNFunc(fekINT, nil))));
|
||||
SetLength(sollValues, Row+1);
|
||||
sollValues[Row] := CreateNumber(floor(0.1));
|
||||
|
||||
// INT (negative argument)
|
||||
inc(Row);
|
||||
MyWorksheet.WriteUTF8Text(Row, 0, '=int(-0.1)');
|
||||
MyWorksheet.WriteRPNFormula(Row, 1, CreateRPNFormula(
|
||||
RPNNumber(-0.1,
|
||||
RPNFunc(fekINT, nil))));
|
||||
SetLength(sollValues, Row+1);
|
||||
sollValues[Row] := CreateNumber(floor(-0.1));
|
||||
|
||||
// LN - valid result
|
||||
inc(Row);
|
||||
MyWorksheet.WriteUTF8Text(Row, 0, '=ln(0.1)');
|
||||
MyWorksheet.WriteRPNFormula(Row, 1, CreateRPNFormula(
|
||||
RPNNumber(0.1,
|
||||
RPNFunc(fekLN, nil))));
|
||||
SetLength(sollValues, Row+1);
|
||||
sollValues[Row] := CreateNumber(ln(0.1));
|
||||
|
||||
// LN - error due to argument = 0
|
||||
inc(Row);
|
||||
MyWorksheet.WriteUTF8Text(Row, 0, '=ln(0.0)');
|
||||
MyWorksheet.WriteRPNFormula(Row, 1, CreateRPNFormula(
|
||||
RPNNumber(0.0,
|
||||
RPNFunc(fekLN, nil))));
|
||||
SetLength(sollValues, Row+1);
|
||||
sollValues[Row] := CreateError(errOverflow);
|
||||
|
||||
// LN - error due to argument < 0
|
||||
inc(Row);
|
||||
MyWorksheet.WriteUTF8Text(Row, 0, '=ln(-0.1)');
|
||||
MyWorksheet.WriteRPNFormula(Row, 1, CreateRPNFormula(
|
||||
RPNNumber(-0.1,
|
||||
RPNFunc(fekLN, nil))));
|
||||
SetLength(sollValues, Row+1);
|
||||
sollValues[Row] := CreateError(errOverflow);
|
||||
|
||||
// LOG10 - valid result
|
||||
inc(Row);
|
||||
MyWorksheet.WriteUTF8Text(Row, 0, '=log10(0.1)');
|
||||
MyWorksheet.WriteRPNFormula(Row, 1, CreateRPNFormula(
|
||||
RPNNumber(0.1,
|
||||
RPNFunc(fekLOG10, nil))));
|
||||
SetLength(sollValues, Row+1);
|
||||
sollValues[Row] := CreateNumber(log10(0.1));
|
||||
|
||||
// LOG10 - error due to argument = 0
|
||||
inc(Row);
|
||||
MyWorksheet.WriteUTF8Text(Row, 0, '=log10(0.0)');
|
||||
MyWorksheet.WriteRPNFormula(Row, 1, CreateRPNFormula(
|
||||
RPNNumber(0.0,
|
||||
RPNFunc(fekLOG10, nil))));
|
||||
SetLength(sollValues, Row+1);
|
||||
sollValues[Row] := CreateError(errOverflow);
|
||||
|
||||
// LOG10 - error due to argument < 0
|
||||
inc(Row);
|
||||
MyWorksheet.WriteUTF8Text(Row, 0, '=log10(-0.1)');
|
||||
MyWorksheet.WriteRPNFormula(Row, 1, CreateRPNFormula(
|
||||
RPNNumber(-0.1,
|
||||
RPNFunc(fekLOG10, nil))));
|
||||
SetLength(sollValues, Row+1);
|
||||
sollValues[Row] := CreateError(errOverflow);
|
||||
|
||||
// LOG - valid result (2 arguments)
|
||||
inc(Row);
|
||||
MyWorksheet.WriteUTF8Text(Row, 0, '=log(0.1, 2)');
|
||||
MyWorksheet.WriteRPNFormula(Row, 1, CreateRPNFormula(
|
||||
RPNNumber(0.1,
|
||||
RPNNumber(2,
|
||||
RPNFunc(fekLOG, 2, nil)))));
|
||||
SetLength(sollValues, Row+1);
|
||||
sollValues[Row] := CreateNumber(logn(2, 0.1));
|
||||
|
||||
// LOG - valid result (2 arguments, base missing)
|
||||
inc(Row);
|
||||
MyWorksheet.WriteUTF8Text(Row, 0, '=log(0.1, )');
|
||||
MyWorksheet.WriteRPNFormula(Row, 1, CreateRPNFormula(
|
||||
RPNNumber(0.1,
|
||||
RPNMissingArg(
|
||||
RPNFunc(fekLOG, 2, nil)))));
|
||||
SetLength(sollValues, Row+1);
|
||||
sollValues[Row] := CreateNumber(logn(10, 0.1));
|
||||
|
||||
// LOG - valid result (1 argument)
|
||||
inc(Row);
|
||||
MyWorksheet.WriteUTF8Text(Row, 0, '=log(0.1)');
|
||||
MyWorksheet.WriteRPNFormula(Row, 1, CreateRPNFormula(
|
||||
RPNNumber(0.1,
|
||||
RPNFunc(fekLOG, 1, nil))));
|
||||
SetLength(sollValues, Row+1);
|
||||
sollValues[Row] := CreateNumber(logn(10, 0.1));
|
||||
|
||||
// LOG - negative base
|
||||
inc(Row);
|
||||
MyWorksheet.WriteUTF8Text(Row, 0, '=log(0.1, -2)');
|
||||
MyWorksheet.WriteRPNFormula(Row, 1, CreateRPNFormula(
|
||||
RPNNumber(0.1,
|
||||
RPNNumber(-2,
|
||||
RPNFunc(fekLOG, 2, nil)))));
|
||||
SetLength(sollValues, Row+1);
|
||||
sollValues[Row] := CreateError(errOverflow);
|
||||
|
||||
// LOG - negative value
|
||||
inc(Row);
|
||||
MyWorksheet.WriteUTF8Text(Row, 0, '=log(-0.1, 2)');
|
||||
MyWorksheet.WriteRPNFormula(Row, 1, CreateRPNFormula(
|
||||
RPNNumber(-0.1,
|
||||
RPNNumber(2.0,
|
||||
RPNFunc(fekLOG, 2, nil)))));
|
||||
SetLength(sollValues, Row+1);
|
||||
sollValues[Row] := CreateError(errOverflow);
|
||||
|
||||
// PI
|
||||
inc(Row);
|
||||
MyWorksheet.WriteUTF8Text(Row, 0, '=pi()');
|
||||
MyWorksheet.WriteRPNFormula(Row, 1, CreateRPNFormula(
|
||||
RPNFunc(fekPI, nil)));
|
||||
SetLength(sollValues, Row+1);
|
||||
sollValues[Row] := CreateNumber(pi);
|
||||
|
||||
// RADIANS
|
||||
inc(Row);
|
||||
MyWorksheet.WriteUTF8Text(Row, 0, '=radians(60)');
|
||||
MyWorksheet.WriteRPNFormula(Row, 1, CreateRPNFormula(
|
||||
RPNNumber(60,
|
||||
RPNFunc(fekRADIANS, nil))));
|
||||
SetLength(sollValues, Row+1);
|
||||
sollValues[Row] := CreateNumber(degtorad(60));
|
||||
|
||||
// RAND
|
||||
// Test omitted because we cannot enforce getting the same random number back
|
||||
// when we are reading the file.
|
||||
|
||||
// ROUND
|
||||
inc(Row);
|
||||
MyWorksheet.WriteUTF8Text(Row, 0, '=ROUND(pi(), 2)');
|
||||
MyWorksheet.WriteRPNFormula(Row, 1, CreateRPNFormula(
|
||||
RPNFunc(fekPI,
|
||||
RPNNumber(2,
|
||||
RPNFunc(fekROUND, nil)))));
|
||||
SetLength(sollValues, Row+1);
|
||||
sollValues[Row] := CreateNumber(RoundTo(pi, 2));
|
||||
|
||||
// SIGN
|
||||
inc(Row);
|
||||
MyWorksheet.WriteUTF8Text(Row, 0, '=sign(-0.1)');
|
||||
MyWorksheet.WriteRPNFormula(Row, 1, CreateRPNFormula(
|
||||
RPNNumber(-0.1,
|
||||
RPNFunc(fekSIGN, nil))));
|
||||
SetLength(sollValues, Row+1);
|
||||
sollValues[Row] := CreateNumber(sign(-0.1));
|
||||
|
||||
// SIN
|
||||
inc(Row);
|
||||
MyWorksheet.WriteUTF8Text(Row, 0, '=sin(0.1)');
|
||||
MyWorksheet.WriteRPNFormula(Row, 1, CreateRPNFormula(
|
||||
RPNNumber(0.1,
|
||||
RPNFunc(fekSIN, nil))));
|
||||
SetLength(sollValues, Row+1);
|
||||
sollValues[Row] := CreateNumber(sin(0.1));
|
||||
|
||||
// SINH
|
||||
inc(Row);
|
||||
MyWorksheet.WriteUTF8Text(Row, 0, '=sinh(0.1)');
|
||||
MyWorksheet.WriteRPNFormula(Row, 1, CreateRPNFormula(
|
||||
RPNNumber(0.1,
|
||||
RPNFunc(fekSINH, nil))));
|
||||
SetLength(sollValues, Row+1);
|
||||
sollValues[Row] := CreateNumber(sinh(0.1));
|
||||
|
||||
// SQRT - valid result
|
||||
inc(Row);
|
||||
MyWorksheet.WriteUTF8Text(Row, 0, '=sqrt(0.1)');
|
||||
MyWorksheet.WriteRPNFormula(Row, 1, CreateRPNFormula(
|
||||
RPNNumber(0.1,
|
||||
RPNFunc(fekSQRT, nil))));
|
||||
SetLength(sollValues, Row+1);
|
||||
sollValues[Row] := CreateNumber(sqrt(0.1));
|
||||
|
||||
// SQRT - error (negative argument)
|
||||
inc(Row);
|
||||
MyWorksheet.WriteUTF8Text(Row, 0, '=sqrt(-0.1)');
|
||||
MyWorksheet.WriteRPNFormula(Row, 1, CreateRPNFormula(
|
||||
RPNNumber(-0.1,
|
||||
RPNFunc(fekSQRT, nil))));
|
||||
SetLength(sollValues, Row+1);
|
||||
sollValues[Row] := CreateError(errOverflow);
|
||||
|
||||
// TAN - valid result
|
||||
inc(Row);
|
||||
MyWorksheet.WriteUTF8Text(Row, 0, '=tan(0.1)');
|
||||
MyWorksheet.WriteRPNFormula(Row, 1, CreateRPNFormula(
|
||||
RPNNumber(0.1,
|
||||
RPNFunc(fekTAN, nil))));
|
||||
SetLength(sollValues, Row+1);
|
||||
sollValues[Row] := CreateNumber(tan(0.1));
|
||||
|
||||
// TAN - error (argument = pi/2)
|
||||
// This test is omitted because it is difficult to exactly hit pi/2.
|
||||
|
||||
// TANH
|
||||
inc(Row);
|
||||
MyWorksheet.WriteUTF8Text(Row, 0, '=tanh(0.1)');
|
||||
MyWorksheet.WriteRPNFormula(Row, 1, CreateRPNFormula(
|
||||
RPNNumber(0.1,
|
||||
RPNFunc(fekTANH, nil))));
|
||||
SetLength(sollValues, Row+1);
|
||||
sollValues[Row] := CreateNumber(tanh(0.1));
|
||||
|
||||
{------------------------------------------------------------------------------}
|
||||
{ Logical functions }
|
||||
{------------------------------------------------------------------------------}
|
||||
|
||||
// AND of one values (bool)
|
||||
inc(Row);
|
||||
MyWorksheet.WriteUTF8Text(Row, 0, '=AND(true)');
|
||||
@ -490,3 +853,4 @@
|
||||
SetLength(sollValues, Row+1);
|
||||
sollValues[Row] := CreateString('A');
|
||||
|
||||
|
||||
|
Reference in New Issue
Block a user