📄 submatrix.java
字号:
package jmathlib.toolbox.jmathlib.matrix;
import jmathlib.core.tokens.*;
import jmathlib.core.tokens.numbertokens.DoubleNumberToken;
import jmathlib.core.functions.ExternalFunction;
import jmathlib.core.interpreter.*;
/**An external function for creating a sub matrix of a DoubleNumberToken */
/* (e.g.: submatrix(a,1,1:2) will return the the elements 1 and 2 from row 1 */
public class submatrix extends ExternalFunction
{
boolean leftCellB = false;
public void setLeftCell()
{
leftCellB = true;
}
/**return a sub matrix
@param operands[0] = matrix
@param operands[1] = vertical limits (1 or 1:3 or : )
@param operands[2] = horizontal limits (optional) (1 or 1:3 or : )
(e.g.: submatrix(a,0,0) returns the top left element of a, <br>
submatrix(a,:,2) returns the second column of a, <br>
submatrix(a,2:3,0:2) returns a 2-by-3 submatrix of a, <br>
submatrix(a,2) returns the first element of the second row of a <br>
e.g.: a=[1,2,3,4,5; <br>
6,7,8,9,10; <br>
1,2,3,4,5] <br>
then submatrix(a,1,2) returns 2 <br>
then submatrix(a,3,:) returns [3,8,3]' <br>
then submatrix(a,2:5,2) returns [7,8,9,10] <br>
then submatrix(a,:) return [1,2,3,4,5,6,7,8,9...]' column <br>
(also see subassign() )
*/
public OperandToken evaluate(Token[] operands)
{
// at least two operands (e.g. submatrix(a,2) )
if ((getNArgIn(operands)<2) || (getNArgIn(operands)>3))
throwMathLibException("SubMatrix: number of arguments <2 or >3");
// first operand must be a DoubleNumberToken
if (!(operands[0] instanceof DataToken))
throwMathLibException("SubMatrix: first argument must be a data token");
// values of the data array
int dy = ((DataToken)operands[0]).getSizeY();
int dx = ((DataToken)operands[0]).getSizeX();
// first limit (y-limit)
int y_dy = 0; // y-size of first limit
int y_dx = 0; // x-size of first limit
double[][] y_indexes = null; // elements
// second limit (x-limit)
int x_dy = 0; // y-size of second limit
int x_dx = 0; // x-size of second limit
double[][] x_indexes = null; // elements
ErrorLogger.debugLine("SubMatrix: "+operands[1].toString());
// evaluate VERTICAL selection (e.g. submatrix(a,<something>,3) )
if(operands[1] instanceof DoubleNumberToken)
{
// e.g. submatrix(a,<number>) or submatrix(a,<number>,4)
// submatrix(a,3:5)
}
else if(operands[1] instanceof LogicalToken)
{
// e.g. submatrix(a,[true,true,false,true])
LogicalToken l = (LogicalToken)operands[1];
// find number of elements unequal zero
int n = 0;
for (int i=0; i<l.getNumberOfElements(); i++)
{
if (l.getValue(i))
n++;
}
// create index array from boolean values
// eg. a=[true,true,false,true] ->[1,2,4] (use indices with "true")
double[][] values = new double [1][n];
int ni =0;
for (int i=0; i<l.getNumberOfElements(); i++)
{
if (l.getValue(i))
{
values[0][ni] = (double)i + 1;
ni++;
}
}
operands[1] = new DoubleNumberToken(values,null);
}
else if(operands[1] instanceof Expression)
{
// e.g. submatrix(a,:) or submatrix(a,2:end)
Expression expr = (Expression)operands[1];
OperatorToken op = (OperatorToken)expr.getData();
// check if expression contains colon, e.g. (:) , (3:end)
if ((op == null) ||
(!(op instanceof ColonOperatorToken)) )
throwMathLibException("SubMatrix: colon error");
OperandToken colonOp = null;
// possible colon operations. e.g. (:),(2:end),(2:3:end)
if (expr.getNumberOfChildren() == 2)
{
// Get operands (e.g. <1>:<5>)
OperandToken left = expr.getChild(0);
OperandToken right = expr.getChild(1);
if ( (!(right instanceof DelimiterToken)) ||
(!((DelimiterToken)right).getWordValue().equals("end")) )
throwMathLibException("SubMatrix: wrong delimiter");
// "end" delimiter indicates total number of values or
// just the number of rows
// if two arguments: e.g. submatrix(a,3:end) -> 3:dy*dx
// if three arguments: e.g. submatrix(a,3:end,4:8) -> 3:dy
if (getNArgIn(operands)==2)
right = new DoubleNumberToken(dy*dx);
else
right = new DoubleNumberToken(dy);
// create new ColonOperator and return new indexes
colonOp = new Expression(new ColonOperatorToken(), left, right);
}
else if (expr.getNumberOfChildren() == 3)
{
// e.g. (2:3:end)
// Get operands (e.g. <1>:<5>)
OperandToken left = expr.getChild(0);
OperandToken middle = expr.getChild(1);
OperandToken right = expr.getChild(2);
if ( (!(right instanceof DelimiterToken)) ||
(!((DelimiterToken)right).getWordValue().equals("end")) )
throwMathLibException("SubMatrix: wrong delimiter");
// "end" delimiter indicates total number of values or
// just the number of rows
// if two arguments: e.g. submatrix(a,3:2:end) -> 3:2:dy*dx
// if three arguments: e.g. submatrix(a,3:2:end,4:8) -> 3:2:dy
if (getNArgIn(operands)==2)
right = new DoubleNumberToken(dy*dx);
else
right = new DoubleNumberToken(dy);
// create new ColonOperator and return new indexes
colonOp = new Expression(new ColonOperatorToken(), left, middle, right);
}
else if (expr.getNumberOfChildren() == 0)
{
// ":" indicates all indexes of matrix/rows
// if two arguments: e.g. submatrix(a,:) -> ALL elements
// if three arguments: e.g. submatrix(a,3,:) -> all rows
int len = 0;
if (getNArgIn(operands)==2)
len = (dy*dx);
else
len = dy;
colonOp = new Expression(new ColonOperatorToken(),
new DoubleNumberToken(1),
new DoubleNumberToken(len) );
}
else
throwMathLibException("SubMatrix: colon wrong number of childs");
// evaluate new colon expression
colonOp = colonOp.evaluate(null);
if ( !(colonOp instanceof DoubleNumberToken))
throwMathLibException("SubMatrix: colon error wrong type");
// e.g. a(:) must return a column vector
if (getNArgIn(operands)==2)
colonOp = colonOp.transpose();
// copy new array of indices to second operand of SubMatrix
operands[1]= colonOp;
}
else
throwMathLibException("SubMatrix: eval: unknown operand");
// get limits size and indices
y_dy = ((DoubleNumberToken)operands[1]).getSizeY();
y_dx = ((DoubleNumberToken)operands[1]).getSizeX();
y_indexes = ((DoubleNumberToken)operands[1]).getReValues();
ErrorLogger.debugLine("SubMatrix: "+y_dy+" "+y_dx);
/***********************************************************************/
// create return array for e.g. submatrix(a,5) or submatrix(a,3:5)
// or submatrix(a,3:end) or submatrix(a,:) or submatrix(a,[1,6,2,4])
if(getNArgIn(operands)==2)
{
// create return array with size of limits operator
DataToken retToken = ((DataToken)operands[0]).getElementSized(y_dy,y_dx);
// copy data to return array
for (int xi=0; xi<y_dx; xi++)
{
for (int yi=0; yi<y_dy ; yi++)
{
int index = (int)y_indexes[yi][xi]-1;
if ((index<0) || (index>dy*dx-1))
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -