📄 subassign.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 assigning a sub matrix to another matrix */
/* (e.g.: subassign(a,b,1,1:2) will assign matrix b to matrix a. */
/* Matrix indices start with <b>1</b> and <b>not</b> with <b>0</b>. */
public class subassign extends ExternalFunction
{
boolean leftCellB = false;
public void setLeftCell()
{
leftCellB = true;
}
/**return a sub matrix and assign a submatrix
@param operands[0] = original matrix
@param operands[1] = replacement matrix
@param operands[1] = vertical limits (1 or 1:3 or : )
@param operands[2] = horizontal limits (optional) (1 or 1:3 or : )
(e.g.: a= subassign(a,b,1,1) assigns the value b to the element (1,1) of matrix a,
a = subassign(a,b,:,2) assigns b as the second column of a,
a = subassign(a,b,2:3,0:2) assigns b as a 2-by-3 submatrix of a,
a = subassign(a,b,2) returns the first element of the second row of a*/
public OperandToken evaluate(Token[] operands)
{
DataToken retToken = null;
// at least three operands (e.g. subassign(a,b,2) )
// maximum is 4 operands (e.g. a=subassign(a,b,2,4) )
if ((getNArgIn(operands)<3) ||
(getNArgIn(operands)>4) )
throwMathLibException("SubAssign: number of arguments < 3 or >4");
if (operands[0]!=null) debugLine("SubAssign1: "+operands[0].toString());
if (operands[1]!=null) debugLine("SubAssign2: "+operands[1].toString());
if (operands[2]!=null) debugLine("SubAssign3: "+operands[2].toString());
// first two operands must be DataTokens (e.g. subassign(a,b,..) )
if ((operands[0] != null) &&
(!(operands[0] instanceof DataToken)) )
throwMathLibException("SubAssign: first argument must be a data token");
if (!(operands[1] instanceof DataToken))
throwMathLibException("SubAssign: second argument must be a data token");
// e.g. a={3,4,5} then a(2)=99 is wrong, must be a(2)={99}
// because "a" is a cell array.
if ( !leftCellB &&
(operands[0] instanceof CellArrayToken) &&
!(operands[1] instanceof CellArrayToken) )
throwMathLibException("SubAssign: conversion to cell from something not possible");
// values of the original matrix
int dy = 0;
int dx = 0;
if (operands[0]!=null)
{
// original matrix does not have any values yet
// e.g. subassign(null,9,1)
dy = ((DataToken)operands[0]).getSizeY();
dx = ((DataToken)operands[0]).getSizeX();
}
else
{
// e.g. subassign(null,888,3)
// create return token as same type as '888'
operands[0] = ((DataToken)operands[1]).getElementSized(1,1);
}
// size of replacement matrix
int dy_r = ((DataToken)operands[1]).getSizeY();
int dx_r = ((DataToken)operands[1]).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
int dy_max = 0;
// 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
int dx_max = 0;
// evaluate vertical selection (e.g. subassign(a,<....>,3) )
if(operands[2] instanceof DoubleNumberToken)
{
// e.g. submatrix(a,<number>) or submatrix(a,<number>,4)
// submatrix(a,3:5)
}
else if(operands[2] instanceof Expression)
{
// e.g. submatrix(a,:) or submatrix(a,2:end)
Expression expr = (Expression)operands[2];
OperatorToken op = (OperatorToken)expr.getData();
debugLine("submatrix expr="+operands[2].toString());
// 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)==3)
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)==3)
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)==3)
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[2]= colonOp;
}
else
throwMathLibException("SubMatrix: eval: unknown operand");
// get limits size and indices
y_dy = ((DoubleNumberToken)operands[2]).getSizeY();
y_dx = ((DoubleNumberToken)operands[2]).getSizeX();
y_indexes = ((DoubleNumberToken)operands[2]).getReValues();
ErrorLogger.debugLine("SubMatrix: y_dy="+y_dy+" y_dx="+y_dx);
// find highest index
for (int xi=0; xi<y_dx; xi++)
{
for (int yi=0; yi<y_dy ; yi++)
{
if (y_indexes[yi][xi]> dy_max)
dy_max = (int)y_indexes[yi][xi];
if (y_indexes[yi][xi]<=0)
throwMathLibException("SubMatrix: index y <=0");
}
}
debugLine("SubMatrix: dy_max "+dy_max);
// evaluate horizontal selection (e.g. subassign(a,b,3,<...>) )
if(operands.length==4)
{
debugLine("SubMatrix: "+operands[3].toString());
if(operands[3] instanceof DoubleNumberToken)
{
// e.g. submatrix(a,1,<some array>)
// e.g. submatrix(a,1,2)
}
else if(operands[3] instanceof Expression)
{
// e.g. submatrix(a,:) or submatrix(a,2:end)
Expression expr = (Expression)operands[3];
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;
if (expr.getNumberOfChildren() == 2)
{
// submatrix(a,3,4:end)
OperandToken left = expr.getChild(0);
OperandToken right = expr.getChild(1);
if ( (!(right instanceof DelimiterToken)) ||
(!((DelimiterToken)right).getWordValue().equals("end")) )
throwMathLibException("SubMatrix: wrong delimiter");
// if three arguments: e.g. submatrix(a,3,4:end) -> 4:dx
right = new DoubleNumberToken(dx);
// create new ColonOperator and return new indexes
colonOp = new Expression(new ColonOperatorToken(), left, right);
}
else if (expr.getNumberOfChildren() == 3)
{
// e.g. (2:3:end)
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");
// if three arguments: e.g. submatrix(a,3,4:2:end) -> 4:2:dx
right = new DoubleNumberToken(dx);
// create new ColonOperator and return new indexes
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -