1 package org.lcsim.recon.tracking.spacegeom; 2 import java.io.*; 3 4 class Matrix 5 { 6 7 protected int _row; 8 protected int _col; 9 protected double _a[][]; 10 protected Matrix _eigenvalues; 11 protected Eigensystem _eigensystem; 12 13 public Matrix() 14 { 15 _row = 0; 16 _col = 0; 17 createData(); 18 } 19 20 public Matrix(int i, int j) 21 { 22 _row = i; 23 _col = j; 24 createData(); 25 } 26 27 public Matrix(Matrix matrix) 28 { 29 _row = matrix._row; 30 _col = matrix._col; 31 _eigensystem = matrix._eigensystem; 32 createData(); 33 for(int i = 0; i < _row; i++) 34 { 35 for(int j = 0; j < _col; j++) 36 _a[i][j] = matrix._a[i][j]; 37 38 } 39 40 } 41 42 protected void QL(Matrix matrix, Matrix matrix1, Matrix matrix2, boolean flag) 43 { 44 int k1 = _row; 45 for(int i = 1; i < k1; i++) 46 matrix2.set(i - 1, 0, matrix2.at(i, 0)); 47 48 matrix2.set(k1 - 1, 0, 0.0D); 49 for(int l = 0; l < k1; l++) 50 { 51 int j1 = 0; 52 int i1; 53 do 54 { 55 for(i1 = l; i1 < k1 - 1; i1++) 56 { 57 double d2 = Math.abs(matrix1.at(i1, 0)) + Math.abs(matrix1.at(i1 + 1, 0)); 58 if(Math.abs(matrix2.at(i1, 0)) + d2 == d2) 59 break; 60 } 61 62 if(i1 != l) 63 { 64 if(j1++ == 30) 65 { 66 System.err.println("Matrix::QL -> Too many iterations."); 67 System.exit(0); 68 } 69 double d5 = (matrix1.at(l + 1, 0) - matrix1.at(l, 0)) / (2D * matrix2.at(l, 0)); 70 double d7 = pythagoras(d5, 1.0D); 71 d5 = (matrix1.at(i1, 0) - matrix1.at(l, 0)) + matrix2.at(l, 0) / (d5 + SIGN(d7, d5)); 72 double d1; 73 double d8 = d1 = 1.0D; 74 double d6 = 0.0D; 75 int j; 76 for(j = i1 - 1; j >= l; j--) 77 { 78 double d3 = d8 * matrix2.at(j, 0); 79 double d = d1 * matrix2.at(j, 0); 80 matrix2.set(j + 1, 0, d7 = pythagoras(d3, d5)); 81 if(d7 == 0.0D) 82 { 83 matrix1.set(j + 1, 0, matrix1.at(j + 1, 0) - d6); 84 matrix2.set(i1, 0, 0.0D); 85 break; 86 } 87 d8 = d3 / d7; 88 d1 = d5 / d7; 89 d5 = matrix1.at(j + 1, 0) - d6; 90 d7 = (matrix1.at(j, 0) - d5) * d8 + 2D * d1 * d; 91 matrix1.set(j + 1, 0, d5 + (d6 = d8 * d7)); 92 d5 = d1 * d7 - d; 93 if(flag) 94 { 95 for(int k = 0; k < k1; k++) 96 { 97 double d4 = matrix.at(k, j + 1); 98 matrix.set(k, j + 1, d8 * matrix.at(k, j) + d1 * d4); 99 matrix.set(k, j, d1 * matrix.at(k, j) - d8 * d4); 100 } 101 102 } 103 } 104 105 if(d7 != 0.0D || j < l) 106 { 107 matrix1.set(l, 0, matrix1.at(l, 0) - d6); 108 matrix2.set(l, 0, d5); 109 matrix2.set(i1, 0, 0.0D); 110 } 111 } 112 } while(i1 != l); 113 } 114 115 } 116 117 protected double SIGN(double d, double d1) 118 { 119 if(d1 >= 0.0D) 120 return Math.abs(d); 121 else 122 return -Math.abs(d); 123 } 124 125 126 public double at(int i, int j) 127 { 128 return _a[i][j]; 129 } 130 131 public int cols() 132 { 133 return _col; 134 } 135 136 protected void createData() 137 { 138 int i = _row + 1; 139 int j = _col + 1; 140 _a = new double[i][j]; 141 } 142 143 public Eigensystem eigensystem() 144 { 145 if(!isSymmetric()) 146 { 147 System.err.println("Matrix::eigensystem -> Matrix is not symmetric."); 148 System.exit(0); 149 } 150 int i = _row; 151 Matrix matrix = new Matrix(this); 152 Matrix matrix1 = new Matrix(i, 1); 153 Matrix matrix2 = new Matrix(i, 1); 154 householder(matrix, matrix1, matrix2, true); 155 QL(matrix, matrix1, matrix2, true); 156 if(_eigensystem == null) 157 _eigensystem = new Eigensystem(); 158 Matrix matrix3 = new Matrix(matrix); 159 _eigensystem.setEigenvectors(matrix3); 160 Matrix matrix4 = new Matrix(matrix1); 161 _eigensystem.setEigenvalues(matrix4); 162 return _eigensystem; 163 } 164 165 public Matrix eigenvalues() 166 { 167 if(!isSymmetric()) 168 { 169 System.err.println("Matrix::eigenvalues -> Matrix is not symmetric."); 170 System.exit(0); 171 } 172 int i = _row; 173 Matrix matrix = new Matrix(this); 174 Matrix matrix1 = new Matrix(i, 1); 175 Matrix matrix2 = new Matrix(i, 1); 176 householder(matrix, matrix1, matrix2, false); 177 QL(matrix, matrix1, matrix2, false); 178 if(_eigenvalues == null) 179 _eigenvalues = new Matrix(i, 1); 180 _eigenvalues = new Matrix(matrix1); 181 return _eigenvalues; 182 } 183 184 185 public Eigensystem getEigensystem() 186 { 187 return _eigensystem; 188 } 189 190 public Matrix getEigenvalues() 191 { 192 return _eigenvalues; 193 } 194 195 protected void householder(Matrix matrix, Matrix matrix1, Matrix matrix2, boolean flag) 196 { 197 int j3 = 0; 198 int k3 = _row; 199 for(int i = k3 - 1; i > 0; i--) 200 { 201 j3 = i - 1; 202 double d; 203 double d7 = d = 0.0D; 204 if(j3 > 0) 205 { 206 for(int k1 = 0; k1 <= j3; k1++) 207 d += Math.abs(matrix.at(i, k1)); 208 209 if(d == 0.0D) 210 { 211 matrix2.set(i, 0, matrix.at(i, i)); 212 } 213 else 214 { 215 for(int l1 = 0; l1 <= j3; l1++) 216 { 217 matrix.set(i, l1, matrix.at(i, l1) / d); 218 d7 += matrix.at(i, l1) * matrix.at(i, l1); 219 } 220 221 double d1 = matrix.at(i, j3); 222 double d3 = d1 < 0.0D ? Math.sqrt(d7) : -Math.sqrt(d7); 223 matrix2.set(i, 0, d * d3); 224 d7 -= d1 * d3; 225 matrix.set(i, j3, d1 - d3); 226 d1 = 0.0D; 227 for(int k = 0; k <= j3; k++) 228 { 229 if(flag) 230 matrix.set(k, i, matrix.at(i, k) / d7); 231 double d4 = 0.0D; 232 for(int i2 = 0; i2 <= k; i2++) 233 d4 += matrix.at(k, i2) * matrix.at(i, i2); 234 235 for(int j2 = k + 1; j2 <= j3; j2++) 236 d4 += matrix.at(j2, k) * matrix.at(i, j2); 237 238 matrix2.set(k, 0, d4 / d7); 239 d1 += matrix2.at(k, 0) * matrix.at(i, k); 240 } 241 242 double d8 = d1 / (d7 + d7); 243 for(int l = 0; l <= j3; l++) 244 { 245 double d2 = matrix.at(i, l); 246 double d5 = matrix2.at(l, 0) - d8 * d2; 247 matrix2.set(l, 0, d5); 248 for(int k2 = 0; k2 <= l; k2++) 249 matrix.set(l, k2, matrix.at(l, k2) - (d2 * matrix2.at(k2, 0) + d5 * matrix.at(i, k2))); 250 251 } 252 253 } 254 } 255 else 256 { 257 matrix2.set(i, 0, matrix.at(i, j3)); 258 } 259 matrix1.set(i, 0, d7); 260 } 261 262 if(flag) 263 matrix1.set(0, 0, 0.0D); 264 matrix2.set(0, 0, 0.0D); 265 for(int j = 0; j < k3; j++) 266 { 267 if(flag) 268 { 269 j3 = j - 1; 270 if(matrix1.at(j, 0) != 0.0D) 271 { 272 for(int i1 = 0; i1 <= j3; i1++) 273 { 274 double d6 = 0.0D; 275 for(int l2 = 0; l2 <= j3; l2++) 276 d6 += matrix.at(j, l2) * matrix.at(l2, i1); 277 278 for(int i3 = 0; i3 <= j3; i3++) 279 matrix.set(i3, i1, matrix.at(i3, i1) - d6 * matrix.at(i3, j)); 280 281 } 282 283 } 284 } 285 matrix1.set(j, 0, matrix.at(j, j)); 286 if(flag) 287 { 288 matrix.set(j, j, 1.0D); 289 for(int j1 = 0; j1 <= j3; j1++) 290 { 291 matrix.set(j, j1, 0.0D); 292 matrix.set(j1, j, matrix.at(j, j1)); 293 } 294 295 } 296 } 297 298 } 299 300 public Matrix inverse() 301 { 302 if(!isSquare()) 303 { 304 System.err.println("Matrix::inverse -> Matrix is not square."); 305 System.exit(0); 306 } 307 int i = _row; 308 Matrix matrix = new Matrix(i, 2 * i); 309 Matrix matrix1 = new Matrix(i, 1); 310 Matrix matrix2 = new Matrix(i, 1); 311 for(int j = 0; j < i; j++) 312 { 313 for(int i2 = 0; i2 < i; i2++) 314 matrix.set(j, i2, _a[j][i2]); 315 316 } 317 318 for(int k = 0; k < i; k++) 319 { 320 for(int j2 = i; j2 < 2 * i; j2++) 321 matrix.set(k, j2, 0.0D); 322 323 matrix.set(k, i + k, 1.0D); 324 } 325 326 for(int i4 = 0; i4 < i; i4++) 327 { 328 for(int l = i4; l < i; l++) 329 { 330 matrix2.set(l, 0, 0.0D); 331 for(int k2 = i4; k2 < i; k2++) 332 matrix2.set(l, 0, matrix2.at(l, 0) + matrix.at(l, k2)); 333 334 matrix1.set(l, 0, Math.abs(matrix.at(l, i4)) / matrix2.at(l, 0)); 335 } 336 337 int k4 = i4; 338 for(int i1 = i4 + 1; i1 < i; i1++) 339 if(matrix1.at(i1, 0) > matrix1.at(i1 - 1, 0)) 340 k4 = i1; 341 342 if(matrix1.at(k4, 0) == 0.0D) 343 { 344 System.err.println("Matrix::inverse -> Matrix is singular."); 345 System.exit(0); 346 } 347 if(k4 != i4) 348 { 349 for(int l2 = 0; l2 < 2 * i; l2++) 350 { 351 double d = matrix.at(i4, l2); 352 matrix.set(i4, l2, matrix.at(k4, l2)); 353 matrix.set(k4, l2, d); 354 } 355 356 } 357 for(int i3 = 2 * i - 1; i3 >= i4; i3--) 358 matrix.set(i4, i3, matrix.at(i4, i3) / matrix.at(i4, i4)); 359 360 for(int j1 = i4 + 1; j1 < i; j1++) 361 { 362 for(int j3 = 2 * i - 1; j3 >= i4 + 1; j3--) 363 matrix.set(j1, j3, matrix.at(j1, j3) - matrix.at(i4, j3) * matrix.at(j1, i4)); 364 365 } 366 367 } 368 369 for(int j4 = i - 1; j4 >= 0; j4--) 370 { 371 for(int k1 = j4 - 1; k1 >= 0; k1--) 372 { 373 for(int k3 = i; k3 < 2 * i; k3++) 374 matrix.set(k1, k3, matrix.at(k1, k3) - matrix.at(j4, k3) * matrix.at(k1, j4)); 375 376 } 377 378 } 379 380 Matrix matrix3 = new Matrix(i, i); 381 for(int l1 = 0; l1 < i; l1++) 382 { 383 for(int l3 = 0; l3 < i; l3++) 384 matrix3.set(l1, l3, matrix.at(l1, l3 + i)); 385 386 } 387 388 return matrix3; 389 } 390 391 public boolean isLowerDiagonal() 392 { 393 for(int i = 0; i < _row - 1; i++) 394 { 395 for(int j = i + 1; j < _col; j++) 396 if(_a[i][j] != 0.0D) 397 return false; 398 399 } 400 401 return true; 402 } 403 404 public boolean isSquare() 405 { 406 return _row == _col; 407 } 408 409 public boolean isSymmetric() 410 { 411 if(!isSquare()) 412 return false; 413 for(int i = 0; i < _row; i++) 414 { 415 for(int j = i + 1; j < _col; j++) 416 if(_a[i][j] != _a[j][i]) 417 return false; 418 419 } 420 421 return true; 422 } 423 424 public boolean isUpperDiagonal() 425 { 426 for(int i = 1; i < _row; i++) 427 { 428 for(int j = 0; j < i; j++) 429 if(_a[i][j] != 0.0D) 430 return false; 431 432 } 433 434 return true; 435 } 436 437 public void makeIdentity() 438 { 439 if(_row != _col) 440 { 441 System.err.println("Matrix::makeIdentity -> Matrix is not square."); 442 System.exit(0); 443 } 444 int i = _row; 445 for(int j = 0; j < i; j++) 446 { 447 for(int k = 0; k < i; k++) 448 _a[j][k] = 0.0D; 449 450 _a[j][j] = 1.0D; 451 } 452 453 } 454 455 public Matrix times(double d) 456 { 457 int i = _row; 458 int j = _col; 459 Matrix matrix = new Matrix(i, j); 460 for(int k = 0; k < i; k++) 461 { 462 for(int l = 0; l < j; l++) 463 matrix.set(k, l, d * _a[k][l]); 464 465 } 466 467 return matrix; 468 } 469 470 public Matrix times(Matrix matrix) 471 { 472 int i = _row; 473 int j = _col; 474 int k = matrix.cols(); 475 if(_col != matrix.rows()) 476 { 477 System.err.println("Matrix::operator* -> Invalid dimensions of matrices."); 478 System.exit(0); 479 } 480 Matrix matrix1 = new Matrix(i, k); 481 for(int l = 0; l < i; l++) 482 { 483 for(int i1 = 0; i1 < k; i1++) 484 { 485 double d = 0.0D; 486 for(int j1 = 0; j1 < j; j1++) 487 d += _a[l][j1] * matrix.at(j1, i1); 488 489 matrix1.set(l, i1, d); 490 } 491 492 } 493 494 return matrix1; 495 } 496 497 protected double pythagoras(double d, double d1) 498 { 499 double d2 = Math.abs(d); 500 double d3 = Math.abs(d1); 501 if(d2 > d3) 502 return d2 * Math.sqrt(1.0D + square(d3 / d2)); 503 else 504 return d3 != 0.0D ? d3 * Math.sqrt(1.0D + square(d2 / d3)) : 0.0D; 505 } 506 507 508 509 public int rows() 510 { 511 return _row; 512 } 513 514 public void set(int i, int j, double d) 515 { 516 _a[i][j] = d; 517 } 518 519 public void plusequal(int i, int j, double d) 520 { 521 _a[i][j] += d; 522 } 523 524 public void plusEqual(Matrix b) 525 { 526 for(int i=0; i<rows(); ++i) 527 { 528 for(int j=0; j<cols(); ++j) 529 { 530 _a[i][j] += b._a[i][j]; 531 } 532 } 533 } 534 535 protected double square(double d) 536 { 537 if(d == 0.0D) 538 return 0.0D; 539 else 540 return d * d; 541 } 542 543 public Matrix submatrix(int i, int j, int k, int l) 544 { 545 Matrix matrix = new Matrix(i, j); 546 for(int i1 = 0; i1 < i; i1++) 547 { 548 for(int j1 = 0; j1 < j; j1++) 549 matrix._a[i1][j1] = _a[i1 + k][j1 + l]; 550 551 } 552 553 return matrix; 554 } 555 556 public Matrix subtract(Matrix matrix) 557 { 558 int i = _row; 559 int j = _col; 560 if(i != matrix.rows() || j != matrix.cols()) 561 { 562 System.err.println("Matrix::operator- -> Invalid dimensions of matrices."); 563 System.exit(0); 564 } 565 Matrix matrix1 = new Matrix(i, j); 566 for(int k = 0; k < i; k++) 567 { 568 for(int l = 0; l < j; l++) 569 matrix1.set(k, l, _a[k][l] - matrix.at(k, l)); 570 571 } 572 573 return matrix1; 574 } 575 576 public Matrix transposed() 577 { 578 int i = _row; 579 int j = _col; 580 Matrix matrix = new Matrix(j, i); 581 for(int k = 0; k < j; k++) 582 { 583 for(int l = 0; l < i; l++) 584 matrix.set(k, l, _a[l][k]); 585 586 } 587 588 return matrix; 589 } 590 591 public Matrix upperDiagonal() 592 { 593 int i2 = _row; 594 int j2 = _col; 595 if(i2 < j2) 596 { 597 System.err.println("Matrix::upperDiagonal -> More rows than columns required."); 598 System.exit(0); 599 } 600 Matrix matrix = new Matrix(this); 601 int l1 = j2; 602 if(i2 - 1 < j2) 603 l1 = i2 - 1; 604 for(int i1 = 0; i1 <= l1; i1++) 605 { 606 double d1 = 0.0D; 607 for(int i = i1; i < i2; i++) 608 d1 += matrix.at(i, i1) * matrix.at(i, i1); 609 610 double d4 = 0.0D; 611 if(matrix.at(i1, i1) < 0.0D) 612 d4 = -1D; 613 if(matrix.at(i1, i1) > 0.0D) 614 d4 = 1.0D; 615 double d2 = -d4 * Math.sqrt(d1); 616 double d = d1 - matrix.at(i1, i1) * d2; 617 matrix.set(i1, i1, matrix.at(i1, i1) - d2); 618 for(int k1 = i1 + 1; k1 < j2; k1++) 619 { 620 double d3 = 0.0D; 621 for(int j = i1; j < i2; j++) 622 d3 += matrix.at(j, i1) * matrix.at(j, k1); 623 624 double d5 = d3 / d; 625 for(int k = i1; k < i2; k++) 626 matrix.set(k, k1, matrix.at(k, k1) - matrix.at(k, i1) * d5); 627 628 } 629 630 matrix.set(i1, i1, d2); 631 } 632 633 for(int l = 1; l < i2; l++) 634 { 635 for(int j1 = 0; j1 < l; j1++) 636 matrix.set(l, j1, 0.0D); 637 638 } 639 640 if(matrix.at(j2 - 1, j2 - 1) == 0.0D) 641 { 642 System.err.println("Matrix::householder -> Rank of matrix < n"); 643 System.exit(0); 644 } 645 int k2 = _row; 646 if(_col < _row) 647 k2 = _col; 648 return matrix.submatrix(k2, k2, 0, 0); 649 } 650 651 public void write(String s) 652 { 653 write(s, ""); 654 } 655 656 public void write(String s, String s1) 657 { 658 System.out.println("Writing matrix to '" + s + "'."); 659 try 660 { 661 PrintWriter printwriter = new PrintWriter(new BufferedWriter(new FileWriter(s))); 662 String s2 = "# " + s1; 663 printwriter.println(s2); 664 String s3 = _row + " " + _col; 665 printwriter.println(s3); 666 String s4 = ""; 667 for(int i = 0; i < _row; i++) 668 { 669 String s5 = ""; 670 for(int j = 0; j < _col; j++) 671 s5 = s5 + _a[i][j] + " "; 672 673 printwriter.println(s5.substring(0, s5.length() - 1)); 674 } 675 676 printwriter.close(); 677 } 678 catch(IOException _ex) 679 { 680 System.err.println("Matrix::write -> Error writing to '" + s + "'."); 681 System.exit(0); 682 } 683 System.out.println("Matrix written."); 684 } 685 686 public String toString() 687 { 688 return "Matrix: "; 689 } 690 691 public Matrix column(int col) 692 { 693 int rows = _row; 694 int cols = 1; 695 Matrix matrix = new Matrix(rows, cols); 696 for(int i = 0; i < rows; ++i) 697 { 698 matrix.set(i, 0, _a[i][col]); 699 } 700 701 return matrix; 702 } 703 704 public Matrix row(int row) 705 { 706 int rows = 1; 707 int cols = _col; 708 Matrix matrix = new Matrix(rows, cols); 709 for(int i = 0; i < cols; ++i) 710 { 711 matrix.set(0, i, _a[row][i]); 712 } 713 714 return matrix; 715 } 716 }