001/* A library for mathematical operations on matrices of longs. 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-2014 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//// LongMatrixMath 038 039/** 040 This class provides a library for mathematical operations on 041 matrices of longs. 042 043 Rows and column numbers of matrices are specified with zero-based indices. 044 045 All calls expect matrix arguments to be non-null. In addition, all 046 rows of the matrix are expected to have the same number of columns. 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 LongMatrixMath { 054 // private constructor prevents construction of this class. 055 private LongMatrixMath() { 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 longs. 061 * @param z The long number to add. 062 * @return A new matrix of longs. 063 */ 064 public static final long[][] add(long[][] matrix, long z) { 065 long[][] returnValue = new long[_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 longs. 081 * @param matrix2 The second matrix of longs. 082 * @return A new matrix of longs. */ 083 public static final long[][] add(final long[][] matrix1, 084 final long[][] matrix2) { 085 _checkSameDimension("add", matrix1, matrix2); 086 087 long[][] returnValue = new long[_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 longs. 100 * @return A new matrix of longs. 101 */ 102 public static final long[][] allocCopy(final long[][] 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 * LongBinaryOperation 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 long[][] applyBinaryOperation(LongBinaryOperation op, 112 final long z, final long[][] matrix) { 113 int rows = _rows(matrix); 114 int columns = _columns(matrix); 115 116 long[][] returnValue = new long[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 * LongBinaryOperation 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 long[][] applyBinaryOperation(LongBinaryOperation op, 133 final long[][] matrix, final long z) { 134 int rows = _rows(matrix); 135 int columns = _columns(matrix); 136 137 long[][] returnValue = new long[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 * LongBinaryOperation to the two matrices, element by element, 150 * using the elements of the first matrix as the left operands 151 * and the elements of the second matrix as the right operands. 152 * (op.operate(matrix1[i][j], matrix2[i][j])). If the matrices 153 * are not the same size, throw an IllegalArgumentException. 154 */ 155 public static final long[][] applyBinaryOperation(LongBinaryOperation op, 156 final long[][] matrix1, final long[][] matrix2) { 157 int rows = _rows(matrix1); 158 int columns = _columns(matrix1); 159 160 _checkSameDimension("applyBinaryOperation", matrix1, matrix2); 161 162 long[][] returnValue = new long[rows][columns]; 163 164 for (int i = 0; i < rows; i++) { 165 for (int j = 0; j < columns; j++) { 166 returnValue[i][j] = op.operate(matrix1[i][j], matrix2[i][j]); 167 } 168 } 169 170 return returnValue; 171 } 172 173 /** Return a new array that is formed by applying an instance of a 174 * LongUnaryOperation to each element in the input matrix 175 * (op.operate(matrix[i][j])). 176 */ 177 public static final long[][] applyUnaryOperation( 178 final LongUnaryOperation op, final long[][] matrix) { 179 int rows = _rows(matrix); 180 int columns = _columns(matrix); 181 182 long[][] returnValue = new long[rows][columns]; 183 184 for (int i = 0; i < rows; i++) { 185 for (int j = 0; j < columns; j++) { 186 returnValue[i][j] = op.operate(matrix[i][j]); 187 } 188 } 189 190 return returnValue; 191 } 192 193 /** Return a new matrix that is the formed by bitwise ANDing z 194 * with each element of the input matrix (matrix[i][j] & z). 195 */ 196 public static final long[][] bitwiseAnd(final long[][] matrix, 197 final long z) { 198 int rows = _rows(matrix); 199 int columns = _columns(matrix); 200 201 long[][] returnValue = new long[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 long[][] bitwiseAnd(final long[][] matrix1, 218 final long[][] matrix2) { 219 int rows = _rows(matrix1); 220 int columns = _columns(matrix1); 221 222 _checkSameDimension("bitwiseAnd", matrix1, matrix2); 223 224 long[][] returnValue = new long[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 long[][] bitwiseComplement(final long[][] matrix) { 239 int rows = _rows(matrix); 240 int columns = _columns(matrix); 241 242 long[][] returnValue = new long[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 public static final long[][] bitwiseOr(final long[][] matrix, 257 final long z) { 258 int rows = _rows(matrix); 259 int columns = _columns(matrix); 260 261 long[][] returnValue = new long[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 long[][] bitwiseOr(final long[][] matrix1, 278 final long[][] matrix2) { 279 int rows = _rows(matrix1); 280 int columns = _columns(matrix1); 281 282 _checkSameDimension("bitwiseOr", matrix1, matrix2); 283 284 long[][] returnValue = new long[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 long[][] bitwiseXor(final long[][] matrix, 299 final long z) { 300 int rows = _rows(matrix); 301 int columns = _columns(matrix); 302 303 long[][] returnValue = new long[rows][columns]; 304 305 for (int i = 0; i < rows; i++) { 306 for (int j = 0; j < columns; j++) { 307 returnValue[i][j] = matrix[i][j] ^ z; 308 } 309 } 310 311 return returnValue; 312 } 313 314 /** Return a new array that is the element-by-element bitwise XOR 315 * of the two input matrices (matrix1[i][j] & matrix2[i][j]). If 316 * the two matrices are not the same size, throw an 317 * IllegalArgumentException. 318 */ 319 public static final long[][] bitwiseXor(final long[][] matrix1, 320 final long[][] matrix2) { 321 int rows = _rows(matrix1); 322 int columns = _columns(matrix1); 323 324 _checkSameDimension("bitwiseXor", matrix1, matrix2); 325 326 long[][] returnValue = new long[rows][columns]; 327 328 for (int i = 0; i < rows; i++) { 329 for (int j = 0; j < columns; j++) { 330 returnValue[i][j] = matrix1[i][j] ^ matrix2[i][j]; 331 } 332 } 333 334 return returnValue; 335 } 336 337 /** Return a new matrix that is a sub-matrix of the input 338 * matrix argument. The row and column from which to start 339 * and the number of rows and columns to span are specified. 340 * @param matrix A matrix of longs. 341 * @param rowStart An int specifying which row to start on. 342 * @param colStart An int specifying which column to start on. 343 * @param rowSpan An int specifying how many rows to copy. 344 * @param colSpan An int specifying how many columns to copy. 345 */ 346 public static final long[][] crop(final long[][] matrix, final int rowStart, 347 final int colStart, final int rowSpan, final int colSpan) { 348 long[][] returnValue = new long[rowSpan][colSpan]; 349 350 for (int i = 0; i < rowSpan; i++) { 351 System.arraycopy(matrix[rowStart + i], colStart, returnValue[i], 0, 352 colSpan); 353 } 354 355 return returnValue; 356 } 357 358 /** Return a new matrix that is constructed by placing the 359 * elements of the input array on the diagonal of the square 360 * matrix, starting from the top left corner down to the bottom 361 * right corner. All other elements are zero. The size of of the 362 * matrix is n x n, where n is the length of the input array. 363 */ 364 public static final long[][] diag(final long[] array) { 365 int n = array.length; 366 367 long[][] returnValue = new long[n][n]; 368 369 // Assume the matrix is zero-filled. 370 for (int i = 0; i < n; i++) { 371 returnValue[i][i] = array[i]; 372 } 373 374 return returnValue; 375 } 376 377 /** Return a new matrix that is constructed from the argument by 378 * dividing the second argument to every element. 379 * @param matrix A matrix of longs. 380 * @param z The long number to divide. 381 * @return A new matrix of longs. 382 */ 383 public static final long[][] divide(long[][] matrix, long z) { 384 long[][] returnValue = new long[_rows(matrix)][_columns(matrix)]; 385 386 for (int i = 0; i < _rows(matrix); i++) { 387 for (int j = 0; j < _columns(matrix); j++) { 388 returnValue[i][j] = matrix[i][j] / z; 389 } 390 } 391 392 return returnValue; 393 } 394 395 /** Return a new matrix that is constructed by element by element 396 * division of the two matrix arguments. Each element of the 397 * first matrix is divided by the corresponding element of the 398 * second matrix. If the two matrices are not the same size, 399 * throw an IllegalArgumentException. 400 */ 401 public static final long[][] divideElements(final long[][] matrix1, 402 final long[][] matrix2) { 403 int rows = _rows(matrix1); 404 int columns = _columns(matrix1); 405 406 _checkSameDimension("divideElements", matrix1, matrix2); 407 408 long[][] returnValue = new long[rows][columns]; 409 410 for (int i = 0; i < rows; i++) { 411 for (int j = 0; j < columns; j++) { 412 returnValue[i][j] = matrix1[i][j] / matrix2[i][j]; 413 } 414 } 415 416 return returnValue; 417 } 418 419 /** Return a new array that is filled with the contents of the matrix. 420 * The longs are stored row by row, i.e. using the notation 421 * (row, column), the entries of the array are in the following order 422 * for a (m, n) matrix : 423 * (0, 0), (0, 1), (0, 2), ... , (0, n-1), (1, 0), (1, 1), ..., (m-1)(n-1) 424 * @param matrix A matrix of longs. 425 * @return A new array of longs. 426 */ 427 public static final long[] fromMatrixToArray(final long[][] matrix) { 428 return fromMatrixToArray(matrix, _rows(matrix), _columns(matrix)); 429 } 430 431 /** Return a new array that is filled with the contents of the matrix. 432 * The maximum numbers of rows and columns to copy are specified so 433 * that entries lying outside of this range can be ignored. The 434 * maximum rows to copy cannot exceed the number of rows in the matrix, 435 * and the maximum columns to copy cannot exceed the number of columns 436 * in the matrix. 437 * The longs are stored row by row, i.e. using the notation 438 * (row, column), the entries of the array are in the following order 439 * for a matrix, limited to m rows and n columns : 440 * (0, 0), (0, 1), (0, 2), ... , (0, n-1), (1, 0), (1, 1), ..., (m-1)(n-1) 441 * @param matrix A matrix of longs. 442 * @return A new array of longs. 443 */ 444 public static final long[] fromMatrixToArray(final long[][] matrix, 445 int maxRow, int maxCol) { 446 long[] returnValue = new long[maxRow * maxCol]; 447 448 for (int i = 0; i < maxRow; i++) { 449 System.arraycopy(matrix[i], 0, returnValue, i * maxCol, maxCol); 450 } 451 452 return returnValue; 453 } 454 455 /** Return an new identity matrix with the specified dimension. The 456 * matrix is square, so only one dimension specifier is needed. 457 */ 458 public static final long[][] identity(final int dim) { 459 long[][] returnValue = new long[dim][dim]; 460 461 // we rely on the fact Java fills the allocated matrix with 0's 462 for (int i = 0; i < dim; i++) { 463 returnValue[i][i] = 1L; 464 } 465 466 return returnValue; 467 } 468 469 /** Return an new identity matrix with the specified dimension. The 470 * matrix is square, so only one dimension specifier is needed. 471 */ 472 public static final long[][] identityMatrixLong(final int dim) { 473 return identity(dim); 474 } 475 476 /** Replace the first matrix argument elements with the values of 477 * the second matrix argument. The second matrix argument must be 478 * large enough to hold all the values of second matrix argument. 479 * @param destMatrix A matrix of longs, used as the destination. 480 * @param srcMatrix A matrix of longs, used as the source. 481 */ 482 public static final void matrixCopy(final long[][] srcMatrix, 483 final long[][] destMatrix) { 484 matrixCopy(srcMatrix, 0, 0, destMatrix, 0, 0, _rows(srcMatrix), 485 _columns(srcMatrix)); 486 } 487 488 /** Replace the first matrix argument's values, in the specified row 489 * and column range, with the second matrix argument's values, starting 490 * from specified row and column of the second matrix. 491 * @param srcMatrix A matrix of longs, used as the destination. 492 * @param srcRowStart An int specifying the starting row of the source. 493 * @param srcColStart An int specifying the starting column of the 494 * source. 495 * @param destMatrix A matrix of longs, used as the destination. 496 * @param destRowStart An int specifying the starting row of the dest. 497 * @param destColStart An int specifying the starting column of the 498 * dest. 499 * @param rowSpan An int specifying how many rows to copy. 500 * @param colSpan An int specifying how many columns to copy. 501 */ 502 public static final void matrixCopy(final long[][] srcMatrix, 503 final int srcRowStart, final int srcColStart, 504 final long[][] destMatrix, final int destRowStart, 505 final int destColStart, final int rowSpan, final int colSpan) { 506 // We should verify the parameters here 507 for (int i = 0; i < rowSpan; i++) { 508 System.arraycopy(srcMatrix[srcRowStart + i], srcColStart, 509 destMatrix[destRowStart + i], destColStart, colSpan); 510 } 511 } 512 513 /** Return a new matrix that is constructed by computing the 514 * remainders between each element in the matrix and z. 515 */ 516 public static final long[][] modulo(final long[][] matrix, final long z) { 517 long[][] returnValue = new long[_rows(matrix)][_columns(matrix)]; 518 519 for (int i = 0; i < _rows(matrix); i++) { 520 for (int j = 0; j < _columns(matrix); j++) { 521 returnValue[i][j] = matrix[i][j] % z; 522 } 523 } 524 525 return returnValue; 526 } 527 528 /** Return a new matrix that is constructed by computing the 529 * remainders between each element in the first matrix argument 530 * and the corresponding element in the second matrix argument. 531 * If the two matrices are not the same size, throw an 532 * IllegalArgumentException. 533 */ 534 public static final long[][] modulo(final long[][] matrix1, 535 final long[][] matrix2) { 536 int rows = _rows(matrix1); 537 int columns = _columns(matrix1); 538 539 _checkSameDimension("modulo", matrix1, matrix2); 540 541 long[][] returnValue = new long[rows][columns]; 542 543 for (int i = 0; i < rows; i++) { 544 for (int j = 0; j < columns; j++) { 545 returnValue[i][j] = matrix1[i][j] % matrix2[i][j]; 546 } 547 } 548 549 return returnValue; 550 } 551 552 /** Return a new matrix that is constructed by multiplying the matrix 553 * by a scaleFactor. 554 */ 555 public static final long[][] multiply(final long[][] matrix, 556 final long scaleFactor) { 557 int rows = _rows(matrix); 558 int columns = _columns(matrix); 559 560 long[][] returnValue = new long[rows][columns]; 561 562 for (int i = 0; i < rows; i++) { 563 for (int j = 0; j < columns; j++) { 564 returnValue[i][j] = matrix[i][j] * scaleFactor; 565 } 566 } 567 568 return returnValue; 569 } 570 571 /** Return a new array that is constructed from the argument by 572 * pre-multiplying the array (treated as a row vector) by a matrix. 573 * The number of rows of the matrix must equal the number of elements 574 * in the array. The returned array will have a length equal to the number 575 * of columns of the matrix. 576 */ 577 public static final long[] multiply(final long[][] matrix, 578 final long[] array) { 579 int rows = _rows(matrix); 580 int columns = _columns(matrix); 581 582 if (rows != array.length) { 583 throw new IllegalArgumentException( 584 "preMultiply : array does not have the same number of " 585 + "elements (" + array.length 586 + ") as the number of rows " + "of the matrix (" 587 + rows + ")"); 588 } 589 590 long[] returnValue = new long[columns]; 591 592 for (int i = 0; i < columns; i++) { 593 long sum = 0L; 594 595 for (int j = 0; j < rows; j++) { 596 sum += matrix[j][i] * array[j]; 597 } 598 599 returnValue[i] = sum; 600 } 601 602 return returnValue; 603 } 604 605 /** Return a new array that is constructed from the argument by 606 * post-multiplying the matrix by an array (treated as a row vector). 607 * The number of columns of the matrix must equal the number of elements 608 * in the array. The returned array will have a length equal to the number 609 * of rows of the matrix. 610 */ 611 public static final long[] multiply(final long[] array, 612 final long[][] matrix) { 613 int rows = _rows(matrix); 614 int columns = _columns(matrix); 615 616 if (columns != array.length) { 617 throw new IllegalArgumentException( 618 "postMultiply() : array does not have the same number " 619 + "of elements (" + array.length 620 + ") as the number of " + "columns of the matrix (" 621 + columns + ")"); 622 } 623 624 long[] returnValue = new long[rows]; 625 626 for (int i = 0; i < rows; i++) { 627 long sum = 0L; 628 629 for (int j = 0; j < columns; j++) { 630 sum += matrix[i][j] * array[j]; 631 } 632 633 returnValue[i] = sum; 634 } 635 636 return returnValue; 637 } 638 639 /** Return a new matrix that is constructed from the argument by 640 * multiplying the first matrix by the second one. 641 * Note this operation is not commutative, 642 * so care must be taken in the ordering of the arguments. 643 * The number of columns of matrix1 644 * must equal the number of rows of matrix2. If matrix1 is of 645 * size m x n, and matrix2 is of size n x p, the returned matrix 646 * will have size m x p. 647 * 648 * <p>Note that this method is different from the other multiply() 649 * methods in that this method does not do pointwise multiplication. 650 * 651 * @see #multiplyElements(long[][], long[][]) 652 * @param matrix1 The first matrix of longs. 653 * @param matrix2 The second matrix of longs. 654 * @return A new matrix of longs. 655 */ 656 public static final long[][] multiply(long[][] matrix1, long[][] matrix2) { 657 long[][] returnValue = new long[_rows(matrix1)][matrix2[0].length]; 658 659 for (int i = 0; i < _rows(matrix1); i++) { 660 for (int j = 0; j < matrix2[0].length; j++) { 661 long sum = 0L; 662 663 for (int k = 0; k < matrix2.length; k++) { 664 sum += matrix1[i][k] * matrix2[k][j]; 665 } 666 667 returnValue[i][j] = sum; 668 } 669 } 670 671 return returnValue; 672 } 673 674 /** Return a new matrix that is constructed by element by element 675 * multiplication of the two matrix arguments. If the two 676 * matrices are not the same size, throw an 677 * IllegalArgumentException. 678 * <p>Note that this method does pointwise matrix multiplication. 679 * See {@link #multiply(long[][], long[][])} for standard 680 * matrix multiplication. 681 */ 682 public static final long[][] multiplyElements(final long[][] matrix1, 683 final long[][] matrix2) { 684 int rows = _rows(matrix1); 685 int columns = _columns(matrix1); 686 687 _checkSameDimension("multiplyElements", matrix1, matrix2); 688 689 long[][] returnValue = new long[rows][columns]; 690 691 for (int i = 0; i < rows; i++) { 692 for (int j = 0; j < columns; j++) { 693 returnValue[i][j] = matrix1[i][j] * matrix2[i][j]; 694 } 695 } 696 697 return returnValue; 698 } 699 700 /** Return a new matrix that is the additive inverse of the 701 * argument matrix. 702 */ 703 public static final long[][] negative(final long[][] matrix) { 704 int rows = _rows(matrix); 705 int columns = _columns(matrix); 706 707 long[][] returnValue = new long[rows][columns]; 708 709 for (int i = 0; i < rows; i++) { 710 for (int j = 0; j < columns; j++) { 711 returnValue[i][j] = -matrix[i][j]; 712 } 713 } 714 715 return returnValue; 716 } 717 718 /** Return a new matrix that is constructed from the argument by 719 * arithmetically shifting the elements in the matrix by the 720 * second argument. If the second argument is positive, the 721 * elements are shifted left by the second argument. If the 722 * second argument is negative, the elements are shifted right 723 * (arithmetically, with the >>> operator) by the absolute value 724 * of the second argument. If the second argument is 0, no 725 * operation is performed (the matrix is just copied). 726 * @param matrix A first matrix of longs. 727 * @param shiftAmount The amount to shift by, positive for left shift, 728 * negative for right shift. 729 * @return A new matrix of longs. */ 730 public static final long[][] shiftArithmetic(final long[][] matrix, 731 final int shiftAmount) { 732 int rows = _rows(matrix); 733 int columns = _columns(matrix); 734 735 long[][] returnValue = new long[rows][columns]; 736 737 if (shiftAmount >= 0) { 738 for (int i = 0; i < rows; i++) { 739 for (int j = 0; j < columns; j++) { 740 returnValue[i][j] = matrix[i][j] << shiftAmount; 741 } 742 } 743 } else if (shiftAmount < 0) { 744 for (int i = 0; i < rows; i++) { 745 for (int j = 0; j < columns; j++) { 746 returnValue[i][j] = matrix[i][j] >>> -shiftAmount; 747 } 748 } 749 } 750 751 return returnValue; 752 } 753 754 /** Return a new matrix that is constructed from the argument by 755 * logically shifting the elements in the matrix by the second 756 * argument. If the second argument is positive, the elements 757 * are shifted left by the second argument. If the second 758 * argument is negative, the elements are shifted right 759 * (logically, with the >> operator) by the absolute value of the 760 * second argument. If the second argument is 0, no operation is 761 * performed (the matrix is just copied). 762 * @param matrix A first matrix of longs. 763 * @param shiftAmount The amount to shift by, positive for left shift, 764 * negative for right shift. 765 * @return A new matrix of longs. */ 766 public static final long[][] shiftLogical(final long[][] matrix, 767 final int shiftAmount) { 768 int rows = _rows(matrix); 769 int columns = _columns(matrix); 770 771 long[][] returnValue = new long[rows][columns]; 772 773 if (shiftAmount >= 0) { 774 for (int i = 0; i < rows; i++) { 775 for (int j = 0; j < columns; j++) { 776 returnValue[i][j] = matrix[i][j] << shiftAmount; 777 } 778 } 779 } else if (shiftAmount < 0) { 780 for (int i = 0; i < rows; i++) { 781 for (int j = 0; j < columns; j++) { 782 returnValue[i][j] = matrix[i][j] >> -shiftAmount; 783 } 784 } 785 } 786 787 return returnValue; 788 } 789 790 /** Return a new matrix that is constructed from the argument by 791 * subtracting the second matrix from the first one. If the two 792 * matrices are not the same size, throw an 793 * IllegalArgumentException. 794 */ 795 public static final long[][] subtract(final long[][] matrix1, 796 final long[][] matrix2) { 797 _checkSameDimension("subtract", matrix1, matrix2); 798 799 int rows = _rows(matrix1); 800 int columns = _columns(matrix1); 801 802 long[][] returnValue = new long[rows][columns]; 803 804 for (int i = 0; i < rows; i++) { 805 for (int j = 0; j < columns; j++) { 806 returnValue[i][j] = matrix1[i][j] - matrix2[i][j]; 807 } 808 } 809 810 return returnValue; 811 } 812 813 /** Return the sum of the elements of a matrix. 814 * @return The sum of the elements of the matrix. 815 */ 816 public static final long sum(final long[][] matrix) { 817 long sum = 0L; 818 819 for (long[] element : matrix) { 820 for (int j = 0; j < element.length; j++) { 821 sum += element[j]; 822 } 823 } 824 825 return sum; 826 } 827 828 /** Return a new matrix that is formed by converting the long values 829 * in the argument matrix to complex numbers. Each complex number 830 * has a real part equal to the value in the argument matrix and a 831 * zero imaginary part. 832 * 833 * @param matrix A matrix of long values. 834 * @return A new matrix of complex numbers. 835 */ 836 public static final Complex[][] toComplexMatrix(final long[][] matrix) { 837 int rows = _rows(matrix); 838 int columns = _columns(matrix); 839 840 Complex[][] returnValue = new Complex[rows][columns]; 841 842 for (int i = 0; i < rows; i++) { 843 for (int j = 0; j < columns; j++) { 844 returnValue[i][j] = new Complex(matrix[i][j], 0.0); 845 } 846 } 847 848 return returnValue; 849 } 850 851 /** Return a new matrix that is formed by converting the longs in 852 * the argument matrix to doubles. 853 * @param matrix An matrix of long. 854 * @return A new matrix of doubles. 855 */ 856 public static final double[][] toDoubleMatrix(final long[][] matrix) { 857 int rows = _rows(matrix); 858 int columns = _columns(matrix); 859 860 double[][] returnValue = new double[rows][columns]; 861 862 for (int i = 0; i < rows; i++) { 863 for (int j = 0; j < columns; j++) { 864 returnValue[i][j] = matrix[i][j]; 865 } 866 } 867 868 return returnValue; 869 } 870 871 /** Return a new matrix that is formed by converting the longs in 872 * the argument matrix to floats. 873 * @param matrix An matrix of long. 874 * @return A new matrix of floats. 875 */ 876 public static final float[][] toFloatMatrix(final long[][] matrix) { 877 int rows = _rows(matrix); 878 int columns = _columns(matrix); 879 880 float[][] returnValue = new float[rows][columns]; 881 882 for (int i = 0; i < rows; i++) { 883 for (int j = 0; j < columns; j++) { 884 returnValue[i][j] = matrix[i][j]; 885 } 886 } 887 888 return returnValue; 889 } 890 891 /** Return a new matrix that is formed by converting the longs in 892 * the argument matrix to integers. 893 * @param matrix An matrix of long. 894 * @return A new matrix of integers. 895 */ 896 public static final int[][] toIntegerMatrix(final long[][] matrix) { 897 int rows = _rows(matrix); 898 int columns = _columns(matrix); 899 900 int[][] returnValue = new int[rows][columns]; 901 902 for (int i = 0; i < rows; i++) { 903 for (int j = 0; j < columns; j++) { 904 returnValue[i][j] = (int) matrix[i][j]; 905 } 906 } 907 908 return returnValue; 909 } 910 911 /** Return a new matrix of longs that is initialized from a 1-D array. 912 * The format of the array must be (0, 0), (0, 1), ..., (0, n-1), (1, 0), 913 * (1, 1), ..., (m-1, n-1) where the output matrix is to be m x n and 914 * entries are denoted by (row, column). 915 * @param array An array of longs. 916 * @param rows An integer representing the number of rows of the new 917 * matrix. 918 * @param cols An integer representing the number of columns of the new 919 * matrix. 920 * @return A new matrix of longs. 921 */ 922 public static final long[][] toMatrixFromArray(long[] array, int rows, 923 int cols) { 924 long[][] returnValue = new long[rows][cols]; 925 926 for (int i = 0; i < rows; i++) { 927 System.arraycopy(array, i * cols, returnValue[i], 0, cols); 928 } 929 930 return returnValue; 931 } 932 933 /** Return a new String representing the matrix, formatted as 934 * in Java array initializers. 935 */ 936 public static final String toString(final long[][] matrix) { 937 return toString(matrix, ", ", "{", "}", "{", ", ", "}"); 938 } 939 940 /** Return a new String representing the matrix, formatted as 941 * specified by the ArrayStringFormat argument. 942 * To get a String in the Ptolemy expression language format, 943 * call this method with ArrayStringFormat.exprASFormat as the 944 * format argument. 945 */ 946 public static final String toString(final long[][] matrix, 947 String elementDelimiter, String matrixBegin, String matrixEnd, 948 String vectorBegin, String vectorDelimiter, String vectorEnd) { 949 StringBuffer sb = new StringBuffer(); 950 sb.append(matrixBegin); 951 952 for (int i = 0; i < _rows(matrix); i++) { 953 sb.append(vectorBegin); 954 955 for (int j = 0; j < _columns(matrix); j++) { 956 sb.append(Long.toString(matrix[i][j])); 957 958 if (j < _columns(matrix) - 1) { 959 sb.append(elementDelimiter); 960 } 961 } 962 963 sb.append(vectorEnd); 964 965 if (i < _rows(matrix) - 1) { 966 sb.append(vectorDelimiter); 967 } 968 } 969 970 sb.append(matrixEnd); 971 972 return new String(sb); 973 } 974 975 /** Return the trace of a square matrix, which is the sum of the 976 * diagonal entries A<sub>11</sub> + A<sub>22</sub> + ... + A<sub>nn</sub> 977 * Throw an IllegalArgumentException if the matrix is not square. 978 * Note that the trace of a matrix is equal to the sum of its eigenvalues. 979 */ 980 public static final long trace(final long[][] matrix) { 981 int dim = _checkSquare("trace", matrix); 982 long sum = 0L; 983 984 for (int i = 0; i < dim; i++) { 985 sum += matrix[i][i]; 986 } 987 988 return sum; 989 } 990 991 /** Return a new matrix that is constructed by transposing the input 992 * matrix. If the input matrix is m x n, the output matrix will be 993 * n x m. 994 */ 995 public static final long[][] transpose(final long[][] matrix) { 996 int rows = _rows(matrix); 997 int columns = _columns(matrix); 998 999 long[][] returnValue = new long[columns][rows]; 1000 1001 for (int i = 0; i < rows; i++) { 1002 for (int j = 0; j < columns; j++) { 1003 returnValue[j][i] = matrix[i][j]; 1004 } 1005 } 1006 1007 return returnValue; 1008 } 1009 1010 /** Return true if the elements of the two matrices differ by no more 1011 * than the specified distance. If <i>distance</i> is negative, return 1012 * false. 1013 * @param matrix1 The first matrix. 1014 * @param matrix2 The second matrix. 1015 * @param distance The distance to use for comparison. 1016 * @return True if the elements of the two matrices are within the 1017 * specified distance. 1018 * @exception IllegalArgumentException If the matrices do not have the same dimension. 1019 * This is a run-time exception, so it need not be declared explicitly. 1020 */ 1021 public static final boolean within(final long[][] matrix1, 1022 final long[][] matrix2, long distance) { 1023 int rows = _rows(matrix1); 1024 int columns = _columns(matrix1); 1025 1026 _checkSameDimension("within", matrix1, matrix2); 1027 1028 for (int i = 0; i < rows; i++) { 1029 for (int j = 0; j < columns; j++) { 1030 if (matrix1[i][j] > matrix2[i][j] + distance 1031 || matrix1[i][j] < matrix2[i][j] - distance) { 1032 return false; 1033 } 1034 } 1035 } 1036 1037 return true; 1038 } 1039 1040 /** Return true if the elements of the two matrices differ by no more 1041 * than the specified distances. If any element of <i>errorMatrix</i> is 1042 * negative, return false. 1043 * @param matrix1 The first matrix. 1044 * @param matrix2 The second matrix. 1045 * @param errorMatrix The distance to use for comparison. 1046 * @return True if the elements of the two matrices are within the 1047 * specified distance. 1048 * @exception IllegalArgumentException If the matrices do not have the same dimension. 1049 * This is a run-time exception, so it need not be declared explicitly. 1050 */ 1051 public static final boolean within(final long[][] matrix1, 1052 final long[][] matrix2, final long[][] errorMatrix) { 1053 int rows = _rows(matrix1); 1054 int columns = _columns(matrix1); 1055 1056 _checkSameDimension("within", matrix1, matrix2); 1057 _checkSameDimension("within", matrix1, errorMatrix); 1058 1059 for (int i = 0; i < rows; i++) { 1060 for (int j = 0; j < columns; j++) { 1061 if (matrix1[i][j] > matrix2[i][j] + errorMatrix[i][j] 1062 || matrix1[i][j] < matrix2[i][j] - errorMatrix[i][j]) { 1063 return false; 1064 } 1065 } 1066 } 1067 1068 return true; 1069 } 1070 1071 /** Check that the two matrix arguments are of the same dimension. 1072 * If they are not, an IllegalArgumentException is thrown. 1073 * @param caller A string representing the caller method name. 1074 * @param matrix1 A matrix of longs. 1075 * @param matrix2 A matrix of longs. 1076 */ 1077 protected static final void _checkSameDimension(final String caller, 1078 final long[][] matrix1, final long[][] matrix2) { 1079 int rows = _rows(matrix1); 1080 int columns = _columns(matrix1); 1081 1082 if (rows != _rows(matrix2) || columns != _columns(matrix2)) { 1083 throw new IllegalArgumentException("ptolemy.math.LongMatrixMath." 1084 + caller + "() : one matrix " + _dimensionString(matrix1) 1085 + " is not the same size as another matrix " 1086 + _dimensionString(matrix2) + "."); 1087 } 1088 } 1089 1090 /** Check that the argument matrix is a square matrix. If the matrix is not 1091 * square, an IllegalArgumentException is thrown. 1092 * @param caller A string representing the caller method name. 1093 * @param matrix A matrix of longs. 1094 * @return The dimension of the square matrix. 1095 */ 1096 protected static final int _checkSquare(final String caller, 1097 final long[][] matrix) { 1098 if (_rows(matrix) != _columns(matrix)) { 1099 throw new IllegalArgumentException("ptolemy.math.LongMatrixMath." 1100 + caller + "() : matrix argument " 1101 + _dimensionString(matrix) + " is not a square matrix."); 1102 } 1103 1104 return _rows(matrix); 1105 } 1106 1107 /** Return the number of columns of a matrix. 1108 * @param matrix The matrix. 1109 * @return The number of columns. 1110 */ 1111 protected static final int _columns(final long[][] matrix) { 1112 return matrix[0].length; 1113 } 1114 1115 /** Return a string that describes the number of rows and columns. 1116 * @param matrix The matrix that is to be described. 1117 * @return a string describing the dimensions of this matrix. 1118 */ 1119 protected static final String _dimensionString(final long[][] matrix) { 1120 return "[" + _rows(matrix) + " x " + _columns(matrix) + "]"; 1121 } 1122 1123 /** Return the number of rows of a matrix. */ 1124 protected static final int _rows(final long[][] matrix) { 1125 return matrix.length; 1126 } 1127}