Commit 88ad1296 authored by T.J. Corona's avatar T.J. Corona Committed by Kitware Robot

Merge topic 'unary-plus'

1f890b9b Added unary plus and fixed scientific notation bug in vtkFunctionParser
Acked-by: Kitware Robot's avatarKitware Robot <kwrobot@kitware.com>
Acked-by: Ben Boeckel's avatarBen Boeckel <ben.boeckel@kitware.com>
Reviewed-by: Utkarsh Ayachit's avatarUtkarsh Ayachit <utkarsh.ayachit@kitware.com>
Merge-request: !503
parents 24ba3f80 1f890b9b
......@@ -97,6 +97,8 @@ SCALAR_FUNC(TestSqrt,sqrt,std::sqrt);
SCALAR_FUNC(TestTan,tan,std::tan);
SCALAR_FUNC(TestTanh,tanh,std::tanh);
static int TestScalars();
static int TestUnaryOperations();
static int TestScientificNotation();
static int TestVectors();
static int TestMinMax();
static int TestScalarLogic();
......@@ -127,6 +129,8 @@ int UnitTestFunctionParser(int,char *[])
status += TestTanh(-1.0, 1.0);
status += TestScalars();
status += TestUnaryOperations();
status += TestScientificNotation();
status += TestVectors();
status += TestMinMax();
status += TestScalarLogic();
......@@ -148,6 +152,56 @@ int UnitTestFunctionParser(int,char *[])
return EXIT_SUCCESS;
}
int TestUnaryOperations()
{
std::cout << "Testing Scalar Unary" << "...";
std::string formula[4] = {
"-x * +y",
"+x + +y",
"+x - -y",
"-x - +y"};
double expected[4] = {-2.,3.,3.,-3.};
vtkSmartPointer<vtkFunctionParser> parser =
vtkSmartPointer<vtkFunctionParser>::New();
parser->SetScalarVariableValue("x", 1.0);
parser->SetScalarVariableValue("y", 2.0);
for (unsigned i=0;i<4;i++)
{
parser->SetFunction(&formula[i][0]);
double result = parser->GetScalarResult();
if (!vtkMathUtilities::FuzzyCompare(
result, expected[i],
std::numeric_limits<double>::epsilon() * 1.0))
{
std::cout << "FAILED\n";
return 1;
}
}
parser->SetScalarVariableValue("x", 3);
parser->SetScalarVariableValue("y", 2);
parser->SetFunction("-x ^ +y");
int result = parser->GetScalarResult();
std::cout<<"result: "<<result<<std::endl;
if (result != 9)
{
std::cout << "FAILED\n";
return 1;
}
parser->SetFunction("(-x)");
result = parser->GetScalarResult();
if (result != -3)
{
std::cout << "FAILED\n";
return 1;
}
std::cout << "PASSED\n";
return 0;
}
int TestScalars()
{
std::cout << "Testing Scalar Add / Subtract / Multiply / Divide" << "...";
......@@ -155,7 +209,7 @@ int TestScalars()
vtkSmartPointer<vtkFunctionParser>::New();
parser->SetScalarVariableValue("x", 1.0);
parser->SetScalarVariableValue("y", 2.0);
parser->SetFunction( "(x-y)/(x-y) * -(x-y)/(x-y) + (x - x)");
parser->SetFunction( "+(x-y)/(x-y) * -(x-y)/(x-y) + (x - x)");
double result = parser->GetScalarResult();
if (result != -1.0)
{
......@@ -169,6 +223,32 @@ int TestScalars()
}
}
int TestScientificNotation()
{
std::cout << "Testing Scientific notation" << "...";
vtkSmartPointer<vtkFunctionParser> parser =
vtkSmartPointer<vtkFunctionParser>::New();
parser->SetFunction( "3.0e+01");
double expected = 3.0e+01;
double result = parser->GetScalarResult();
if (!vtkMathUtilities::FuzzyCompare(
result, expected,
std::numeric_limits<double>::epsilon() * 1.0))
{
std::cout << " Scientific notation expected " << expected
<< " but got " << result;
std::cout << "eps ratio is: " << (result - expected)
/ std::numeric_limits<double>::epsilon() << std::endl;
std::cout << "FAILED\n";
return 1;
}
else
{
std::cout << "PASSED\n";
return 0;
}
}
int TestVectors()
{
std::cout << "Testing Cross" << "...";
......
......@@ -171,6 +171,7 @@ int vtkFunctionParser::Parse()
// - scalar/vector +
// - scalar/vector -
// - scalar/vector unary minus
// - scalar/vector unary plus
// - * (2 scalars) or scalar multiple (scalar, vector)
result = this->DisambiguateOperators();
if (!result)
......@@ -229,6 +230,12 @@ int vtkFunctionParser::DisambiguateOperators()
this->ByteCode[i] = VTK_PARSER_VECTOR_UNARY_MINUS;
}
break;
case VTK_PARSER_UNARY_PLUS:
if (tempStack[tempStackPtr] != 0)
{
this->ByteCode[i] = VTK_PARSER_VECTOR_UNARY_PLUS;
}
break;
case VTK_PARSER_ADD:
if (tempStack[tempStackPtr] != 0 && tempStack[tempStackPtr-1] != 0)
{
......@@ -487,6 +494,8 @@ bool vtkFunctionParser::Evaluate()
case VTK_PARSER_UNARY_MINUS:
this->Stack[stackPosition] = -(this->Stack[stackPosition]);
break;
case VTK_PARSER_UNARY_PLUS:
break;
case VTK_PARSER_ADD:
this->Stack[stackPosition-1] += this->Stack[stackPosition];
stackPosition--;
......@@ -724,6 +733,8 @@ bool vtkFunctionParser::Evaluate()
this->Stack[stackPosition-1] = -this->Stack[stackPosition-1];
this->Stack[stackPosition-2] = -this->Stack[stackPosition-2];
break;
case VTK_PARSER_VECTOR_UNARY_PLUS:
break;
case VTK_PARSER_DOT_PRODUCT:
this->Stack[stackPosition-3] *= this->Stack[stackPosition];
this->Stack[stackPosition-4] *= this->Stack[stackPosition-1];
......@@ -1427,11 +1438,21 @@ void vtkFunctionParser::BuildInternalSubstringStructure(int beginIndex,
this->AddInternalByte(VTK_PARSER_UNARY_MINUS);
return;
}
if (this->GetMathConstantNumber(beginIndex+1) > 0 &&
this->FindEndOfMathConstant(beginIndex+1) == endIndex)
}
if (this->Function[beginIndex] == '+')
{
if (this->IsSubstringCompletelyEnclosed(beginIndex+1, endIndex))
{
this->BuildInternalSubstringStructure(beginIndex+2, endIndex-1);
this->AddInternalByte(VTK_PARSER_UNARY_PLUS);
return;
}
if (this->GetMathFunctionNumber(beginIndex+1) > 0 &&
this->FindEndOfMathFunction(beginIndex+1) == endIndex)
{
this->BuildInternalSubstringStructure(beginIndex+1, endIndex);
this->AddInternalByte(VTK_PARSER_UNARY_MINUS);
this->AddInternalByte(VTK_PARSER_UNARY_PLUS);
return;
}
}
......@@ -1539,7 +1560,7 @@ void vtkFunctionParser::BuildInternalSubstringStructure(int beginIndex,
if (parenthesisCount == 0 &&
// arithmetic or boolean
this->Function[i] == elementaryMathOps[opNum] &&
!(this->Function[i] == '-' &&
!((this->Function[i] == '-' || this->Function[i] == '+') &&
(this->IsElementaryOperator(this->Function[i-1]) ||
this->Function[i-1] == '(' ||
(this->Function[i-1] == 'e' && i > 1 &&
......@@ -1560,8 +1581,12 @@ void vtkFunctionParser::BuildInternalSubstringStructure(int beginIndex,
} // end of for (opNum = 0; opNum < numMathOps; opNum++)
beginIndex2 = beginIndex;
if (this->Function[beginIndex] == '-')
bool unaryMinus = false;
if (this->Function[beginIndex] == '-' ||
this->Function[beginIndex] == '+')
{
if (this->Function[beginIndex] == '-')
unaryMinus = true;
beginIndex2++;
}
......@@ -1574,7 +1599,10 @@ void vtkFunctionParser::BuildInternalSubstringStructure(int beginIndex,
}
if (beginIndex2 > beginIndex)
{
this->AddInternalByte(VTK_PARSER_UNARY_MINUS);
if (unaryMinus)
this->AddInternalByte(VTK_PARSER_UNARY_MINUS);
else
this->AddInternalByte(VTK_PARSER_UNARY_PLUS);
}
}
......@@ -2172,6 +2200,21 @@ void vtkFunctionParser::CheckExpression(int &pos, char **error)
}
}
// Check for leading +
if (currentChar == '+')
{
currentChar = this->Function[++index];
if(index == this->FunctionLength)
{
this->ParseErrorPositon = this->FindPositionInOriginalFunction(index);
this->SetParseError("Syntax error: unary plus with no operand");
this->CopyParseError(pos, error);
delete [] expectCommaOnParenthesisCount;
delete [] expectTwoCommasOnParenthesisCount;
return;
}
}
// Check for math function
if ((functionNumber = this->GetMathFunctionNumberByCheckingParenthesis(index)))
{
......
......@@ -46,76 +46,78 @@
#define VTK_PARSER_IMMEDIATE 1
#define VTK_PARSER_UNARY_MINUS 2
#define VTK_PARSER_UNARY_PLUS 3
// supported math functions
#define VTK_PARSER_ADD 3
#define VTK_PARSER_SUBTRACT 4
#define VTK_PARSER_MULTIPLY 5
#define VTK_PARSER_DIVIDE 6
#define VTK_PARSER_POWER 7
#define VTK_PARSER_ABSOLUTE_VALUE 8
#define VTK_PARSER_EXPONENT 9
#define VTK_PARSER_CEILING 10
#define VTK_PARSER_FLOOR 11
#define VTK_PARSER_LOGARITHM 12
#define VTK_PARSER_LOGARITHME 13
#define VTK_PARSER_LOGARITHM10 14
#define VTK_PARSER_SQUARE_ROOT 15
#define VTK_PARSER_SINE 16
#define VTK_PARSER_COSINE 17
#define VTK_PARSER_TANGENT 18
#define VTK_PARSER_ARCSINE 19
#define VTK_PARSER_ARCCOSINE 20
#define VTK_PARSER_ARCTANGENT 21
#define VTK_PARSER_HYPERBOLIC_SINE 22
#define VTK_PARSER_HYPERBOLIC_COSINE 23
#define VTK_PARSER_HYPERBOLIC_TANGENT 24
#define VTK_PARSER_MIN 25
#define VTK_PARSER_MAX 26
#define VTK_PARSER_SIGN 28
#define VTK_PARSER_ADD 4
#define VTK_PARSER_SUBTRACT 5
#define VTK_PARSER_MULTIPLY 6
#define VTK_PARSER_DIVIDE 7
#define VTK_PARSER_POWER 8
#define VTK_PARSER_ABSOLUTE_VALUE 9
#define VTK_PARSER_EXPONENT 10
#define VTK_PARSER_CEILING 11
#define VTK_PARSER_FLOOR 12
#define VTK_PARSER_LOGARITHM 13
#define VTK_PARSER_LOGARITHME 14
#define VTK_PARSER_LOGARITHM10 15
#define VTK_PARSER_SQUARE_ROOT 16
#define VTK_PARSER_SINE 17
#define VTK_PARSER_COSINE 18
#define VTK_PARSER_TANGENT 19
#define VTK_PARSER_ARCSINE 20
#define VTK_PARSER_ARCCOSINE 21
#define VTK_PARSER_ARCTANGENT 22
#define VTK_PARSER_HYPERBOLIC_SINE 23
#define VTK_PARSER_HYPERBOLIC_COSINE 24
#define VTK_PARSER_HYPERBOLIC_TANGENT 25
#define VTK_PARSER_MIN 26
#define VTK_PARSER_MAX 27
#define VTK_PARSER_SIGN 29
// functions involving vectors
#define VTK_PARSER_CROSS 27
#define VTK_PARSER_VECTOR_UNARY_MINUS 29
#define VTK_PARSER_DOT_PRODUCT 30
#define VTK_PARSER_VECTOR_ADD 31
#define VTK_PARSER_VECTOR_SUBTRACT 32
#define VTK_PARSER_SCALAR_TIMES_VECTOR 33
#define VTK_PARSER_VECTOR_TIMES_SCALAR 34
#define VTK_PARSER_VECTOR_OVER_SCALAR 35
#define VTK_PARSER_MAGNITUDE 36
#define VTK_PARSER_NORMALIZE 37
#define VTK_PARSER_CROSS 28
#define VTK_PARSER_VECTOR_UNARY_MINUS 30
#define VTK_PARSER_VECTOR_UNARY_PLUS 31
#define VTK_PARSER_DOT_PRODUCT 32
#define VTK_PARSER_VECTOR_ADD 33
#define VTK_PARSER_VECTOR_SUBTRACT 34
#define VTK_PARSER_SCALAR_TIMES_VECTOR 35
#define VTK_PARSER_VECTOR_TIMES_SCALAR 36
#define VTK_PARSER_VECTOR_OVER_SCALAR 37
#define VTK_PARSER_MAGNITUDE 38
#define VTK_PARSER_NORMALIZE 39
// constants involving vectors
#define VTK_PARSER_IHAT 38
#define VTK_PARSER_JHAT 39
#define VTK_PARSER_KHAT 40
#define VTK_PARSER_IHAT 40
#define VTK_PARSER_JHAT 41
#define VTK_PARSER_KHAT 42
// code for if(bool, trueval, falseval) resulting in a scalar
#define VTK_PARSER_IF 41
#define VTK_PARSER_IF 43
// code for if(bool, truevec, falsevec) resulting in a vector
#define VTK_PARSER_VECTOR_IF 42
#define VTK_PARSER_VECTOR_IF 44
// codes for boolean expressions
#define VTK_PARSER_LESS_THAN 43
#define VTK_PARSER_LESS_THAN 45
// codes for boolean expressions
#define VTK_PARSER_GREATER_THAN 44
#define VTK_PARSER_GREATER_THAN 46
// codes for boolean expressions
#define VTK_PARSER_EQUAL_TO 45
#define VTK_PARSER_EQUAL_TO 47
// codes for boolean expressions
#define VTK_PARSER_AND 46
#define VTK_PARSER_AND 48
// codes for boolean expressions
#define VTK_PARSER_OR 47
#define VTK_PARSER_OR 49
// codes for scalar variables come before those for vectors. Do not define
// values for VTK_PARSER_BEGIN_VARIABLES+1, VTK_PARSER_BEGIN_VARIABLES+2, ...,
// because they are used to look up variables numbered 1, 2, ...
#define VTK_PARSER_BEGIN_VARIABLES 48
#define VTK_PARSER_BEGIN_VARIABLES 50
// the value that is retuned as a result if there is an error
#define VTK_PARSER_ERROR_RESULT VTK_FLOAT_MAX
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment