package jmathlib.core.tokens;
import jmathlib.core.interpreter.*;
import jmathlib.core.tokens.numbertokens.DoubleNumberToken;
/**Used to implement relation operations within an expression*/
public class RelationOperatorToken extends BinaryOperatorToken
{
/**Constructor taking the operator and priority
* @param _operator = the operator being created
*/
public RelationOperatorToken (char _operator)
{
super(_operator, RELATION_PRIORITY);
}
/**
*
* @return priority of current relation (e.g. < > | & && ...)
*/
public int getPriority()
{
switch (value)
{
case '<':
case '>':
case 'l':
case 'g':
return RELATION_PRIORITY;
case 'e':
case 'n':
return RELATION_PRIORITY;
case '&':
return AND_PRIORITY;
case '|':
return OR_PRIORITY;
case 'a':
return ANDAND_PRIORITY;
case 'o':
return OROR_PRIORITY;
}
Errors.throwMathLibException("RelationToken unknown priority");
return 0;
}
/**evaluates the operator
* @param operands = the operators operands
* @return the result as an OperandToken
*/
public OperandToken evaluate(Token[] operands, GlobalValues globals)
{
ErrorLogger.debugLine("RelationToken: evaluate");
// it is much easier to compare number, so convert to number
if (operands[0] instanceof LogicalToken)
operands[0]=((LogicalToken)operands[0]).getDoubleNumberToken();
// it is much easier to compare number, so convert to number
if (operands[1] instanceof LogicalToken)
operands[1]=((LogicalToken)operands[1]).getDoubleNumberToken();
if ( (operands[0] instanceof DoubleNumberToken)
&& (operands[1] instanceof DoubleNumberToken) )
{
// two operands and both a numbers
// e.g. 2>3, 3>=6, 4!=3, [2,3,4]>3
DoubleNumberToken num0 = (DoubleNumberToken)operands[0];
DoubleNumberToken num1 = (DoubleNumberToken)operands[1];
int[] size0 = num0.getSize();
int[] size1 = num1.getSize();
int n0 = num0.getNumberOfElements();
int n1 = num1.getNumberOfElements();
if ( num0.isScalar() && num1.isScalar() )
{
// <scalar> <operator> <scalar>
// e.g. 2!=3, 5>6
boolean returnValue = evalRelation(value,
num0.getValueRe(0),
num1.getValueRe(0));
return new LogicalToken( returnValue );
}
else if ( num1.isScalar() )
{
// <array> <operator> <scalar>
// e.g. [2,3,4,5] > 3
boolean[] returnValues = new boolean[n0];
// Check relation for each element
for (int i=0; i<n0; i++)
{
returnValues[i] = evalRelation(value,
num0.getValueRe(i),
num1.getValueRe(0));
}
return new LogicalToken(size0, returnValues);
}
else if ( num0.isScalar() )
{
// <scalar> <operator> <array>
// e.g. 3 > [2,3,4]
boolean[] returnValues = new boolean[n1];
// Check relation for each element
for (int i=0; i<n1; i++)
{
returnValues[i] = evalRelation(value,
num0.getValueRe(0),
num1.getValueRe(i));
}
return new LogicalToken(size1, returnValues);
}
else if ( DataToken.checkEqualDimensions(size0, size1) )
{
// <array> <operator> <array>
// e.g. [3,3,3] > [2,3,4]
boolean[] returnValues = new boolean[n0];
// Check relation for each element
for (int i=0; i<n0; i++)
{
returnValues[i] = evalRelation(value,
num0.getValueRe(i),
num1.getValueRe(i));
}
return new LogicalToken(size0, returnValues);
}
else
{
// dimensions do not fit
// e.g. [2,3]>[2,3,4]
Errors.throwMathLibException("RelationToken: dimensions don't fit");
return null;
}
}
else if ( (operands[0] instanceof CharToken)
&& (operands[1] instanceof CharToken) )
{
// two operands and both are strings
// e.g. 2>3, 3>=6, 4!=3
CharToken char0 = (CharToken)operands[0];
CharToken char1 = (CharToken)operands[1];
int[] size0 = char0.getSize();
int[] size1 = char1.getSize();
int n0 = char0.getNumberOfElements();
int n1 = char1.getNumberOfElements();
// !!! changed from x,y to n-d-array
String op0Values = ((CharToken)operands[0]).getValue();
int op0SizeX = op0Values.length();
String op1Values = ((CharToken)operands[1]).getValue();
int op1SizeX = op1Values.length();
if (op1SizeX == 1)
{
// <array> <operator> <scalar>
// e.g. 'asdf' != 'd'
boolean[][] returnValues = new boolean[1][op0SizeX];
// Check relation for each element
for (int xx=0; xx<op0SizeX; xx++)
{
returnValues[0][xx] = evalRelation(value,
op0Values.charAt(xx),
op1Values.charAt(0));
}
return new LogicalToken( returnValues );
}
else if (op0SizeX == 1)
{
// <array> <operator> <scalar>
// e.g. 'asdf' != 'd'
boolean[][] returnValues = new boolean[1][op1SizeX];
// Check relation for each element
for (int xx=0; xx<op1SizeX; xx++)
{
returnValues[0][xx] = evalRelation(value,
op0Values.charAt(0),
op1Values.charAt(xx));
}
return new LogicalToken( returnValues );
}
else if ( op0SizeX == op1SizeX )
{
// <array> <operator> <scalar>
// e.g. 'asdf' != 'asdd'
boolean[][] returnValues = new boolean[1][op0SizeX];
// Check relation for each element
for (int xx=0; xx<op0SizeX; xx++)
{
returnValues[0][xx] = evalRelation(value,
op0Values.charAt(xx),
op1Values.charAt(xx));
}
return new LogicalToken( returnValues );
}
else
{
// dimensions do not fit
// e.g. [2,3]>[2,3,4]
Errors.throwMathLibException("RelationToken: dimensions don't fit");
}
}
Errors.throwMathLibException("RelationToken: Token not supported");
return null;
}
/** evaluate relations (<, >, <=, >=, == ~=)
* @param value = the tpye of operator
* @param arg0 = the left hand operand
* @param arg1 = the right hand operand
* @return the result as a double
*/
private boolean evalRelation(char value, double arg0, double arg1)
{
switch (value)
{
case '<':
if (arg0 < arg1) return true;
break;
case '>':
if (arg0 > arg1) return true;
break;
case 'l':
if (arg0 <= arg1) return true;
break;
case 'g':
if (arg0 >= arg1) return true;
break;
case 'e':
if (arg0 == arg1) return true;
break;
case 'n':
if (arg0 != arg1) return true;
break;
case '|':
if ((arg0!=0.0) || (arg1!=0.0)) return true;
break;
case 'o':
if ((arg0!=0.0) || (arg1!=0.0)) return true;
break;
case '&':
if ((arg0!=0.0) && (arg1!=0.0)) return true;
break;
case 'a':
if ((arg0!=0.0) && (arg1!=0.0)) return true;
break;
}
// relation not true --> return false
return false;
}
/**
*
* @param value
* @param arg0
* @param arg1
* @return
*/
private boolean evalRelation(char value, char arg0, char arg1)
{
switch (value)
{
case '<':
case '>':
case 'l':
case 'g':
case '|':
case 'o':
case '&':
case 'a':
Errors.throwMathLibException("relation not implemented");
break;
case 'e':
if (arg0 == arg1) return true;
break;
case 'n':
if (arg0 != arg1) return true;
break;
}
// relation not true --> return false
return false;
}
/**
*
* @return
*/
public String toString()
{
String valueString = String.valueOf(value);
switch (value)
{
case 'l':
valueString = "<=";
break;
case 'g':
valueString = ">=";
break;
case 'e':
valueString = "==";
break;
case 'n':
valueString = "~=";
break;
case 'a':
valueString = "&&";
break;
case 'o':
valueString = "||";
break;
}
return valueString;
}
} // end RelationOperatorToken