001/* A library for mathematical operations on matrices of ints. 002 003 Some algorithms are from 004 005 [1] Embree, Paul M. and Bruce Kimble. "C Language Algorithms for Digital 006 Signal Processing". Prentice Hall. Englewood Cliffs, NJ, 1991. 007 008 Copyright (c) 1998-2018 The Regents of the University of California. 009 All rights reserved. 010 011 Permission is hereby granted, without written agreement and without 012 license or royalty fees, to use, copy, modify, and distribute this 013 software and its documentation for any purpose, provided that the above 014 copyright notice and the following two paragraphs appear in all copies 015 of this software. 016 017 IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY 018 FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES 019 ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF 020 THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF 021 SUCH DAMAGE. 022 023 THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, 024 INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 025 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE 026 PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF 027 CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, 028 ENHANCEMENTS, OR MODIFICATIONS. 029 030 PT_COPYRIGHT_VERSION_2 031 COPYRIGHTENDKEY 032 033 */ 034package ptolemy.math; 035 036////////////////////////////////////////////////////////////////////////// 037//// IntegerMatrixMath 038 039/** 040 This class provides a library for mathematical operations on 041 matrices of ints. 042 043 Rows and column numbers of matrices are specified with zero-based indices. 044 All calls expect matrix arguments to be non-null. In addition, all 045 rows of the matrix are expected to have the same number of columns. 046 047 @author Jeff Tsay 048 @version $Id$ 049 @since Ptolemy II 1.0 050 @Pt.ProposedRating Yellow (ctsay) 051 @Pt.AcceptedRating Yellow (ctsay) 052 */ 053public class IntegerMatrixMath { 054 // private constructor prevents construction of this class. 055 private IntegerMatrixMath() { 056 } 057 058 /** Return a new matrix that is constructed from the argument by 059 * adding the second argument to every element. 060 * @param matrix A matrix of ints. 061 * @param z The int number to add. 062 * @return A new matrix of ints. 063 */ 064 public static final int[][] add(int[][] matrix, int z) { 065 int[][] returnValue = new int[_rows(matrix)][_columns(matrix)]; 066 067 for (int i = 0; i < _rows(matrix); i++) { 068 for (int j = 0; j < _columns(matrix); j++) { 069 returnValue[i][j] = matrix[i][j] + z; 070 } 071 } 072 073 return returnValue; 074 } 075 076 /** Return a new matrix that is constructed from the argument by 077 * adding the second matrix to the first one. If the two 078 * matrices are not the same size, throw an 079 * IllegalArgumentException. 080 * @param matrix1 The first matrix of ints. 081 * @param matrix2 The second matrix of ints. 082 * @return A new matrix of ints. */ 083 public static final int[][] add(final int[][] matrix1, 084 final int[][] matrix2) { 085 _checkSameDimension("add", matrix1, matrix2); 086 087 int[][] returnValue = new int[_rows(matrix1)][_columns(matrix1)]; 088 089 for (int i = 0; i < _rows(matrix1); i++) { 090 for (int j = 0; j < _columns(matrix1); j++) { 091 returnValue[i][j] = matrix1[i][j] + matrix2[i][j]; 092 } 093 } 094 095 return returnValue; 096 } 097 098 /** Return a new matrix that is a copy of the matrix argument. 099 * @param matrix A matrix of ints. 100 * @return A new matrix of ints. 101 */ 102 public static final int[][] allocCopy(final int[][] matrix) { 103 return crop(matrix, 0, 0, _rows(matrix), _columns(matrix)); 104 } 105 106 /** Return a new array that is formed by applying an instance of a 107 * IntegerBinaryOperation to each element in the input matrix, 108 * using z as the left operand in all cases and the matrix elements 109 * as the right operands (op.operate(z, matrix[i][j])). 110 */ 111 public static final int[][] applyBinaryOperation(IntegerBinaryOperation op, 112 final int z, final int[][] matrix) { 113 int rows = _rows(matrix); 114 int columns = _columns(matrix); 115 116 int[][] returnValue = new int[rows][columns]; 117 118 for (int i = 0; i < rows; i++) { 119 for (int j = 0; j < columns; j++) { 120 returnValue[i][j] = op.operate(z, matrix[i][j]); 121 } 122 } 123 124 return returnValue; 125 } 126 127 /** Return a new array that is formed by applying an instance of a 128 * IntegerBinaryOperation to each element in the input matrix, 129 * using the matrix elements as the left operands and z as the right 130 * operand in all cases (op.operate(matrix[i][j], z)). 131 */ 132 public static final int[][] applyBinaryOperation(IntegerBinaryOperation op, 133 final int[][] matrix, final int z) { 134 int rows = _rows(matrix); 135 int columns = _columns(matrix); 136 137 int[][] returnValue = new int[rows][columns]; 138 139 for (int i = 0; i < rows; i++) { 140 for (int j = 0; j < columns; j++) { 141 returnValue[i][j] = op.operate(matrix[i][j], z); 142 } 143 } 144 145 return returnValue; 146 } 147 148 /** Return a new array that is formed by applying an instance of a 149 * IntegerBinaryOperation to the two matrices, element by 150 * element, using the elements of the first matrix as the left 151 * operands and the elements of the second matrix as the right 152 * operands. (op.operate(matrix1[i][j], matrix2[i][j])). If the 153 * matrices are not the same size, throw an 154 * IllegalArgumentException. 155 */ 156 public static final int[][] applyBinaryOperation(IntegerBinaryOperation op, 157 final int[][] matrix1, final int[][] matrix2) { 158 int rows = _rows(matrix1); 159 int columns = _columns(matrix1); 160 161 _checkSameDimension("applyBinaryOperation", matrix1, matrix2); 162 163 int[][] returnValue = new int[rows][columns]; 164 165 for (int i = 0; i < rows; i++) { 166 for (int j = 0; j < columns; j++) { 167 returnValue[i][j] = op.operate(matrix1[i][j], matrix2[i][j]); 168 } 169 } 170 171 return returnValue; 172 } 173 174 /** Return a new array that is formed by applying an instance of a 175 * IntegerUnaryOperation to each element in the input matrix 176 * (op.operate(matrix[i][j])). 177 */ 178 public static final int[][] applyUnaryOperation( 179 final IntegerUnaryOperation op, final int[][] matrix) { 180 int rows = _rows(matrix); 181 int columns = _columns(matrix); 182 183 int[][] returnValue = new int[rows][columns]; 184 185 for (int i = 0; i < rows; i++) { 186 for (int j = 0; j < columns; j++) { 187 returnValue[i][j] = op.operate(matrix[i][j]); 188 } 189 } 190 191 return returnValue; 192 } 193 194 /** Return a new matrix that is the formed by bitwise ANDing z 195 * with each element of the input matrix (matrix[i][j] & z). 196 */ 197 public static final int[][] bitwiseAnd(final int[][] matrix, final int z) { 198 int rows = _rows(matrix); 199 int columns = _columns(matrix); 200 201 int[][] returnValue = new int[rows][columns]; 202 203 for (int i = 0; i < rows; i++) { 204 for (int j = 0; j < columns; j++) { 205 returnValue[i][j] = matrix[i][j] & z; 206 } 207 } 208 209 return returnValue; 210 } 211 212 /** Return a new array that is the element-by-element bitwise AND 213 * of the two input matrices (matrix1[i][j] & matrix2[i][j]). If 214 * the two matrices are not the same size, throw an 215 * IllegalArgumentException. 216 */ 217 public static final int[][] bitwiseAnd(final int[][] matrix1, 218 final int[][] matrix2) { 219 int rows = _rows(matrix1); 220 int columns = _columns(matrix1); 221 222 _checkSameDimension("bitwiseAnd", matrix1, matrix2); 223 224 int[][] returnValue = new int[rows][columns]; 225 226 for (int i = 0; i < rows; i++) { 227 for (int j = 0; j < columns; j++) { 228 returnValue[i][j] = matrix1[i][j] & matrix2[i][j]; 229 } 230 } 231 232 return returnValue; 233 } 234 235 /** Return a new array that formed by the bitwise complement of 236 * each element in the input matrix (~matrix[i][j]). 237 */ 238 public static final int[][] bitwiseComplement(final int[][] matrix) { 239 int rows = _rows(matrix); 240 int columns = _columns(matrix); 241 242 int[][] returnValue = new int[rows][columns]; 243 244 for (int i = 0; i < rows; i++) { 245 for (int j = 0; j < columns; j++) { 246 returnValue[i][j] = ~matrix[i][j]; 247 } 248 } 249 250 return returnValue; 251 } 252 253 /** Return a new matrix that is the formed by bitwise ORing z with 254 * each element of the input matrix (matrix[i][j] | z). 255 256 */ 257 public static final int[][] bitwiseOr(final int[][] matrix, final int z) { 258 int rows = _rows(matrix); 259 int columns = _columns(matrix); 260 261 int[][] returnValue = new int[rows][columns]; 262 263 for (int i = 0; i < rows; i++) { 264 for (int j = 0; j < columns; j++) { 265 returnValue[i][j] = matrix[i][j] | z; 266 } 267 } 268 269 return returnValue; 270 } 271 272 /** Return a new array that is the element-by-element bitwise OR 273 * of the two input matrices (matrix1[i][j] | matrix2[i][j]). If 274 * the two matrices are not the same size, throw an 275 * IllegalArgumentException. 276 */ 277 public static final int[][] bitwiseOr(final int[][] matrix1, 278 final int[][] matrix2) { 279 int rows = _rows(matrix1); 280 int columns = _columns(matrix1); 281 282 _checkSameDimension("bitwiseOr", matrix1, matrix2); 283 284 int[][] returnValue = new int[rows][columns]; 285 286 for (int i = 0; i < rows; i++) { 287 for (int j = 0; j < columns; j++) { 288 returnValue[i][j] = matrix1[i][j] | matrix2[i][j]; 289 } 290 } 291 292 return returnValue; 293 } 294 295 /** Return a new matrix that is the formed by bitwise XORing z 296 * with each element of the input matrix (matrix[i][j] ^ z). 297 */ 298 public static final int[][] bitwiseXor(final int[][] matrix, final int z) { 299 int rows = _rows(matrix); 300 int columns = _columns(matrix); 301 302 int[][] returnValue = new int[rows][columns]; 303 304 for (int i = 0; i < rows; i++) { 305 for (int j = 0; j < columns; j++) { 306 returnValue[i][j] = matrix[i][j] ^ z; 307 } 308 } 309 310 return returnValue; 311 } 312 313 /** Return a new array that is the element-by-element bitwise XOR 314 * of the two input matrices (matrix1[i][j] & matrix2[i][j]). If 315 * the two matrices are not the same size, throw an 316 * IllegalArgumentException. 317 */ 318 public static final int[][] bitwiseXor(final int[][] matrix1, 319 final int[][] matrix2) { 320 int rows = _rows(matrix1); 321 int columns = _columns(matrix1); 322 323 _checkSameDimension("bitwiseXor", matrix1, matrix2); 324 325 int[][] returnValue = new int[rows][columns]; 326 327 for (int i = 0; i < rows; i++) { 328 for (int j = 0; j < columns; j++) { 329 returnValue[i][j] = matrix1[i][j] ^ matrix2[i][j]; 330 } 331 } 332 333 return returnValue; 334 } 335 336 /** Return a new matrix that is a sub-matrix of the input 337 * matrix argument. The row and column from which to start 338 * and the number of rows and columns to span are specified. 339 * @param matrix A matrix of ints. 340 * @param rowStart An int specifying which row to start on. 341 * @param colStart An int specifying which column to start on. 342 * @param rowSpan An int specifying how many rows to copy. 343 * @param colSpan An int specifying how many columns to copy. 344 */ 345 public static final int[][] crop(final int[][] matrix, final int rowStart, 346 final int colStart, final int rowSpan, final int colSpan) { 347 int[][] returnValue = new int[rowSpan][colSpan]; 348 349 for (int i = 0; i < rowSpan; i++) { 350 System.arraycopy(matrix[rowStart + i], colStart, returnValue[i], 0, 351 colSpan); 352 } 353 354 return returnValue; 355 } 356 357 /** Return a new matrix that is constructed by placing the 358 * elements of the input array on the diagonal of the square 359 * matrix, starting from the top left corner down to the bottom 360 * right corner. All other elements are zero. The size of of the 361 * matrix is n x n, where n is the length of the input array. 362 */ 363 public static final int[][] diag(final int[] array) { 364 int n = array.length; 365 366 int[][] returnValue = new int[n][n]; 367 368 // Assume the matrix is zero-filled. 369 for (int i = 0; i < n; i++) { 370 returnValue[i][i] = array[i]; 371 } 372 373 return returnValue; 374 } 375 376 /** Return a new matrix that is constructed from the argument by 377 * dividing the second argument to every element. 378 * @param matrix A matrix of ints. 379 * @param z The int number to divide. 380 * @return A new matrix of ints. 381 */ 382 public static final int[][] divide(int[][] matrix, int z) { 383 int[][] returnValue = new int[_rows(matrix)][_columns(matrix)]; 384 385 for (int i = 0; i < _rows(matrix); i++) { 386 for (int j = 0; j < _columns(matrix); j++) { 387 returnValue[i][j] = matrix[i][j] / z; 388 } 389 } 390 391 return returnValue; 392 } 393 394 /** Return a new matrix that is constructed by element by element 395 * division of the two matrix arguments. Each element of the 396 * first matrix is divided by the corresponding element of the 397 * second matrix. If the two matrices are not the same size, 398 * throw an IllegalArgumentException. 399 */ 400 public static final int[][] divideElements(final int[][] matrix1, 401 final int[][] matrix2) { 402 int rows = _rows(matrix1); 403 int columns = _columns(matrix1); 404 405 _checkSameDimension("divideElements", matrix1, matrix2); 406 407 int[][] returnValue = new int[rows][columns]; 408 409 for (int i = 0; i < rows; i++) { 410 for (int j = 0; j < columns; j++) { 411 returnValue[i][j] = matrix1[i][j] / matrix2[i][j]; 412 } 413 } 414 415 return returnValue; 416 } 417 418 /** Return a new array that is filled with the contents of the matrix. 419 * The ints are stored row by row, i.e. using the notation 420 * (row, column), the entries of the array are in the following order 421 * for a (m, n) matrix : 422 * (0, 0), (0, 1), (0, 2), ... , (0, n-1), (1, 0), (1, 1), ..., (m-1)(n-1) 423 * @param matrix A matrix of ints. 424 * @return A new array of ints. 425 */ 426 public static final int[] fromMatrixToArray(final int[][] matrix) { 427 return fromMatrixToArray(matrix, _rows(matrix), _columns(matrix)); 428 } 429 430 /** Return a new array that is filled with the contents of the matrix. 431 * The maximum numbers of rows and columns to copy are specified so 432 * that entries lying outside of this range can be ignored. The 433 * maximum rows to copy cannot exceed the number of rows in the matrix, 434 * and the maximum columns to copy cannot exceed the number of columns 435 * in the matrix. 436 * The ints are stored row by row, i.e. using the notation 437 * (row, column), the entries of the array are in the following order 438 * for a matrix, limited to m rows and n columns : 439 * (0, 0), (0, 1), (0, 2), ... , (0, n-1), (1, 0), (1, 1), ..., (m-1)(n-1) 440 * @param matrix A matrix of ints. 441 * @return A new array of ints. 442 */ 443 public static final int[] fromMatrixToArray(final int[][] matrix, 444 int maxRow, int maxCol) { 445 int[] returnValue = new int[maxRow * maxCol]; 446 447 for (int i = 0; i < maxRow; i++) { 448 System.arraycopy(matrix[i], 0, returnValue, i * maxCol, maxCol); 449 } 450 451 return returnValue; 452 } 453 454 /** Return an new identity matrix with the specified dimension. The 455 * matrix is square, so only one dimension specifier is needed. 456 */ 457 public static final int[][] identity(final int dim) { 458 int[][] returnValue = new int[dim][dim]; 459 460 // we rely on the fact Java fills the allocated matrix with 0's 461 for (int i = 0; i < dim; i++) { 462 returnValue[i][i] = 1; 463 } 464 465 return returnValue; 466 } 467 468 /** Return an new identity matrix with the specified dimension. The 469 * matrix is square, so only one dimension specifier is needed. 470 */ 471 public static final int[][] identityMatrixInt(final int dim) { 472 return identity(dim); 473 } 474 475 /** Replace the first matrix argument elements with the values of 476 * the second matrix argument. The second matrix argument must be 477 * large enough to hold all the values of second matrix argument. 478 * @param destMatrix A matrix of ints, used as the destination. 479 * @param srcMatrix A matrix of ints, used as the source. 480 */ 481 public static final void matrixCopy(final int[][] srcMatrix, 482 final int[][] destMatrix) { 483 matrixCopy(srcMatrix, 0, 0, destMatrix, 0, 0, _rows(srcMatrix), 484 _columns(srcMatrix)); 485 } 486 487 /** Replace the first matrix argument's values, in the specified row 488 * and column range, with the second matrix argument's values, starting 489 * from specified row and column of the second matrix. 490 * @param srcMatrix A matrix of ints, used as the destination. 491 * @param srcRowStart An int specifying the starting row of the source. 492 * @param srcColStart An int specifying the starting column of the 493 * source. 494 * @param destMatrix A matrix of ints, used as the destination. 495 * @param destRowStart An int specifying the starting row of the dest. 496 * @param destColStart An int specifying the starting column of the 497 * dest. 498 * @param rowSpan An int specifying how many rows to copy. 499 * @param colSpan An int specifying how many columns to copy. 500 */ 501 public static final void matrixCopy(final int[][] srcMatrix, 502 final int srcRowStart, final int srcColStart, 503 final int[][] destMatrix, final int destRowStart, 504 final int destColStart, final int rowSpan, final int colSpan) { 505 // We should verify the parameters here 506 for (int i = 0; i < rowSpan; i++) { 507 System.arraycopy(srcMatrix[srcRowStart + i], srcColStart, 508 destMatrix[destRowStart + i], destColStart, colSpan); 509 } 510 } 511 512 /** Return a new matrix that is constructed by computing the 513 * remainders between each element in the matrix and z. 514 */ 515 public static final int[][] modulo(final int[][] matrix, final int z) { 516 int[][] returnValue = new int[_rows(matrix)][_columns(matrix)]; 517 518 for (int i = 0; i < _rows(matrix); i++) { 519 for (int j = 0; j < _columns(matrix); j++) { 520 returnValue[i][j] = matrix[i][j] % z; 521 } 522 } 523 524 return returnValue; 525 } 526 527 /** Return a new matrix that is constructed by computing the 528 * remainders between each element in the first matrix argument 529 * and the corresponding element in the second matrix argument. 530 * If the two matrices are not the same size, throw an 531 * IllegalArgumentException. 532 */ 533 public static final int[][] modulo(final int[][] matrix1, 534 final int[][] matrix2) { 535 int rows = _rows(matrix1); 536 int columns = _columns(matrix1); 537 538 _checkSameDimension("modulo", matrix1, matrix2); 539 540 int[][] returnValue = new int[rows][columns]; 541 542 for (int i = 0; i < rows; i++) { 543 for (int j = 0; j < columns; j++) { 544 returnValue[i][j] = matrix1[i][j] % matrix2[i][j]; 545 } 546 } 547 548 return returnValue; 549 } 550 551 /** Return a new matrix that is constructed by multiplying the matrix 552 * by a scaleFactor. 553 */ 554 public static final int[][] multiply(final int[][] matrix, 555 final int scaleFactor) { 556 int rows = _rows(matrix); 557 int columns = _columns(matrix); 558 559 int[][] returnValue = new int[rows][columns]; 560 561 for (int i = 0; i < rows; i++) { 562 for (int j = 0; j < columns; j++) { 563 returnValue[i][j] = matrix[i][j] * scaleFactor; 564 } 565 } 566 567 return returnValue; 568 } 569 570 /** Return a new array that is constructed from the argument by 571 * pre-multiplying the array (treated as a row vector) by a matrix. 572 * The number of rows of the matrix must equal the number of elements 573 * in the array. The returned array will have a length equal to the number 574 * of columns of the matrix. 575 */ 576 public static final int[] multiply(final int[][] matrix, 577 final int[] array) { 578 int rows = _rows(matrix); 579 int columns = _columns(matrix); 580 581 if (rows != array.length) { 582 throw new IllegalArgumentException( 583 "preMultiply : array does not have the same number of " 584 + "elements (" + array.length 585 + ") as the number of rows " + "of the matrix (" 586 + rows + ")"); 587 } 588 589 int[] returnValue = new int[columns]; 590 591 for (int i = 0; i < columns; i++) { 592 int sum = 0; 593 594 for (int j = 0; j < rows; j++) { 595 sum += matrix[j][i] * array[j]; 596 } 597 598 returnValue[i] = sum; 599 } 600 601 return returnValue; 602 } 603 604 /** Return a new array that is constructed from the argument by 605 * post-multiplying the matrix by an array (treated as a row vector). 606 * The number of columns of the matrix must equal the number of elements 607 * in the array. The returned array will have a length equal to the number 608 * of rows of the matrix. 609 */ 610 public static final int[] multiply(final int[] array, 611 final int[][] matrix) { 612 int rows = _rows(matrix); 613 int columns = _columns(matrix); 614 615 if (columns != array.length) { 616 throw new IllegalArgumentException( 617 "postMultiply() : array does not have the same number " 618 + "of elements (" + array.length 619 + ") as the number of " + "columns of the matrix (" 620 + columns + ")"); 621 } 622 623 int[] returnValue = new int[rows]; 624 625 for (int i = 0; i < rows; i++) { 626 int sum = 0; 627 628 for (int j = 0; j < columns; j++) { 629 sum += matrix[i][j] * array[j]; 630 } 631 632 returnValue[i] = sum; 633 } 634 635 return returnValue; 636 } 637 638 /** Return a new matrix that is constructed from the argument by 639 * multiplying the first matrix by the second one. 640 * Note this operation is not commutative, 641 * so care must be taken in the ordering of the arguments. 642 * The number of columns of matrix1 643 * must equal the number of rows of matrix2. If matrix1 is of 644 * size m x n, and matrix2 is of size n x p, the returned matrix 645 * will have size m x p. 646 * 647 * <p>Note that this method is different from the other multiply() 648 * methods in that this method does not do pointwise multiplication. 649 * 650 * @see #multiplyElements(int[][], int[][]) 651 * @param matrix1 The first matrix of ints. 652 * @param matrix2 The second matrix of ints. 653 * @return A new matrix of ints. 654 */ 655 public static final int[][] multiply(int[][] matrix1, int[][] matrix2) { 656 int[][] returnValue = new int[_rows(matrix1)][matrix2[0].length]; 657 658 for (int i = 0; i < _rows(matrix1); i++) { 659 for (int j = 0; j < matrix2[0].length; j++) { 660 int sum = 0; 661 662 for (int k = 0; k < matrix2.length; k++) { 663 sum += matrix1[i][k] * matrix2[k][j]; 664 } 665 666 returnValue[i][j] = sum; 667 } 668 } 669 670 return returnValue; 671 } 672 673 /** Return a new matrix that is constructed by element by element 674 * multiplication of the two matrix arguments. If the two 675 * matrices are not the same size, throw an 676 * IllegalArgumentException. 677 * <p>Note that this method does pointwise matrix multiplication. 678 * See {@link #multiply(int[][], int[][])} for standard 679 * matrix multiplication. 680 */ 681 public static final int[][] multiplyElements(final int[][] matrix1, 682 final int[][] matrix2) { 683 int rows = _rows(matrix1); 684 int columns = _columns(matrix1); 685 686 _checkSameDimension("multiplyElements", matrix1, matrix2); 687 688 int[][] returnValue = new int[rows][columns]; 689 690 for (int i = 0; i < rows; i++) { 691 for (int j = 0; j < columns; j++) { 692 returnValue[i][j] = matrix1[i][j] * matrix2[i][j]; 693 } 694 } 695 696 return returnValue; 697 } 698 699 /** Return a new matrix that is the additive inverse of the 700 * argument matrix. 701 */ 702 public static final int[][] negative(final int[][] matrix) { 703 int rows = _rows(matrix); 704 int columns = _columns(matrix); 705 706 int[][] returnValue = new int[rows][columns]; 707 708 for (int i = 0; i < rows; i++) { 709 for (int j = 0; j < columns; j++) { 710 returnValue[i][j] = -matrix[i][j]; 711 } 712 } 713 714 return returnValue; 715 } 716 717 /** Return a new matrix that is constructed from the argument by 718 * arithmetically shifting the elements in the matrix by the 719 * second argument. If the second argument is positive, the 720 * elements are shifted left by the second argument. If the 721 * second argument is negative, the elements are shifted right 722 * (arithmetically, with the >>> operator) by the absolute value 723 * of the second argument. If the second argument is 0, no 724 * operation is performed (the matrix is just copied). 725 * 726 * @param matrix A first matrix of ints. 727 * @param shiftAmount The amount to shift by, positive for left shift, 728 * negative for right shift. 729 * @return A new matrix of ints. 730 */ 731 public static final int[][] shiftArithmetic(final int[][] matrix, 732 final int shiftAmount) { 733 int rows = _rows(matrix); 734 int columns = _columns(matrix); 735 736 int[][] returnValue = new int[rows][columns]; 737 738 if (shiftAmount >= 0) { 739 for (int i = 0; i < rows; i++) { 740 for (int j = 0; j < columns; j++) { 741 returnValue[i][j] = matrix[i][j] << shiftAmount; 742 } 743 } 744 } else if (shiftAmount < 0) { 745 for (int i = 0; i < rows; i++) { 746 for (int j = 0; j < columns; j++) { 747 returnValue[i][j] = matrix[i][j] >>> -shiftAmount; 748 } 749 } 750 } 751 752 return returnValue; 753 } 754 755 /** Return a new matrix that is constructed from the argument by 756 * logically shifting the elements in the matrix by the second 757 * argument. If the second argument is positive, the elements 758 * are shifted left by the second argument. If the second 759 * argument is negative, the elements are shifted right 760 * (logically, with the >> operator) by the absolute value of the 761 * second argument. If the second argument is 0, no operation is 762 * performed (the matrix is just copied). 763 * 764 * @param matrix A first matrix of ints. 765 * @param shiftAmount The amount to shift by, positive for left shift, 766 * negative for right shift. 767 * @return A new matrix of ints. 768 */ 769 public static final int[][] shiftLogical(final int[][] matrix, 770 final int shiftAmount) { 771 int rows = _rows(matrix); 772 int columns = _columns(matrix); 773 774 int[][] returnValue = new int[rows][columns]; 775 776 if (shiftAmount >= 0) { 777 for (int i = 0; i < rows; i++) { 778 for (int j = 0; j < columns; j++) { 779 returnValue[i][j] = matrix[i][j] << shiftAmount; 780 } 781 } 782 } else if (shiftAmount < 0) { 783 for (int i = 0; i < rows; i++) { 784 for (int j = 0; j < columns; j++) { 785 returnValue[i][j] = matrix[i][j] >> -shiftAmount; 786 } 787 } 788 } 789 790 return returnValue; 791 } 792 793 /** Return a new matrix that is constructed from the argument by 794 * subtracting the second matrix from the first one. If the two 795 * matrices are not the same size, throw an 796 * IllegalArgumentException. 797 */ 798 public static final int[][] subtract(final int[][] matrix1, 799 final int[][] matrix2) { 800 _checkSameDimension("subtract", matrix1, matrix2); 801 802 int rows = _rows(matrix1); 803 int columns = _columns(matrix1); 804 805 int[][] returnValue = new int[rows][columns]; 806 807 for (int i = 0; i < rows; i++) { 808 for (int j = 0; j < columns; j++) { 809 returnValue[i][j] = matrix1[i][j] - matrix2[i][j]; 810 } 811 } 812 813 return returnValue; 814 } 815 816 /** Return the sum of the elements of a matrix. 817 * @return The sum of the elements of the matrix. 818 */ 819 public static final int sum(final int[][] matrix) { 820 int sum = 0; 821 822 for (int[] element : matrix) { 823 for (int j = 0; j < element.length; j++) { 824 sum += element[j]; 825 } 826 } 827 828 return sum; 829 } 830 831 /** Return a new matrix that is formed by converting the integers 832 * in the argument matrix to complex numbers. Each complex number 833 * has a real part equal to the value in the argument matrix and a 834 * zero imaginary part. 835 * 836 * @param matrix A matrix of integers. 837 * @return A new matrix of complex numbers. 838 */ 839 public static final Complex[][] toComplexMatrix(final int[][] matrix) { 840 int rows = _rows(matrix); 841 int columns = _columns(matrix); 842 843 Complex[][] returnValue = new Complex[rows][columns]; 844 845 for (int i = 0; i < rows; i++) { 846 for (int j = 0; j < columns; j++) { 847 returnValue[i][j] = new Complex(matrix[i][j], 0.0); 848 } 849 } 850 851 return returnValue; 852 } 853 854 /** Return a new matrix that is formed by converting the ints in 855 * the argument matrix to doubles. 856 * @param matrix An matrix of int. 857 * @return A new matrix of doubles. 858 */ 859 public static final double[][] toDoubleMatrix(final int[][] matrix) { 860 int rows = _rows(matrix); 861 int columns = _columns(matrix); 862 863 double[][] returnValue = new double[rows][columns]; 864 865 for (int i = 0; i < rows; i++) { 866 for (int j = 0; j < columns; j++) { 867 returnValue[i][j] = matrix[i][j]; 868 } 869 } 870 871 return returnValue; 872 } 873 874 /** Return a new matrix that is formed by converting the ints in 875 * the argument matrix to floats. 876 * @param matrix An matrix of int. 877 * @return A new matrix of floats. 878 */ 879 public static final float[][] toFloatMatrix(final int[][] matrix) { 880 int rows = _rows(matrix); 881 int columns = _columns(matrix); 882 883 float[][] returnValue = new float[rows][columns]; 884 885 for (int i = 0; i < rows; i++) { 886 for (int j = 0; j < columns; j++) { 887 returnValue[i][j] = matrix[i][j]; 888 } 889 } 890 891 return returnValue; 892 } 893 894 /** Return a new matrix that is formed by converting the ints in 895 * the argument matrix to longs. 896 * @param matrix An matrix of int. 897 * @return A new matrix of longs. 898 */ 899 public static final long[][] toLongMatrix(final int[][] matrix) { 900 int rows = _rows(matrix); 901 int columns = _columns(matrix); 902 903 long[][] returnValue = new long[rows][columns]; 904 905 for (int i = 0; i < rows; i++) { 906 for (int j = 0; j < columns; j++) { 907 returnValue[i][j] = matrix[i][j]; 908 } 909 } 910 911 return returnValue; 912 } 913 914 /** Return a new matrix of ints that is initialized from a 1-D array. 915 * The format of the array must be (0, 0), (0, 1), ..., (0, n-1), (1, 0), 916 * (1, 1), ..., (m-1, n-1) where the output matrix is to be m x n and 917 * entries are denoted by (row, column). 918 * @param array An array of ints. 919 * @param rows An integer representing the number of rows of the new 920 * matrix. 921 * @param cols An integer representing the number of columns of the new 922 * matrix. 923 * @return A new matrix of ints. 924 */ 925 public static final int[][] toMatrixFromArray(int[] array, int rows, 926 int cols) { 927 int[][] returnValue = new int[rows][cols]; 928 929 for (int i = 0; i < rows; i++) { 930 System.arraycopy(array, i * cols, returnValue[i], 0, cols); 931 } 932 933 return returnValue; 934 } 935 936 /** Return a new String representing the matrix, formatted as 937 * in Java array initializers. 938 */ 939 public static final String toString(final int[][] matrix) { 940 return toString(matrix, ", ", "{", "}", "{", ", ", "}"); 941 } 942 943 /** Return a new String representing the matrix, formatted as 944 * specified by the ArrayStringFormat argument. 945 * To get a String in the Ptolemy expression language format, 946 * call this method with ArrayStringFormat.exprASFormat as the 947 * format argument. 948 */ 949 public static final String toString(final int[][] matrix, 950 String elementDelimiter, String matrixBegin, String matrixEnd, 951 String vectorBegin, String vectorDelimiter, String vectorEnd) { 952 StringBuffer sb = new StringBuffer(); 953 sb.append(matrixBegin); 954 955 for (int i = 0; i < _rows(matrix); i++) { 956 sb.append(vectorBegin); 957 958 for (int j = 0; j < _columns(matrix); j++) { 959 sb.append(Integer.toString(matrix[i][j])); 960 961 if (j < _columns(matrix) - 1) { 962 sb.append(elementDelimiter); 963 } 964 } 965 966 sb.append(vectorEnd); 967 968 if (i < _rows(matrix) - 1) { 969 sb.append(vectorDelimiter); 970 } 971 } 972 973 sb.append(matrixEnd); 974 975 return new String(sb); 976 } 977 978 /** Return the trace of a square matrix, which is the sum of the 979 * diagonal entries A<sub>11</sub> + A<sub>22</sub> + ... + A<sub>nn</sub> 980 * Throw an IllegalArgumentException if the matrix is not square. 981 * Note that the trace of a matrix is equal to the sum of its eigenvalues. 982 */ 983 public static final int trace(final int[][] matrix) { 984 int dim = _checkSquare("trace", matrix); 985 int sum = 0; 986 987 for (int i = 0; i < dim; i++) { 988 sum += matrix[i][i]; 989 } 990 991 return sum; 992 } 993 994 /** Return a new matrix that is constructed by transposing the input 995 * matrix. If the input matrix is m x n, the output matrix will be 996 * n x m. 997 */ 998 public static final int[][] transpose(final int[][] matrix) { 999 int rows = _rows(matrix); 1000 int columns = _columns(matrix); 1001 1002 int[][] returnValue = new int[columns][rows]; 1003 1004 for (int i = 0; i < rows; i++) { 1005 for (int j = 0; j < columns; j++) { 1006 returnValue[j][i] = matrix[i][j]; 1007 } 1008 } 1009 1010 return returnValue; 1011 } 1012 1013 /** Return true if the elements of the two matrices differ by no 1014 * more than the specified distance. If <i>distance</i> is 1015 * negative, return false. 1016 * @param matrix1 The first matrix. 1017 * @param matrix2 The second matrix. 1018 * @param distance The distance to use for comparison. 1019 * @return True if the elements of the two matrices are within the 1020 * specified distance. 1021 * @exception IllegalArgumentException If the matrices do not 1022 * have the same dimension. This is a run-time exception, so it 1023 * need not be declared explicitly. 1024 */ 1025 public static final boolean within(final int[][] matrix1, 1026 final int[][] matrix2, int distance) { 1027 int rows = _rows(matrix1); 1028 int columns = _columns(matrix1); 1029 1030 _checkSameDimension("within", matrix1, matrix2); 1031 1032 for (int i = 0; i < rows; i++) { 1033 for (int j = 0; j < columns; j++) { 1034 if (matrix1[i][j] > matrix2[i][j] + distance 1035 || matrix1[i][j] < matrix2[i][j] - distance) { 1036 return false; 1037 } 1038 } 1039 } 1040 1041 return true; 1042 } 1043 1044 /** Return true if the elements of the two matrices differ by no more 1045 * than the specified distances. If any element of <i>errorMatrix</i> is 1046 * negative, return false. 1047 * @param matrix1 The first matrix. 1048 * @param matrix2 The second matrix. 1049 * @param errorMatrix The distance to use for comparison. 1050 * @return True if the elements of the two matrices are within the 1051 * specified distance. 1052 * @exception IllegalArgumentException If the matrices do not 1053 * have the same dimension. This is a run-time exception, so it 1054 * need not be declared explicitly. 1055 */ 1056 public static final boolean within(final int[][] matrix1, 1057 final int[][] matrix2, final int[][] errorMatrix) { 1058 int rows = _rows(matrix1); 1059 int columns = _columns(matrix1); 1060 1061 _checkSameDimension("within", matrix1, matrix2); 1062 _checkSameDimension("within", matrix1, errorMatrix); 1063 1064 for (int i = 0; i < rows; i++) { 1065 for (int j = 0; j < columns; j++) { 1066 if (matrix1[i][j] > matrix2[i][j] + errorMatrix[i][j] 1067 || matrix1[i][j] < matrix2[i][j] - errorMatrix[i][j]) { 1068 return false; 1069 } 1070 } 1071 } 1072 1073 return true; 1074 } 1075 1076 /** Check that the two matrix arguments are of the same dimension. 1077 * If they are not, an IllegalArgumentException is thrown. 1078 * @param caller A string representing the caller method name. 1079 * @param matrix1 A matrix of ints. 1080 * @param matrix2 A matrix of ints. 1081 */ 1082 protected static final void _checkSameDimension(final String caller, 1083 final int[][] matrix1, final int[][] matrix2) { 1084 int rows = _rows(matrix1); 1085 int columns = _columns(matrix1); 1086 1087 if (rows != _rows(matrix2) || columns != _columns(matrix2)) { 1088 throw new IllegalArgumentException("ptolemy.math.IntegerMatrixMath." 1089 + caller + "() : one matrix " + _dimensionString(matrix1) 1090 + " is not the same size as another matrix " 1091 + _dimensionString(matrix2) + "."); 1092 } 1093 } 1094 1095 /** Check that the argument matrix is a square matrix. If the matrix is not 1096 * square, an IllegalArgumentException is thrown. 1097 * @param caller A string representing the caller method name. 1098 * @param matrix A matrix of ints. 1099 * @return The dimension of the square matrix. 1100 */ 1101 protected static final int _checkSquare(final String caller, 1102 final int[][] matrix) { 1103 if (_rows(matrix) != _columns(matrix)) { 1104 throw new IllegalArgumentException("ptolemy.math.IntegerMatrixMath." 1105 + caller + "() : matrix argument " 1106 + _dimensionString(matrix) + " is not a square matrix."); 1107 } 1108 1109 return _rows(matrix); 1110 } 1111 1112 /** Return the number of columns of a matrix. 1113 * @param matrix The matrix. 1114 * @return The number of columns. 1115 */ 1116 protected static final int _columns(final int[][] matrix) { 1117 return matrix[0].length; 1118 } 1119 1120 /** Return a string that describes the number of rows and columns. 1121 * @param matrix The matrix that is to be described. 1122 * @return a string describing the dimensions of this matrix. 1123 */ 1124 protected static final String _dimensionString(final int[][] matrix) { 1125 return "[" + _rows(matrix) + " x " + _columns(matrix) + "]"; 1126 } 1127 1128 /** Return the number of rows of a matrix. */ 1129 protected static final int _rows(final int[][] matrix) { 1130 return matrix.length; 1131 } 1132}