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