001/* A token that contains a 2-D int matrix. 002 003 Copyright (c) 1998-2018 The Regents of the University of California. 004 All rights reserved. 005 Permission is hereby granted, without written agreement and without 006 license or royalty fees, to use, copy, modify, and distribute this 007 software and its documentation for any purpose, provided that the above 008 copyright notice and the following two paragraphs appear in all copies 009 of this software. 010 011 IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY 012 FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES 013 ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF 014 THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF 015 SUCH DAMAGE. 016 017 THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, 018 INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 019 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE 020 PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF 021 CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, 022 ENHANCEMENTS, OR MODIFICATIONS. 023 024 PT_COPYRIGHT_VERSION_2 025 COPYRIGHTENDKEY 026 027 028 */ 029package ptolemy.data; 030 031import ptolemy.data.expr.ASTPtRootNode; 032import ptolemy.data.expr.ParseTreeEvaluator; 033import ptolemy.data.expr.PtParser; 034import ptolemy.data.type.BaseType; 035import ptolemy.data.type.Type; 036import ptolemy.data.type.TypeLattice; 037import ptolemy.graph.CPO; 038import ptolemy.kernel.util.IllegalActionException; 039import ptolemy.kernel.util.InternalErrorException; 040import ptolemy.math.Complex; 041import ptolemy.math.ComplexMatrixMath; 042import ptolemy.math.DoubleMatrixMath; 043import ptolemy.math.IntegerArrayMath; 044import ptolemy.math.IntegerMatrixMath; 045import ptolemy.math.LongMatrixMath; 046 047/////////////////////////////////////////////////////////////////// 048//// IntMatrixToken 049 050/** 051 A token that contains a 2-D int matrix. 052 053 @author Yuhong Xiong, Jeff Tsay, Steve Neuendorffer 054 @version $Id$ 055 @since Ptolemy II 0.2 056 @Pt.ProposedRating Green (neuendor) 057 @Pt.AcceptedRating Yellow (wbwu) 058 */ 059public class IntMatrixToken extends MatrixToken { 060 /** Construct an IntMatrixToken with a one by one matrix. The 061 * only element in the matrix has value 0.0 062 */ 063 public IntMatrixToken() { 064 _value = new int[1]; 065 _value[0] = 0; 066 _rowCount = 1; 067 _columnCount = 1; 068 } 069 070 /** Construct a IntMatrixToken with the specified 1-D matrix. 071 * Make a copy of the matrix and store the copy, 072 * so that changes on the specified matrix after this token is 073 * constructed will not affect the content of this token. 074 * @param value The 1-D matrix. 075 * @param rows The number of rows. 076 * @param columns The number of columns. 077 * @exception IllegalActionException If the specified matrix 078 * is null. 079 */ 080 public IntMatrixToken(int[] value, int rows, int columns) 081 throws IllegalActionException { 082 this(value, rows, columns, DO_COPY); 083 } 084 085 /** Construct a IntMatrixToken with the specified 1-D matrix. 086 * If copy is DO_COPY, make a copy of the matrix and store the copy, 087 * so that changes on the specified matrix after this token is 088 * constructed will not affect the content of this token. 089 * If copy is DO_NOT_COPY, just reference the matrix (do not copy 090 * its contents). This saves some time and memory. 091 * The argument matrix should NOT be modified after this constructor 092 * is called to preserve immutability. 093 * @param value The 1-D matrix. 094 * @param rows The number of rows. 095 * @param columns The number of columns. 096 * @param copy If this parameter is 097 * {@link ptolemy.data.MatrixToken#DO_COPY}, then the value matrix 098 * is copied. If this parameter is 099 * {@link ptolemy.data.MatrixToken#DO_NOT_COPY}, then the value matrix 100 * is NOT copied and should not be modified after construction of this 101 * object. 102 * @exception IllegalActionException If the specified matrix 103 * is null. 104 */ 105 public IntMatrixToken(int[] value, int rows, int columns, int copy) 106 throws IllegalActionException { 107 if (value == null) { 108 throw new IllegalActionException( 109 "IntMatrixToken: The specified " + "matrix is null."); 110 } 111 112 _rowCount = rows; 113 _columnCount = columns; 114 115 if (copy == DO_COPY) { 116 _value = IntegerArrayMath.allocCopy(value); 117 } else { 118 _value = value; 119 } 120 } 121 122 /** Construct a IntMatrixToken with the specified 2-D matrix. 123 * Make a copy of the matrix and store the copy, 124 * so that changes on the specified matrix after this token is 125 * constructed will not affect the content of this token. 126 * @param value The 2-D matrix used to initialize this object. 127 * @exception IllegalActionException If the specified matrix 128 * is null. 129 */ 130 public IntMatrixToken(int[][] value) throws IllegalActionException { 131 this(value, DO_COPY); 132 } 133 134 /** Construct a IntMatrixToken with the specified 2-D matrix. 135 * If copy is DO_COPY, make a copy of the matrix and store the copy, 136 * so that changes on the specified matrix after this token is 137 * constructed will not affect the content of this token. 138 * If copy is DO_NOT_COPY, just reference the matrix (do not copy 139 * its contents). This saves some time and memory. 140 * The argument matrix should NOT be modified after this constructor 141 * is called to preserve immutability. 142 * <p> 143 * Since the DO_NOT_COPY option requires some care, this constructor 144 * should be protected, but is not. 145 * @param value The 2-D matrix used to initialize this object. 146 * @param copy If this parameter is 147 * {@link ptolemy.data.MatrixToken#DO_COPY}, then the value matrix 148 * is copied. If this parameter is 149 * {@link ptolemy.data.MatrixToken#DO_NOT_COPY}, then the value matrix 150 * is NOT copied and should not be modified after construction of this 151 * object. 152 153 * @exception IllegalActionException If the specified matrix 154 * is null. 155 */ 156 public IntMatrixToken(int[][] value, int copy) 157 throws IllegalActionException { 158 if (value == null) { 159 throw new IllegalActionException( 160 "IntMatrixToken: The specified " + "matrix is null."); 161 } 162 163 _initialize(value); 164 } 165 166 /** Construct an IntMatrixToken from the specified string. 167 * @param init A string expression of a 2-D int matrix. 168 * @exception IllegalActionException If the string does 169 * not contain a parsable 2-D int matrix. 170 */ 171 public IntMatrixToken(String init) throws IllegalActionException { 172 PtParser parser = new PtParser(); 173 ASTPtRootNode tree = parser.generateParseTree(init); 174 Token token = new ParseTreeEvaluator().evaluateParseTree(tree); 175 176 if (token instanceof IntMatrixToken) { 177 int[][] value = ((IntMatrixToken) token).intMatrix(); 178 _initialize(value); 179 } else { 180 throw new IllegalActionException("A matrix token cannot be" 181 + " created from the expression '" + init + "'"); 182 } 183 } 184 185 /** Construct an IntMatrixToken from the specified array of 186 * tokens. The tokens in the array must be scalar tokens 187 * convertible into integers. 188 * @param tokens The array of tokens, which must contains 189 * rows * columns ScalarTokens. 190 * @param rows The number of rows in the matrix to be created. 191 * @param columns The number of columns in the matrix to be 192 * created. 193 * @exception IllegalActionException If the array of tokens is 194 * null, or the length of the array is not correct, or if one of 195 * the elements of the array is null, or if one of the elements 196 * of the array cannot be losslessly converted to an integer. 197 */ 198 public IntMatrixToken(Token[] tokens, int rows, int columns) 199 throws IllegalActionException { 200 int elements = rows * columns; 201 202 if (tokens == null) { 203 throw new IllegalActionException( 204 "IntMatrixToken: The specified" + " array is null."); 205 } 206 207 if (tokens.length != elements) { 208 throw new IllegalActionException("IntMatrixToken: The specified" 209 + " array is not of the correct length"); 210 } 211 212 _rowCount = rows; 213 _columnCount = columns; 214 _value = new int[elements]; 215 216 for (int i = 0; i < elements; i++) { 217 Token token = tokens[i]; 218 219 if (token instanceof ScalarToken) { 220 _value[i] = ((ScalarToken) token).intValue(); 221 } else { 222 throw new IllegalActionException("IntMatrixToken: Element " + i 223 + " in the array with value " + token 224 + " is not a ScalarToken"); 225 } 226 } 227 } 228 229 /////////////////////////////////////////////////////////////////// 230 //// public methods //// 231 232 /** Return the content of this token as a 2-D Complex matrix. 233 * @return A 2-D Complex matrix 234 */ 235 @Override 236 public Complex[][] complexMatrix() { 237 return ComplexMatrixMath.toMatrixFromArray( 238 IntegerArrayMath.toComplexArray(_value), _rowCount, 239 _columnCount); 240 } 241 242 /** Convert the specified token into an instance of IntMatrixToken. 243 * This method does lossless conversion. 244 * If the argument is already an instance of IntMatrixToken, 245 * it is returned without any change. Otherwise, if the argument 246 * is below IntMatrixToken in the type hierarchy, it is converted to 247 * an instance of IntMatrixToken or one of the subclasses of 248 * IntMatrixToken and returned. If none of the above condition is 249 * met, an exception is thrown. 250 * @param token The token to be converted to a IntMatrixToken. 251 * @return A IntMatrixToken 252 * @exception IllegalActionException If the conversion cannot 253 * be carried out. 254 */ 255 public static IntMatrixToken convert(Token token) 256 throws IllegalActionException { 257 if (token instanceof IntMatrixToken) { 258 return (IntMatrixToken) token; 259 } 260 261 int compare = TypeLattice.compare(BaseType.INT_MATRIX, token); 262 263 if (compare == CPO.LOWER || compare == CPO.INCOMPARABLE) { 264 throw new IllegalActionException( 265 notSupportedIncomparableConversionMessage(token, "[int]")); 266 } 267 268 // try int 269 // compare = TypeLattice.compare(BaseType.INT, token); 270 // if (compare == CPO.SAME || compare == CPO.HIGHER) { 271 // IntToken tem = IntToken.convert(token); 272 // int[][] result = new int[1][1]; 273 // result[0][0] = tem.intValue(); 274 // return new IntMatrixToken(result); 275 // } 276 // try ByteMatrix? 277 // compare = TypeLattice.compare(BaseType.INT_MATRIX, token); 278 // if (compare == CPO.SAME || compare == CPO.HIGHER) { 279 // IntMatrixToken tem = convert(token); 280 // int[][] result = tem.intMatrix(); 281 // return new IntMatrixToken(result); 282 // } 283 // The argument is below IntMatrixToken in the type hierarchy, 284 // but I don't recognize it. 285 throw new IllegalActionException( 286 notSupportedConversionMessage(token, "[int]")); 287 } 288 289 /** Convert the specified scalar token into an instance of 290 * IntMatrixToken. The resulting matrix will be square, with 291 * the number of rows and columns equal to the given size. 292 * This method does lossless conversion. 293 * @param token The token to be converted to a IntMatrixToken. 294 * @param size The number of rows and columns of the resulting matrix. 295 * @return A IntMatrixToken 296 * @exception IllegalActionException If the conversion cannot 297 * be carried out. 298 */ 299 public static Token convert(ScalarToken token, int size) 300 throws IllegalActionException { 301 // Check to make sure that the token is convertible to INT. 302 int compare = TypeLattice.compare(BaseType.INT, token); 303 304 if (compare == CPO.SAME || compare == CPO.HIGHER) { 305 if (token.isNil()) { 306 throw new IllegalActionException( 307 Token.notSupportedConversionMessage(token, "[int]")); 308 } 309 IntToken intToken = IntToken.convert(token); 310 int intValue = intToken.intValue(); 311 int[] result = new int[size * size]; 312 313 for (int i = 0; i < size; i++) { 314 result[i] = intValue; 315 } 316 317 return new IntMatrixToken(result, size, size, DO_NOT_COPY); 318 } 319 320 throw new IllegalActionException( 321 notSupportedConversionMessage(token, "[int]")); 322 } 323 324 /** Return a new matrix that is a sub-matrix of this matrix. 325 * @param rowStart The row to start on. 326 * @param colStart The column to start on. 327 * @param rowSpan The number of rows to copy. 328 * @param colSpan The number of columns to copy. 329 * @return a sub-matrix of this matrix. 330 * @exception IllegalActionException If the returned matrix is empty or if the specified 331 * parameters result in out of bounds accesses. 332 */ 333 @Override 334 public MatrixToken crop(int rowStart, int colStart, int rowSpan, 335 int colSpan) throws IllegalActionException { 336 int[][] value = this.intMatrix(); 337 try { 338 int[][] result = IntegerMatrixMath.crop(value, rowStart, colStart, 339 rowSpan, colSpan); 340 return new IntMatrixToken(result); 341 } catch (ArrayIndexOutOfBoundsException ex) { 342 throw new IllegalActionException( 343 "Matrix crop indices out of bounds (rowStart = " + rowStart 344 + ", colStart = " + colStart + ", rowSpan = " 345 + rowSpan + ", colSpan = " + colSpan + ")."); 346 } 347 } 348 349 /** Return the content of this token as a 2-D double matrix. 350 * @return A 2-D double matrix. 351 */ 352 @Override 353 public double[][] doubleMatrix() { 354 return DoubleMatrixMath.toMatrixFromArray( 355 IntegerArrayMath.toDoubleArray(_value), _rowCount, 356 _columnCount); 357 } 358 359 /** Return true if the argument is an instance of IntMatrixToken 360 * of the same dimensions and the corresponding elements of the matrices 361 * are equal. 362 * @param object An instance of Object. 363 * @return True if the argument is an instance of IntMatrixToken 364 * of the same dimensions and the corresponding elements of the 365 * matrices are equal. 366 */ 367 @Override 368 public boolean equals(Object object) { 369 if (object == null) { 370 return false; 371 } 372 // This test rules out instances of a subclass. 373 if (object.getClass() != getClass()) { 374 return false; 375 } 376 377 IntMatrixToken matrixArgument = (IntMatrixToken) object; 378 379 if (_rowCount != matrixArgument.getRowCount()) { 380 return false; 381 } 382 383 if (_columnCount != matrixArgument.getColumnCount()) { 384 return false; 385 } 386 387 int[] value = matrixArgument._value; 388 int elements = _rowCount * _columnCount; 389 390 for (int i = 0; i < elements; i++) { 391 if (_value[i] != value[i]) { 392 return false; 393 } 394 } 395 396 return true; 397 } 398 399 /** Return the number of columns in the matrix. 400 * @return The number of columns in the matrix. 401 */ 402 @Override 403 public int getColumnCount() { 404 return _columnCount; 405 } 406 407 /** Return the element of the matrix at the specified 408 * row and column in a IntToken. 409 * @param row The row index of the desired element. 410 * @param column The column index of the desired element. 411 * @return A IntToken containing the matrix element. 412 * @exception ArrayIndexOutOfBoundsException If the specified 413 * row or column number is outside the range of the matrix. 414 */ 415 @Override 416 public Token getElementAsToken(int row, int column) 417 throws ArrayIndexOutOfBoundsException { 418 return new IntToken(_value[row * _columnCount + column]); 419 } 420 421 /** Return the element of the contained matrix at the specified 422 * row and column. 423 * @param row The row index of the desired element. 424 * @param column The column index of the desired element. 425 * @return The int at the specified matrix entry. 426 * @exception ArrayIndexOutOfBoundsException If the specified 427 * row or column number is outside the range of the matrix. 428 */ 429 public int getElementAt(int row, int column) { 430 return _value[row * _columnCount + column]; 431 } 432 433 /** Return the Type of the tokens contained in this matrix token. 434 * This must be a type representing a scalar token. 435 * @return BaseType.INT. 436 */ 437 @Override 438 public Type getElementType() { 439 return BaseType.INT; 440 } 441 442 /** Return the number of rows in the matrix. 443 * @return The number of rows in the matrix. 444 */ 445 @Override 446 public int getRowCount() { 447 return _rowCount; 448 } 449 450 /** Return the type of this token. 451 * @return BaseType.INT_MATRIX 452 */ 453 @Override 454 public Type getType() { 455 return BaseType.INT_MATRIX; 456 } 457 458 /** Return a hash code value for this token. This method returns the 459 * sum of the elements. 460 * @return A hash code value for this token. 461 */ 462 @Override 463 public int hashCode() { 464 int code = 0; 465 int elements = _rowCount * _columnCount; 466 467 for (int i = 0; i < elements; i++) { 468 code += _value[i]; 469 } 470 471 return code; 472 } 473 474 /** Return the content in the token as a 2-D int matrix. 475 * The returned matrix is a copy so the caller is free to 476 * modify it. 477 * @return A 2-D int matrix. 478 */ 479 @Override 480 public int[][] intMatrix() { 481 return IntegerMatrixMath.toMatrixFromArray(_value, _rowCount, 482 _columnCount); 483 } 484 485 /** Join a matrix of matrices into a single matrix by tiling. 486 * All matrices in the matrix must be of the same type, 487 * the same type as this matrix. But none of them needs to 488 * actually be this matrix. This base class simply throws 489 * an exception. Derived classes provide the implementation. 490 * The number of columns in the resulting matrix is the sum 491 * of the number of columns in the first row of the argument. 492 * The number of rows in the resulting matrix is the sum 493 * of the number of rows in the first column of the argument. 494 * The matrices are copied into the result starting at the 495 * position determined by the first row or column. 496 * If the matrices overlap, then while copying left to right, 497 * top-to-bottom, data will be overwritten. If there are gaps, 498 * the resulting matrix will be filled with zeros. 499 * @param matrices A two-dimensional array of matrix tokens. 500 * @return A new matrix token of the same type as the elements 501 * in the input matrix of matrix tokens. 502 * @exception IllegalActionException If the types of the matrices 503 * in the input are not all the same, or if tiling fails due 504 * to size incompatibilities, or if the input matrix has no 505 * tokens. 506 */ 507 @Override 508 public MatrixToken join(MatrixToken[][] matrices) 509 throws IllegalActionException { 510 if (matrices == null || matrices.length == 0 511 || matrices[0].length == 0) { 512 throw new IllegalActionException("matrixJoin: No input matrices."); 513 } 514 // Calculate the size of the result. 515 // This assumes the matrices tile. 516 int rows = 0; 517 int columns = 0; 518 for (MatrixToken[] matrice : matrices) { 519 rows += matrice[0].getRowCount(); 520 } 521 for (int j = 0; j < matrices[0].length; j++) { 522 columns += matrices[0][j].getColumnCount(); 523 } 524 int[][] tiled = new int[rows][columns]; 525 int row = 0; 526 for (int i = 0; i < matrices.length; i++) { 527 int column = 0; 528 for (int j = 0; j < matrices[i].length; j++) { 529 if (!(matrices[i][j] instanceof IntMatrixToken)) { 530 throw new IllegalActionException( 531 "matrixJoin: matrices not all of the same type."); 532 } 533 int rowCount = matrices[i][j].getRowCount(); 534 if (row + rowCount > rows) { 535 rowCount = rows - row; 536 } 537 int columnCount = matrices[i][j].getColumnCount(); 538 if (column + columnCount > columns) { 539 columnCount = columns - column; 540 } 541 IntegerMatrixMath.matrixCopy(matrices[i][j].intMatrix(), 0, 0, 542 tiled, row, column, rowCount, columnCount); 543 // Starting position for the next column. 544 column += matrices[0][j].getColumnCount(); 545 } 546 // Starting position for the next column. 547 row += matrices[i][0].getRowCount(); 548 } 549 return new IntMatrixToken(tiled); 550 } 551 552 /** Return the content of this token as a 2-D long matrix. 553 * @return A 2-D long matrix. 554 */ 555 @Override 556 public long[][] longMatrix() { 557 return LongMatrixMath.toMatrixFromArray( 558 IntegerArrayMath.toLongArray(_value), _rowCount, _columnCount); 559 } 560 561 /** Return a new Token representing the left multiplicative 562 * identity. The returned token contains an identity matrix 563 * whose dimensions are the same as the number of rows of 564 * the matrix contained in this token. 565 * @return A new IntMatrixToken containing the left multiplicative 566 * identity. 567 */ 568 @Override 569 public Token one() { 570 try { 571 return new IntMatrixToken(IntegerMatrixMath.identity(_rowCount), 572 DO_NOT_COPY); 573 } catch (IllegalActionException illegalAction) { 574 // should not happen 575 throw new InternalErrorException( 576 "IntMatrixToken.one: " + "Cannot create identity matrix."); 577 } 578 } 579 580 /** Return a new Token representing the right multiplicative 581 * identity. The returned token contains an identity matrix 582 * whose dimensions are the same as the number of columns of 583 * the matrix contained in this token. 584 * @return A new IntMatrixToken containing the right multiplicative 585 * identity. 586 */ 587 @Override 588 public Token oneRight() { 589 try { 590 return new IntMatrixToken(IntegerMatrixMath.identity(_columnCount), 591 DO_NOT_COPY); 592 } catch (IllegalActionException illegalAction) { 593 // should not happen 594 throw new InternalErrorException("IntMatrixToken.oneRight: " 595 + "Cannot create identity matrix."); 596 } 597 } 598 599 /** Split this matrix into multiple matrices. See the base 600 * class for documentation. 601 * @param rows The number of rows per submatrix. 602 * @param columns The number of columns per submatrix. 603 * @return An array of matrix tokens. 604 */ 605 @Override 606 public MatrixToken[][] split(int[] rows, int[] columns) { 607 MatrixToken[][] result = new MatrixToken[rows.length][columns.length]; 608 int[][] source = intMatrix(); 609 int row = 0; 610 for (int i = 0; i < rows.length; i++) { 611 int column = 0; 612 for (int j = 0; j < columns.length; j++) { 613 int[][] contents = new int[rows[i]][columns[j]]; 614 int rowspan = rows[i]; 615 if (row + rowspan > source.length) { 616 rowspan = source.length - row; 617 } 618 int columnspan = columns[j]; 619 if (column + columnspan > source[0].length) { 620 columnspan = source[0].length - column; 621 } 622 if (columnspan > 0 && rowspan > 0) { 623 IntegerMatrixMath.matrixCopy(source, row, column, contents, 624 0, 0, rowspan, columnspan); 625 } 626 column += columns[j]; 627 try { 628 result[i][j] = new IntMatrixToken(contents); 629 } catch (IllegalActionException e) { 630 throw new InternalErrorException(e); 631 } 632 } 633 row += rows[i]; 634 } 635 return result; 636 } 637 638 /** Return a new Token representing the additive identity. 639 * The returned token contains a matrix whose elements are 640 * all zero, and the size of the matrix is the same as the 641 * matrix contained in this token. 642 * @return A new IntMatrixToken containing the additive identity. 643 */ 644 @Override 645 public Token zero() { 646 try { 647 return new IntMatrixToken(new int[_rowCount * _columnCount], 648 _rowCount, _columnCount, DO_NOT_COPY); 649 } catch (IllegalActionException illegalAction) { 650 // should not happen 651 throw new InternalErrorException( 652 "IntMatrixToken.zero: " + "Cannot create zero matrix."); 653 } 654 } 655 656 /////////////////////////////////////////////////////////////////// 657 //// protected methods //// 658 659 /** Return a new token whose value is the value of the argument 660 * Token added to the value of this Token. It is assumed that 661 * the type of the argument is IntMatrixToken. 662 * @param rightArgument The token to add to this token. 663 * @exception IllegalActionException If the units are not 664 * compatible, or this operation is not supported by the derived 665 * class. 666 * @return A new IntMatrixToken containing the result. 667 */ 668 @Override 669 protected MatrixToken _add(MatrixToken rightArgument) 670 throws IllegalActionException { 671 IntMatrixToken convertedArgument = (IntMatrixToken) rightArgument; 672 int[] result = IntegerArrayMath 673 .add(convertedArgument._getInternalIntArray(), _value); 674 return new IntMatrixToken(result, _rowCount, _columnCount, DO_NOT_COPY); 675 } 676 677 /** Return a new token whose value is the value of the argument 678 * Token added to the value of each element of this Token. It is 679 * assumed that the type of the argument is the same as the type 680 * of each element of this class or is a matrix with one element. 681 * @param rightArgument The token to add to this token. 682 * @exception IllegalActionException If this operation is not 683 * supported by the derived class. 684 * @return A new Token containing the result. 685 */ 686 @Override 687 protected MatrixToken _addElement(Token rightArgument) 688 throws IllegalActionException { 689 int scalar; 690 if (rightArgument instanceof IntMatrixToken) { 691 if (((IntMatrixToken) rightArgument).getRowCount() != 1 692 || ((IntMatrixToken) rightArgument).getColumnCount() != 1) { 693 // Throw an exception. 694 return super._moduloElement(rightArgument); 695 } 696 scalar = ((IntMatrixToken) rightArgument).getElementAt(0, 0); 697 } else { 698 scalar = ((IntToken) rightArgument).intValue(); 699 } 700 int[] result = IntegerArrayMath.add(_value, scalar); 701 return new IntMatrixToken(result, _rowCount, _columnCount, DO_NOT_COPY); 702 } 703 704 /** Return a new token whose elements are the result of dividing 705 * the elements of this token by the argument. It is 706 * assumed that the type of the argument is the same as the type 707 * of each element of this class, or is an integer matrix 708 * with one element that is of the same type. 709 * @param rightArgument The token that divides this token. 710 * @exception IllegalActionException If this operation is not 711 * supported by the derived class. 712 * @return A new Token containing the result. 713 */ 714 @Override 715 protected MatrixToken _divideElement(Token rightArgument) 716 throws IllegalActionException { 717 int scalar; 718 if (rightArgument instanceof IntMatrixToken) { 719 if (((IntMatrixToken) rightArgument).getRowCount() != 1 720 || ((IntMatrixToken) rightArgument).getColumnCount() != 1) { 721 // Throw an exception. 722 return super._moduloElement(rightArgument); 723 } 724 scalar = ((IntMatrixToken) rightArgument).getElementAt(0, 0); 725 } else { 726 scalar = ((IntToken) rightArgument).intValue(); 727 } 728 int[] result = IntegerArrayMath.divide(_value, scalar); 729 return new IntMatrixToken(result, _rowCount, _columnCount, DO_NOT_COPY); 730 } 731 732 /** Return a reference to the internal 2-D matrix of ints that represents 733 * this Token. Because no copying is done, the contents must NOT be 734 * modified to preserve the immutability of Token. 735 * @return An int matrix. 736 */ 737 protected int[] _getInternalIntArray() { 738 return _value; 739 } 740 741 /** Return a new token whose elements are the remainders of 742 * the elements of this token when divided by the argument. 743 * It is guaranteed by the caller that the type of the argument 744 * is the same as the type of each element of this class 745 * or is a matrix with one element. 746 * @param rightArgument The token that performs modulo on this token. 747 * @exception IllegalActionException If this operation is not 748 * supported by the derived class. 749 * @return A new Token containing the result. 750 */ 751 @Override 752 protected MatrixToken _moduloElement(Token rightArgument) 753 throws IllegalActionException { 754 int scalar; 755 if (rightArgument instanceof IntMatrixToken) { 756 if (((IntMatrixToken) rightArgument).getRowCount() != 1 757 || ((IntMatrixToken) rightArgument).getColumnCount() != 1) { 758 // Throw an exception. 759 return super._moduloElement(rightArgument); 760 } 761 scalar = ((IntMatrixToken) rightArgument).getElementAt(0, 0); 762 } else { 763 scalar = ((IntToken) rightArgument).intValue(); 764 } 765 int[] result = IntegerArrayMath.modulo(_value, scalar); 766 return new IntMatrixToken(result, _rowCount, _columnCount, DO_NOT_COPY); 767 } 768 769 /** Return a new token whose value is the value of this token 770 * multiplied by the value of the argument token. It is assumed 771 * that the type of the argument is IntMatrixToken. 772 * @param rightArgument The token to multiply this token by. 773 * @exception IllegalActionException If the units are not 774 * compatible, or this operation is not supported by the derived 775 * class. 776 * @return A new IntMatrixToken containing the result. 777 */ 778 @Override 779 protected MatrixToken _multiply(MatrixToken rightArgument) 780 throws IllegalActionException { 781 IntMatrixToken convertedArgument = (IntMatrixToken) rightArgument; 782 int[] A = _value; 783 int[] B = convertedArgument._getInternalIntArray(); 784 int m = _rowCount; 785 int n = _columnCount; 786 int p = convertedArgument.getColumnCount(); 787 int[] newMatrix = new int[m * p]; 788 int in = 0; 789 int ta = 0; 790 791 for (int i = 0; i < m; i++) { 792 ta += n; 793 794 for (int j = 0; j < p; j++) { 795 int sum = 0; 796 int ib = j; 797 798 for (int ia = i * n; ia < ta; ia++, ib += p) { 799 sum += A[ia] * B[ib]; 800 } 801 802 newMatrix[in++] = sum; 803 } 804 } 805 806 return new IntMatrixToken(newMatrix, m, p, DO_NOT_COPY); 807 } 808 809 /** Return a new token whose value is the value of this token 810 * multiplied by the value of the argument scalar token. 811 * @param rightArgument The token to multiply this token by. 812 * @exception IllegalActionException If this method is not 813 * supported by the derived class. 814 * @return A new IntMatrixToken containing the result. 815 */ 816 @Override 817 protected MatrixToken _multiplyElement(Token rightArgument) 818 throws IllegalActionException { 819 int scalar; 820 if (rightArgument instanceof IntMatrixToken) { 821 if (((IntMatrixToken) rightArgument).getRowCount() != 1 822 || ((IntMatrixToken) rightArgument).getColumnCount() != 1) { 823 // Throw an exception. 824 return super._moduloElement(rightArgument); 825 } 826 scalar = ((IntMatrixToken) rightArgument).getElementAt(0, 0); 827 } else { 828 scalar = ((IntToken) rightArgument).intValue(); 829 } 830 int[] result = IntegerArrayMath.multiply(_value, scalar); 831 return new IntMatrixToken(result, _rowCount, _columnCount, DO_NOT_COPY); 832 } 833 834 /** Return a new token whose value is the value of the argument token 835 * subtracted from the value of this token. It is assumed that the 836 * type of the argument is IntMatrixToken. 837 * @param rightArgument The token to subtract from this token. 838 * @exception IllegalActionException If the units are not 839 * compatible, or this operation is not supported by the derived 840 * class. 841 * @return A new IntMatrixToken containing the result. 842 */ 843 @Override 844 protected MatrixToken _subtract(MatrixToken rightArgument) 845 throws IllegalActionException { 846 IntMatrixToken convertedArgument = (IntMatrixToken) rightArgument; 847 int[] result = IntegerArrayMath.subtract(_value, 848 convertedArgument._getInternalIntArray()); 849 return new IntMatrixToken(result, _rowCount, _columnCount, DO_NOT_COPY); 850 } 851 852 /** Return a new token whose value is the value of the argument 853 * Token subtracted from the value of each element of this Token. It is 854 * assumed that the type of the argument is the same as the type 855 * of each element of this class or is a matrix with one element. 856 * @param rightArgument The token to subtract from this token. 857 * @exception IllegalActionException If this operation is not 858 * supported by the derived class. 859 * @return A new Token containing the result. 860 */ 861 @Override 862 protected MatrixToken _subtractElement(Token rightArgument) 863 throws IllegalActionException { 864 int scalar; 865 if (rightArgument instanceof IntMatrixToken) { 866 if (((IntMatrixToken) rightArgument).getRowCount() != 1 867 || ((IntMatrixToken) rightArgument).getColumnCount() != 1) { 868 // Throw an exception. 869 return super._moduloElement(rightArgument); 870 } 871 scalar = ((IntMatrixToken) rightArgument).getElementAt(0, 0); 872 } else { 873 scalar = ((IntToken) rightArgument).intValue(); 874 } 875 int[] result = IntegerArrayMath.add(_value, -scalar); 876 return new IntMatrixToken(result, _rowCount, _columnCount, DO_NOT_COPY); 877 } 878 879 /** Return a new token whose value is the value of the argument 880 * Token subtracted from the value of each element of this Token. It is 881 * assumed that the type of the argument is the same as the type 882 * of each element of this class or is a matrix with one element. 883 * @param rightArgument The token to subtract from this token. 884 * @exception IllegalActionException If this operation is not 885 * supported by the derived class. 886 * @return A new Token containing the result. 887 */ 888 @Override 889 protected MatrixToken _subtractElementReverse(Token rightArgument) 890 throws IllegalActionException { 891 int scalar; 892 if (rightArgument instanceof IntMatrixToken) { 893 if (((IntMatrixToken) rightArgument).getRowCount() != 1 894 || ((IntMatrixToken) rightArgument).getColumnCount() != 1) { 895 // Throw an exception. 896 return super._moduloElement(rightArgument); 897 } 898 scalar = ((IntMatrixToken) rightArgument).getElementAt(0, 0); 899 } else { 900 scalar = ((IntToken) rightArgument).intValue(); 901 } 902 int[] result = IntegerArrayMath 903 .negative(IntegerArrayMath.add(_value, -scalar)); 904 return new IntMatrixToken(result, _rowCount, _columnCount, DO_NOT_COPY); 905 } 906 907 /////////////////////////////////////////////////////////////////// 908 //// private methods //// 909 // Initialize the row and column count and copy the specified 910 // matrix. This method is used by the constructors. 911 private void _initialize(int[][] value) { 912 _rowCount = value.length; 913 _columnCount = value[0].length; 914 _value = IntegerMatrixMath.fromMatrixToArray(value); 915 } 916 917 /////////////////////////////////////////////////////////////////// 918 //// private variables //// 919 private int[] _value; 920 921 private int _rowCount; 922 923 private int _columnCount; 924}