001/* A token that contains a 2-D FixPoint matrix. 002 003 Copyright (c) 1998-2014 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 This class does not handle operations well, because the result may have 027 unusual precision. 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.FixPoint; 041import ptolemy.math.Precision; 042import ptolemy.math.Quantizer; 043 044/////////////////////////////////////////////////////////////////// 045//// FixMatrixToken 046 047/** 048 A token that contains a 2-D FixToken matrix. 049 050 @author Bart Kienhuis, Steve Neuendorffer 051 @version $Id$ 052 @since Ptolemy II 0.4 053 @Pt.ProposedRating Yellow (neuendor) 054 @Pt.AcceptedRating Yellow (kienhuis) 055 @see ptolemy.math.FixPoint 056 */ 057public class FixMatrixToken extends MatrixToken { 058 /** Construct a FixMatrixToken with a one by one matrix. The only 059 * element present in the matrix has value 0.0 and a precision of 060 * (32.0) which means 32 bits of which 0 bits are used for the 061 * fractional part. 062 */ 063 public FixMatrixToken() { 064 _rowCount = 1; 065 _columnCount = 1; 066 _precision = new Precision(32, 32); 067 _value = new FixPoint[1][1]; 068 _value[0][0] = Quantizer.round(0.0, _precision); 069 } 070 071 /** Construct a FixMatrixToken with the specified 2-D matrix. 072 * This method makes a copy of the matrix and stores the copy, 073 * so changes on the specified matrix after this token is 074 * constructed will not affect the content of this token. 075 * If any element of the specified matrix is null, then it 076 * is replaced with an element with value zero and precision 077 * the same as previous elements in the matrix. Note that the 078 * very first element cannot be null. 079 * @param value the 2D matrix of FixPoint values. 080 * @exception IllegalActionException If the precisions of the 081 * entries in the matrix are not all identical, or the specified 082 * matrix is null. 083 */ 084 public FixMatrixToken(FixPoint[][] value) throws IllegalActionException { 085 if (value == null) { 086 throw new IllegalActionException( 087 "FixMatrixToken: The specified " + "matrix is null."); 088 } 089 090 _initialize(value, null); 091 } 092 093 /** Construct a FixMatrixToken from the specified string. 094 * @param init A string expression of a 2-D fix matrix. 095 * @exception IllegalActionException If the string does 096 * not contain a parsable 2-D fix matrix. 097 */ 098 public FixMatrixToken(String init) throws IllegalActionException { 099 PtParser parser = new PtParser(); 100 ASTPtRootNode tree = parser.generateParseTree(init); 101 Token token = new ParseTreeEvaluator().evaluateParseTree(tree); 102 103 if (token instanceof FixMatrixToken) { 104 FixPoint[][] value = ((FixMatrixToken) token).fixMatrix(); 105 _initialize(value, null); 106 } else { 107 throw new IllegalActionException("A FixMatrixToken cannot be" 108 + " created from the expression '" + init + "'"); 109 } 110 } 111 112 /** Construct a FixMatrixToken with the specified 2-D matrix. 113 * This method makes a copy of the matrix and stores the copy, 114 * so changes on the specified matrix after this token is 115 * constructed will not affect the content of this token. 116 * If any element of the specified matrix is null, then it 117 * is replaced with an element with value zero and precision 118 * the same as previous elements in the matrix. Note that the 119 * very first element cannot be null. 120 * @param value the 2D matrix of FixPoint values. 121 * @param precision The precision to use. 122 * @exception IllegalActionException If the precisions of the 123 * entries in the matrix are not all identical, or the specified 124 * matrix is null. 125 */ 126 public FixMatrixToken(FixPoint[][] value, Precision precision) 127 throws IllegalActionException { 128 if (value == null) { 129 throw new IllegalActionException( 130 "FixMatrixToken: The specified " + "matrix is null."); 131 } 132 _initialize(value, precision); 133 } 134 135 /** Construct an FixMatrixToken from the specified array of 136 * tokens. The tokens in the array must be scalar tokens 137 * convertible into integers. 138 * @param tokens The array of tokens, which must contains 139 * rows*columns ScalarTokens. 140 * @param rows The number of rows in the matrix to be created. 141 * @param columns The number of columns in the matrix to be 142 * created. 143 * @exception IllegalActionException If the array of tokens is 144 * null, or the length of the array is not correct, or if one of 145 * the elements of the array is null, or if one of the elements 146 * of the array cannot be losslessly converted to a fixed point. 147 */ 148 public FixMatrixToken(Token[] tokens, int rows, int columns) 149 throws IllegalActionException { 150 if (tokens == null) { 151 throw new IllegalActionException( 152 "FixMatrixToken: The specified" + " array is null."); 153 } 154 155 if (tokens.length != rows * columns) { 156 throw new IllegalActionException("FixMatrixToken: The specified" 157 + " array is not of the correct length"); 158 } 159 160 _rowCount = rows; 161 _columnCount = columns; 162 _value = new FixPoint[rows][columns]; 163 164 for (int i = 0; i < tokens.length; i++) { 165 Token token = tokens[i]; 166 167 if (token instanceof ScalarToken) { 168 _value[i / columns][i % columns] = ((ScalarToken) token) 169 .fixValue(); 170 } else if (token instanceof FixToken) { 171 _value[i / columns][i % columns] = ((FixToken) token) 172 .fixValue(); 173 } else { 174 throw new IllegalActionException("FixMatrixToken: Element " + i 175 + " in the array with value " + token 176 + " is not a ScalarToken"); 177 } 178 } 179 } 180 181 /////////////////////////////////////////////////////////////////// 182 //// public methods //// 183 184 /** Convert the specified token into an instance of FixMatrixToken. 185 * This method does lossless conversion. 186 * If the argument is already an instance of FixMatrixToken, 187 * it is returned without any change. Otherwise, if the argument 188 * is below FixMatrixToken in the type hierarchy, it is converted to 189 * an instance of FixMatrixToken or one of the subclasses of 190 * FixMatrixToken and returned. If none of the above condition is 191 * met, an exception is thrown. 192 * @param token The token to be converted to a FixMatrixToken. 193 * @return A FixMatrixToken 194 * @exception IllegalActionException If the conversion cannot 195 * be carried out. 196 */ 197 public static FixMatrixToken convert(Token token) 198 throws IllegalActionException { 199 if (token instanceof FixMatrixToken) { 200 return (FixMatrixToken) token; 201 } 202 203 int compare = TypeLattice.compare(BaseType.FIX_MATRIX, token); 204 205 if (compare == CPO.LOWER || compare == CPO.INCOMPARABLE) { 206 throw new IllegalActionException( 207 notSupportedIncomparableConversionMessage(token, "[fix]")); 208 } 209 210 // try Fix 211 // compare = TypeLattice.compare(BaseType.FIX, token); 212 // if (compare == CPO.SAME || compare == CPO.HIGHER) { 213 // FixPoint[][] result = new FixPoint[1][1]; 214 // FixToken tem = FixToken.convert(token); 215 // result[0][0] = tem.fixValue(); 216 // return new FixMatrixToken(result); 217 // } 218 // The argument is below FixMatrixToken in the type hierarchy, 219 // but I don't recognize it. 220 throw new IllegalActionException( 221 notSupportedConversionMessage(token, "[fix]")); 222 } 223 224 /** Return a new matrix that is a sub-matrix of this matrix. 225 * @param rowStart The row to start on. 226 * @param colStart The column to start on. 227 * @param rowSpan The number of rows to copy. 228 * @param colSpan The number of columns to copy. 229 * @return a sub-matrix of this matrix. 230 * @exception IllegalActionException If the returned matrix is 231 * empty or if the specified parameters result in out of bounds 232 * accesses. 233 */ 234 @Override 235 public MatrixToken crop(int rowStart, int colStart, int rowSpan, 236 int colSpan) throws IllegalActionException { 237 FixPoint[][] value = this.fixMatrix(); 238 try { 239 FixPoint[][] result = new FixPoint[rowSpan][colSpan]; 240 for (int i = 0; i < rowSpan; i++) { 241 System.arraycopy(value[rowStart + i], colStart, result[i], 0, 242 colSpan); 243 } 244 return new FixMatrixToken(result); 245 } catch (ArrayIndexOutOfBoundsException ex) { 246 throw new IllegalActionException( 247 "Matrix crop indices out of bounds (rowStart = " + rowStart 248 + ", colStart = " + colStart + ", rowSpan = " 249 + rowSpan + ", colSpan = " + colSpan + ")."); 250 } 251 } 252 253 /** Return true if the argument is an instance of FixMatrixToken 254 * of the same dimensions and the corresponding elements of the matrices 255 * are equal. 256 * @param object An instance of Object. 257 * @return True if the argument is an instance of FixMatrixToken 258 * of the same dimensions and the corresponding elements of the 259 * matrices are equal. 260 */ 261 @Override 262 public boolean equals(Object object) { 263 if (object == null) { 264 return false; 265 } 266 // This test rules out instances of a subclass. 267 if (object.getClass() != getClass()) { 268 return false; 269 } 270 271 FixMatrixToken matrixArgument = (FixMatrixToken) object; 272 273 if (_rowCount != matrixArgument.getRowCount()) { 274 return false; 275 } 276 277 if (_columnCount != matrixArgument.getColumnCount()) { 278 return false; 279 } 280 281 FixPoint[][] matrix = matrixArgument.fixMatrix(); 282 283 for (int i = 0; i < _rowCount; i++) { 284 for (int j = 0; j < _columnCount; j++) { 285 if (!_value[i][j].equals(matrix[i][j])) { 286 return false; 287 } 288 } 289 } 290 291 return true; 292 } 293 294 /** Return the content of this token as a new 2-D FixPoint matrix. 295 * @return A 2-D FixPoint matrix 296 */ 297 @Override 298 public FixPoint[][] fixMatrix() { 299 FixPoint[][] matrix = new FixPoint[_rowCount][_columnCount]; 300 301 for (int i = 0; i < _rowCount; i++) { 302 for (int j = 0; j < _columnCount; j++) { 303 // FixPoint is immutable, so no need to copy. 304 matrix[i][j] = _value[i][j]; 305 } 306 } 307 308 return matrix; 309 } 310 311 /** Return the number of columns in the matrix. 312 * @return The number of columns in the matrix. 313 */ 314 @Override 315 public int getColumnCount() { 316 return _columnCount; 317 } 318 319 /** Return the element of the matrix at the specified 320 * row and column in a FixToken. 321 * @param row The row index of the desired element. 322 * @param column The column index of the desired element. 323 * @return A FixToken containing the matrix element. 324 * @exception ArrayIndexOutOfBoundsException If the specified 325 * row or column number is outside the range of the matrix. 326 */ 327 @Override 328 public Token getElementAsToken(int row, int column) 329 throws ArrayIndexOutOfBoundsException { 330 return new FixToken(_value[row][column]); 331 } 332 333 /** Return the element of the contained matrix at the specified 334 * row and column. 335 * @param row The row index of the desired element. 336 * @param column The column index of the desired element. 337 * @return The FixPoint at the specified matrix entry. 338 * @exception ArrayIndexOutOfBoundsException If the specified 339 * row or column number is outside the range of the matrix. 340 */ 341 public FixPoint getElementAt(int row, int column) { 342 return _value[row][column]; 343 } 344 345 /** Return the Type of the tokens contained in this matrix token. 346 * This must be a type representing a scalar token. 347 * @return BaseType.UNSIZED_FIX. 348 */ 349 @Override 350 public Type getElementType() { 351 return BaseType.UNSIZED_FIX; 352 } 353 354 /** Return the number of rows in the matrix. 355 * @return The number of rows in the matrix. 356 */ 357 @Override 358 public int getRowCount() { 359 return _rowCount; 360 } 361 362 /** Return the type of this token. 363 * @return BaseType.FIX_MATRIX 364 */ 365 @Override 366 public Type getType() { 367 return BaseType.FIX_MATRIX; 368 } 369 370 /** Return a hash code value for this token. This method returns the 371 * integer portion of the sum of the elements. 372 * @return A hash code value for this token. 373 */ 374 @Override 375 public int hashCode() { 376 double code = 0.0; 377 378 for (int i = 0; i < _rowCount; i++) { 379 for (int j = 0; j < _columnCount; j++) { 380 code += _value[i][j].doubleValue(); 381 } 382 } 383 384 return (int) code; 385 } 386 387 /** Join a matrix of matrices into a single matrix by tiling. 388 * All matrices in the matrix must be of the same type, 389 * the same type as this matrix. But none of them needs to 390 * actually be this matrix. This base class simply throws 391 * an exception. Derived classes provide the implementation. 392 * The number of columns in the resulting matrix is the sum 393 * of the number of columns in the first row of the argument. 394 * The number of rows in the resulting matrix is the sum 395 * of the number of rows in the first column of the argument. 396 * The matrices are copied into the result starting at the 397 * position determined by the first row or column. 398 * If the matrices overlap, then while copying left to right, 399 * top-to-bottom, data will be overwritten. If there are gaps, 400 * the resulting matrix will be filled with zeros. 401 * @param matrices A two-dimensional array of matrix tokens. 402 * @return A new matrix token of the same type as the elements 403 * in the input matrix of matrix tokens. 404 * @exception IllegalActionException If the types of the matrices 405 * in the input are not all the same, or if tiling fails due 406 * to size incompatibilities, or if the input matrix has no 407 * tokens. 408 */ 409 @Override 410 public MatrixToken join(MatrixToken[][] matrices) 411 throws IllegalActionException { 412 if (matrices == null || matrices.length == 0 413 || matrices[0].length == 0) { 414 throw new IllegalActionException("matrixJoin: No input matrices."); 415 } 416 // Calculate the size of the result. 417 // This assumes the matrices tile. 418 int rows = 0; 419 int columns = 0; 420 for (MatrixToken[] matrice : matrices) { 421 rows += matrice[0].getRowCount(); 422 } 423 for (int j = 0; j < matrices[0].length; j++) { 424 columns += matrices[0][j].getColumnCount(); 425 } 426 FixPoint[][] tiled = new FixPoint[rows][columns]; 427 int row = 0; 428 for (int i = 0; i < matrices.length; i++) { 429 int column = 0; 430 for (int j = 0; j < matrices[i].length; j++) { 431 if (!(matrices[i][j] instanceof FixMatrixToken)) { 432 throw new IllegalActionException( 433 "matrixJoin: matrices not all of the same type."); 434 } 435 int rowCount = matrices[i][j].getRowCount(); 436 if (row + rowCount > rows) { 437 rowCount = rows - row; 438 } 439 int columnCount = matrices[i][j].getColumnCount(); 440 if (column + columnCount > columns) { 441 columnCount = columns - column; 442 } 443 // There is no FixMatrixMath class, so we need 444 // to implement the matrix copy here. 445 for (int ii = 0; ii < rowCount; ii++) { 446 System.arraycopy(matrices[i][j].fixMatrix()[ii], 0, 447 tiled[row + ii], column, columnCount); 448 } 449 // Starting position for the next column. 450 column += matrices[0][j].getColumnCount(); 451 } 452 // Starting position for the next column. 453 row += matrices[i][0].getRowCount(); 454 } 455 return new FixMatrixToken(tiled); 456 } 457 458 /** Split this matrix into multiple matrices. See the base 459 * class for documentation. 460 * @param rows The number of rows per submatrix. 461 * @param columns The number of columns per submatrix. 462 * @return An array of matrix tokens. 463 */ 464 @Override 465 public MatrixToken[][] split(int[] rows, int[] columns) { 466 MatrixToken[][] result = new MatrixToken[rows.length][columns.length]; 467 FixPoint[][] source = fixMatrix(); 468 int row = 0; 469 for (int i = 0; i < rows.length; i++) { 470 int column = 0; 471 for (int j = 0; j < columns.length; j++) { 472 FixPoint[][] contents = new FixPoint[rows[i]][columns[j]]; 473 int rowspan = rows[i]; 474 if (row + rowspan > source.length) { 475 rowspan = source.length - row; 476 } 477 int columnspan = columns[j]; 478 if (column + columnspan > source[0].length) { 479 columnspan = source[0].length - column; 480 } 481 if (columnspan > 0 && rowspan > 0) { 482 // There is no FixPointMatrixMath class, so we need 483 // to implement the matrix copy here. 484 for (int ii = 0; ii < rowspan; ii++) { 485 System.arraycopy(source[row + ii], column, contents[ii], 486 0, columnspan); 487 } 488 } 489 column += columns[j]; 490 try { 491 // Use the precision of the (0,0) element because the entire submatrix 492 // may be zero, in which case the precision cannot be inferred. 493 result[i][j] = new FixMatrixToken(contents, 494 getElementAt(0, 0).getPrecision()); 495 } catch (IllegalActionException e) { 496 throw new InternalErrorException(e); 497 } 498 } 499 row += rows[i]; 500 } 501 return result; 502 } 503 504 /** Return a new Token representing the left multiplicative 505 * identity with the same precision as the current 506 * FixMatrixToken. The returned token contains an identity matrix 507 * whose dimensions are the same as the number of rows of the 508 * matrix contained in this token. 509 * @return A new FixMatrixToken containing the left multiplicative 510 * identity. 511 */ 512 @Override 513 public Token one() { 514 FixPoint[][] result = new FixPoint[_rowCount][_rowCount]; 515 516 for (int i = 0; i < _rowCount; i++) { 517 for (int j = 0; j < _rowCount; j++) { 518 result[i][j] = Quantizer.round(0.0, _precision); 519 } 520 521 result[i][i] = Quantizer.round(1.0, _precision); 522 } 523 524 try { 525 return new FixMatrixToken(result); 526 } catch (IllegalActionException ex) { 527 // precisions are all the same, so this should not be thrown. 528 throw new InternalErrorException("Unequal precisions!"); 529 } 530 } 531 532 /** Return a new Token representing the right multiplicative 533 * identity with the same precision as the current 534 * FixMatrixToken.. The returned token contains an identity 535 * matrix whose dimensions are the same as the number of columns of 536 * the matrix contained in this token. 537 * @return A new FixMatrixToken containing the right multiplicative 538 * identity. 539 */ 540 @Override 541 public Token oneRight() { 542 FixPoint[][] result = new FixPoint[_columnCount][_columnCount]; 543 544 for (int i = 0; i < _columnCount; i++) { 545 for (int j = 0; j < _columnCount; j++) { 546 result[i][j] = Quantizer.round(0.0, _precision); 547 } 548 549 result[i][i] = Quantizer.round(0.0, _precision); 550 } 551 552 try { 553 return new FixMatrixToken(result); 554 } catch (IllegalActionException ex) { 555 // precisions are all the same, so this should not be thrown. 556 throw new InternalErrorException("Unequal precisions!"); 557 } 558 } 559 560 /** Return a new Token representing the additive identity with the 561 * same precision as the current FixMatrixToken. The returned 562 * token contains a matrix whose elements are all zero, and the 563 * size of the matrix is the same as the matrix contained in this 564 * token. 565 * @return A new FixMatrixToken containing the additive identity. 566 */ 567 @Override 568 public Token zero() { 569 FixPoint[][] result = new FixPoint[_rowCount][_columnCount]; 570 FixPoint zero = Quantizer.round(0.0, _precision); 571 572 for (int i = 0; i < _rowCount; i++) { 573 for (int j = 0; j < _columnCount; j++) { 574 result[i][j] = zero; 575 } 576 } 577 578 try { 579 return new FixMatrixToken(result); 580 } catch (IllegalActionException ex) { 581 // precisions are all the same, so this should not be thrown. 582 throw new InternalErrorException("Unequal precisions!"); 583 } 584 } 585 586 /////////////////////////////////////////////////////////////////// 587 //// protected methods //// 588 589 /** Return a new token whose value is the value of the argument 590 * Token added to the value of this Token. It is assumed that 591 * the type of the argument is FixMatrixToken. 592 * @param rightArgument The token to add to this token. 593 * @exception IllegalActionException If the units are not 594 * compatible, or this operation is not supported by the derived 595 * class. 596 * @return A new FixMatrixToken containing the result. 597 */ 598 @Override 599 protected MatrixToken _add(MatrixToken rightArgument) 600 throws IllegalActionException { 601 FixMatrixToken convertedArgument = (FixMatrixToken) rightArgument; 602 FixPoint[][] result = convertedArgument.fixMatrix(); 603 604 for (int i = 0; i < _rowCount; i++) { 605 for (int j = 0; j < _columnCount; j++) { 606 result[i][j] = result[i][j].add(_value[i][j]); 607 } 608 } 609 610 return new FixMatrixToken(result); 611 } 612 613 /** Return a new token whose value is the value of the argument 614 * Token added from the value of each element of this Token. It is 615 * assumed that the type of the argument is the same as the type 616 * of each element of this class or is a matrix with one element. 617 * @param rightArgument The token to add from this token. 618 * @exception IllegalActionException If this operation is not 619 * supported by the derived class. 620 * @return A new Token containing the result. 621 */ 622 @Override 623 protected MatrixToken _addElement(Token rightArgument) 624 throws IllegalActionException { 625 FixPoint scalar; 626 if (rightArgument instanceof FixMatrixToken) { 627 if (((FixMatrixToken) rightArgument).getRowCount() != 1 628 || ((FixMatrixToken) rightArgument).getColumnCount() != 1) { 629 // Throw an exception. 630 return super._moduloElement(rightArgument); 631 } 632 scalar = ((FixMatrixToken) rightArgument).getElementAt(0, 0); 633 } else { 634 scalar = ((FixToken) rightArgument).fixValue(); 635 } 636 FixPoint[][] result = fixMatrix(); 637 638 for (int i = 0; i < _rowCount; i++) { 639 for (int j = 0; j < _columnCount; j++) { 640 result[i][j] = result[i][j].add(scalar); 641 } 642 } 643 644 return new FixMatrixToken(result); 645 } 646 647 /** Return a new token whose value is the value of this token 648 * multiplied by the value of the argument token. It is assumed 649 * that the type of the argument is FixMatrixToken. 650 * @param rightArgument The token to multiply this token by. 651 * @return A new FixMatrixToken containing the result. 652 * @exception IllegalActionException If the units are not 653 * compatible, or if the matrix dimensions are incompatible. 654 */ 655 @Override 656 protected MatrixToken _multiply(MatrixToken rightArgument) 657 throws IllegalActionException { 658 FixMatrixToken convertedArgument = (FixMatrixToken) rightArgument; 659 660 if (_columnCount != convertedArgument._rowCount) { 661 throw new IllegalActionException( 662 "Matrix dimensions are not compatible. Cannot multiply."); 663 } 664 665 FixPoint[][] result = new FixPoint[_rowCount][convertedArgument._columnCount]; 666 667 for (int i = 0; i < _rowCount; i++) { 668 for (int j = 0; j < convertedArgument._columnCount; j++) { 669 FixPoint sum = _value[i][0] 670 .multiply(convertedArgument._value[0][j]); 671 672 for (int k = 1; k < _columnCount; k++) { 673 sum = sum.add(_value[i][k] 674 .multiply(convertedArgument._value[k][j])); 675 } 676 677 result[i][j] = sum; 678 } 679 } 680 681 return new FixMatrixToken(result); 682 } 683 684 /** Return a new token whose value is the value of the argument 685 * Token multiplyed from the value of each element of this Token. It is 686 * assumed that the type of the argument is the same as the type 687 * of each element of this class or is a matrix with one element. 688 * @param rightArgument The token to multiply from this token. 689 * @exception IllegalActionException If this operation is not 690 * supported by the derived class. 691 * @return A new Token containing the result. 692 */ 693 @Override 694 protected MatrixToken _multiplyElement(Token rightArgument) 695 throws IllegalActionException { 696 FixPoint scalar; 697 if (rightArgument instanceof FixMatrixToken) { 698 if (((FixMatrixToken) rightArgument).getRowCount() != 1 699 || ((FixMatrixToken) rightArgument).getColumnCount() != 1) { 700 // Throw an exception. 701 return super._moduloElement(rightArgument); 702 } 703 scalar = ((FixMatrixToken) rightArgument).getElementAt(0, 0); 704 } else { 705 scalar = ((FixToken) rightArgument).fixValue(); 706 } 707 FixPoint[][] result = fixMatrix(); 708 709 for (int i = 0; i < _rowCount; i++) { 710 for (int j = 0; j < _columnCount; j++) { 711 // System.out.println("left = " + result[i][j] + ", " 712 // + result[i][j].getPrecision()); 713 // System.out.println("right = " + scalar + ", " 714 // + scalar.getPrecision()); 715 result[i][j] = result[i][j].multiply(scalar); 716 717 // System.out.println("result = " + result[i][j] + ", " 718 // + result[i][j].getPrecision()); 719 } 720 } 721 722 return new FixMatrixToken(result); 723 } 724 725 /** Return a new token whose value is the value of the argument 726 * Token subtracted to the value of this Token. It is assumed that 727 * the type of the argument is FixMatrixToken. 728 * @param rightArgument The token to subtract to this token. 729 * @exception IllegalActionException If the units are not 730 * compatible, or this operation is not supported by the derived 731 * class. 732 * @return A new FixMatrixToken containing the result. 733 */ 734 @Override 735 protected MatrixToken _subtract(MatrixToken rightArgument) 736 throws IllegalActionException { 737 FixMatrixToken convertedArgument = (FixMatrixToken) rightArgument; 738 FixPoint[][] result = convertedArgument.fixMatrix(); 739 740 for (int i = 0; i < _rowCount; i++) { 741 for (int j = 0; j < _columnCount; j++) { 742 result[i][j] = result[i][j].subtract(_value[i][j]); 743 } 744 } 745 746 return new FixMatrixToken(result); 747 } 748 749 /** Return a new token whose value is the value of the argument 750 * Token subtracted from the value of each element of this Token. It is 751 * assumed that the type of the argument is the same as the type 752 * of each element of this class or is a matrix with one element. 753 * @param rightArgument The token to subtract from this token. 754 * @exception IllegalActionException If this operation is not 755 * supported by the derived class. 756 * @return A new Token containing the result. 757 */ 758 @Override 759 protected MatrixToken _subtractElement(Token rightArgument) 760 throws IllegalActionException { 761 FixPoint scalar; 762 if (rightArgument instanceof FixMatrixToken) { 763 if (((FixMatrixToken) rightArgument).getRowCount() != 1 764 || ((FixMatrixToken) rightArgument).getColumnCount() != 1) { 765 // Throw an exception. 766 return super._moduloElement(rightArgument); 767 } 768 scalar = ((FixMatrixToken) rightArgument).getElementAt(0, 0); 769 } else { 770 scalar = ((FixToken) rightArgument).fixValue(); 771 } 772 FixPoint[][] result = fixMatrix(); 773 774 for (int i = 0; i < _rowCount; i++) { 775 for (int j = 0; j < _columnCount; j++) { 776 result[i][j] = result[i][j].subtract(scalar); 777 } 778 } 779 780 return new FixMatrixToken(result); 781 } 782 783 /** Return a new token whose value is the value of the argument 784 * Token subtracted from the value of each element of this Token. It is 785 * assumed that the type of the argument is the same as the type 786 * of each element of this class or is a matrix with one element. 787 * @param rightArgument The token to subtract from this token. 788 * @exception IllegalActionException If this operation is not 789 * supported by the derived class. 790 * @return A new Token containing the result. 791 */ 792 @Override 793 protected MatrixToken _subtractElementReverse(Token rightArgument) 794 throws IllegalActionException { 795 FixPoint scalar; 796 if (rightArgument instanceof FixMatrixToken) { 797 if (((FixMatrixToken) rightArgument).getRowCount() != 1 798 || ((FixMatrixToken) rightArgument).getColumnCount() != 1) { 799 // Throw an exception. 800 return super._moduloElement(rightArgument); 801 } 802 scalar = ((FixMatrixToken) rightArgument).getElementAt(0, 0); 803 } else { 804 scalar = ((FixToken) rightArgument).fixValue(); 805 } 806 FixPoint[][] result = fixMatrix(); 807 808 for (int i = 0; i < _rowCount; i++) { 809 for (int j = 0; j < _columnCount; j++) { 810 result[i][j] = scalar.subtract(result[i][j]); 811 } 812 } 813 814 return new FixMatrixToken(result); 815 } 816 817 /////////////////////////////////////////////////////////////////// 818 //// private methods //// 819 820 /** Initialize the row and column count and copy the specified 821 * matrix. This method is used by the constructors. 822 * @param value The value. 823 * @param precision The precision, or null to infer it from the values. 824 */ 825 private void _initialize(FixPoint[][] value, Precision precision) 826 throws IllegalActionException { 827 _rowCount = value.length; 828 _columnCount = value[0].length; 829 _value = new FixPoint[_rowCount][_columnCount]; 830 831 for (int i = 0; i < _rowCount; i++) { 832 for (int j = 0; j < _columnCount; j++) { 833 _value[i][j] = value[i][j]; 834 if (_value[i][j] == null) { 835 // NOTE: This requires that the very first element 836 // must be non-null, in order to set the precision, 837 // or that the precision be provided in the argument. 838 _value[i][j] = Quantizer.round(0.0, precision); 839 } 840 if (precision == null) { 841 precision = _value[i][j].getPrecision(); 842 } 843 844 if (_precision != null && !_precision.equals(precision)) { 845 throw new IllegalActionException( 846 "Attempt to create a FixMatrixToken" 847 + " with unequal precisions: " + _precision 848 + " and " + precision); 849 } 850 851 _precision = precision; 852 } 853 } 854 } 855 856 /////////////////////////////////////////////////////////////////// 857 //// private variables //// 858 // The 2D matrix of FixPoints. 859 private FixPoint[][] _value = null; 860 861 // The precision of all entries in the FixPoint matrix. 862 private Precision _precision = null; 863 864 // The number of rows of the matrix. 865 private int _rowCount = 0; 866 867 // The number of column of the matrix. 868 private int _columnCount = 0; 869}