001/******************************************************************************* 002 * This software is provided as a supplement to the authors' textbooks on digital 003 * image processing published by Springer-Verlag in various languages and editions. 004 * Permission to use and distribute this software is granted under the BSD 2-Clause 005 * "Simplified" License (see http://opensource.org/licenses/BSD-2-Clause). 006 * Copyright (c) 2006-2023 Wilhelm Burger, Mark J. Burge. All rights reserved. 007 * Visit https://imagingbook.com for additional details. 008 ******************************************************************************/ 009 010package imagingbook.common.math; 011 012import imagingbook.common.math.exception.DivideByZeroException; 013import org.apache.commons.math3.linear.Array2DRowRealMatrix; 014import org.apache.commons.math3.linear.CholeskyDecomposition; 015import org.apache.commons.math3.linear.DecompositionSolver; 016import org.apache.commons.math3.linear.LUDecomposition; 017import org.apache.commons.math3.linear.MatrixUtils; 018import org.apache.commons.math3.linear.NonPositiveDefiniteMatrixException; 019import org.apache.commons.math3.linear.RealMatrix; 020import org.apache.commons.math3.linear.RealVector; 021import org.apache.commons.math3.linear.SingularMatrixException; 022 023import java.io.ByteArrayOutputStream; 024import java.io.PrintStream; 025import java.util.Arrays; 026import java.util.Locale; 027 028import static imagingbook.common.math.Arithmetic.sqr; 029 030/** 031 * <p> 032 * This class defines a set of static methods for calculations with vectors and matrices using native Java arrays 033 * without any enclosing object structures. Matrices are simple two-dimensional arrays {@code A[r][c]}, where {@code r} 034 * is the (vertical) <strong>row</strong> index and {@code c} is the (horizontal) <strong>column</strong> index (as 035 * common in linear algebra). This means that matrices are really vectors of row vectors. Only arrays of type 036 * {@code float} and {@code double} are supported. All matrices are assumed to be rectangular (i.e., all rows are of 037 * equal length). 038 * </p> 039 * <p> 040 * Note: Methods named with a trailing '{@code D}' (e.g., {@link #multiplyD(double, double[])}) operate destructively, 041 * i.e., modify one of the supplied arguments. 042 * </p> 043 * 044 * @author WB 045 * @version 2022/08/29 046 */ 047@SuppressWarnings("serial") 048public abstract class Matrix { 049 050 private Matrix() { 051 } 052 053 /** 054 * Locale used for printing decimal numbers by {@code toString()} methods. 055 */ 056 public static Locale PrintLocale = Locale.US; 057 058 /** 059 * Character used to separate successive vector and matrix elements by {@code toString()} methods. 060 */ 061 public static char SeparationChar = ','; 062 063 /** 064 * Leading delimiter used for lists of vector and matrix elements by {@code toString()} methods. 065 */ 066 public static char LeftDelimitChar = '{'; 067 068 /** 069 * Trailing delimiter used for lists of vector and matrix elements by {@code toString()} methods. 070 */ 071 public static char RightDelimitChar = '}'; 072 073 // ---- Matrix creation ----------------------------- 074 075 /** 076 * <p> 077 * Creates and returns a {@code double[][]} matrix containing the specified values. Throws a 078 * {@link IllegalArgumentException} if the number of supplied values does not exactly match the matrix size. Example 079 * for creating a 2x3 matrix: 080 * </p> 081 * <pre> 082 * double[][] A = makeDoubleMatrix(2, 3, 083 * 1.0, 2.0, 3.0, 084 * 4.0, 5.0, 6.0 );</pre> 085 * <p> 086 * See also {@link #flatten(double[][])}. 087 * </p> 088 * 089 * @param rows the number of matrix rows 090 * @param cols the number of matrix columns 091 * @param values a sequence of matrix values in row-major order (may also be passed as a {@code double[]}) 092 * @return a {@code double[][]} matrix 093 */ 094 public static double[][] makeDoubleMatrix(final int rows, final int cols, final double... values) { 095 final double[][] A = new double[rows][cols]; 096 if (values == null || values.length == 0) { 097 return A; 098 } else if (values.length != rows * cols) { 099 throw new IllegalArgumentException("wrong number of matrix values: " 100 + values.length + " instead of " + rows * cols); 101 } 102 103 for (int i = 0, r = 0; r < rows; r++) { 104 for (int c = 0; c < cols; c++) { 105 A[r][c] = values[i]; 106 i++; 107 } 108 } 109 return A; 110 } 111 112 /** 113 * <p> 114 * Creates and returns a {@code float[][]} matrix containing the specified values. Throws a 115 * {@link IllegalArgumentException} if the number of supplied values does not exactly match the matrix size. Example 116 * for creating a 2x3 matrix: 117 * </p> 118 * <pre> 119 * float[][] A = makeFloatMatrix(2, 3, 120 * 1.0f, 2.0f, 3.0f, 121 * 4.0f, 5.0f, 6.0f );</pre> 122 * <p> 123 * See also {@link #flatten(float[][])}. 124 * </p> 125 * 126 * @param rows the number of matrix rows 127 * @param cols the number of matrix columns 128 * @param values a sequence of matrix values in row-major order (may also be passed as a {@code float[]}) 129 * @return a {@code float[][]} matrix 130 */ 131 public static float[][] makeFloatMatrix(final int rows, final int cols, final float... values) { 132 final float[][] A = new float[rows][cols]; 133 if (values == null || values.length == 0) { 134 return A; 135 } else if (values.length != rows * cols) { 136 throw new IllegalArgumentException("wrong number of matrix values: " 137 + values.length + " instead of " + rows * cols); 138 } 139 140 for (int i = 0, r = 0; r < rows; r++) { 141 for (int c = 0; c < cols; c++) { 142 A[r][c] = values[i]; 143 i++; 144 } 145 } 146 return A; 147 } 148 149 /** 150 * <p> 151 * Creates and returns a {@link RealMatrix} containing the specified {@code double} values. Calls 152 * {@link #makeDoubleMatrix(int, int, double...)}. Example for creating a 2x3 matrix: 153 * </p> 154 * <pre> 155 * RealMatrix A = makeRealMatrix(2, 3, 156 * 1.0, 2.0, 3.0, 157 * 4.0, 5.0, 6.0 );</pre> 158 * <p> 159 * See also {@link #flatten(RealMatrix)}. 160 * </p> 161 * 162 * @param rows the number of matrix rows 163 * @param cols the number of matrix columns 164 * @param values a sequence of matrix values in row-major order (may also be passed as a {@code double[]}) 165 * @return a {@link RealMatrix} 166 */ 167 public static RealMatrix makeRealMatrix(final int rows, final int cols, final double... values) { 168 return MatrixUtils.createRealMatrix(makeDoubleMatrix(rows, cols, values)); 169 } 170 171 172 /** 173 * Returns the values of the specified matrix as a {@code double[]} with elements arranged in row-major order. The 174 * matrix must be fully rectangular (all rows of same length). See also 175 * {@link #makeDoubleMatrix(int, int, double...)}. 176 * 177 * @param A a matrix 178 * @return a {@code double[]} with the matrix elements 179 */ 180 public static double[] flatten(double[][] A) { 181 final int rows = A.length; 182 final int cols = A[0].length; 183 final double[] vals = new double[rows * cols]; 184 int i = 0; 185 for (int r = 0; r < rows; r++) { 186 for (int c = 0; c < cols; c++) { 187 vals[i] = A[r][c]; 188 i++; 189 } 190 } 191 return vals; 192 } 193 194 /** 195 * Returns the values of the specified matrix as a {@code float[]} with elements arranged in row-major order. The 196 * matrix must be fully rectangular (all rows of same length). See also 197 * {@link #makeFloatMatrix(int, int, float...)}. 198 * 199 * @param A a matrix 200 * @return a {@code float[]} with the matrix elements 201 */ 202 public static float[] flatten(float[][] A) { 203 final int rows = A.length; 204 final int cols = A[0].length; 205 final float[] vals = new float[rows * cols]; 206 int i = 0; 207 for (int r = 0; r < rows; r++) { 208 for (int c = 0; c < cols; c++) { 209 vals[i] = A[r][c]; 210 i++; 211 } 212 } 213 return vals; 214 } 215 216 /** 217 * Returns the values of the specified matrix as a {@code double[]} with elements arranged in row-major order. See 218 * also {@link #makeRealMatrix(int, int, double...)}. 219 * 220 * @param A a matrix 221 * @return a {@code double[]} with the matrix elements 222 */ 223 public static double[] flatten(RealMatrix A) { 224 return flatten(A.getData()); 225 } 226 227 // -------------------------------------------------------------------------- 228 229 /** 230 * Creates and returns a {@code double[]} vector from the specified values. 231 * 232 * @param values a sequence of vector values (may also be passed as a single {@code double[]}) 233 * @return a {@code double[]} 234 */ 235 public static double[] makeDoubleVector(double... values) { 236 return values; 237 } 238 239 /** 240 * Creates and returns a {@code float[]} vector from the specified values. 241 * 242 * @param values a sequence of vector values (may also be passed as a single {@code float[]}) 243 * @return a {@code float[]} 244 */ 245 public static float[] makeFloatVector(float... values) { 246 return values; 247 } 248 249 /** 250 * Creates and returns a {@link RealVector} from the specified {@code double} values. 251 * 252 * @param values a sequence of vector values (may also be passed as a single {@code double[]}) 253 * @return a {@link RealVector} 254 */ 255 public static RealVector makeRealVector(double... values) { 256 return MatrixUtils.createRealVector(values); 257// return new ArrayRealVector(values); 258 } 259 260 // Specific vector/matrix creation: 261 262 /** 263 * Creates and returns a new zero-valued {@code double[]} vector of the specified length. Throws an exception if the 264 * length is less than 1. 265 * 266 * @param length the length of the vector 267 * @return a {@code double[]} with zero values 268 */ 269 public static double[] zeroVector(int length) { 270 if (length < 1) 271 throw new IllegalArgumentException("vector size cannot be < 1"); 272 return new double[length]; 273 } 274 275 /** 276 * Creates and returns a new identity matrix of the specified size. Throws an exception if the size is less than 1. 277 * 278 * @param size the size of the matrix 279 * @return an identity matrix 280 */ 281 public static double[][] idMatrix(int size) { 282 if (size < 1) 283 throw new IllegalArgumentException("matrix size cannot be < 1"); 284 double[][] A = new double[size][size]; 285 for (int i = 0; i < size; i++) { 286 A[i][i] = 1; 287 } 288 return A; 289 } 290 291 // Matrix properties ------------------------------------- 292 293 /** 294 * Returns the number of rows of the specified {@code double} matrix. 295 * 296 * @param A a {@code double[][]} matrix 297 * @return the number of rows 298 */ 299 public static int getNumberOfRows(double[][] A) { 300 return A.length; 301 } 302 303 304 /** 305 * Returns the number of columns of the specified {@code double} matrix. 306 * 307 * @param A a {@code double[][]} matrix 308 * @return the number of columns 309 */ 310 public static int getNumberOfColumns(double[][] A) { 311 return A[0].length; 312 } 313 314 /** 315 * Returns the number of rows of the specified {@code float} matrix. 316 * 317 * @param A a {@code float[][]} matrix 318 * @return the number of rows 319 */ 320 public static int getNumberOfRows(float[][] A) { 321 return A.length; 322 } 323 324 /** 325 * Returns the number of columns of the specified {@code float} matrix. 326 * 327 * @param A a {@code float[][]} matrix 328 * @return the number of columns 329 */ 330 public static int getNumberOfColumns(float[][] A) { 331 return A[0].length; 332 } 333 334 /** 335 * Returns the number of rows of the specified {@link RealMatrix}. 336 * 337 * @param A a {@link RealMatrix} 338 * @return the number of rows 339 */ 340 public static int getNumberOfRows(RealMatrix A) { 341 return A.getRowDimension(); 342 } 343 344 /** 345 * Returns the number of columns of the specified {@link RealMatrix}. 346 * 347 * @param A a {@link RealMatrix} 348 * @return the number of columns 349 */ 350 public static int getNumberOfColumns(RealMatrix A) { 351 return A.getColumnDimension(); 352 } 353 354 // Extract rows or columns 355 356 /** 357 * Returns a particular row of the specified {@code double} matrix as a {@code double} vector. 358 * 359 * @param A a {@code double[][]} matrix 360 * @param r the row index (starting with 0) 361 * @return a {@code double} vector 362 */ 363 public static double[] getRow(double[][] A, int r) { 364 return A[r].clone(); 365 } 366 367 /** 368 * Returns a particular row of the specified {@code float} matrix as a {@code float} vector. 369 * 370 * @param A a {@code float[][]} matrix 371 * @param r the row index (starting with 0) 372 * @return a {@code float} vector 373 */ 374 public static float[] getRow(float[][] A, int r) { 375 return A[r].clone(); 376 } 377 378 /** 379 * Returns a particular column of the specified {@code double} matrix as a {@code double} vector. 380 * 381 * @param A a {@code double[][]} matrix 382 * @param c the column index (starting with 0) 383 * @return a {@code double} vector 384 */ 385 public static double[] getColumn(double[][] A, int c) { 386 final int rows = A.length; 387 double[] col = new double[rows]; 388 for (int r = 0; r < rows; r++) { 389 col[r] = A[r][c]; 390 } 391 return col; 392 } 393 394 /** 395 * Returns a particular column of the specified {@code float} matrix as a {@code float} vector. 396 * 397 * @param A a {@code float[][]} matrix 398 * @param c the column index (starting with 0) 399 * @return a {@code float} vector 400 */ 401 public static float[] getColumn(float[][] A, int c) { 402 final int rows = A.length; 403 float[] col = new float[rows]; 404 for (int r = 0; r < rows; r++) { 405 col[r] = A[r][c]; 406 } 407 return col; 408 } 409 410 // Checking vector/matrix dimensions 411 412 /** 413 * Checks if all rows of the given matrix have the same length. 414 * 415 * @param A a {@code float[][]} matrix 416 * @return true iff the matrix is rectangular 417 */ 418 public static boolean isRectangular(float[][] A) { 419 final int nCols = A[0].length; 420 for (int i = 1; i < A.length; i++) { 421 if (A[i].length != nCols) { 422 return false; 423 } 424 } 425 return true; 426 } 427 428 /** 429 * Checks if all rows of the given matrix have the same length. 430 * 431 * @param A a {@code double[][]} matrix 432 * @return true iff the matrix is rectangular 433 */ 434 public static boolean isRectangular(double[][] A) { 435 final int nCols = A[0].length; 436 for (int i = 1; i < A.length; i++) { 437 if (A[i].length != nCols) { 438 return false; 439 } 440 } 441 return true; 442 } 443 444 /** 445 * Checks it the given matrix has the same number of rows and columns. 446 * 447 * @param A a {@code double[][]} matrix 448 * @return true iff the matrix is square 449 */ 450 public static boolean isSquare(double[][] A) { 451 return A.length > 0 && A.length == A[0].length; 452 } 453 454 /** 455 * Checks it the given matrix has the same number of rows and columns. 456 * 457 * @param A a {@code float[][]} matrix 458 * @return true iff the matrix is square 459 */ 460 public static boolean isSquare(float[][] A) { 461 return A.length > 0 && A.length == A[0].length; 462 } 463 464 /** 465 * Returns a vector with the diagonal elements of the specified matrix. 466 * 467 * @param A a square {@code double[][]} matrix 468 * @return the vector of diagonal elements 469 */ 470 public static double[] getDiagonal(double[][] A) { 471 if (!isSquare(A)) { 472 throw new NonsquareMatrixException(); 473 } 474 final int n = A.length; 475 double[] diag = new double[n]; 476 for (int i = 0; i < n; i++) { 477 diag[i] = A[i][i]; 478 } 479 return diag; 480 } 481 482 /** 483 * Returns a vector with the diagonal elements of the specified matrix. 484 * 485 * @param A a square {@code float[][]} matrix 486 * @return the vector of diagonal elements 487 */ 488 public static float[] getDiagonal(float[][] A) { 489 if (!isSquare(A)) { 490 throw new NonsquareMatrixException(); 491 } 492 final int n = A.length; 493 float[] diag = new float[n]; 494 for (int i = 0; i < n; i++) { 495 diag[i] = A[i][i]; 496 } 497 return diag; 498 } 499 500 /** 501 * Returns a vector with the diagonal elements of the specified matrix. 502 * 503 * @param A a square {@link RealMatrix} 504 * @return the {@link RealVector} of diagonal elements 505 */ 506 public static RealVector getDiagonal(RealMatrix A) { 507 return MatrixUtils.createRealVector(getDiagonal(A.getData())); 508 } 509 510 /** 511 * Creates and returns a diagonal matrix from the specified vector. See also {@link #getDiagonal(double[][])}. 512 * 513 * @param d vector of diagonal matrix elements 514 * @return a diagonal matrix 515 */ 516 public double[][] diagMatrix(double[] d) { 517 return MatrixUtils.createRealDiagonalMatrix(d).getData(); 518 } 519 520 /** 521 * Checks is the given square {@code double[][]} matrix is non-singular. 522 * 523 * @param A a square {@code double[][]} matrix 524 * @return true if the matrix is singular 525 * @throws NonsquareMatrixException if the matrix is not square 526 */ 527 public static boolean isSingular(double[][] A) throws NonsquareMatrixException { 528 if (!Matrix.isSquare(A)) { 529 throw new NonsquareMatrixException(); 530 } 531 return isSingular(new Array2DRowRealMatrix(A)); 532 } 533 534 /** 535 * Checks is the given square matrix is non-singular. 536 * 537 * @param A a square {@link RealMatrix} 538 * @return true if the matrix is singular 539 * @throws NonsquareMatrixException if the matrix is not square 540 */ 541 public static boolean isSingular(RealMatrix A) throws NonsquareMatrixException { 542 if (!A.isSquare()) { 543 throw new NonsquareMatrixException(); 544 } 545 DecompositionSolver solver = new LUDecomposition(A).getSolver(); 546 return !solver.isNonSingular(); 547 } 548 549 /** 550 * Default matrix symmetry tolerance. 551 */ 552 public static final double DefaultSymmetryTolerance = 1e-12; 553 554 /** 555 * Checks is the given square matrix is symmetric using the specified relative tolerance. 556 * 557 * @param A a square matrix 558 * @param relTolerance relative symmetry tolerance 559 * @return true if the matrix is symmetric 560 */ 561 public static boolean isSymmetric(RealMatrix A, double relTolerance) { 562 return MatrixUtils.isSymmetric(A, relTolerance); 563 } 564 565 /** 566 * Checks is the given square matrix is symmetric, using the default tolerance value 567 * ({@link Arithmetic#EPSILON_DOUBLE}). 568 * 569 * @param A a square matrix 570 * @return true if the matrix is symmetric 571 */ 572 public static boolean isSymmetric(RealMatrix A) { 573 return isSymmetric(A, DefaultSymmetryTolerance); 574 } 575 576 /** 577 * Checks is the given square matrix is symmetric using the specified relative tolerance. 578 * 579 * @param A a square matrix 580 * @param relTolerance relative symmetry tolerance 581 * @return true if the matrix is symmetric 582 */ 583 public static boolean isSymmetric(double[][] A, double relTolerance) { 584 return MatrixUtils.isSymmetric(MatrixUtils.createRealMatrix(A), relTolerance); 585 } 586 587 /** 588 * Checks is the given square matrix is symmetric, using the default tolerance value 589 * ({@link Arithmetic#EPSILON_DOUBLE}). 590 * 591 * @param A a square matrix 592 * @return true if the matrix is symmetric 593 */ 594 public static boolean isSymmetric(double[][] A) { 595 return isSymmetric(A, DefaultSymmetryTolerance); 596 } 597 598 /** 599 * Checks is the given square matrix is positive definite, using the specified symmetry tolerance value. 600 * 601 * @param A a square matrix 602 * @param tolerance the absolute positivity and relative symmetry tolerance 603 * @return true if the matrix is positive definite 604 */ 605 public static boolean isPositiveDefinite(RealMatrix A, double tolerance) { // TODO: split tolerance in two parameters 606 try { 607 new CholeskyDecomposition(A, tolerance, tolerance); 608 return true; 609 } catch (NonPositiveDefiniteMatrixException e) { 610 return false; 611 } 612 } 613 614 /** 615 * Checks is the given square matrix is positive definite. 616 * 617 * @param A a square matrix 618 * @return true if the matrix is positive definite 619 */ 620 public static boolean isPositiveDefinite(RealMatrix A) { 621 return isPositiveDefinite(A, Arithmetic.EPSILON_DOUBLE); 622 } 623 624 /** 625 * Checks if the given vectors have the same length. 626 * 627 * @param a first vector 628 * @param b second vector 629 * @return true iff both vectors have the same length 630 */ 631 public static boolean sameSize(double[] a, double[] b) { 632 return a.length == b.length; 633 } 634 635 /** 636 * Checks if the given vectors have the same length. 637 * 638 * @param a first vector 639 * @param b second vector 640 * @return true iff both vectors have the same length 641 */ 642 public static boolean sameSize(float[] a, float[] b) { 643 return a.length == b.length; 644 } 645 646 /** 647 * Checks if the given matrices have the same size. 648 * 649 * @param A first matrix 650 * @param B second matrix 651 * @return true iff both matrices have the same size 652 */ 653 public static boolean sameSize(double[][] A, double[][] B) { 654 return (A.length == B.length) && (A[0].length == B[0].length); 655 } 656 657 /** 658 * Checks if the given matrices have the same size. 659 * 660 * @param A first matrix 661 * @param B second matrix 662 * @return true iff both matrices have the same size 663 */ 664 public static boolean sameSize(float[][] A, float[][] B) { 665 return (A.length == B.length) && (A[0].length == B[0].length); 666 } 667 668 // Matrix and vector duplication ------------------------------ 669 670 /** 671 * Returns a copy of the given {@code double[]} vector. 672 * 673 * @param a a {@code double[]} vector 674 * @return a copy of the vector 675 */ 676 public static double[] duplicate(final double[] a) { 677 return a.clone(); 678 } 679 680 /** 681 * Returns a copy of the given {@code float[]} vector. 682 * 683 * @param a a {@code float[]} vector 684 * @return a copy of the vector 685 */ 686 public static float[] duplicate(final float[] a) { 687 return a.clone(); 688 } 689 690 /** 691 * Returns a copy of the given {@code double[][]} matrix. 692 * 693 * @param A a {@code double[][]} matrix 694 * @return a copy of the matrix 695 */ 696 public static double[][] duplicate(final double[][] A) { 697 final int m = A.length; 698 final double[][] B = new double[m][]; 699 for (int i = 0; i < m; i++) { 700 B[i] = A[i].clone(); 701 } 702 return B; 703 } 704 705 /** 706 * Returns a copy of the given {@code float[][]} matrix. 707 * 708 * @param A a {@code float[][]} matrix 709 * @return a copy of the matrix 710 */ 711 public static float[][] duplicate(final float[][] A) { 712 final int m = A.length; 713 float[][] B = new float[m][]; 714 for (int i = 0; i < m; i++) { 715 B[i] = A[i].clone(); 716 } 717 return B; 718 } 719 720 // vector copying ------------------------------ 721 722 /** 723 * Copy data from one {@code float[]} vector to another. The two vectors must have the same length (not checked). 724 * 725 * @param source the source vector (unmodified) 726 * @param target the target vector (modified) 727 */ 728 public static void copyD(float[] source, float[] target) { 729 System.arraycopy(source, 0, target, 0, source.length); 730 } 731 732 /** 733 * Copy data from one {@code double[]} vector to another. The two vectors must have the same length (not checked). 734 * 735 * @param source the source vector (unmodified) 736 * @param target the target vector (modified) 737 */ 738 public static void copyD(double[] source, double[] target) { 739 System.arraycopy(source, 0, target, 0, source.length); 740 } 741 742 // ----- double <-> float conversions ----------------- 743 744 /** 745 * Converts a {@code double[]} to a {@code float[]}. 746 * 747 * @param a the original {@code double[]} array 748 * @return a copy of the array of type {@code float[]} 749 */ 750 public static float[] toFloat(final double[] a) { 751 final int m = a.length; 752 final float[] b = new float[m]; 753 for (int i = 0; i < m; i++) { 754 b[i] = (float) a[i]; 755 } 756 return b; 757 } 758 759 /** 760 * Converts a {@code double[][]} to a {@code float[][]}. 761 * 762 * @param A the original {@code double[][]} array 763 * @return a copy of the array of type {@code float[][]} 764 */ 765 public static float[][] toFloat(final double[][] A) { 766 final int m = A.length; 767 final int n = A[0].length; 768 final float[][] B = new float[m][n]; 769 for (int i = 0; i < m; i++) { 770 for (int j = 0; j < n; j++) { 771 B[i][j] = (float) A[i][j]; 772 } 773 } 774 return B; 775 } 776 777 /** 778 * Converts a {@code double[][]} to a {@code long[][]} whose elements contain the 64-bit representation of the 779 * original {@code double} values. Its printed representation is comparatively compact (see 780 * {@link #toString(long[][])}). This is useful for defining literal {@code double} arrays without losing any 781 * precision (by avoiding conversion to decimal representation). Note that the {@code long} are bit representations 782 * and cannot be used to perform any arithmetic calculations. 783 * 784 * @param A the original {@code double} array 785 * @return a copy of the array of type {@code float[][]} 786 * @see #fromLongBits(long[][]) 787 * @see #toString(long[][]) 788 * @see #printToStream(long[][], PrintStream) 789 */ 790 public static long[][] toLongBits(final double[][] A) { 791 final int m = A.length; 792 final int n = A[0].length; 793 final long[][] B = new long[m][n]; 794 for (int i = 0; i < m; i++) { 795 for (int j = 0; j < n; j++) { 796 B[i][j] = Double.doubleToLongBits(A[i][j]); 797 } 798 } 799 return B; 800 } 801 802 /** 803 * Converts a {@code long[][]} with 64-bit {@code double} representations to the equivalent {@code double[][]}. This 804 * is useful for defining literal {@code double} arrays without losing any precision (by avoiding conversion to 805 * decimal representation). 806 * 807 * @param A a {@code long} array 808 * @return the equivalent {@code double} array 809 * @see #toLongBits(double[][]) 810 */ 811 public static double[][] fromLongBits(final long[][] A) { 812 final int m = A.length; 813 final int n = A[0].length; 814 final double[][] B = new double[m][n]; 815 for (int i = 0; i < m; i++) { 816 for (int j = 0; j < n; j++) { 817 B[i][j] = Double.longBitsToDouble(A[i][j]); 818 } 819 } 820 return B; 821 } 822 823 /** 824 * Converts a {@code float[]} to a {@code double[]}. 825 * 826 * @param a the original {@code float[]} array 827 * @return a copy of the array of type {@code double[]} 828 */ 829 public static double[] toDouble(final float[] a) { 830 final int m = a.length; 831 final double[] B = new double[m]; 832 for (int i = 0; i < m; i++) { 833 B[i] = a[i]; 834 } 835 return B; 836 } 837 838 /** 839 * Converts a {@code float[][]} to a {@code double[][]}. 840 * 841 * @param A the original {@code float[][]} array 842 * @return a copy of the array of type {@code double[][]} 843 */ 844 public static double[][] toDouble(final float[][] A) { 845 final int m = A.length; 846 final int n = A[0].length; 847 final double[][] B = new double[m][n]; 848 for (int i = 0; i < m; i++) { 849 for (int j = 0; j < n; j++) { 850 B[i][j] = A[i][j]; 851 } 852 } 853 return B; 854 } 855 856 // ----------- fill operations (destructive) ------------------------ 857 858 /** 859 * Fills the given {@code double} vector with the specified value (destructively). 860 * 861 * @param x a vector (which is modified) 862 * @param val the fill value 863 */ 864 public static void fillD(final double[] x, double val) { 865 Arrays.fill(x, val); 866 } 867 868 /** 869 * Fills the given {@code float} vector with the specified value (destructively). 870 * 871 * @param x a vector (which is modified) 872 * @param val the fill value 873 */ 874 public static void fillD(final float[] x, float val) { 875 Arrays.fill(x, val); 876 } 877 878 /** 879 * Fills the given {@code double} matrix with the specified value (destructively). 880 * 881 * @param A a matrix (which is modified) 882 * @param val the fill value 883 */ 884 public static void fillD(final double[][] A, double val) { 885 for (int i = 0; i < A.length; i++) { 886 Arrays.fill(A[i], val); 887 } 888 } 889 890 /** 891 * Fills the given {@code float} matrix with the specified value (destructively). 892 * 893 * @param A a matrix (which is modified) 894 * @param val the fill value 895 */ 896 public static void fillD(final float[][] A, float val) { 897 for (int i = 0; i < A.length; i++) { 898 Arrays.fill(A[i], val); 899 } 900 } 901 902 903 // Element-wise arithmetic ------------------------------- 904 905 /** 906 * Calculates and returns the sum of the specified {@code double} vectors (non-destructively). An exception is 907 * thrown if the vectors are of different lengths. None of the arguments is modified. 908 * 909 * @param a the first vector 910 * @param b the second vector 911 * @return a new {@code double} vector 912 */ 913 public static double[] add(final double[] a, final double[] b) { 914 double[] c = b.clone(); 915 addD(a, c); 916 return c; 917 } 918 919 /** 920 * Adds the elements of the first {@code double} vector to the second vector (destructively). An exception is thrown 921 * if the vectors are of different lengths. The second vector is modified. 922 * 923 * @param a the first vector 924 * @param b the second vector 925 */ 926 public static void addD(final double[] a, final double[] b) { 927 if (!sameSize(a, b)) 928 throw new IncompatibleDimensionsException(); 929 for (int i = 0; i < a.length; i++) { 930 b[i] = a[i] + b[i]; 931 } 932 } 933 934 /** 935 * Calculates and returns the sum of the specified {@code float} vectors (non-destructively). An exception is thrown 936 * if the vectors are of different lengths. None of the arguments is modified. 937 * 938 * @param a the first vector 939 * @param b the second vector 940 * @return a new {@code float} vector 941 */ 942 public static float[] add(final float[] a, final float[] b) { 943 float[] c = b.clone(); 944 addD(a, c); 945 return c; 946 } 947 948 /** 949 * Adds the elements of the first {@code float} vector to the second vector (destructively). An exception is thrown 950 * if the vectors are of different lengths. The second vector is modified. 951 * 952 * @param a the first vector 953 * @param b the second vector 954 */ 955 public static void addD(final float[] a, final float[] b) { 956 if (!sameSize(a, b)) 957 throw new IncompatibleDimensionsException(); 958 for (int i = 0; i < a.length; i++) { 959 b[i] = a[i] + b[i]; 960 } 961 } 962 963 /** 964 * Calculates and returns the sum of the specified {@code double} matrix (non-destructively). An exception is thrown 965 * if the matrices are of different size. None of the arguments is modified. 966 * 967 * @param A the first matrix 968 * @param B the second matrix 969 * @return a new {@code double} matrix 970 */ 971 public static double[][] add(final double[][] A, final double[][] B) { 972 double[][] C = duplicate(B); 973 addD(A, C); 974 return C; 975 } 976 977 /** 978 * Adds the elements of the first {@code double} matrix to the second vector (destructively). An exception is thrown 979 * if the matrices are of different size. The second matrix is modified. 980 * 981 * @param A the first matrix 982 * @param B the second matrix 983 */ 984 public static void addD(final double[][] A, final double[][] B) { 985 if (!sameSize(A, B)) 986 throw new IncompatibleDimensionsException(); 987 for (int i = 0; i < A.length; i++) { 988 for (int j = 0; j < A[i].length; j++) { 989 B[i][j] = A[i][j] + B[i][j]; 990 } 991 } 992 } 993 994 /** 995 * Calculates and returns the sum of the specified {@code float} matrix (non-destructively). An exception is thrown 996 * if the matrices are of different size. None of the arguments is modified. 997 * 998 * @param A the first matrix 999 * @param B the second matrix 1000 * @return a new {@code float} matrix 1001 */ 1002 public static float[][] add(final float[][] A, final float[][] B) { 1003 float[][] C = duplicate(B); 1004 addD(A, C); 1005 return C; 1006 } 1007 1008 /** 1009 * Adds the elements of the first {@code float} matrix to the second vector (destructively). An exception is thrown 1010 * if the matrices are of different size. The second matrix is modified. 1011 * 1012 * @param A the first matrix 1013 * @param B the second matrix 1014 */ 1015 public static void addD(final float[][] A, final float[][] B) { 1016 if (!sameSize(A, B)) 1017 throw new IncompatibleDimensionsException(); 1018 for (int i = 0; i < A.length; i++) { 1019 for (int j = 0; j < A[i].length; j++) { 1020 B[i][j] = A[i][j] + B[i][j]; 1021 } 1022 } 1023 } 1024 1025 // ------------------------------------------------ 1026 1027 /** 1028 * Calculates and returns the difference (a - b) of the specified {@code double} vectors (non-destructively). An 1029 * exception is thrown if the vectors are of different lengths. None of the arguments is modified. 1030 * 1031 * @param a the first vector 1032 * @param b the second vector 1033 * @return a new {@code double} vector 1034 */ 1035 public static double[] subtract(final double[] a, final double[] b) { 1036 if (!sameSize(a, b)) 1037 throw new IncompatibleDimensionsException(); 1038 final int n = a.length; 1039 double[] c = new double[n]; 1040 for (int i = 0; i < n; i++) { 1041 c[i] = a[i] - b[i]; 1042 } 1043 return c; 1044 } 1045 1046 // non-destructive a - b 1047 1048 /** 1049 * Calculates and returns the difference (a - b) of the specified {@code float} vectors (non-destructively). An 1050 * exception is thrown if the vectors are of different lengths. None of the arguments is modified. 1051 * 1052 * @param a the first vector 1053 * @param b the second vector 1054 * @return a new {@code float} vector 1055 */ 1056 public static float[] subtract(final float[] a, final float[] b) { 1057 if (!sameSize(a, b)) 1058 throw new IncompatibleDimensionsException(); 1059 final int n = a.length; 1060 float[] c = new float[n]; 1061 for (int i = 0; i < n; i++) { 1062 c[i] = a[i] - b[i]; 1063 } 1064 return c; 1065 } 1066 1067 // Scalar multiplications ------------------------------- 1068 1069 // non-destructive 1070 1071 /** 1072 * Multiplies a {@code double[]} vector by a scalar and returns a new {@code double[]} vector (non-destructive). 1073 * 1074 * @param s a scalar 1075 * @param x a vector 1076 * @return a new vector 1077 */ 1078 public static double[] multiply(final double s, final double[] x) { 1079 double[] b = x.clone(); 1080 multiplyD(s, b); 1081 return b; 1082 } 1083 1084 // destructive 1085 1086 /** 1087 * Multiplies a {@code double[]} vector by a scalar. Destructive, i.e., the specified vector is modified. 1088 * 1089 * @param s a scalar 1090 * @param x a vector 1091 */ 1092 public static void multiplyD(final double s, final double[] x) { 1093 for (int i = 0; i < x.length; i++) { 1094 x[i] = x[i] * s; 1095 } 1096 } 1097 1098 // non-destructive 1099 1100 /** 1101 * Multiplies a {@code double[][]} matrix by a scalar and returns a new {@code double[][]} matrix 1102 * (non-destructive). 1103 * 1104 * @param s a scalar 1105 * @param A a matrix 1106 * @return a new matrix 1107 */ 1108 public static double[][] multiply(final double s, final double[][] A) { 1109 double[][] B = duplicate(A); 1110 multiplyD(s, B); 1111 return B; 1112 } 1113 1114 /** 1115 * Multiplies a {@code double[][]} matrix by a scalar. Destructive, i.e., the specified matrix is modified. 1116 * 1117 * @param s a scalar 1118 * @param A a matrix 1119 */ 1120 public static void multiplyD(final double s, final double[][] A) { 1121 for (int i = 0; i < A.length; i++) { 1122 for (int j = 0; j < A[i].length; j++) { 1123 A[i][j] = A[i][j] * s; 1124 } 1125 } 1126 } 1127 1128 // non-destructive 1129 1130 /** 1131 * Multiplies a {@code float[]} vector by a scalar and returns a new {@code float[]} vector (non-destructive). 1132 * 1133 * @param s a scalar 1134 * @param x a vector 1135 * @return a new vector 1136 */ 1137 public static float[] multiply(final float s, final float[] x) { 1138 float[] B = duplicate(x); 1139 multiplyD(s, B); 1140 return B; 1141 } 1142 1143 // destructive 1144 1145 /** 1146 * Multiplies a {@code float[]} vector by a scalar. Destructive, i.e., the specified vector is modified. 1147 * 1148 * @param s a scalar 1149 * @param x a matrix 1150 */ 1151 public static void multiplyD(final float s, final float[] x) { 1152 for (int i = 0; i < x.length; i++) { 1153 x[i] = x[i] * s; 1154 } 1155 } 1156 1157 // non-destructive 1158 1159 /** 1160 * Multiplies a {@code float[][]} matrix by a scalar and returns a new {@code float[][]} matrix (non-destructive). 1161 * 1162 * @param s a scalar 1163 * @param A a matrix 1164 * @return a new matrix 1165 */ 1166 public static float[][] multiply(final float s, final float[][] A) { 1167 float[][] B = duplicate(A); 1168 multiplyD(s, B); 1169 return B; 1170 } 1171 1172 // destructive 1173 1174 /** 1175 * Multiplies a {@code float[][]} matrix by a scalar. Destructive, i.e., the specified matrix is modified. 1176 * 1177 * @param s a scalar 1178 * @param A a matrix 1179 */ 1180 public static void multiplyD(final float s, final float[][] A) { 1181 for (int i = 0; i < A.length; i++) { 1182 for (int j = 0; j < A[i].length; j++) { 1183 A[i][j] = A[i][j] * s; 1184 } 1185 } 1186 } 1187 1188 // matrix-vector multiplications ---------------------------------------- 1189 1190 /** 1191 * Multiplies a vector x with a matrix A "from the left", i.e., y = x * A, where x is treated as a row vector and 1192 * the result y is also a row vector. 1193 * 1194 * @param x a (row) vector of length m 1195 * @param A a matrix of size (m,n) 1196 * @return a (row) vector of length n 1197 */ 1198 public static double[] multiply(final double[] x, final double[][] A) { 1199 double[] y = new double[getNumberOfColumns(A)]; 1200 multiplyD(x, A, y); 1201 return y; 1202 } 1203 1204 /** 1205 * Destructive version of {@link #multiply(double[], double[][])}. 1206 * 1207 * @param x a (row) vector of length m 1208 * @param A matrix of size (m,n) 1209 * @param y a (row) vector of length n 1210 */ 1211 public static void multiplyD(final double[] x, final double[][] A, double[] y) { 1212 if (x == y) 1213 throw new SameSourceTargetException(); 1214 final int m = getNumberOfRows(A); 1215 final int n = getNumberOfColumns(A); 1216 if (x.length != m || y.length != n) 1217 throw new IncompatibleDimensionsException(); 1218 for (int i = 0; i < n; i++) { 1219 double s = 0; 1220 for (int j = 0; j < m; j++) { 1221 s = s + x[j] * A[j][i]; 1222 } 1223 y[i] = s; 1224 } 1225 } 1226 1227 /** 1228 * Multiplies a matrix A with a vector x "from the right", i.e., y = A * x, where x is treated as a column vector 1229 * and the result y is also a column vector. 1230 * 1231 * @param x a (column) vector of length n 1232 * @param A a matrix of size (m,n) 1233 * @return a (column) vector of length m 1234 */ 1235 public static double[] multiply(final double[][] A, final double[] x) { 1236 double[] y = new double[getNumberOfRows(A)]; 1237 multiplyD(A, x, y); 1238 return y; 1239 } 1240 1241 /** 1242 * Multiplies a matrix A with a vector x "from the right", i.e., y = A * x, where x is treated as a column vector 1243 * and the result y is also a column vector. The result is placed in the vector passed as the last argument, which 1244 * is modified. Destructive version of {@link #multiply(double[][], double[])}. An exception is thrown if any matrix 1245 * or vector dimensions do not match or if the two vectors are the same. 1246 * 1247 * @param A matrix of size (m,n) 1248 * @param x a (column) vector of length n 1249 * @param y a (column) vector of length m 1250 */ 1251 public static void multiplyD(final double[][] A, final double[] x, double[] y) { 1252 if (x == y) 1253 throw new SameSourceTargetException(); 1254 final int m = getNumberOfRows(A); 1255 final int n = getNumberOfColumns(A); 1256 if (x.length != n || y.length != m) 1257 throw new IncompatibleDimensionsException(); 1258 for (int i = 0; i < m; i++) { 1259 double s = 0; 1260 for (int j = 0; j < n; j++) { 1261 s = s + A[i][j] * x[j]; 1262 } 1263 y[i] = s; 1264 } 1265 } 1266 1267 /** 1268 * Multiplies a matrix A with a vector x from the right, i.e., y = A * x, where x is treated as a column vector and 1269 * the result y is also a column vector. 1270 * 1271 * @param x a (column) vector of length n 1272 * @param A a matrix of size (m,n) 1273 * @return a (column) vector of length m 1274 */ 1275 public static float[] multiply(final float[][] A, final float[] x) { 1276 float[] y = new float[getNumberOfRows(A)]; 1277 multiplyD(A, x, y); 1278 return y; 1279 } 1280 1281 /** 1282 * Multiplies a matrix A with a vector x "from the right", i.e., y = A * x, where x is treated as a column vector 1283 * and the result y is also a column vector. The result is placed in the vector passed as the last argument, which 1284 * is modified. Destructive version of {@link #multiply(float[][], float[])}. An exception is thrown if any matrix 1285 * or vector dimensions do not match or if the two vectors are the same. 1286 * 1287 * @param A matrix of size (m,n) 1288 * @param x a (column) vector of length n 1289 * @param y a (column) vector of length m 1290 */ 1291 public static void multiplyD(final float[][] A, final float[] x, float[] y) { 1292 if (x == y) 1293 throw new SameSourceTargetException(); 1294 final int m = getNumberOfRows(A); 1295 final int n = getNumberOfColumns(A); 1296 if (x.length != n || y.length != m) 1297 throw new IncompatibleDimensionsException(); 1298 for (int i = 0; i < m; i++) { 1299 double s = 0; 1300 for (int j = 0; j < n; j++) { 1301 s = s + A[i][j] * x[j]; 1302 } 1303 y[i] = (float) s; 1304 } 1305 } 1306 1307 1308 // Matrix-matrix products --------------------------------------- 1309 1310 // returns A * B (non-destructive) 1311 1312 /** 1313 * Returns the product of two {@code double[][]} matrices A, B as a new {@code double[][]} matrix. Non-destructive, 1314 * i.e., none of the arguments is modified. 1315 * 1316 * @param A first matrix 1317 * @param B second matrix 1318 * @return the matrix product A * B 1319 */ 1320 public static double[][] multiply(final double[][] A, final double[][] B) { 1321 final int nA = getNumberOfColumns(A); 1322 final int mB = getNumberOfRows(B); 1323 if (nA != mB) 1324 throw new IncompatibleDimensionsException(); // check size of A, B 1325 int ma = getNumberOfRows(A); 1326 int nb = getNumberOfColumns(B); 1327 double[][] C = makeDoubleMatrix(ma, nb); 1328 multiplyD(A, B, C); 1329 return C; 1330 } 1331 1332 // A * B -> C (destructive) 1333 1334 /** 1335 * Calculates the product of two {@code double[][]} matrices A, B and places the results in the third 1336 * {@code double[][]} matrix C, which is modified (destructively). An exception is thrown if any matrix dimensions 1337 * do not match or if the target matrix is the same as one of the source matrices. 1338 * 1339 * @param A first matrix 1340 * @param B second matrix 1341 * @param C the result matrix 1342 * @throws SameSourceTargetException if the target matrix is the same as one of the source matrices 1343 * @throws IncompatibleDimensionsException if any matrix dimensions do not match 1344 */ 1345 public static void multiplyD(final double[][] A, final double[][] B, final double[][] C) 1346 throws SameSourceTargetException, IncompatibleDimensionsException { 1347 if (A == C || B == C) 1348 throw new SameSourceTargetException(); 1349 final int mA = getNumberOfRows(A); 1350 final int nA = getNumberOfColumns(A); 1351 final int mB = getNumberOfRows(B); 1352 final int nB = getNumberOfColumns(B); 1353 if (nA != mB) 1354 throw new IncompatibleDimensionsException(); // check size of A, B 1355 if (mA != getNumberOfRows(C) || nB != getNumberOfColumns(C)) 1356 throw new IncompatibleDimensionsException(); // check size of C 1357 1358 for (int i = 0; i < mA; i++) { 1359 for (int j = 0; j < nB; j++) { 1360 double s = 0; 1361 for (int k = 0; k < nA; k++) { 1362 s = s + A[i][k] * B[k][j]; 1363 } 1364 C[i][j] = s; 1365 } 1366 } 1367 } 1368 1369 // returns A * B (non-destructive) 1370 1371 /** 1372 * Returns the product of two {@code float[][]} matrices A, B as a new {@code float[][]} matrix. Non-destructive, 1373 * i.e., none of the arguments is modified. 1374 * 1375 * @param A first matrix 1376 * @param B second matrix 1377 * @return the matrix product A * B 1378 */ 1379 public static float[][] multiply(final float[][] A, final float[][] B) { 1380 final int nA = getNumberOfColumns(A); 1381 final int mB = getNumberOfRows(B); 1382 if (nA != mB) 1383 throw new IncompatibleDimensionsException(); // check size of A, B 1384 final int mA = getNumberOfRows(A); 1385 final int nB = getNumberOfColumns(B); 1386 float[][] C = makeFloatMatrix(mA, nB); 1387 multiplyD(A, B, C); 1388 return C; 1389 } 1390 1391 // A * B -> C (destructive) 1392 1393 /** 1394 * Calculates the product of two {@code float[][]} matrices A, B and places the results in the third 1395 * {@code float[][]} matrix C, which is modified (destructively). An exception is thrown if any matrix dimensions do 1396 * not match or if the target matrix is the same as one of the source matrices. 1397 * 1398 * @param A first matrix 1399 * @param B second matrix 1400 * @param C the result matrix 1401 */ 1402 public static void multiplyD(final float[][] A, final float[][] B, final float[][] C) { 1403 if (A == C || B == C) 1404 throw new SameSourceTargetException(); 1405 final int mA = getNumberOfRows(A); 1406 final int nA = getNumberOfColumns(A); 1407 final int mB = getNumberOfRows(B); 1408 final int nB = getNumberOfColumns(B); 1409 if (nA != mB) 1410 throw new IncompatibleDimensionsException(); // check size of A,B 1411 if (mA != getNumberOfRows(C) || nB != getNumberOfColumns(C)) 1412 throw new IncompatibleDimensionsException(); // check size of C 1413 for (int i = 0; i < mA; i++) { 1414 for (int j = 0; j < nB; j++) { 1415 float s = 0; 1416 for (int k = 0; k < nA; k++) { 1417 s = s + A[i][k] * B[k][j]; 1418 } 1419 C[i][j] = s; 1420 } 1421 } 1422 } 1423 1424 // Vector-vector products --------------------------------------- 1425 1426 /** 1427 * Calculates and returns the dot (inner or scalar) product of two vectors, which must have the same length. Throws 1428 * an exceptions if vector dimensions do not match. 1429 * 1430 * @param a first vector 1431 * @param b second vector 1432 * @return the dot product 1433 */ 1434 public static double dotProduct(final double[] a, final double[] b) { 1435 if (!sameSize(a, b)) 1436 throw new IncompatibleDimensionsException(); 1437 double sum = 0; 1438 for (int i = 0; i < a.length; i++) { 1439 sum = sum + a[i] * b[i]; 1440 } 1441 return sum; 1442 } 1443 1444 // a is considered a column vector, b is a row vector, of length m, n, resp. 1445 // returns a matrix M of size (m,n). 1446 1447 /** 1448 * Calculates and returns the outer product of two vectors, which is a matrix of size (m,n), where m is the length 1449 * of the first vector and m is the length of the second vector. 1450 * 1451 * @param a first (column) vector (of length m) 1452 * @param b second (row) vector (of length n) 1453 * @return the outer product (matrix) 1454 */ 1455 public static double[][] outerProduct(final double[] a, final double[] b) { 1456 final int m = a.length; 1457 final int n = b.length; 1458 final double[][] M = new double[m][n]; 1459 for (int i = 0; i < m; i++) { 1460 for (int j = 0; j < n; j++) { 1461 M[i][j] = a[i] * b[j]; 1462 } 1463 } 1464 return M; 1465 } 1466 1467 // Vector norms --------------------------------------------------- 1468 1469 /** 1470 * Calculates and returns the L1 norm of the given vector. 1471 * 1472 * @param a a vector 1473 * @return the L1 norm of the vector 1474 */ 1475 public static double normL1(final double[] a) { 1476 double sum = 0; 1477 for (double val : a) { 1478 sum = sum + Math.abs(val); 1479 } 1480 return sum; 1481 } 1482 1483 /** 1484 * Calculates and returns the L1 norm of the given vector. 1485 * 1486 * @param a a vector 1487 * @return the L1 norm of the vector 1488 */ 1489 public static float normL1(final float[] a) { 1490 double sum = 0; 1491 for (double val : a) { 1492 sum = sum + Math.abs(val); 1493 } 1494 return (float) sum; 1495 } 1496 1497 /** 1498 * Calculates and returns the L2 norm of the given vector. 1499 * 1500 * @param a a vector 1501 * @return the L2 norm of the vector 1502 */ 1503 public static double normL2(final double[] a) { 1504 return Math.sqrt(normL2squared(a)); 1505 } 1506 1507 /** 1508 * Calculates and returns the squared L2 norm of the given vector. The squared norm is less costly to calculate (no 1509 * square root needed) than the L2 norm and is thus often used for efficiency. 1510 * 1511 * @param a a vector 1512 * @return the squared L2 norm of the vector 1513 */ 1514 public static double normL2squared(final double[] a) { 1515 double sum = 0; 1516 for (double val : a) { 1517 sum = sum + sqr(val); 1518 } 1519 return sum; 1520 } 1521 1522 /** 1523 * Calculates and returns the L2 norm of the given vector. 1524 * 1525 * @param x a vector 1526 * @return the L2 norm of the vector 1527 */ 1528 public static float normL2(final float[] x) { 1529 return (float) Math.sqrt(normL2squared(x)); 1530 } 1531 1532 /** 1533 * Calculates and returns the squared L2 norm of the given vector. The squared norm is less costly to calculate (no 1534 * square root needed) than the L2 norm and is thus often used for efficiency. 1535 * 1536 * @param a a vector 1537 * @return the squared L2 norm of the vector 1538 */ 1539 public static double normL2squared(final float[] a) { 1540 double sum = 0; 1541 for (double val : a) { 1542 sum = sum + sqr(val); 1543 } 1544 return sum; 1545 } 1546 1547 // Normalize vectors 1548 1549 /** 1550 * Normalizes the specified {@code double[]} vector to unit (L2) norm and returns the result as a new 1551 * {@code double[]} vector. 1552 * 1553 * @param a a vector 1554 * @return the normalized vector 1555 */ 1556 public static double[] normalize(final double[] a) { 1557 double[] xx = duplicate(a); 1558 normalizeD(xx); 1559 return xx; 1560 } 1561 1562 /** 1563 * Normalizes the specified {@code double[]} vector to unit (L2) norm. The vector is modified (destructively). 1564 * 1565 * @param a a vector 1566 */ 1567 public static void normalizeD(final double[] a) { 1568 double normx = normL2(a); 1569 if (Arithmetic.isZero(normx)) 1570 throw new IllegalArgumentException("cannot normalize zero-norm vector " + Matrix.toString(a)); 1571 multiplyD(1.0 / normx, a); 1572 } 1573 1574 /** 1575 * Normalizes the specified {@code float[]} vector to unit (L2) norm and returns the result as a new {@code float[]} 1576 * vector. 1577 * 1578 * @param a a vector 1579 * @return the normalized vector 1580 */ 1581 public static float[] normalize(final float[] a) { 1582 float[] xx = duplicate(a); 1583 normalizeD(xx); 1584 return xx; 1585 } 1586 1587 /** 1588 * Normalizes the specified {@code float[]} vector to unit (L2) norm. The vector is modified (destructively). 1589 * 1590 * @param a a vector 1591 */ 1592 public static void normalizeD(final float[] a) { 1593 double normx = normL2(a); 1594 if (Arithmetic.isZero(normx)) 1595 throw new IllegalArgumentException("cannot normalize zero-norm vector"); 1596 multiplyD((float) (1.0 / normx), a); 1597 } 1598 1599 // Distance between vectors --------------------------------------- 1600 1601 /** 1602 * Calculates the L2 distance between two vectors (points) in n-dimensional space. Both vectors must have the same 1603 * number of elements. 1604 * 1605 * @param a first vector 1606 * @param b second vector 1607 * @return the distance 1608 */ 1609 public static double distL2(double[] a, double[] b) { 1610 return Math.sqrt(distL2squared(a, b)); 1611 } 1612 1613 /** 1614 * Calculates the squared L2 distance between two vectors (points) in n-dimensional space. Both vectors must have 1615 * the same number of elements. 1616 * 1617 * @param a first vector 1618 * @param b second vector 1619 * @return the squared distance 1620 */ 1621 public static double distL2squared(double[] a, double[] b) { 1622 double sum = 0; 1623 for (int i = 0; i < a.length; i++) { 1624 sum = sum + sqr(a[i] - b[i]); 1625 } 1626 return sum; 1627 } 1628 1629 /** 1630 * Calculates the L2 distance between two vectors (points) in n-dimensional space. Both vectors must have the same 1631 * number of elements. 1632 * 1633 * @param a first vector 1634 * @param b second vector 1635 * @return the distance 1636 */ 1637 public static float distL2(float[] a, float[] b) { 1638 return (float) Math.sqrt(distL2squared(a, b)); 1639 } 1640 1641 /** 1642 * Calculates the squared L2 distance between two vectors (points) in n-dimensional space. Both vectors must have 1643 * the same number of elements. 1644 * 1645 * @param a first vector 1646 * @param b second vector 1647 * @return the squared distance 1648 */ 1649 public static float distL2squared(float[] a, float[] b) { 1650 double sum = 0; 1651 for (int i = 0; i < a.length; i++) { 1652 sum = sum + sqr(a[i] - b[i]); 1653 } 1654 return (float) sum; 1655 } 1656 1657 // Matrix (Froebenius) norm --------------------------------------- 1658 1659 /** 1660 * Calculates and returns the Froebenius norm of the given matrix. 1661 * 1662 * @param A a matrix 1663 * @return the norm of the matrix 1664 */ 1665 public static double norm(final double[][] A) { 1666 final int m = getNumberOfRows(A); 1667 final int n = getNumberOfColumns(A); 1668 double s = 0; 1669 for (int i = 0; i < m; i++) { 1670 for (int j = 0; j < n; j++) { 1671 s = s + sqr(A[i][j]); 1672 } 1673 } 1674 return Math.sqrt(s); 1675 } 1676 1677 // Summation -------------------------------------------------- 1678 1679 /** 1680 * Calculates and returns the sum of the elements in the specified {@code double[]} vector. 1681 * 1682 * @param a a vector 1683 * @return the sum of vector elements 1684 */ 1685 public static double sum(final double[] a) { 1686 double sum = 0; 1687 for (int i = 0; i < a.length; i++) { 1688 sum = sum + a[i]; 1689 } 1690 return sum; 1691 } 1692 1693 /** 1694 * Calculates and returns the sum of the elements in the specified {@code double[][]} matrix. 1695 * 1696 * @param A a matrix 1697 * @return the sum of matrix elements 1698 */ 1699 public static double sum(final double[][] A) { 1700 double sum = 0; 1701 for (int i = 0; i < A.length; i++) { 1702 for (int j = 0; j < A[i].length; j++) { 1703 sum = sum + A[i][j]; 1704 } 1705 } 1706 return sum; 1707 } 1708 1709 /** 1710 * Calculates and returns the sum of the elements in the specified {@code float[]} vector. 1711 * 1712 * @param a a vector 1713 * @return the sum of vector elements 1714 */ 1715 public static double sum(final float[] a) { 1716 double sum = 0; 1717 for (int i = 0; i < a.length; i++) { 1718 sum = sum + a[i]; 1719 } 1720 return sum; 1721 } 1722 1723 /** 1724 * Calculates and returns the sum of the elements in the specified {@code float[][]} matrix. 1725 * 1726 * @param A a matrix 1727 * @return the sum of matrix elements 1728 */ 1729 public static double sum(final float[][] A) { 1730 double sum = 0; 1731 for (int i = 0; i < A.length; i++) { 1732 for (int j = 0; j < A[i].length; j++) { 1733 sum = sum + A[i][j]; 1734 } 1735 } 1736 return sum; 1737 } 1738 1739 // -------------------------------------------------- 1740 1741 /** 1742 * Calculates the sum of the elements in the specified matrix row. 1743 * 1744 * @param A a matrix 1745 * @param row the row index 1746 * @return the sum of the row's elements 1747 */ 1748 public static double sumRow(final double[][] A, final int row) { 1749 return sum(A[row]); 1750 } 1751 1752 /** 1753 * Calculates the sum of the elements in the specified matrix row. 1754 * 1755 * @param A a matrix 1756 * @param row the row index 1757 * @return the sum of the row's elements 1758 */ 1759 public static double sumRow(final float[][] A, final int row) { 1760 return sum(A[row]); 1761 } 1762 1763 1764 /** 1765 * Calculates the sum of the elements in the specified matrix column. 1766 * 1767 * @param A a matrix 1768 * @param col the column index 1769 * @return the sum of the column's elements 1770 */ 1771 public static double sumColumn(final double[][] A, final int col) { 1772 double sum = 0; 1773 for (int r = 0; r < A.length; r++) { 1774 sum = sum + A[r][col]; 1775 } 1776 return sum; 1777 } 1778 1779 /** 1780 * Calculates the sum of the elements in the specified matrix column. 1781 * 1782 * @param A a matrix 1783 * @param col the column index 1784 * @return the sum of the column's elements 1785 */ 1786 public static double sumColumn(final float[][] A, final int col) { 1787 double sum = 0; 1788 for (int r = 0; r < A.length; r++) { 1789 sum = sum + A[r][col]; 1790 } 1791 return sum; 1792 } 1793 1794 /** 1795 * Calculates the sums of all matrix rows and returns them as a vector with one element per row. 1796 * 1797 * @param A a matrix of size (M,N) 1798 * @return a vector of length M containing the sums of all matrix columns 1799 */ 1800 public static double[] sumRows(final double[][] A) { 1801 double[] sumVec = new double[getNumberOfRows(A)]; 1802 for (int i = 0; i < sumVec.length; i++) { 1803 double sum = 0; 1804 for (int j = 0; j < A[i].length; j++) { 1805 sum = sum + A[i][j]; 1806 } 1807 sumVec[i] = sum; 1808 } 1809 return sumVec; 1810 } 1811 1812 /** 1813 * Calculates the sums of all matrix rows and returns them as a vector with one element per row. 1814 * 1815 * @param A a matrix of size (M,N) 1816 * @return a vector of length M containing the sums of all matrix columns 1817 */ 1818 public static float[] sumRows(final float[][] A) { 1819 float[] sumVec = new float[getNumberOfRows(A)]; 1820 for (int i = 0; i < sumVec.length; i++) { 1821 double sum = 0; 1822 for (int j = 0; j < A[i].length; j++) { 1823 sum = sum + A[i][j]; 1824 } 1825 sumVec[i] = (float) sum; 1826 } 1827 return sumVec; 1828 } 1829 1830 /** 1831 * Calculates the sums of all matrix columns and returns them as a vector with one element per column. 1832 * 1833 * @param A a matrix of size (M,N) 1834 * @return a vector of length N containing the sums of all matrix rows 1835 */ 1836 public static double[] sumColumns(final double[][] A) { 1837 double[] sumVec = new double[getNumberOfColumns(A)]; 1838 for (int c = 0; c < sumVec.length; c++) { 1839 double sum = 0; 1840 for (int r = 0; r < A.length; r++) { 1841 sum = sum + A[r][c]; 1842 } 1843 sumVec[c] = sum; 1844 } 1845 return sumVec; 1846 } 1847 1848 /** 1849 * Calculates the sums of all matrix columns and returns them as a vector with one element per column. 1850 * 1851 * @param A a matrix of size (M,N) 1852 * @return a vector of length N containing the sums of all matrix rows 1853 */ 1854 public static float[] sumColumns(final float[][] A) { 1855 float[] sumVec = new float[getNumberOfColumns(A)]; 1856 for (int c = 0; c < sumVec.length; c++) { 1857 double sum = 0; 1858 for (int r = 0; r < A.length; r++) { 1859 sum = sum + A[r][c]; 1860 } 1861 sumVec[c] = (float) sum; 1862 } 1863 return sumVec; 1864 } 1865 1866 // min/max of vectors ------------------------ 1867 1868 /** 1869 * Returns the index of the smallest element in the specified vector. If the smallest value is not unique, the 1870 * lowest index is returned. An exception is thrown if the vector has zero length. 1871 * 1872 * @param a a vector 1873 * @return the index of the smallest value 1874 */ 1875 public static int idxMin(double[] a) { 1876 if (a.length == 0) 1877 throw new ZeroLengthVectorException(); 1878 double minval = a[0]; 1879 int minidx = 0; 1880 for (int i = 1; i < a.length; i++) { 1881 if (a[i] < minval) { 1882 minval = a[i]; 1883 minidx = i; 1884 } 1885 } 1886 return minidx; 1887 } 1888 1889 /** 1890 * Returns the index of the smallest element in the specified vector. If the smallest value is not unique, the 1891 * lowest index is returned. An exception is thrown if the vector has zero length. 1892 * 1893 * @param a a vector 1894 * @return the index of the smallest value 1895 */ 1896 public static int idxMin(float[] a) { 1897 if (a.length == 0) 1898 throw new ZeroLengthVectorException(); 1899 float minval = a[0]; 1900 int minidx = 0; 1901 for (int i = 1; i < a.length; i++) { 1902 if (a[i] < minval) { 1903 minval = a[i]; 1904 minidx = i; 1905 } 1906 } 1907 return minidx; 1908 } 1909 1910 1911 /** 1912 * Returns the index of the largest element in the specified vector. If the largest value is not unique, the lowest 1913 * index is returned. An exception is thrown if the vector has zero length. 1914 * 1915 * @param a a vector 1916 * @return the index of the largest value 1917 */ 1918 public static int idxMax(double[] a) { 1919 if (a.length == 0) 1920 throw new ZeroLengthVectorException(); 1921 double maxval = a[0]; 1922 int maxidx = 0; 1923 for (int i = 1; i < a.length; i++) { 1924 if (a[i] > maxval) { 1925 maxval = a[i]; 1926 maxidx = i; 1927 } 1928 } 1929 return maxidx; 1930 } 1931 1932 /** 1933 * Returns the index of the largest element in the specified vector. If the largest value is not unique, the lowest 1934 * index is returned. An exception is thrown if the vector has zero length. 1935 * 1936 * @param a a vector 1937 * @return the index of the largest value 1938 */ 1939 public static int idxMax(float[] a) { 1940 if (a.length == 0) 1941 throw new ZeroLengthVectorException(); 1942 float maxval = a[0]; 1943 int maxidx = 0; 1944 for (int i = 1; i < a.length; i++) { 1945 if (a[i] > maxval) { 1946 maxval = a[i]; 1947 maxidx = i; 1948 } 1949 } 1950 return maxidx; 1951 } 1952 1953 1954 /** 1955 * Returns the smallest value in the specified vector. An exception is thrown if the vector has zero length. 1956 * 1957 * @param a a vector 1958 * @return the largest value 1959 */ 1960 public static float min(final float[] a) { 1961 if (a.length == 0) 1962 throw new ZeroLengthVectorException(); 1963 float minval = Float.POSITIVE_INFINITY; 1964 for (float val : a) { 1965 if (val < minval) { 1966 minval = val; 1967 } 1968 } 1969 return minval; 1970 } 1971 1972 /** 1973 * Returns the smallest value in the specified vector. An exception is thrown if the vector has zero length. 1974 * 1975 * @param a a vector 1976 * @return the largest value 1977 */ 1978 public static double min(final double[] a) { 1979 if (a.length == 0) 1980 throw new ZeroLengthVectorException(); 1981 double minval = Double.POSITIVE_INFINITY; 1982 for (double val : a) { 1983 if (val < minval) { 1984 minval = val; 1985 } 1986 } 1987 return minval; 1988 } 1989 1990 /** 1991 * Returns the largest value in the specified {@code double[]} vector. An exception is thrown if the vector has zero 1992 * length. 1993 * 1994 * @param a a vector 1995 * @return the largest value 1996 */ 1997 public static double max(final double[] a) { 1998 if (a.length == 0) 1999 throw new ZeroLengthVectorException(); 2000 double maxval = Double.NEGATIVE_INFINITY; 2001 for (double val : a) { 2002 if (val > maxval) { 2003 maxval = val; 2004 } 2005 } 2006 return maxval; 2007 } 2008 2009 /** 2010 * Returns the largest value in the specified {@code float[]} vector. An exception is thrown if the vector has zero 2011 * length. 2012 * 2013 * @param a a vector 2014 * @return the largest value 2015 */ 2016 public static float max(final float[] a) { 2017 if (a.length == 0) 2018 throw new ZeroLengthVectorException(); 2019 float maxval = Float.NEGATIVE_INFINITY; 2020 for (float val : a) { 2021 if (val > maxval) { 2022 maxval = val; 2023 } 2024 } 2025 return maxval; 2026 } 2027 2028 /** 2029 * Returns the largest value in the specified {@code double[][]} matrix. 2030 * 2031 * @param A a matrix 2032 * @return the largest matrix value 2033 */ 2034 public static double max(double[][] A) { 2035 double maxval = Double.NEGATIVE_INFINITY; 2036 for (int r = 0; r < A.length; r++) { 2037 for (double val : A[r]) { 2038 if (val > maxval) { 2039 maxval = val; 2040 } 2041 } 2042 } 2043 return maxval; 2044 } 2045 2046 /** 2047 * Returns the largest value in the specified {@code float[][]} matrix. 2048 * 2049 * @param A a matrix 2050 * @return the largest matrix value 2051 */ 2052 public static float max(float[][] A) { 2053 float maxval = Float.NEGATIVE_INFINITY; 2054 for (int r = 0; r < A.length; r++) { 2055 for (float val : A[r]) { 2056 if (val > maxval) { 2057 maxval = val; 2058 } 2059 } 2060 } 2061 return maxval; 2062 } 2063 2064 // Vector concatenation ----------------------- 2065 2066 /** 2067 * Joins (concatenates) a sequence of vectors into a single vector. 2068 * 2069 * @param as a sequence of vectors (at least one vector) 2070 * @return a vector containing all elements of the input vectors 2071 */ 2072 public static float[] join(float[]... as) { 2073 int n = 0; 2074 for (float[] x : as) { 2075 n = n + x.length; 2076 } 2077 float[] va = new float[n]; 2078 int j = 0; 2079 for (float[] x : as) { 2080 for (int i = 0; i < x.length; i++) { 2081 va[j] = x[i]; 2082 j++; 2083 } 2084 } 2085 return va; 2086 } 2087 2088 /** 2089 * Joins (concatenates) a sequence of vectors into a single vector. 2090 * 2091 * @param as a sequence of vectors (at least one vector) 2092 * @return a vector containing all elements of the input vectors 2093 */ 2094 public static double[] join(double[]... as) { 2095 int n = 0; 2096 for (double[] x : as) { 2097 n = n + x.length; 2098 } 2099 double[] va = new double[n]; 2100 int j = 0; 2101 for (double[] x : as) { 2102 for (int i = 0; i < x.length; i++) { 2103 va[j] = x[i]; 2104 j++; 2105 } 2106 } 2107 return va; 2108 } 2109 2110 // Vector linear interpolation --------------------------------- 2111 2112 /** 2113 * Performs linear interpolation between two vectors {@code a} and {@code b}, which must have the same length. 2114 * Returns a new vector {@code c = a + t * (b - a)}. 2115 * 2116 * @param a first vector (to be interpolated from) 2117 * @param b second vector (to be interpolated to) 2118 * @param t interpolation coefficient, expected to be in [0,1] 2119 * @return the interpolated vector 2120 */ 2121 public static float[] lerp(float[] a, float[] b, final float t) { 2122 final float[] c = new float[a.length]; 2123 for (int i = 0; i < a.length; i++) { 2124 c[i] = a[i] + t * (b[i] - a[i]); 2125 } 2126 return c; 2127 } 2128 2129 /** 2130 * Performs linear interpolation between two vectors {@code a} and {@code b}, which must have the same length. 2131 * Returns a new vector {@code c = a + t * (b - a)}. 2132 * 2133 * @param a first vector (to be interpolated from) 2134 * @param b second vector (to be interpolated to) 2135 * @param t interpolation coefficient, expected to be in [0,1] 2136 * @return the interpolated vector 2137 */ 2138 public static double[] lerp(double[] a, double[] b, final double t) { 2139 final double[] c = new double[a.length]; 2140 for (int i = 0; i < a.length; i++) { 2141 c[i] = a[i] + t * (b[i] - a[i]); 2142 } 2143 return c; 2144 } 2145 2146 2147 // Homogeneous coordinates --------------------------------- 2148 2149 /** 2150 * Converts a Cartesian vector to an equivalent homogeneous vector by attaching an additional 1-element. The 2151 * resulting homogeneous vector is one element longer than the specified Cartesian vector. See also 2152 * {@link #toCartesian(double[])}. 2153 * 2154 * @param ac a Cartesian vector 2155 * @return an equivalent homogeneous vector 2156 */ 2157 public static double[] toHomogeneous(double[] ac) { 2158 double[] xh = new double[ac.length + 1]; 2159 for (int i = 0; i < ac.length; i++) { 2160 xh[i] = ac[i]; 2161 xh[xh.length - 1] = 1; 2162 } 2163 return xh; 2164 } 2165 2166 /** 2167 * Converts a homogeneous vector to its equivalent Cartesian vector, which is one element shorter. See also 2168 * {@link #toHomogeneous(double[])}. 2169 * 2170 * @param ah a homogeneous vector 2171 * @return the equivalent Cartesian vector 2172 * @throws DivideByZeroException if the last vector element is zero 2173 */ 2174 public static double[] toCartesian(double[] ah) throws DivideByZeroException { 2175 double[] xc = new double[ah.length - 1]; 2176 final double s = 1 / ah[ah.length - 1]; 2177 if (!Double.isFinite(s)) // isZero(s) 2178 throw new DivideByZeroException(); 2179 for (int i = 0; i < ah.length - 1; i++) { 2180 xc[i] = s * ah[i]; 2181 } 2182 return xc; 2183 } 2184 2185 // Determinants -------------------------------------------- 2186 2187 /** 2188 * Calculates and returns the determinant of the given {@link RealMatrix}. Throws an exception if the matrix is 2189 * non-square. 2190 * 2191 * @param A a square matrix 2192 * @return the determinant 2193 */ 2194 public static double determinant(RealMatrix A) { 2195 if (!A.isSquare()) 2196 throw new NonsquareMatrixException(); 2197 return new LUDecomposition(A).getDeterminant(); 2198 } 2199 2200 /** 2201 * Calculates and returns the determinant of the given {@code double[][]} matrix. Throws an exception if the matrix 2202 * is non-square. 2203 * 2204 * @param A a square matrix 2205 * @return the determinant 2206 */ 2207 public static double determinant(final double[][] A) { 2208 return determinant(MatrixUtils.createRealMatrix(A)); 2209 } 2210 2211 /** 2212 * Calculates and returns the determinant of the given 2x2 {@code double[][]} matrix. This method is hard-coded for 2213 * the specific matrix size for better performance than the general method ({@link #determinant(double[][])}). 2214 * Throws an exception if the matrix is not 2x2. 2215 * 2216 * @param A a 2x2 matrix 2217 * @return the determinant 2218 */ 2219 public static double determinant2x2(final double[][] A) { 2220 if (A.length != 2 || A[0].length != 2) 2221 throw new IncompatibleDimensionsException(); 2222 return A[0][0] * A[1][1] - A[0][1] * A[1][0]; 2223 } 2224 2225 /** 2226 * Calculates and returns the determinant of the given 2x2 {@code float[][]} matrix. Throws an exception if the 2227 * matrix is not 2x2. 2228 * 2229 * @param A a 2x2 matrix 2230 * @return the determinant 2231 */ 2232 public static float determinant2x2(final float[][] A) { 2233 if (A.length != 2 || A[0].length != 2) 2234 throw new IncompatibleDimensionsException(); 2235 return A[0][0] * A[1][1] - A[0][1] * A[1][0]; 2236 } 2237 2238 2239 /** 2240 * Calculates and returns the determinant of the given 3x3 {@code double[][]} matrix. This method is hard-coded for 2241 * the specific matrix size for better performance than the general method ({@link #determinant(double[][])}). 2242 * Throws an exception if the matrix is not 3x3. 2243 * 2244 * @param A a 3x3 matrix 2245 * @return the determinant 2246 */ 2247 public static double determinant3x3(final double[][] A) { 2248 if (A.length != 3 || A[0].length != 3) 2249 throw new IncompatibleDimensionsException(); 2250 return 2251 A[0][0] * A[1][1] * A[2][2] + 2252 A[0][1] * A[1][2] * A[2][0] + 2253 A[0][2] * A[1][0] * A[2][1] - 2254 A[2][0] * A[1][1] * A[0][2] - 2255 A[2][1] * A[1][2] * A[0][0] - 2256 A[2][2] * A[1][0] * A[0][1]; 2257 } 2258 2259 /** 2260 * Calculates and returns the determinant of the given 3x3 {@code float[][]} matrix. Throws an exception if the 2261 * matrix is not 3x3. 2262 * 2263 * @param A a 3x3 matrix 2264 * @return the determinant 2265 */ 2266 public static float determinant3x3(final float[][] A) { 2267 if (A.length != 3 || A[0].length != 3) 2268 throw new IncompatibleDimensionsException(); 2269 return 2270 A[0][0] * A[1][1] * A[2][2] + 2271 A[0][1] * A[1][2] * A[2][0] + 2272 A[0][2] * A[1][0] * A[2][1] - 2273 A[2][0] * A[1][1] * A[0][2] - 2274 A[2][1] * A[1][2] * A[0][0] - 2275 A[2][2] * A[1][0] * A[0][1]; 2276 } 2277 2278 2279 // Matrix trace --------------------------------------- 2280 2281 /** 2282 * Calculates and returns the trace of the given {@code double[][]} matrix. Throws an exception if the matrix is 2283 * non-square. 2284 * 2285 * @param A a square matrix 2286 * @return the trace 2287 */ 2288 public static double trace(final double[][] A) { 2289 final int m = getNumberOfRows(A); 2290 final int n = getNumberOfColumns(A); 2291 if (m != n) 2292 throw new NonsquareMatrixException(); 2293 double s = 0; 2294 for (int i = 0; i < m; i++) { 2295 s = s + A[i][i]; 2296 } 2297 return s; 2298 } 2299 2300 /** 2301 * Calculates and returns the trace of the given {@code float[][]} matrix. Throws an exception if the matrix is 2302 * non-square. 2303 * 2304 * @param A a square matrix 2305 * @return the trace 2306 */ 2307 public static float trace(final float[][] A) { 2308 final int m = getNumberOfRows(A); 2309 final int n = getNumberOfColumns(A); 2310 if (m != n) 2311 throw new NonsquareMatrixException(); 2312 double s = 0; 2313 for (int i = 0; i < m; i++) { 2314 s = s + A[i][i]; 2315 } 2316 return (float) s; 2317 } 2318 2319 // Matrix transposition --------------------------------------- 2320 2321 /** 2322 * Returns the transpose of the given {@code double[][]} matrix. The original matrix is not modified. 2323 * 2324 * @param A a matrix 2325 * @return the transpose of the matrix 2326 */ 2327 public static double[][] transpose(double[][] A) { 2328 final int m = getNumberOfRows(A); 2329 final int n = getNumberOfColumns(A); 2330 double[][] At = new double[n][m]; 2331 for (int i = 0; i < m; i++) { 2332 for (int j = 0; j < n; j++) { 2333 At[j][i] = A[i][j]; 2334 } 2335 } 2336 return At; 2337 } 2338 2339 /** 2340 * Returns the transpose of the given {@code float[][]} matrix. The original matrix is not modified. 2341 * 2342 * @param A a matrix 2343 * @return the transpose of the matrix 2344 */ 2345 public static float[][] transpose(float[][] A) { 2346 final int m = getNumberOfRows(A); 2347 final int n = getNumberOfColumns(A); 2348 float[][] At = new float[n][m]; 2349 for (int i = 0; i < m; i++) { 2350 for (int j = 0; j < n; j++) { 2351 At[j][i] = A[i][j]; 2352 } 2353 } 2354 return At; 2355 } 2356 2357 2358 // Checking vectors for all zero values ------------------------------ 2359 2360 /** 2361 * Checks if all elements of the specified {@code double[]} vector are zero using the specified tolerance value. 2362 * 2363 * @param a a vector 2364 * @param tolerance the tolerance value 2365 * @return true if all vector elements are smaller than the tolerance 2366 */ 2367 public static boolean isZero(double[] a, double tolerance) { 2368 for (int i = 0; i < a.length; i++) { 2369 if (!Arithmetic.isZero(a[i], tolerance)) { 2370 return false; 2371 } 2372 } 2373 return true; 2374 } 2375 2376 /** 2377 * Checks if all elements of the specified {@code double[]} vector are zero using the default tolerance value 2378 * ({@link Arithmetic#EPSILON_DOUBLE}). 2379 * 2380 * @param a a vector 2381 * @return true if all vector elements are smaller than the tolerance 2382 */ 2383 public static boolean isZero(double[] a) { 2384 return isZero(a, Arithmetic.EPSILON_DOUBLE); 2385 } 2386 2387 /** 2388 * Checks if all elements of the specified {@code float[]} vector are zero using the specified tolerance value. 2389 * 2390 * @param a a vector 2391 * @param tolerance the tolerance value 2392 * @return true if all vector elements are smaller than the tolerance 2393 */ 2394 public static boolean isZero(float[] a, float tolerance) { 2395 for (int i = 0; i < a.length; i++) { 2396 if (!Arithmetic.isZero(a[i], tolerance)) { 2397 return false; 2398 } 2399 } 2400 return true; 2401 } 2402 2403 /** 2404 * Checks if all elements of the specified {@code float[]} vector are zero using the default tolerance value 2405 * ({@link Arithmetic#EPSILON_DOUBLE}). 2406 * 2407 * @param a a vector 2408 * @return true if all vector elements are smaller than the tolerance 2409 */ 2410 public static boolean isZero(float[] a) { 2411 return isZero(a, Arithmetic.EPSILON_FLOAT); 2412 } 2413 2414 // Checking matrices for all zero values ------------------------------ 2415 2416 /** 2417 * Checks if all elements of the specified {@code double[][]} matrix are zero using the specified tolerance value. 2418 * 2419 * @param A a matrix 2420 * @param tolerance the tolerance value 2421 * @return true if all matrix elements are smaller than the tolerance 2422 */ 2423 public static boolean isZero(double[][] A, double tolerance) { 2424 for (int i = 0; i < A.length; i++) { // for each matrix row i 2425 if (!Matrix.isZero(A[i], tolerance)) { 2426 return false; 2427 } 2428 } 2429 return true; 2430 } 2431 2432 /** 2433 * Checks if all elements of the specified {@code double[][]} matrix are zero using default tolerance value 2434 * ({@link Arithmetic#EPSILON_DOUBLE}). 2435 * 2436 * @param A a matrix 2437 * @return true if all matrix elements are smaller than the tolerance 2438 */ 2439 public static boolean isZero(double[][] A) { 2440 return isZero(A, Arithmetic.EPSILON_DOUBLE); 2441 } 2442 2443 // Sorting vectors (non-destructively) ------------------------------ 2444 2445 /** 2446 * Returns a sorted copy of the given {@code double[]} vector. Elements are sorted by increasing value (smallest 2447 * first). 2448 * 2449 * @param a a {@code double[]} vector 2450 * @return a sorted copy of the vector 2451 */ 2452 public static double[] sort(double[] a) { 2453 double[] y = Arrays.copyOf(a, a.length); 2454 Arrays.sort(y); 2455 return y; 2456 } 2457 2458 /** 2459 * Returns a sorted copy of the given {@code float[]} vector. Elements are sorted by increasing value (smallest 2460 * first). 2461 * 2462 * @param a a {@code float[]} vector 2463 * @return a sorted copy of the vector 2464 */ 2465 public static float[] sort(float[] a) { 2466 float[] y = Arrays.copyOf(a, a.length); 2467 Arrays.sort(y); 2468 return y; 2469 } 2470 2471 // Matrix inversion --------------------------------------- 2472 2473 /** 2474 * Calculates and returns the inverse of the given matrix, which must be square. Exceptions are thrown if the 2475 * supplied matrix is not square or ill-conditioned (singular). 2476 * 2477 * @param A a square matrix 2478 * @return the inverse matrix 2479 * @throws NonsquareMatrixException if the supplied matrix is not square 2480 */ 2481 public static double[][] inverse(final double[][] A) throws NonsquareMatrixException { 2482 if (!isSquare(A)) 2483 throw new NonsquareMatrixException(); 2484 RealMatrix M = MatrixUtils.createRealMatrix(A); 2485 return MatrixUtils.inverse(M).getData(); 2486 } 2487 2488 /** 2489 * Calculates and returns the inverse of the given matrix, which must be square. Exceptions are thrown if the 2490 * supplied matrix is not square or ill-conditioned (singular). 2491 * 2492 * @param A a square matrix 2493 * @return the inverse matrix 2494 * @throws NonsquareMatrixException if the supplied matrix is not square 2495 */ 2496 public static float[][] inverse(final float[][] A) throws NonsquareMatrixException { 2497 if (!isSquare(A)) 2498 throw new NonsquareMatrixException(); 2499 double[][] Ad = toDouble(A); 2500 return toFloat(inverse(Ad)); 2501 } 2502 2503 // ------------------------------------------------------------------------ 2504 2505 /** 2506 * Finds the exact solution x for the linear system of equations A * x = b. Returns the solution vector x or 2507 * {@code null} if the supplied matrix is ill-conditioned (i.e., singular). Exceptions are thrown if A is not square 2508 * or dimensions are incompatible. Calls {@link #solve(RealMatrix, RealVector)}. 2509 * 2510 * @param A a square matrix of size n x n 2511 * @param b a vector of length n 2512 * @return the solution vector (x) of length n or {@code null} if no solution possible 2513 */ 2514 public static double[] solve(final double[][] A, double[] b) { 2515 RealVector x = solve(MatrixUtils.createRealMatrix(A), MatrixUtils.createRealVector(b)); 2516 return (x == null) ? null : x.toArray(); 2517 } 2518 2519 /** 2520 * Finds the exact solution x for the linear system of equations A * x = b. Returns the solution vector x or 2521 * {@code null} if the supplied matrix is ill-conditioned (i.e., singular). Exceptions are thrown if A is not square 2522 * or dimensions are incompatible. Uses {@link LUDecomposition} from the Apache Commons Math library. 2523 * 2524 * @param A a square matrix of size n x n 2525 * @param b a vector of length n 2526 * @return the solution vector (x) of length n or {@code null} if no solution possible 2527 */ 2528 public static RealVector solve(RealMatrix A, RealVector b) { 2529 if (!A.isSquare()) { 2530 throw new NonsquareMatrixException(); 2531 } 2532 if (A.getRowDimension() != b.getDimension()) { 2533 throw new IncompatibleDimensionsException(); 2534 } 2535// DecompositionSolver solver = new LUDecomposition(A, 0.0).getSolver(); 2536 DecompositionSolver solver = new LUDecomposition(A).getSolver(); 2537 RealVector x = null; 2538 try { 2539 x = solver.solve(b); 2540 } catch (SingularMatrixException e) { 2541 } 2542 return x; 2543 } 2544 2545 // Output to strings and streams ------------------------------------------ 2546 2547 /** 2548 * Returns a string representation of the specified vector. 2549 * 2550 * @param a a vector 2551 * @return the string representation 2552 */ 2553 public static String toString(double[] a) { 2554 if (a == null) { 2555 return String.valueOf(a); 2556 } 2557 ByteArrayOutputStream bas = new ByteArrayOutputStream(); 2558 PrintStream strm = new PrintStream(bas); 2559 printToStream(a, strm); 2560 return bas.toString(); 2561 } 2562 2563 /** 2564 * Returns a string representation of the specified vector. 2565 * 2566 * @param a a vector 2567 * @return the string representation 2568 */ 2569 public static String toString(float[] a) { 2570 if (a == null) { 2571 return String.valueOf(a); 2572 } 2573 ByteArrayOutputStream bas = new ByteArrayOutputStream(); 2574 PrintStream strm = new PrintStream(bas); 2575 printToStream(a, strm); 2576 return bas.toString(); 2577 } 2578 2579 /** 2580 * Returns a string representation of the specified vector. 2581 * 2582 * @param a a vector 2583 * @return the string representation 2584 */ 2585 public static String toString(RealVector a) { 2586 if (a == null) { 2587 return String.valueOf(a); 2588 } else { 2589 return toString(a.toArray()); 2590 } 2591 } 2592 2593 /** 2594 * Returns a string representation of the specified matrix. 2595 * 2596 * @param A a matrix 2597 * @return the string representation 2598 */ 2599 public static String toString(double[][] A) { 2600 if (A == null) { 2601 return String.valueOf(A); 2602 } 2603 ByteArrayOutputStream bas = new ByteArrayOutputStream(); 2604 PrintStream strm = new PrintStream(bas); 2605 printToStream(A, strm); 2606 return bas.toString(); 2607 } 2608 2609 /** 2610 * Returns a string representation of the specified matrix. 2611 * 2612 * @param A a matrix 2613 * @return the string representation 2614 */ 2615 public static String toString(float[][] A) { 2616 if (A == null) { 2617 return String.valueOf(A); 2618 } 2619 ByteArrayOutputStream bas = new ByteArrayOutputStream(); 2620 PrintStream strm = new PrintStream(bas); 2621 printToStream(A, strm); 2622 return bas.toString(); 2623 } 2624 2625 /** 2626 * Returns a string representation of the specified matrix with {@code long} elements. 2627 * 2628 * @param A a matrix 2629 * @return the string representation 2630 */ 2631 public static String toString(long[][] A) { 2632 if (A == null) { 2633 return String.valueOf(A); 2634 } 2635 ByteArrayOutputStream bas = new ByteArrayOutputStream(); 2636 PrintStream strm = new PrintStream(bas); 2637 printToStream(A, strm); 2638 return bas.toString(); 2639 } 2640 2641 /** 2642 * Returns a string representation of the specified matrix. 2643 * 2644 * @param A a matrix 2645 * @return the string representation 2646 */ 2647 public static String toString(RealMatrix A) { 2648 if (A == null) { 2649 return String.valueOf(A); 2650 } else { 2651 return toString(A.getData()); 2652 } 2653 } 2654 2655 // -------------------- 2656 2657 /** 2658 * Outputs a string representation of the given vector to the specified output stream. 2659 * 2660 * @param a the vector 2661 * @param strm the output stream 2662 * @see #toString(double[]) 2663 */ 2664 public static void printToStream(double[] a, PrintStream strm) { 2665 String fStr = PrintPrecision.getFormatStringFloat(); 2666 strm.format("%c", LeftDelimitChar); 2667 for (int i = 0; i < a.length; i++) { 2668 if (i > 0) 2669 strm.format("%c ", SeparationChar); 2670 strm.format(PrintLocale, fStr, a[i]); 2671 } 2672 strm.format("%c", RightDelimitChar); 2673 strm.flush(); 2674 } 2675 2676 /** 2677 * Outputs a string representation of the given matrix to the specified output stream. 2678 * 2679 * @param A the matrix 2680 * @param strm the output stream 2681 * @see #toString(double[][]) 2682 */ 2683 public static void printToStream(double[][] A, PrintStream strm) { 2684 String fStr = PrintPrecision.getFormatStringFloat(); 2685 strm.format("%c", LeftDelimitChar); 2686 for (int i = 0; i < A.length; i++) { 2687 if (i == 0) 2688 strm.format("%c", LeftDelimitChar); 2689 else 2690 strm.format("%c \n%c", SeparationChar, LeftDelimitChar); 2691 for (int j = 0; j < A[i].length; j++) { 2692 if (j == 0) 2693 strm.format(PrintLocale, fStr, A[i][j]); 2694 else 2695 strm.format(PrintLocale, "%c " + fStr, SeparationChar, A[i][j]); 2696 } 2697 strm.format("%c", RightDelimitChar); 2698 } 2699 strm.format("%c", RightDelimitChar); 2700 strm.flush(); 2701 } 2702 2703 /** 2704 * Outputs a string representation of the given vector to the specified output stream. 2705 * 2706 * @param a the vector 2707 * @param strm the output stream 2708 * @see #toString(float[]) 2709 */ 2710 public static void printToStream(float[] a, PrintStream strm) { 2711 String fStr = PrintPrecision.getFormatStringFloat(); 2712 strm.format("%c", LeftDelimitChar); 2713 for (int i = 0; i < a.length; i++) { 2714 if (i > 0) 2715 strm.format("%c ", SeparationChar); 2716 strm.format(PrintLocale, fStr, a[i]); 2717 } 2718 strm.format("%c", RightDelimitChar); 2719 strm.flush(); 2720 } 2721 2722 /** 2723 * Outputs a string representation of the given matrix to the specified output stream. 2724 * 2725 * @param A the matrix 2726 * @param strm the output stream 2727 * @see #toString(float[][]) 2728 */ 2729 public static void printToStream(float[][] A, PrintStream strm) { 2730 String fStr = PrintPrecision.getFormatStringFloat(); 2731 strm.format("%c", LeftDelimitChar); 2732 for (int i = 0; i < A.length; i++) { 2733 if (i == 0) 2734 strm.format("%c", LeftDelimitChar); 2735 else 2736 strm.format("%c \n%c", SeparationChar, LeftDelimitChar); 2737 for (int j = 0; j < A[i].length; j++) { 2738 if (j == 0) 2739 strm.format(PrintLocale, fStr, A[i][j]); 2740 else 2741 strm.format(PrintLocale, "%c " + fStr, SeparationChar, A[i][j]); 2742 } 2743 strm.format("%c", RightDelimitChar); 2744 } 2745 strm.format("%c", RightDelimitChar); 2746 strm.flush(); 2747 } 2748 2749 // -------------------------------------------------------------------------- 2750 2751 public static void printToStream(long[][] A, PrintStream strm) { 2752 strm.format("%c", LeftDelimitChar); 2753 for (int i = 0; i < A.length; i++) { 2754 if (i == 0) 2755 strm.format("%c", LeftDelimitChar); 2756 else 2757 strm.format("%c \n%c", SeparationChar, LeftDelimitChar); 2758 for (int j = 0; j < A[i].length; j++) { 2759 if (j == 0) 2760 strm.format(PrintLocale, "%dL", A[i][j]); 2761 else 2762 strm.format(PrintLocale, "%c %dL", SeparationChar, A[i][j]); 2763 } 2764 strm.format("%c", RightDelimitChar); 2765 } 2766 strm.format("%c", RightDelimitChar); 2767 strm.flush(); 2768 } 2769 2770 // Exceptions ---------------------------------------------------------------- 2771 2772 /** 2773 * Thrown when the dimensions of matrix/vector arguments do not match. 2774 */ 2775 public static class IncompatibleDimensionsException extends RuntimeException { 2776 public IncompatibleDimensionsException() { 2777 super("incompatible matrix-vector dimensions"); 2778 } 2779 2780 public IncompatibleDimensionsException(String msg) { 2781 super(msg); 2782 } 2783 } 2784 2785 /** 2786 * Thrown when a non-square matrix is encountered where a square matrix is assumed. 2787 */ 2788 public static class NonsquareMatrixException extends RuntimeException { 2789 public NonsquareMatrixException() { 2790 super("square matrix expected"); 2791 } 2792 2793 public NonsquareMatrixException(String msg) { 2794 super(msg); 2795 } 2796 } 2797 2798 /** 2799 * Thrown when source and target objects are identical but shouldn't. 2800 */ 2801 public static class SameSourceTargetException extends RuntimeException { 2802 public SameSourceTargetException() { 2803 super("source and target must not be the same"); 2804 } 2805 2806 public SameSourceTargetException(String msg) { 2807 super(msg); 2808 } 2809 } 2810 2811 /** 2812 * Thrown when the length of some vector is zero. 2813 */ 2814 public static class ZeroLengthVectorException extends RuntimeException { 2815 public ZeroLengthVectorException() { 2816 super("vector length must be at least 1"); 2817 } 2818 2819 public ZeroLengthVectorException(String msg) { 2820 super(msg); 2821 } 2822 } 2823 2824}