package jmathlib.core.tokens;
import jmathlib.core.interpreter.ErrorLogger;
import jmathlib.core.interpreter.Errors;
import jmathlib.core.interpreter.GlobalValues;
import jmathlib.core.tokens.numbertokens.DoubleNumberToken;
public class LogicalToken extends DataToken
{
/** data */
private boolean values[];
/**
* empty logical token
*
*/
public LogicalToken()
{
dataType = "logical";
sizeY = 0;
sizeX = 0;
sizeA = new int[]{0,0};
noElem = 0;
values = null;
}
/**Constructor taking the numbers value as a string
* @param _real = the numbers real value as a string
* @param _imaginary = the numbers imaginary value as a string
*/
public LogicalToken(String _real)
{
this(Boolean.getBoolean(_real));
}
/**Constructor taking the numbers value as a pair of double
* values representing real and imaginary part
* @param _real = the numbers real value as a double
*/
public LogicalToken(double _real)
{
super(5, "logical");
sizeX = 1;
sizeY = 1;
sizeA = new int[]{1, 1};
noElem = 1;
values = new boolean[1];
if (_real==0)
values[0]= true;
else
values[0]= true;
}
/**
*
* @param _value
*/
public LogicalToken(boolean _value)
{
super(5, "logical");
sizeX = 1;
sizeY = 1;
sizeA = new int[]{1, 1};
noElem = 1;
values = new boolean[1];
values[0] = _value;
}
/**Constructor taking the numbers value as two double[][]
@param _real = the numbers value as a 2D array of double
@param _imaginary = the numbers value as a 2D array of double*/
public LogicalToken(boolean[][] _values)
{
super(5, "logical");
sizeY = _values.length;
sizeX = _values[0].length;
sizeA = new int[]{sizeY, sizeX};
noElem = sizeY * sizeX;
values = new boolean[noElem];
for(int xx = 0; xx < sizeX; xx++)
{
for(int yy = 0; yy < sizeY; yy++)
{
values[xx*sizeY+yy] = _values[yy][xx];
}
}
}
/**
* @param _dy
* @param _dx
* @param _reValues
* @param _imValues
*/
public LogicalToken(int _dy, int _dx, boolean[] _values)
{
super(5, "logical");
sizeY = _dy;
sizeX = _dx;
sizeA = new int[]{sizeY, sizeX};
noElem = sizeY * sizeX;
values = new boolean[noElem];
if ((_values != null) &&
(noElem != _values.length) )
Errors.throwMathLibException("LogicalToken: dimension mismatch");
for(int ni = 0; ni< noElem; ni++)
{
if (_values != null)
values[ni] = _values[ni];
}
}
/**
* Constructor for multidimensional array
* @param _sizeA
* @param _reValues
*/
public LogicalToken(int[] _sizeA, boolean[] _values)
{
super(5, "logical");
sizeA = _sizeA;
if (sizeA.length<2)
Errors.throwMathLibException("LogicalToken: dimension too low <2");
sizeY = sizeA[0];
sizeX = sizeA[1];
// compute number of elements over all dimensions
noElem = 1;
for (int i=0; i<sizeA.length; i++)
{
noElem *= sizeA[i];
}
values = new boolean[noElem];
if ((_values != null) &&
(noElem != _values.length) )
Errors.throwMathLibException("LogicalToken: dimension mismatch");
for(int ni = 0; ni< noElem; ni++)
{
if (_values != null)
values[ni] = _values[ni];
}
}
/**
* Convert y,x points to element number n
* @param y
* @param x
* @return n
*/
protected int yx2n(int y, int x)
{
int n = x*sizeY + y;
return n;
}
/*protected int n2y(int n)
{
int x = (int) (n/sizeY); // column to start
int y = n - x*sizeY; // row to start
return y;
}*/
/*protected int n2x(int n)
{
int x = (int) (n/sizeY); // column to start
return x;
}*/
/**
* Convert from index to n (e.g. index={2,3,5} -> n)
* @param
* @return
*/
public int index2n(int[] index)
{
String s="";
for (int i=0; i<index.length; i++)
s += index[i]+" ";
ErrorLogger.debugLine("LogicalToken: index2n: index: "+s);
int dn = noElem;
int n = 0;
for (int i=index.length-1; i>0; i--)
{
dn = dn / sizeA[i];
n += dn * index[i];
}
n+= index[0];
return n;
}
/**
*
*/
public DataToken getElementSized(int y, int x)
{
return new LogicalToken(y, x, new boolean[y*x]);
}
/** increase/decrease the size of the current DoubleNumberToken to size y*x
* @param dy number of rows
* @param dx number of columns
*/
public void setSize(int dy, int dx)
{
boolean[] newValues = new boolean[dy*dx];
ErrorLogger.debugLine("boolean "+dy+" "+dx);
ErrorLogger.debugLine("boolean "+sizeY+" "+sizeX);
// new array must be bigger than original value, otherwise values will be
// lost after copying into the new array
if ((dy<sizeY) || (dx<sizeX))
Errors.throwMathLibException("LogicalToken: setSize: loosing values");
for(int yy = 0; yy < sizeY; yy++)
{
for(int xx = 0; xx < sizeX; xx++)
{
int n = yx2n(yy,xx);
ErrorLogger.debugLine("boolean "+yy+" "+xx);
newValues[xx*dy + yy] = values[n];
}
}
values = newValues;
sizeY = dy;
sizeX = dx;
sizeA = new int[]{sizeY, sizeX};
noElem = sizeY * sizeX;
} // end setSize
/**
*
* @param y
* @param x
* @return
*/
public OperandToken getElement(int y, int x)
{
int n = yx2n(y,x);
return getElement(n);
}
/**
*
* @param n
* @return
*/
public OperandToken getElement(int n)
{
return new LogicalToken(values[n]);
}
/**
*
* @param y
* @param x
* @param num
*/
public void setElement(int y, int x, OperandToken num)
{
int n = yx2n(y,x);
setElement(n, num);
}
/**
*
* @param n
* @param num
*/
public void setElement(int n, OperandToken num)
{
values[n] = ((LogicalToken)num).getValue(n);
}
/**
*
* @param n
* @return
*/
public boolean getValue(int n)
{
return values[n];
}
/**
*
* @return
*/
public boolean[][] getValues()
{
boolean[][] temp = new boolean[sizeY][sizeX];
if ((sizeY==0) && (sizeX==0))
return null;
for(int yy = 0; yy < sizeY; yy++)
{
for(int xx = 0; xx < sizeX; xx++)
{
int n = yx2n(yy,xx);
temp[yy][xx] = values[n];
}
}
return temp;
}
/** Set value at position y, x
* @param y = y position in matrix
* @param x = x position in matrix
* @param real = real value
* @param imag = imaginary value
*/
public void setValue(int y, int x, boolean _value)
{
int n = yx2n(y,x);
setValue(n, _value);
}
/**
*
* @param n
* @param _real
* @param _imag
*/
public void setValue(int n, boolean _value)
{
values[n] = _value;
}
/**
*
* @param index multidimensional index
* @param _real
* @param _imag
*/
public void setValue(int[] index, boolean _value)
{
int n = index2n(index);
setValue(n, _value);
}
/**
* conversion into a number token
* @return
*/
public DoubleNumberToken getDoubleNumberToken()
{
double[] ret = new double[values.length];
for (int i=0; i<values.length; i++)
{
if (values[i])
ret[i]=1.0;
else
ret[i]=0.0;
}
return new DoubleNumberToken(sizeA, ret, null);
}
/**return the number as a string*/
public String toString()
{
String result = null;
if((sizeY == 0) && (sizeX == 0))
{
// e.g. a=null;
result = "[]";
}
else if((sizeY == 1) && (sizeX == 1) && sizeA.length==2)
{
// e.g. a=555;
result = ""+values[0];
}
else if (sizeA.length ==2)
{
result = toString2d(new int[]{sizeY,sizeX});
}
else
{
// e.g. a=[1,2,3;4,5,6] or multidimensional
int[] dim = new int[sizeA.length];
dim[0] = sizeY;
dim[1] = sizeX;
String s = toString(dim, sizeA.length-1);
result = new String(s);
}
return result;
}
/**
* @param dim
* @param i
* @return
*/
private String toString(int[] dim, int i)
{
String ret="";
if (i>=2)
{
// e.g. at least 3rd dimension
// e.g. a(5,3,4,x,3,1)
for (int n=0; n<sizeA[i]; n++)
{
dim[i]=n;
// e.g. a(5,3,Y,x,3,1)
ret += toString(dim, i-1);
}
}
else
{
// e.g.
ret += "(:,:";
for (int k=2; k<dim.length; k++)
{
ret += "," + (dim[k]+1); //NOTE: conversion from internal to external index
}
ret += ") = \n";
ret += toString2d(dim);
ret += "\n";
}
return ret;
}
/**
*
* @param nn
* @return
*/
private String toString2d(int[] nn)
{
StringBuffer buffer = new StringBuffer(20);
for(int yy = 0; yy < sizeA[0]; yy++)
{
buffer.append(" [");
for(int xx = 0; xx < sizeA[1]; xx++)
{
nn[0] = yy;
nn[1] = xx;
int n = index2n(nn);
ErrorLogger.debugLine(" NToken: "+index2n(nn));
buffer.append(values[n]);
if(xx < sizeX - 1)
buffer.append(" , ");
}
buffer.append("]\n");
}
return buffer.toString();
}
/**Evaluate the token. This causes it to return itself*/
public OperandToken evaluate(Token[] operands, GlobalValues globals)
{
return this;
}
/**Check if two tokens are equal
@param arg = the object to check against*/
public boolean equals(Object arg)
{
if(arg instanceof LogicalToken)
{
LogicalToken nArg = (LogicalToken)arg;
if(sizeX == nArg.getSizeX() && sizeY == nArg.getSizeY())
{
boolean equal = true;
for (int yy=0; yy<sizeY && equal; yy++)
{
for (int xx=0; xx<sizeX && equal; xx++)
{
int n = yx2n(yy,xx);
if(values[n] != nArg.getValue(n))
equal = false;
}
}
return equal;
}
return false;
}
return false;
}
///////////////////////standard operators///////////////////
////////////////////////////////////////////////////////////
/**add arg to this object for a number token
@param = the value to add to it
@return the result as an OperandToken*/
/* public OperandToken add(OperandToken arg)
{
if(!(arg instanceof LogicalToken))
Errors.throwMathLibException("LogicalToken: add: not logical");
LogicalToken nArg = ((LogicalToken)arg);
// Check dimensions of matrices
if(checkEqualDimensions(sizeA, nArg.sizeA))
{
// Add (n*m) + (n*m) or
// same dimensions (n,m,r)==(n,m,r)
ErrorLogger.debugLine("LogicalToken: add (n*m) + (n*m)");
LogicalToken result = new LogicalToken(sizeA, null);
for(int n = 0; n < noElem; n++)
{
boolean b = getValue(n) | nArg.getValue(n);
result.setValue(n, b);
}
return result;
}
else if(isScalar())
{
// 1 + [3,4,5]
ErrorLogger.debugLine("LogicalToken: add (1*1) + (n*m)");
DoubleNumberToken result = new DoubleNumberToken(nArg.sizeA, null, null);
for(int n = 0; n < nArg.getNumberOfElements(); n++)
{
double realval = getValueRe() + nArg.getValueRe(n);
result.setValue(n, realval, imaginaryval);
}
//ErrorLogger.debugLine("end DoubleNumberToken: add (n*m) + (n*m)");
return result;
}
else if(nArg.isScalar())
{
// [3,4,5] +1
ErrorLogger.debugLine("LogicalToken: add (n,m) + (1,1)");
DoubleNumberToken result = new DoubleNumberToken(sizeA, null, null);
for(int n = 0; n < noElem; n++)
{
double realval = getValueRe(n) + nArg.getValueRe();
result.setValue(n, realval, imaginaryval);
}
//ErrorLogger.debugLine("end DoubleNumberToken: add (n*m) + (n*m)");
return result;
}
else
{
// Matrices have unequal size: (n*m) != (o*p)
Errors.throwMathLibException("LogicalToken: add matrices of unequal size");
return null;
}
} // and add
*/
/**calculate the transpose of an array
@return the result as an OperandToken*/
public OperandToken transpose()
{
// transposed array
boolean[][] b = new boolean[sizeX][sizeY];
// swap rows and columns
for (int y=0; y<sizeY; y++)
{
for (int x=0; x<sizeX; x++)
{
int n = yx2n(y,x);
// copy (y,x) -> (x,y)
b[x][y] = values[n];
}
}
return new LogicalToken(b);
}
/**
* @return true if this number token is a scalar (1*1 matrix)
*/
public boolean isScalar()
{
for (int i=0; i<sizeA.length; i++)
{
// in case one entry in the size-array is unequal 1 it
// is not a scalar any more
if (sizeA[i]!=1)
return false;
}
return true;
}
} // end LogicalToken